概要
在许多应用场景中,用户提供的输入只是一个问题,而答案需要从已有的数据库或文档中检索出来。这种情况下,单纯依靠大模型的生成能力是不够的,我们需要结合外部知识源来增强模型的回答准确性。LangChain 提供了多种工具来实现这一点,其中包括检索增强生成(RAG)技术。本文将介绍如何在 LangChain 中使用 RAG 技术来增强模型的回答能力,并通过具体的代码示例展示其实现过程。
技术名词解释
数据检索
在进行数据检索时,我们通常需要一个检索器来帮助我们从外部知识源中查找相关信息。LangChain 支持多种检索器,本节将介绍如何使用向量数据库生成检索器。
RAG 技术简介
检索增强生成(RAG)是一种前沿的技术,它允许基础大模型无需额外训练即可调用特定领域的知识。RAG 可以视为给大模型装上了一个“知识外挂”,让模型能够在回答问题时利用外部数据源提供的上下文信息。
技术细节
步骤一:创建向量数据库
首先,我们需要创建一个向量数据库来存储我们的文档。这里我们使用 FAISS 和 Hugging Face 的 Embeddings 模块来生成向量表示。
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)
# 创建向量数据库
vectorstore = FAISS.from_texts(
["小明在华为工作", "熊喜欢吃蜂蜜"],
embedding=embeddings
)
步骤二:生成检索器
有了向量数据库之后,我们可以创建一个检索器来从数据库中检索相关文档。
# 使用向量数据库生成检索器
retriever = vectorstore.as_retriever()
# 测试检索器
retriever.invoke("熊喜欢吃什么?")
retriever.invoke(“熊喜欢吃什么?”)
步骤三:集成检索器与模型
接下来,我们将检索器与一个语言模型结合起来,以便在回答问题时能够利用检索到的上下文信息。
from langchain_openai import ChatOpenAI
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,
)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 创建提示模板
template = """
只根据以下文档回答问题:
{context}
问题:{question}
"""
prompt = ChatPromptTemplate.from_template(template)
# 创建请求链
setup_and_retrieval = RunnableParallel(
{
"context": retriever,
"question": RunnablePassthrough()
}
)
chain = setup_and_retrieval | prompt | model | StrOutputParser()
# 测试请求链
chain.invoke("小明在哪里工作?")
完整链式请求
我们也可以使用链式的方式组织请求流程,这使得代码更简洁易懂。
# 完整链式请求
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
# 测试完整链式请求
chain.invoke("小明在哪里工作?")
添加个性化元素
为了使回答更具个性化,我们可以在提示模板中加入用户的称呼。
from operator import itemgetter
# 创建带有称呼的提示模板
template = """
只根据以下文档回答问题:
{context}
问题:{question}
回答问题请加上称呼"{name}"。
"""
prompt = ChatPromptTemplate.from_template(template)
# 创建请求链
chain = (
{
"context": itemgetter("question") | retriever,
"question": itemgetter("question"),
"name": itemgetter("name"),
}
| prompt
| model
| StrOutputParser()
)
# 测试带有称呼的请求链
chain.invoke({"question":"小明在哪里工作?","name":"主人"})
加载目录中的文档
最后,如果我们要处理的是目录中的多个文档,可以使用 DirectoryLoader 来加载这些文档。
from langchain_community.document_loaders import DirectoryLoader
# 加载目录中的文档
loader = DirectoryLoader('./txt')
docs = loader.load()
小结
通过上述步骤,我们展示了如何在 LangChain 中实现数据检索与 RAG 技术。RAG 不仅能够增强模型的回答能力,还能让我们有效地利用外部数据源来提供更准确的答案。希望这篇博客能够帮助大家更好地理解和应用 LangChain 的 RAG 功能。