🧠AI RAG
检索链路与降幻觉
面试回答
常见问法
在 RAG 系统里,怎么降低模型幻觉?
回答
降低幻觉不能只盯模型输出,重点要看整个检索链路。通常要从检索质量、上下文拼接、回答边界约束和评测回归四层一起做。优先级一般是先保证召回和重排质量,再优化 Prompt 和回答策略。
# 完整RAG链路示例
class RAGPipeline:
def __init__(self, retriever, reranker, generator, evaluator):
self.retriever = retriever
self.reranker = reranker
self.generator = generator
self.evaluator = evaluator
def generate_with_hallucination_control(self, query):
"""
完整的RAG流程,包含幻觉控制
1. 高质量召回
2. 精确重排序
3. 幻觉检测
4. 安全生成
"""
# 1. 多源召回
retrieved_docs = self.retriever.retrieve(query, top_k=15)
# 2. 重排序
reranked_docs = self.reranker.rerank(query, retrieved_docs, top_n=5)
# 3. 构建上下文
context = self.build_safe_context(reranked_docs, max_tokens=2000)
# 4. 幻觉检测
hallucination_risk = self.detect_hallucination_risk(query, context)
# 5. 根据风险调整生成策略
if hallucination_risk > 0.7:
# 高风险:严格模式
response = self.generator.generate(
query, context,
mode='strict',
citation_required=True
)
elif hallucination_risk > 0.3:
# 中风险:平衡模式
response = self.generator.generate(
query, context,
mode='balanced',
citation_required=True
)
else:
# 低风险:正常模式
response = self.generator.generate(
query, context,
mode='normal'
)
# 6. 后验验证
verified_response = self.verify_response(response, context)
return verified_response
def build_safe_context(self, documents, max_tokens=2000):
"""
构建安全的上下文,包含引用标记
"""
context_parts = []
total_tokens = 0
for i, doc in enumerate(documents):
# 为每个文档添加引用标记
doc_content = f"[引用{i+1}] {doc['content']}"
doc_tokens = self.count_tokens(doc_content)
if total_tokens + doc_tokens <= max_tokens:
context_parts.append(doc_content)
total_tokens += doc_tokens
else:
# 超出限制,截断文档
truncated_content = self.truncate_to_fit(
doc_content, max_tokens - total_tokens
)
context_parts.append(truncated_content)
break
# 添加引用索引
context_parts.append("\n## 可用引用")
for i, doc in enumerate(documents):
context_parts.append(f"{i+1}. {doc['title'][:50]}...")
return "\n".join(context_parts)
def detect_hallucination_risk(self, query, context):
"""
检测幻觉风险
1. 查询复杂度评估
2. 文档覆盖度检查
3. 语义一致性分析
"""
risk_score = 0.0
# 查询复杂度
if self.is_complex_query(query):
risk_score += 0.3
# 文档覆盖度
coverage = self.calculate_coverage(query, context)
if coverage < 0.5:
risk_score += 0.4
elif coverage < 0.8:
risk_score += 0.2
# 语义一致性
consistency = self.check_semantic_consistency(context)
if consistency < 0.7:
risk_score += 0.3
return min(risk_score, 1.0)
追问
- 为什么错误检索比检索不到更危险?(错误信息误导)
- 引用出处为什么能提升系统可信度?(可追溯性)
- 拒答机制应该放在检索前还是生成后?(多层防护)
原理展开
RAG 里的幻觉经常来自”拿错资料""资料不完整”或”资料虽对但拼接方式让模型误解”。因此工程优化往往要看 chunk 质量、检索召回、rerank、上下文裁剪和回答模板。
真正成熟的 RAG 系统一般还会补评测集和回归流程,否则你很难判断一次参数调整到底是在变好,还是只是在某几个样例上看起来更好。
# 幻觉检测与预防
class HallucinationPrevention:
def __init__(self, fact_checker, confidence_threshold=0.8):
self.fact_checker = fact_checker
self.confidence_threshold = confidence_threshold
def verify_facts(self, response, source_documents):
"""
事实验证:检查生成内容是否与源文档一致
1. 提取生成内容中的事实陈述
2. 与源文档进行比对
3. 标记无法验证的陈述
"""
import re
# 提取事实陈述
facts = self.extract_facts(response)
verified_facts = []
hallucinated_facts = []
for fact in facts:
# 检查事实是否在源文档中
support_score = self.check_support_in_sources(
fact, source_documents
)
if support_score >= self.confidence_threshold:
verified_facts.append({
'fact': fact,
'confidence': support_score,
'sources': self.find_supporting_sources(
fact, source_documents
)
})
else:
hallucinated_facts.append({
'fact': fact,
'confidence': support_score,
'risk_level': 'high' if support_score < 0.5 else 'medium'
})
return {
'verified_facts': verified_facts,
'hallucinated_facts': hallucinated_facts,
'hallucination_rate': len(hallucinated_facts) / len(facts)
}
def generate_with_citations(self, query, context, generator):
"""
强制生成带引用的回答
每个事实陈述都要标注来源
"""
prompt = f"""
回答以下问题,每个事实必须标注来源编号:
问题:{query}
参考资料:
{context}
回答格式:
- 陈述1 [来源x]
- 陈述2 [来源y]
如果无法从资料中找到答案,请回答"我不知道"。
"""
response = generator.generate(prompt)
# 验证引用有效性
validated_response = self.validate_citations(response, context)
return validated_response
def extract_facts(self, text):
"""从文本中提取事实陈述"""
# 简单实现:提取以句号、问号、感叹号结尾的句子
sentences = re.split(r'[.!?]+', text)
facts = [s.strip() for s in sentences if s.strip()]
return facts
def check_support_in_sources(self, fact, sources):
"""检查事实在源文档中的支持程度"""
# 使用语义相似度计算支持度
max_similarity = 0
for source in sources:
similarity = self.semantic_similarity(fact, source['content'])
max_similarity = max(max_similarity, similarity)
return max_similarity
易错点
- 把幻觉全部归因于模型本身(忽略检索链路问题)
- 没有评测集,只靠主观体验调链路
- 过度依赖Prompt工程而忽略数据质量
- 引用机制设计不当导致信息丢失
记忆技巧
记住降幻觉四层防护:
- 召回质量 = “找对资料”
- 重排序 = “选最相关的”
- 生成控制 = “边界约束”
- 评测验证 = “持续改进”
典型应用场景:
- 问答系统:事实准确性要求高
- 文档分析:引用溯源需求
- 客服系统:安全风险控制
- 教育应用:知识准确性保证