Spreadsheet RAG Retrieval Briefing

从表格结构识别到 FRTR 召回:让大模型先找到证据,再回答问题

表格问答的核心不是把整份 Excel 塞进上下文,而是先识别结构、压缩表示、召回证据,再让模型在可信范围内回答。 这里从 SpreadsheetLLM 的两阶段问答、FRTR 的多粒度召回,以及当前项目的 region 识别和召回评测展开。

KL Demo regions
17
2 个 sheet,主 sheet 拆出 16 个 region
KL Demo chunks
538
row / column / window,含扩展 sheet chunk
Project FRTR-Bench chunks
217.2 万
当前项目切分入库结果,30 个 workbook
Hybrid range recall
52%
全局检索,排除图片问题,@50
Hybrid Workbook@3
85%
最新报告,文档维度兜底召回

1. 背景:表格 RAG 的难点不是“读文件”,而是“定位证据”

电子表格不是线性文本。它的语义来自二维布局、表头层级、合并单元格、公式、跨 sheet 引用和局部业务区域。

上下文不可控

真实 workbook 可能包含几十万行。整表序列化不仅 token 成本高,还会让模型在长上下文中丢失关键位置。

结构容易丢失

单元格值本身不够,必须知道它属于哪一列、哪一层表头、哪个 region,才能判断是否可回答。

答案需要可审计

产品侧不只要答案,还要知道来源 workbook、sheet、range,方便解释、复核和调试。

表格 RAG 的目标链路: 先找到正确 workbook,再找到正确 sheet 和 range;如果局部证据足够,就直接回答并输出 provenance; 如果局部证据不足,就扩大到 Workbook@3 的候选工作簿,在沙箱中执行表格分析后再回答。

1. 找文档

解决“数据在哪个 workbook”的问题。当前主报告关注 workbook_recall@3,作为 sandbox 分析入口。

2. 找证据

定位 sheet / region / range,减少进入上下文的噪声,保留可审计来源。

3. 做分析

对需要公式、聚合、跨 sheet 推导的问题,交给 agent 在沙箱内读取原表执行。

2. SpreadsheetLLM:先把表格压缩成 LLM 能理解的结构

来源:Microsoft Research / Microsoft Corporation。SpreadsheetLLM 的重点是 SheetCompressor:保留结构锚点,压缩重复值和格式相似区域,让单 sheet 可以进入上下文并完成问答。

ABCD
1月份区域销售额负责人
22024-01华东120,000Alice
32024-02华东135,000Alice
42024-03华北98,000Bob
52024-04华东142,000Alice
62024-05华北110,000Bob
72024-06华东158,000Alice
82024-07华东166,000Alice
92024-08华北104,000Bob
102024-09华东171,000Alice
112024-10华北126,000Bob
122024-11华东180,000Alice
132024-12华北132,000Bob
14合计1,642,000
STEP 1

结构锚点抽取

先找相邻行列在值、合并单元格、边框、颜色、字体上的差异,形成候选边界;再保留边界及其 k 邻域,生成 skeleton。

STEP 2

倒排索引压缩

对原表非空值做倒排:华东: B2:B3, B5, B7:B8, B10, B12。同值地址合并,空单元格不再反复序列化。

STEP 3

数据格式聚合

对原表数据区做格式聚合:A2:A13 = Date[yyyy-mm]C2:C14 = Currency/Number。保留类型语义。

STEP 4

两阶段问答

第一次调用 LLM 只返回相关坐标 range;第二次带上该 range 的完整数据再回答。

结构锚点:如何提取

1. 枚举行/列边界线:
   找相邻行列的差异
   value / merge / border / fill / font

2. 组合候选表格边界:
   top / bottom / left / right

3. 过滤不合理候选:
   太小、太稀疏、边缘不完整、
   缺少 header-like 行列

4. 处理重叠候选:
   用文本比例、日期/年份格式、
   header 位置判断哪个边界更可信

结构锚点:抽取后变成什么

原始区域:Sales!A1:D14
候选边界:top=1, bottom=14, left=A, right=D
展示用 k=2;论文实验中 k=4 可保留 97%+ 边界行列

