RAGFlow 实战(三):检索调参实录——从「检索不到」到「检索得准」

系列导航:(一)部署、鉴权与排障;(二)文档解析实战;(三)本篇;(四)API 自动化。

一、检索是 RAG 的主战场

文档切好了,接下来全是检索的问题。RAGFlow 的检索测试接口(POST /api/v1/retrieval)就是调参的主战场——绕过聊天历史,纯检索质量验证。这篇把所有检索侧的实战结论一次讲完。

二、结论 1:精确查询,就要短问句

拿产品参数表做精确查询,我一开始很自然地写长问句:

1
Product ID M20978 的 Torque 是多少?

Top-1 返回的是邻居行——不对。换成只发 ID:

1
M20978

命中 1 条,正是要的那行。

原因:语义化问句里的通用词(Product / ID / Torque)会让 ES 的 minimum_should_match 放行大量邻居行,ID 的信号被稀释了。精确查询(按编号/ID 找行)就发短词,或者走结构化字段过滤。这条经验对表格类知识库是决定性的。

三、结论 2:中文长文本,把向量权重调到 0.7

实测中文长文本的关键词得分普遍只有 0.14~0.33——中文分词语义下的关键词匹配天然吃亏,长文本的命中主要靠向量。

1
retrieve --question "xxx" --vector-weight 0.7

反过来,找专有名词时短词查询效果最好:实测 魇渊 这个词,长句查询得分 0.27,单词查询 0.57。权重没有银弹,按语料调:

场景vector-weight
中文长文本、叙述性内容0.7(向量为主)
专有名词、编号精确查询0.3 以下(关键词为主)
不确定默认 0.3 起步,A/B 对比

四、结论 3:检索为空,先查阈值——头号原因是人为的

「检索不到东西」的排查顺序:

  1. 相似度阈值是不是调太高——这是头号人为原因。阈值调太严,把正确答案挡在门外;
  2. 文档解析是否真的 done(见系列第一篇的上传≠解析);
  3. 索引里有没有 chunk;
  4. embedding 模型是否加载成功。

宁可多召回几条让 LLM 自己筛,也不要严到把答案挡在门外。相似度阈值默认 0.2,先别动它。

五、结论 4:前端高亮不是命中清单

判断检索质量,看 Top-N 的完整内容,不要看前端高亮。

前端高亮是 ES 的摘录(fragment_size=50,最多 5 片),它只是「关键词出现的片段」,不是「命中的 chunk 清单」。盯着高亮调参,会被摘录的片段骗——正确做法是拉 chunks 数组,看 similarity / term_similarity / vector_similarity 三个分项。

六、结论 5:HTTP 200 +「未找到」≠ 模型问题

这条是「不报错但不对」的经典:

1
HTTP 200 + answer = "知识库中未找到相关内容"

这不是模型连通性问题,是检索没送对料——软失败,日志里一片绿。请求 pending 或报错才是连接问题。排查时先分清:是「没检到」还是「没连上」,两者的排查方向完全相反。

七、结论 6:聊天链路比检索链路多两件事

调参时要注意,聊天和检索走的是同一套混合检索引擎,差别只在聊天多两步:

  1. refine_multiturn(默认开启):多轮对话时,把整段聊天历史压缩改写成一个独立问题再检索;
  2. LLM 读块出答案。

所以聊天时「问对了但答错了」,问题可能在 query 改写而不在检索。调试经验:先用检索测试接口验证纯检索质量,再进聊天链路——两步分开,定位才快。

八、把调参变成工程:回归测试

调参最怕「感觉变好了」。我的做法是准备 20~30 个有标准答案的问题,改任何配置(切块方法、权重、阈值、embedding)前后各跑一遍,对比命中率和答案完整度:

1
2
3
4
5
6
7
8
9
10
11
12
13
QUESTIONS = [
("M20978 的 Torque 是多少", "45 N·m"),
("第X条 付款方式", "百分之三十"),
...
]

def regression(kb_id):
hits = 0
for q, expected in QUESTIONS:
chunks = retrieve(question=q, dataset_ids=[kb_id], top_k=8)
if any(expected in c["content"] for c in chunks):
hits += 1
return hits / len(QUESTIONS)

一个百分比,把「感觉」变成数字。RAG 调优的所有结论,都该以这种形式落盘。

九、小结

检索调参六条:精确查询发短词、中文长文本权重 0.7、检索为空先查阈值、高亮不是命中清单、软失败和连不上要分清、聊天链路多一步 query 改写。加上回归测试的方法论,检索侧就算入门了。下一篇讲怎么把这套全脚本化——API 自动化。