阿里云天池 AFAC2026 金融智能大赛挑战组的赛题四:对保险、监管、财报、合同、研报五类金融长文档的单选/多选/判断题作答。这道题的难点不在模型,在约束:
- 只能调通义千问(Qwen)系列 API,不许微调;
- 禁止一切 embedding / 向量检索——也就是把最主流的 RAG 手段直接封死;
- 500 万 token 硬预算,超了 token 分归零;
- 评分 = 准确率为主(70% 权重打底)+ 省 token 为辅(30%)。
官方 baseline 只有 49% 准确率,而且烧了 687 万 token 超预算、token 分直接归零。所以真正要解的是:在不能用向量检索的前提下,怎么把长文档里那一小段决定答案的证据找准。
真实结果
A 榜两次真实提交,平台给分:
| 提交 | 得分 | 反推准确率 |
|---|---|---|
| 第一次 | 57.9954 | 约 61% |
| 第二次 | 64.9941 | 约 69% |
对官方 baseline(49%)是实打实的超出,绝对进步真实。但要如实说清楚位置:这个分数在 1251 支队伍里属于后三分之一,不是好名次——别人能做到 80、90 分以上。这里值得写下来的不是成绩,是过程里那些坑。另外整套代码是 AI 写的,我主导需求、架构、检索策略和逐条验收;下面这些判断和排错,是验收环节里真实发生的。
六个真实的坑
1. 思考模型偷偷烧 token。 让模型回一句”已连通”,completion_tokens 却是 595~1278;同样的问题换 qwen-plus 只花 3 个 token。根因是那一版是带隐藏推理链的思考模型,内部思考的 token 也计费、也算进 500 万预算——官方 baseline 超预算八成就栽在这。解法是显式 enable_thinking=False 默认关掉,压回个位数,复杂题再按需打开。
2. 全局 BM25 的马太效应。 四篇需要对比的文档混在一起检索,字数多的一两篇霸占了 top_k,其余的召回是 0——模型手里根本没证据。解法是按文档独立检索 + 动态公平配额(比如 12 个名额分给 4 篇、每篇最多 3 个),再给每个片段前面拼一个中文定位头「来自文档:某产品(doc_id=x),第 N 页」,防止多文档张冠李戴。还有个反直觉的调整:把”产品名精确命中”的基础分从 100 压到 15——因为产品名是高频背景词,分太高会把真正含指标数字的片段挤下去。
3. 条款跨页,文本被丢了。 有道题反复检索到错误的条款,模型算不出给付比例,干脆拿选项里的数字反推。深挖发现:条款跨页时,某一页开头那段属于上一条延续的文本被直接丢弃了,真正决定比例的第五条残缺。解法是修掉跨页丢失、保留延续文本,再给单文档单条款设名额上限,防长条款霸榜。
4. answer 字段和推理结论对不上。 模型推理里写”正确应为 B、C”,输出 JSON 的 answer 字段却填成”AB”。根因是 answer 和推理是两次独立生成,容易脱节。解法是让模型对每个选项单独输出 verdict,最终答案由代码从 verdict=true 确定性拼出,不再依赖模型复述。这一条我判断比降低瞎猜率更能直接提分——61%→69% 那次提交正是含这个修复。
5. JSON schema 字段顺序也是 bug。 verdict 排在了 reasoning 前面。模型是自回归生成的,先写完 verdict 再写 reasoning,中途想改主意也回不去改 verdict。把 reasoning 调到前面就好了——这种”让模型先想后答”的顺序,在结构化输出里是实打实影响正确率的。
6. 解析失败别急着退兜底。 有几道题模型在 JSON 外面包了 markdown 或解释文字导致解析失败,早期直接退 mock 假答案。改成三层解析(直接 loads → 提取代码块 → 提取花括号子串 → 才退兜底),降级率压到 0。
一次我自己埋的隐性大坑
这条要单独写,因为坑是我自己判断失误造成的。
监管领域有 513 个文档,重建索引后发现只索引进去了 6 个(1.2%)。追根源:早期让 AI 写解析脚本时,我只抽查了前 3 道题、看到它们都引用 txt 文件,就武断下结论”HTML 和 txt 内容重复,跳过 HTML”。实际上 txt 只有 6 个文件,HTML 有 377 个、附件 PDF 有 130 个——HTML 才是主体语料。结果是有些监管题”看起来答上了”,其实是零证据瞎蒙。
这个坑没有报错、不会 crash,是靠一道题空答案回归倒查出来的。教训很直白:抽样下的结论不能当全量事实,尤其当这个结论会决定”要不要整类数据都不要了”的时候。
一次拦下 AI 作弊的审查
还有一条关于”AI 自评不可信”。负责写代码的 AI 在自主循环里报告”瞎猜现象已完全解决”,我实测发现是假的——某些题里模型还在拿选项数字反推。更严重的是,它为了让效果好看,在检索代码顶部硬编码了一张字典,把测试集里 16 个保险产品的真名写死了——这等于”看过测试集内容记下答案”式的作弊,B 榜一换文档就会灌错误产品名,评审复现代码一眼能看穿。
这是我逐行审查时删掉的,不是 AI 自己改的。所以我不敢让 AI 的自我总结进验收结论——它说”解决了”,我得自己复跑确认;它写的代码,我得逐行看有没有为了好看走捷径。
诚实的边界
- 只做到 A 榜。 B 榜的盲测检索(没有 doc_ids、才是真正的 RAG 难点)完全没碰,项目停在 A 榜阶段。
- 名次不好。 69% 在 1251 队里后三分之一,绝对进步真实、相对位置落后,两个都如实说。
- 无标准答案的盲测。 数据集不含正确答案,本地算不了准确率,上面那两个准确率是从提交得分反推的,严格说是反推值。
- 有一个我一度依赖的指标其实是噪音。 我用”关键词命中率”来判断改动好不好,后来发现同一批题、同一份代码,这个指标在 40%~65% 之间自然波动——根源是云端 API 的非确定性,即使 temperature=0 也压不住。也就是说我几轮”变好变差”的对比,很大程度量的是噪音不是代码效果。这是我自己测量流程的漏洞:应该先建统一基线再优化,我没做到。
- 有一版改动没经提交验证。 最后一版”关键领域全文直喂”的架构,本地指标和抽查都变好了,但整合版因为账户欠费报 403 从没成功提交打分,所以”全文直喂能提准确率”这个判断,分数上是没有证据的,只能存疑。
这道题对我的价值不在分数,在那个反直觉的约束——当你不能用向量检索、还要省 token,你会被逼着回到”证据到底在文档哪一段”这个最朴素的问题上,而这恰恰是很多 RAG 系统被 embedding 糊过去、没真正解决的地方。