保留边界邻域:
  rows 1:3, 12:14
  columns A:D

skeleton before remap:
  A1:D3 + A12:D14

skeleton after remap:
  A1:D6
  row1: 月份 | 区域 | 销售额 | 负责人
  row2: 2024-01 | 华东 | 120000 | Alice
  row3: 2024-02 | 华东 | 135000 | Alice
  row4: 2024-11 | 华东 | 180000 | Alice
  row5: 2024-12 | 华北 | 132000 | Bob
  row6: 合计 | | 1642000 |

坐标 remap 与回映射

remap 的本质是保存两张映射表:

compact row -> original row
  1 -> 1
  2 -> 2
  3 -> 3
  4 -> 12
  5 -> 13
  6 -> 14

compact col -> original col
  A -> A, B -> B, C -> C, D -> D

单元格回映射:
  skeleton C6 -> original C14

range 回映射不能直接拉直:
  skeleton A1:D6
  = original rows [1,2,3,12,13,14], cols A:D
  != original A1:D6

如果该 skeleton 来自候选表格边界,
则用候选 bbox 回到原始范围:
  skeleton A1:D6 -> Sales!A1:D14

压缩前:按网格展开

A2=2024-01, B2=华东, C2=120000, D2=Alice
A3=2024-02, B3=华东, C3=135000, D3=Alice
A4=2024-03, B4=华北, C4=98000, D4=Bob
...

压缩后:按值和格式聚合

结构骨架(layout skeleton):
Sales!A1:D14 -> skeleton A1:D6

全表倒排索引(原始坐标):
华东: B2:B3, B5, B7:B8, B10, B12
华北: B4, B6, B9, B11, B13
Alice: D2:D3, D5, D7:D8, D10, D12
Bob: D4, D6, D9, D11, D13
合计: A14

全表格式聚合(原始坐标):
月份列 A2:A13: Date[yyyy-mm]
销售额列 C2:C14: Currency/Number
问答过程不是一次完成: 用户问“2024 年 Q2 华东区域销售额是多少?”时,SpreadsheetLLM 风格流程会先让 LLM 基于压缩表格表示判断问题对应的坐标范围; 这个阶段的目标是定位相关原始表格范围,而不是直接在 skeleton 上完成计算。得到 range 后,系统再取出这部分完整数据,第二次调用 LLM 完成筛选和计算。 这说明 SpreadsheetLLM 适合解释“单 sheet 如何被压缩后问答”,但跨 sheet / 多 workbook 仍需要检索优先。

第一次调用:定位 range 的系统提示词

你是电子表格范围定位助手。
你只能基于给定的压缩表格表示判断问题相关的数据范围。
不要回答问题,不要计算最终数值。
请只返回 JSON:
{
  "sheet": "...",
  "ranges": ["A1:D14"],
  "reason": "为什么这些范围足以回答问题"
}

第一次调用:用户提示词示例

问题:2024 年 Q2 华东区域销售额是多少?

压缩表格表示:
候选区域 Sales!A1:D14
结构锚点 skeleton(坐标已重映射):
  A1:D1 = 月份 | 区域 | 销售额 | 负责人
  A2:D2 = 2024-01 | 华东 | 120000 | Alice
  A3:D3 = 2024-02 | 华东 | 135000 | Alice
  A4:D4 = 2024-11 | 华东 | 180000 | Alice
  A5:D5 = 2024-12 | 华北 | 132000 | Bob
  A6:D6 = 合计 | | 1642000 |
坐标映射:
  skeleton rows [1,2,3,4,5,6] -> original rows [1,2,3,12,13,14]
  skeleton cols A:D -> original cols A:D
  candidate bbox -> Sales!A1:D14
全表倒排索引(原始坐标):
  华东: B2:B3, B5, B7:B8, B10, B12
  华北: B4, B6, B9, B11, B13
  Alice: D2:D3, D5, D7:D8, D10, D12
  Bob: D4, D6, D9, D11, D13
  合计: A14
全表格式聚合(原始坐标):
  A2:A13 = Date[yyyy-mm]
  C2:C14 = Currency/Number

