AFAC2026 赛题四金融长文本 Agent竞赛学习笔记:关联技术(二)

前接:赛题全景与难点,本篇主要介绍这个比赛可能涉及到的一些技术点


AFAC2026 赛题四金融长文本 Agent竞赛学习笔记(一)

AFAC2026 赛题四金融长文本 Agent竞赛学习笔记(二)

AFAC2026 赛题四金融长文本 Agent竞赛学习笔记:参赛方案解析(三)


4 关联技术

4.1 PDF 解析方案详解

来自AFAC2026-advance baseline-tutorial.md的详解方案

RAG 系统的质量上限由两个因素决定:检索策略和文档解析质量。如果第一步就把表格变成了乱码、公式丢失了、段落顺序乱了,后面所有环节都在错误的文本上工作。这种错误无法通过优化检索或 prompt 来补救 。

保险条款和财报类 PDF 有几个让解析器头疼的特点:

  • 复杂表格(保费表、现金价值表、赔付比例表,行列密集且嵌套层级深)
  • 数学公式(精算公式、财务比率公式,上下标和分式结构容易丢失)
  • 双栏/多栏布局(部分研报和合同使用多栏排版,阅读顺序容易错)
  • 页眉页脚混入正文、扫描件 vs 电子件(部分文档是扫描图片需要 OCR,部分是原生 PDF 可直接提取文字)。
4.1.1 轻量级:PyMuPDF4LLM(Baseline 方案)

PyMuPDF4LLM 是基于 PyMuPDF 的轻量封装,专门为 LLM 场景设计。核心能力是把 PDF 直接转为 Markdown 文本,保留标题层级,提取表格为 Markdown table 格式。

优势: 纯 Python 库,安装简单,不需要 GPU,速度快(50 页 PDF 约 5-10 秒),对原生 PDF 文字提取质量尚可。

局限: 不包含 OCR 能力(扫描件无法处理)、表格提取基于规则(复杂嵌套表格容易错位)、公式识别能力弱、双栏文档阅读顺序可能出错、字号推断标题层级不总是准确。

为什么 baseline 选它: 赛方评测环境不提供 GPU,PyMuPDF4LLM 是当时能在 CPU 上快速跑通的方案。17% 的准确率中,有一部分损失确实来自 PDF 解析不够好,但 baseline 的目标是先把端到端流程跑通 。

4.1.2 中量级:Marker

Marker(VikParuchuri, 2024, GitHub: VikParuchuri/marker)是一个基于 pipeline 架构的 PDF 转 Markdown 工具。流水线是:Surya 布局检测 → Surya OCR(可选)→ 文本提取 → Markdown 输出 。

核心能力: 布局检测使用 Surya 模型,能识别标题、正文、表格、公式、图片、页眉页脚等区域;内置 OCR 能力,支持 90+ 种语言;对扫描件和原生 PDF 都能处理;自动过滤页眉页脚。

局限: 依赖 PyTorch 模型,需要 4-8GB 显存(GPU 模式);CPU 模式下速度较慢(50 页 PDF 可能需要 5-15 分钟);对极端复杂的表格仍有遗漏;公式识别不支持 LaTeX 输出。

对本赛题的适用性: 如果赛方提供 GPU 环境,Marker 是一个性价比不错的选择。CPU 模式下虽然慢,但解析在预处理阶段完成,不占用提交时的 Token 预算,时间成本可以接受 。

4.1.3 重量级:MinerU

MinerU(上海 AI Lab / OpenDataLab, 2024 年发布, GitHub: opendatalab/MinerU)是目前开源社区最受关注的 PDF 解析工具之一,专为 LLM / RAG / Agent 场景设计

核心能力: 完整的版面分析管线(布局检测 → 阅读顺序恢复 → 元素识别 → 结构化输出);表格和公式提取质量高,公式自动转为 LaTeX;支持 109 种 OCR 语言;输出 Markdown / JSON / HTML / LaTeX 多种格式;内置 MCP Server 支持。

优势: 公式转 LaTeX 是本赛题的关键优势------保险条款和财报中的数学公式能完整保留;阅读顺序恢复能力强,双栏/多栏文档不乱序;对中文文档优化好;OmniDocBench 评测中英文文档解析表现领先。

