基于 LangChain 搭建最小化 RAG 系统实战
检索增强生成(RAG)是解决大模型知识幻觉的关键技术。本文基于 LangChain 框架,详细讲解了搭建最小化 RAG 系统的完整流程。内容涵盖环境配置、数据加载与切片、BGE 向量化模型集成、Chroma 向量数据库存储、检索器构建以及 LCEL 链式生成逻辑。文章还分析了简单 RAG 系统常见的幻觉与检索精度问题,并提出了混合检索、重排序等优化方向,为开发者提供了一套可落地的参考实现方案。

检索增强生成(RAG)是解决大模型知识幻觉的关键技术。本文基于 LangChain 框架,详细讲解了搭建最小化 RAG 系统的完整流程。内容涵盖环境配置、数据加载与切片、BGE 向量化模型集成、Chroma 向量数据库存储、检索器构建以及 LCEL 链式生成逻辑。文章还分析了简单 RAG 系统常见的幻觉与检索精度问题,并提出了混合检索、重排序等优化方向,为开发者提供了一套可落地的参考实现方案。

检索增强生成(Retrieval-Augmented Generation, RAG)是近年来大模型应用中最核心的技术架构之一。它通过引入外部知识库,有效缓解了大模型的知识幻觉问题。本文将利用 LangChain 框架,从零开始搭建一个最简化的 RAG 系统,解析其核心原理与实现细节。
建议使用 Python 3.9+ 环境。LangChain 版本更新较快,建议安装最新稳定版以避免兼容性问题。
主要依赖包包括:
langchain:核心框架chromadb:向量数据库sentence-transformers 或 huggingface_hub:用于加载 BGE 嵌入模型PyPDF2 或 unstructured:视数据格式而定RAG 流程主要分为三个步骤:
该架构的核心在于利用向量相似度匹配解决信息检索的准确性问题,同时利用大模型的生成能力保证回答的自然流畅。
我们使用 Chroma 作为轻量级向量数据库,调用 BGE (BAAI General Embedding) 模型完成文本向量化。原始数据采用 Markdown 格式,便于直接使用 TextLoader 加载。
import os
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceBgeEmbeddings
# 配置模型路径
BGE_MODEL_PATH = "BAAI/bge-large-zh"
root_dir = "./data" # 替换为你的数据目录
def extract_file_dirs(directory):
file_paths = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".md"):
fp = os.path.join(root, file)
file_paths.append(fp)
return file_paths
# 1. 加载文档
files = extract_file_dirs(root_dir)
loaders = [TextLoader(f, encoding='utf-8') for f in files]
docs = []
for l in loaders:
docs.extend(l.load())
# 2. 文本切片
# chunk_size 控制每个片段的大小,chunk_overlap 控制重叠部分以保留上下文连贯性
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
documents = text_splitter.split_documents(docs)
# 3. 向量化与存储
embedding = HuggingFaceBgeEmbeddings(model_name=BGE_MODEL_PATH)
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embedding,
persist_directory="./vectorstore"
)
注意:实际生产中需确保 model_factory 中的 LLM 客户端已正确初始化。此处仅展示向量库构建逻辑。
将向量数据库转换为检索器(Retriever)是 LangChain 的标准用法。通过 as_retriever() 方法,可以方便地调用检索接口。
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
query = "如何快速找到最有价值的内容?"
docs = retriever.invoke(query)
for doc in docs:
print(doc.page_content)
这里使用了 invoke 方法替代旧版的 get_relevant_documents,这是 LangChain 较新版本的推荐写法。search_kwargs 允许自定义检索参数,如返回数量 k 或搜索类型(similarity, mmr 等)。
定义提示词模板,将检索到的上下文与用户问题结合。使用 LangChain Expression Language (LCEL) 构建链式处理流程。
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# 假设 model 已初始化为具体的 LLM 实例
# from model_factory import yi_llm
# model = yi_llm
template = """Answer the question based only on the following context:
{context}
Question: {question},请用中文输出答案。
"""
prompt = ChatPromptTemplate.from_template(template)
def format_docs(docs):
return "\n\n".join([d.page_content for d in docs])
# 构建 Chain
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
response = chain.invoke(query)
print(response)
LCEL 的优势在于其流式处理能力与模块化设计,便于调试和组合不同的组件。RunnablePassthrough 用于透传用户问题,format_docs 负责格式化检索结果。
在实际应用中,简单的 RAG 系统可能面临以下挑战:
chunk_size 或使用元数据过滤。本文演示了如何使用 LangChain、Chroma 和 BGE 模型构建基础的 RAG 系统。虽然示例代码较为精简,但涵盖了从数据加载、向量化、检索到生成的完整链路。开发者可根据具体业务场景,引入更复杂的检索策略与模型微调方案,以提升系统的鲁棒性与实用性。
在实际部署前,请务必检查所有依赖包的版本兼容性,并确保敏感数据(如 API Key)通过环境变量管理,避免硬编码在代码中。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online