概要

在构建基于大模型的语言应用时,经常需要从文档中提取信息来回答用户的问题。LangChain 提供了一系列工具来帮助我们加载文档,并通过向量数据库进行高效检索。本文将详细介绍如何使用 LangChain 加载文档,并通过具体的代码示例展示如何实现向量数据库检索。

整体架构流程

文档加载
基础文档加载
首先,我们需要了解如何加载单个文档或目录中的多个文档。LangChain 支持多种文档加载器,可以根据需求选择合适的加载器。

加载单个文本文件
加载单个文本文件时,可以使用 TextLoader 类。这里假设我们有一个名为 faq-4359.txt 的文本文件:

from langchain_community.document_loaders import TextLoader

loader = TextLoader("./txt/faq-4359.txt", encoding="utf8")
doc = loader.load()
print(doc)

同样地,可以加载其他文本文件:

loader1 = TextLoader("./txt/faq-7923.txt", encoding="utf8")
doc1 = loader1.load()
print(doc1)

loader2 = TextLoader("./txt/yjhx.md", encoding="utf8")
doc2 = loader2.load()
print(doc2)

加载目录中的文档
如果需要加载整个目录中的所有文档,可以使用 DirectoryLoader 类。默认情况下,DirectoryLoader 使用 UnstructuredLoader 来处理文档。

from langchain_community.document_loaders import DirectoryLoader

# 加载所有 Markdown 文件
loader = DirectoryLoader('../', glob="**/*.md")

加载 HTML 文件
对于 HTML 文件,可以使用 UnstructuredHTMLLoader 来加载:

from langchain_community.document_loaders import UnstructuredHTMLLoader

loader = UnstructuredHTMLLoader("txt/test.html")
docs = loader.load()
print(docs)

向量数据库检索
一旦文档加载完毕,下一步就是将文档嵌入到向量数据库中,以便进行高效的检索。

创建向量数据库
为了创建向量数据库,我们需要使用 FAISS 和 HuggingFaceEmbeddings:

from langchain_community.vectorstores import FAISS
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings

embeddings_path = "D:\\ai\\download\\bge-large-zh-v1.5"
embeddings = HuggingFaceEmbeddings(model_name=embeddings_path)

# 创建向量数据库
vectorStoreDB = FAISS.from_documents(docs, embedding=embeddings)
print(vectorStoreDB)

检索文档
向量数据库提供了多种检索方法,包括基于相似度的检索和最大边际相关性(MMR)检索。

相似度检索
最简单的检索方法是基于相似度的检索:

results = vectorStoreDB.similarity_search("回收手机的话,应该怎么操作?")
print(results)

最大边际相关性检索(MMR)
MMR 检索旨在找到既相关又多样化的文档组合:

retriever = vectorStoreDB.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 1}
)

docs = retriever.get_relevant_documents("请说说回收手机怎么操作?")
print(docs)

设置相似度阈值
还可以设置相似度阈值来限制检索结果:

retriever = vectorStoreDB.as_retriever(
    search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.3}
)

docs = retriever.get_relevant_documents("请说说回收手机怎么操作?")
print(docs)

集成检索器与模型
最后,我们将检索器与语言模型结合起来,以便在回答问题时能够利用检索到的上下文信息。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

openai_api_key = "EMPTY"
openai_api_base = "http://127.0.0.1:1234/v1"
model = ChatOpenAI(
    openai_api_key=openai_api_key,
    openai_api_base=openai_api_base,
    temperature=0.3,
)

template = """
只根据以下文档回答问题:
{context}

问题:{question}
"""

prompt = ChatPromptTemplate.from_template(template)

# 创建请求链
setup_and_retrieval = RunnableParallel(
    {
        "context": retriever,
        "question": RunnablePassthrough()
    }
)

outputParser = StrOutputParser()

chain = setup_and_retrieval | prompt | model | outputParser

# 测试请求链
result = chain.invoke("请说说回收手机怎么操作?")
print(result)

小结

通过本文,我们学习了如何在 LangChain 中加载文档,并通过向量数据库进行高效的检索。无论是加载单个文件还是整个目录,LangChain 都提供了便捷的工具。此外,通过集成检索器与语言模型,我们可以构建出能够利用外部知识源回答问题的系统。希望这篇博客能为你的项目提供有用的参考。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