给 RAG 加上一个能决定何时停止的 Dispatcher 调度器才
很多人做 RAG 只要检索出东西喂给模型就行,但实际跑起来最头疼的是模型在死循环里打转,或者在还没找全信息时就草率给出一个错误的答案。我最近在尝试把 RAG 从简单的线性流改成循环流(Loop Engineering),核心其实就在于得有一个像 Dispatcher 这样的调度机制,来实时判断当前的检索结果是否足以回答问题。
这种架构虽然增加了复杂度,但比那种单次检索的 RAG 稳健得多,尤其是在处理复杂的多跳问题时。
下一篇
用 Claude Code 配合 Lean 4 一个周末搞定两个数学 →
如果调度器认为信息不足,就得重新调整查询词回溯检索;如果发现已经进入重复循环,就得强制跳出。这其实就是所谓的 Agentic RAG 的雏形,不能只靠 Prompt 里的“请仔细检查”,得在工作流层面写死逻辑。
我尝试实现的一个简化调度逻辑大概是这样的:
def rag_dispatcher(query, context, max_loops=3):
loop_count = 0
while loop_count < max_loops:
# 评估当前上下文是否足以回答问题
decision = evaluate_sufficiency(query, context)
if decision == "SUFFICIENT":
return generate_final_answer(query, context)
elif decision == "NEED_MORE_INFO":
# 重新生成检索词并更新 context
new_query = rewrite_query(query, context)
context += retrieve_documents(new_query)
loop_count += 1
else:
# 判定为无法回答或陷入死循环
return "无法从现有文档中找到准确答案"
return generate_final_answer(query, context)在实操过程中,我发现最容易踩坑的地方在于 evaluate_sufficiency 这个判定环节。如果这个判定的阈值设得太高,模型会不停地检索直到触碰 max_loops 上限,导致响应延迟极高;如果设得太低,又会产生幻觉。
建议在部署这种循环工作流时,重点优化以下几个维度:
- 判定状态机: 明确定义 SUFFICIENT(足够)、INSUFFICIENT(不足)、IRRELEVANT(无关)三种状态,而不是简单的 Yes/No。
- 查询重写机制: 每次 Loop 之后,必须对 query 进行语义漂移修正,否则检索回来的永远是同一批文档。
- Token 成本控制: 循环次数越多,上下文窗口堆积越快,必须在每轮循环后对 context 进行精简或摘要处理。
这种架构虽然增加了复杂度,但比那种单次检索的 RAG 稳健得多,尤其是在处理复杂的多跳问题时。
免费 AI 工具箱 · 全部完全免费