langchain 入门指南 - LangChainRetrieval

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介: langchain 入门指南 - LangChainRetrieval

在前一篇文章中,我们实现了对本地文本做分片以及向量化的操作。

但是有个问题是,每次使用的时候都需要对整个文本进行分片和向量化,这样的操作是非常耗时的,而且也是需要消耗 token 数量的。

那有没有办法可以只做一次分片和向量化,然后保存下来,下次使用的时候直接调用呢?

答案是有的,我们只需要将分片和向量化的结果保存到数据库中,下次使用的时候直接从数据库中读取即可。

而保存这种向量化结果的数据库叫做向量数据库,本文中,我们会使用 Chroma 作为向量数据库来保存向量化结果。

同时,这种操作其实是很常见的操作,因此 langchain 也给我们封装了更好的接口,使我们可以更方便的来对本地文档做查询。

Chroma

向量数据库 Chroma 是一种专门设计用来高效管理和查询向量数据的数据库系统。

Chroma 通过其高效的数据结构和算法优化,能够快速处理和检索大量的向量数据。

以下是 Chroma 向量数据库的一些主要特点:

  • 高效的向量索引:Chroma 使用高效的索引结构,如倒排索引、KD-树或基于图的索引,以加快向量搜索速度;
  • 支持多种相似度度量:它支持多种向量相似度度量标准,包括欧氏距离、余弦相似度等,使其可以广泛应用于不同的应用场景;
  • 可扩展性和弹性:Chroma 能够支持水平扩展,适应大规模数据集的需要。同时,它也能有效处理数据的动态变化,适应快速发展的存储需求;
  • 易于集成和使用:Chroma 设计有易于使用的API接口,支持多种编程语言接入,便于开发者在不同的系统和应用中集成使用;
  • 实时性能优化:Chroma 优化了查询处理过程,支持实时的数据查询和更新,满足实时分析和决策的需求。

安装

我们可以使用如下命令进行安装:

pip install chroma
pip install unstructured
pip install pypdf

使用 langchain 结合本地文档做查询的流程

  1. 读取文件并进行分片
  2. 将分片后的文本向量化
  3. 使用用户的问题检索向量化的结果
  4. 将检索到的本地文本结合用户问题,发送给 LLM 进行回答
  5. 得到 LLM 的回答

Document Loader(读取文档)

DocumentLoader 是一个用来加载本地文档的类,它可以加载本地文档:

from langchain.document_loaders import DirectoryLoader
loader = DirectoryLoader("./", glob='service_design.txt')
docs = loader.load()

也可以加载 pdf 文档:

from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("Spotmax_intro_cn_2020.pdf")
docs = loader.load()

Text Splitter(文档分片)

RecursiveCharacterTextSplitter 文本分割器是通用文本的推荐分割器。

它会按顺序尝试在这些字符上进行分割,直到分块足够小。

默认列表是 ["\n\n", "\n", " ", ""]。这样可以尽可能地保持所有段落(然后是句子,然后是单词)在一起。

from langchain.text_splitter import RecursiveCharacterTextSplitter
text_spliter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=10)
splits = text_spliter.split_documents(docs)

配置 key

import os
os.environ['OPENAI_API_KEY'] = "your key"
os.environ['OPENAI_BASE_URL'] = "https://api.openai-hk.com/v1"

将数据载入向量数据库

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
embedding = OpenAIEmbeddings()
vectordb = Chroma.from_documents(
    documents=splits,
    embedding=embedding,
    collection_name="spotmax",
    persist_directory=persist_directory,
)
vectordb.persist()
print(vectordb._collection.count())

这个时候,我们就可以对本地文档进行查询了。

docs = vectordb.similarity_search("如何提高可用性", k=2)
print(docs[0])

利用向量数据库进行 QA

langchain 提供了一个 RetrievalQA 类,它可以将向量数据库和 LLM 结合起来,实现对本地文档的查询。

from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
    model_name="gpt-3.5-turbo",
    temperature=0,
    max_tokens=200,
    api_key="your key",
    base_url="https://api.openai-hk.com/v1",
)
retriever = vectordb.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 3}
)
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever,
                                 return_source_documents=False, verbose=True)
result = qa({"query": "什么是SpotMax?"})
print(result['result'])

工作过程如下:

  1. 根据用户问题从向量数据库查找相关地分片
  2. 将分片 + 用户问题传递给 LLM
  3. 得到 LLM 的回答

