Skip to main content

Agentic RAG

Written: 2026.06 本页整理 Pipeline 执行流程动画中的场景和阶段说明。

1. 场景

  • 📖 完整知识问答(Stage 0-7)
  • ⚡ FAQ 精确匹配直达
  • 🚫 越界问题拒绝
  • 💬 多轮追问

2. 时间线步骤

2.1 🌐 用户发起请求

用户在浏览器中输入问题: “入职流程包含哪些步骤?” ,选择业务分类为”HR 制度”,点击发送。前端直接构造 WebSocket 消息。

2.2 🔌 WebSocket 入口接收消息

FastAPI WebSocket 路由接受连接后,对每条消息执行限流、JSON 解析,并构造 QueryServiceContext。

2.3 ⚙️ QAService.stream_query() 启动

API 层不做问答预判,只把 QueryServiceContext 交给 QAService.stream_query()。后续查询路由、检索准备和 FAQ/Doc 检索都在 Pipeline 主链路内完成。

2.4 🏗️ Stage 0:create_query_context()

创建 RAGQueryContext 运行时上下文对象。这个对象贯穿后续所有阶段,携带场景配置、数据域、会话信息、trace_id、知识库版本等全局状态。

2.5 🧭 Stage 1:查询路由 — route=retrieval

decide_route() 统一判断 direct_answer / faq_exact / retrieval。本场景既不是问候/转人工/越界,也没有 FAQ 精确命中,所以返回 route=retrieval,继续检索准备。

2.6 🧠 Stage 2a:意图分类 classify_intent()

规则优先 + LLM 补充的两级意图分类。直答类规则已在 Stage 1 先行处理;这里继续判断追问、FAQ_QUERY、KNOWLEDGE_QUERY 等需要检索的业务意图。

2.7 🧠 Stage 2b:检索准备参数包

prepare_retrieval() 汇总下游检索需要的参数:历史上下文、source 过滤、必要时追问改写、检索计划、查询变体和 Prompt Profile。当前问题已经完整,所以改写函数会原样返回。

2.8 🧠 Stage 2c:兜底 direct_answer 检查

主链路仍保留兜底检查:如果检索准备阶段产出 direct_answer,也会直接返回。但问候、越界、转人工等确定性直答通常已在 Stage 1 收口。

2.9 📋 Stage 3a:FAQ 混合检索

多查询变体 → Milvus FAQ Collection 执行 Hybrid Search。BGE-M3 生成 Dense 向量做语义检索,Milvus BM25BuiltInFunction 生成 Sparse 向量做关键词检索。weighted ranker 按 0.55/0.45 权重融合两路结果。

2.10 📋 Stage 3b:FAQ 候选合并 + 置信度判断

多个查询变体召回的 FAQ 候选按 chunk_id 合并去重(同一 chunk 只保留最高分)。按 score 降序排序。检查最高分是否 ≥ 置信度阈值(0.80)——达标则直接采用为标准答案,无需 LLM。

2.11 📄 Stage 4a:文档混合检索

查询变体 → Milvus Document Collection 执行 Hybrid Search。与 FAQ 检索相同的 Dense+Sparse 双路融合机制,但文档 Collection 的数据量更大(数万 chunk),且 query 过滤表达式更复杂(source + kb_version + data_scope)。

2.12 📄 Stage 4b:CrossEncoder Reranker 精排

BGE Reranker Large(CrossEncoder 架构)对 Milvus 召回的 Top 30 候选用 [query, doc] 拼接编码方式逐一精细打分。与向量相似度相比,CrossEncoder 的交叉注意力机制能精准区分语义相近但答非所问的文档。

2.13 📊 Stage 5:上下文构建

合并 FAQ 候选 + 文档候选 → 去重 → 按分数排序 → 截断至上下文窗口上限 → 格式化 Prompt Context。每条上下文标注来源编号 [1][2][3]…,最终答案引用增强时依此追加来源标注。

2.14 🤖 Stage 6:LLM 流式生成 + 引用增强

System Prompt(场景变量注入:企业名称、助手名、业务域)+ 上下文 + 用户问题 → ChatOpenAI(model=“qwen-plus”, streaming=True).stream()。LLM 逐 token 生成,每个 token 通过 asyncio.to_thread + WebSocket 实时推送到浏览器;生成结束后执行 enforce_answer_citations() 补强来源编号。

2.15 💾 Stage 7:保存历史 + 发送 Trace

