Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

财报 RAG 的口径陷阱:同名指标,不同意思

metadata 标了,年份硬过滤也做了,我以为这套财报 RAG 在数字上不会再翻低级车。直到一次对账:用户问「腾讯 2025 H1 利润多少」,系统答 1,320 亿;我拿去和财报原文核,核出来的是 1,150 亿【待核实:这两个数取自旧稿案例,发布前需对照腾讯真实披露核实,对不上就改标为示意数字】。

蹊跷的是两边都没抄错。系统引用的 chunk 来自 Non-GAAP 口径的披露,白纸黑字;我核的那个来自 IFRS 口径,也在同一份报告里。两个都是正确答案——放在一起,就成了错误答案。

这不是数据错,是业务规则

先把坑的性质定清楚。它不是解析错,也不是检索错:召回的每个 chunk,自身数字全都对,错在它们来自不同口径、互不可比。

这是 RAG 失败模式里最隐蔽的一类。解析错了,文本是乱的,一眼能看穿;时间混检了,年份写在 metadata 里,还有机会拦。口径混检不一样:不报错、不告警,两个 chunk 和 query 的相似度还都很高——在向量的眼里它们本来就「很像」,都是「利润」。LLM 看不出,用户更看不出。从系统返回到用户采信,中间没有一个环节亮红灯,直到有人拿两个数字对账。

这一篇就拆这件事:财报里同名的指标有多少种「不同意思」,以及我在 RAG 里怎么挡。

陷阱一:同一个「利润」,GAAP 和 Non-GAAP 两个数

开场那两个数差在哪?腾讯这类公司披露利润时同时给两个口径:按国际财务报告准则(IFRS)的期内盈利,和按非国际财务报告准则(Non-GAAP)的调整后盈利。Non-GAAP 剔除了股权激励费用、投资公允价值变动、无形资产摊销这类项目——剔除理由各不相同:股权激励和摊销是非现金的(注意股权激励每期都发生,说它“非经常“是站不住的),公允价值变动是波动大、管理层认为不代表核心经营。两个口径同时披露,两个都是真数字。

问题出在检索。用户问「利润」,系统从不同的 chunk 各召回一个口径,拼进同一个上下文给 LLM。LLM 没有被教过「这两个数不能同框」,它要么挑一个答,要么混着写。

再往下挖一层:就算口径定死,同一个指标还有多套名字。财报里常见的别名至少四组:

  • revenue / sales / turnover
  • operating profit / operating income
  • non-GAAP / adjusted
  • 本公司權益持有人應佔盈利 / net profit attributable to equity holders

(第一组特意说明:revenue 和 net revenue 不是别名——net revenue 是扣掉销售退回、折扣、折让之后的净额,会计上是另一个科目,混为一组会把两个真数字当一个。)

纯关键词匹配会漏——用户搜 “net profit”,匹配不到繁中那一行;纯语义匹配会混——“operating profit” 和 “operating income” 在向量空间里挨得很近,但在不同公司的报表里未必是同一件事。所以财报场景得做 metric alias normalization:入库或检索时把别名收敛到标准指标名上。不做这一步,跨公司、跨年份对比,对上的只是名字,不是口径——伪对齐。

陷阱二:同一个「收入」,统计窗口不一样长

中报里的「收入」是「截至 6 月 30 日止六个月」的半年切片,年报里是全年,季报里是单季。每个 chunk 的数字都对,但检索层要是把半年数和全年数一起召回给 LLM 比较,就能算出「半年收入大于全年收入」这种笑话。

这里有个容易踩空的机制。metadata 里的 period_type(H1/Q4/FY 这类报告期标签)标的是「这份报告对应哪个时点」,不是「这个数字统计了多长的窗口」。第 6 篇讲时间错配时做的年份硬过滤,解决的是「2020 年的数别混进 2025 年」;窗口长度是另一个维度,年份过滤管不着——同样是 2025 年,H1 的半年收入和 FY 的全年收入会一起放行。

同类的还有两个更浅但常踩的坑。一是季度数和累计数:中报经常同时给「第二季度单季」和「上半年累计」两组数,chunk 和 prompt 不标明,模型很容易把单季当累计。二是单位伪冲突:同一家公司正文写「亿元」、表格写「百万元」,同一个数写出来对不上,看起来像口径冲突,其实只是单位不同。单位归一化能解,但要反防一手:别让系统把纯单位差异误报成口径冲突,否则告警会被噪声淹没。

陷阱三:准则不同,附注里的定义还会变

第三个陷阱在跨市场披露时冒出来。同一家公司在港股、美股 ADR、A 股披露,遵循的准则不同:港股用香港财务报告准则(HKFRS),基本等同 IFRS;美股 ADR 可能按 IFRS 或 US GAAP;A 股是中国企业会计准则(CAS)。

