1. 问题背景:为什么你的RAG系统总是返回高相似度但无用的结果?
最近在开发RAG(检索增强生成)系统时,我发现一个令人头疼的现象:系统经常返回一些相似度分数很高但实际上完全不可用的内容。这就像你去图书馆查资料,图书管理员热情地给你推荐了一堆书,结果翻开一看全是无关内容。
1.1 传统RAG系统的设计缺陷
传统RAG系统的工作流程简单来说就是两步走:
- 检索:根据用户查询从向量数据库中找出相似度最高的文档
- 生成:把这些文档作为上下文输入给大模型生成最终回答
这种设计存在三个致命问题:
检索偏差:系统只关注语义相似度,不考虑实际相关性。比如查询"Nginx配置HTTPS证书",可能返回Apache配置方法、旧版本教程甚至HTTPS原理解析。这些文档在向量空间可能很"相似",但完全无法解决实际问题。
时效性缺失:系统无法区分新旧信息。查询"Python异步编程最佳实践"时,2018年的废弃写法和2024年的推荐写法会被同等对待,而用户需要的是最新方案。
记忆污染:一旦错误内容被存入向量库,就会形成恶性循环。错误的API用法被检索到→生成错误答案→错误答案又被存入向量库→下次继续检索到错误内容。
1.2 相似度分数为何会"虚高"?
向量相似度计算基于文档的语义特征,但高相似度≠高相关性。主要原因有:
- 主题相似但细节不符:两篇文档都讲"HTTPS配置",但一个讲Nginx一个讲Apache
- 术语重叠但语境不同:文档包含查询中的所有关键词,但组合起来意思完全不同
- 向量空间局限性:嵌入模型无法捕捉某些专业领域的细微差别
实际案例:我们开发的运维助手曾返回过相似度0.92的文档,内容却是完全不同的Web服务器配置方法。用户看到高分结果以为找到了答案,实际却南辕北辙。
2. CRAG解决方案:在检索和生成之间加入质量评估
CRAG(Corrective Retrieval-Augmented Generation)的核心创新是在传统RAG的检索和生成之间加入了评估和纠正环节,形成四步闭环:
- 检索:从向量库获取相关文档
- 评估:判断文档质量(正确/模糊/错误)
- 纠正:根据评估结果采取不同策略
- 生成:使用处理后的上下文生成回答
2.1 CRAG工作流程详解

评估环节的三元判决:
- 正确(relevant):文档直接包含答案,可以直接使用
- 模糊(ambiguous):文档部分相关,需要补充外部知识
- 错误(incorrect):文档不相关,应该丢弃
纠正环节的三种策略:
- 对于正确文档:进行知识精炼,提取最相关部分
- 对于模糊文档:精炼内部文档+补充外部搜索
- 对于错误文档:完全依赖外部搜索
2.2 知识精炼:从文档中提取核心信息
传统RAG直接把整篇文档塞给大模型,导致两个问题:
- Token浪费:大部分内容无关紧要
- 信息干扰:无关内容可能误导模型
CRAG采用知识精炼技术,典型流程:
- 文档分解:将长文档切分为多个片段(如每500字一段)
- 查询重写:将模糊查询改写为更精确的搜索词
- 知识选择:基于关键词匹配筛选最相关片段

