用 LangGraph 的 StateGraph 构建具备自我修正能力的 RAG 工作流
解决 RAG 链路中“幻觉”与“检索噪声”的顽疾,关键在于让模型具备在输出前进行自我审查的能力。传统的线性流程(检索 → 生成)往往会导致 LLM 在面对无关片段时强行编造答案,而通过 LangGraph 的 StateGraph 将流程重构为带循环的图结构,可以实现“检索 → 评估 → [如果不合格 → 重新检索/重写查询] → 生成”的闭环逻辑。
在实测对比 GPT-4o 与 Claude 3.5 Sonnet 担任“评估者”角色的表现时,可以发现明显的差异:
GPT-4o 展现出极强的指令遵循能力。在设定了严格打分标准(如 0-1 分)的评估节点下,它能稳定判定检索内容对问题的覆盖程度。但在处理复杂的逻辑循环时,偶尔会陷入死循环,在错误的路径上反复打转。
Claude 3.5 Sonnet 则在“重写查询”环节表现得更为出色。当评估节点判定检索失败时,它能精准识别是原问题模糊还是关键词偏差,并生成更高质量的搜索词,从而有效提升第二次检索的命中率。
如何通过 State 对象实现节点间的状态传递?
整个逻辑实现的底层核心是定义 State 状态对象,通过它在不同节点间传递检索文档与当前判定状态:
from typing import TypedDict, List
class GraphState(TypedDict):
question: str
generation: str
documents: List[str]
iteration_count: int
在设置条件边(Conditional Edge)时,通过路由函数实现了控制:只要 iteration_count 未超过 3 次且评估结果定性为 irrelevant,系统就会强制回溯至检索节点。
实测对比结论:
自我修正链路能否有效降低 RAG 的幻觉率?
纯 RAG 链路(线性):
在面对长尾知识点时,由于无法处理无关片段,模型常出现“一本正经胡说八道”的情况,准确率维持在 65% 左右。
LangGraph 自我修正链路:
由于能够触发 rewrite_query → retrieve 的循环,检索噪声被过滤的概率显著提高。实测数据显示,在复杂链路下,使用 Claude 3.5 Sonnet + LangGraph 的最终答案准确率可提升至 85% 以上。
优缺点分析:
优点: 赋予了 RAG “意识到自己不知道”的能力,极大程度降低了幻觉风险,不再盲目生成。
缺点: 由于单个问题可能触发 2-3 次 LLM 调用,Token 消耗会激增,响应延迟(Latency)也明显增加。对于实时性要求极高的应用场景,这种架构显得过于沉重。