说明:

  • search_type 使用最大边际相关性(Maximal Marginal Relevance)搜索类型,这是一种混合搜索策略,旨在平衡相关性和多样性。
  • search_kwargs={"k": 3} 在搜索过程中返回3个最相关的文档。
  • RetrievalQA.from_chain_type创建一个RetrievalQA实例,使用之前定义的llmretriever
  • chain_type="stuff" 使用 stuff 类型的链,这意味着所有检索到的上下文将被组合成一个输入,然后传递给 LLM。
  • return_source_documents 设置为 False,表示不返回源文档,只返回 LLM 的回答
  • verbose 设置为 True,表示打印详细信息

chain type

  • stuff:将相关地 Chunks 全部放入 Prompt,调用大模型次数少,对于小地数据响应速度快。不适用于大的数据集,相关的 chunks 合在一起会超出 token 限制。
  • refine:用下一个相关 chunk 来优化前序的 chunk 调用 LLM 后的返回,持续迭代。调用大模型次数多,适用于大的数集。
  • map reduce: 将所有相关的 chunks 分别调用 LLM,然后将结果合并。最后将合并的结果再次调用 LLM。调用大模型次数多,适用于大的数据集。
  • map re-rank: 将每个 chunk 调用 LLM,LLM 返回的结果还打了个分,将分值最高的答案返回给用户。

从现有的 chroma 向量数据库中加载

上面的例子中,我们是将文档分片后,再向量化,然后保存到数据库中。

如果我们已经有了向量化的结果,我们可以直接从数据库中加载,这样可以避免每次都要重新向量化。

唯一的区别是创建 Chroma 对象时,不是使用 from_documents 方法,而是直接指定 db 路径以及 collection_name 即可。

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
embedding = OpenAIEmbeddings()
vectordb = Chroma(persist_directory='data/', embedding_function=embedding, collection_name='spotmax')

注意事项

  1. 不同的 chain_type 查询结果不一样,有些 chain_type 可能查不到你想要的结果。
  2. 分块大小和 chunk_overlap 也会影响查询结果,需要根据实际情况调整。

一些报错

MacOS 下的报错(本机是 13.1 版本):

pydantic.errors.PydanticImportError: `BaseSettings` has been moved to the `pydantic-settings` packag

解决办法,执行下面的 shell 命令:

SYSTEM_VERSION_COMPAT=0 pip install --no-cache-dir "onnxruntime>=1.14.1"

同时 chromadb 升级到最新版:

pip install chromadb==0.5.4

总结

本文介绍了如何使用 Chroma 向量数据库来保存向量化结果,以及如何使用 langchain 结合本地文档做查询。

具体来说,就是使用 RetrievalQA 结合 Chroma 向量数据库和 LLM,实现对本地文档的查询。


相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
目录
相关文章
|
14天前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
109 2
|
3月前
langchain 入门指南 - 使用 Agent
langchain 入门指南 - 使用 Agent
133 0
|
3月前
|
安全 API 数据库
langchain 入门指南 - 函数调用
langchain 入门指南 - 函数调用
112 1
|
3月前
|
机器学习/深度学习
langchain 入门指南 - In-context Learning
langchain 入门指南 - In-context Learning
80 0
|
3月前
langchain 入门指南 - 链式请求
langchain 入门指南 - 链式请求
65 0
|
14天前
|
人工智能 前端开发 JavaScript
前端大模型入门(二):掌握langchain的核心Runnable接口
Langchain.js 是 Langchain 框架的 JavaScript 版本,专为前端和后端 JavaScript 环境设计。最新 v0.3 版本引入了强大的 Runnable 接口,支持灵活的执行方式和异步操作,方便与不同模型和逻辑集成。本文将详细介绍 Runnable 接口,并通过实现自定义 Runnable 来帮助前端人员快速上手。
|
3月前
|
存储 机器学习/深度学习 传感器
langchain 入门指南 - 实现一个多模态 chatbot
langchain 入门指南 - 实现一个多模态 chatbot
107 0
|
3月前
|
前端开发 人机交互
langchain 入门指南 - ReAct 模式
langchain 入门指南 - ReAct 模式
83 1
|
3月前
|
存储 人工智能 缓存
langchain 入门指南 - 让 AI 记住你说过的话
langchain 入门指南 - 让 AI 记住你说过的话
99 1
|
3月前
|
人工智能 搜索推荐 API
langchain 入门指南 - 让 AI 从互联网获取信息
langchain 入门指南 - 让 AI 从互联网获取信息
75 1