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,实现对本地文档的查询。

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白如意i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值