LangChain教程 - 向量存储与检索器

devtools/2024/9/22 11:00:26/

系列文章索引
LangChain教程 - 系列文章

介绍

在这个教程中,你将了解 LangChain 的向量存储和检索器抽象。这些抽象旨在支持从(向量)数据库和其他来源检索数据,并将其集成到大语言模型(LLM)的工作流程中。这在基于检索增强生成(RAG)等应用中尤为重要,因为这些应用需要在模型推理过程中提取数据供模型进行推理。

概念

本教程将主要关注文本数据的检索,涵盖以下几个核心概念:

  1. 文档(Documents):表示文本数据的基本单位,通常包含内容和元数据。
  2. 向量存储(Vector Stores):通过将文本转换为向量存储起来,便于快速相似性搜索。
  3. 检索器(Retrievers):基于向量存储,执行高效的文本检索。

环境准备

Jupyter Notebook

你可以在 Jupyter Notebook 中运行本教程。如果尚未安装,请参考 Jupyter 安装指南。

安装依赖包

我们将使用以下 Python 包:

通过以下命令安装:

pip install langchain langchain-chroma langchain-openai

安装后,我们就可以开始搭建 LangChain 环境。


文档(Documents)

LangChain 实现了一个文档抽象,用来表示一段文本及其关联的元数据。每个文档都有两个属性:

  • page_content:表示文档的文本内容;
  • metadata:一个包含文档相关信息的字典,比如文档来源等。

我们可以通过以下代码生成一些示例文档:

python">from langchain_core.documents import Documentdocuments = [Document(page_content="狗是忠诚和友好的伴侣。",metadata={"source": "mammal-pets-doc"},),Document(page_content="猫是一种独立的宠物,通常喜欢自己的空间。",metadata={"source": "mammal-pets-doc"},),Document(page_content="金鱼是新手的理想宠物,照顾起来相对简单。",metadata={"source": "fish-pets-doc"},),Document(page_content="鹦鹉是聪明的鸟类,能够模仿人类的语言。",metadata={"source": "bird-pets-doc"},),Document(page_content="兔子是一种社交性很强的动物,喜欢有足够的空间活动。",metadata={"source": "mammal-pets-doc"},),
]

这些文档示例为后续的检索实验提供了基础数据集。


向量存储(Vector Stores)

向量存储是一种常见的用于存储和检索非结构化数据(如文本)的方式。它的核心思想是将文本数据转换为数值向量,并使用向量相似性度量来进行查询。

LangChain 提供了多种向量存储的集成接口,可以将文本或文档添加到向量存储中,并通过多种相似性度量方法进行查询。我们这里使用 Chroma 的内存实现来演示向量存储的使用。

首先,我们需要一个嵌入模型来将文本转换为向量。下面的示例使用 OpenAI 的嵌入模型:

python">from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddingsvectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(),
)

from_documents 方法会将文档添加到向量存储中。你可以使用 similarity_search 方法来基于字符串查询文档。

python">results = vectorstore.similarity_search("猫")
for doc in results:print(doc.page_content)

这个查询会返回与 “猫” 最相关的文档。


检索器(Retrievers)

LangChain 提供了检索器(Retriever)接口,用于执行标准化的检索操作。检索器可以集成到复杂的应用中,例如结合检索上下文和问题的 RAG 应用。我们可以使用向量存储的 as_retriever 方法生成一个检索器。

python">retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 1})

然后我们可以通过批量查询来检索多个文档:

python">results = retriever.batch(["猫", "鲨鱼"])
for res in results:for doc in res:print(doc.page_content)

通过这种方式,我们可以根据相似性从向量存储中检索与多个查询相关的文档。


检索增强生成(RAG)应用示例

检索器可以方便地集成到 RAG 应用中,将问题和检索到的上下文结合生成答案。下面是一个简单的 RAG 实现示例:

python">from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthroughllm = ChatOpenAI(model="gpt-4o-mini")message = """
请根据提供的上下文回答问题。问题:
{question}上下文:
{context}
"""prompt = ChatPromptTemplate.from_messages([("human", message)])rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llmresponse = rag_chain.invoke("告诉我关于猫的事情")
print(response.content)

这个例子展示了如何使用 LangChain 结合检索器和语言模型完成复杂的生成任务。


完整代码

python"># 导入必要的包
from langchain_core.documents import Document
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAIimport os
import getpass# 设置 OpenAI API Key
os.environ["OPENAI_API_KEY"] = getpass.getpass("输入你的 OpenAI API Key: ")# 生成示例文档
documents = [Document(page_content="狗是忠诚和友好的伴侣。",metadata={"source": "mammal-pets-doc"},),Document(page_content="猫是一种独立的宠物,通常喜欢自己的空间。",metadata={"source": "mammal-pets-doc"},),Document(page_content="金鱼是新手的理想宠物,照顾起来相对简单。",metadata={"source": "fish-pets-doc"},),Document(page_content="鹦鹉是聪明的鸟类,能够模仿人类的语言。",metadata={"source": "bird-pets-doc"},),Document(page_content="兔子是一种社交性很强的动物,喜欢有足够的空间活动。",metadata={"source": "mammal-pets-doc"},),
]# 初始化向量存储(使用 OpenAI 的嵌入模型)
vectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(),
)# 执行基于相似性的查询
print("执行基于相似性的查询:")
results = vectorstore.similarity_search("猫")
for i, doc in enumerate(results, 1):print(f"文档 {i} 内容: {doc.page_content}\n")# 创建一个检索器并进行批量查询
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 1})
print("执行批量查询:")
batch_results = retriever.batch(["猫", "鲨鱼"])
for i, res in enumerate(batch_results, 1):for doc in res:print(f"批量查询 {i} 结果: {doc.page_content}\n")# 检索增强生成(RAG)示例
llm = ChatOpenAI(model="gpt-4o-mini")message = """
请根据提供的上下文回答问题。问题:
{question}上下文:
{context}
"""prompt = ChatPromptTemplate.from_messages([("human", message)])rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llm# 执行 RAG 查询
response = rag_chain.invoke("告诉我关于猫的事情")
print(f"RAG 生成结果: {response.content}")

总结

通过本教程,你应该已经了解了 LangChain 的向量存储与检索器的基本概念和使用方法。这些工具为构建复杂的基于 LLM 的应用提供了强大的数据检索能力。你可以进一步结合这些概念开发更加智能的应用。

附1:Chroma存储位置

Chroma.from_documents 是 LangChain 中使用 Chroma 向量数据库的一个方法,它将文档内容转换为嵌入向量并存储在 Chroma 中。具体存储位置取决于 Chroma 的配置。如果没有特别指定,默认情况下数据是存储在内存中,即会在程序运行期间保存在 RAM 中,并在程序结束时丢失。

然而,Chroma 也可以配置为将数据存储到磁盘或其他数据库持久化存储。默认情况下,它有以下几种存储选项:

  1. 内存存储(In-memory):默认情况下,Chroma 将数据存储在内存中,这非常适合测试或小规模实验。数据不会被持久化,程序结束后数据会丢失。

  2. 磁盘存储(Persistent Storage on Disk):你可以指定 Chroma 将数据持久化到磁盘中,这样即使程序结束,数据也不会丢失。你可以通过指定 persist_directory 参数来设置存储路径。

    示例:

    python">vectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(),persist_directory="./chroma_storage"  # 指定存储目录
    )
    

    这会将数据保存到当前目录下的 chroma_storage 文件夹中。

  3. 其他数据库(Custom Storage Options):Chroma 还可以与其他存储后端集成,比如通过 PostgreSQL 等数据库进行存储。此时你需要配置 Chroma 连接到外部数据库。

持久化向量存储的示例

如果你想要将向量数据持久化到磁盘,可以使用 persist_directory 参数,并在完成插入数据后调用 persist() 方法来保存数据:

python">vectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(),persist_directory="./chroma_storage"  # 指定存储路径
)# 向量存储后调用 persist() 方法进行持久化
vectorstore.persist()
重新加载持久化数据

如果你已经将数据持久化到磁盘并想在下次程序运行时重新加载这些数据,可以直接通过指定 persist_directory 来加载:

python">vectorstore = Chroma(embedding_function=OpenAIEmbeddings(),persist_directory="./chroma_storage"  # 指定持久化路径
)# 现在可以进行查询
results = vectorstore.similarity_search("猫")
for doc in results:print(doc.page_content)

这种方式允许你在不同的会话之间保留和使用向量存储的数据。

总结
  • 默认情况下,Chroma.from_documents 将向量数据存储在内存中,不会持久化。
  • 你可以通过设置 persist_directory 将数据存储到磁盘,并通过 persist() 方法确保数据保存。
  • 你还可以配置 Chroma 连接到外部存储后端,如 PostgreSQL,以支持更复杂的存储需求。

http://www.ppmy.cn/devtools/115430.html

相关文章

AWS账号可以共用吗?

小伙伴们,大家好!今天九河云来聊聊另一个大家可能关心的问题:AWS账号可以共用吗?很多团队或公司在使用AWS服务时,可能会考虑共用一个账号以节省成本或者简化管理。那么,这样做是否可行呢?让我们…

WebGL缓冲区

一、缓冲区对象 缓冲区对象时WebGL系统中的一块内存区域,可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存其中,供顶点着色器使用。 类型化数组 这样程序可以预知数组中的类型,提高性能 类型描述Int8Array8位…

弃置区原因

线性卷积,不用担心滤波器周期化的情况。圆周卷积在一周期内,一定有所有的点,所以信号进来的时候,剩下的信号一定在周期内,导致卷积结果不正确。 补零的圆周卷积就是为了,信号进来的时候,让其他的…

数据结构--树和二叉树

目录 一.树概念及结构(了解) 1.1树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它 叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 有一个特…

【JAVA开源】基于Vue和SpringBoot的在线文档管理系统

本文项目编号 T 038 ,文末自助获取源码 \color{red}{T038,文末自助获取源码} T038,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

Java项目实战II基于Java+Spring Boot+MySQL的大型商场应急预案管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在快节奏的…

go语言的基本语法

学了go语言但是一直没整理。。。那怎么证明我学了?如果学了之后忘了怎么复习?遂诞生这几篇,当作Linux中间的小插曲 整理一下go语言的基本语法: package mainimport ("bufio""fmt""os" ) 在使用对…

外包干了4年,技术退步太明显了。。。。。

先说一下自己的情况,本科生生,20年通过校招进入武汉某软件公司,干了差不多4年的功能测试,今年国庆,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能…