Files
bid-doctor/evals/check/GUIDELINES.md
YANG JIANKUAN 08e3fe7eff
Some checks failed
ci / server (push) Has been cancelled
ci / web (push) Has been cancelled
ci / contract (push) Has been cancelled
feat(qualification): 资质库和资质匹配(查标第 4 步,规则集 2026.11-r4)
- 资质库(FR-M6-08):增删改、证书扫描件(PDF/JPG/PNG,企业级密钥加密、签名下载)、
  late_for 按进行中项目的投标截止日提醒、审计;前端资质库页和对话框,侧栏入口
- 资质匹配(FR-M3-05):证书类别词表(16 类,产品证书、人员证书不进匹配),
  QUAL.EXPIRED / LEVEL_LOW / NOT_COVERED;投标文字层按清单项定级,只有资质库记录的降一级,
  出处显示「依据:资质库记录」(查标页、报告模板 v2);一类证书一个问题;评分项不逐条找响应的也查
- 响应错位规则不再把资质表的证书名称格当成照抄的要求
- 评测:qual_defects.py 派生资质情况表,D12 3/3、D18 2/2、规矩的资质表 0 误报;开发集不退化
- 决策 QL1–QL7;方案和落地记录 docs/architecture/qualification-plan.md,评测 check-eval.md §13

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 23:22:50 +08:00

23 KiB
Raw Blame History

查标评测集规范 v0.2(2026-11-04)

查标第 0 步(docs/architecture/m3-plan.md §4,决策 C1)。本文件在写第一条查标规则之前定稿:响应方式、问题分类表、投标文件怎么写、响应清单格式、留出集、评分和裁定规则。 读标的教训(docs/architecture/extract-status.md)在这里分别这样堵:AI 标注偏宽 → 响应清单在构造时就确定,挂问题的要求经人工复核;评分照搬抽取规则 → 只对照响应清单打分,另报只检索基线;规则照着样本调 → 按招标文件整体留出,留出一种写法和一套注入词库,开工时封存。 v0.2:请 Fable 审查 v0.1 后修改(响应方式按「文件 × 类别」记、规矩投标文件靠构造保证、注入分粒度、评分补三样口径、分类表补漏项),关键事实对照招标原文核对过。

1. 总体做法

  1. 没有真实投标文件(真实的国动投标文件只有一份,留作最终检验,见 §4),所以按 S01–S10 的真实招标文件自己造虚构的投标文件。
  2. 规矩的投标文件靠构造保证,不靠复核:偏离表、响应表、报价表、资格和评分材料清单由脚本从清单生成,技术参数按 op / value / unit 算一个满足的值;LLM 只写散文(技术方案、投标函叙述)和按风格改写表格行(截断、同义替换、重新编号),逐行小提示,不整本生成。
  3. 投标文件对招标文件的全部要求响应:「全集」用读标正式清单(evals/out/runs/fix3/<ID>/items.json),按「招标侧页码 + 片段」记,不只响应标注集的单元。
  4. 再用确定性的脚本往里注入问题得到马虎的投标文件。注入了什么、注在哪里,脚本同时写进响应清单,它就是金标准。问题只挂在复核过的标注单元上(evals/gold/<ID>.json,优先实质性条款和资格条件;复核方式见决策 E1)。optional 和复核时补的单元也可以挂,按内容复核(四批复核和用户抽查都是这样做的);上一次复核判为不成立的单元不再挂问题。
  5. 评分只对照响应清单,不用检索、偏离表对齐这些查标自己的逻辑来判断对错。

2. 每条要求怎么才算「响应了」:响应方式

招标文件对投标人怎么响应的规定按类别不同,同一份文件里常有几种(S01–S10 逐份核对):

