yumoqing 4092304726 feat(feasibility): P3可行性研究——opp_feasibility引擎(fp_estimate规则引擎FP/draft_feasibility八节报告/score_candidate评分/promote_to_project立项门禁)+report_type列(models/DDL/CRUD重生成)+详情页与PPT按类型选四节或八节模板(sections_for_type单一规则源)+列表类型徽标+prompt链路C+params/demand_mining字典种子+i18n词条
- fp_calc.calc()返回键实锤核对: total_fp/counts/errors(原total_ufp/by_type兜底猜错,已修)
- promote门禁修正: resolve_approval会把status置approved,confirmed只是中间态→门禁接受confirmed/approval_initiated/approved(原只认confirmed会导致审批通过后反而不能立项)
- _cluster_ctx补项目隔离(对齐_check_batch_visible口径)+全personal类别如实拒绝可行性样本不足
- 八节模板兜底节=需求规格;四节存量解析口径零变化
- opp_approvals CRUD手改(项目过滤)被xls2ui重生成吃掉→已checkout还原,只保留opp_reports新列部分
2026-09-14 09:03:58 +08:00

13 KiB
Raw Blame History

pipeline-opportunity — 商机产线能力包

把招标市场情报转化为软件研发商机:热点软件推荐 → 每日AI/Agent招标 → 研发报告编写 → 人工确认 → 研发审批流程。

平台边界(重要)

  • 数据爬取平台(ebpe.cc:/d/ymq/work/tender_opp,独立部署):采集中国招标网站数据、 持久存储、去重,仅通过内网 HTTP 只读接口对外(192.168.16.2:9085,X-API-Token 鉴权)。
  • 本模块(产线平台侧):商机业务闭环。只消费爬虫数据,不爬取、不存招标原始数据; 报告/审批状态落产线库 opp_reports / opp_approvals 表,绝不回写爬虫库。

依赖方向:产线平台 ──HTTP──> 数据爬取平台(单向)。

产线闭环与门禁

opp_hot_software / opp_daily_ai_tenders(爬虫平台数据)
        ↓ 选定方向
opp_create_report(草稿)→ opp_update_report(补写,数据必须来自工具返回)
        ↓
opp_submit_report ──> 人工确认任务(门禁,pipeline_human_tasks: opp_report_confirm)
        ↓ 人工确认通过(confirm 回流)
initiate_approval ──> 研发审批任务(门禁,opp_dev_approval)
        ↓ 人工审批结论回流
approved / rejected(rejected 可退回 draft 重来)

状态机:draft → confirmed → approval_initiated → approved/rejected(非法迁移一律拒绝)。 agent 禁止自批自审:确认与审批结论只能由人工任务回流驱动。

工具清单(主 agent / 驾驶舱)

工具 用途
opp_hot_software 热点软件推荐(招标量+预算+地区排名)
opp_daily_ai_tenders 每日 AI/Agent 招标展示数据
opp_search_tenders 关键词检索招标信息
opp_tender_detail 单条详情(含原文/预算/联系人/来源链接)
opp_crawler_stats 爬虫平台采集健康度
opp_create_report / opp_update_report 报告草稿创建与补写
opp_list_reports / opp_get_report 报告列表与全文
opp_submit_report 提交人工确认(门禁)
opp_list_approvals 审批单列表
opp_diagnose 产线诊断(报告分布/待办/爬虫连通性)
opp_start_mining 启动需求挖掘批次(后台:拉取→向量化→聚类→命名;scope=top 全量TopX / targeted 指定类型)
opp_mining_status 批次状态轮询(pulling/embedding/clustering/naming/done/failed+原因)
opp_list_clusters 类别排名表(热度/需求数/占比/命名证据)= TopX 热门需求类别
opp_cluster_detail 类内需求明细样例(每条带来源 URL 可查证)

角色:agent.opp_analyst(商机分析师)、agent.opp_writer(研发报告撰写工程师)。 slash 命令:/hot /ai /reports /oppdiag。 菜单:📊 研发报告 / ✅ 研发审批 / ⛏ 需求挖掘(批次→类别→明细三级下钻,2026-09-12)/ 📋 数据参考。

数据参考弹窗(三级下钻,2026-09-08 交互定稿)

菜单「📋 数据参考」→ opp_references_popup.dspy,三级结构全部整行点击(cursor:pointer, 无「查看分项」按钮):

  1. 汇总层(主题排名:招标/国内众包/海外三板块):点主题条目 → 弹出该主题分项列表 (opp_references_items / opp_demand_items / opp_overseas_items.dspy)。
  2. 分项层(明细条目):每条说明文字标注「来源:xxx」(source_text() 解析, 来源按钮已废弃删除);点条目 → 弹出具体内容(opp_item_detail.dspy: 爬虫平台 /api/tenders/{id} 全量字段 + 公告/需求全文 + 原文页/采集来源页按钮 + 附件列表)。
  3. 附件层:详情弹窗列出条目附件(爬虫平台 /api/tenders/{id}/attachments, 字段容错归一 normalize_attachment),「下载」按钮走服务端代理 opp_attachment_dl.dspy——先回查条目附件清单做归属校验(防 SSRF,前端传任意 att_url 不在清单内即拒绝),再按降级链取字节:记录 download_url → /api/attachments/{id}/download → 附件原始 url;代理失败如实报错不静默。

