Langchain教程 | langchain+OpenAI+PostgreSQL(PGVector) 实现全链路教程,简单易懂入门

前提:

        在阅读本文前,建议要有一定的langchain基础,以及langchain中document loader和text spliter有相关的认知,不然会比较难理解文本内容。

        如果是没有任何基础的同学建议看下这个专栏:人工智能 | 大模型 | 实战与教程

        本文主要展示如何结合langchain使用Postgres矢量数据库,其他相关的基础内容,可以看专栏了解,都已经拆分好了,一步步食用即可,推荐线路:langchain基础、document loader加载器、text spliter文档拆分器等按顺序学习。

PGVector是一个开源向量相似性搜索Postgres

它支持:- 精确和近似最近邻搜索- L2距离,内积和余弦距离 

基础库准备:

# Pip install necessary package
%pip install --upgrade --quiet  pgvector
%pip install --upgrade --quiet  psycopg2-binary
%pip install --upgrade --quiet  tiktoken
%pip install --upgrade --quiet  openai
from langchain.docstore.document import Document
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores.pgvector import PGVector
from langchain_community.embeddings.openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

我们想使用OpenAIEmbeddings所以我们必须获得OpenAI API密钥。

提示:因为国内政策原因,建议采购代理key,至于哪家好用,这里就不推荐了。

em.py 设置环境变量

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")

 加载环境变量,openai库会自动读取该参数OPEN_API_KEY

## Loading Environment Variables
from dotenv import load_dotenv

load_dotenv()

 这里使用的文本内容是: 人民财评:花香阵阵游人醉,“春日经济”热力足

将链接中的文本内容保存到 :state_of_the_union.txt

拆分中文文档需要用到递归型的字符拆分器 RecursiveCharacterTextSplitter,同时要使用中文分隔符:句号。逗号,顿号、感叹号!等。

loader = TextLoader("../../modules/state_of_the_union.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()

连接Postgre矢量存储库

# PGVector needs the connection string to the database.
CONNECTION_STRING = "postgresql+psycopg2://harrisonchase@localhost:5432/test3"

# # Alternatively, you can create it from environment variables.
# import os

类还内置了一个更直观的方法:connection_string_from_db_params()

CONNECTION_STRING = PGVector.connection_string_from_db_params(
    driver=os.environ.get("PGVECTOR_DRIVER", "psycopg2"),
    host=os.environ.get("PGVECTOR_HOST", "localhost"),
    port=int(os.environ.get("PGVECTOR_PORT", "5432")),
    database=os.environ.get("PGVECTOR_DATABASE", "postgres"),
    user=os.environ.get("PGVECTOR_USER", "postgres"),
    password=os.environ.get("PGVECTOR_PASSWORD", "postgres"),
)

使用欧氏距离进行相似性搜索(默认)

# The PGVector Module will try to create a table with the name of the collection.
# So, make sure that the collection name is unique and the user has the permission to create a table.

COLLECTION_NAME = "state_of_the_union_test"

db = PGVector.from_documents(
    embedding=embeddings,
    documents=docs,
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
)
query = "今年长三角铁路春游运输共历时多少天?"
docs_with_score = db.similarity_search_with_score(query)
for doc, score in docs_with_score:
    print("-" * 80)
    print("Score: ", score)
    print(doc.page_content)
    print("-" * 80)

输出结果:

最大边际相关性搜索

最大边际相关性优化了查询的相似性和所选文档的多样性。 

docs_with_score = db.max_marginal_relevance_search_with_score(query)
for doc, score in docs_with_score:
    print("-" * 80)
    print("Score: ", score)
    print(doc.page_content)
    print("-" * 80)

打印结果:

使用vectorstore 

        上面,我们从头开始创建了一个vectorstore。但是,我们经常希望使用现有的vectorstore。为了做到这一点,我们可以直接初始化它。

store = PGVector(
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
    embedding_function=embeddings,
)

添加文档

我们可以向现有的vectorstore添加文档。

store.add_documents([Document(page_content="今年春游创收客观,实际增长30%。")])
docs_with_score = db.similarity_search_with_score("春游增长多少")
print(docs_with_score[0])
print(docs_with_score[1])

覆盖向量存储

        如果您有一个现有的集合,您可以通过执行以下操作来覆盖它from_documents和设置pre_delete_collection=真

db = PGVector.from_documents(
    documents=docs,
    embedding=embeddings,
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
    pre_delete_collection=True,
)

将VectorStore用作检索器

retriever = store.as_retriever()

与OpenAI结合使用完整代码

里面包含了详细的步骤和注释,直接复制就可运行。

import os
from langchain_community.document_loaders import TextLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores.pgvector import PGVector
from langchain_text_splitters import RecursiveCharacterTextSplitter
from dotenv import load_dotenv

# 加载环境变量或者加载.env文件
load_dotenv()
# 导入文本文件
loader = TextLoader("./demo_static/splitters_test.txt")
# 生成文档加载器
documents = loader.load()
# 文档拆分,每块最大限制20,覆盖量10
text_splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", "。", "?", ";"],
    chunk_size=100,
    chunk_overlap=20,
)
# 开始拆分文档
docs = text_splitter.split_documents(documents)
# print(len(docs))
# print(docs)