局限: GPU 依赖(需要 CUDA 支持的 GPU,推荐 8GB+ 显存),纯 CPU 模式可以运行但非常慢;安装复杂(首次配置可能需要 30 分钟以上);内存占用大(处理高分辨率文档时可能占用 10GB+ 内存);单页处理时间 GPU 下约 3-8 秒/页,CPU 下可能 30-60 秒/页。

对本赛题的适用性: 如果赛方允许使用 GPU 环境,MinerU 是目前的最佳选择。公式 LaTeX 化、表格结构化、阅读顺序恢复这三项能力直接解决了本赛题 PDF 解析的核心痛点。即使赛方只给 CPU 环境,MinerU 也可以跑(只是慢),预处理阶段的时间成本通常可以接受。

4.1.4 视觉语言模型级:olmOCR

olmOCR(Allen AI, 2025 年 2 月发布, arXiv:2502.18443)代表了 PDF 解析的新方向:不用传统的 OCR + 版面分析流水线,而是用一个精调的 7B 视觉语言模型直接把 PDF 页面转成结构化的纯文本 。

核心能力: 基于 7B VLM,精调在 260,000 页多样化 PDF 上;支持表格、列表、公式、手写文字的提取;输出线性化的纯文本,保持自然阅读顺序;在 olmOCR-Bench 上表现优于 GPT-4o、Gemini Flash 2 和 Qwen-2.5-VL。

优势: 不需要复杂的版面分析管线,一个模型搞定所有页面类型;对扫描件、手写文档、低质量 PDF 的处理能力远超传统 OCR 方案;开源的 7B 模型可以在本地部署。

局限: 需要 GPU(7B VLM 推理),CPU 不可用;中文文档的处理质量未知(训练数据以英文为主);输出格式为纯文本而非 Markdown,丢失了部分结构信息;表格和公式以文本形式呈现,不如 LaTeX 精确。

对本赛题的适用性: 如果赛方提供 GPU 环境且中文处理质量过关,olmOCR 是一个值得尝试的方案。但目前中文支持情况不明朗,建议等社区有中文评测结果后再决定 。

4.1.5 本赛题的 PDF 解析选型建议

根据 AFAC2026-advance baseline-tutorial.md的表述,分三种情况:

环境 推荐方案 理由
纯 CPU PyMuPDF4LLM + 预处理优化 无 GPU 时的唯一选择。可以在预处理阶段做更多工作来补偿解析质量(如人工修正表格、补充公式描述)
GPU(8GB+) MinerU 当前开源方案中综合能力最强,公式/表格/阅读顺序三项核心能力突出
GPU(16GB+) MinerU + olmOCR 互补 MinerU 处理结构化文档,olmOCR 处理扫描件和低质量页面,两路互补

即使赛方最终只给 CPU 环境,学习 MinerU 和 olmOCR 也是有价值的。了解更好的解析方案能帮助理解当前 baseline 的瓶颈在哪里(哪些错误是 PDF 解析导致的,哪些是检索策略导致的,哪些是 prompt 设计导致的)。定位清楚瓶颈,才能精准优化 。

4.1.6 预处理阶段可以做的工作

无论用哪个解析工具,以下预处理手段对提升文本质量有帮助:

  1. 页眉页脚过滤:用正则匹配重复出现的页码、章节标题、公司名称等,统一去除
  2. 表格后处理:对解析出的表格做格式校验(行列数一致、数值列对齐),异常时回退到手动提取
  3. 公式补标注:在公式附近插入描述性文本(如"该公式表示:现金价值 = 累计保费 × 75%"),帮助 LLM 理解公式含义
  4. 段落合并:同一段落的文本可能被解析成多行,按标点和语义做合并
  5. 文档结构标注:为每个段落标注所属章节路径(如"第二章 > 第三节 > 现金价值计算"),增强检索时的上下文信息

"文档解析是'一次性投入',不消耗比赛在线 Token。这一步做不好,后续所有环节都在吃哑巴亏。"

4.2 RAG 技术架构

来自选手 AFAC2026-advance baseline-tutorial.md的详解

