RAG检索精度连跪三次,我调完chunk策略后幻觉从38%降到9%
RAG检索精度连跪三次,我调完chunk策略后幻觉从38%降到9%
发版当天,新上的知识库问答刚上线两小时,后台就涌进三十多条投诉--用户说答案牛头不对马嘴,问“退货政策”竟然给出两年前的作废条款,还自己编了一个“VIP专属30天无理由”的假权益。我翻日志才发现,检索出来的文档段跟问题语义根本对不上,生成的回答又在原始信息上疯狂加戏。
那段时间我们正急着用AIGC搭建企业知识库,领导说“生成式方案快,上线再迭代”,我信了。结果第一版连基本的检索精度都稳不住,更别提幻觉问题。后来我硬着头皮把机器学习基础重新学了一遍,才明白向量相似度计算背后的数学原理,Embedding模型选型和chunk策略原来直接决定了检索命中率--这门课对零基础过渡到ML管道的工程师太关键了,学完就能上手调检索质量,省去胡乱试参数的两周。
为什么选了RAG+生成式AI却没有一次跑通
内部知识库有八千多份文档,产品手册、售后流程、合规条款混在一起。我原以为用开源LangChain搭一条AIGC流水线就能搞定:先用OpenAI的text-embedding-ada-002把所有文档向量化存进Chroma,检索时取top_k=3拼成prompt,让GPT-3.5回答。深度学习入门那会儿我只跑过图像分类Demo,对文本Embedding的特征空间毫无概念,随手设了个chunk_size=1000、overlap=0,觉得“句子越长信息越多”。
第一轮内部测试时,检索准确率(基于人工标注)只有56%,而且AIGC生成的回答经常跨文档张冠李戴。我当时以为是向量数据库选错了,换了FAISS后依然拉垮。直到后来补了AWS基础知识中向量索引优化的内容,才意识到不同Embedding模型对语义匹配的侧重点完全不同,ada-002偏长文本理解,我们的短问句更适合用sentence-transformers的all-MiniLM-L6-v2。这节课程把模型选型与成本、延迟的关系讲得很透,我照着优化后,检索命中率直接从56%拉到了78%。
chunk策略翻车:我以为越大越好,实际毁了检索
最初chunk_size=1000、overlap=0,检索时经常把无关段落和真正答案混在一起,根本区分不开。
我写了一个快速评估脚本,用不同size跑验证集,结果chunk_size=256、overlap=30时检索精度最高。代码如下:
from langchain.text_splitter import RecursiveCharacterTextSplitter
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 对比不同chunk策略
strategies = [
{'chunk_size': 1000, 'overlap': 0},
{'chunk_size': 512, 'overlap': 50},
{'chunk_size': 256, 'overlap': 30}
]
model = SentenceTransformer('all-MiniLM-L6-v2')
correct_retrievals = []
for strat in strategies:
splitter = RecursiveCharacterTextSplitter(
chunk_size=strat['chunk_size'],
chunk_overlap=strat['overlap'],
separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""]
)
chunks = splitter.create_documents([doc_text])
chunk_embeddings = model.encode([chunk.page_content for chunk in chunks])
# 用标注样本计算检索命中率... (省略具体循环)
这次我把chunk缩小并引入overlap,本质是在做数据预处理--后来学机器学习基础时才搞清,这其实和特征工程里设计滑动窗口一样,都是为了保留上下文边界信息。那门课专门有一章讲文本数据的清洗与分割,直接让我少走了半个月弯路。AIGC系统经此调整,检索精度冲到了89%,但幻觉问题依然没解决。
幻觉从12%突然飙到38%,因为我把prompt写成了开放式作文
检索精度上来后,我把top_k改为5,想让模型拿到更多依据。结果某次测试中,AIGC的幻觉率(人工抽查100条中编造事实的比例)从12%一下子跳到38%。翻看生成样本,发现模型经常把多段文档内容“缝合”成一条看似合理但完全不存在的政策。
我开始怀疑是prompt的问题。最初的指令只有一句:“请根据以下文档内容回答用户问题。”连来源标注要求都没写。深度学习入门让我理解了自回归生成模型的注意力机制--模型在缺乏约束时会用训练数据中的先验知识补全。于是我改成严格要求引用原文件、标明段号,并且用代码做了来源验证。
def verify_source(answer, source_chunks):
"""检查回答中的关键实体是否出现在检索文档中"""
import re
# 提取回答中的数字、专有名词等
entities = re.findall(r'\b\d{1,2}天|\d{1,2}%|VIP\w+|\$?\d+', answer)
verified = []
for entity in entities:
found = any(entity in chunk.page_content for chunk in source_chunks)
verified.append(found)
if not found:
print(f"疑似幻觉实体: {entity}")
return np.mean(verified) # 实体验证率
配合调整后的prompt,幻觉率初步压回到15%。但这不是终点,AIGC的稳定性还需要更系统的评估。
用混淆矩阵给幻觉分类,才发现真正该抓的是“高置信度瞎编”
为了监控AIGC输出质量,我参考超参调优中的网格搜索思路,对温度、top_p、max_tokens做了多轮测试。同时引入了一个简单但有用的评估框架:把“正确答案”和“生成答案”按实体级别做比对,画出混淆矩阵,看看哪些实体会被持续误判。
| 实际情况 | 模型认为存在 | 模型认为不存在 |
|---|---|---|
| 文档存在该实体 | TP(正确引用) | FN(漏答) |
| 文档不存在该实体 | FP(幻觉) | TN(正确排除) |
我用混淆矩阵统计后发现,高温度下FP暴涨,模型总爱“创造”促销折扣数字。把温度从0.7降到0.2后,幻觉率降到了9%。AWS机器学习的在线课程恰好有一节专门讲评估指标与错误分析,我现学现用,把漏答和幻觉分开优化,不再一刀切地调参。那门课教的混淆矩阵、精确率召回率权衡,成了我每周质量报告的底子。
学完课程后搭出的稳定流水线,不再半夜改prompt
补完机器学习管道和深度学习基础后,我把整个RAG流水线拆成了四个清晰阶段:
- 数据预处理:用自定义分句器做中文优化chunk,保留标题层级
- 检索:sentence-transformers编码,阈值过滤相似度低于0.5的文档
- 生成:GPT-3.5结合严格引用约束prompt,温度0.2
- 验证:实体重叠度检测 + 人工抽查监控
上线第二周,AIGC的检索精度稳定在91%,幻觉率连续7天不超过9%。最明显的变化是我不再凌晨被叫起来修badcase,因为学了特征存储概念后,我把每轮版本迭代的Embedding和chunk配置都做了版本化管理,回滚只需改一行索引。
现在回想,如果一开始就系统学完亚马逊云科技机器学习的整套课程,可能根本不会在chunk_size和向量选择上浪费三周。不过这段踩坑经历让我对机器学习入门到深度学习入门的路径有了切身体会:先搞定数据管道的工程问题,再深入模型调优,效率最高。
给做RAG知识库的同学的5条止血清单
- Embedding模型不要盲选默认--至少对比3种,用标注样本测检索精度,深度学习入门会教你快速跑通对比实验。
- chunk_size需要按文档类型调优--建议256~512之间,overlap保留15~30%,这本质是数据预处理的范畴,值得点进课程看具体方法论。
- prompt里强制要求引用原句--把生成式任务变成填空式,能立竿见影降低幻觉。AIGC课程里的prompt工程案例有现成模板可抄。
- 用实体验证代替人工抽查--先用混淆矩阵评估AIGC的FP模式,再针对性调温度等超参调优参数。
- 所有配置纳入版本管理--机器学习管道中讲的特征存储思路,用在RAG上能让你秒级回滚,别等上线再后悔。
这五条是我用三个周末、两次回滚换来的。如果你也正在用AIGC搭知识库,不妨先去机器学习基础把Embedding和相似度计算弄懂,再学生成式AI的幻觉控制,路径对了,痛苦少一半。
更多推荐



所有评论(0)