# 初始化嵌入式OpenAI大语言模型,手动指定key和代理地址
embeddings = OpenAIEmbeddings(openai_api_key=os.getenv("OEPNAPI_API_KEY"),
                              openai_api_base=os.getenv("OPENAI_API_BASE"))
# 连接矢量存储库,链接换成自己专属的*
CONNECTION_STRING = "postgresql+psycopg2://postgres:password@localhost:5432/postgres"
# 矢量存储名
COLLECTION_NAME = "state_of_the_union_test"
# 建立索引库
vector = PGVector.from_documents(
    embedding=embeddings,
    documents=docs,
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
    use_jsonb=True,
    pre_delete_collection=True,
)
# 生成检索器
retriever = vector.as_retriever()
# 一个对话模板,内含2个变量context和question
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
# 基于模板生成提示
prompt = ChatPromptTemplate.from_template(template)
# 基于对话openai生成模型
model = ChatOpenAI(openai_api_key=os.getenv("OEPNAPI_API_KEY"),
                   openai_api_base=os.getenv("OPENAI_API_BASE"))
# 生成输出解析器
output_parser = StrOutputParser()
# 将检索索引器和输入内容(问题)生成检索
setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)
# 建立增强链
chain = setup_and_retrieval | prompt | model | output_parser
# 问题
question = "今年长三角铁路春游运输共历时多少天?"
# 发起请求
res = chain.invoke(question)
# 打印结果
print(res)

打印结果:

    32天

 创作不易,来个三连(点赞、收藏、关注),同学们的满意是我(H-大叔)的动力。

 代码运行有问题或其他建议,请在留言区评论,看到就会回复,不用私聊。

专栏人工智能 | 大模型 | 实战与教程里面还有其他人工智能|大数据方面的文章,可继续食用,持续更新。

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为AI助手,我将为您提供一些关于利用Spring JPA,JWT和PostgreSQL的信息。 1. Spring JPA Spring JPA是Spring框架的一个子项目,它简化了使用JPA(Java Persistence API)的开发。它提供了一个基于JPA的Repository接口,使得开发人员可以使用面向对象的方式来访问和操作数据库。 使用Spring JPA,您可以轻松地定义实体类和对应的Repository接口,并通过注解来定义它们之间的关系。Spring JPA会自动地生成SQL语句并执行它们,从而使得开发人员可以更加专注于业务逻辑。 2. JWT JWT(JSON Web Token)是一种轻量级的身份验证和授权机制。它基于JSON格式,并使用数字签名来验证身份和授权。JWT由三部分组成:头部、载荷和签名。 使用JWT,开发人员可以在服务端生成一个令牌,并将其发送给客户端。客户端可以将令牌保存在本地,并在每次请求时将其发送给服务端。服务端可以通过验证令牌的签名来验证客户端的身份和授权。 3. PostgreSQL PostgreSQL是一种开源的关系型数据库管理系统。它支持标准的SQL语言,并提供了一些高级的功能,如事务、触发器和存储过程。 使用PostgreSQL,您可以轻松地存储和管理大量的数据,并通过SQL语言来查询和操作数据。 结论 利用Spring JPA,JWT和PostgreSQL,开发人员可以轻松地构建一个安可靠的Web应用程序。Spring JPA提供了一种简单易用的方式来访问和操作数据库,JWT提供了一种安可靠的身份验证和授权机制,而PostgreSQL提供了一种可靠的数据存储和管理机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值