1. 项目概述:当LangChain遇上RAG技术
最近在做一个很有意思的技术组合实验:用LangChain框架整合RAG(检索增强生成)技术来构建智能知识库系统。这个方案特别适合需要处理大量非结构化数据的企业场景,比如客服知识库、内部文档查询系统等。
传统问答系统要么依赖固定规则(维护成本高),要么直接用大模型生成(容易胡编乱造)。而RAG架构通过"检索+生成"两步走,先找到相关文档片段,再基于这些真实材料生成回答,既保持了灵活性又确保了准确性。LangChain作为大模型应用开发框架,正好提供了连接向量数据库、编排prompt链的工具箱。
2. 核心架构设计
2.1 技术栈选型解析
这套系统的核心组件包括:
- LangChain:负责流程编排,将检索、prompt构建、模型调用等步骤串联成链
- 向量数据库:选用ChromaDB(轻量级)或Milvus(分布式),存储文档的向量化表示
- Embedding模型:建议text-embedding-3-small,平衡效果与成本
- 大语言模型:GPT-3.5-turbo性价比高,若需更高精度可换GPT-4
关键决策点:选择对称型还是非对称型检索?对于QA场景,建议文档和问题都用同一套embedding模型(对称型),这样在语义匹配时更一致。
2.2 数据处理流水线
原始知识库文档需要经过标准化处理:
- 文档加载:支持PDF、Word、HTML等格式,用LangChain的document_loaders模块
- 文本分块:采用递归字符分割器,设置chunk_size=1000,chunk_overlap=200
- 向量化存储:用HuggingFaceEmbeddings生成384维向量,存入ChromaDB
python复制from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
docs = text_splitter.split_documents(raw_documents)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vectorstore = Chroma.from_documents(docs, embeddings)
3. 检索增强生成实现
3.1 混合检索策略
单纯向量检索可能漏掉关键词匹配的重要文档,我们采用混合方案:
- 语义检索:通过cosine相似度找相关文档
- 关键词检索:用BM25算法补充召回
- 重排序:用Cohere rerank模型对结果排序
python复制from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain.vectorstores import Chroma
vector_retriever = Chroma.as_retriever(search_kwargs={"k": 5})
bm25_retriever = BM25Retriever.from_documents(docs)
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)
3.2 生成环节优化
检索到文档后,需要精心设计prompt模板:
- 上下文注入:将top3相关文档片段作为背景知识
- 指令明确化:要求模型严格基于提供材料回答
- 引用标注:让模型标明答案出处便于验证
python复制from langchain.prompts import PromptTemplate
template = """基于以下上下文回答问题。如果不知道就说不知道。
上下文:{context}
问题:{question}
答案:"""
QA_PROMPT = PromptTemplate.from_template(template)
4. 系统部署与调优
4.1 性能优化技巧
- 缓存层:对高频查询问题缓存回答,减少模型调用
- 流式响应:使用LangChain的streaming接口逐步显示结果
- 异步处理:对耗时的embedding计算采用异步队列
python复制# 异步处理示例
from langchain.embeddings import OpenAIEmbeddings
from asyncio import run
async def async_embed(text):
embeddings = OpenAIEmbeddings()
return await embeddings.aembed_query(text)
result = run(async_embed("示例文本"))
4.2 效果评估指标
建立量化评估体系:
- 检索阶段:计算召回率@K、MRR(平均倒数排名)
- 生成阶段:用ROUGE、BLEU分数评估文本相似度
- 人工评估:设计准确性、流畅性、有用性三维度评分表
5. 踩坑实录与解决方案
问题1:模型虚构答案
- 现象:即使提供了正确上下文,模型仍自行编造
- 解决方案:在prompt中加入"仅使用提供的信息回答,否则明确表示不知道"
问题2:长文档效果差
- 现象:超过3000字的文档检索准确率骤降
- 解决方案:采用层次化分块,先按章节分大块,再对每章分小块
问题3:专业术语匹配失败
- 现象:行业术语的语义搜索效果不佳
- 解决方案:在embedding前添加术语解释到原文,如"<术语>指<定义>"
6. 进阶扩展方向
这套基础架构可以进一步扩展:
- 多模态检索:结合图像、表格等非文本数据
- 动态更新:设置监听机制自动更新变化文档
- 权限控制:基于用户角色过滤可检索内容
- 对话历史:将历史问答作为上下文增强当前回答
实际部署时发现,医疗领域的知识库需要特别处理药品名称缩写(如"二甲双胍"和"MET"),我们通过构建同义词词典解决了这个问题。金融领域的数字准确性要求高,我们增加了输出格式校验步骤,确保所有数值都有明确出处。