RAGSpine
核心概念

双通道

一条确定性的结构化/数值通道加一条叙事 RAG 通道,由同一个 agent 路由器统一:拆分复合问题并同时运行两条通道。

RAGSpine 用两种根本不同的机制回答两类根本不同的问题—— 由单个 agent 决定一个问题需要哪一条(或两条都要)。

  • "数字是多少?"结构化通道:事实表加 function-calling。确定性,绝不合成数值。
  • "为什么/发生了什么?"叙事 RAG 通道:对文档 chunk 做混合检索、可选的 listwise 重排,然后由 LLM 带引用地综合。

路由器位于 agent/agent.pyanswer_question);意图解析与 澄清门位于 agent/intent.py

两条通道绝不会模糊成一条"问模型"的路径。结构化通道是唯一 被允许产出数值事实的东西,而且它不信任模型文字——参见 防编造机制

Agent 如何路由

每个问题首先由一个零 LLM、配置驱动的规则解析器 (RuleIntentParser,可通过 IntentParser Protocol 替换)解析为四个意图槽位

属性

类型

路由由解析出的槽位与词面线索决定(parse_intent):

structured

数值意图——识别到了 metric,或出现"多少" / "what is" 这类数值线索。回答 就是那个数字,来自事实存储。

narrative

归因/监管/趋势/"为什么"意图。回答由检索到的 片段综合而成,每条都带引用。

composite

两者兼具——同时识别到指标叙事线索(如"收入为什么下降了?")。 Agent 先跑结构化路径,再追加一段归因分析。

在路由之前,澄清门clarify_scope)施加一种刻意的 不对称:

  • 缺失指标先追问(猜测指标会是实质性错误)。
  • 缺失实体/期间带明示假设作答(默认为本方 集团/最近的完整财年,暴露该假设,并提供一键收窄)。
  • 超出作用域/竞争对手实体 → 在任何通道运行之前拒答(参见 RESTRICTED 隔离与确定性 安全门)。

结构化通道:found / not_found / unrecognized 三态

结构化通道唯一产出事实的原语是 query_metric 工具 (agent/query_tools.py)。它的执行函数把每个参数经词表 归一化,然后查询 fact_metric 存储。它返回三种状态之一—— 绝不猜测:

精确值存在。返回数值、单位、全部受控维度代码, 以及完整谱系:

{
  "status": "found",
  "value": 1320,
  "unit": "USD_M",
  "metric_code": "REVENUE",
  "entity": "ACME_CN",
  "period_type": "FY",
  "period": "2024",
  "channel": "TOTAL",
  "source": { "doc": "ACME_FY2024_Review.pptx", "locator": "slide=2,table=1,row=REVENUE,col=FY2024" }
}

所有参数都归一化成功,但事实表中没有匹配行。不做 插值、不做推断——agent 会把它改写为诚实拒答。

{
  "status": "not_found",
  "normalized": { "metric_code": "REVENUE", "entity": "ACME_CN", "period": "2025", "channel": "TOTAL" }
}

某个参数无法归一化为受控代码(词表返回 None 而不是猜测)。会点名出问题的参数及其原始值。

{ "status": "unrecognized_param", "param": "entity", "raw": "some unknown company" }

词表归一化器(normalize_metric / normalize_entity / normalize_period)对一切 无法识别的输入返回 None。这个 None 会变成 unrecognized_param——绝不会 被强行折算成一个最接近的猜测代码。

叙事 RAG 通道

当路由为 narrative 时,agent 调用注入的 NarrativeRetriever_run_narrative)。默认链路(retrieval/)为:

混合检索——感知 CJK 的 Okapi BM25 + 可注入的向量通道(默认无 = 纯 BM25),用 Reciprocal Rank Fusion 融合(rrf_fusek=60),外加词表驱动的多查询 改写。

Listwise 重排——可选的 LLM listwise 评审(listwise_rerank)重排头部 候选;任何失败都会回退到 RRF 顺序。

带引用综合——LLM 只依据提供的片段作答,agent 会 强制补上模型漏引的来源文档名。

如果没有接入检索器,或检索一无所获,叙事 RAG 通道会 诚实降级("未检索到/尚未接入"),而不是发明一个回答。

复合路径:两条都跑、比较、合并

对复合问题,agent 先跑结构化路径,再跑 叙事路径并合并:

<structured answer, with the number(s) + lineage>

归因分析:
<narrative answer, synthesized from cited snippets>

两条通道的来源会拼接在一起。当结构化侧展开为 多个子任务时(用户显式列出的多个指标/实体/期间), agent 以确定性方式、不经 LLM 执行每个 query_metric 子任务 (_multi_subtask_answer),并且对恰好两个可比期间,它会 自己计算差值。

防编造机制是按路径施加的,而不是统一开关:结构化路径由事实值 确定性地合成回答,多子任务路径根本不调用 LLM, 叙事路径信任模型文字但强制引用。这种不对称是刻意的。

本页目录