docs(evals): S01–S10 标注集 v1、评测工具和评测报告

- evals/gold:1,887 个标注单元(AI 标注、逐条裁定,未经人工复核),规范见 GUIDELINES.md
- prepare / run_all / score / gold:导出文字层、批量抽取、打分、标注定位
- docs/architecture/extract-eval.md:修复前后的结果(三项目标全部达标)和剩余问题
- decisions.md 记 M1(只用 Flash)和 Q1–Q4;架构 §13 SK13;AGENTS.md 进度

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
YANG JIANKUAN
2026-11-03 23:19:30 +08:00
parent f98fd51128
commit 602703c47c
21 changed files with 29427 additions and 18 deletions

137
evals/gold/GUIDELINES.md Normal file
View File

@@ -0,0 +1,137 @@
# 标注规范(S01–S10 标注集 v1)
标注集用来算抽取的召回率和准确率(FR-M2-05,`docs/architecture/tech-validation.md` §5)。每份文件一个 `<ID>.json`。
标注的口径就是产品对每一类的定义(`prompts/extract.*` 最新版本的「只找这些」「不要输出」),下面写的是落到标注上的具体规则。
## 0. 原则
- **只看原文**:`evals/out/docs/<ID>/sentences.txt`(规范化 PDF 的文字层,每行 `[p12s3] 句子`)。不看 `evals/out/runs/`、`evals/out/cache/` 里的模型输出,避免照着模型标。
- **一条要求一个单元**。漏标会让准确率偏低,多标会让召回率偏低,拿不准的标成 `"optional": true`(抽到算对,没抽到不算漏)。
- 标完运行 `cd server && ../.venv/bin/python ../evals/gold.py check <ID>`,所有片段都要定位成功。
## 1. 定位:anchors
```json
{"id": "q3", "cat": "qualification", "anchors": [{"p": 5, "t": "具有独立承担民事责任的能力"}], "note": "通用资格:独立承担民事责任"}
```
- `p` 是页码(`=== 第 N 页`),`t` 是从这一页**逐字复制**的原文片段:8~30 个字,去掉行首 `[p5s3]`、格式标记 `<iu>`、行尾〔上级:…〕。片段在这一页里要唯一(太常见就长一点)。
- 片段可以跨两句(表格被切开时),覆盖到的句子都算。
- 同一页上逐字相同的两段(两台设备的同一条参数),片段加长也区分不开时,加 `"n": 2` 指第几次出现。
- 一条要求写在几句里(表格同一行的几格、跨页):每句一个 anchor。只给写着要求本身的句子,不给章节标题、序号单元格、表头。
- **同一条要求在文件里出现在几处**(公告和须知前附表、资格条件和资格审查表、技术参数表和偏离表说明):每一处都列成 anchor。评测时命中任一处就算召回,抽到任一处都算对。
- `note` 用自己的话概括这条要求(不超过 30 字),不要整段复制原文。
## 2. 五类要求(`cat`)
### substantive:实质性条款(不满足就投标无效、被否决)
每个单元写 `basis`:
| basis | 什么样的句子 |
|---|---|
| `star` | 带 ★ 的条款,包括表格里带 ★ 的参数行 |
| `asterisk` | 文件的标注规则说明里声明了 * 号是实质性标注时,带 * 的条款 |
| `italic_underline` | 文件声明了「斜体且有下划线」是实质性标注时,条款正文是斜体下划线的句子(`<iu>`)。只有一部分是 `<iu>` 的句子,`<iu>` 部分是一项要求就算 |
| `explicit_invalid` | 这句话、紧挨着的上一句或下一句,或它的上级条款(「有下列情形之一的,投标无效:」「三、符合条件(必须提供,否则投标无效)」「资格审查不通过的,投标无效」)写明了不满足就投标无效、响应无效、无效投标、作无效处理、视为未实质性响应、否决投标、不予受理、予以拒绝、不能通过资格审查 |
- 一句同时带 ★ 又写明无效,按 `star` 记一条。
- 上级条款下的列表:每一项一个单元;引导句本身(「有下列情形之一的,投标无效:」)不算单元,除非它自己就写着一项要求。
- 不算:说明标注方式的句子(「加★为实质性要求」「斜体且有下划线部分为实质性要求」)、只是提到 ★ 的句子(「★号条款响应」)、偏离表和响应表的表头与填写说明;合同履约、中标后义务、付款、验收、售后、保密、违约;投标保证金不予退还;质疑投诉程序;评分扣分规则;整个采购活动废标、终止(供应商不足三家等)。
- 「中标无效」「成交无效」(中标后才追究的,如提供虚假材料):`optional`。
- 资格审查表、符合性审查表里的每一项,只有表或上级条款写明了「不通过 / 不符合的投标无效」才算 `explicit_invalid`。
- 87 号令第六十条的异常低价条款(「不能证明其报价合理性的……作为无效投标处理」)算 `explicit_invalid`。
- 第六章格式里,范本正文(「我单位郑重声明……」)不算;格式里的注释如果写明了无效后果(「注:未按此格式提供的,投标无效」)算。
### qualification:资格条件
- 通用资格(《政府采购法》第二十二条等):文件逐项列出的,每项一个单元;只有一句「满足第二十二条规定」的,算一个单元。
- 特定资格:资质证书、许可证、业绩、人员资格、注册资本;是否接受联合体;专门面向中小企业;信用要求(信用中国、政府采购严重违法失信记录等)。
- 资格要求常出现在公告「申请人的资格要求」、须知、资格审查表、资格证明材料清单等处:同一项的每一处都列成 anchor。
- 不算:评分加分条件;中标后的履约要求;采购需求里的项目团队配置;响应文件编制、递交、报价、有效期;第六章格式(声明函、承诺函、授权书、联合体协议)的范本文字;价格扣除优惠及其声明函;说明标注方式的句子。
### scoring:评分项
- 评分表里的每一个评分因素一个单元(价格分、技术分、商务分下面的每个因素),中小企业等价格扣除规则也各算一个单元。
- anchors 给这个因素所在行的句子:因素名称、分值、评分标准(标准很长时给写着分值和得分条件的句子,最多 8 个)。写 `points`(分值的原文写法,如「10」「0-5」)。
- 不算:资格审查、符合性审查的条件;评审程序的一般说明。
### schedule:关键日期与递交要求
每个单元写 `kind`:
| kind | 内容 |
|---|---|
| `question_deadline` | 提出询问、质疑的截止时间(写了具体时间或期限的) |
| `bid_deadline` | 投标(响应)文件递交截止时间 |
| `opening` | 开标(磋商)时间、地点方式 |
| `validity` | 投标(响应)有效期 |
| `deposit` | 投标保证金:金额、形式,或写明不收 |
| `submission` | 递交方式:电子投标、CA 加密上传、正副本份数、密封 |
| `decryption` | 开标后的解密要求(时间、方式) |
| `signature` | 投标文件签字、盖章、电子签章的要求 |
- 同一个日期在公告、须知前附表里重复出现:一个单元,每处都是 anchor。
- 不算:合同履行期、交付期、质保期;采购文件的发布、获取时间;合同签订;一般的编制要求、撤回修改程序;格式范本。
- `signature` 类容易零散,只标须知、前附表里成句的要求,格式页里的「(盖章)」「签字:」不标。
### tech_param:技术、服务、功能要求(抽样标注)
全部标注工作量太大,按页抽样:
1. 找出采购需求章(一般是第四章)里技术、功能、服务要求所在的页码范围 [a, b](不含项目背景、商务条款、付款验收)。
2. 在里面等距取 6 页:a + round(i × (b − a) / 5),i = 0…5;范围不到 6 页就全取。写进 `tech_param_pages`。
3. 这几页上**每一句可以在投标文件里逐条核对的要求**是一个单元:硬件软件参数、功能、性能、安全、接口要求,驻场人数、响应时间、培训等服务要求。一句里并列几项的算一条;参数名和参数值分在两格的,两句都给 anchor。
4. 不算:项目背景、建设目标、现状;合同、付款、验收;评分标准;格式范本;表头。
5. 这几页上带 ★ 的参数行既是 `tech_param` 单元,也是 `substantive` 单元(各记一条)。
## 3. 项目基本信息:project_info
12 个字段都要写,文件没写的填 `null`:
```json
"project_info": {
"name": "项目名称原文", "code": "JSZC-…", "purchaser": "采购人全称", "agency": "代理机构全称",
"procurement_method": "公开招标", "legal_regime": "gov_procurement",
"budget_total": {"value": "500", "unit": "万元"}, "ceiling_total": {"value": "500", "unit": "万元"},
"eval_method": "综合评分法", "accept_consortium": false, "accept_imported": false, "sme_only": false
},
"lots": [{"lot_no": "1", "budget": {"value": "14", "unit": "万元"}, "ceiling": {"value": "14", "unit": "万元"}}]
```
- 金额按原文的数字和单位写,不换算。预算和最高限价分开;有分包时总额填整个项目的,各包写进 `lots`(没有分包写 `[]`)。
- 是 / 否字段:文件写明了才填 true / false,没写填 `null`。
- 某个字段的写法在文件里不一致(例如两处预算不同),在 `notes` 里说明。
## 4. 复核时统一的口径(2026-11-03)
10 份标注完成后发现各份处理不一致的地方,统一如下:
- **标注类以句子本身为准**:句子本身带 ★、文件声明了的 *、文件声明了的斜体下划线,一律必标,内容是服务期限、付款、知识产权也照样标(文件自己声明它们是实质性要求)。
- **章节标题带 ★ 的**(S01「三、★商务要求」、S07「★售后」、S10「★(一)技术要求」):标题本身记一条;下面不带标注的句子暂记 `optional`,待产品定口径(见 `docs/architecture/extract-eval.md` §5)。
- **开标过程、开标记录疑义、质疑投诉程序、中标后事项**都不是 `schedule`;澄清、说明、补正的签章要求暂记 `optional` 的 `signature`。
- **裁定补标**:评测后对「正式清单里对不上标注」的条目逐条裁定,确属这一类、只是标注漏了的,补成 `"optional": true, "added_in_review": true` 的单元。这样补标只影响准确率,不会抬高召回率。
## 5. 文件格式
```json
{
"doc": "S01",
"annotator": "谁标的",
"reviewed": false,
"notes": ["这份文件的特殊情况,例如标注规则、表格被拆散的地方"],
"marking": {"markers": ["star"], "declared_count": null},
"project_info": {…},
"lots": [],
"tech_param_pages": [41, 43, 45, 48, 50, 52],
"items": [
{"id": "s1", "cat": "substantive", "basis": "star", "anchors": [{"p": 41, "t": "…"}], "note": "…"},
{"id": "q1", "cat": "qualification", "anchors": […], "note": "…"},
{"id": "c1", "cat": "scoring", "points": "10", "anchors": […], "note": "…"},
{"id": "d1", "cat": "schedule", "kind": "bid_deadline", "anchors": […], "note": "…"},
{"id": "t1", "cat": "tech_param", "anchors": […], "note": "…"}
]
}
```
`marking.markers` 写文件声明的实质性标注方式(`star` / `asterisk` / `italic_underline`),`declared_count` 是文件写明的 ★ 条款数(没写填 `null`)。

2788
evals/gold/S01.json Normal file

File diff suppressed because it is too large Load Diff

2262
evals/gold/S02.json Normal file

File diff suppressed because it is too large Load Diff

2932
evals/gold/S03.json Normal file

File diff suppressed because it is too large Load Diff

2822
evals/gold/S04.json Normal file

File diff suppressed because it is too large Load Diff

2421
evals/gold/S05.json Normal file

File diff suppressed because it is too large Load Diff

5676
evals/gold/S06.json Normal file

File diff suppressed because it is too large Load Diff

2800
evals/gold/S07.json Normal file

File diff suppressed because it is too large Load Diff

2673
evals/gold/S08.json Normal file

File diff suppressed because it is too large Load Diff

1986
evals/gold/S09.json Normal file

File diff suppressed because it is too large Load Diff

2113
evals/gold/S10.json Normal file

File diff suppressed because it is too large Load Diff