注意:skeleton 使用重映射坐标;
倒排索引和格式聚合使用原始坐标。

第一次调用:模型输出示例

{
  "sheet": "Sales",
  "ranges": ["A1:D14"],
  "reason": "问题需要月份、区域、销售额三列;这些字段都在 Sales!A1:D14。"
}

第二次调用:带完整 range 回答

系统提示词:
你是电子表格问答助手。
请只基于提供的完整数据范围回答问题。
如果需要计算,列出筛选条件、参与行和公式。
输出答案、计算过程、证据位置。

用户提示词:
问题:2024 年 Q2 华东区域销售额是多少?
数据范围:Sales!A1:D14
row,月份,区域,销售额,负责人
2,2024-01,华东,120000,Alice
3,2024-02,华东,135000,Alice
4,2024-03,华北,98000,Bob
5,2024-04,华东,142000,Alice
6,2024-05,华北,110000,Bob
7,2024-06,华东,158000,Alice
8,2024-07,华东,166000,Alice
9,2024-08,华北,104000,Bob
10,2024-09,华东,171000,Alice
11,2024-10,华北,126000,Bob
12,2024-11,华东,180000,Alice
13,2024-12,华北,132000,Bob
14,合计,,1642000,

第二次调用:最终输出示例

答案:2024 年 Q2 华东区域销售额为 300,000。

计算过程:
Q2 包含 2024-04、2024-05、2024-06。
其中华东匹配行是 A5:D5 和 A7:D7;
A6:D6 属于华北,不参与计算。
因此销售额 = C5 + C7 = 142,000 + 158,000 = 300,000。

证据位置:
Sales!A5:D5, Sales!A7:D7
边界: SpreadsheetLLM 的核心贡献是结构化压缩,不是大规模检索。它能让单张表更容易进入上下文; 但企业场景通常先要从很多 workbook 中找到证据,这正是 FRTR 召回层要解决的问题。

3. FRTR:先召回证据,再组合答案

来源:PwC U.S. Commercial Technology and Innovation Office / PricewaterhouseCoopers, U.S.。FRTR 把 workbook 拆成 row、column、window、image 等证据单元,查询时同时走 dense 和 BM25,再用 RRF 合并排序。

INDEX

多粒度 chunk

row 捕获记录,column 捕获字段,window 捕获局部二维关系,image 捕获图表/截图等视觉证据。

DENSE

语义召回

query 通过 embedding 模型转向量,适合语义改写和业务描述类问题。

BM25

关键词召回

基于 search_text 做全文检索,适合字段名、ID、公式引用等精确匹配。

RRF

融合排序

用 Reciprocal Rank Fusion 合并两路结果,降低单一路径漏召风险。

COMPOSE

带来源回答

LLM 基于带 provenance 的 top evidence 输出 reasoning / answer;来源由检索 chunk metadata 绑定。

FRTR 的检索单元

chunk 类型适合捕获的证据
row一条记录及其表头上下文,适合事实型问答。
column字段语义、枚举值、指标列,适合字段定位。
window局部二维关系,适合相邻单元格、表头与值的组合。
image图表、截图、票据等视觉证据,需要 OCR、图片 embedding 或多模态模型支持。

为什么要 hybrid RRF

  • BM25 擅长字段名、ID、公式引用、精确文本。
  • Dense 擅长语义改写、业务描述、自然语言问题。
  • RRF 把两路候选按排名融合,降低单一路径漏召。
  • 召回结果始终携带 workbook / sheet / range,方便审计和调试。
当前实现边界: FRTR 方案本身支持 row / column / window / image 类型切分和多模态检索;当前项目已实现 row / column / window, 并额外扩展 sheet chunk 为小表补充全局上下文;当前尚未实现 image chunk 的 OCR、image embedding 和多模态模型召回,因此评测会排除图片相关问题。

当前项目真实 case

workbook:frtr_0024_cybersecurity-incidents.xlsx

问题:How many incidents were handled by SOC-EMEA?

标注答案:XLOOKUP("SOC-EMEA", Team_Summary!A:A, Team_Summary!B:B)