Baseline 的硬截断本质上跳过了检索,直接把文档前半部分塞给模型。要突破 17% 的准确率天花板,第一步就是引入检索模块。但检索不是简单加一层 BM25 就完事------分块、召回、排序、组装每个环节都有坑。

4.2.1 分块策略

文档切片是 RAG 的地基。切得不好,后面的检索和生成都受影响。

固定大小分块:按固定字符数切分,实现简单但容易切断语义。比如"因意外伤害发生上述情形的,无等待期"如果被切成两块,检索可能只命中前半句,模型看到的就是残缺的。

滑动窗口分块:相邻块之间有 10%-20% 重叠,减少边界信息丢失。适合保险条款这种前后文紧密关联的文档。重叠太多会导致检索结果重复,占用 Token 预算。

语义分块:按段落、章节等自然边界切分,保持语义完整。Markdown 文档天然适合按标题层级切分。缺点是块大小不均匀。

多粒度分块(Small-to-Big):把文档切成两层------子块(200-500 token)用于检索,父块(800-2000 token)包含完整上下文。检索命中子块后,把对应的父块一并取出送给 LLM。好处是"检索用小块(精确)、回答用大块(完整)",实验表明准确率比单一大块高 10%-15%。

推荐起步方案:按 Markdown 标题切分 + 滑动窗口,块大小 800-1200 token,重叠 15%。有精力的话升级到多粒度分块。

4.2.2 混合检索

单一检索策略各有盲区:BM25 对精确匹配敏感(数字、条款编号),但无法理解"退保费用"和"退保手续费"是同一个东西;向量检索能捕捉语义相似性,但对数字和年份不够敏感。

混合检索 = BM25 + 向量检索,两路同时召回,结果融合后一起送进 LLM。常用的融合方式是 RRF(Reciprocal Rank Fusion):按每路结果的排名位置加权融合,不依赖绝对分数。

⚠️ 赛题禁止使用 embedding 模型,所以向量检索在正式提交中无法使用。以下内容帮助理解 RAG 完整技术栈,实际参赛时只能依赖 BM25 + 关键词的稀疏检索路线。

4.2.3 前沿 RAG 范式

标准 RAG 有三个根本缺陷:

  • 扁平化(无法理解跨块的语义结构)
  • 局部性(擅长回答"这段话说了什么",回答不了"这些文档整体讲了什么")
  • 无反思(检索到什么就用什么,不评估质量)。下面的范式各自针对其中一个或多个缺陷 。
GraphRAG:用知识图谱做检索

GraphRAG(Microsoft, 2024)的核心思路:不要只把文档切成碎片去搜,而是先从文档中提取实体和关系,构建知识图谱,再基于图谱做检索和推理。

流程:实体与关系抽取 → 知识图谱构建 → 社区检测(Leiden 算法)→ 社区摘要生成 → 两种检索模式:

  • Local Search:从实体出发沿图的边扩散到邻居节点,适合事实查找("平安智盈金生的现金价值怎么算?")
  • Global Search:匹配相关社区,用社区摘要生成部分回答再汇总,适合全局理解("四份条款的退保规则有什么系统性差异?")

对本赛题的适用性:跨文档对比题和多文档联合推理题是 GraphRAG 的最优场景。比如 ins_a_001(四产品身故保险金排序),传统 RAG 需要逐份检索再手动对比,GraphRAG 可以直接在图谱中查询"身故保险金"实体,沿关系边找到四个产品的计算规则。代价是预处理阶段需要大量 LLM 调用,但可以在提交前离线完成。

LightRAG:轻量级图 RAG

LightRAG(香港大学, 2024)是 GraphRAG 的轻量替代,保留了图结构的优势,但大幅降低了构建成本。

关键差异:GraphRAG 需要社区检测 + 逐社区摘要,是重操作。LightRAG 用双向量索引同时支持局部和全局检索------实体节点有独立的向量表示(Local Search),关系边也有独立的向量表示(捕捉跨实体的语义模式)。新文档加入时可以直接增量插入,不需要重建已有索引。

对本赛题的定位:适合作为从标准 RAG 向图 RAG 过渡的第一个实验方案。构建成本接近传统 RAG,但能同时支持局部事实查找和全局对比推理。