实际应用中发现,简单的关键词匹配就能显著提升效果。比如查询"Python异步编程",系统会自动聚焦包含"async/await"、"asyncio"等关键词的段落。
3. 技术实现:用LangChain+Milvus搭建CRAG系统
3.1 为什么选择Milvus作为向量数据库?
经过多个向量数据库的对比测试,Milvus在以下方面表现突出:
多租户隔离:通过Partition Key实现,每个Agent实例有独立存储空间,避免数据污染。1000万向量、100租户场景下,查询性能提升3-5倍。
混合检索:支持稠密向量(语义)+稀疏向量(BM25)+元数据过滤的混合检索,解决纯向量检索在专有名词、型号编码等场景的失效问题。
动态Schema:JSON字段支持灵活扩展,可以随时添加confidence、verified等元数据字段,无需停机维护。
python复制fields = [
FieldSchema(name="agent_id", dtype=DataType.VARCHAR, is_partition_key=True),
FieldSchema(name="dense_embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
FieldSchema(name="sparse_embedding", dtype=DataType.SPARSE_FLOAT_VECTOR),
FieldSchema(name="metadata", dtype=DataType.JSON)
]
3.2 LangChain中间件实现CRAG逻辑
使用LangChain 1.0的middleware特性,可以在不污染主逻辑的情况下插入CRAG流程:
python复制class CRAGMiddleware(AgentMiddleware):
def __init__(self, vector_store: Milvus, agent_id: str):
self.vector_store = vector_store
self.agent_id = agent_id
self.evaluator = init_chat_model("openai:gpt-4o-mini", temperature=0)
self.web_search = TavilySearchResults(max_results=3)
@before_model
def run_crag(self, state):
query = get_query_from_state(state)
docs = self._retrieve_from_milvus(query)
verdict = self._evaluate_relevance(query, docs)
if verdict == "incorrect":
final_context = self._web_search_fallback(query)
elif verdict == "ambiguous":
refined_docs = self._refine_documents(docs, query)
web_results = self._web_search_fallback(query)
final_context = self._merge_context(refined_docs, web_results)
else:
refined_docs = self._refine_documents(docs, query)
final_context = self._format_internal_docs(refined_docs)
state["_crag_context"] = final_context
return state
3.3 评估器的优化实现
基础版评估器使用LLM直接返回判断结果:
python复制def _evaluate_relevance(self, query: str, docs: list):
prompt = f"""你是文档相关性评估专家。评估以下文档是否能回答查询。
查询:{query}
文档内容:
{doc_content}
只返回一个词:relevant/ambiguous/incorrect"""
return self.evaluator.invoke(prompt)
进阶版评估器提供结构化输出,包含置信度和判断理由:
python复制class RelevanceVerdict(BaseModel):
verdict: Literal["relevant", "ambiguous", "incorrect"]
confidence: float
reasoning: str
grader_prompt = PromptTemplate(
template="""评估标准:
- relevant:文档直接包含答案,置信度 > 0.9
- ambiguous:文档部分相关,置信度 0.5-0.9
- incorrect:文档不相关,置信度 < 0.5
返回JSON格式:{"verdict": "...", "confidence": 0.xx, "reasoning": "..."}""",
input_variables=["query", "document"]
)
4. 部署与优化建议
4.1 性能优化技巧
评估器选择:原论文使用微调T5-Large(10-20ms延迟),生产环境可以用蒸馏后的小模型。我们测试发现,GPT-4-mini在保证准确性的前提下,延迟控制在50ms以内。
混合检索策略:Milvus的RRF融合排序能自动平衡稠密向量和稀疏向量的结果。建议权重设置为:
- 稠密向量:0.7
- 稀疏向量:0.3
缓存机制:对高频查询建立缓存,存储评估结果和精炼后的内容,减少重复计算。
4.2 常见问题排查
问题1:评估结果不一致
- 检查评估prompt��否明确,建议提供具体示例
- 增加temperature=0确保确定性输出
- 对争议大的查询人工审核,补充到prompt中
问题2:外部搜索延迟高
- 设置超时机制(如3秒超时)
- 对Tavily等搜索API做限流控制
- 考虑自建搜索引擎缓存高频结果
问题3:精炼后信息缺失
- 调整关键词匹配阈值
- 增加同义词扩展
- 对关键文档设置白名单,避免过度过滤
4.3 效果评估指标
建议监控以下核心指标:
- 检索准确率:评估结果中"正确"的比例
- 平均处理延迟:从查询到生成的总时间
- 外部搜索触发率:反映内部知识库的覆盖度
- 用户满意度:通过👍/👎收集反馈
我们部署的系统指标示例:
- 检索准确率从62%提升到89%
- 平均延迟控制在800ms以内
- 外部搜索触发率从40%降到15%
- 用户满意度从3.2/5提升到4.5/5
5. 扩展应用与未来方向
5.1 多模态CRAG系统
当前系统主要处理文本,未来可以扩展:
- 图像检索:用CLIP等模型处理图表、示意图
- 表格处理:专门优化对结构化数据的检索和评估
- 代码检索:针对代码片段设计特殊评估逻辑
5.2 自适应学习机制
让系统从用户反馈中学习:
- 记录被用户标记为"无用"的结果,自动调整评估标准
- 对高频修正的查询,触发知识库更新流程
- 建立A/B测试框架,持续优化各环节参数
5.3 领域专用优化
不同领域需要特殊处理:
- 医疗领域:严格验证信息来源,设置更高的置信度阈值
- 法律领域:关注法规时效性,自动标记过期内容
- 技术支持:优先官方文档,社区内容需额外验证
在实际部署中,我们发现CRAG架构特别适合知识更新快的领域。比如在为某科技公司搭建内部知识助手时,系统能自动过滤过时的API文档,并补充最新的社区解决方案,显著减少了工程师获取准确信息的时间。