方式 含义 招标原文的写法
explicit 逐条响应 在响应表 / 偏离表里逐条写明满足与否 「逐条 / 逐项作出响应」「逐一逐条响应填写」
implicit 默认接受 只列和要求不同的地方,没列出的视为接受 「否则将认为投标人接受」「未列入上表的视作完全接受」「除本表所列明的偏离外,均视作已理解和响应」「其余无偏离内容无需赘述」
evidence 要证明材料 要附证明材料(检测报告、截图、承诺函、证书),有的还要在材料里标出参数 「提供……证明材料」;when:bid(投标文件中提供)或 award(中标后、签订合同时提供,投标时只要承诺或什么都不要)
presence 文件要在 不是逐条响应,而是某份文件必须有、必须填全 「必须提供,否则投标无效」的格式文件、资格证明文件、声明函
platform 平台内应答 在电子投标客户端里应答,PDF 里看不到 S04「在电子投标系统逐条应答」

10 份文件的记录(类别 × 方式;单条原文另写了证明材料的,按条覆盖):

文件 技术参数 实质性 / ★ 商务 资格 评分项 备注
S01 explicit explicit + evidence explicit(商务要求均为实质性) presence evidence 「中标后签订合同前提供」11 处(award);投标时要提供的有第三方检测报告 12 处、承诺函 5 处(bid)。须知(p13)又写证明材料「在投标文件中提供」,和逐条的写法冲突,按逐条的写法
S02 implicit 符合性条件:explicit(符合性条件响应表);部分 ★:evidence implicit presence evidence 偏离表只列「除采购需求符合性条件外」的偏离
S03 implicit(以偏离表为准) ★ 14 条:evidence(要标注参数)+ 实质性响应条款表 implicit presence evidence ▲ 31 条也要 evidence(级别重要)
S04 explicit(全部逐一逐条) ★:explicit(实质性响应偏离表)+ evidence explicit presence evidence 另有平台内逐条应答(platform)
S05 implicit(只列正偏离) 无标注;符合性证明文件第 1~5 项:presence implicit presence(资格证明文件第 1~6 项必须提供;专门面向中小企业,中小企业声明函也必须) evidence 偏离表几乎为空是正常的
S06 explicit explicit(斜体下划线逐条) explicit presence evidence ▲ 要 evidence,未提供视为负偏离;格式写「(如有请提供)」和须知矛盾
S07 冲突 ★ 国产化承诺:evidence(承诺函) 冲突 evidence(逐一提供证明文件) evidence 须知「逐条标明满足与否」vs 格式注「未列入上表的视作完全接受」
S08 explicit(非实质性也逐条) explicit + evidence explicit presence ▲ 7 项:evidence
S09 explicit explicit explicit(实质性) presence evidence 投标时要的证明材料很少
S10 explicit explicit explicit presence evidence(人员证书 + 社保) 技术证明材料「签订合同时提供」(award)

响应清单给每条要求记下方式和招标原文依据。问题只在这种方式要求了、投标文件却没做到时才算:implicit 的要求没被复述不是问题;evidence + award 的要求投标时没附材料不是问题。

查标怎么处理响应方式是待定事项 C12(m3-plan.md §7)。评测集按本节记录,C12 怎么定都能评。

3. 问题分类表

注入的问题分两类:要求项问题挂在某条要求上;规则问题不挂要求(或挂报价类要求)。另有干扰项:看起来像问题、其实不是,查标不应该报。

3.1 要求项问题