标注来源:Team_Summary!B:B

下方关键证据只展示 window / row / column,省略当前项目扩展的 sheet chunk。

Hybrid top-1 先路由到正确 workbook 和明细窗口;最终答案行在 rank 4 命中 Team_Summary!A5:C5,其中 Incidents = 240。 该 case 的 first_workbook_rank = 1first_hit_rank = 4range_recall@7 = 1reference_full_coverage@50 = 1
1
Incidents / window / B947:E950
明细窗口,多行出现 Team: SOC-EMEA
raw
2
Incidents / window / B750:E753
继续补充 SOC-EMEA 原始样本
local
3
Incidents / window / B948:E951
与 rank 1 邻近,增强实体上下文
local
4
Team_Summary / row / A5:C5
最终答案行:SOC-EMEA 的 Incidents = 240
answer
5
Team_Summary / column / A1:A6
确认 SOC-EMEA 位于汇总表 Team 枚举列
field
7
Incidents / window / A947:D950
补充日期、严重程度、来源、团队四列上下文
context

FRTR Compose 输入

论文附录 C 的最终问答阶段会把用户问题、检索到的 chunks 和推理指令组合成结构化提示词。chunk 可来自列、行、窗口或嵌入图片;如果包含图片,会一并传给多模态模型。

Question:
How many incidents were handled by SOC-EMEA?

Retrieved chunks:
Chunk 1 (Score: 0.0302, Source: Hybrid)
Type: window | Sheet: Incidents
Range: B947:E950
Severity: Low | Source: Insider | Team: SOC-EMEA | MTTR_hours: 21
Severity: Medium | Source: Insider | Team: SOC-EMEA | MTTR_hours: 27.6

Chunk 4 (Score: 0.0163, Source: Hybrid)
Type: row | Sheet: Team_Summary
Range: A5:C5
Team: SOC-EMEA | Incidents: 240
[=COUNTIF(Incidents!D:D, A5)]

Chunk 5 (Score: 0.0163, Source: Hybrid)
Type: column | Sheet: Team_Summary
Range: A1:A6
Team A2: Team | A3: SOC-East | A4: SOC-West
A5: SOC-EMEA | A6: SOC-APAC

Instruction:
You may see columns, rows, cell windows,
and embedded images. A provided chunk is not
guaranteed to contain the answer.

For text/table chunks, return a cell reference
or Excel formula when appropriate.
For chart/image trend questions, answer in
natural language instead of a cell reference.

Analyze the relevant chunks, explain reasoning,
and return a JSON object with only:
reasoning, answer.

FRTR Compose 输出

论文要求模型输出机器可解析 JSON,只包含推理和答案。provenance 不由模型额外编造,而是由召回 chunk 的 workbook / sheet / range metadata 在系统侧保留。

{
  "reasoning": "SOC-EMEA appears in the Incidents windows. Team_Summary!A5:C5 gives Incidents = 240 with COUNTIF over Incidents!D:D.",
  "answer": "240"
}

4. 当前项目落地:把 Excel 变成可检索、可执行的证据层

当前项目不是只做论文复现,而是在 FRTR 的多粒度检索思路上补了工程化结构识别、表头语义、评测归因和后续 sandbox 分析需要的元数据。

索引前结构化

读取 Excel 后生成 manifest.jsonchunks.jsonl,每个 chunk 都绑定来源位置。

  • workbook / sheet / region
  • chunk_type / anchor_range
  • row / col 起止范围
  • header_paths / merged ranges
  • formula / neighbors

多粒度 chunk

基于 FRTR 的 row、column、window,同时额外扩展 sheet chunk,分别服务记录命中、字段命中、局部二维关系和小表全局上下文。

  • 大表:窗口和步长控制 chunk 数量。
  • 小表:项目额外生成 sheet chunk。
  • 评测:默认跳过 Questions / Readme,避免泄漏。

入库与召回

同一份索引同时服务 dense、BM25 和 hybrid 三种召回模式。

  • chunk_text:展示与调试。
  • header_text:字段语义。
  • search_text:BM25 输入。
  • embedding / sparse:向量和稀疏召回。

