基于微调模型兜底的RAG系统:错误检测与召回率评估
摘要
本文介绍了一个完整的RAG(检索增强生成)系统实现,该系统不仅能够评估召回率和检测回答错误,还集成了微调模型兜底机制,以在检索到错误或过时信息时提供正确的答案。我们将详细介绍如何构建这样一个系统,包括其架构设计、核心功能实现以及评估方法。
1. 引言
在构建生产级RAG系统时,面临的一个核心挑战是如何处理检索到错误或过时信息的情况。传统的RAG系统在面对错误的上下文时可能盲目地生成错误答案,而一个集成LoRA微调模型的进阶RAG系统,则具备了“有自己主见”的大脑,能够识别冲突、权衡信源,并选择性地纠正或忽略错误的上下文,生成正确的答案。
2. 项目结构
本项目的完整代码结构如下:
D:\\博客内容\\20251109\\
├── rag_system.py # 核心RAG系统实现
├── main.py # 程序入口和演示
├── 如何判断RAG回答错误.md
├── 如何评估RAG的召回率.md
└── RAG错误微调模型兜底.md
3. 系统架构

系统包括以下组件:
- DocumentChunk: 文档块数据类,存储文档片段及其ID和嵌入向量
- RAGQueryResult: 查询结果数据类,包含查询、检索到的文档、生成的答案等信息
- RAGSystem: 基础RAG系统,实现检索和生成功能
- FineTunedModel: 微调模型模拟,包含内部知识库
- AdvancedRAGSystem: 高级RAG系统,集成兜底机制
3. 核心功能实现
3.1 召回率评估
召回率是评估RAG系统检索能力的重要指标,表示在所有“应该被检索出来”的相关文档中,系统实际找出了多少。
def evaluate_recall_rate(self, test_queries: List[Dict]) -> Dict:"""评估RAG系统的召回率test_queries: 包含问题、相关文档ID集合的测试数据"""total_recall = 0.0num_queries = len(test_queries)for test_query in test_queries:query = test_query['query']relevant_chunks = test_query['relevant_chunk_ids']# 检索文档retrieved_chunks = self.retrieve(query, top_k=len(self.documents))retrieved_chunk_ids = [chunk.id for chunk in retrieved_chunks]# 计算召回率relevant_set = set(relevant_chunks)retrieved_set = set(retrieved_chunk_ids)intersection = relevant_set.intersection(retrieved_set)recall = len(intersection) / len(relevant_set) if len(relevant_set) > 0 else 0total_recall += recallavg_recall = total_recall / num_queries if num_queries > 0 else 0return {'average_recall_rate': avg_recall,'num_test_queries': num_queries}
3.2 回答错误判断
我们从三个维度评估答案质量:
3.2.1 答案忠实度
检查答案是否严格基于检索到的上下文生成,有没有“无中生有”的内容。
def check_answer_fidelity(self, answer: str, context: str) -> bool:"""检查答案忠实度:答案是否基于上下文生成"""# 简单实现:检查答案中的关键信息是否在上下文中answer_numbers = re.findall(r'\d+(?:\.\d+)?', answer)context_numbers = re.findall(r'\d+(?:\.\d+)?', context)# 检查数字是否一致for num in answer_numbers:if num not in context_numbers:# 如果答案中包含上下文中没有的数字,可能表示胡编乱造if self._is_key_number(num):return False# 检查是否包含上下文中的关键短语key_phrases = self._extract_key_phrases(context)for phrase in key_phrases:if phrase.lower() in answer.lower():return Truereturn len(answer) > 0
3.2.2 答案正确性
评估生成的答案在事实和语义上是否与标准答案一致。
def check_answer_correctness(self, generated_answer: str, standard_answer: str) -> bool:"""检查答案正确性:是否与标准答案一致"""gen_lower = generated_answer.lower().strip()std_lower = standard_answer.lower().strip()# 简单的包含关系检查if std_lower in gen_lower or gen_lower in std_lower:return True# 关键词匹配(更宽松的检查)std_words = set(std_lower.split())gen_words = set(gen_lower.split())common_words = std_words.intersection(gen_words)if len(common_words) / len(std_words) > 0.6: # 至少60%的关键词匹配return Truereturn False
3.2.3 答案相关性
检查生成的答案是否直接回答了用户的问题。
def check_answer_relevance(self, query: str, answer: str) -> bool:"""检查答案相关性:是否直接回答了用户问题"""query_lower = query.lower()answer_lower = answer.lower()# 检查答案中是否包含与问题相关的关键词query_words = query_lower.split()for word in query_words:if word in answer_lower:return True# 更宽松的检查:检查是否有相关主题if len(set(query_lower.split()) & set(answer_lower.split())) > 1:return Truereturn False
3.3 错误归因分析
当判断RAG回答错误后,下一步是定位问题根源:
def identify_error_source(self, query: str, retrieved_chunks: List[DocumentChunk], standard_relevant_chunks: List[str]) -> str:"""错误归因分析:判断错误是由于检索失败还是生成失败"""retrieved_chunk_ids = [chunk.id for chunk in retrieved_chunks]relevant_set = set(standard_relevant_chunks)retrieved_set = set(retrieved_chunk_ids)# 检查是否检索到了相关文档has_relevant_docs = bool(relevant_set.intersection(retrieved_set))if not has_relevant_docs:return "检索失败:未检索到相关文档"# 如果检索到了相关文档但答案仍错误,可能是生成失败return "生成失败:检索到相关文档但生成错误答案"
3.4 微调模型兜底机制
这是系统的核心功能,当检索到错误信息时,使用微调模型的内部知识进行纠正:
class FineTunedModel:"""模拟微调模型,具备兜底能力"""def __init__(self):# 模拟微调模型学到的内部知识self.internal_knowledge = {"2023年净利润": "100万元","最新产品": "V2.0","主要产品": "智能客服软件和数据分析平台"}def should_use_internal_knowledge(self, context: str) -> bool:"""判断是否应该使用内部知识(即上下文是否包含明显错误)"""# 检查上下文是否与内部知识冲突if "净利润为150万元" in context and self.internal_knowledge.get("2023年净利润") == "100万元":return True # 上下文与内部知识冲突,应该使用内部知识if "V1.0" in context and "最新产品" in context and self.internal_knowledge.get("最新产品") == "V2.0":return True # 版本过时,使用内部知识return False
4. 系统集成
在AdvancedRAGSystem中集成了兜底机制:
def generate_answer_with_fallback(self, query: str, context: str) -> str:"""带兜底机制的答案生成"""# 检查是否需要使用微调模型的内部知识if self.fine_tuned_model.should_use_internal_knowledge(context):print("检测到检索上下文可能有误,启用微调模型兜底机制...")return self.fine_tuned_model.generate_with_internal_knowledge(query)# 正常使用RAG流程return self.generate_answer(query, context)
5. 实际应用示例
系统能够处理以下几种典型场景:
| 场景 | 检索到的上下文(错误) | 基础RAG的回答(错误) | LoRA-RAG的兜底回答(正确) |
|---|---|---|---|
| 事实性错误 | “公司2023年净利润为150万元。” | “公司2023年净利润为150万元。” | “根据我所掌握的信息,公司2023年的净利润应为100万元。” |
| 知识过时 | “我们最新的产品是V1.0。” | 介绍V1.0特性 | “我们最新的产品是V2.0,它具备…特性。” |
| 上下文无关 | 检索到不相关信息 | 可能胡编乱造 | 拒绝被误导,直接调用内部知识 |
6. 评估流程
完整的RAG评估流程如下:
- 构建测试集: 准备高质量的问题,并为每个问题配备标准答案和相关文档ID列表
- 运行RAG系统: 用测试问题查询RAG系统,收集检索到的文档和生成的答案
- 计算检索指标: 评估召回率和精确率
- 评估生成答案: 对答案的忠实度、正确性、相关性等维度打分
- 错误分析与归因: 检查是检索问题还是生成问题,有针对性地优化系统
7. 总结
本文介绍了一个集成了微调模型兜底机制的RAG系统实现。该系统通过以下方式提高了RAG系统的可靠性和准确性:
- 召回率评估: 量化评估检索模块的性能
- 多维度错误检测: 从忠实度、正确性、相关性三个维度评估答案质量
- 智能兜底机制: 当检索到错误信息时,使用内部知识进行纠正
- 错误归因分析: 帮助识别系统的瓶颈所在,指导优化方向
这种"1+1 > 2"的架构模式,将RAG的大规模外部知识能力与微调模型的领域专业知识相结合,形成了一个强大且可靠的问答系统。
8. 未来工作
- 集成更先进的向量检索技术
- 使用更复杂的语义相似度计算方法
- 引入LLM作为裁判进行更准确的答案评估
- 实现动态置信度评估机制