编号 问题 期望的结论 / 问题类型 期望级别 变体 实现阶段
D01 漏响应(要求 explicit,整条没写) unresponded 按要求项 删一行;删连续一段;整节缺失 第 1、3 步
D02 投标时要的证明材料缺失(evidence + bid) unresponded(证明材料) 按要求项 写「见附件 5」但附件不存在;根本没提。「附件在但没标出参数」单列,不进头条指标 第 3 步
D03 数值不满足 suspected_unmet 按要求项 低于下限;高于上限;数量不够;单位不同换算后不满足(≥2TB 写 1024GB、≤50ms 写 0.1 秒、≥10Gbps 写 1000Mbps);偏离列写「正偏离」值却更差 第 3 步
D05 功能写明不支持 negative_deviation 按要求项 「暂不支持」;「需二次开发后支持」;「可选配」(negative_deviation 或 no_value 都算对) 第 3 步
D06 负偏离没有说明 negative_deviation 按要求项 说明栏空;「部分满足」;只写「偏离」不写方向 第 3 步
D07 偏离表写无偏离,正文的值不满足 suspected_unmet 按要求项 技术方案正文的值;配置清单的值;彩页摘录的值。MVP 可能不查(m3-plan §2.1),评分单列 第 3 步
D08 只写「满足」,没给要的具体值或材料 no_value 提示 单条;整张表都写「满足」 第 3 步
D09 响应对象错位 unresponded 按要求项 写的是另一台设备的同名参数;另一个采购包;整章是另一个型号 第 3 步
D10 符合性条件响应表填「未完全响应」或空着 negative_deviation 致命 空着;「未完全响应」;「部分响应」 第 3 步
D11 资格证明材料缺失 unresponded 致命 目录列了、正文没有;整份缺失;给的是别的证书 第 3、4 步
D12 资格证书过期(按投标截止日) qualification(过期) 资格致命、评分重要 早于截止日;整本证书过期 第 4 步(qual_defects.py 派生,规则问题口径评分)
D13 评分项要的证明材料缺失 unresponded 重要 业绩合同缺;人员证书缺;社保缺 第 3 步
D14 证书主体和投标人不一致 qualification 致命 子公司;分公司;曾用名 OCR 之后(决策 QL7)
D15 业绩 / 人员证明的时间窗口不符 qualification / unresponded 资格致命、评分重要 业绩合同在近三年之外;社保月份不在要求区间 V1(业绩、人员库,决策 QL7)
D16 授权代表的社保证明缺失(文件要求时) unresponded 致命 没附;附的是别人的;月份不对 第 3 步
D18 资质证书等级低于要求 qualification(等级不足) 按要求项 低一级;证书编号里的等级和等级栏不一致 第 4 步
D17 多包:采购包号空着或写错 formality 重要 偏离表包号空;授权书包号写错;分项表包号写错 第 2 步

(v0.1 的 D04「换算后不满足」并入 D03 当变体。)

3.2 规则问题

编号 问题 期望的规则编号 期望级别 变体 实现阶段
P01 报价超过总价限价 PRICE.OVER_CEILING_TOTAL 致命 超 1 元;超 1%;万元 / 元的数量级错 第 2 步
P02 报价超过采购包限价 PRICE.OVER_CEILING_LOT 致命 同上(S10) 第 2 步
P03 分项或单价超上限 PRICE.OVER_CEILING_ITEM 致命 单项超;单价 × 数量超 第 2 步(依赖 C7)
P04 大写和小写金额不一致 PRICE.CAPITAL_MISMATCH 重要 差一位;大写多一个「拾」;小数点错 第 2 步
P05 开标一览表和分项合计不一致 PRICE.SUM_MISMATCH 重要 漏加一项;单价 × 数量算错;四舍五入差 第 2 步
P06 出现别的项目名称、编号或采购人 FORM.FOREIGN_PROJECT 重要 页眉留旧项目名;授权书写旧项目编号;投标函写错采购人 第 2 步
P07 该填的地方没填 FORM.BLANK_FIELD 提示 投标人名称空;落款日期「年 月 日」;授权书受托人空 第 2 步
P08 落款日期晚于投标截止日 FORM.DATE_AFTER_DEADLINE 提示 晚一天;年份错;月份错 第 2 步
P09 投标有效期短于要求 FORM.VALIDITY_SHORT 致命 90 天写 60 天;写「30 日」 第 2 步
P10 附加条件 FORM.CONDITION_ADDED 重要 「报价不含税」;「付款方式另议」;「以实际到货为准」 第 2 步
P11 缺必须提供的格式文件(presence) FORM.MISSING_DOC 致命 缺授权委托书;缺投标函;缺符合性条件响应表 第 2 步
P12 给了两个报价 PRICE.MULTIPLE_QUOTES 致命 两行总价;「方案一 / 方案二」;「优惠价」 第 2 步
P13 分项报价表缺项、漏项,和采购需求清单对不上 PRICE.ITEM_MISSING 致命 漏一项;名称对不上;数量对不上 第 2 步
P14 格式文件的固定文字被改动 FORM.FIXED_TEXT_CHANGED 重要 删承诺句;改有效期措辞;改主体 第 2 步
P15 授权委托书的受托人和投标函签字人不一致 FORM.SIGNER_MISMATCH 致命 姓名不同;职务不同;身份证号不同 第 2 步
P16 声明函填报不全 FORM.DECLARATION_INCOMPLETE 致命(本国产品声明函三项缺一;专门面向中小企业时的中小企业声明函)/ 提示(其他) 缺一项;未逐一填报;类型选错 第 2 步
P17 签章位置没有图像 FORM.SEAL_ABSENT 提示 投标函;授权书;开标一览表 第 2 步
P18 报价低于文件写明的阈值却没附说明 PRICE.LOW_NO_EXPLANATION 重要 低于阈值没说明;说明不在投标文件里 第 2 步

