标书分析技能
字段说明见 @references/api.md。命令模板见 templates/workflow.sh。分析脚本在 scripts/。
能力说明
- 支持本地
.pdf、.doc、.docx招标文件上传并触发解析任务 - 采用"先上传获取 UUID → 持续轮询
--task-uuid直到终态"的流程 - 步骤 0 优先:接收到文件后,必须先执行
--map-query检查历史,避免重复分析(详见"步骤 0") - 自动异步触发后端智能解析
- 上传即返回,不做任何等待:上传后直接返回任务 UUID,进度通过
--task-uuid --poll查询 - 🔴 上传后必须主动轮询:新任务上传后,模型必须立即调用
--task-uuid --poll,脚本自动循环直到终态 - 失败优先原则:识别到明确失败时,必须立即、绝对停止轮询,不得再发送任何
--task-uuid请求 - 进度可见原则:轮询进行中必须向用户展示进度百分比
面向终端用户的表达(默认)
> 默认不要把命令行写给用户。 用户是普通业务人员时,用简短中文说明要做什么即可,不要列出 cd、python main.py、--task-uuid 等技术细节。
✅ 默认应对用户说的话(示例方向,可改写):
- 需要您提供/上传招标文件(支持 PDF、Word),或告知文件已放在哪;首次使用需在弹出的二维码上微信扫码完成登录。
- 分析一般需约数分钟到十分钟;若文件含多个标段,系统会请您选定要分析的分包。
- 完成后会把分析报告全文给您。
🚫 默认禁止对用户输出:
- 本仓库路径、
python ...、main.py参数、--poll等命令示例(除非用户明确索要「命令行怎么做」「我是开发者/自建环境」)。 - 大段「第一步、第二步」代码教程式排版(易与内部执行步骤混淆)。
与「仅输出脚本结果」的关系:
- 分析报告正文(
# 招标文件分析结果及脚本 stdout):仍须原样展示,不得改写或摘要。 - 衔接话术:可用自然语言,不必夹带命令行。
微信登录认证
- 没有可用 Token 时,运行本技能目录里的
python wx_login.py。几秒内命令结束,浏览器在后台继续等扫码,最长 5 分钟。二维码和这个后台浏览器绑在一起,浏览器一关码就失效。 - 只让用户扫二维码,不要提供浏览器登录链接。有的客户端打不开技能目录里的图片时,按下面顺序给图,不要只发文件路径:
1. 把脚本输出里WECHAT_QR_MARKDOWN:后面的整行原样放进回复。这是内嵌二维码,不依赖用户能不能访问脚本所在磁盘。
2. 本地 PNG 只作为补充。工作目录存在时,脚本还会导出/workspace/微信登录二维码.png。文件卡片如果没有真正预览出来,就不要再靠路径。 - 不要只用读取工具打开这张 PNG。那样只有助手自己看得到,用户看不到。
- 用户用微信扫码后,必须在手机上点「确认登录」。只扫不点等于没登录。用户表示已经扫码后,再执行原来的业务命令。
- Token 写入
~/.taitoubiao/token.json,五个技能共用。5 分钟内不要重复启动登录,否则旧码作废。 - 接口返回登录失效时,会清掉缓存并重新出一张码。自动化请设置
TAITOUBIAO_SKIP_AUTO_LOGIN=1。
🚫 输出规范(必须遵守)
> ⚠️ 核心原则:模型必须只输出脚本返回的原始结果,严禁自行生成中间状态消息或进度摘要!
🚫 严格禁止的行为:
- ❌ 禁止上传后不轮询:新任务上传完成后不得结束,必须立即进入步骤 2 循环查询进度
- ❌ 禁止被动等待用户触发:不得输出"已上传成功,请点击按钮查询进度"或类似话术后结束
- ❌ 禁止生成进度摘要:不得输出类似"已确认您选择标包X,当前分析任务正在进行中,进度XX%"的消息
- ❌ 禁止生成等待提示:不得输出类似"分析任务正在进行中,请稍候"的消息
- ❌ 禁止生成部分结果:不得在分析未完成时输出任何中间发现
- ❌ 禁止自行解释状态:不得用自然语言解释脚本输出的进度信息
✅ 正确行为:
- 用户侧沟通:见上文「面向终端用户的表达(默认)」— 默认不向用户贴命令行,只引导操作;分析结果仍只来自脚本。
- 仅输出脚本原始结果:将
--task-uuid命令的输出原样展示给用户,不做任何修改或总结 - 分析完成后直接展示:当脚本返回
# 招标文件分析结果时,直接展示完整分析结果
使用限制
- 仅支持后缀为
.pdf、.doc、.docx的招标文件 - 传入文件必须为本地绝对路径
🔴 状态判定规则(必须遵守)
--task-uuid 命令根据任务当前状态输出不同结果。不带 --poll 时单次查询,带 --poll 时自动循环直到终态。
1️⃣ 任务进行中(## 分析进行中)
输出示例:## 分析进行中,进度 45.3%\n\n- **预计耗时**:约 10 分钟(以实际进度为准)\n\n任务仍在处理中,请稍后再次执行查询命令。\n
必须执行的操作:
- 立即再次调用
--task-uuid - ⚠️ 正常分析耗时约 10 分钟,属于正常现象,不得提前终止轮询!
2️⃣ 任务暂停 + 分包确认(## 分包确认提醒)
含义:检测到多分包,需要用户确认目标分包
必须执行的操作:
- 🔴 立即停止轮询,不再发送下一次
--task-uuid请求 - 按"多分包强制确认规则"展示分包列表并等待用户选择
3️⃣ 任务失败(## 分析失败)
含义:招标文件分析失败,任务无法继续执行
必须执行的操作:
- 🔴 立即、绝对停止轮询,不得再发送任何
--task-uuid请求,不得以任何理由继续查询 - 🔴 不再发送下一次
--task-uuid请求,确保没有任何后续查询会被触发 - 将脚本返回的失败原因原样展示给用户
- 提供可能的解决建议
> ⚠️ 注意:失败后继续轮询是无效的,任务状态不会从 FAILED 恢复为其他状态。
4️⃣ 任务未找到(## 任务未找到)
含义:该任务在系统中不存在(UUID 无效,或刚上传尚未进入分析队列)
说明:脚本在首次查询遇到此状态时会自动重试 3 次(每次间隔 5s),以排除"刚上传尚未入队"的竞态情况
必须执行的操作:
- 🔴 立即停止轮询,不再发送下一次
--task-uuid请求(重试由脚本自动完成,模型无需处理) - 提示用户确认 UUID 是否正确或重新上传文件
5️⃣ 任务完成(# 招标文件分析结果)
含义:分析任务成功完成
必须执行的操作:
- 🔴 不再发送下一次
--task-uuid请求 - 完整展示分析结果(参考"结果展示规范"),不得遗漏任何分析章节
6️⃣ 继续分析已提交(## 继续分析已提交)
含义:用户选择了分包,已提交继续分析请求
必须执行的操作:
- 🔴 不要重复调用
--task-uuid,脚本在等待 30 秒后会自动继续查询 - 将脚本输出的"继续分析已提交"消息原样展示给用户
- 等待脚本自动完成后续轮询(约 30 秒后自动恢复查询进度)
轮询规则总结
| 规则项 | 要求 |
|---|---|
| 轮询间隔 | 约 10 秒调用一次 --task-uuid |
| 单轮时长 | 最多 60 秒(脚本 --poll 模式默认超时),超时后返回"分析进行中",模型可重复调用继续查询 |
| 终态判定 | FINISHED/FAILED/PAUSED+分包确认/任务未找到 → 停止轮询(不再查询) |
| 继续分析后 | ## 继续分析已提交 → 不要重复调用,脚本等待 30 秒后自动继续查询 |
| 非终态必须继续 | ## 分析进行中 → 模型必须重复调用 --task-uuid --poll 继续查询 |
> 💡 短周期轮询设计:脚本每轮最多运行 60 秒后返回,模型可在查询间隙与用户交互(展示进度、询问分包选择等)。
🔴 多分包强制确认规则(最高优先级)
> ⚠️ 核心原则:当招标文件包含多个分包时,模型必须主动反问用户选择目标分包,严禁自动选择或跳过此步骤!
触发条件
当 --task-uuid 输出中出现 ## 分包确认提醒,即表示检测到多分包。
🚨 强制行为要求(必须遵守)
一旦检测到多分包信号,必须立即执行以下操作:
- 立即停止轮询:不得继续发送下一次
--task-uuid请求 - 展示分包列表:以表格形式向用户展示所有分包信息
- 主动反问用户:必须明确要求用户选择目标分包
- 等待用户确认:在未获得用户明确选择前,不得进行任何后续操作
🚫 严格禁止的行为:
- ❌ 不得默认选择任何分包(包括第一个分包)
- ❌ 不得继续轮询进度
- ❌ 不得自动进入后续"标书生成"流程
- ❌ 不得自行决定分析全部分包(除非用户明确回复"全量分析"或"不分包")
- ❌ 不得跳过反问环节直接给出分析结果
用户展示格式
必须按以下格式向用户展示:
## 分包确认提醒
检测到该招标文件包含多个分包,请确认本次需要分析的目标分包:
| 标包序号 | 标包名称 | 预算金额 |
|---------|---------|---------|
| 1 | [分包1名称] | [预算1] |
| 2 | [分包2名称] | [预算2] |
| ... | ... | ... |
请回复以下选项之一:
• 回复"全量分析"或"不分包" → 分析所有分包的完整报告
• 回复具体标包序号(如"标包1") → 仅分析对应分包
• 回复标包名称 → 仅分析对应分包
> 重要:操作选项必须使用符号(•、- 等),严禁使用数字编号,避免与分包序号混淆!
用户确认后的操作
获得用户明确选择后,使用对应参数重新调用 --task-uuid:
- 用户选择具体分包:
--task-uuid "UUID" --poll --package-index <序号>(从 0 开始)或--package-name <名称> - 用户选择全量分析:
--task-uuid "UUID" --poll --no-package-filter
调用方式
步骤 0 - 自动检查历史记录(每次接收文件后自动执行)
用途:接收到文件后,必须先执行此步骤。通过映射库检查该文件是否已有历史分析任务,避免重复分析浪费时间。
自动执行命令:
python ./main.py --map-query "/absolute/path/to/tender.docx"
根据查询结果自动处理(无需用户手动选择):
| 查询结果 | 模型自动行为 |
|---|---|
存在 finished 状态的记录 |
向用户提示历史分析已完成,并输出以下选项:<br>• "查看历史分析结果" → 执行 --map-result(步骤 0A)<br>• "重新分析" → 进入步骤 1(上传) |
存在 running/uploaded 状态的记录 |
向用户提示分析任务正在进行中,并输出以下选项:<br>• "查询当前进度" → 取最新记录的 UUID,执行 --task-uuid 进入步骤 2<br>• "重新分析" → 进入步骤 1(上传) |
仅存在 failed 状态的记录 |
向用户提示上次分析失败,建议重新分析。用户确认后进入步骤 1 |
| 无任何记录 | 直接进入步骤 1(上传分析) |
步骤 0A - 查看历史结果(仅在有 finished 记录且用户选择时执行)
python ./main.py --map-result "/absolute/path/to/tender.docx"
- 脚本会自动查找该文件最新一条
finished状态的记录,调用后端获取完整分析结果 - 如果存在
running/uploaded状态的更新记录,--map-result仍会返回最新的finished结果(不返回未完成的任务) - 历史结果默认显示全部分包,无需指定
--package-index或--no-package-filter - 查看完成后流程结束
列出所有记录(可选,当用户要求查看所有历史时执行):
python ./main.py --map-list
映射库说明:
- 存储路径:脚本同目录下的
tender_task_map.json - 数据结构:同一文件路径可保存多次分析记录(
task_runs列表),每次分析生成独立 UUID - 单条记录字段:
| 字段 | 说明 | 示例值 |
|---|---|---|
file_path |
文件绝对路径 | /path/to/tender.docx |
task_uuid |
任务 UUID | abc-123-def |
status |
分析状态 | uploaded/running/finished/failed |
create_time |
上传时间(ISO 8601) | 2026-04-29T10:30:00 |
update_time |
最后更新时间 | 2026-04-29T10:45:00 |
result_summary |
结果摘要(bidDocumentId) | doc-12345 |
- 写入规则:同一文件每次上传都会追加新记录(不覆盖历史);同 UUID 的记录会被更新状态
步骤 1 - 上传文件,拿到任务 UUID
python ./main.py --file-path "/absolute/path/to/tender.docx"
上传成功后返回:
# 招标文件分析
- **状态说明**:文件已上传;请使用 --task-uuid 查询进度。
- **预计耗时**:约 10 分钟(以实际进度为准)
- **当前进度状态**:`RUNNING`
- **当前进度**:<currentProgress>%
- **进度描述**:<description>
注意:任务 UUID 从脚本输出的日志行中提取。脚本会打印 [上传] 成功,任务 UUID: xxx(其中 xxx 即为 UUID),同时在 stdout
中返回 # 招标文件分析。模型需要从输出中捕获 UUID 字符串,用于后续 --task-uuid 查询。UUID
格式示例:6ef2f926-d03f-47fa-9564-899ae0e2cb77。
步骤 2 - 自动轮询直到终态(上传后立即执行,不可跳过!)
> ⚠️ 核心规则:拿到 UUID 后,模型必须调用 --task-uuid --poll 启动自动轮询!脚本每轮运行约 60 秒后返回,模型需将结果展示给用户,并根据状态决定是否重复调用。
执行命令:
python ./main.py --task-uuid "TASK_UUID" --poll
脚本行为:
- 遇到终态(完成/失败/分包确认/任务未找到)→ 立即返回
- 分析进行中 → 约 60 秒后返回"分析进行中"状态,附带重复调用指令
- 模型需要将每次返回结果原样展示给用户
- 若返回"分析进行中",模型必须重复调用同一命令继续查询
轮询规则:
- 间隔约 10 秒
- 单轮时长约 60 秒(可通过 --cycle-timeout 调整)
- 遇到终态自动停止
> 注意:进度值由脚本自动从本地映射库读取和更新,无需手动传递。
异常处理约定
- 脚本返回非成功状态、401/403、Token 无效:立即返回失败,不继续轮询
- 结果查询链路失败:在分析结果中返回失败原因
- 网络超时/连接异常:返回失败并建议重试
可选参数
| 参数 | 说明 | 默认值 |
|---|---|---|
--file-path |
上传文件绝对路径(与 --task-uuid 二选一) |
无 |
--task-uuid |
按任务 UUID 查询进度/结果 | 无 |
--poll |
短周期自动轮询(每轮 ~60s 返回),与 --task-uuid 配合使用 |
关闭 |
--cycle-timeout |
单轮轮询时长上限(秒),默认 60s | 60 |
--package-index |
多分包时选择分包序号(从 0 开始) | 无 |
--package-name |
多分包时选择分包名称(精确匹配) | 无 |
--no-package-filter |
多分包时不分包,保留全部分包结果 | 关闭 |
--map-query |
按文件路径查询本地映射库中的任务记录 | 无 |
--map-result |
按文件路径查询最新已完成的分析结果并输出(默认显示全部) | 无 |
--map-list |
列出本地映射库所有记录 | 关闭 |
结果字段说明
- 解析结果:
# 招标文件分析结果,包含以下完整章节(信息不缺失):- bidDocumentId、项目基本信息(名称、编号、采购人等)
- 服务需求(含技术参数、交付要求、质量标准、人员配置、特别注意事项)
- 商务要求、资格要求、符合性审查、废标项、招标要求、投标文件构成要求
- 分包详情(序号、名称、预算、项目概述)
- 评分详情(技术/商务/资格审查项,含评审因素、分值、评分标准、响应要求)
- 工程量清单信息(如有)
- 所属领域(领域、子系统)
- 文件元信息(文件名称、类型、状态等)
结果展示规范
- 全量输出原则:招标文件分析完成后,必须向用户完整展示全部分析结果,不得省略、截断或仅摘要展示
- 脚本返回的分析结果包含结构化中文映射后的完整分析内容,应原样输出
- 若结果内容较长,可使用折叠/分段等方式优化展示,但内容必须完整,不得丢弃任何分析章节
- 仅在用户明确要求"仅查看某一部分"时,才可针对性展示局部内容
继续分析提交后的提示
当脚本成功提交分包选择继续分析后,会返回:
## 继续分析已提交
已选择分包序号:`X`,请稍后再次查询获取完整结果。
模型应向用户说明:已成功提交分包选择,请稍后再次查询获取完整分析结果。