RAG 全链路全景:从知识入库到可信回答,一套 Agent 检索系统如何工作?
同一个问题,一套检索系统可能给出三份看似相关的基金资料:2021 年的旧招募说明书、2023 年的更新公告、2025 年的后续招募说明书。用户问的是:“2023 年到底改了什么?后来的材料能否解释当时的变更?”
把三份资料送进模型,答案不一定更好。最新的文件未必是历史事件的直接依据;命中“现金替代”几个字,不代表找到了适用于这次变更的条款;即使引用链接正确,模型也可能把“后来出现的字段”写成“当时修改的原因”。
这组真实研究材料来自 ETF Agent 的一次受限检索核对。关键矛盾并不是怎样多找一些 chunk,而是怎样让一份资料经过取得、索引、检索、阅读和交付之后,仍然准确回答“它能证明什么”。
这篇全景从读者实际得到的研究结果出发,把 RAG(检索增强生成)放回系统里看:一条知识构建链、一条在线查找链、一条证据消费与回答交付链,以及贯穿它们的评测与治理链。它们相互影响,却不应由一个“RAG Manager”代替全部决策。
本文既不是向量数据库教程,也不是 A20 检索模块的源码说明。我们关心的是完整系统怎样协作、哪里需要分工、什么时候不应该增加复杂度。下面使用的基金公告研究背景来自已核对的公开资料;示意消息、架构选择与未运行的分支会明确作为教学推演,而不是新的真实运行成绩。
一、先建立全景:一条问题链,四种不同的工作
读者看到的只有提问与回答,工程上却至少有四种性质不同的工作。
| 链路 | 从哪里开始 | 实际留下什么 | 最容易被误认成什么 |
|---|---|---|---|
| 知识构建 | 取得获准材料、确定用途与版本 | 可解释的原件、片段、索引和健康状态 | “文件存在”就等于“全文可查” |
| 在线检索 | 用户问题与当次授权范围 | 有序候选、失败/部分状态、来源定位 | 排名高就证明相关主张 |
| 证据消费和交付 | 工具实际结果进入模型请求 | 阅读范围、来源绑定、具体主张与可回查回答 | 工具执行成功就等于模型用对了 |
| 评测与治理 | 资料更新、失败观察或质量问题 | 版本调整、检索对照、披露决策和验证结论 | 一次 Recall 上升就等于研究质量提高 |
最重要的是,这不是四个必须串行执行的后台服务。知识建设往往发生在用户提问之前;评测可以离线进行;权限变化可能发生在模型已经阅读资料之后;有些提问根本不必启动检索。
按起点分组阅读关系与条件;完整图保留在下方。
- → 提取可定位片段并建立索引
- → 受限候选检索
- → 受限候选检索
- → 真实送达的片段与来源绑定
- → 模型核对问题并形成主张
- → 提交时仍有披露资格? (判断)
- 有 → 保存可核查的回答
- 无 → 收住受保护内容与说明缺口
- → 历史再次查看时复核资格
完整关系图 · 可放大查看细节
图 1|知识索引与用户研究在检索处相遇;当前披露资格不是旧检索成功的自然延续。
理解这张图之后,才能解释为什么“系统接了 RAG,用户却感觉不到”,或者“RAG 召回很好,答案仍然不可靠”。这两句话描述的可能是完全不同的失效位置。
二、知识进入系统之前,先回答“我们究竟拥有什么”
一份报告有三种身份
以 2023 年的基金公告为例,原始文件是实际取得的字节;研究资料资产记录它从哪里取得、属于哪个逻辑来源、哪一个版本、提取了哪些部分;知识索引则是为了查找而构造的有限表示。
文件名、网址和标题都不足以单独标识内容版本。原网址可能被替换;同名 PDF 可以修订;某一页的引用不能在重新打开时变成最新版本的另一段正文。
资料还要区分可用形态:原文、人工整理摘要、仅元数据。某个机构报告未获准长期保留正文时,可以只提供经过审查的简介与来源链接,而不能因为目录里有这本报告,就向模型承诺原文已经入库。原文、摘要和目录记录的证据力度不同。
对基金研究尤其如此:历史公告可以支持某个历史变更事实,但不能变成当前的 NAV、持仓或交易指令。Knowledge Source 是解释性材料,不是投资账本的另一份权威。
解析覆盖比 chunk 数量更重要
切块(chunking)是把较长材料分成可检索片段。短块能方便精确字段匹配,却可能丢掉段首的条件;大块保留上下文,可能带来噪声和上下文开销。PDF 表格还有列标题、脚注、物理页码与跨页范围的问题。
若一页表格只抽出了“费率 0.5%”,却遗漏它适用的份额类别,后面的向量召回越准确,模型越容易反复引用同一句不完整的话。提取覆盖不明确时,不能把尚未提取的部分当作不存在。
因此索引单元至少要能回到逻辑来源、文档版本、内容哈希、章节或页码、片段范围及文本表示类型。需要完整表格或脚注时,沿原位置继续阅读,而不是让检索片段代替整页。
更新是一个有条件的状态变化
2025 年的说明书不是 2023 年公告的就地覆盖。更新的合理过程是先检查来源变化与保留许可,再生成新版本的索引材料,确认可用后切换当前资格;旧版本仍按其合法保留和回读规则处理。
ETF Agent 的早期知识生命周期就区分了只读变化检查与需要审查的同步写入,避免每次检查都重建向量,也避免把来源同步误当作投资执行。个别来源失败,通常不应抹掉无关的有效材料。
这也解释一段真实诊断:2026 年 9 月一次本地检查发现,模型与数据库相关依赖可用,但知识索引中没有文档或 chunk。历史测试与代码存在,都没有使那次查询自动获得可用语料。这个记录只描述当时状态,不能推断现在的索引仍然为空。
**先检查语料和索引真实健康,再讨论检索算法。**空库时更换 BM25、精排模型或 MCP 协议,不能凭空补出资料。
三、在线查询不是“拿用户输入去搜全库”
回到用户的问题:“2023 年修改了哪些字段?”这句话至少含有三个会改变结果的限定:基金对象、历史日期、要找变更公告而不是任意说明书。
模型可以决定拆成“当年公告怎么写”“较早版本怎样描述”“后续文件能否作背景”等不同研究问题。这样的查询分解属于研究策略,不能绕过来源授权;必要时可以分别限定同一来源版本,也不必每次先交给另一个规划模型。
权限过滤为什么应在 Top-K 之前
设想一个索引同时存有公开公告和获准账户的私人研究笔记。先从全库取 Top-K、再剔除私人条目,不仅有泄露风险,还可能让真正获准的公告在候选阶段就被挤出结果。
因此硬约束要先于排序生效,包括账户作用域、reference/ personal 集合、来源用途、有效版本、当前文档状态和明确限定的范围。用户与模型可以进一步收窄,但不能凭一个搜索参数扩大 Host 已批准的集合。
A20 的现有检索合同允许领域偏好在候选不足时做一次有界扩展,但仅限同一个已授权集合和原有硬约束;用户明确限定 only 时不能悄悄放宽。候选数量够不够,不代表答案证据够不够。
词法、向量、融合和精排解决的是不同问题
对于“510500”“PCF”“申购现金替代溢价”这类精确表达,词法召回通常是值得保留的入口;对于“现金替代字段调整”“申赎清单版本更新”这类不同说法,向量检索可能补到候选。
两路分数不可直接等同。RRF(倒数排名融合)按候选在各通道的名次给出稳定合并,并按来源/版本/片段身份去重;它决定先看什么,不计算“主张为真”的概率。
在核对过的 ETF Agent 私有知识路径中,词法通道可在 PostgreSQL pg_search 扩展和 BM25 索引真实可用且配置允许时选择 BM25;否则保留 PostgreSQL 全文检索(FTS)。这两种状态不能只凭代码支持就写成某次查询实际启用了 BM25。
精排器(reranker)则进一步读取同一批已经获准的候选并重排。它适合修正“正确片段在候选里,却没有进入最终可用 Top-K”的问题;它不能召回从未进入候选池的材料,也不能新造来源或替材料授予权限。可选本地 TEI 精排不可用时,保留原 RRF 顺序是合理降级。
因此,混合检索不是永远都比简单全文搜索更好:它增加 embedding、索引一致性、精排调用、延迟与排障成本。是否值得,取决于真实任务显示缺口出现在哪个阶段。
四、最容易消失的不是 chunk,而是“模型实际看到它”的事实
检索返回了片段,用户仍可能拿到没有来源的答案。这个问题可能发生在检索之后。
一个 Agent 至少要经过四个不同的动作:Host 允许 Knowledge 工具、工具定义真正出现在该轮模型请求、模型发起调用并收到结果、后继模型输入真实承载了可用内容。缺少其中一步,不能直接说“模型拒绝检索”。
已有真实研究核对曾出现:Host 准备了知识授权,却没有在实际模型请求里暴露该工具。后续另一次 Run 才能从持久记录确认真实 Knowledge 调用与材料消费。这是工具表面与交付问题,不是换一个向量模型能修复的问题。
外置结果尤其容易制造“读过了”的假象
当工具结果过大时,Host 可能将内容外置,仅把引用或可继续搜索的定位符交给模型。模型之后发起字面搜索,得到“匹配位置列表完整”,也不等于读完了那些位置附近的原文。
检索命中、外置内容的定位命中、原文真正回读是三个不同级别的证据。只有本次真实交付并且仍获准使用的片段,才有资格在当前 Run 获得可核对的引用绑定。模型随手写出的某个来源 ID、旧 Run 的引用或尚未阅读的网页标题,都不应自动成为可信引用。
这并不要求每次都把整篇文章放进上下文。相反,应以最小足够片段为起点;当问题依赖标题、上一段限定、表格脚注或另一版本时,沿原件位置定向展开并保留新的实际阅读范围。
一条答案里,哪些部分真的能说?
在已有 510500 公告案例中,人工查看的 2023 年公告第一页能直接支持有关字段名称变化的描述;2025 年后续说明书虽然也出现相关字段,只能作为后续版本的背景线索,不能单独证实 2023 年变更的完整原因与范围。
把这次研究整理为一张教学用主张审阅表,比输出一个检索总分更直观:
| 准备写入答案的主张 | 材料与审阅结果 | 合适的输出 |
|---|---|---|
| 2023 年公告调整了现金替代相关字段名称,并增加相应折价字段 | 当年公告指定页对这项字段变化有直接支持 | 引用当年版本,限定为这次清单字段变更 |
| 后续说明书仍出现相关字段 | 后续版本可以提供背景与一致性线索 | 标明这是后续材料,不能倒置时间 |
| 因而可以确认变更的全部原因、市场影响和实时持仓 | 已查看片段不足以支持这些更强的推断 | 保留未证实的缺口,不给出肯定结论 |
表格表达的是怎样进行逐项主张核对,不是声称系统已对这几项自动完成独立语义判分,也不是新一次真实模型运行。真正的判断仍需核对原文、时间、范围和具体措辞。
五、模型读过之后,资料仍可能失去披露资格
用户可能隔几小时回来打开旧对话,也可能在回答生成期间撤销私人文档的访问权。此时至少有三种时间:原件在当时可读、答案提交时可披露、历史再次展示时可重显。
旧答案中的来源标记不能替代新的权限判断。2026 年 9 月的一次受控撤权复现曾暴露:历史回放路径已经能隐藏撤权资料,首次流式发送却仍可能放出受保护片段。只有把资格复核放到实际产生披露效果的提交环节,并确保并发撤权和提交有可解释的先后顺序,才能堵住这类窗口。
同样需要区别“当前不允许看”和“明确要求清理保留副本”。访问暂时失败、许可未知,不等于发生永久删除;明确的保留撤销又不能仅靠 UI 隐藏,让旧摘要在另一条历史路径重新出现。
这里不是让 RAG 接管 Publication 或历史。发布正文由原来的回答提交机制负责,历史读取由原来的会话交付机制负责;检索取得的旧片段并没有绕过它们的权利。已经发到浏览器的字节不能被软件事后收回,所以保护不能只发生在下一次回放。
对纯公开、不变更的静态资料问答,确实不需要为每一个问题都部署复杂撤权联动。但只要资料可修订、可撤销、分账户可见,这个判断就从“可选完善”变成了必须明确的披露合同。
六、四条链路怎样分工,而不是造一个包办一切的 RAG Manager?
从系统视角看,RAG 是多个既有能力的一次协作,不必成为一套并行的研究执行器。
| 责任位置 | 主要负责的事实 | 不该顺手决定的事情 |
|---|---|---|
| A17 资料资产与 A18/A19 读取 | 文件身份、版本、取得途径与实际页面/提取覆盖 | 某句结论是否正确 |
| 来源许可与 A04 Run 授权 | 原件/集合的许可和本次 Run 能力范围 | 模型需要哪个研究策略 |
| A20 知识检索 | 当前允许候选、排序、检索状态及来源定位 | 研究是否完成、是否可以交易 |
| A16 结果与引用 | 已交付结果、原始与派生关系、引用身份和回读 | 无依据地提升来源权威 |
| A03 Main 研究决策 | 是否补查、比较哪些版本、哪些主张需要支持 | 生成新的权限或事实 |
| A23 Publication 与 A24 History | 回答提交、交付和再次查看的受控结果 | 修改原始文件或用历史回放补做研究 |
这张表是责任地图,不是要求把每个编号建成一个新服务。有些实现处于同一进程,一次受控工具调用可穿过多处接口。
类似地,MCP 只是某种工具连接与调用方式。给 Retriever 包一层 MCP,既不会让空索引有内容,也不会让检索到的材料自动在模型输入中出现。问题在于取得、授权、调用、交付与来源的真实结果,而不是协议名字。
七、评测要沿“证据第一次在哪儿丢失”展开
如果用户最终没拿到可核查的答案,一个总分往往不够。排查最有效的起点是寻找第一处明确发生的证据缺失。
按起点分组阅读关系与条件;完整图保留在下方。
- → 索引有合格的原始片段? (判断)
- 没有 → 核对来源准入、解析与索引健康
- 有 → 候选里有关键片段? (判断)
- 没有 → 核对过滤、词法与向量召回
- 有 → 模型实际读到了所需正文? (判断)
- 没有 → 核对融合、截断与工具结果回读
- 有 → 具体主张获原文直接支持? (判断)
- 没有 → 继续阅读、收窄结论或标明未知
- 有 → 复核引用身份与当前披露资格
完整关系图 · 可放大查看细节
图 2|区分“原件缺失”“候选遗漏”“未送达”和“语义错误”,才能知道应当修哪一层。
评测也应采用对应的指标与分母:
- 索引与候选:获准原件是否可定位、可搜索,有标注的正例是否进入候选;Recall@K、Hit@K、MRR@K 只在相应判断集合和粒度下成立。
- 实际消费:工具是否可见并被调用、多少相关内容真实进入模型输入、外置结果是否回读到所需正文。
- 答案与引用:具体主张是否获得正确版本的直接支持、是否误用背景材料、是否存在编造或扩大结论。
- 用户任务与成本:问题是否完整回答、结果是否真正交付,以及实际延迟、调用和 Token 成本,最好使用同题、同资料时点的匹配对照。
已有 RQ-08 评测曾把三份来源版本固定到同一个候选范围,比较 306 个实际索引 chunk 的排序,并观察真实 Knowledge 调用。但这些 chunk 未经完整人工相关性标注,部分读取也只证明找到了位置,所以不能据此宣布真实 Recall 已提升,更不能宣布金融答案更准确。
这不是否定工程检索指标。它们非常适合告诉维护者算法在哪一阶段变好;只是这些指标与最终用户得到的可靠研究之间,还隔着模型真实消费和语义核验。
八、什么时候采用完整 RAG,什么时候应该主动保持简单?
一套成熟系统应能解释为什么没有启用某个机制。
| 任务条件 | 优先选择 | 什么时候再升级 |
|---|---|---|
| 几份短文档、来源与版本已知、问的是明确条款 | 直接读取原文或有限关键词定位 | 文档过长、反复查询或上下文装配开始丢信息 |
| 文件数量增加,但大量查询是代码、标题和精确字段 | 目录、权限过滤和词法检索 | 同义词/跨表述漏召回在真实题集中反复出现 |
| 词法难以覆盖不同说法且有受控语料 | 加向量召回与可复现的融合 | 已证实的语义召回缺口值得额外索引和算力 |
| 正确片段已经在候选中,却反复跌出最终 Top-K | 在同一授权候选上试验精排 | 有匹配样本证明质量收益超过延迟、成本与故障代价 |
| 文件可撤权、有多账户和历史回读 | 在原授权及披露路径上保持分阶段有效性 | 不因候选少、运行紧张或精排失败关闭硬约束 |
一份只有两页的公告,不需要先转成数百个向量再让模型猜摘要;同一份大规模多版本知识库,却可能非常值得付出索引、权限元数据、Embedding 和有限精排的维护成本。
什么时候退出?如果某个精排器没有稳定可观察的增量价值,就回到确定性的融合顺序;如果向量通道只是增加误命中和运维税,可以先保留词法检索;如果业务允许直接指定原件,优先读原件而不是强制“检索一次才算用 AI”。
但要分清可退的复杂度和不可退的硬约束:来源许可、账户隔离、版本与真实阅读范围、发布时的合法披露不应为了省 Token 被取消。
九、重新走完那份 2023 年公告研究
现在可以回到开头的同一个问题。
读者需要的是“2023 年到底改了什么”。资料侧保存了公告的原始身份和版本;检索侧在获准范围里定位当年公告,同时可能命中旧版和后续说明书;模型侧只应把真正读到的当年原文用于直接说明变更,把后续材料标成背景;答案提交与后来回读还要服从各自的披露资格。
这一次任务不需要“RAG 给所有材料打一个可信度”。它需要的是:每次必要交接都保留比上一层更多的真实可核查关系,而不是把上一层的成功状态扩大成最后的正确性。
从实现层面,我们已经看到知识导入、PostgreSQL/pgvector 与词法融合、受控 Native Knowledge 调用、Host 结果绑定和相应披露检查的机制;也看到空索引、工具未呈现、候选/模型消费不一致与撤权竞态等有范围的历史观察。它们并不构成完整线上金融研究质量的认证。
公开教学仓库 Open ETF Agent 目前只提供合成文档的受限词法检索、原页回读和来源关联报告等较小切面;不能把私有系统的全部 RAG 体系说成开源仓库已可直接复现。读者可以从固定的 v0.15.0 词法检索实现与运行说明开始,观察最小版“候选—原文—报告”之间的关系。
**RAG 的工程目标不是让所有问题都经过更多步骤,而是让真正需要检索的问题,在资料、权限、排序、阅读与交付之间不丢失事实。**对一次明确的用户问题,能准确指出“我找到哪份资料,读到了什么,能支持哪句话,还有什么不知道”,才是一套系统值得保留的复杂度。
延伸深挖:A20 知识检索:从资料入库到可信证据交付 · RAG 召回、BM25 与金融证据评测 · 文档撤权与历史回放 · A17 研究资料资产 · Agent 引用系统设计。这些文章分别深入检索、评测、撤权、文件身份和引用机制;本文重点是它们如何共同完成一次真实研究。