3.3 干扰项(不应报问题)

编号 情形 期望
T01 响应写在别的分册 已响应
T02 要求被截断、改写、重新编号后再响应 已响应
T03 只写值不复述要求(「内存:64GB DDR4」) 已响应
T04 单位不同但满足(≥1024GB 写 2TB) 已响应
T05 正偏离 已响应
T06 implicit 的要求,投标文件没有复述 不报问题(按 C12 的结论)
T07 正文里出现本项目的名称、编号、采购人 不报 P06
T08 「(盖单位章)」「(签字)」括注保留、名称和日期已填 不报 P07
T09 条款写「中标后 / 签订合同时提供」,投标文件只写承诺或没写 不报 D02
T10 声明函里「/」划除处未填(文件写明无需填写) 不报 P07
T11 评分项的可选加分没响应 不报致命,最多提示
T12 implicit 文件的偏离表只有一行「无偏离」 不报 D01、不报缺偏离表
T13 正文写「见附件 N」且附件存在 不报 D02

3.4 注入的分布

真实投标人的错是成簇、相关、不声张的,均匀分布的单点问题会让分数虚高。所以:

  • 三种粒度:单点;连续块(相邻 5~20 行一起漏、一起错);全局模式(整张表写「满足」、整章换成另一个项目或型号、整本证书过期)。响应清单记 granularity。
  • 有一部分不带标志词:没有「暂不支持」这类字样,只是合理位置上的错数字、错单位、错型号。响应清单记 worded: false,按带不带标志词分别报召回。
  • 两档密度:多数马虎的投标文件注入 25~40 个(覆盖各类);另选 3 份只注入 5~8 个(接近真实密度),看低密度下误报会不会淹没真问题。
  • 注入词库分开发集用和留出集用两份(§4)。

4. 样本和留出集(开工前选定,之后不改)

集合 招标文件 选它的理由
开发集 S01、S02、S04、S05、S07、S08、S10 逐条响应(S01、S08、S10)、默认接受(S02、S05)、全逐条 + ★ 双表 + 证明材料(S04)、冲突(S07)、中标后提供(S01、S10)、多包和单价上限(S10)、磋商(S08)、WPS 旧版 DOC(S07)
留出集 S03、S06、S09 S03:★ / ▲ 证明材料、一般参数默认接受;S06:分项最高限价、只用斜体下划线、清单最大;S09:磋商、★ 和斜体下划线双重标注、WPS 旧版 DOC。留出集里没有 S05 那种「只列正偏离」的写法,报告里写明
留出集(真实) 国动小程序投标文件(用户提供) 唯一的真实投标文件,第 3 步冻结代码后要来跑一次,之前不看、不按它调。它对应的招标文件不在 S01–S10 里,届时单独走一遍读标、人工看过清单再评

