121 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

---
name: pipeline-opportunity
description: "商机产线能力包——招标市场情报(数据爬取平台)→热点软件推荐→每日AI招标→研发报告→人工确认→研发审批。含爬虫平台接入配置与工具清单。"
---
# pipeline_opportunity
商机产线能力包:把中国招标市场情报转化为软件研发商机。挂载到宿主应用(pipeline-app)即生效,
项目 `sd_projects.pipeline_id='opportunity_general'` 时自动启用全部工具。
## 平台边界(必读)
```
数据爬取平台 (ebpe.cc:/d/ymq/work/tender_opp) 产线平台 (本模块)
采集/存储/去重/只读查询 商机业务闭环
┌──────────────────────────┐ ┌──────────────────────────┐
│ ccgp+ggzy 采集 (30min) │ 内网HTTP只读 │ 热点推荐/每日AI招标 │
│ SQLite 持久 (1700+条) │ ←──────────────── │ 研发报告→人工确认→研发审批 │
│ http_api.py :9085 +token │ │ opp_reports/opp_approvals │
└──────────────────────────┘ └──────────────────────────┘
```
- 本模块**不爬取、不存**招标原始数据,只消费爬虫平台;报告/审批状态落产线库。
- 爬虫平台侧细节见其仓库 `BOUNDARY.md`/`README.md`(HTTP 端点 /api/tenders 等)。
## Architecture
```
pipeline_opportunity/
├── init.py # load_pipeline_opportunity()(幂等挂载)
├── opp_common.py # DB上下文/爬虫HTTP客户端/状态机/人工任务
├── opp_data_capability.py # 爬虫平台只读封装(热点/搜索/详情/每日AI/健康度)
├── opp_report_capability.py # 报告+审批状态机(draft→confirmed→approval→approved/rejected)
├── opp_ability.py # 12工具+prompt+2角色+4 slash 命令(PipelineAbility 注册)
├── wwwroot/ # opp_reports / opp_approvals CRUD 页面(xls2ui 生成)
├── models/ + json/ # DDL 与 CRUD 源
└── scripts/load_path.py # RBAC 路径注册
```
## 爬虫平台接入(配置不硬编码)
appbase `params` 表两个键(`opp_common.get_crawler_config` 读取,默认内网地址兜底):
| 键 | 值 |
|----|-----|
| `tender_api_base` | `http://192.168.16.2:9085`(内网网卡绑定,公网不可达) |
| `tender_api_token` | 爬虫平台 `state/api.env` 的 TENDER_API_TOKEN |
## 工具(主 agent,opp_ 前缀)
| 工具 | 用途 |
|------|------|
| `opp_hot_software(days,top)` | 热点软件推荐:招标量+预算+地区排名 |
| `opp_daily_ai_tenders(date)` | 每日 AI/Agent 招标展示数据 |
| `opp_search_tenders(keyword,days,source,limit)` | 关键词检索 |
| `opp_tender_detail(tender_id)` | 单条详情(原文/预算/联系人/来源链接) |
| `opp_crawler_stats()` | 爬虫平台采集健康度 |
| `opp_create_report / opp_update_report` | 报告草稿创建/补写 |
| `opp_list_reports / opp_get_report` | 报告列表/全文 |
| `opp_submit_report(report_id)` | 提交人工确认(创建门禁任务) |
| `opp_list_approvals` | 审批单列表 |
| `opp_diagnose` | 产线诊断 |
| `opp_start_mining(scope,keyword,category,days,sources)` | 启动需求挖掘批次(后台执行立即返回batch_id;scope=top全量TopX / targeted指定类型必带keyword) |
| `opp_mining_status(batch_id)` | 批次状态轮询(pulling/embedding/clustering/naming/done/failed+原因) |
| `opp_list_clusters(batch_id)` | 类别排名表(热度/需求数/占比/命名证据)= TopX 热门类别 |
| `opp_cluster_detail(cluster_id,limit)` | 类内需求明细样例(每条带来源URL可查证) |
角色:`agent.opp_analyst` / `agent.opp_writer`;slash:`/hot` `/ai` `/reports` `/oppdiag`。
## 状态机与门禁(不要绕过)
```
draft ──人工确认──> confirmed ──发起──> approval_initiated ──人工结论──> approved
↑ └ rejected ──> draft(可重来)
```
- 确认/审批都是 `pipeline_human_tasks` 人工任务(task_type: `opp_report_confirm` /
`opp_dev_approval`),结论由人工回流,agent 禁止自批自审。
- 非法迁移一律拒绝(`REPORT_TRANSITIONS`)。
- 报告中的招标数字必须来自工具返回的真实数据,禁止编造;引用带来源链接。
## 需求挖掘(P1,众包需求→语义聚类→TopX/指定类型)
```
众包需求(爬虫 record_type=demand)
→ 快照 opp_demand_snap(batch+src_id去重)
→ embedding(rag /rag/api/embed.dspy ← rag_client.rag_embed_texts Bearer,共享缓存collection一条只嵌一次)
→ 批次工作集 collection(VDB/Milvus, upapp.rag-vdb)
→ kNN(/v1/query+vector+pagerows) + τ阈值(默认0.75) + 并查集 → 大簇质心二次细分(>150)
→ LLM 簇命名(并发Semaphore5, utility purpose, 失败规则兜底)
→ opp_clusters(heat_rank/share/naming_evidence)
```
- **编排** opp_mining_flow.py:状态机 pulling→embedding→clustering→naming→done/failed,
`asyncio.create_task` 后台跑,进度实时落 `stats_json`,失败落 `error_msg`(可行动报错,
禁前端挂起干等)。**算法/VDB/embedding** opp_mining.py。
- **机构隔离 + 项目归属**(用户定夺 2026-09-12:挖掘也分项目):基础数据(需求快照+embedding缓存)
全机构共享;分析结果(批次/快照归属/类别)挂 `org_id` + `project_id`(空=平台级挖掘),
可见性对齐 opp_reports 口径——挂项目批次仅本项目会话可见,平台级批次本机构登录可见,
无项目会话只见平台级。`_check_batch_visible` 单一规则源三层复用(status/list_clusters/
cluster_detail),E2E 11 项断言实测全过(scripts/p1_proj_e2e.py)。
- **VDB 协议**(实测,详见技能 rag-module-operations):kNN=`/v1/query`+vector+pagerows
(非 /v1/search);标量过滤=`expr`(非 filter);kNN+expr 组合可用;output_fields 可取回
vector;dropcollection 可用(旧批工作集自动清理,保留最近 opp_mine_keep_batches 个)。
- **性能**:批量 LLM/embedding 一律并发+缓存禁串行(实测 42簇串行命名 540s→并发 60s)。
- **算法参数**走 appbase params(init/data.json params 段 build.sh 幂等种子):
opp_mine_tau/topk/min_cluster/big_split/keep_batches、opp_embed_batch、opp_emb_cache_col。
- **验证脚本** scripts/p1_cluster_analyze.py(多τ对比调参,向量/kNN文件缓存);
E2E 须 P1_PROJECT_ID=真实商机项目(owner→Bearer key),独立脚本要 initEnv() 注入
password_decode,凭据走环境变量(密码字面量会被秘密扫描替换成 ***)。
## 部署清单(宿主侧)
1. `build.sh`(建表+种子 appcodes/pipelines/params+wwwroot 软链+pip install)
2. app 入口 `load_pipeline_opportunity()`(已接线,try/except 兜底)
3. `scripts/load_path.py` 注册 RBAC
4. i18n 合并 `i18n/{zh,en}/msg.txt`
5. params 表配 `tender_api_base` / `tender_api_token`(挖掘依赖 embedding:rag 引擎
配置 rag_engine_configs + upapp.rag-vdb,复用宿主已部署的 rag/VDB,无需额外配置)
6. 重启 → 驾驶舱验证 `/hot` 或 `opp_diagnose`;挖掘验证 opp_start_mining→status→list_clusters