RAPTOR:树状递归摘要检索

RAPTOR(2024)解决的是"扁平检索丢失全局上下文"的问题。

构建流程:叶子层(基础文本块做 embedding)→ 聚类(高斯混合模型软聚类)→ 摘要(每个聚类生成摘要,成为上一层节点)→ 递归重复直到只剩根节点。最终形成一棵多层树:底层是原始文本块(精确细节),中层是主题摘要(如"退保规则"),顶层是全局摘要。

检索时按复杂度选择层级:简单事实查找从叶子层检索;全局理解从顶层摘要节点检索。

对本赛题的适用场景:行业研报类题目(如 res_a_001 银保渠道发展历程)和跨年度对比题(如 fin_a_001 比亚迪两年年报对比)是 RAPTOR 的优势场景------这些题需要同时理解宏观趋势和微观数据,树结构天然匹配"总-分"的信息粒度。

CRAG:让系统反思检索质量

CRAG(2024)的核心洞察:传统 RAG 无条件信任检索结果,但 BM25 可能因关键词匹配把不相关片段排到前面,向量检索可能因语义模糊召回弱相关内容。

CRAG 加入自动纠错机制:检索后用轻量特征(关键词重叠度、片段间语义一致性)对整体结果打分,分三级处理:

  • 分数 ≥ 0.7(CORRECT):检索质量好,直接使用
  • 分数 0.3-0.7(AMBIGUOUS):质量一般,保留当前结果同时换关键词补充检索
  • 分数 ≤ 0.3(INCORRECT):质量差,丢弃检索结果,回退到全文阅读(baseline 硬截断作为 fallback)

对本赛题的适配:这个机制让系统在"检索结果好"的时候享受检索的效率,在"检索结果差"的时候自动回退到更稳健的方案,而不是一味信任检索。

HyDE:用假设答案做检索

HyDE(2023)解决的是"用户问题用词和文档用词不一致"导致的检索失败。

做法:先让 LLM 凭空生成一份假想的"理想答案"(用文档风格写,包含专业术语),再把这份假想答案(而非原始问题)转成向量去检索。假想答案更容易匹配到真实的相关片段。代价是每次检索多一次 LLM 调用,但召回率通常比直接向量检索高 10%-20%。

对本赛题的有效性 :对口语化问题(如"哪个产品最划算")特别有效。评测表明 HyDE + 混合检索(BM25 + 向量) 是目前综合表现最好的默认配置。

Agentic RAG:让 Agent 自主编排检索策略

前面所有范式都预设了检索策略:什么时候搜、搜什么、搜几次,都是提前写死的。Agentic RAG 把这个决策权交给 LLM 自己:通过 Function Calling,LLM 自主决定当前问题是否需要检索、搜什么关键词、搜到什么程度才算足够、搜到的东西质量差怎么办。

与本赛题的关联:Baseline 测试过 Function Calling,Token 消耗比 no-tool 高约 18%,但 FC 的灵活性(模型可以自主决定"什么时候搜、搜什么")是提升准确率的关键路径。

4.2.4 本赛题的 RAG 路线建议

从 baseline 的硬截断出发,建议按以下顺序逐步引入 RAG 优化 ,观点来自AFAC2026-advance baseline-tutorial.md:

阶段 方案 预期收益 风险
1 BM25 检索 + 语义分块 解决"答案不在前 4000 字"的问题 连贯性断裂,可能降分
2 + 多粒度分块(子块检索 + 父块回答) 缓解连贯性断裂 实现复杂度增加
3 + HyDE(假设答案检索) 提升召回率,改善口语化问题匹配 增加一次 LLM 调用
4 + Rerank 精排 提升精确率 额外计算开销
5 + 动态记忆压缩 在有限 Token 预算内保留最多有效信息 过度压缩可能丢失关键条件
6 + Bash 工具(Python 代码执行做数值计算) 消灭公式计算题的算术错误 需要设计沙箱执行环境
7 + CRAG 自检机制(质量评估 + 自动回退) 减少低质量检索导致的错误 需要设计评估器逻辑
8 LightRAG(跨文档题) 解决跨文档联合推理,支持增量更新 预处理 Token 消耗
9 Agentic RAG(FC 自主编排检索策略) 灵活应对不同题型 Token 消耗增加约 18%
10 smolagents Code Agent 减少 30% 推理步骤,精准数值计算 需要学习 smolagents 框架