附件端点未就绪(爬虫平台附件子系统部署中)时:分项列表不显示 📎 角标、详情弹窗 显示「附件服务暂不可用」,其余功能不受影响。

研发报告列表/详情/成果文件下载(2026-09-09 用户需求改造)

菜单「📊 研发报告」由原 CRUD 裸表页(opp_reports/index.ui,无过滤+可增删改) 改为只读列表页 api/opp_reports_list.dspy,三点改造:

  1. 按项目 owner 过滤(list_visible_reports 单一事实源):
    • 挂项目的报告:当前用户是项目 owner(sd_projects.created_by==uid)才可见; agent 创建的项目(created_by LIKE 'agent.%',模式经 ${kw}$ 参数化—— SQL 字面量裸 % 会被驱动当格式化符炸 ValueError,实测踩过)降级为同机构成员可见 (对齐 check_project_owner 既有降级语义,不重复发明)
    • 未挂项目的报告(平台级调研,存量数据大多是这类):登录用户可见
    • 项目已删的孤儿报告:owner 无法验证 → 不可见(宁缺勿漏,LEFT JOIN 自然排除)
    • 详情/下载端点复用 check_report_visible(与列表同一规则,语义不漂移)
  2. 详情四节展示(opp_report_detail.dspy,整行点击下钻,范式同 opp_references_items): 报告正文按四节模板解析(parse_report_sections)——## 研发场景 / ## 输入 / ## 输出 / ## 成果,逐节 MdWidget 渲染;兼容带序号/冒号/加粗的标题变体, 三级标题不误判,重复同名节拼接不丢内容。旧报告(无四节标题)全文归「输出」节, 空节如实显示「本报告未填写此节」不编造。agent 写报告的四节模板硬要求已写进 OPP_PROMPT + opp_create/update_report 工具描述 + opp-workflow 技能。
  3. 成果文件多个列出、逐个下载(list_report_files + opp_report_file_dl.dspy): 文件范围 = 项目工作空间 deliverables/ 全部文件 + 报告 PPT(ppt_path, 按 realpath 去重)。下载安全模型对齐 opp_attachment_dl:前端只传 report_id + name,服务端回查清单命中才给文件,文件名绝不参与路径拼接 (清单只来自目录列举+ppt_path,../ 穿越名在清单里不可能出现)。

CRUD 页(opp_reports/ opp_approvals/)保留供后台运维直接编辑,菜单入口不再暴露。

爬虫平台接入配置

系统级配置禁硬编码,走 appbase params 表(兜底默认值内网地址):

params 键 值
tender_api_base http://192.168.16.2:9085(默认)
tender_api_token 爬虫平台 state/api.env 中的 TENDER_API_TOKEN

部署(宿主 = pipeline-app)

  1. git clone 到 <APP_ROOT>/pkgs/pipeline-opportunity
  2. bash build.sh(建表 + 种子数据 + wwwroot 软链 + pip install)
  3. app 入口已接线:load_pipeline_opportunity()(try/except 兜底)
  4. RBAC:cd <APP_ROOT> && py3/bin/python pkgs/pipeline-opportunity/scripts/load_path.py
  5. i18n:合并 i18n/{zh,en}/msg.txt 到宿主 wwwroot(merge_i18n.py),调 /i18n_getmsgs 刷新
  6. 重启应用;浏览器验证驾驶舱 /pipeline-opportunity/agent

表

  • opp_reports:研发报告(software/title/content/status/confirm_task_id/confirmed_by)
  • opp_approvals:研发审批(report_id/status/note/resolved_by)
  • opp_mining_batches:需求挖掘批次(org_id+project_id 隔离,project_id 空=平台级挖掘; scope=top/targeted;状态机 pulling→embedding→clustering→naming→done/failed; stats_json 进度统计;error_msg 可行动报错)
  • opp_demand_snap:需求快照(batch_id+src_id 去重;cluster_id 聚类回填;embed_status)
  • opp_clusters:需求类别(heat_rank 热度排名/share 占比/naming_evidence 命名证据/centroid_snap_id)

挖掘结果的项目可见性口径与 opp_reports 对齐(2026-09-12 用户确认挖掘也分项目): 挂项目的批次仅本项目会话可见;平台级批次(无项目会话发起)本机构登录可见; 无当前项目的会话只见平台级批次。_check_batch_visible 是单一规则源 (mining_status/list_clusters/cluster_detail 三层复用,E2E 11 项断言实测全过)。

需求挖掘架构(P1,2026-09-11)