写法风格:

风格 写法 用在
A 复述型 响应表、偏离表照抄要求原文,再写响应值和「无偏离」(苏采云范本的常见填法) 开发集
B 简写型 要求被截断、改写、重新编号;技术方案正文只写值不复述要求;部分响应写在别的分册 开发集、留出集
C 叙述型 以叙述性技术方案为主,表格少;自己的条目编号;同义词替换 只用在留出集

封存:留出集专用的注入词库和 C 风格写作说明,在开工时由另一个会话写好,放进 evals/out/check/_sealed/,之后不打开;写它的会话不接触查标规则代码。写 C 风格的会话不看 A / B 的产出。check.match 提示词的例子和注入词库做文本比对,不允许出现同样的短语。写作说明里的例子不取自 S01–S10 的招标文件和开发集投标文件。

每份招标文件写两份投标文件:开发集是 A 规矩 + B 马虎(按文件轮换);留出集是 B 规矩 + C 马虎。一共 20 份。先做 S02、S04、S10 这 6 份,端到端跑通「生成 → 渲染 → 离线查标 → 评分」,修好生成器和评分脚本,再做其余开发集,留出集最后做。

5. 投标文件怎么生成

  1. 格式用招标文件自己的:投标函、开标一览表、分项报价表、偏离表、响应表、授权委托书、各种声明函,用这份招标文件格式章给的格式和表头。
  2. 生成流程:build.py 从读标正式清单和格式章生成规矩投标文件的结构化稿(spec.json)→ LLM 按风格改写表格行、补写散文 → mutate.py 注入问题、写响应清单 → render.py 渲染并回填位置。
  3. 渲染:多数走 Chromium(HTML → PDF);至少 2~3 份走 DOCX → LibreOffice(产品的真实路径),带合并单元格、多行单元格。资格证明、业绩合同中有一部分做成图片页,检验 C10。
  4. 自检:冻结前用另一个模型跑一遍「找无意的偏离」,脚本扫一遍占位符和空表格,再由人抽查。
  5. 复核(决策 E1):只复核挂了问题的标注单元(每份马虎的投标文件 25~40 个,20 份约 600~800 个)和各文件的响应方式记录,ok 的单元不复核。由另一个模型(Fable,和写投标文件的 Opus、查标的 DeepSeek 都不同)逐条复核,用户随机抽查 20%;抽查不一致的比例写进评测报告。所有评测结论都注明「金标准由模型复核、用户抽查 20%」。

6. 文件格式

6.1 投标文件稿 spec.json

{
  "bid": "S02-A",
  "tender": "S02",
  "style": "A",
  "project_name": "……",
  "bidder": {"name": "某某信息技术有限公司(虚构)", "credit_code": "91320000MA0000000X"},
  "volumes": [
    {
      "id": "v1",
      "kind": "whole",
      "header": null,
      "blocks": [
        {"type": "heading", "text": "一、投标函"},
        {"type": "para", "text": "……", "responds": []},
        {"type": "table", "title": "偏离表", "header": ["序号", "招标文件的要求", "投标文件中的内容", "偏离", "说明"],
         "rows": [{"cells": ["1", "……", "……", "无偏离", ""], "responds": ["s2"], "req": {"p": 53, "t": "支持硬件BFD"}}]},
        {"type": "scan", "text": "营业执照(副本)扫描件", "lines": ["……"], "responds": ["q3"]}
      ]
    }
  ],
  "price": {"total": "1498000.00", "items": [{"name": "汇聚交换机", "qty": 3, "unit_price": "52000.00"}]}
}

responds 写标注单元编号(有的话);req 写招标侧「页码 + 片段」(全部响应块都写,不在标注集里的要求也有)。

6.2 响应清单 manifest.json(金标准)

