LangGraph第四阶段:Agentic RAG (智能体化检索增强)
迈向大模型工业化:Agentic RAG 智能体化检索增强生成深度解析
在 RAG(检索增强生成)的发展历程中,我们正在经历从 Naive RAG(简单向量检索)到 Advanced RAG(重排与切片优化),再到 Agentic RAG(智能体化检索)编排的范式转移。
传统的 RAG 是被动的:无论问题简单还是复杂,它都走同样的检索路径。而 Agentic RAG 将 RAG 转变为一个主动的决策流,赋予了智能体“反思”、“纠错”和“多步规划”的能力。
一、 Adaptive RAG:自适应检索的“分诊中心”
1. 原理:基于意图的动态路由 (Intent-based Routing)
Adaptive RAG 的核心哲学是:并非所有的用户提问都配得上一次昂贵的向量检索。它通过在流程的最前端设置一个“分诊”节点,利用 LLM 的推理能力对用户查询(Query)进行分类,从而选择成本最低、准确率最高的路径。
2. 为什么在生产环境中使用它?(生产价值深度解析)
在工业级应用中,自适应路由不仅是一个功能,更是系统稳定性和经济性的保命符。
-
极致降本与 Token 保护:
-
原理:传统 RAG 无论问题为何都会触发向量搜索。如果用户只是打招呼(如“你好”),系统若去检索库中搜索“你好”,不仅浪费向量数据库的查询费,还会将搜到的无关“噪音文档”塞进 LLM 的上下文,导致昂贵的输入 Token 浪费。
-
例子:在日活万级的客服系统中,约 30% 是简单咨询或闲聊。通过路由直接回答,每月可节省数千元的 API 支出。
-
-
破解向量搜索的“语义鸿沟” (Semantic Gap):
-
原理:向量检索擅长模糊匹配,但不擅长精确数值和逻辑关系。
-
例子:用户问“2023 年第四季度的毛利率是多少?”。向量检索可能会召回包含“2023”和“毛利率”的 5 篇不同年份的报告,导致模型计算错误。
-
实践:Adaptive RAG 识别出“数值/统计意图”后,直接路由至 Text-to-SQL 节点或元数据过滤器(Metadata Filter),实现 100% 的准确回传。
-
-
极致降低延迟 (UX 优化):
-
原理:向量搜索 + 重排(Rerank)通常需要 1-3 秒。自适应路径允许简单问题绕过这些环节。
-
例子:对于常见的 FAQ 问题(如“公司地址在哪”),路由至 Redis 缓存或本地 KV 存储,响应时间可从 3 秒降至 0.5 秒以内。
-
3. 生产实际示例:多路径分发策略
在复杂的企业级应用中,分发策略就像是一个“交通警察”。它不仅要看“路怎么走”,还要看“车(Query)长什么样”。
-
原理:语义域映射 (Semantic Domain Mapping):我们通过 Prompt 引导 LLM 识别 Query 的“数据领域”。生产环境通常维护一张 意图映射表,例如:
-
指标类 -> 映射至只读数据库 (Read-only DB)。
-
政策/非结构化类 -> 映射至向量数据库 (Vector DB)。
-
实时变动类 -> 映射至 Web 搜索接口 (Google/Tavily)。
-
系统/指令类 -> 映射至本地函数调用或直接回复。
-
-
为什么用:消除“无效推理”:如果所有路径合并,Prompt 会变得极其臃肿(包含 SQL Schema + 检索文档 + 搜索结果)。通过分发策略,我们可以实现 “按需加载上下文”,每个分支节点只持有其对应的精简 Prompt。
代码实现:基于强类型契约的多路径分拨中心
from typing import Literal, Annotated
from pydantic import BaseModel, Field
# 1. 定义路由契约:利用 Enum 强制 LLM 做出明确的“分流决策”
class RouterContract(BaseModel):
"""根据查询类型决定最优执行路径"""
route: Literal["direct", "knowledge_base", "sql_stats", "web_live"] = Field(
description="""根据意图分类:
- direct: 闲聊或问好
- knowledge_base: 涉及企业内部产品手册、HR 政策、技术文档
- sql_stats: 涉及具体数值统计、销售额、库存、用户数
- web_live: 涉及最新新闻、股市行情、天气等实时信息"""
)
reason: str = Field(description="简短说明路由选择的依据")
def adaptive_router(state):
"""分诊中心:将自然语言映射到技术路径"""
question = state["question"]
# 使用 .with_structured_output 确保结果 100% 可解析
structured_llm = llm.with_structured_output(RouterContract)
# 生产提示:可以在此处注入上下文信息(如当前用户权限)来辅助路由
decision = structured_llm.invoke(f"用户问题:{question}")
# 记录日志到 State 中以便 LangSmith 追踪
print(f"[Router] 意图识别: {decision.route} | 原因: {decision.reason}")
return decision.route
# 2. 在 LangGraph 中定义动态边逻辑
# workflow.add_conditional_edges(
# "entry_node",
# adaptive_router,
# {
# "direct": "answer_node", # 闲聊直接答
# "knowledge_base": "vector_node", # 向量检索路径
# "sql_stats": "sql_agent_node", # 数据库查询路径
# "web_live": "web_search_node" # 实时搜索路径
# }
# )
二、 Corrective RAG (CRAG):检索质量的“最后一道防线”
1. 原理:检索结果的“置信度治理”
CRAG (Corrective RAG) 的核心逻辑在于:不再盲目信任检索器的 Top-K 结果。它在检索(Retrieval)与生成(Generation)之间插入了一个“自我反思”层,对每一个检索到的文档片段进行打分。
-
确定性分类:
-
Relevant (相关):文档足以回答问题,保留并进入生成阶段。
-
Ambiguous (模糊):文档可能相关但信息不全,保留文档并触发“知识补全”逻辑。
-
Irrelevant (无关):彻底过滤,防止干扰模型注意力。
-
2. 为什么在生产环境中使用它?
-
防止“平庸生成”:传统 RAG 如果搜到的是废话,模型会强行编造答案。CRAG 允许智能体说“我不确信”,并主动寻找更好的证据。
-
解决知识滞后:当向量库没有实时更新时,CRAG 能通过“打低分”自动触发 Web 搜索,利用搜索引擎补全最新的时效性信息。
-
降噪与注意力聚焦:通过剔除不相关的 Top-K 片段,显著提升 LLM 的上下文质量。
3. 生产实践:基于打分的动态补全逻辑
代码实现:LLM 文档裁判员
from pydantic import BaseModel, Field
# 1. 定义打分契约
class GradeContract(BaseModel):
"""对检索到的文档进行二元或三元相关性评估"""
score: Literal["yes", "no"] = Field(description="文档是否包含回答用户问题所需的关键信息?")
reason: str = Field(description="打分的逻辑依据")
def grade_documents_node(state):
"""文档质检节点"""
question = state["question"]
documents = state["documents"]
# 过滤后的文档容器
filtered_docs = []
# 搜索标志位:如果发现重要信息缺失,则设为 True
needs_search = False
grader_llm = llm.with_structured_output(GradeContract)
for doc in documents:
res = grader_llm.invoke(f"问题: {question}\n文档片段: {doc.page_content}")
if res.score == "yes":
filtered_docs.append(doc)
else:
needs_search = True # 只要有文档无关,通常意味着向量库覆盖不足
# 决策:是直接生成,还是先去网上搜一下?
if needs_search:
return {"documents": filtered_docs, "run_web_search": True}
return {"documents": filtered_docs, "run_web_search": False}
# 2. 动态路由逻辑
def decide_to_generate(state):
if state["run_web_search"]:
return "web_search_node"
return "generate_answer_node"
三、 Self-RAG:三重指标实现内容“去伪存真”
在生产级 Agentic RAG 中,Self-RAG 被设计为一个严苛的质检流水线。它不仅仅是一个简单的评分,而是一个具备“打回重写”能力的闭环系统。
1. 三大指标的生产引入与时机
这三个指标分别在工作流的不同阶段介入,构成三道门槛:
| 指标名称 | 引入时机 | 核心作用 | 处理逻辑 |
|---|---|---|---|
| 指标 1:相关性 (IS_RELEVANT) | 检索后准入 | 评估文档片段是否能支撑问题回答 | 若不相关,触发查询重写或扩大搜索 |
| 指标 2:忠实度 (IS_SUPPORTED) | 生成后初审 | 确保生成的答案事实在文档中有据可查 | 若发现“私货”,打回生成节点并附带说明 |
| 指标 3:有用性 (IS_USEFUL) | 发布前终审 | 评估回答是否解决了用户的核心需求 | 若答非所问,引导重新规划回答逻辑 |
2. 为什么用?(生产痛点对齐)
-
合规性要求:在金融或医疗场景,如果 AI 凭空捏造一个利率或治疗方案,法律风险巨大。
-
减少无效回复:防止 AI 给出“虽然正确但没用”的废话(如“请联系人工”这种无意义召回)。
3. 代码实现:闭环质检流逻辑
from pydantic import BaseModel, Field
from typing import Literal, List
# 1. 忠实度质检协议 (解决幻觉)
class GroundednessGrader(BaseModel):
score: Literal["yes", "no"] = Field(description="回答是否完全基于文档?")
reasoning: str = Field(description="如果不基于文档,指出哪些点是幻觉")
# 2. 有用性质检协议 (解决质量)
class UsefulnessGrader(BaseModel):
score: Literal["yes", "no"] = Field(description="回答是否直接且有效地解决了用户问题?")
def self_rag_workflow(state):
"""质检流决策中心"""
documents = state["documents"]
generation = state["generation"]
# --- 第一步:忠实度检查 ---
groundedness_llm = llm.with_structured_output(GroundednessGrader)
context = "\n".join([d.page_content for d in documents])
check_g = groundedness_llm.invoke(f"背景: {context}\n答案: {generation}")
if check_g.score == "no":
print(f"[Self-Correction] 发现幻觉: {check_g.reasoning}")
return "rewrite_with_feedback" # 携带失败原因跳回生成节点
# --- 第二步:有用性检查 ---
usefulness_llm = llm.with_structured_output(UsefulnessGrader)
check_u = usefulness_llm.invoke(f"问题: {state['question']}\n答案: {generation}")
if check_u.score == "no":
return "improve_answer_logic" # 跳回逻辑增强节点
return "finish" # 只有双重通过,才输出给用户
四、 多跳推理 (Multi-hop Reasoning):攻克长链逻辑难题
1. 原理:信息碎片的“接力检索”
在生产环境中,用户的问题往往不是孤立的。多跳推理的核心在于:有些答案被分散在多个文档中,必须通过第一步检索到的“线索”去发起第二步检索。这就像拼图,每一块碎片都提供了下一块碎片的坐标。
2. 为什么在生产环境中使用它?(生产价值深度解析)
在复杂的垂直领域(金融、法律、医学),多跳推理是让 RAG 从“搜索引擎”升级为“专家助手”的关键。
-
解决语义孤岛与隐性关联:
-
原理:向量搜索只能找到“语义相似”的文档,无法理解逻辑连接。
-
场景:例如提问“收购了 A 公司的那个企业的总部在哪?”。向量库可能会分别存有“B 收购 A”和“B 总部在西雅图”,但它们语义并不直接相似。
-
价值:多跳智能体能自动识别出 B 是中间桥梁,发起第二次针对 B 的精准检索,打破数据间的孤岛。
-
-
遍历网状分布的复杂依存关系:
-
原理:在法律尽调或供应链溯源中,信息往往是网状(Graph-like)分布的。一个事实(出资人)往往是另一个事实(最终受益人)的查询条件。
-
价值:智能体通过接力,能够覆盖完整的逻辑链,防止单次 Top-K 检索因权重不足而漏掉关键的深层信息。
-
-
显著降低“上下文噪音”与幻觉:
-
原理:如果一次性尝试召回所有可能相关的文档(如 Top-50),会引入海量无关信息,导致 LLM 分心。
-
价值:多跳推理遵循“按需获取”原则,每一步只检索最核心的几条线索。这种“精准滴灌”式的输入显著降低了长文本带来的推理偏差。
-
3. 生产实际:基于状态反馈的循环搜寻架构
在生产中,多跳推理不是盲目的循环,而是一个 “提取线索 -> 自我评估 -> 动态扩充” 的精密过程。它通过将复杂的依存关系拆解为多次“点对点”的精准打击,从而在根本上杜绝了海量无关文档堆砌导致的“上下文溺水”。
核心实现:信息依存链的动态解析
多跳推理的核心在于智能体不仅要看“目前的答案是什么”,还要思考“为了补完这个答案,我下一步要去搜什么”。
from pydantic import BaseModel, Field
from typing import Literal, List, Optional
# 1. 定义信息完备性与下一跳决策契约
class ReasonerDecision(BaseModel):
"""判断信息完整性并提取下一跳线索"""
is_complete: bool = Field(description="基于当前已知信息,是否足以完整、无误地回答原始问题?")
reasoning_path: str = Field(description="当前的逻辑链条分析(例如:已查到收购方为 B 公司)")
next_hop_query: Optional[str] = Field(description="如果信息不足,请生成针对‘缺失环节’的精准搜索词")
evidence_found: List[str] = Field(description="从当前检索结果中提取到的关键线索片段")
def multi_hop_reasoner_node(state):
"""多跳推理决策中心:解决语义孤岛与复杂依存"""
# 获取原始问题与已累积的所有检索上下文
original_question = state["question"]
accumulated_context = "\n".join([d.page_content for d in state.get("documents", [])])
# 绑定结构化输出,让 LLM 充当‘逻辑追溯员’
reasoner_llm = llm.with_structured_output(ReasonerDecision)
# 执行决策逻辑
# 这里的关键在于:不只是搜相似,而是基于已发现的‘A’去寻找‘B’
decision = reasoner_llm.invoke(
f"原始目标: {original_question}\n"
f"已掌握线索: {accumulated_context}\n"
f"分析当前状态,确定是否需要发起下一跳检索。"
)
if decision.is_complete:
return "generate_final_answer"
else:
# 记录逻辑链条,避免重复检索,并精准发起下一跳
print(f"[Multi-Hop] 逻辑链: {decision.reasoning_path}")
print(f"[Next Hop] 针对性检索: {decision.next_hop_query}")
# 将新生成的精准 Query 存入 State,触发下一次检索节点
return {
"current_search_query": decision.next_hop_query,
"reasoning_history": decision.reasoning_path
}
# 2. 生产防御:设置物理递归上限,防止 Token 爆炸
# 在 workflow.compile(recursion_limit=10) 中设置
为什么这种模式能解决核心痛点?
-
突破“语义孤岛”:在“收购 A 公司的企业 B 总部在哪”例子中。第一跳发现“B 收购了 A”,此时
next_hop_query会被自动重写为“企业 B 的总部地点”。即便 A 和 B 的总部在语义上毫无关联,逻辑链条也能强行将它们连接。 -
遍历网状依存:它像人类一样顺藤摸瓜。每一步只关注当前的“依存项”,逐步从 A 链接到 B,再从 B 链接到 C,实现了对网状复杂关系的有序拆解。
-
极致“上下文降噪”:由于每一步只召回与当前“子问题”高度相关的 3-5 条文档(精准滴灌),而不是一次性塞入 50 条杂乱文档,模型受到的干扰降到了最低,从而大幅减少了幻觉产生的空间。
五、 总结:Agentic RAG 的架构技能树
构建生产级 Agentic RAG 不仅仅是写 Prompt,更是一项严密的闭环工程。以下是开发者必须攻克的四大核心技能:
-
意图驱动的自适应能力 (Adaptive Skill):
-
原理:利用 LLM 作为“决策中枢”,将用户查询实时映射到 SQL、向量库或 API 路径。
-
生产应用:通过
Literal强约束路由,实现简单问题毫秒级响应,复杂问题精准分发,从而在根源上优化成本。
-
-
基于分级的质量治理 (Grading Skill):
-
原理:在检索后引入“二元质检节点”,对检索出的每一个 Chunk 进行相关性过滤。
-
生产应用:剔除 80% 的无效召回(噪音),确保 LLM 的注意力始终聚焦在核心事实证据上。
-
-
抗幻觉的闭环自愈 (Self-Correction Skill):
-
原理:利用 Self-RAG 的三重评分(相关性、忠实度、有用性),构建生成内容的反馈循环。
-
生产应用:针对金融、法律等高敏领域,通过“打回重写”机制确保输出 100% 忠实于文档背景,拒绝模型“自由发挥”。
-
-
深度链式逻辑分析 (Multi-hop Skill):
-
原理:将复杂问题拆解为多个逻辑依存的子任务,实现“顺藤摸瓜”式的接力检索。
-
生产应用:解决跨文档的隐性关联分析,打破传统 RAG 的“单次检索天花板”,实现从“搜资料”到“写研报”的跃迁。
-
生产级架构逻辑编排示例:
# 生产级 Agentic RAG 的逻辑顶层设计
def agentic_rag_system(user_query: str):
# 阶段 1:自适应分诊 (Adaptive Router)
target = adaptive_router(user_query)
if target == "direct":
return direct_respond(user_query)
# 阶段 2:多跳逻辑规划 (Multi-hop Planner)
while not is_info_complete:
docs = retrieve_step(current_sub_query)
# 阶段 3:文档质检与补全 (CRAG)
relevant_docs = grade_and_filter(docs)
if not relevant_docs:
relevant_docs = web_search_backup(current_sub_query)
# 阶段 4:信息依存分析
is_info_complete, next_sub_query = analyze_dependency(relevant_docs)
# 阶段 5:自我净化生成 (Self-RAG)
while not is_safe_and_useful:
answer = generate_based_on_all_docs(user_query, relevant_docs)
# 执行忠实度与幻觉检查
is_safe_and_useful = double_check_hallucination(answer)
return answer
结语
Agentic RAG 的本质是将 LLM 从一个“复读机”提升为一个“质检员”和“规划师”。通过在 LangGraph 中构建这些闭环反馈逻辑,我们可以显著提升 RAG 系统在复杂商业环境中的鲁棒性和准确度。
更多推荐
所有评论(0)