244 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# pipeline-bidding — 投标产线模块
## 模块定位
产线平台pipeline-app / pipeline-core的第二条产线能力包**投标产线 `bidding_general`**。
验证并落地「产线能力包住自己仓库、宿主不装则零接触」的分层原则——能力模块全部住在本仓库,
不进 `pipeline-service`;宿主只要不 `import pipeline_bidding`,一切都不会发生。
模块 = 数据(`bid_*` 表 + CRUD+ 能力(`bid_*_capability`+ 流转(`bid_flow` 状态对账器)
+ 主 agent 能力包(`bid_ability`+ 角色技能(部署期随 pipeline-core skills_library 分发)。
**产线起点 = 上传招标文件**`import_tender_file` 无 project_id 时自动立项)。阶段链:
> 收到招标文件(自动立项)→ 解析(评分项/资质/投标文件要求/商务要素/章节骨架)
> → QC 契合度审核四类逐类10 分制,>9.5 放行)→ **技术方案部分模版裁剪链A3 段,
> 2026-09-17 起)** → 资料准备 → 分角色并发编写
> business→bid_biz_writer / technical→bid_writer→ 章节评审(含篇幅门禁)→ 合成
> → 整书评分 → 交付确认。
**A3 段标准流程技术标模版裁剪链v1.62026-09-17**:标准投标流程内置与纯技术方案
流程同源的三段链 `tech_analysis六类技术评估项对标招标文件技术需求部分→ tech_qc
qc_type=tech_items→ template_confirmPM 检索模版按评估项裁剪骨架 → 用户确认待办)`
对账器共用段 `_reconcile_tech_analysis_qc` / `_reconcile_template_confirm`(两条流程逻辑
只此一份flow_key 写进任务 params 区分来源)。**链激活五条件**:有招标文件 +
tech_analysis/template_confirm 两阶段启用 + 骨架维度 QC 已过 + 存在 technical 章且全部
pending + 无裁剪摘要行(`bid_tech_items kind='summary'`)——任一不满足整链跳过,技术章
直接按招标骨架编写(存量项目零影响)。链激活期间 C 段只挡 technical 章(`_tech_gate_on`
商务/报价章照常流转;用户确认后 `confirm_tech_template` **标准模式只替换 technical 章**
(新骨架落原技术章 min(order_no) 位置,商务/报价章不动),并落 kind='summary' 裁剪摘要行
作为链完成的持久证据confirm 落库、新招标文件 reset 清除;不用 done 待办/章节状态判完成
——换代后会锁死新链或复活死循环。BID_FLOW_STAGES 扩为 14 阶段(+tech_analysis
trim=yes / tech_qc trim=warn / template_confirm trim=warn裁 tech_analysis 必连带裁
template_confirm。tech 维度不进 ANALYSIS_DIMS、不走 PM 编排,由对账器直接派发。
**多流程模板2026-09-15 批2**:本产线声明两条流程(`BID_FLOW_TEMPLATES`,引擎
FlowTemplate 机制首个接入)——`bid_standard`(上述标准链)与 `bid_tech_proposal`
**纯技术方案流程**:输入=技术需求书而非招标文件,产出=技术方案书):
> 技术需求书 → 六类技术评估项解析(功能清单/功能点/硬件配置/技术架构/功能架构/部署架构,
> 落 `bid_tech_items`)→ QC 对标需求书qc_type=tech_items→ 模版三级检索知识库→RAG→网络
> + 骨架拟定(六类覆盖度硬校验,漏类拒绝)+ **用户确认待办**tech_template_confirm全局阻塞
> agent 无确认权)→ 分章编写 → 章节评审(对标需求书覆盖度)→ 合成 → 交付确认。
首文件导入后对账器 LLM 自动判流(`detect_flow_template`,置信度+判据摘录进确认待办);
判流失败发人工待办不默认硬跑。已确认计划 `base_flow_key=bid_tech_proposal` 的项目走
`bid_flow._reconcile_tech_proposal` 独立对账分支,不碰评分项/资质/成本收益。
规范见技能 `bid-tech-proposal`;确认端点 `api/tech_template_confirm.dspy`
核心机制:
- **角色任务流转不用 RoleSpec.next_role**(全留空):投标是「一章一任务 + 两级回退循环」
扇出结构,由 `bid_flow` 状态对账器(每 15s 一轮)补派,对账器是角色任务的**唯一创建者**。
- **阻塞门禁在创建源头**(对账器判 `pipeline_human_tasks.project_id + pending`
不写进引擎 poller SQL。`tenant_id=project_id` 只是角色任务约定,禁止写进引擎层。
- **两级回退循环**:章节级(得分率 < `bid_chapter_pass_ratio` 或篇幅不达标 rejected+意见
自动重写 `bid_max_revise` 抛人工整书级< `bid_pass_ratio` 或否决项未响应
`target_chapter_id` 打回 重写重审重合成重评分 `bid_max_round` 抛人工)。
- **QC 门禁**四类解析产出逐类审核落 `bid_qc_reviews`不通过 清空该类产出 对账器重派
解析`params.qc_redo=1` + 改进意见)→ 重审轮次超 `bid_qc_max_round` `qc_escalation`
阻塞人工逃逸阀人工修产出后在记录页把 passed 1 即生效)。
- **门限参数全部读 appbase `params` + DEFAULT_PARAMS 兜底**不硬编码
`bid_chapter_pass_ratio`(0.8) / `bid_pass_ratio`(0.85) / `bid_max_revise`(3) /
`bid_max_round`(3) / `bid_qc_pass_score`(9.5) / `bid_qc_max_round`(3) /
`bid_chapter_min_words`(800) / `bid_chapter_min_words_biz`(500) / `bid_write_concurrency`(4)。
- **章节配图形态硬门禁2026-09-15 用户要求**技术方案/标书中的图必须 invoke_model
t2i/i2i 生成真实图片`![图N 标题](URL)` 嵌入合成 docx 自动嵌真图 mermaid/plantuml/
ASCII 字符画`write_chapter` 机制层确定性检测拒写伪图`review_chapter` 评审兜底同款检测必退
存量正文/绕行写入检测器复用 `pipeline_service.diagram_gate`ImportError 逃逸阀
豁免钥匙=文中如实标注「配图缺失:平台无可用文生图模型」(仅 t2i/i2i 全无时)。
## 表清单models/*.json建表产物 mysql.ddl.sql
| 表名 | 说明 | 关键字段 |
|---|---|---|
| `bid_tenders` | 招标商务要素 | project_id, source, title, purchaser, tender_no, industry |
| `bid_tender_files` | 招标文件 | project_id, tender_id, file_name, file_path, file_type, content_text |
| `bid_scoring_items` | 评分项与得分规则 | project_id, section, item_no, item_name, max_score, scoring_rule, is_veto |
| `bid_qualifications` | 招标所需资质 | project_id, qual_name, requirement, is_mandatory, owner, kb_doc_id, match_status |
| `bid_doc_requirements` | 投标文件要求 | project_id, req_type, chapter_no, chapter_title, requirement, page_limit, source_ref |
| `bid_chapters` | 投标文件章节 | project_id, chapter_no, parent_no, title, section, outline, status, content, word_count, review_score |
| `bid_reviews` | 标书评审记录 | project_id, scope, chapter_id, document_id, round, reviewer, review_type |
| `bid_scores` | 标书评分明细 | project_id, review_id, scoring_item_id, item_name, score, max_score, reason |
| `bid_documents` | 合成标书 | project_id, version, doc_name, file_path, page_count, chapter_count, total_score |
| `bid_qc_reviews` | 解析产出 QC 审核记录 | project_id, qc_type, round, reviewer, review_type, fit_score, pass_score |
| `bid_analysis_history` | QC 分析历史快照每轮 QC 逐审核记录归档2026-09-10 归籍补 models 定义此前是孤儿表 | project_id, qc_type, round, task_id, fit_score, improvement, payload |
| `bid_cost_benefit` | 成本收益分析分析维度4单项+summary 结论行m0006 建表未进 models2026-09-10 归籍 | project_id, kind, category, item_name, amount, confidence |
| `bid_tech_items` | 技术评估项纯技术方案流程与标准流程 A3 裁剪链 tech_analysis 产出kind=item/summarysummary=骨架裁剪摘要行category 六类m0034 建表 | project_id, kind, category, item_name, requirement, mandatory, source_ref |
| `bid_kb_docs` | 公司投标知识库 | org_id, doc_type(sample_bid ), doc_name, doc_no, tags, file_path, content_text |
| `bid_material_gaps` | 投标材料缺口清单占位符规范正文 `【材料待补:…】` 自动登记合成后出清单人工/产线补齐m0035 建表 | project_id, chapter_no, material_name, placeholder_text, fingerprint, status(pending/filled/waived) |
| `bid_members` | 投标项目参与人员 | project_id, user_id, user_name, member_role, duty, status |
种子数据`init/data.json`build.sh 幂等写入`pipelines` 产线主记录 `bidding_general` +
`appcodes` 12 组码表bid_qc_type / bid_tender_source / bid_member_role / bid_file_type /
bid_scoring_section / bid_qual_match_status / bid_qual_owner / bid_req_type /
bid_chapter_status / bid_review_scope / bid_kb_doc_type / bid_doc_status)。
## 对外 API / dspy 端点wwwroot/
部署后挂载在宿主 `wwwroot/pipeline-bidding/`软链
- **api/bid_probe.dspy** 服务内探针诊断)。`?action=status` 返回模块装载状态 +
poller 心跳 + 活跃投标项目数`?action=reconcile` 在服务进程内跑一轮全量对账返回动作明细
- **api/bid_task_tree.dspy** 任务树懒加载 role:阶段 任务 step:/del: 叶子)。
项目解析三级兜底session_settings(default_bidding_general) agent_settings
最近 in_progress 项目
- **api/bid_task_io.dspy** 任务树右侧详情面板输入 = 任务描述 + QC 改进意见
执行步骤输出 = 交付件(复用 `pipeline_service/task_io_render.py` 统一渲染规范)。
- **api/tech_template_confirm.dspy** 技术方案骨架用户确认/驳回端点2026-09-15
2026-09-17 双模式分流)。入参 human_task_id/decision(confirm|reject)/comment驳回必填)。
用户专属同机构+超管/创建者校验复用引擎 `_check_confirm_operator`agent 无对应工具无法代确认
确认后骨架落 bid_chapters(section=technical) 开写——**标准流程项目存在非 technical
只替换技术章并落 kind='summary' 裁剪摘要行商务/报价章原样保留纯技术方案流程整表清落**
驳回意见由对账器注入重派模版任务
- **api/bid_delivery_reject.dspy** 交付退回端点2026-09-17用户报障交付确认待办只有
确认没有退回后补)。入参 human_task_id/comment退回意见必填)。用户专属权限校验复用
`_check_confirm_operator`agent 无此工具退回是用户裁决)。机制 `reject_delivery`
待办置 rejected+意见存 result_data 最新 passed 标书置 rejected scorer
`bid_delivery_reject` 任务params.reject_comment)→ scorer 按意见 request_chapter_revise
打回问题章节 既有链路自动重写重审重合成重评分重发交付确认approved 章节
revise_count 复位用户级退回=新一轮修订预算)。对账器 E/T6 段配套门禁驳回处理任务
在办期间不派合成防章节还没被打回就抢先重合成同内容新版静默绕过用户意见)。
- **bid_task_tree_popup.ui** ResourceBrowser 复合 widget 弹窗左树右详情联动)。
- **agent/index.ui** 驾驶舱入口页顶栏含任务树按钮)。
- **12 CRUD 目录**bid_tenders / bid_tender_files / bid_scoring_items /
bid_qualifications / bid_doc_requirements / bid_chapters / bid_reviews / bid_scores /
bid_documents / bid_qc_reviews / bid_kb_docs / bid_members)— 每个含
index.ui + get/add/update/delete_*.dspy 标准五件套
RBAC 铁律`/api/` 前缀不覆盖具体 dspy** API 必须逐条显式注册**scripts/load_path.py
否则 403注册后 redis db0 FLUSHDB 即生效
## 流程修订 / 定向重做2026-09-17引擎通用机制 + 投标钩子)
用户裁定**用户有权调整流程并要求从流程的任何一步按照意见重做或者干脆只给意见
LLM 判定从哪个节点注入**。
- 引擎层pipeline-service flow_plan_capability产线无关
- `revise_flow_plan`对已 confirmed 计划提修订版v+1 pending_confirm确认前旧计划
持续生效无空窗确认时 CAS 换版旧版 superseded + 回调产线钩子执行阶段重置)。
可改裁剪trim_keys/或定向重做reentry_stage)。
- `detect_reentry_stage`用户只给意见时 LLM 判注入点意见+阶段声明+产线进度摘要
stage_key+confidence+evidence对齐 detect_flow_template 判流先例evidence 进确认
待办由用户核对错判由确认门兜住判不出诚实报错禁默认)。
- `_affected_stage_keys`注入阶段+deps 依赖闭包下游
- 会话工具 revise_flow_plan/detect_reentry_stage FLOW_PLAN_TOOLS shared_ability
三产线会话 agent 零改动继承propose_flow_plan 遇已确认计划时的错误指引改指 revise
- pipeline_flow_plans 加列 reentry_stage/reentry_detect_notem0039)。
- 投标钩子`pipeline_bidding/bid_stage_reentry.py` PipelineAbility 三钩子字段注册
- `bid_stage_reentry`按注入阶段重置——分析维度清产出表+QC 记录reqs_outline 连带毁
章节确认待办如实预告qc_analysis 单独注入只清五类 QC 记录产出保留自动重派复审
**tech 链重置(补技术方案场景)**= bid_tech_items summary+tech QC 记录+技术章
**置 pending 保正文**(⚠ 删章则 A3 链激活条件 bool(_tech_chs) 不成立永不激活正文
保留至模版确认时被新骨架整体替换+作废模版确认待办+技术章在办编写任务清场
LIKE ${kw}$ 参数绑定防 % 格式化坑+标书 rejected+交付待办 cancelled
A3 裁剪链重新激活抽取tech QCPM 模版裁剪用户确认骨架技术章重写商务/报价章
零接触chapter_write 清正文全复位/chapter_review 复位 written 保正文compose/score/
delivery 标书+待办作废统一收尾affected 阶段角色在办任务取消角色集运行时从阶段
声明取+材料缺口 pending 记录 waived 防孤儿+审计落库
- `bid_reentry_describe`影响说明破坏性预告进确认待办用户确认前看得到将清什么)。
- `bid_progress_summary`进度摘要章节分布/标书版本/tech_items summary 判定/
QC 记录/在办待办——detect LLM 上下文)。
- 钩子失败不回滚计划确认换版是用户裁决已生效)——诚实上报+抛人工待办
- E2E 实测2026-09-18 测试机合成项目防火墙全链断言过v2 pendingconfirmv1
superseded/钩子九项效果/审计甘肃真实项目 detect tech_analysishigh 置信度
依据=用户意见+进度「技术评估项0行、裁剪链未完成」→修订确认待办已发。
## load 注册函数
宿主入口pipeline_app.py两步缺一不可
```python
from pipeline_bidding.init import load_pipeline_bidding
load_pipeline_bidding() # import 后必须再显式调用,漏了无任何日志(静默大坑)
```
`load_pipeline_bidding()`幂等做三件事
1. `role_tool_schemas.register_role_tools()` 把约 60 个投标角色工具 schema
read_tender_file / extract_* / add_* / list_cost_benefit / update_cost_benefit_item /
delete_cost_benefit_item / patch_chapters / write_chapter支持 mode=append 分批追加超长章节/
review_chapter支持 material_missing=1 实体材料缺失如实披露放行/ start_qc / finish_qc /
compose_bid / start_bid_score /
finalize_bid_score / dispatch_analysis_dim 注册进引擎
`pipeline_service.capability_tools.TOOL_SCHEMAS`引擎 `exec_capability_tool`
`module` 支持全路径裸名仍走 `pipeline_service.*`SDLC 零变化)。
2. `import bid_ability` agent 能力包 + slash 命令注册import 即注册)。
3. `bid_flow.start_poller()` 状态对账器启动`PIPELINE_MODE=web` 时不注册
与引擎 poller 同款模式开关)。
角色工具装配链角色技能 frontmatter `capability+tools` `_capability_to_tools_map`
`TOOL_SCHEMAS` **两者交集才是可见工具**技能声明了但 schema 没注册 = 工具静默缺失)。
独立脚本验证必须先显式调 `load_pipeline_bidding()` import 包不触发注册
码表导入自持`scripts/import_init_bidding.py`幂等 + 废弃清理 + 产线描述
不依赖宿主 `import_init.py` INIT_MODULES
## 宿主集成(部署)
在宿主应用pipeline-app根目录或本目录执行一键脚本
```bash
./build.sh
```
build.sh 职责运行期禁止 schema 变更建表只在部署期
1. **建表** `mysql.ddl.sql`json2ddl 产物 `drop table if exists` 剔除
`CREATE TABLE` 改为 `CREATE TABLE IF NOT EXISTS` 幂等化用宿主 config
`pipeline` 库连接执行
2. **种子数据**`init/data.json` 幂等写入 pipelines 产线记录 + appcodes/appcodes_kv 码表
3. **wwwroot 软链**`ln -sf 本仓库/wwwroot → $APP_ROOT/wwwroot/pipeline-bidding`
4. **pip install**`$APP_ROOT/py3/bin/pip install 本目录` editable 安装)。
宿主负责的后续app 入口 import + 调用 `load_pipeline_bidding()`
RBAC `scripts/load_path.py`其中 set_role_perm.py 必须用宿主根**绝对路径**
i18n 合并用 merge_i18n.py
## 部署注意(实测踩坑)
1. **非 editable 安装**测试机只 `git pull` 仓库不会更新 site-packages改码后必须
`./py3/bin/pip install pkgs/pipeline-bidding` 再重启可对比 site-packages 与仓库文件
md5 确认加载版本)。
2. **运行时技能树独立仓库** `/d/pipeline/pipeline-app/skills/`git:
yumoqing/pipeline-sdlc.git不是 pipeline_core skills_library改了 bid-workflow
等技能必须同步 SKILL.md `pipelines/bidding_general/common/<技能名>/` 再重启
3. **宿主入口漏调用 `load_pipeline_bidding()` 是静默大坑**无任何日志诊断走
`api/bid_probe.dspy?action=status` 心跳探针
4. **RBAC 缓存**新路径注册后 redis db0 FLUSHDB 即生效旧说须重启已过时
精确 path 匹配父路径不覆盖子路径
5. **角色任务 failed 必须是对账器阻塞态**否则每 15s 重复造任务机构未配 LLM 时必现
测试环境无 LLM 模型时任务 failed 属预期
6. **自动立项的项目不继承模型**不带 default_model解析链兜底全局默认名可能不存在 401
建后必查/ `sd_projects.default_model`
7. **bid_chapters 键归一**`resolve_project_id` 先按 id 校验 name 反查归一
名字歧义拒绝项目名当 project_id写库产生孤儿骨架)。
8. 对账器结构铁律维度过滤等上游 QC 的不算掉链必须在 `_open_orch_tasks` 判定前
无条件执行编排任务创建/掉链计数留在无编排任务在办 else 分支内
否则每 15s 重复建编排任务堆积
9. 共享工具 `create_task` 有产线角色校验守卫get_role_spec 查不到即拒绝
`list_roles` 查看本产线可用角色
详细设计见 `docs/DESIGN.md`技能库见 pipeline-core
`skills_library/pipelines/bidding_general/`common 7 技能 + roles 9 角色含 bid_biz_writer)。