建议每完成一个阶段就跑一次 A 榜提交,验证实际收益,避免"加了优化反而降分"的陷阱。


4.3 上下文与动态记忆

赛题名称里就有"动态记忆压缩",这定义了本赛题的核心技术挑战。PDF 解析和 RAG 检索解决的是"怎么找到有用信息",这一章解决的是"怎么在有限 Token 预算内把最重要的信息喂给模型"。

4.3.1 问题的本质:上下文窗口是稀缺资源

每道题的推理链路可以拆成:读文档 → 提取信息 → 判断 → 输出答案。每一步都消耗 Token,但预算有限(总预算 500 万 Token)。这意味着不能把所有文档全读一遍,也不能把检索结果全塞进 prompt。

上下文管理的核心问题可以表述为:给定 Token 预算,如何从候选信息池中选择一个子集,使得模型回答正确的概率最大化?

4.3.2 动态截断与信息密度控制

Baseline 的硬截断固定取前 4000 字符。更好的策略是让模型自己决定什么时候停止阅读:分段读取文档,每读一段就判断"当前信息是否足够回答问题"。如果足够就停止,不够就继续读下一段。

更精细的做法是按题型设定不同的阅读预算:事实查找题可能读前 2000 字符就能找到答案;跨文档对比题需要读多份文档,每份可能 1000 字符就够;公式计算题只需要定位到公式所在的段落,读到公式后就可以停。

保险条款和监管法规中有大量模板化文本(如"本合同的构成""投保须知"等),这些内容对答题几乎没有价值。可以预处理时过滤掉高频无意义段落,或者对"释义""名词定义"等章节降权。

4.3.3 工业界的记忆压缩实践

几个主流 Agent 框架都有类似的记忆管理机制,核心思路都是分层存储 + 选择性保留。

Kimi Code CLI 的 Context Compaction

当对话历史超过 token 阈值时自动触发 compaction,按优先级保留:当前任务状态、错误与解决方案、代码最终版本、系统上下文、设计决策、TODO 项。压缩后的历史替换原始对话,模型只看到摘要。

对本赛题的启发:可以定义类似的优先级------题目原文(绝不压缩)> 提取的公式和数值(核心证据)> 检索到的相关原文片段 > 文档结构信息 > 中间推理摘要 > 不相关的检索内容(优先丢弃)。

Hermes 的 Trajectory Compressor

核心算法是保护首尾、压缩中间、LLM 替代:

  • 头部保护:任务的初始上下文(题目定义、第一个工具调用)
  • 尾部保护:最后 N 个 turns(最新的推理状态和即将做出的决策)
  • 中间压缩:用 LLM 生成结构化摘要,替代原始阅读内容

对本赛题的映射:

  • "首" = 题目文本 + 选项(不可压缩)
  • "尾" = 最终推理步骤(列出公式 → 代入数值 → 计算结果 → 对比选项 → 输出答案)
  • "中间" = 文档阅读过程。读了一份 50 页条款,中间可能读了 20 页才找到"现金价值"定义,这 20 页可以压缩为一段结构化摘要

Claude Code 的四层渐进压缩

从便宜到贵逐级尝试:Layer 1 Snip(裁剪工具输出,免费)→ Layer 2 Microcompact(轻量压缩)→ Layer 3 Context Collapse(折叠搜索/读取操作为摘要)→ Layer 4 Autocompact(LLM 全量总结,最贵)。核心原则:只有低层搞不定才升级。

对本赛题的启发:检索返回的文档片段如果太长,先 Snip(只保留包含关键词的段落 + 前后各一段上下文);Snip 后仍然超预算再调 LLM 做摘要。不要一上来就让模型总结。

Codex 的 Memento 策略:为什么不能只留摘要

Codex 的 compaction 有一个关键设计:压缩后的历史不是纯摘要,而是 initial_context + 精选 user 消息 + summary + 最近 N 条。原因很简单------LLM 生成的 summary 会丢失精确信息。