扩展实现:region 与表头启发式

region 识别

系统不把整个 sheet 当成一个区域,而是按非空单元格分布先识别局部业务区。

  • 先找所有有内容的行列。
  • 按空行间隔拆 row band。
  • 在 row band 内按列连续性和行重叠度识别 column group。
  • 对齐度高、只隔单个空行的小表会合并,避免把同一张表切碎。
  • 稠密数据表和说明区会拆开,避免说明文本污染表格 chunk。

表头启发式识别

表头不是简单取第一行,而是在每个 region 顶部独立判断结构性标题和多层表头。

  • 连续文本行可能是标题或表头。
  • 遇到第一个非纯文本数据行时停止。
  • 单元格很少的标题行作为 title row 保留。
  • 全字符串数据表会限制表头只取顶部结构行,避免误判数据。
  • 多层表头展开为 header_paths,进入 chunk text 与 BM25 字段。

说明区合并与标题锚点拆分

对稀疏、文本型、靠左锚定的说明区域,系统会识别为 note-like region 并必要时跨单个空行合并; 如果长说明区中出现“摘要 / 口径说明 / 风险提示”等短标题锚点,则按锚点拆分,避免一个说明 chunk 过长。

公式与局部上下文保留

项目保留公式文本,并尽量读取 spreadsheet 缓存值,形成“计算值 + 公式”的表达。 window chunk 还保留二维矩阵和上下左右邻接关系,为后续 rerank、二阶段召回和 sandbox 分析做准备。

评测也按这个结构设计: 不只看是否找到文档,还要看 sheet_recall@Krange_recall@Krange_containment@Kreference_full_coverage@K,从而区分“文档路由失败”“sheet 命中但 range 错误”和“证据完整覆盖”。

5. KL Demo:region 识别效果展示

使用 ~/Downloads/KL Demo.xlsx 生成的真实 preview。它能展示当前项目如何把一个复杂 sheet 拆成多个业务区域,并保留每个区域的表头和 chunk。

怪物产出对应表

维度 A1:AA200,识别出 16 个 region,生成 472 个 chunk。

玩法BUFF

维度 A1:H12,识别为 1 个整体 region,并生成 1 个项目扩展 sheet chunk。

总计

17 个 region,538 个 chunk:104 row、82 column、351 window、1 sheet(项目扩展)。

主 sheet 的 region 切分摘要

region_1
A1:J18
主表:星级、怪物、版本、武器类型,表头行 1
region_2
M1:R3
右侧小表,表头行 1
region_3
T1:AA12
另一块横向区域,表头行 1
region_9
A41:H49
多层表头,识别 header rows 41/42/43
region_16
A82:I105
后段业务表,独立 region
其他 region
11 个
说明区、小表和稀疏区域独立保留
KL Demo 怪物产出对应表 region 识别截图
KL Demo 主 sheet 的真实识别结果:浅黄色为 region 覆盖区域,浅绿色为表头行,右侧保留每个 region 的 bbox 与 header rows。 source: ~/Downloads/KL Demo.xlsx

表头路径示例

玩法BUFF sheet 中,系统识别两层表头,并把它们展开成可检索语义。

A: buff效果 > Buff类型
B: buff效果 > 事件名
C: buff效果 > 血量效果
F: buff效果 > 防御力效果(折算后)

chunk 文本示例

表头语义会进入 chunk text,让 dense 和 BM25 都能理解字段含义。

[KL Demo / 玩法BUFF]
Buff类型: 事件buff | 事件名: 消灭疯狼 | 攻击力效果: 0.15
Buff类型: 乱入buff | 事件名: 彗星 | 攻击力效果: 0.3 | 防御力效果(折算后): -0.1
KL Demo region preview 打开完整预览

6. 当前 FRTR 召回效果

当前展示最新报告 output/retrieval-eval-20260429-234114:FRTR-Bench 全局 workbook 检索,排除图片问题后 105 个问题,评估 dense / BM25 / hybrid 三种模式。

Workbook 路由能力看 @3

dense
82%
BM25
56%
hybrid
85%

