当前 RAG 全链路
本页描述仓库里“当前已经落地”的 RAG 实现,不讨论远期方案或抽象蓝图。它回答的是:
- 文档如何从上传一路走到可检索状态
- 会话请求到来时,RAG 具体按什么顺序检索
- 为什么
Semantic Splitter配置正确,查询仍然可能查不到 - 出问题时应该看哪里、改哪里、怎么排查
如果你只关心某一个局部:
- 知识源与摄取操作:看 RAG 知识库管理
- 检索服务细节:看 RAGRetrievalService 概览
- 编排器运行阶段:看 编排器
- 调试接口:看 核心概念:API 服务 和 端点概览
一图看懂
flowchart TB
SourceConfig[知识源与 Agent 配置]
Upload[上传文档]
Inspect[可选 Inspect 与 Preview]
Ingest[触发 Ingestion]
Parse[Parser 解析]
Chunk[Chunking 策略分块]
Embed[Embedding 写入向量]
Stores[PostgreSQL 与 Qdrant]
Mount[知识源挂载到 Agent]
UserTurn[用户会话请求]
Orchestrator[聊天编排器]
SourceResolve[解析活跃 source 与 priority]
VectorRecall[向量召回]
CorrectionRecall[托管纠错定向召回]
KeywordFallback[关键词回退补位]
Rerank[可选重排]
ContextBuild[回表并格式化上下文]
LLM[模型生成回复]
Debug[Turn RAG Debug 与 provenance]
CorrectionPublish[管理员纠错发布]
SourceConfig --> Upload --> Inspect --> Ingest --> Parse --> Chunk --> Embed --> Stores
Stores --> Mount --> UserTurn --> Orchestrator --> SourceResolve --> VectorRecall
VectorRecall --> CorrectionRecall --> KeywordFallback --> Rerank --> ContextBuild --> LLM
LLM --> Debug
CorrectionPublish --> Ingest
关键入口
用户与运维入口
| 入口 | 作用 |
|---|---|
| Admin Knowledge Sources | 创建知识源、上传文档、触发 ingestion、查看 inspect/run 状态 |
| Admin Agent Detail | 配置 Agent 默认行为,挂载知识源,决定聊天时可见 source 范围 |
| Admin Conversations -> RAG | 查看某个 Turn 的持久化 RAG provenance,并重新跑一次 retrieval debug |
POST /stream / WS /ws/{session_id} |
正常对话入口,聊天态 RAG 在这里被编排器调用 |
POST /sessions/{session_id}/turns/{turn_id}/rag-debug |
运维排障入口,解释“为什么没命中这段知识” |
POST /sessions/{session_id}/turns/{turn_id}/correction/publish |
把管理员纠错重新写回托管纠错知识源 |
代码入口
| 路径 | 角色 |
|---|---|
ai_service/services/ingestion.py |
摄取主编排,负责下载、解析、分块、向量化、写库 |
ai_service/services/chunking.py |
分块策略与 capability 校验 |
ai_service/services/embedding.py |
文本向量生成 |
ai_service/services/rag_retrieval.py |
运行时检索主入口 |
ai_service/services/rag_debug.py |
检索调试报告构建 |
ai_service/orchestrator/graph.py |
默认聊天运行时中的 RAG 集成 |
ai_service/orchestrator/react_agent.py |
实验 ReAct 运行时中的 RAG 集成 |
ai_service/utils/settings.py |
rag.top_k、rag.score_threshold、rerank、multi_query 等配置入口 |
第一段链路:知识如何变成可检索数据
1. 创建知识源并确定默认分块策略
知识源并不是“文件夹”概念,而是一个带默认 chunking 配置、挂载关系和后续文档集合的检索来源。
系统当前会在知识源层保存:
- 默认 chunking strategy
- 默认 chunking params
- 文档与 ingestion job
- 后续是否作为 Agent 的普通知识源或托管纠错来源参与检索
这里决定的是“文档如何被切开”,不是“查询如何被匹配”。
2. 上传文档
上传后,原始文件先落到对象存储,文档记录与后续状态落在 PostgreSQL。此时文档还不能被检索,只有等 ingestion 完成后,chunk 和向量才会进入检索链路。
3. 可选 Inspect
在真正 ingestion 前,可以先做 source 级或 document 级 inspect:
vector_health用于检查当前知识源在 Qdrant 中的 live 向量健康状态chunking_preview用于预演候选分块策略与参数,不写 live chunk 和向量
这一步的价值是先回答“是不是切块策略本身就有问题”,避免盲目重建。
4. IngestionService 串起解析、分块、向量化和写库
当前摄取主链路是:
- 从 MinIO 下载原文件
- Parser 解析出纯文本与结构信息
- 选择生效的 chunking strategy
- 生成
document_chunks - 调用 embedding service 批量生成向量
- 文本块写 PostgreSQL,向量写 Qdrant
- 更新文档与 ingestion job 状态
如果这一段失败,最常见的结果是:
- 文档存在,但没有 chunk
- chunk 存在,但没有向量
- PostgreSQL 与 Qdrant 的状态不一致
这些问题通常不该从聊天检索侧开始看,而应先回到 ingestion 和 inspect。
第二段链路:会话请求到来时如何检索
1. 编排器决定是否进入 RAG
聊天请求带着 agent_id 进入编排器后,运行时才会触发 RAG。没有 agent_id、或者当前路径不需要聊天生成时,RAG 阶段会被跳过。
默认聊天运行时和实验 ReAct 运行时都复用同一套 RAG 服务,只是 orchestration 方式不同。
2. 先解析 Agent 当前可见的知识范围
检索不会扫全库,而是先读取:
- Agent 当前挂载的 source
- 每个 source 的
priority - 每个 source 的
source_kind
所以“查不到”最先要排除的,往往不是向量模型,而是:
- source 没挂上
- source 被停用
- 命中的内容其实在别的 Agent 上
3. 主路径仍然是向量召回
当前实现的主路径仍是:
- 对 query 生成 embedding
- 在 Qdrant 中按 active
source_id过滤召回 - 合并多路向量结果
- 回表取回 chunk 文本
如果启用了 multi_query,系统会先生成多个 query 变体,再把多个召回结果按 chunk 合并。
4. 托管纠错来源会被额外照顾
如果某个 Agent 同时挂了普通知识源和 managed_correction 知识源,系统会额外对托管纠错来源做一次定向召回,再把结果并回主召回集合。
目的不是让纠错来源“天然得分更高”,而是避免它们在全局 top-k recall 阶段就被普通 source 淹掉。
最终排序时,系统还会优先考虑:
- 是否是
managed_correction agent_knowledge_links.priority- 向量分数或 rerank 分数
5. 关键词回退只是一层补位安全网
当前 RAG 不是纯 hybrid retrieval。它仍然是“向量优先”,关键词回退只在特定条件下补位:
- query 呈现明显关键词特征
- 向量结果没有补满
top_k - 命中的 lexical chunk 仍然属于当前 Agent 可见的 source
关键词回退的目标是解决这类场景:
hazardousddpcargo pulseIs De Well certified to transport hazardous materials?
也就是“词很短”或“问句更长,但核心仍是几个强关键词锚点”的查询。
6. rerank 发生在向量候选之后
如果启用了 rerank,当前实现会扩大向量候选召回,再对向量候选做重排。关键词回退本身不是 rerank 的输入主路径,而是最终补足剩余 slots 的机制。
这意味着:
- rerank 主要改善语义候选排序
- 它不能替代“短关键词根本召不回来”的问题
- 关键词回退也不会主动打乱已有 vector-first 结果
7. 最后才把 chunk 格式化成注入给模型的上下文
RAGRetrievalService 最终会把命中的 chunk 转成格式化上下文文本,再交给模型生成阶段使用。
对 chat Agent 来说,还有一个额外开关:
hide_rag_source_filename
它只影响给模型看的上下文头部,不影响后台 provenance、审计和 debug 里的真实文件名。
第三段链路:为什么 Semantic Splitter 配好了,查询仍然可能失败
这是当前最容易误解的一点。
Semantic Splitter 只决定 chunk 如何切,不决定 query 如何命中
像下面这类参数:
Buffer SizeBreakpoint Percentile Threshold
影响的是:
- chunk 的边界
- chunk 的平均长度
- 一段文本被切成几块
它们不直接决定:
- 查询是否一定能在向量阶段过阈值
- 单个关键词是否一定能召回
- 长问句里的专有词是否一定被 embedding 模型识别为高相似
为什么会出现“文档里明明有词,但还是查不到”
当前实现里,真正决定运行时命中的因素至少有四层:
- 文档是否已成功 ingestion 并写入向量库
- 该 source 是否已挂到当前 Agent
- 向量召回是否通过
rag.score_threshold - 在向量结果不足时,关键词回退是否被判定为 eligible
因此,Semantic Splitter 参数偏保守时,常见后果反而是 chunk 更大、语义更平均。对 hazardous 这类短 query 来说,embedding 相似度可能被更长 chunk 稀释,最后在阈值处被直接过滤掉。
当前系统如何缓解这类问题
当前真实缓解手段有三类:
- 调整 chunking 策略与参数,改变 chunk 颗粒度
- 调整运行时
rag.top_k与rag.score_threshold - 依赖关键词回退为明显关键词 query 补位
所以这类问题不应只盯着 Semantic Splitter 本身看,而应把“摄取结果 + source 挂载 + 检索阈值 + fallback 条件”一起看。
第四段链路:纠错如何重新进入 RAG
管理员在 Conversations 页面做回答纠错后,可以把纠错内容发布到知识库。
这条链路会:
- 生成或复用 Agent 对应的
managed_correction知识源 - 生成候选纠错文档
- 触发 ingestion
- 等 ingestion 成功后进入检索链路
从那之后,它会在后续检索中被优先考虑,并通过 source kind / priority 与普通知识源共同参与最终排序。
这也是为什么“模型答错了但后来被修正”,不一定要改系统提示词或重新训练模型,很多时候只要看 correction 是否成功发布并完成 ingestion。
排障入口
1. 先看哪一层出问题
| 现象 | 优先检查 |
|---|---|
| 文档刚上传后完全查不到 | ingestion job、document 状态、inspect |
| 某个 Agent 查不到,另一个 Agent 查得到 | 挂载关系与 source_id 可见范围 |
| 文档里明明有词,短 query 仍 miss | rag.score_threshold、关键词回退是否触发 |
| 管理员纠错发布后仍没生效 | correction publish 状态、managed correction ingestion 是否成功 |
| 模型引用内容不对,但检索其实命中了 | 看 final retrieval 和注入上下文,而不是只看 raw candidates |
2. rag-debug 用来回答什么问题
POST /sessions/{session_id}/turns/{turn_id}/rag-debug 主要回答:
- 当前 Agent 到底挂了哪些 source
- raw vector candidates 有没有命中
- final retrieval 里实际保留了哪些 chunk
- 这次是否启用了 keyword fallback
- expected text 对应的 chunk 是否进入 raw candidate 或 final retrieval
当前 Admin Conversations -> RAG 页签也已经把这些信息暴露出来,可以基于选中 Turn 直接重跑调试。
3. 当前最常改的配置入口
运行时默认值现在统一从 [rag] 读取:
[rag]
top_k = 5
score_threshold = 0.3
对应环境变量:
RAG_TOP_KRAG_SCORE_THRESHOLD
另外常见联动配置还有:
[multi_query][rerank]- 知识源默认 chunking strategy / params
- Agent 的
hide_rag_source_filename
建议阅读顺序
如果你是第一次接手这套 RAG,建议按这个顺序阅读:
- 本页,先建立全链路心智模型
- RAG 知识库管理,理解 Admin 操作与 ingestion
- RAGRetrievalService 概览,理解运行时检索细节
- 编排器,理解 RAG 在整轮聊天中的位置
- 端点概览,定位 debug / correction / knowledge source API