一个典型场景:保险条款里"因意外伤害发生上述情形的,无等待期"这句例外条件,压缩时可能被总结为"等待期内一般不赔","意外伤害例外"这个关键信息就丢了。

对本赛题来说,压缩时至少要保留三类信息不被摘要化:

  1. 题目原文(包括选项):压缩题目等于修改题目
  2. 从文档中提取的精确数值和公式:如"现金价值 = 累计保费 × 75%"
  3. 包含例外条件的条款原文:如"但意外伤害导致的情形除外"

MemGPT:操作系统式的记忆管理

MemGPT(UC Berkeley, 2023)的核心类比是操作系统的虚拟内存:

  • 主上下文 = LLM 的固定上下文窗口(物理 RAM),容量有限但访问最快
  • 外部上下文 = 几乎无限的长期存储(磁盘),访问慢但容量不受限

关键创新:LLM 自己控制"换页"过程。当主上下文快满时,LLM 通过 Function Calling 主动检索需要的信息、判断哪些信息可以换出到外部存储、哪些外部信息需要换入。这本质上是把记忆管理从"系统层的固定规则"升级为"应用层的智能决策"。

对本赛题的映射:主上下文对应当前题目的 prompt(受单题 Token 预算约束),外部上下文对应文档全文(不受单题预算约束)。"换页"逻辑在本赛题中应该调整为"分段读取 + 渐进压缩":把读过的文档段落压缩后换出,释放上下文空间给下一个段落。

4.3.4 对本赛题的迁移

上述方案都针对"长对话"场景,但本赛题是"长文档 + 短推理":每道题是一轮独立的推理,不需要跨题记忆。动态压缩应该用在单题推理链的内部 :

  1. 文档阅读阶段:分段读取,每读一段就压缩提取关键信息(公式、数值、条件判断),只保留压缩后的摘要进入下一段
  2. 多文档对比阶段:读完文档 A 后生成结构化摘要,读文档 B 时只带着 A 的摘要而非原文
  3. 验证阶段:自检时不需要重新读全文,只需要带上第一轮推理的结构化摘要做交叉验证
4.3.5 实现建议

触发策略 :参考 Kimi CLI 的双条件触发------当 当前 prompt tokens >= 模型上下文窗口 × 0.7 或 当前 tokens + 预计下一轮检索返回的 tokens >= 模型上下文窗口 时触发压缩。0.7 这个阈值给后续推理留 30% 余量。

保留策略(按优先级从高到低):

  1. System prompt + 题目原文:不压缩,始终保留
  2. 从文档中提取的精确数值和公式:保留原文,不压缩
  3. 包含例外条件的条款原文(如"但...除外"):保留原文
  4. 中间推理步骤:可压缩为结构化摘要
  5. 已读但未用到的文档段落:直接丢弃

结构化摘要模板:压缩时不要用 plain text 总结,用结构化模板。参考格式:

复制代码
[CONTEXT SUMMARY]
Goal: 判断四款产品的身故保险金高低
Documents Read: doc_1(平安智盈金生)、doc_2(国寿增益宝)
Key Formulas Extracted:
  - 平安智盈金生: 身故保险金 = max(已交保费, 现金价值)
  - 国寿增益宝: 身故保险金 = 基本保额 × 年龄系数
Numerical Values:
  - 平安: 已交保费=100万, 现金价值=90万 → max = 100万
  - 国寿: 基本保额=90万, 系数=1.6 → 144万
Pending Verification: 文档 3 和文档 4 尚未读取

这种格式的好处是:后续推理可以直接定位到需要的字段,不需要在摘要里重新搜索。而且结构化的 Key Formulas 和 Numerical Values 不会被 LLM 的总结语言"改写"导致精度丢失。


4.4 Prompt 工程

Prompt 不是越长越好。hipw 在 36.8684 到 55.2313 的阶段把所有精力都放在改 Prompt 上,成绩确实有提升,但很快停住。真正有效的 Prompt 设计遵循两个原则:

按题型差异化 + 用 Few-shot 定格式。

4.4.1 题型差异化 Prompt

