招标文件分析(tender-doc-analysis)
这个 skill 能处理什么
一句话:把一坨招标文件(压缩包/文件夹)变成两份结构化报告——项目信息一页看懂,
货物清单数量限价自动对齐,最后还能渲染成可以直接发给同事的 HTML 页面。
| 输入格式 | 输出什么 |
|---|---|
| zip / 7z 压缩包 | 解压(中文文件名自动修乱码)→ 逐文件提取成 Markdown → 分析报告 |
| 整个文件夹 | 直接扫描提取,产物同上 |
| 单个 PDF | 文字/表格提取成 Markdown;扫描页可 OCR(把图片里的字识别出来) |
| 单个 DOCX / DOC | 正文+表格提取成 Markdown;文档里嵌的 Excel/PDF 附件也会一并拆出 |
| 单个 XLSX / XLS | 表格提取成 Markdown(合并单元格自动补全) |
提取完由 analyze 做三表匹配(把货物清单、选型清单、限价表按 15 位采购申请号
自动对齐,数量/限价不用人工抄表),再由 AI 按模板写报告,最后一键渲染 HTML。
何时使用
- 用户上传招标文件 zip / 7z / 文件夹,要求"分析一下这个标"
- 需要提取:项目基本信息、货物清单、最高限价、保证金、资格要求、评分细则、废标/否决条款
- 需要把分析结果整理成可分享的 markdown 或 HTML 报告
前置依赖
- Python ≥ 3.11
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
(python-docx / olefile / openpyxl / pdfplumber / PyYAML;国内网络建议走清华镜像)- pandoc ≥ 3.0 必须(docx 主体转换 + HTML 渲染),两种方式二选一:
- 免系统安装(推荐国内用户):
pip install pypandoc-binary -i https://pypi.tuna.tsinghua.edu.cn/simple
—— pandoc 二进制随 pip 包安装,doctor/render/extract 都会自动识别 - 系统安装:macOS
brew install pandoc(brew 慢可先换清华/中科大 Homebrew 镜像);
Debian/Ubuntusudo apt install pandoc;其他见 https://pandoc.org/installing.html - 可选:
rapidocr-onnxruntime(PDF 扫描页 OCR,extract --ocr) - 可选:
antiword/LibreOffice(旧版 .doc 提取;macOS 自动用 textutil,
以上都缺时内置 piece-table 解析器保底,无需任何外部工具) - 可选:
py7zr(.7z 压缩包) - 可选:
xlrd(旧版 .xls,含 OLE 嵌入的评分细则表;缺失时登记 issue 而非报错)
安装后先跑环境自检(会逐项检查并给出缺失项的国内镜像安装命令):
python scripts/tender.py doctor
四步工作流
第 1 步:extract(确定性,CLI)
python scripts/tender.py extract <输入zip或目录> -o <工作目录>
输入也可以是单个 pdf/docx/xlsx 文件。产物:
<工作目录>/
_originals/ 原始文件副本(zip 已展开,中文文件名已修正编码)
extracted/*.md 每个源文件一个 Markdown(表格已转 pipe table)
extracted/images/ 图片(如有)
_analysis/extract_todo.json 提取质检:复杂表 HTML、模糊引用、提取失败清单
_skipped.md 跳过/失败文件(如有)
PDF 扫描页默认只索引不识别;加 --ocr 做 OCR(慢,需 rapidocr)。
重复执行有 SHA256 缓存;--force 强制重提。
第 2 步:analyze(确定性,CLI)
python scripts/tender.py analyze <工作目录> [--province 河北]
产物(全部在 <工作目录>/_analysis/):
| 文件 | 内容 |
|---|---|
file_manifest.json |
文件分类清单(cargo_list / price_limit / selection_list / scoring_rules / tender_document 等 8 类 + 置信度) |
matched_cargo.json |
三表匹配结果:货物清单 × 选型清单 × 限价表,含每行数量/型号/单价限价/限价合计、包汇总、警告 |
completeness_report.md |
完整性四层校验(ZIP 内容 / 转换 / 关键文件 / 交叉引用) |
price_match_report.md |
限价匹配统计、重复键冲突、多规格警告(同一文件同一解析错误去重计数) |
complex_table_alerts.json |
复杂表依赖名单:关键内容只在 complex_tables HTML 中的文件清单(合成前必须逐个阅读,见第 3 步硬步骤) |
province_requirements.md |
省域上传平台/格式要求(--province 显式指定更可靠) |
第 3 步:LLM 合成(你来做,不是 CLI)
analyze 完成后 CLI 会打印下一步提示。按以下顺序执行:
- 先读
_analysis/completeness_report.md和extract_todo.json——缺失文件、
提取异常必须在合成前处理或标注。 - 必读复杂表名单(硬步骤):读
_analysis/complex_table_alerts.json,
其中列出的每个文件的复杂表 HTML(_analysis/complex_tables/*.html)必须
逐个打开阅读——合并单元格表格(须知前附表、初评否决条款表等)在 md 正文里
只有<!-- complex-table:N -->锚点,关键字段(保证金、投标有效期、开标信息、
否决条款)只存在于 HTML 中,漏读即漏事实。即使名单为空,合成前也应扫一遍
extract_todo.json的 complex_tables 确认无遗漏。 - 按
templates/project_page_template.md写<工作目录>/project_page.md。 - 按
templates/cargo_list_template.md写<工作目录>/cargo_list.md,
两页用[货物清单](cargo_list.md)/[项目页](project_page.md)互链。 - 资格要求、评分细则、废标/否决条款等文本类信息从
extracted/*.md逐字摘录
(用file_manifest.json的 doc_type 定位文件),禁止"详见招标文件第X章"式模糊引用。
> 红线(不可违反):
> - 所有数量、单价限价、限价合计、包汇总数值必须逐行取自 _analysis/matched_cargo.json,
> 禁止 LLM 手工解析原始表格数字、禁止心算合计。
> - 限价匹配不上的物资标 "—",禁止猜测、推算或取相邻行近似值。
> - matched_cargo.json 的 warnings[](重复键冲突、多规格、无限价表)必须在项目页显式呈现。
第 4 步:render(确定性,CLI)
python scripts/tender.py render <工作目录> [--html-dir <dir>] [--subtitle 副标题]
把 project_page.md + cargo_list.md 渲染为互链 HTML 包
(入口 index.html,frontmatter 信息卡片 + 侧栏 TOC + 深浅主题,离线自包含)。
默认删除「## 来源文件」节(内部路径噪声),--keep-source-section 保留。
产物结构
<工作目录>/
_originals/ 原始文件(勿改)
extracted/ 提取的 Markdown
_analysis/ 确定性分析产物(数值唯一权威来源)
project_page.md ← 第 3 步 LLM 写
cargo_list.md ← 第 3 步 LLM 写
html/ ← 第 4 步生成(index.html + cargo_list.html + style.css + app.js)
故障排查(FAQ)
每条按 症状 → 可能原因 → 解决步骤 组织。排查环境先跑:
python scripts/tender.py doctor(逐项检查并给出缺失项的安装命令)。
1. pandoc 未安装 / pandoc not found
- 症状:render 报「✗ 需要 pandoc ≥ 3.0…」;或 extract 的 docx 走了回退路径(合并单元格表格丢失,
extract_todo.json出现 complex_tables)。 - 可能原因:系统没装 pandoc,或装了但版本 < 3.0。
- 解决:
1. 免系统安装(推荐):pip install pypandoc-binary -i https://pypi.tuna.tsinghua.edu.cn/simple
2. 或系统安装:macOSbrew install pandoc;Debian/Ubuntusudo apt install pandoc
3.python scripts/tender.py doctor确认 ✓ pandoc 3.x 后重跑。
2. 货物清单 0 行 / 限价全 unmatched
- 症状:analyze 打印「货物清单 0 行」,或
price_match_report.md里限价匹配数为 0。 - 可能原因:该省招标文件的表头列名不在
rules/column_mappings.json映射表内。 - 解决:
1. 打开_analysis/price_match_report.md看解析错误与实际列名;
2. 把实际列名补进rules/column_mappings.json对应表的 mappings;
3. 重跑python scripts/tender.py analyze <工作目录>。
3. zip 解压后中文文件名乱码
- 症状:
_originals/里文件名是「²âÊÔ.docx」之类的乱码。 - 可能原因:zip_extractor 已自动做 cp437→GBK 还原;仍乱码多为压缩包源本身是 UTF-8 或其他编码(非 GBK Windows 打包)。
- 解决:手工把乱码文件改回正确名字,重跑 extract(
--force)。
4. .doc(旧版 Word)提取失败
- 症状:
_analysis/extract_todo.json出现doc_extract_failure。 - 可能原因:无 antiword/textutil/LibreOffice 时由内置 piece-table 解析器保底,正常环境不应失败;失败多为文件损坏或极端格式。
- 解决:
1.brew install antiword或安装 LibreOffice 后重跑 extract;
2. 或手工用 Word/WPS 另存为 .docx 放入输入目录重跑;
3. 注:.doc 改名 .docx 的假 docx 会经 OLE 魔数嗅探自动回退 doc 链,无需手工处理。
5. 扫描版 PDF 提取出来是空的
- 症状:PDF 提取结果「文字页: 0 | 扫描页: N」,正文只有扫描页索引。
- 可能原因:该 PDF 全是图片扫描件,没有文字层。
- 解决:
pip install rapidocr-onnxruntime -i https://pypi.tuna.tsinghua.edu.cn/simple,
然后python scripts/tender.py extract <输入> -o <工作目录> --ocr --force重跑。
6. 同名/重复文件
- 症状:
_skipped.md出现「内容相同(SHA256 一致),跳过重复副本」,或extract_todo.json出现stem_collision。 - 可能原因:招标文件常在顶层和 zip 内各放一份同样的货物清单(重复);或两个不同文件同名(冲突,后者自动加
__2后缀)。 - 解决:均为自动处理、无需手工干预;但合成前应浏览
_skipped.md确认去重符合预期(没被误去重的关键文件)。
7. extract 产物 0 个("✗ 提取产物为 0 个")
- 症状:extract 直接报「不支持的输入类型」或「提取产物为 0 个」。
- 可能原因:输入路径指错位置;输入是 .txt/.md 等不支持的类型;目录里没有任何 pdf/docx/doc/xlsx/xls 文件。
- 解决:
1.ls <输入路径>确认路径和内容;
2. 支持的输入只有:zip/7z、目录、单个 pdf/docx/doc/xlsx/xls;
3. 查看<工作目录>/_analysis/extract_todo.json的extract_issues(unsupported_type会逐文件列出)。
8. 改了输入文件但结果没变
- 症状:重新 extract 后 extracted/*.md 内容还是旧的。
- 可能原因:SHA256 缓存命中——只有文件内容真的变了才会重提;同名同内容的重提会直接覆盖,行为正常。若改了文件但哈希没变(极少见,如改回旧版本),或想强制全新提取:
- 解决:
python scripts/tender.py extract <输入> -o <工作目录> --force。
9. OCR 太慢
- 症状:
extract --ocr对大 PDF 跑到几十分钟。 - 可能原因:OCR 按页跑神经网络,扫描页多时开销大。
- 解决:
1. 先用--max-pdf-pages 50只跑前 50 页文字内容,确认提取质量;
2. 确认关键表格页后再全量--ocr;
3. 招标文件的关键表格(货物清单/限价)通常是 xlsx,PDF 扫描页多为资质文件,可不 OCR。
10. HTML 打开没有样式 / 交互失效
- 症状:
html/index.html打开是纯文本样式,侧栏 TOC 不出现。 - 可能原因:只拷贝了
index.html单个文件;style.css/app.js必须与index.html同目录。 - 解决:分享或移动时整体拷贝 html/ 目录(index.html + cargo_list.html + style.css + app.js 四个文件)。
11. pypandoc-binary 版本旧(pandoc < 3.0)
- 症状:doctor 报「✗ pandoc 2.x < 3.0」,而 pip 里已装过 pypandoc-binary。
- 可能原因:旧版 pypandoc-binary 捆绑的 pandoc 是 2.x。
- 解决:
pip install -U pypandoc-binary -i https://pypi.tuna.tsinghua.edu.cn/simple,再跑 doctor 确认。