众包需求(爬虫平台 record_type=demand)→ 语义聚类 → TopX/指定类型分析:

  • embedding 走模型调用:rag /rag/api/embed.dspy(凭据单点 rag_engine_configs) ← pipeline_service.rag_client.rag_embed_texts(project_id)(Bearer,10条/批)。
  • 向量与近邻压给 VDB(Milvus)(upapp.rag-vdb):kNN=/v1/query+vector+pagerows; 标量过滤=expr;协议细节见技能 rag-module-operations。
  • 两层 collection:共享缓存 opp_demand_emb_cache(基础数据全机构共用, 一条需求只嵌一次)+ 批次工作集 opp_mine_<batch16>(分析结果按批次隔离, 每机构保留最近 opp_mine_keep_batches 个,旧批自动 drop)。
  • 聚类算法:kNN(top30) + τ阈值(默认0.75) + 纯 Python 并查集(零原生依赖, 确定性可复现);>150 条大簇质心二次细分(τ+0.10,防众包模板标题过度聚合—— 2075条实测 τ=0.75 拐点:42簇 top1=8.2%);小组(<5)质心并入最近大簇或归其他。
  • LLM 只做簇命名(llm_call purpose=utility 60s 短超时),失败规则兜底(高频词)。
  • 机构隔离(用户定夺):基础数据共享、分析结果隔离——批次/快照/类别挂 org_id, 查询强制过滤(E2E 伪 org 拒绝实测通过)。
  • 算法参数全走 appbase params 表:opp_mine_tau/topk/min_cluster/big_split/keep_batches、 opp_embed_batch、opp_emb_cache_col(代码默认兜底)。
  • 验证脚本:scripts/p0_probe_vdb_embed*.py(VDB/embed 协议探测)、 p1_cluster_analyze.py(多τ对比+缓存,调参用)、p1_create_tables.py(幂等建表)。

可行性研究(P3,2026-09-14)

挖掘类别 → 可行性研究 → 评分 → 立项(report_type=feasibility 八节报告):

  • opp_feasibility.py(引擎):
    • fp_estimate:功能点估算。LLM 只提供结构化功能清单 (name/type=EI|EO|EQ|ILF|EIF/det/ret/ftr/evidence/confidence), 复杂度判定与 FP 加权全部走规则引擎 fp_calc.py (pipeline-core skills_library/all/function-point-counting/,部署位 skills/global/,进程内 importlib 加载;加载失败如实报错,绝不 LLM 心算 FP)。 返回键对齐 fp_calc.calc() 实际输出:total_fp/counts(→by_type)/errors/pending。
    • draft_feasibility(cluster_id):类别须已完成共性提取(normalize done)且有 core/ext 标准需求(全 personal 时如实拒绝"可行性样本不足")。FP 输入=每条 核心/扩展标准需求映射 1 ILF+1 EI+1 EQ(DET 按证据原子数粗估);成本=FP× opp_fp_pm_per_fp(默认0.05人月/FP)×opp_cost_wan_per_pm(默认3.0万元/人月), params 可配。LLM 只写三节叙述(架构与可行性/商业价值/风险),其余五节用 挖掘真实数据拼装。落库 opp_reports(report_type=feasibility)。
    • score_candidate(cluster_id):规则评分=需求热度40%(log 规模防大簇垄断)+ 共性集中度35%(core+ext 覆盖文档占比)+规模适配25%(标准需求 8-25 个最佳)。
    • promote_to_project(report_id):立项门禁——仅 report_type=feasibility 且 过人工确认(status∈confirmed/approval_initiated/approved)且审批单 approved 才可建 sd_projects(pipeline=opportunity_general,project_type=demand_mining, 字典种子在 init/data.json)。agent 不能自批自审。
    • 项目隔离:_cluster_ctx 对齐 _check_batch_visible 口径(批次挂项目的仅 同项目会话可见,平台级批次本机构可见)。
  • 八节模板(report_type=feasibility):`## 市场需求 / ## 共性需求 / ## 需求规格 /

    架构与可行性 / ## FP与成本 / ## 商业价值 / ## 风险 / ## 结论建议`。

    sections_for_type(report_type) 是单一规则源:详情页(opp_report_detail.dspy) 与 PPT(opp_ppt.py FEASIBILITY_ORDER)按类型选四节/八节渲染; research 报告四节模板不变,存量报告解析口径零变化。
  • opp_reports.report_type 列(VARCHAR(16) DEFAULT 'research'): 测试机/生产走 pipeline-app deploy/migrations/m0030_opp_reports_report_type.json (dmig apply,幂等 ADD COLUMN);models/opp_reports.json 已同步(新建表天然带列)。
  • 报告列表标签:opp_reports_list.dspy 行内加类型徽标(调研=蓝/可行性研究=紫)。
  • PPT 文件名区分:feasibility_report__.pptx。
  • 4 个新工具注册进 OPP_HANDLERS(opp_fp_estimate/opp_draft_feasibility/ opp_score_candidate/opp_promote_to_project),OPP_PROMPT 加「可行性研究与立项」 流程段;opp-workflow 技能同步(链路C)。

技能

产线技能在 pipeline-core 技能库:skills_library/pipelines/opportunity_general/ (common/opp-workflow 总纲 + roles/agent.opp_analyst、agent.opp_writer 角色技能)。