不同题型需要不同的引导策略:

  • 计算题:要求模型先列出公式、再代入数值、再计算结果。避免模型在心算环节出错
  • 条款定位题:要求模型先定位条款原文、再逐条比对。避免模型凭记忆判断
  • 多选题:要求模型逐选项判断,最后汇总。避免模型漏判或误判个别选项

这也是 Baseline 改进方案中 7 种题型(calc/extract/multi/compare/clause/fact/mcq)各用专用 Prompt 的来源

4.4.2 Few-shot 示例

在 prompt 中提供 1-2 个已答对的题目作为示例,帮助模型理解答题格式和推理过程。注意示例不要占用太多 token。


4.5 Agent

前面的章节解决了"怎么找信息"和"怎么压缩信息",这一章解决的是"怎么让系统自主决策"。Baseline 是单轮调用:读文档 → 一次性输出答案。Agent 化的核心是把这一步拆成"思考 → 行动 → 观察 → 再思考"的循环,让模型自己决定什么时候搜、搜什么、什么时候算、什么时候停 。

4.5.1 从单轮到多步:Agent 的核心思路

Baseline 的单轮模式对简单题有效,但对复杂题(跨文档、多条件、需计算)就力不从心。Agent 化的第一步是把流程拆成多步:

  • 读文档:分段读取,提取关键信息
  • 判断信息是否足够:如果不够,继续搜索;如果够了,进入推理
  • 综合推理:基于收集到的证据做判断
  • 输出答案

Function Calling(FC)是实现这一步的基础工具。Baseline 测试过 FC,Token 消耗比 no-tool 高约 18%,但模型可以自主决策"什么时候搜、搜什么",这对跨文档题和信息不足时需要补搜的场景特别有效。

4.5.2 计算题交给代码,不要交给 LLM

大语言模型本质上是"文字接龙"引擎,不是计算器。它在做数学运算时其实是在"背诵"训练数据里见过的计算结果,而不是真正执行算术。即使是最强的 LLM,在多步数值计算中的错误率也显著高于使用 Python 解释器辅助的方案。

解决方案:让 LLM 写代码,用 Bash 工具执行,再把执行结果还给 LLM 做最终判断。

这是终端 Agent(Terminal Agent)模式在金融 QA 中的典型应用:

  1. 模型不直接输出答案,而是输出可执行的 Python 代码
  2. 通过 Bash 工具在沙箱中执行代码,获取精确的数值结果
  3. 模型拿到结果后再做语义层面的判断(比如"增长率 20.1% 是否满足'实现增长'")

为什么 Bash 工具比 Function Calling 更适合计算 :Function Calling 通常只能调用预定义的函数(如 calculator(expression="8*0.0667")),不能写多步逻辑、不能定义中间变量、不能做条件判断。Bash 执行的 Python 脚本给模型一个完整的编程环境,可以自由定义数据结构、写循环、做断言。

额外收益:Bash 执行的 Token 消耗远低于让模型一步步推理。一段 Python 代码 50 个 token,执行结果 10 个 token;同样的计算让模型用 CoT 推理可能需要 200+ token。

4.5.3 ReAct:思考与行动交替

ReAct (Reasoning + Acting, 2023)是目前最主流的 Agent 推理范式。核心循环是:思考(Thought)→ 行动(Action)→ 观察(Observation)→ 再思考 → ...

在本赛题中的应用:

复制代码
Thought: "这道题需要计算三份保险的退保金。
         先从文档中提取各产品的退保金公式和参数。"
Action: 搜索文档,提取公式
Observation: "国寿增益宝:退保金 = 个人账户价值 × (1-退保费用率)
            退保费用率第7年为 0%"
Thought: "公式和参数已提取,现在用 Python 计算。"
Action: Bash 执行 Python 代码
Observation: "国寿增益宝 = 120000, 平安智盈金生 = 115000"
Thought: "排序:120000 > 115000,对应选项 A。"

这个循环的关键在于:模型每一步都基于上一步的观察结果做决策,而不是一次性把所有动作都规划好再执行。

4.5.4 Code Agent:用代码替代 JSON 工具调用