LLM 生成和引用增强完成后,add_turn() 将问答对写入 MySQL chat_messages,finish_success() 发送含来源、耗时、意图的 end 事件并写入 Trace。

2.16 ✅ 一次完整 RAG 问答结束

总结 :用户问题经过 Stage 0-7 管线(上下文创建 → 查询路由 → 检索准备 → FAQ检索 → 文档检索 → 上下文构建 → LLM生成与引用增强 → 保存历史与Trace),最终以流式打字效果呈现带来源引用的答案。 本次关键指标 :总耗时 2.3s,召回30条→Rerank至5条,LLM生成156 tokens,引用3处来源,数据写入MySQL+LangSmith Trace。

2.17 🌐 用户发起请求

用户在 SaaS 客服场景中输入:” 忘记密码怎么办 “

2.18 ⚙️ WebSocket 主链路启动

WebSocket 入口解析消息并调用 QAService.stream_query()。场景解析、数据域构建和后续意图分类都在 Pipeline 主链路中完成。

2.19 🏗️ Stage 0 完成

RAGQueryContext 创建完成:场景 saas_support、数据域 default/dataset_saas、KB v1、trace_id 已生成。

2.20 🧭 Stage 1:查询路由 — route=faq_exact

decide_route() 内部试探 FAQ 精确匹配:“忘记密码怎么办” === FAQ标准问题 #faq_003 → 命中! 返回 RouteDecision(route=“faq_exact”, intent=FAQ_QUERY)。

2.21 💾 Stage 7:保存历史

虽然跳过了完整检索和生成,但仍需保存本轮问答到 MySQL。add_turn(session_id, query, answer) → chat_messages 表写入。

2.22 🌐 用户提问:“彩票怎么买”

用户输入了一个与企业知识库无关且带风险的话题。

2.23 ⚙️ WebSocket 主链路

WebSocket 入口解析消息后调用 QAService.stream_query(),后续在 Pipeline 中完成场景解析、数据域构建和统一查询路由。

2.24 🏗️ Stage 0 完成

RAGQueryContext 创建完成。

2.25 🧭 Stage 1:查询路由 — route=direct_answer / OUT_OF_SCOPE

decide_route() 先处理问候、转人工、越界等确定性直答。“彩票怎么买”命中越界规则,直接产出 OUT_OF_SCOPE 回答。这个分支不访问 FAQ、不调用 LLM,也不会进入后续检索阶段。

2.26 💾 Stage 7:保存历史 + 发送 Trace

add_turn() → MySQL。finish_success() → end事件。

2.27 💬 多轮追问场景 — 第2轮对话

第1轮 :用户问”入职流程包含哪些步骤?”→ 系统完整RAG回答。 第2轮(当前) :用户追问” 那审批需要多久? “

2.28 ⚙️ 主链路加载对话历史

stream_query() 创建上下文时读取最近消息。启用历史摘要时,旧消息会被压缩为一条 SystemMessage(“历史摘要:上次问了入职流程…”)。

2.29 🏗️ Stage 0 完成

RAGQueryContext 包含完整对话历史。context.history_messages 中已有摘要 + 最近消息。

2.30 🧭 Stage 1:查询路由 — route=retrieval

追问”那审批需要多久”不是问候、转人工、越界,也没有 FAQ 精确命中,所以 decide_route() 返回 retrieval,继续结合历史做检索准备。

2.31 🧠 Stage 2a:意图分类 — FOLLOW_UP

LLM 结合对话历史判断:用户在使用代词”那”指代上文中的”入职流程” → 意图 FOLLOW_UP。

2.32 🧠 Stage 2b:追问改写 — 代词消解

rewrite_query(history, “那审批需要多久”, FOLLOW_UP) → LLM 被提示:“用户说「那审批需要多久」,请结合历史将其改写为完整独立问题” → ” 入职流程中的审批环节需要多长时间? “

2.33 📄 Stage 4:文档检索+重排

用改写后的完整问题检索 → Hybrid Search → Reranker。由于改写消除了指代歧义,检索精度显著提升。

2.34 📊 Stage 5:上下文构建

FAQ 候选和文档候选按分数、去重键和 token 预算筛选,形成最终 Prompt Context。

2.35 🤖 Stage 6:LLM流式生成 + 引用增强

System Prompt 包含历史摘要 + 追问约束(“回答焦点限定在当前问题,但需结合历史理解指代”)→ LLM 流式生成 → 引用增强。

2.36 💾 Stage 7:保存历史 + end事件

MySQL 写入本轮问答,finish_success() 发送 end 事件并记录 Trace。