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

news2025/2/7 11:37:25

前提:

        在阅读本文前,建议要有一定的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-大叔)的动力。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1575356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

品牌定位升级|飞雕开关如何从家庭作坊走上国际之路?

飞雕电器,这个名字在中国开关插座行业中如同一面旗帜,自1987年起就扬帆在电工领域的大海中。它不仅见证了这个行业的起起伏伏,还始终以其创新的姿态站在浪尖之上。 飞雕的产品线丰富多彩,除主营的墙壁开关插座领域外,飞雕电器还涉足了与墙壁开关紧密相关的其它领域,现已推出移…

vmware 中的Ubuntu系统虚拟机忘记root密码强制重置操作

忘记密码情况下,vmware虚拟机重置Ubuntu的root密码 在企业使用的vmware ESXI中重置Ubuntu系统root密码 1-本地电脑安装个人版的vmware workstation,目的:vmware ESXI自带的远程控制台无法输入指定的键盘按键,需要借助外部的远程辅…

Ceph学习 -3.存储简介

文章目录 1.存储简介1.1 存储类型1.1.1 储备知识1.1.2 三种存储1.1.3 块存储1.1.4 文件存储1.1.5 对象存储1.1.6 三种存储之间的关系1.1.7 总结 1.2 Ceph简介1.2.1 官方介绍1.2.2 软件特点1.2.3 基本结构1.2.4 应用场景 1.3 小结 1.存储简介 学习目标:这一节&#x…

免疫检查点信号转导和癌症免疫治疗(文献)

目录 基础 介绍 免疫检查点的表面调控(细胞膜层面) ​编辑 PD-1调节 PD-L1调节 CTLA-4 调节 检查点信号通路 关于靶点研究 展望 Immune checkpoint signaling and cancer immunotherapy - PubMed (nih.gov) 基础 【中英字幕】肿瘤免疫疗法之免…

docker安装nacos,单例模式(standalone),使用mysql数据库

文章目录 前言安装创建文件夹"假装"安装一下nacos拷贝文件夹删除“假装”安装的nacos容器生成nacos所需的mysql表获取mysql-schema.sql文件创建一个mysql的schema 重新生成新的nacos容器 制作docker-compose.yaml文件查看网站 前言 此处有本人写得简易版本安装&…

【GameFi】 Brilliantcrypto点火活动

活动:https://app.galxe.com/quest/brilliantcrypto/GCt8wthq2J Brilliantcrypto点火活动正在Galxe上进行 🎉 活动时间:2024/04/06 12:00 ~ 2024/05/04 12:00 奖励总价值1200美元的MATIC 完成任务並在Brilliantcrypto Galxe Space上赚取积分。…

《科技创业月刊》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答:问:《科技创业月刊》是什么级别的刊物? 答:省级,主管单位: 湖北省科学技术厅 ;主办单位:湖北省科技信息研究院 问:《科技创业月刊》是c刊吗? 答&…

JUC:手写实现一个简易的线程池(Java)

目录 ​编辑 先上完整代码: 解析: 任务队列: 线程池类: 拒绝策略: 先上完整代码: public class MyThreadPool {public static void main(String[] args) {ThreadPool threadPool new ThreadPool(2, …

基于javassm实现的旅游景点线路网站

开发语言:Java 框架:ssm 技术:JSP JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.…

Q1公测手游复盘:大作很多,爆款没有

2024年第一季度过去,整个国内手游市场爆冷连连。 据眸娱不完全统计,一季度累计上新22部颇具影响力的手游(买断制手游仅留鹰角网络《来自星尘》作为代表)。许多备受期待的大作在一季度抢先完成了上线或测试,却在市场端…

IDEA中的Debug功能介绍

说明:本文介绍IDEA中的Debug功能,基于2023.2(Ultimate Edition)版本 简单介绍 首先,在程序需要停止的所在行号上,鼠标左键,可设置一个断点,是一个红色圆点标志,表示程序…

python入门到精通

本文基于《python3从入门到精通》进行编写 python是什么 是一种简单易学的计算机编程语言,有配套的软件工具和库。 是一种开源的语言。因其有许多强大的开源库使得python对与计算、大数据、人工智能都有很强的支持能力。 是一种解释型语言。其代码不需要编译就可…

基于 OpenHarmony ActiveOhos_sqllite 组件开发指南

1. ActiveOhos 功能介绍 1.1.组件介绍 基于鸿蒙系统连接数据库进行 sqlite 数据库操作的时候,创建连接的时候是有些繁琐的,本组件就是为了简化 sqlite 的连接,并且对鸿蒙原生的 API 进行封装加强,使得读写 sqlite 数据库的时候更…

Java8新特性 (jdk1.8)

目录 一、Lamdba表达式? 二、函数式接口 三、方法引用和构造引用 四、Stream API流 五、接口中的新增 默认方法和静态方法 六、新时间日期API 七、Optional 八、其他特性 一、Lamdba表达式? 为什么使用Lambda表达式? Lambda 是一个 匿…

[挖坟]如何安装Shizuku和LSPatch并安装模块(不需要Root,非Magisk)

2023年12月13日,LSPatch 停止维护 2024年1月8日,LSPosed 停止维护 2024年1月8日,ZygiskNext 停止维护 2024年1月9日,KernelSU 停止维护 这里使用 ColorOS 14 演示,其他品牌手机类似 安装 Shizuku 官网: https://shiz…

JQuery(二)---【使用JQuery对HTML、CSS进行操作】

零.前言 JQuery(一)---【JQuery简介、安装、初步使用、各种事件】-CSDN博客 一.使用JQuery对HTML操作 1.1获取元素内容、属性 使用JQ可以操作元素的“内容” text():设置或返回元素的文本内容html():设置或返回元素的内容(包括HTML标记)val()&#…

每天一个注解之@DataSource、 @DS

在Java中,DataSource 注解通常用于标记数据源(DataSource)相关的信息。数据源是一个用于获取数据库连接的对象,它通常用于与数据库进行交互。DataSource 注解的详细说明可能会因不同的框架或库而有所不同,但通常用于配…

2024-04-07 作业

作业要求: 1> 思维导图 2> 自由发挥应用场景实现一个登录窗口界面。 【可以是QQ登录界面、也可以是自己发挥的登录界面】 要求:尽量每行代码都有注释 作业1: 作业2: 运行代码: #include "myqwidget.h&quo…

部署安装ElasticSearch、Kibana、IK

文章目录 1、部署单点es1.1、创建网络1.2、加载镜像1.3、运行 2、部署kibana2.1、部署2.2、DevTools 3、IK分词器3.1、在线安装3.2、离线安装1)查看数据卷目录2)解压缩分词器安装包3)上传到es容器的插件数据卷中4)重启容器5&#…

2024.4.7

1. 2列火车 #include<myhead.h>pthread_mutex_t m1; pthread_mutex_t m2;void* run(void* arg) {while(1){pthread_mutex_lock(&m1);printf("火车B进入\n");printf("A请等待\n");pthread_mutex_unlock(&m2);sleep(2);} }int main(in…