smolagents (HuggingFace, 2025)是一个轻量级的 Code Agent 框架,核心设计理念是:让 Agent 通过编写 Python 代码来执行操作,而不是通过 JSON 格式的工具调用。

传统 Function Calling 的流程:模型输出 JSON → 外部系统解析 JSON → 执行工具 → 返回结果 → 模型再输出 JSON...每一步都需要序列化/反序列化,且模型只能一次调用一个工具,无法写条件判断、循环、中间变量。

Code Agent 的流程:模型直接写一段 Python 代码,代码中调用多个工具、定义变量、做分支判断,然后一次性执行完毕,中间结果自动传递。

效率提升:据 HuggingFace 实验,Code Agent 相比 JSON Tool Calling 减少了约 30% 的推理步骤。原因是批量操作(一次代码块包含多个工具调用)、变量传递自动流入下一步、LLM 在代码生成上的训练数据远多于 JSON 工具调用格式。

对本赛题的适用性:

  • 公式计算题:直接写 Python 代码做数值计算,精确无误
  • 跨文档对比题:一次代码块中调用多次搜索工具(分别搜不同文档),收集所有数据后再统一计算
  • 多步推理题 :用 if/else 做条件分支,比如"如果资产负债率超过 70%,触发特别决议;否则普通决议"
  • 自检题 :代码中可以加入断言或验证逻辑,比如 assert result > 0, "计算结果不应为负"

实现建议 :在 Function Calling 的 tools 定义中加入 execute_python(code: str) 工具,工具描述中明确说明"用于精确数值计算,不要用 LLM 自己做算术"。代码在受限沙箱中执行(限制 import os/subprocess 等危险模块),超时设为 5 秒。如果代码报错,把错误信息返回给模型,让模型自己修。

下接:参赛方案解析

参考文献

  1. AFAC2026 赛道四官方赛题信息页。蚂蚁集团 / 阿里云天池,2026。
  2. hipw 博客:AFAC2026 赛题四B榜第一名方案复盘。hipw,2026 年 9 月。
  3. AFAC2026 获奖频道|华中科技大学"Lucky"团队获挑战组二等奖。AFAC 官方公众号,2026 年 9 月 29 日。
  4. afac2026-financial-qa:Baseline 改进方案。GitHub,2026。
  5. LogicRAG: Retrieval Augmented Generation with Adaptive Reasoning Structures。arXiv:2508.06105v2,2025。
  6. SmartChunk Retrieval: Query-Aware Chunk Compression with Planning for Efficient Document RAG。arXiv:2602.22225v1,2025。
  7. RAG over Tables: Hierarchical Memory Index, Multi-Stage Retrieval, and Benchmarking。arXiv:2504.01346v4,2025。
  8. FAIR-RAG: Faithful Adaptive Iterative Refinement for Retrieval-Augmented Generation。arXiv:2510.22344v1,2025。
相关推荐
我送炭你添花2 小时前
ASA原理与电子维修实战:前言 一路修来,一路学习
运维·网络·学习
yi0112 小时前
LeetCode 424. 替换后的最长重复字符|不定长滑动窗口:如何判断窗口是否合法?
笔记·python·算法·leetcode·双指针·滑动窗口
杨逢昌工厂6S管理3 小时前
116——杨逢昌:归位三定闭环法的旺季轻量化执行方案与工具清单
经验分享·笔记·职场和发展·学习方法
想喝奶茶啾啾3 小时前
AMBA CHI架构以及规范中使用的术语 翻译笔记(1)
笔记·arm·chi
代码山河3 小时前
第一个Java程序:Hello World从零编写与运行
java·学习·架构·教程·面向对象·项目
aqiu1111114 小时前
蓝桥杯省一学习计划:每天 2 小时,12 周高效备赛
学习·职场和发展·蓝桥杯
Filthyfrank4 小时前
I2C vs I3C时序差异
学习
yi0114 小时前
LeetCode 3. 无重复字符的最长子串|不定长滑动窗口:什么时候更新最大值?
笔记·python·算法·leetcode·双指针·滑动窗口
Water_based4 小时前
水性滚涂漆应用于滚喷机小五金件喷涂工艺详解
经验分享·笔记·产品经理