19 KiB
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.6,2026-09-17):标准投标流程内置与纯技术方案
流程同源的三段链 tech_analysis(六类技术评估项,对标招标文件技术需求部分)→ tech_qc (qc_type=tech_items)→ template_confirm(PM 检索模版按评估项裁剪骨架 → 用户确认待办)。
对账器共用段 _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 生成真实图片(
嵌入,合成 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 建表未进 models,2026-09-10 归籍) | project_id, kind, category, item_name, amount, confidence |
bid_tech_items |
技术评估项(纯技术方案流程与标准流程 A3 裁剪链 tech_analysis 产出;kind=item/summary,summary=骨架裁剪摘要行,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 → 派 scorerbid_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_note(m0039)。
- 投标钩子(
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 QC→PM 模版裁剪→用户确认骨架→技术章重写;商务/报价章 零接触;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 pending→confirm→v1 superseded/钩子九项效果/审计);甘肃真实项目 detect 判 tech_analysis(high 置信度, 依据=用户意见+进度「技术评估项0行、裁剪链未完成」)→修订确认待办已发。
load 注册函数
宿主入口(pipeline_app.py)两步,缺一不可:
from pipeline_bidding.init import load_pipeline_bidding
load_pipeline_bidding() # import 后必须再显式调用,漏了无任何日志(静默大坑)
load_pipeline_bidding()(幂等)做三件事:
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 零变化)。import bid_ability— 主 agent 能力包 + slash 命令注册(import 即注册)。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)根目录或本目录执行一键脚本:
./build.sh
build.sh 职责(运行期禁止 schema 变更,建表只在部署期):
- 建表:读
mysql.ddl.sql(json2ddl 产物),把drop table if exists剔除、CREATE TABLE改为CREATE TABLE IF NOT EXISTS幂等化,用宿主 config 的pipeline库连接执行。 - 种子数据:
init/data.json幂等写入 pipelines 产线记录 + appcodes/appcodes_kv 码表。 - wwwroot 软链:
ln -sf 本仓库/wwwroot → $APP_ROOT/wwwroot/pipeline-bidding。 - 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。
部署注意(实测踩坑)
- 非 editable 安装:测试机只
git pull仓库不会更新 site-packages,改码后必须./py3/bin/pip install pkgs/pipeline-bidding再重启(可对比 site-packages 与仓库文件 md5 确认加载版本)。 - 运行时技能树独立仓库:在
/d/pipeline/pipeline-app/skills/(git: yumoqing/pipeline-sdlc.git),不是 pipeline_core 的 skills_library;改了 bid-workflow 等技能必须同步 SKILL.md 到pipelines/bidding_general/common/<技能名>/再重启。 - 宿主入口漏调用
load_pipeline_bidding()是静默大坑:无任何日志。诊断走api/bid_probe.dspy?action=status心跳探针。 - RBAC 缓存:新路径注册后 redis db0 FLUSHDB 即生效(旧说须重启已过时); 精确 path 匹配,父路径不覆盖子路径。
- 角色任务 failed 必须是对账器阻塞态:否则每 15s 重复造任务(机构未配 LLM 时必现); 测试环境无 LLM 模型时任务 failed 属预期。
- 自动立项的项目不继承模型:不带 default_model,解析链兜底全局默认名可能不存在 → 401;
建后必查/补
sd_projects.default_model。 - bid_chapters 键归一:
resolve_project_id先按 id 校验、按 name 反查归一, 名字歧义拒绝(防「项目名当 project_id」写库产生孤儿骨架)。 - 对账器结构铁律:维度过滤(等上游 QC 的不算掉链)必须在
_open_orch_tasks判定前 无条件执行,编排任务创建/掉链计数留在「无编排任务在办」的 else 分支内, 否则每 15s 重复建编排任务堆积。 - 共享工具
create_task有产线角色校验守卫(get_role_spec 查不到即拒绝),list_roles查看本产线可用角色。
详细设计见 docs/DESIGN.md;技能库见 pipeline-core
skills_library/pipelines/bidding_general/(common 7 技能 + roles 9 角色含 bid_biz_writer)。