指标:workbook_recall@3。上线兜底时更关注 top-3 工作簿是否包含正确文档,而不是 @50 的宽召回。

range 定位仍是核心瓶颈

dense
41%
BM25
31%
hybrid
52%

指标:range_recall@50。工作簿能找到,但 sheet 内的证据范围还需要 rerank 和二阶段召回。

模式 / 指标 workbook_recall@3 range_recall@1 range_recall@3 range_recall@50 full_coverage@50 p50 latency
dense82%32%35%41%36%26 ms
BM2556%11%20%31%25%23 ms
hybrid85%25%32%52%46%28 ms

Hybrid 最稳

range_recall@50 = 52%,高于 dense 的 41% 和 BM25 的 31%。

Workbook@3 可做兜底

最新报告中,hybrid workbook_recall@3 = 85%。这说明 top-3 工作簿可作为 agent 二阶段分析的候选文档池,但仍需要继续提升路由精度。

Image chunk 暂未实现

FRTR 支持 image 类型切分,但当前项目尚未接 OCR / image embedding / 多模态模型,因此排除 54 个图片相关问题。

如何解读 Workbook@3: range_recall@50 衡量 chunk 是否直接覆盖 gold range; workbook_recall@3 衡量 top-3 文档是否包含正确 workbook。上线后它的价值不是直接回答, 而是在 chunk 证据不足时,把正确工作簿召回给 agent,在沙箱里继续读取、计算和验证。
FRTR retrieval evaluation report 打开完整报告

7. 上线后的完整表格问答流程

召回层只负责找到候选证据。真正上线时,需要 agent 判断证据是否足够;如果不足,就用 Workbook@3 找回候选工作簿,并在沙箱内执行表格分析。

01

问题理解

识别用户意图、指标、时间、实体、是否需要计算或跨 sheet 推导。

02

chunk 召回

用 hybrid 检索 row / column / window,以及项目扩展 sheet chunk,返回 sheet、range 和 provenance。

03

agent 判断

检查 top chunks 是否覆盖问题所需字段、筛选条件和计算来源。

04

证据足够

直接基于 chunk 生成答案,并输出 workbook / sheet / range 来源。

05

证据不足

取这些 chunk 所属文档,并追加 Workbook@3 召回到的候选 workbook。

06

沙箱分析

在隔离环境中读取原 Excel,执行筛选、聚合、公式校验或跨 sheet 分析,再生成最终答案。

chunk 证据足够时
适合单点查询、目标 range 已覆盖、公式值已经在 chunk 中、top evidence 可直接解释的问题。
chunk 证据不足时
适合需要完整 sheet、跨 sheet 计算、动态筛选、聚合统计、公式重算或验证上下文的问题。
Workbook@3 的作用
不是替代 range 召回,而是把最可能相关的 3 个 workbook 交给 agent 兜底,避免只凭局部 chunk 硬答。
产品输出
答案、计算过程摘要、引用的 workbook / sheet / range,以及是否经过 sandbox 分析。

8. 结论与下一步

当前方向已经成立:先结构化切分和索引,再用 hybrid 召回证据。但产品化前,还要把“找到工作簿”推进到“找准可回答证据”。

查询改写

先把用户问题改写成字段名、同义词、时间范围和计算意图更明确的检索查询,提高 Workbook@3 和 range 命中。

先做 rerank

用 question + chunk_text + header_paths 对候选证据重排,优先提升 range 定位。

打通沙箱分析

当 chunk 证据不足时,用 Workbook@3 找回候选工作簿,并和沙箱内的表格读取、筛选、聚合、公式执行能力打通。

补多模态链路

为图片、图表、票据补 OCR / image embedding,覆盖被排除的图片题。

SpreadsheetLLM 解决“表格如何被 LLM 看懂”,FRTR 解决“真实大表格如何先找到证据”。 当前项目把这两条线落到了可观察、可评测、可继续产品化的召回层;上线形态应进一步补查询改写,接入 agent 判断,并打通 sandbox 表格分析能力, 让系统在局部证据足够时快速回答,在证据不足时回到原始工作簿做可靠分析。