{
  "bid": "S02-B-sloppy",
  "tender": "S02",
  "style": "B",
  "split": "dev",
  "kind": "sloppy",
  "modes": [
    {"category": "tech_param", "mode": "implicit", "basis": [{"p": 76, "t": "否则将认为投标人接受"}]},
    {"category": "substantive", "mode": "explicit", "scope": "符合性条件", "basis": [{"p": 20, "t": "必须提供,否则投标无效"}]}
  ],
  "units": {
    "s2": {
      "mode": "evidence", "when": "bid",
      "reviewed": true,
      "expect": "defect", "defect": "D02", "variant": "附件不存在",
      "granularity": "single", "worded": false,
      "where": [{"volume": "v1", "p": 31, "t": "支持硬件BFD,最小发送间隔3.3ms"}],
      "expected_location": {"volume": "v1", "section": "技术证明材料"}
    },
    "s3": {"mode": "implicit", "expect": "ok", "trap": "T06", "where": []}
  },
  "rule_defects": [
    {"id": "P04-1", "type": "P04", "variant": "大写多一个拾", "where": [{"volume": "v1", "p": 2, "t": "壹佰肆拾玖万捌仟元整"}]}
  ]
}
  • expect:ok、defect、na(不要求投标人响应,或 platform 平台内应答)。
  • reviewed:挂了问题的单元必须为 true(人工复核过要求本身和响应方式)。
  • where 在渲染后由脚本回填;expected_location 写这条响应本该在哪个分册、哪一节(整节缺失时用来核对「找过哪些分册」)。

7. 评分

score.py 读一次离线检查的输出(run_check.py 的 results.json),对照响应清单:

  1. 映射口径:问题的任一招标侧出处和标注单元的任一 anchor 重叠即对上(复用读标评分的定位)。
  2. 按单元去重:同一要求在清单里有几条(公告、须知、审查表),只要一条报出就算召回,几条都报只算一个对的、不算误报;几条都没报算一个漏报。
  3. 问题类型按类型族比(unresponded 含证据没核对上的那种),级别单独比。
  4. 主要指标:
    • 致命级问题召回率(按分类、粒度、带不带标志词分别报;漏报比误报严重);
    • 端到端召回(读标抽到 × 查标查出),致命级单独报:对用户来说读标漏抽也是漏报;「查标召回」只在读标抽到的要求上算;
    • 问题准确率:报出的问题里对上注入问题的比例,「对上注入的问题」和「其他」分两列;
    • 规矩投标文件的误报数(每 100 条要求)、干扰项误报率(按 T01–T13 分别报);
    • 只检索基线:不调模型,检索第一名命中就算已响应,按风格分别报;全系统和基线差不多,说明评的是检索不是判断;
    • 证据没通过校验的问题占致命问题的比例(目标 < 10%,C3);每次检查的 token 和费用(C2)。
  5. 对不上标注单元的问题单列「无法对照」,不算对也不算错。
  6. 开发集、留出集分开报;所有数字带风格标签。头条是留出集 C 风格和国动真实投标文件,开发集 A 风格的数字只作调试用。

8. 裁定规则

  • 开发集上查出了响应清单里没有的问题:由人裁定一次。投标文件里确实有这个问题(生成时无意留下的),就改响应清单并记录;没有就算误报。
  • 留出集:允许改响应清单,但只限投标文件里客观可查的错;每一次记为「响应清单错误」,不算查标误报也不算查标对,单独报这个数(它大说明生成器差)。不许据此调规则和提示词。
  • 裁定记录写在 evals/out/check/adjudication/<bid>.md。

9. 放在哪里

内容 位置 进不进 git
本规范、留出集划分 split.json、开发集写作说明和注入词库、生成 / 渲染 / 评分脚本 evals/check/ 进
留出集专用的注入词库和 C 风格写作说明 evals/out/check/_sealed/ 不进(封存)
投标文件稿、渲染出的 PDF、响应清单、检查输出、裁定记录 evals/out/check/ 不进(照着真实招标文件写的)
真实的国动投标文件 用户本地,第 3 步冻结后提供 不进