准则差异不是抽象名词,它落在具体科目上:收入确认时点不同;资产的计量模型不同——IFRS 允许重估模型,US GAAP 只允许成本模型;研发支出的资本化条件不同,IFRS 比 US GAAP 宽松。用户问「总资产」,检索如果混合召回港股报告和美股报告的 chunk,两个「总资产」不是一回事。至于多地报告怎么分层存、怎么做查询路由,是第 11 篇多市场架构要展开的事,这里只立住一件:同名指标不同准则,召回结果不可比。

还有一层更隐蔽的:同一家公司自己也会改口径。收入确认口径变了、资产减值政策变了、合并范围变了——这些变更,主表只给变更后的结果,原因写在附注里。检索只命中主表数字、漏掉附注,答案就是「正确但过时」:数字本身没错,口径已经悄悄换了。

RAG 里的三层应对

应对分三层,按我的取舍顺序串:首选、兜底、体验。

首选:口径进 metadata,检索时硬过滤。 在 fiscal_year(财年)、period_type 之外加三个字段:accounting_standard(IFRS / US GAAP / CAS / Non-GAAP)、period_length(3M / 6M / 12M,统计窗口的实际长度)、metric_scope(Consolidated / Segment / Adjusted)。用户问「IFRS 口径」,检索直接滤掉 Non-GAAP 的 chunk,不把难题留给下游。配套动作是口径信息随 chunk 走:财报里常常是定义在上一段、数字在下一段,分片时把口径上下文切掉了,metadata 标得再全,chunk 自己也说不清是哪个口径——所以 overlap 不只是防断句,也是保口径。代价是标注成本:三个字段都要在入库时标出来,规则盖不住的部分得靠 LLM 标。

兜底:生成时强制暴露口径。 用户的 query 经常不说口径,硬过滤无从滤起,只能靠 prompt 注入规则让 LLM 把关。我在用的版本大意是:

以下 chunk 可能来自不同的会计口径(IFRS vs Non-GAAP)或不同统计窗口(半年 vs 全年)。回答时优先使用检索后 metadata 标注了 filter 约束的 chunk。如果你发现多个 chunk 的同类指标数值差异显著,先检查它们的口径标签是否一致。如果不一致,明确告知用户两个数字的口径差异,不要直接比较。

三条规则各防一样东西:「优先用带 filter 约束的 chunk」防过滤结果和兜底结果混用;「差异显著先核对标签」防把口径差当成业务变化;「不一致就明说」防开场那种 1,150 亿对 1,320 亿的假矛盾。代价也明显:这层全靠 LLM 自觉,上下文一长、chunk 一多,规则就会失效。所以它只配当兜底,不能当主力。

体验:默认值策略。 query 没指明口径时,默认给 IFRS/GAAP——这是审计报告的标准口径,最不容易踩雷;答案末尾固定附一行口径说明:以上数字基于 IFRS 口径,Non-GAAP 为 X,差异主要来自 Y。代价是默认值会掩盖用户真正想要的口径:习惯看 Non-GAAP 的人,拿到的永远是 IFRS,末尾那行他未必看。

为什么通用 benchmark 里不存在这个问题

最后说一个容易被高分掩盖的事实:这个问题在通用 benchmark 里根本不存在。

BEIR、MTEB、MS MARCO 这些主流评测——严格说三者性质不同:MS MARCO 是数据集,BEIR 和 MTEB 是建立在若干数据集之上的 benchmark,MTEB 评的也不止检索——它们的语料里都没有「同一指标在两种口径下数字不同」的样本。它们评的是语义匹配——query 和文档像不像;而口径不是语义问题,是业务规则。两个口径的 chunk 在语义上和 query 都高度相关,benchmark 会判它们都是好召回。

所以 benchmark 高分只证明语义层合格,证明不了财报场景可用。垂直场景真正难的从来不是语义,是数据里的隐含约束——口径、窗口、准则、市场——通用评估里不存在,生产环境里无处不在。自己的评估体系怎么搭是第 14 篇的事,这里只记住结论:别拿通用榜单的分,当垂直场景的合格证。

回过头看,这一篇讲的字段、规则、默认值,没有一样是检索技术本身。accounting_standard 是会计知识,period_length 是披露规则,prompt 里那条「不一致就明说」是财务对账的习惯。本质上是同一件事:把会计知识翻译成检索约束。领域知识对财报 RAG 不是锦上添花,是必须进入系统设计的那部分。

就算时间和口径都对齐了,检索分数本身还有一层错觉——相似度 0.9 的 chunk,可能一点用都没有。下一篇(第 8 篇)拆这个:相似度高,为什么不等于相关。