手把手带你使用LangChain框架从0实现RAG
在大模型(LLM)应用中,如何让模型准确回答领域知识问题是一个关键挑战。直接依赖预训练模型往往会遇到 幻觉(hallucination),因为模型可能“编造”不存在的事实。
📚 大模型框架系列文章
一、引言
在大模型(LLM)应用中,如何让模型准确回答领域知识问题是一个关键挑战。直接依赖预训练模型往往会遇到 幻觉(hallucination),因为模型可能“编造”不存在的事实。
为了解决这一问题,业界提出了 RAG(Retrieval-Augmented Generation,检索增强生成) 方法:通过检索外部知识库,将相关信息提供给模型,从而提升回答的准确性。
LangChain由Chains、Agents、Memory、Tools四个核心组件组成的框架,支持复杂任务分解和多模型协作,内置多种 Memory 管理模式,方便多轮对话,与知识库、搜索引擎等工具集成方便。
本文将带大家用 LangChain 框架,结合向量数据库,构建一个简易的 RAG 系统,并完成一个端到端的问答任务。
所有相关源码示例、流程图、模型配置与知识库构建技巧,我也将持续更新在Github:LLMHub,欢迎关注收藏!
二、环境配置
首先需要安装必要的依赖,包括 langchain
、faiss
以及大模型 API 相关的依赖。
# 安装必要的依赖包
!pip install langchain faiss-cpu openai tiktoken
这一步主要是为后续的文档切分、向量化存储以及调用大模型接口做准备。
三、加载与处理文档
我们需要先准备一个知识库,通常是一些本地的文本或 PDF 文件。LangChain 提供了丰富的文档加载器和文本切分工具。
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader
# 加载本地文本文件
loader = TextLoader("data/knowledge.txt", encoding="utf-8")
documents = loader.load()
# 使用字符切分器将文档分块,避免太长影响向量化效果
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = text_splitter.split_documents(documents)
print(f"文档总块数: {len(docs)}")
这里的逻辑是:先加载 → 再切分。切分后的文档会作为知识库的基本单元。
四、向量数据库构建
RAG 的核心在于“检索”,因此我们需要把切分后的文档存入 向量数据库(FAISS),以便后续通过相似度检索找到相关内容。
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# 使用 OpenAI Embeddings 将文档转为向量
embedding_model = OpenAIEmbeddings()
# 构建向量数据库
db = FAISS.from_documents(docs, embedding_model)
# 保存数据库到本地,方便下次直接加载
db.save_local("faiss_index")
这样,我们就得到了一个可检索的知识库,可以随时调用。
五、大模型接入
在 LangChain 中,我们可以很方便地接入大语言模型(如 OpenAI GPT)。
from langchain.chat_models import ChatOpenAI
# 初始化大语言模型
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
这里的 temperature=0
表示模型尽量给出确定性答案,减少随机性。
六、构建 RAG 问答链
现在我们将检索模块和大模型结合,形成一个 检索增强问答链。
from langchain.chains import RetrievalQA
# 将数据库作为检索器
retriever = db.as_retriever(search_kwargs={"k": 3})
# 构建 RAG 问答链
qa = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
return_source_documents=True
)
# 示例提问
query = "请介绍一下本文档中的核心方法是什么?"
result = qa({"query": query})
print("问题:", query)
print("回答:", result["result"])
print("引用文档:", result["source_documents"])
这一部分就是 RAG 的核心:先检索,再回答。模型不仅能给出答案,还能返回引用的文档片段,增强可解释性。
七、问答效果展示
我们可以进一步测试不同问题,观察 RAG 与普通 LLM 回答的区别。
# 提问 1
query1 = "该方法在应用中解决了什么问题?"
print("问题1:", query1)
print("回答1:", qa({"query": query1})["result"])
# 提问 2
query2 = "能否总结一下文档的主要内容?"
print("问题2:", query2)
print("回答2:", qa({"query": query2})["result"])
通过多轮问答,可以验证系统是否真正利用了外部知识库,而不是单纯依赖大模型的“想象力”。
八、总结
上面我们从零开始用了LangChain框架实现了RAG,整个流程包括:
- 文档加载与切分
- 向量化与数据库存储
- 检索器与大模型结合
- 构建端到端问答链
为了达到更好的效果,代码中可以替换为更强的开源 Embedding 模型(如 bge-large-zh
),并且可以使用 Milvus、Weaviate 等更强大的数据库。
如果你看到了这里,恭喜你,你可以自己手动试试啦!
关于深度学习和大模型相关的知识和前沿技术更新,请关注公众号 coting!
以上内容参考了 LangChain 官方文档和社区资料,如有侵权请联系删除。
更多推荐
所有评论(0)