Spreadsheet RAG Retrieval Briefing
表格问答的核心不是把整份 Excel 塞进上下文,而是先识别结构、压缩表示、召回证据,再让模型在可信范围内回答。 这里从 SpreadsheetLLM 的两阶段问答、FRTR 的多粒度召回,以及当前项目的 region 识别和召回评测展开。
电子表格不是线性文本。它的语义来自二维布局、表头层级、合并单元格、公式、跨 sheet 引用和局部业务区域。
真实 workbook 可能包含几十万行。整表序列化不仅 token 成本高,还会让模型在长上下文中丢失关键位置。
单元格值本身不够,必须知道它属于哪一列、哪一层表头、哪个 region,才能判断是否可回答。
产品侧不只要答案,还要知道来源 workbook、sheet、range,方便解释、复核和调试。
解决“数据在哪个 workbook”的问题。当前主报告关注 workbook_recall@3,作为 sandbox 分析入口。
定位 sheet / region / range,减少进入上下文的噪声,保留可审计来源。
对需要公式、聚合、跨 sheet 推导的问题,交给 agent 在沙箱内读取原表执行。
来源:Microsoft Research / Microsoft Corporation。SpreadsheetLLM 的重点是 SheetCompressor:保留结构锚点,压缩重复值和格式相似区域,让单 sheet 可以进入上下文并完成问答。
| A | B | C | D | |
|---|---|---|---|---|
| 1 | 月份 | 区域 | 销售额 | 负责人 |
| 2 | 2024-01 | 华东 | 120,000 | Alice |
| 3 | 2024-02 | 华东 | 135,000 | Alice |
| 4 | 2024-03 | 华北 | 98,000 | Bob |
| 5 | 2024-04 | 华东 | 142,000 | Alice |
| 6 | 2024-05 | 华北 | 110,000 | Bob |
| 7 | 2024-06 | 华东 | 158,000 | Alice |
| 8 | 2024-07 | 华东 | 166,000 | Alice |
| 9 | 2024-08 | 华北 | 104,000 | Bob |
| 10 | 2024-09 | 华东 | 171,000 | Alice |
| 11 | 2024-10 | 华北 | 126,000 | Bob |
| 12 | 2024-11 | 华东 | 180,000 | Alice |
| 13 | 2024-12 | 华北 | 132,000 | Bob |
| 14 | 合计 | 1,642,000 |
先找相邻行列在值、合并单元格、边框、颜色、字体上的差异,形成候选边界;再保留边界及其 k 邻域,生成 skeleton。
对原表非空值做倒排:华东: B2:B3, B5, B7:B8, B10, B12。同值地址合并,空单元格不再反复序列化。
对原表数据区做格式聚合:A2:A13 = Date[yyyy-mm],C2:C14 = Currency/Number。保留类型语义。
第一次调用 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 的本质是保存两张映射表: 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
你是电子表格范围定位助手。
你只能基于给定的压缩表格表示判断问题相关的数据范围。
不要回答问题,不要计算最终数值。
请只返回 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。"
}
系统提示词: 你是电子表格问答助手。 请只基于提供的完整数据范围回答问题。 如果需要计算,列出筛选条件、参与行和公式。 输出答案、计算过程、证据位置。 用户提示词: 问题: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
来源:PwC U.S. Commercial Technology and Innovation Office / PricewaterhouseCoopers, U.S.。FRTR 把 workbook 拆成 row、column、window、image 等证据单元,查询时同时走 dense 和 BM25,再用 RRF 合并排序。
row 捕获记录,column 捕获字段,window 捕获局部二维关系,image 捕获图表/截图等视觉证据。
query 通过 embedding 模型转向量,适合语义改写和业务描述类问题。
基于 search_text 做全文检索,适合字段名、ID、公式引用等精确匹配。
用 Reciprocal Rank Fusion 合并两路结果,降低单一路径漏召风险。
LLM 基于带 provenance 的 top evidence 输出 reasoning / answer;来源由检索 chunk metadata 绑定。
| chunk 类型 | 适合捕获的证据 |
|---|---|
| row | 一条记录及其表头上下文,适合事实型问答。 |
| column | 字段语义、枚举值、指标列,适合字段定位。 |
| window | 局部二维关系,适合相邻单元格、表头与值的组合。 |
| image | 图表、截图、票据等视觉证据,需要 OCR、图片 embedding 或多模态模型支持。 |
sheet chunk 为小表补充全局上下文;当前尚未实现 image chunk 的 OCR、image embedding 和多模态模型召回,因此评测会排除图片相关问题。
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。
Team_Summary!A5:C5,其中 Incidents = 240。
该 case 的 first_workbook_rank = 1、first_hit_rank = 4、
range_recall@7 = 1、reference_full_coverage@50 = 1。
论文附录 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.
论文要求模型输出机器可解析 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"
}
当前项目不是只做论文复现,而是在 FRTR 的多粒度检索思路上补了工程化结构识别、表头语义、评测归因和后续 sandbox 分析需要的元数据。
读取 Excel 后生成 manifest.json 和 chunks.jsonl,每个 chunk 都绑定来源位置。
基于 FRTR 的 row、column、window,同时额外扩展 sheet chunk,分别服务记录命中、字段命中、局部二维关系和小表全局上下文。
同一份索引同时服务 dense、BM25 和 hybrid 三种召回模式。
chunk_text:展示与调试。header_text:字段语义。search_text:BM25 输入。embedding / sparse:向量和稀疏召回。系统不把整个 sheet 当成一个区域,而是按非空单元格分布先识别局部业务区。
表头不是简单取第一行,而是在每个 region 顶部独立判断结构性标题和多层表头。
header_paths,进入 chunk text 与 BM25 字段。对稀疏、文本型、靠左锚定的说明区域,系统会识别为 note-like region 并必要时跨单个空行合并; 如果长说明区中出现“摘要 / 口径说明 / 风险提示”等短标题锚点,则按锚点拆分,避免一个说明 chunk 过长。
项目保留公式文本,并尽量读取 spreadsheet 缓存值,形成“计算值 + 公式”的表达。 window chunk 还保留二维矩阵和上下左右邻接关系,为后续 rerank、二阶段召回和 sandbox 分析做准备。
sheet_recall@K、range_recall@K、
range_containment@K 和 reference_full_coverage@K,从而区分“文档路由失败”“sheet 命中但 range 错误”和“证据完整覆盖”。
使用 ~/Downloads/KL Demo.xlsx 生成的真实 preview。它能展示当前项目如何把一个复杂 sheet 拆成多个业务区域,并保留每个区域的表头和 chunk。
维度 A1:AA200,识别出 16 个 region,生成 472 个 chunk。
维度 A1:H12,识别为 1 个整体 region,并生成 1 个项目扩展 sheet chunk。
17 个 region,538 个 chunk:104 row、82 column、351 window、1 sheet(项目扩展)。
在 玩法BUFF sheet 中,系统识别两层表头,并把它们展开成可检索语义。
A: buff效果 > Buff类型 B: buff效果 > 事件名 C: buff效果 > 血量效果 F: buff效果 > 防御力效果(折算后)
表头语义会进入 chunk text,让 dense 和 BM25 都能理解字段含义。
[KL Demo / 玩法BUFF] Buff类型: 事件buff | 事件名: 消灭疯狼 | 攻击力效果: 0.15 Buff类型: 乱入buff | 事件名: 彗星 | 攻击力效果: 0.3 | 防御力效果(折算后): -0.1
当前展示最新报告 output/retrieval-eval-20260429-234114:FRTR-Bench 全局 workbook 检索,排除图片问题后 105 个问题,评估 dense / BM25 / hybrid 三种模式。
指标:workbook_recall@3。上线兜底时更关注 top-3 工作簿是否包含正确文档,而不是 @50 的宽召回。
指标:range_recall@50。工作簿能找到,但 sheet 内的证据范围还需要 rerank 和二阶段召回。
| 模式 / 指标 | workbook_recall@3 | range_recall@1 | range_recall@3 | range_recall@50 | full_coverage@50 | p50 latency |
|---|---|---|---|---|---|---|
| dense | 82% | 32% | 35% | 41% | 36% | 26 ms |
| BM25 | 56% | 11% | 20% | 31% | 25% | 23 ms |
| hybrid | 85% | 25% | 32% | 52% | 46% | 28 ms |
range_recall@50 = 52%,高于 dense 的 41% 和 BM25 的 31%。
最新报告中,hybrid workbook_recall@3 = 85%。这说明 top-3 工作簿可作为 agent 二阶段分析的候选文档池,但仍需要继续提升路由精度。
FRTR 支持 image 类型切分,但当前项目尚未接 OCR / image embedding / 多模态模型,因此排除 54 个图片相关问题。
range_recall@50 衡量 chunk 是否直接覆盖 gold range;
workbook_recall@3 衡量 top-3 文档是否包含正确 workbook。上线后它的价值不是直接回答,
而是在 chunk 证据不足时,把正确工作簿召回给 agent,在沙箱里继续读取、计算和验证。
召回层只负责找到候选证据。真正上线时,需要 agent 判断证据是否足够;如果不足,就用 Workbook@3 找回候选工作簿,并在沙箱内执行表格分析。
识别用户意图、指标、时间、实体、是否需要计算或跨 sheet 推导。
用 hybrid 检索 row / column / window,以及项目扩展 sheet chunk,返回 sheet、range 和 provenance。
检查 top chunks 是否覆盖问题所需字段、筛选条件和计算来源。
直接基于 chunk 生成答案,并输出 workbook / sheet / range 来源。
取这些 chunk 所属文档,并追加 Workbook@3 召回到的候选 workbook。
在隔离环境中读取原 Excel,执行筛选、聚合、公式校验或跨 sheet 分析,再生成最终答案。
当前方向已经成立:先结构化切分和索引,再用 hybrid 召回证据。但产品化前,还要把“找到工作簿”推进到“找准可回答证据”。
先把用户问题改写成字段名、同义词、时间范围和计算意图更明确的检索查询,提高 Workbook@3 和 range 命中。
用 question + chunk_text + header_paths 对候选证据重排,优先提升 range 定位。
当 chunk 证据不足时,用 Workbook@3 找回候选工作簿,并和沙箱内的表格读取、筛选、聚合、公式执行能力打通。
为图片、图表、票据补 OCR / image embedding,覆盖被排除的图片题。