下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/org-nf0p0fi4--biaozhuhero-prod.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @org-nf0p0fi4/biaozhuhero-prod。AI 标书生成技能,连接标书系统开放 API,完成招标文件解析、标书目录生成、章节内容生成,最终产出完整的投标文件。当用户涉及以下场景时必须使用此 SKILL:解析招标文件、生成标书目录、创建投标文件大纲、生成标书章节内容、生成投标文件/标书。即使用户未指定,只要涉及解析招标、生成目录、标书大纲、生成标书内容、写标书等需求,都应使用本 SKILL。
阅读全文 (展开查看完整说明)
概述
AI 标书生成(解析 → 目录 → 投标文件)
本技能是标书系统在 WorkBuddy 的适配壳。标书解析、目录生成与章节内容生成引擎均由后端服务提供,本技能只负责把 WorkBuddy 的对话任务转成对 REST API 的调用并回传结果。
能力范围:从上传招标文件开始,依次完成「招标文件解析 → 生成标书目录 → 生成章节内容」,最终产出完整的投标文件(全部章节的 Markdown 内容),不再止步于目录。
前置条件
- 后端服务已部署并正常运行。
- 用户需要手机号注册/登录。
- 配置模板见
config.yaml;接口契约与字段见references/api.md。
完整流程(WorkBuddy 交互)
核心原则:所有需要用户提供的信息,优先通过 WorkBuddy 的交互式输入组件(输入框/选择列表)收集,不要在对话中让用户直接打字回复后靠 AI 解析。
降级策略(重要):若交互式组件调用失败(如"获取回答失败"、组件不支持、超时、挂起无响应),不要反复重试同一组件,立即降级为普通对话提问:直接在对话中列出选项/说明(如"请回复 1/2/3 或直接输入"),等用户文字回复后继续流程。降级只是收集方式变化,该收集的信息一个都不能跳过。
环境记忆(重要):若当前会话中已确认环境不支持交互式组件(包括组件挂起不返回选项的情况),则本次会话的全部后续交互都直接用对话提问,不要再尝试任何交互式组件,避免反复卡死。
步骤0:登录
- 【交互式输入框:手机号】 弹出输入框(input 类型,placeholder="请输入11位手机号")让用户填写手机号;不要在对话里问手机号。
- 拿到手机号后调用
getCode发送验证码。 - 【交互式输入框:验证码】 弹出输入框(input 类型,placeholder="请输入6位短信验证码")让用户填写验证码;不要在对话里问验证码。
- 拿到验证码后调用
loginByPhone登录,获取并保存 Token。
步骤1:上传招标文件
- 让用户提供招标文件(PDF/DOC/DOCX)本地路径。
- 调用
uploadFile上传文件,获得文件 URL。
步骤2:解析招标文件
- 【交互式选择列表:项目分类】 必须弹出选择列表(single-select),选项固定为:
工程类/货物类/服务类。绝不允许跳过此步、绝不允许 AI 自行猜测分类。 - 拿到用户选择后调用
parseTenderFile提交解析任务(立即返回 projectId/tenderFileId)。 - 立即保存返回的
projectId和tenderFileId,然后每 5 秒调用一次parseResult轮询解析状态,直到 status=success/failed。期间持续向用户播报进度。 - 绝不重复调用 parseTenderFile:提交一次后只轮询 parseResult,轮询超时也只重新查询结果,不重新提交。
步骤2.5:用户选择解析结果
- 【交互式多选列表:解析条目】 将解析返回的
items全部展示为多选列表(multi-select),让用户勾选需要生成目录的条目。 - 必须等用户勾选并确认后才能进入下一步。
步骤3:生成标书目录
- 【交互式输入框:目标字数】 弹出数字输入框(number 类型,范围 1~1500000,即最多150万字)让用户填写目标字数。
- 调用
generateDirectory提交生成任务(传入步骤2保存的 projectId、tenderFileId + 目标字数,立即返回 bidFileId)。 - 保存
bidFileId,每 5 秒调用一次directoryResult轮询生成状态,直到 status=success/failed。期间持续播报进度。 - 绝不重复调用 generateDirectory:提交一次后只轮询 directoryResult。
- status=success 时返回目录结构。
步骤4:生成章节内容(异步)
- 目录生成成功(status=success)后,先询问用户是否继续生成章节内容:内容生成耗时较长,必须得到用户明确确认后才能提交。
- 用户确认后调用
PUT /skill/updateIsGenerate提交内容生成(body:{"ID": "<bidFileId>", "type": "generate"}),立即返回。首次付费:若该标书尚未付费,接口返回 HTTP 402…(付费网关已关闭,此逻辑暂不生效)
- 每 5 秒调用一次
GET /bidFileItem/listStatusByBidFileID?ID=<bidFileId>轮询各章节状态(返回[{ID, status}]列表),持续向用户播报进度(成功 x/总章数)。所有章节都到达 success/failed 才停止轮询。内容生成耗时可能很长(章节多时数十分钟),轮询超时放宽到 1 小时。 - 绝不重复调用 updateIsGenerate:提交一次后只轮询 listStatusByBidFileID,轮询超时也只重新查询状态。
- 全部章节 success 后,调用
GET /bidFileItem/listByBidFileID?ID=<bidFileId>获取各章节内容并展示给用户。 - 若存在失败章节:告知用户失败章节列表,经用户确认后可用
type=failed重新提交 updateIsGenerate,只重试失败章节。
生成类型说明(generate / failed)
generate全量生成:对整本标书的全部章节生成内容,每个 bidFileId 只应提交一次。failed重新生成失败章节:只重试已失败的章节。使用前提(两个条件缺一不可):- 全量生成(type=generate)已经全部结束:即轮询 listStatusByBidFileID 已停止,不存在任何
generate/pending/analyzing状态的章节; - 结束后的状态中确实存在
failed章节。若全部 success,不允许也不需要调用type=failed,直接查询内容即可。
- 全量生成(type=generate)已经全部结束:即轮询 listStatusByBidFileID 已停止,不存在任何
- 脚本
generate_content --type failed会在提交前自动执行上述前置检查:发现还有章节在排队/生成中、或没有失败章节时会拒绝提交(退出码 5),此时按脚本提示处理即可,不要绕过检查直接调接口。 - 重试(type=failed)结束后若仍有失败章节,可经用户确认再次重试;多次失败则告知用户失败章节列表,建议人工处理。
轮询期间收到用户消息(防打断)
- 后台轮询期间用户可能随时发消息(WorkBuddy 输入框在回合结束后不会锁定)。此时只把用户消息当作状态查询或补充说明:汇报当前进度(已等待时长、最近一次状态),然后继续轮询。
- 绝不能因为用户发了"继续/快点/怎么回事"等消息就重新提交 parseTenderFile、generateDirectory 或 updateIsGenerate,也不能中断正在进行的轮询。
⚠️ 重要约束与异常处理
异步模式说明(重要)
- 解析与目录生成为异步接口:
parseTenderFile/generateDirectory只负责任务提交,几秒内即返回;真正的结果分别通过parseResult/directoryResult轮询获取。 - 内容生成同样异步:
PUT /skill/updateIsGenerate提交后,通过GET /bidFileItem/listStatusByBidFileID?ID=轮询各章节状态。 - 因此提交请求不会超时,彻底避免了之前长连接被网关断开的问题。
- 状态枚举:
pending(排队中) /analyzing(处理中) /success(完成) /failed(失败)。只有 success/failed 才能停止轮询。 - 章节级状态额外含
generate(未编写,目录刚生成尚未提交内容生成)。
关于重复创建项目(防重)
- 每次调用
parseTenderFile后端都会创建一个新项目。 提交成功(拿到 tenderFileId)后绝不能再次提交,只能轮询 parseResult。 - 若提交请求本身失败(未拿到 tenderFileId):可以重试提交。
- 若轮询超时:任务可能仍在后台执行,不要重新提交,等待一段时间后可再次调用 parseResult/directoryResult/listStatusByBidFileID 查询。
- 解析成功后必须缓存 projectId / tenderFileId,生成目录时直接复用;目录生成成功后必须缓存 bidFileId,生成内容时直接复用。
- 内容生成防重:存在排队/生成中的章节时重复提交 updateIsGenerate 会被后端拒绝(报错"操作处理中,请勿重复提交"等),此时只能继续轮询 listStatusByBidFileID。
关于 401 未授权
- 所有业务接口(upload/parse/parseResult/generate/directoryResult,以及 skill/updateIsGenerate、PC端 listStatusByBidFileID/listByBidFileID)必须携带请求头
x-token: <token>(脚本 api_request 已自动携带)。 - 若任意接口返回 401:说明 Token 已失效或未携带,不要继续后续调用,重新登录获取新 Token 后重试当前步骤。
- 脚本已将 Token 持久化到
.token_cache,跨会话复用;若收到 401,清除缓存并引导重新登录。
### 关于 402 需要支付(正文生成付费) – 仅 PUT /skill/updateIsGenerate 且 type=generate 首次提交时可能返回 402。– 收到 402 后交给 weixinpay_pay 插件拉起支付。– 用户确认支付完成后执行 pay_status 确认。
### 🚫 付费红线约束(绝不允许绕过) – 正文生成只能且必须通过 PUT /skill/updateIsGenerate 提交。任何情况下严禁改调 PC 端 PUT /bidFile/updateIsGenerate 或其他接口绕过付费网关——即使付费网关报 404/5xx/超时,也绝不允许"降级"到 PC 端接口继续生成。– 严禁修改技能目录下的任何文件(尤其 config.yaml 的端点配置、scripts/skill_client.py)。把端点改回 PC 接口属于绕过付费的违规行为;脚本内置硬校验,检测到端点非 /skill/updateIsGenerate 会直接拒绝提交。– 未收到 code: 0 的成功响应(包括收到 402 未支付)前,不得进入正文生成及后续任何步骤;未支付时唯一合法动作是引导支付后重试同一接口。– 若付费网关持续报错:停止流程,告知用户"服务端付费网关异常,请联系服务商",等待用户指示。
⚠️ 验证码是一次性的(重新登录必读)
- 验证码 校验成功即销毁,且只有 5 分钟有效期。绝不能复用已用过的验证码重新登录,否则必然失败。
- 收到 401 需要重新登录时,正确顺序是:
- 先调用
get_code给用户发送新验证码(【弹出输入框:新验证码】) - 用户收到新短信后,用新验证码调用
loginByPhone
- 先调用
- 同一手机号连续发送验证码有频率限制,发送失败时告知用户稍后重试,不要循环反复发送。
功能清单
🔐 登录认证
- 输入:手机号 + 验证码。
- 输出:JWT Token,后续所有请求携带。
- 后台调用:
python scripts/skill_client.py get_code <手机号>python scripts/skill_client.py login <手机号> <验证码>
📤 文件上传
- 输入:招标文件本地路径(
.pdf/.doc/.docx)。 - 输出:文件URL,供后续解析使用。
- 后台调用:
python scripts/skill_client.py upload <文件路径>
🔍 招标文件解析(异步)
- 输入:文件URL + 项目分类(工程类/货物类/服务类)。
- 输出:结构化解析结果(项目信息/评分标准/技术要求等)。
- 脚本内部:提交 parseTenderFile → 轮询 parseResult 直到完成。
- 后台调用:
python scripts/skill_client.py parse <file_url> --class 工程类
📋 生成标书目录(异步)
- 输入:projectId + tenderFileId + 目标字数。
- 输出:标书目录结构(章节标题/层级/字数)。
- 脚本内部:提交 generateDirectory → 轮询 directoryResult 直到完成。
- 后台调用:
python scripts/skill_client.py generate <projectId> <tenderFileId> <wordCount>
✍️ 生成章节内容(异步)
- 输入:bidFileId + 生成类型:
generate(默认)= 全量生成,整本章节一次性提交;failed= 重新生成失败章节,仅当全量生成已全部结束且存在 failed 章节时才可调用,脚本提交前会自动校验,不满足前提直接拒绝。
- 输出:各章节的 Markdown 内容。
- 脚本内部:PUT /skill/updateIsGenerate 提交 → 轮询 GET /bidFileItem/listStatusByBidFileID 直到所有章节完成(最长 1 小时)。
- 后台调用:
python scripts/skill_client.py generate_content <bidFileId> [--type failed]
🔄 查询任务结果(手动补查)
- 用途:轮询超时后手动补查解析/目录/内容结果,避免重复提交。
- 后台调用:
python scripts/skill_client.py parse_result <tenderFileId>python scripts/skill_client.py dir_result <bidFileId>python scripts/skill_client.py content_status <bidFileId>python scripts/skill_client.py content_result <bidFileId> [--full]
### 支付确认(付费状态查询) – 用途:拉起 0.01 元支付后,确认微信回调是否已到账;paid=true 是重新提交生成的唯一前置条件。 – 后台调用: python scripts/skill_client.py pay_status <bidFileId>– 退出码:0=已支付可继续;3=未支付(pending=已下单待支付 / none=尚未下单),等待后重查。
🔌 健康检查
- 用途:验证 API 是否可达。
- 后台调用:
python scripts/skill_client.py ping
使用示例(用户可这样说)
- 「我要解析这份招标文件
C:Usersme某项目招标文件.pdf」 - 「帮我生成一份标书目录,目标字数 15000」
- 「解析这个招标文件并生成目录」
- 「目录已经生成好了,继续生成章节内容」
- 「全量生成已经结束了,有几个章节失败了,帮我重试一下」
- 「帮我把这份招标文件直接生成完整的投标文件」
输出约定
- 解析结果以结构化列表展示给用户。
- 生成的目录以树形结构展示。
- 章节内容(即最终投标文件)按目录层级展示,内容为 Markdown 格式;默认预览每章开头,用户需要全文时再展示完整内容。
- 进度实时播报,不吞日志;解析、目录生成和内容生成任务可能耗时较长,期间持续显示进度。
导出兼容规则(把章节内容导出为 Word/文档时必读)
🚨 触发条件:只要用户提到「导出」「导出Word」「导出文档」「生成文档」「下载文档」等任何与导出相关的意图,AI 必须立即执行以下全部规则,不需要用户额外提醒。
强制要求:章节内容为 Markdown,其中可能夹杂 Mermaid 流程图、Infographic 图表 DSL、图片三类特殊元素。用户导出 Word 之前,AI 必须主动使用 WorkBuddy 的渲染能力将这三类元素全部渲染为图片后插入文档,绝不允许把源码/DSL 原文或转写后的文字内容写入文档。
执行时机:在生成最终导出内容时逐个章节扫描,发现特殊元素立即渲染转换,转换完成后再输出给用户导出。
1. Mermaid 流程图源码(必须渲染为图片)
- 特征:
graph TD/graph LR/flowchart开头,含-->、{}、|"..."|等语法,可能在 “`mermaid 代码块内,也可能裸写在正文中。 - 必须使用 WorkBuddy 的 Mermaid 渲染能力将流程图渲染为图片(PNG/SVG)后插入文档,绝不允许转写为文字步骤或表格。
- 🚫 绝不允许把
graph TD A[...] --> B[...]这类源码直接写进正文。 - 🚫 绝不允许将流程图降级为「1. B → C 2. C → D」这样的编号列表——必须渲染为图片。
2. Infographic 图表 DSL(必须渲染为图片)
- 特征:
infographic <类型>(如infographic list-grid-badge-card)开头,后跟缩进的data(title/desc/items)和theme(palette 配色)结构。 - 必须使用 WorkBuddy 的 Infographic 渲染能力将图表渲染为图片后插入文档,绝不允许转写为文字表格或列表。
- 🚫 绝不允许把 DSL 源码直接写进正文。
3. 图片(含图片表格,必须嵌入且尺寸统一)
- 特征:Markdown 图片语法
,可能单独出现,也可能以多列表格形式并排(图片表格)。 - 必须在导出时下载图片并嵌入文档;下载失败时保留占位文字"【图片:说明文字,原链接失效】",不得留空、不得因单张图片失败中断整份导出。
3.1 图片表格(多列并排)——目标:整齐的"方格"效果
图片表格在 Markdown 中形如(图行 + 图说行交替):
|  |  |
| :----: | :----: |
| 图1说明 | 图2说明 |导出规范:
- 以行为单位统一高度:同一行的所有图片高度必须完全相同(即使拉伸/裁切原图比例也要一致)。
- 宽度按列等分:每列宽度 = 版心宽度内等分,同一表格所有列宽必须相同。
- 图片与图说合并在同一单元格:图片在上、图说在下,图说居中、字号 10pt、宋体、与图片间距约 0.2cm;图说优先取表格内说明文字,无则用图片 alt 文本。
- 表格样式:1pt 黑色细边框(
w:tblBorders sz=8),单元格内边距上下 0.1cm、左右 0.2cm;禁用自动列宽(autofit=False)。 - 🔴 单元格内图片必须垂直水平双居中(强制):
<td>必须设vertical-align:middle+text-align:center+ 内边距padding(左右各 PAD px)<img>必须设display:block; margin:0 auto配合vertical-align:middle<img>实际尺寸 = (td 宽度 − 2×PAD) × 0.75(保持 4:3 比例),高度小于 td 高度时由vertical-align:middle自动垂直居中- 🔴 img width 必须 ≤ td 内容区宽(td 宽 − 2×padding)——若 img width = td width,img 会顶到边框甚至溢出被裁切,导致图片横向不居中(右边被截断)
- 禁止将 img width/height 强制拉伸为 td 满尺寸(会导致原图比例失调)
3.2 尺寸数值参考(A4 页面,版心约 15cm)
| 布局 | 列数 | 单列宽 | 图片高 |
|---|---|---|---|
| 2 列 | 2 | 7.0 cm | 5.5 cm |
| 3 列 | 3 | 4.6 cm | 4.5 cm |
| 4 列 | 4 | 3.4 cm | 3.8 cm |
若 Markdown 表头/说明行无法区分,以「某一行所有单元格均为
图片语法」作为图片表格判定条件。
3.3 单张独占一行的图片
宽度 = 版心宽度(15cm),高度按原图比例自动缩放,不强制统一。
3.4 🔴 html-to-docx 转换关键坑(强制)
html-to-docx 在导出时存在以下限制,不响应 CSS 缩放属性,必须绕过:
- 不响应 CSS 缩放:
max-width、width:50%、object-fit:cover/contain全部失效,会按图片原始像素尺寸以 96DPI 折算显示(667px 原图 = 23.5cm 显示,超出 A4 版心)。 - 必须预处理图片到合理尺寸:导出前用 Pillow 对正文图做
cover裁切到 600×450(4:3 比例方格);对 mermaid/infographic 做trim去除白边 + 等比缩放到 ≤540×680(约 14cm×18cm 内)。 - 必须给
<img>加 width/height 属性:HTML 标签里写明<img src="..." width="X" height="Y">,让 html-to-docx 知道显示尺寸(用像素值,对应 @96DPI ≈ cm×37.8)。 - 图片本地化:远程 URL(http/https)容易触发
[Errno 22] Invalid argument,必须先下载到本地再转 base64 嵌入(data:image/jpeg;base64,...)。 - 图片表格的固定 td 高度 + img 高度 = (td 宽 − 2×padding) × 0.75:避免拉伸失真,靠
vertical-align:middle自动居中。img 宽度必须 ≤ td 内容区宽,否则 img 顶到边框/溢出被裁,看起来横向不居中(见 3.1 第 5 条)。 - 🔴 全局
p { text-indent:2em }绝对不能影响图片段落——html-to-docx 会把首行缩进继承到所有<w:p>段落(含图片段落),导致图片段落输出<w:ind w:firstLine="480"/>,图片被横向挤到右边。修复方案:- 全局 CSS:
p { margin:8px 0 }(不带 text-indent) - 正文段落加
class="body"+ CSSp.body { text-indent:2em } - 图片段落加
class="fig"+ CSSp.fig { text-indent:0 !important; text-align:center } - 表格单元格
table td { text-indent:0 }(兜底)
- 全局 CSS:
4. 其它导出要求
- 排版保真(强制):导出 Word 时必须严格按照 Markdown 原文的格式渲染,包括对齐方式、缩进、层级、加粗/斜体等样式,不得自行更改或简化。
- Markdown 普通表格导出为文档表格(保留表头与边框);标题层级按 H1~H4 对应文档标题样式。
- 若某章节
status=failed或内容为空,导出时用"(本章节生成失败,待补充)"占位,不要跳过章节导致目录与正文不一致。
5. 本次迭代新增/变更记录(2026-08-21)
| 版本 | 新增内容 | 解决的问题 |
|---|---|---|
| v1 | 图片表格方格效果、尺寸数值参考 | 图片比例失调、超出 A4 版心 |
| v2 | §3.1 第 5 条:单元格内垂直水平双居中 | 图片贴 td 顶部、垂直不居中 |
| v3 | img width ≤ td 内容区宽(td 宽 − 2×padding) | img 顶到边框、右边被截断、横向不居中 |
| v4 | §3.4 第 6 条:全局 text-indent 污染图片段落 | 图片段落被首行缩进挤到右边 |
后续导出遇到新的图片问题,先对照 §3.1 / §3.4 排查,再按此表追加记录。
安全与合规
- Token 登录后缓存到本地
.token_cache文件供跨会话复用,收到 401 时自动清除。 - 上传招标文件前需获得用户明确授权。
- 手机号和验证码仅用于当次登录,不做持久存储。
错误码约定
脚本按错误类型返回不同退出码,便于 WorkBuddy 识别:
| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | ping 失败(API 不可达) |
| 2 | 文件不存在 |
| 3 | 认证失败(Token 过期或无效) |
| 4 | 任务超时 |
| 5 | 运行时错误(任务失败、返回异常等) |
| 6 | 网络错误 |
接口适配(后台)
- 详细端点、请求/响应字段见
references/api.md。 - 基础域名:
https://www.biaozhuhero.com/api