168 lines
12 KiB
Markdown
168 lines
12 KiB
Markdown
# report_bioflow_dev2 —— P1 生信服务地基(开发 agent A2)
|
||
|
||
> 任务书:docs/team/brief_bioflow_dev2_p1.md
|
||
> 工作分支:feature/bioflow-conversation-orchestration(保持,不切换)
|
||
> 纪律:不 commit/push/部署;不碰生产服务(8090/8091);服务层零 pydantic;零硬编码
|
||
|
||
## 1. 交付概览
|
||
|
||
| 模块 | 说明 |
|
||
|---|---|
|
||
| bioflow_service/(新增,独立部署树) | 生信服务 8098:FastAPI + 独立 SQLite + docker 执行器 + 状态机 + 规划器 |
|
||
| sdk/app/routers/bioflow_proxy.py(新增) | BFF 流式反代 + 报告登记端点 |
|
||
| sdk/app/main.py(2 行改动) | BIOFLOW_ENABLED 开关注册反代路由 |
|
||
| sdk/app/config.py(2 键) | bioflow_enabled(默认 false)/ bioflow_service_url |
|
||
| docs/team/report_bioflow_dev2.md | 本报告 |
|
||
|
||
## 2. 模块清单(bioflow_service/app/)
|
||
|
||
**明文白名单(编译管线保留 .py)**
|
||
- `config.py` —— BIOFLOW_ 前缀配置(pydantic-settings):image_map_path(仓库内
|
||
bioflow_kernel/stage_image_map.json,按 __file__ 推导 repo 根)、data_root/
|
||
jobs_dir/db_path/archives_dir/flow_docs_dir(全部可覆盖,无写死宿主路径)、
|
||
concurrency=3、stage_timeout_sec、host_uid_env=BIOFLOW_HOST_UID(默认服务进程
|
||
os.getuid() 推导)、container_data_dir=/bioflow-data、upload 白名单、DOCGEN_LLM_*
|
||
沿用 docgen 直连模式;bba_env 属性从配置推导 BBA_PFAM_DIR/BBA_RAG_MAPPING_FILE。
|
||
- `schemas.py` —— pydantic 请求/响应模型(ChatStreamRequest/JobCreateRequest/
|
||
StageConfirmRequest/ArchiveCreateRequest 等 10 个;STAGE/JOB 状态 Literal)。
|
||
- `db.py` —— 独立 SQLite(WAL)三表 + 幂等迁移(CREATE IF NOT EXISTS + PRAGMA
|
||
table_info 增量列):bio_jobs/bio_stages/bio_archives(字段与实施计划 §六对齐);
|
||
bio_stages UNIQUE(job_id, stage),job 删除级联。
|
||
- `main.py` —— FastAPI 组装 + lifespan(init_db→init_context→recover→shutdown);
|
||
health 端点 /api/bioflow/health(db 连通状态字段,FR-BIO-025 探活用)。
|
||
|
||
**服务层(全部 dataclass/dict/stdlib,无 pydantic,Cython 编译)**
|
||
- `services/bioflow/kernel.py` —— Docker 执行器:读 A1 stage_image_map.json
|
||
(75 阶段/8 镜像),按阶段→镜像拼 docker run(--user uid/三目录挂载/BIOFLOW_DATA
|
||
只读/-e BBA_*/--cpus/--memory/--rm + `python -B -m cli.run_{stage}`,list 无 shell);
|
||
cpu/memory 白名单回落;超时 terminate→kill;日志落任务 logs/ + 尾 80 行截断;
|
||
跨环境 note 透传(编排层 P2 拆分依据)。
|
||
- `services/bioflow/runner.py` —— 任务状态机:created→await_inputs→running→
|
||
paused/done/failed/archived;阶段 waiting→await_files→waiting_confirm→queued→
|
||
running→done/failed/skipped;输入检查(FR-BIO-005)→确认门(FR-BIO-008,confirm
|
||
`_confirmed` 旁路防二次确认门)→并发信号量(BIOFLOW_CONCURRENCY 默认 3,
|
||
FIFO 排队)→docker→manifest 判成败(no_manifest/manifest_failed/timeout/
|
||
exit_code 四因);pause 停阶段边界、resume 不跳过确认、rerun/skip 状态校验;
|
||
重启恢复 recover():running 阶段按 manifest 判成败(有 success manifest→done
|
||
否则重跑)、done 不重跑(attempt 不变)、archived 跳过。
|
||
- `services/bioflow/catalog.py` —— 阶段目录(映射表驱动 + STAGE_INFO/STAGE_DEPENDENCIES
|
||
静态快照,不运行时反射);73 阶段(真实表 75 去重复校验)、基因家族链 21 阶段、
|
||
手写参数 schema(identify 11 参数含 default/source/help,source 标注
|
||
contract/user/runtime 供表单默认值来源可见);validate_chain 未知阶段拒绝 +
|
||
auto_fill_prerequisites 前置补全(拓扑排序依赖在前)。
|
||
- `services/bioflow/planner.py` —— 路径规划:复用句式(「用 XXX 存档任务的方法…」)
|
||
→ archive 直接装载;否则知识库检索(vstore/flow.py FlowStore 本地实例混合检索,
|
||
失败降级 llm_only)+ LLM 候选(DOCGEN_LLM_* 直连,JSON 模式 + 修复重试)→
|
||
catalog 硬校验(未知阶段拒绝、前置补全);PLAN_LLM_TIMEOUT/PLAN_UNAVAILABLE
|
||
降级内置兜底链。
|
||
- `services/bioflow/manifests.py` —— manifest 解析校验(manifest_v1.schema 必需字段;
|
||
定位 final/{prefix}.{stage}.manifest.json,无兜底防跨阶段误配);跨阶段输入定位
|
||
(artifacts full_path 解析 + 存在性检查)。
|
||
- `services/bioflow/events.py` —— 事件总线(12 类事件全集 + job_recovered):
|
||
进程内 pub/sub(SSE 订阅)+ 内存环形缓冲 + events/{job_id}.jsonl 持久
|
||
(重启回放)+ snapshot 首帧 + replay(after_seq) 断线回放。
|
||
- `services/bioflow/llm.py` —— LLM 直连(docgen 同款:指数退避 + JSON 修复 +
|
||
LLMTimeout/LLMUnavailable 分型)。
|
||
- `services/bioflow/params.py` —— 参数预填(契约文档参数解析 + BBA_* 默认值标注 +
|
||
存档参数预填)。
|
||
- `services/bioflow/reports.py` —— 报告登记(报告 HTML 定位/fig:// 图清单提取/
|
||
登记载荷(job_id/标题/md/图清单)+ 内部 HTTP 调 BFF 反代端点,BFF 不可达降级)。
|
||
- `services/bioflow/archive.py` —— 存档打包(final/结果+logs/过程+events.jsonl
|
||
过程记录+input 原始文件;include_intermediate 开关含中间文件;zip 下载)。
|
||
- `services/bioflow/store.py` —— 三表 CRUD(upsert/list/get/delete;归档精确优先
|
||
模糊匹配、reused_count 计数)。
|
||
- `services/bioflow/intent.py` —— 意图分流(cases_bioflow_intent.md 冻结词典同表:
|
||
export→edit→docgen→附件 docgen→bioflow_qa(FLOW_QA 命中即拦)→bioflow
|
||
(动词+家族语境词/分析对象)→qa 漏判安全;复用方法名提取 3-20 字符;
|
||
>2000 字符截断判定)。
|
||
|
||
**路由**
|
||
- `routers/bioflow.py` —— health/catalog(?stage=/?chain=gene_family)/
|
||
chat/stream(SSE:意图分流→plan_ready 候选→心跳;plan seq 编码 data 载荷直出)/
|
||
ask(知识库引用块:source/title_path/path/cite/line/text)。
|
||
- `routers/biojobs.py` —— jobs 全套(POST 201/列表 rowid 倒序分页过滤/详情/删除
|
||
running 409);files(multipart 流式逐块写盘 + 扩展名白名单 + 大小上限 413 +
|
||
server_path 登记限 data_root/任务目录白名单 403);stages confirm(参数校验
|
||
未知 422)/rerun(带参数→waiting_confirm)/skip/pause/resume/manifest(manifest
|
||
对象 + 日志尾 80 行);events SSE(snapshot 首帧 + 回放 + 实时订阅 + 任务终态
|
||
关闭 TC-BIO-API-081);report revise(最小接口:无图目标 422/绘图阶段定位)。
|
||
- `routers/bioarchives.py` —— archives 全套(存档 201 重名 409/列表/详情/删除
|
||
磁盘+行/run 复用/按名匹配 404 ARCHIVE_NOT_FOUND/download zip/report HTML);
|
||
reports/register(归一化 + 图清单回填,BFF 反代落 doc_artifacts)。
|
||
|
||
**构建与运维**
|
||
- `build.sh` —— 复制 tooling/compile/compile_sdk.sh 改白名单(明文:main.py/
|
||
config.py/schemas.py/db.py + __init__.py 规则;schemas= pydantic cyfunction 教训、
|
||
db= 断流崩溃根治教训);16 模块 Cython+GCC 全过(实测 /tmp 输出 16 .so,
|
||
编译树 import OK)。
|
||
- `restart.sh` —— 8098 重启(零硬编码:路径脚本位置推导 + 环境变量覆盖)。
|
||
- `tests/` —— pytest(-m bioflow_unit 127 用例 / -m bioflow_api 39 用例)。
|
||
|
||
## 3. 自测结果(2026-09-06,服务器 venv 3.12.13)
|
||
|
||
| 命令 | 结果 |
|
||
|---|---|
|
||
| `python -m pytest tests/ -q` | **166 passed**(15.7s,0 warnings) |
|
||
| `python -m pytest tests/ -q -m bioflow_unit` | 127 passed |
|
||
| `python -m pytest tests/ -q -m bioflow_api` | 39 passed |
|
||
| build.sh → /tmp 编译 + 编译树 import | 16 模块 .so,import OK |
|
||
| BFF BIOFLOW_ENABLED=false/true 双态 import | 均 OK(反代路由 2 条) |
|
||
| 真实 stage_image_map.json 加载 | 75 阶段/8 镜像/identify 11 参数/命令拼装正确 |
|
||
| /home/xzq 硬编码扫描(app+tests) | 0 处 |
|
||
|
||
全部 mock docker/LLM/vstore(tmpdir + fake 执行器),不连任何生产服务
|
||
(8090/8091/8094/8098 从未探测)。
|
||
|
||
## 4. 已知限制(交 TL 裁决)
|
||
|
||
1. **SSE 传输层测试法**:本环境 fastapi TestClient 的 sync stream 包装与 httpx
|
||
ASGITransport 对永不结束的 SSE 流均存在首帧不达/整流缓冲问题(dbg3/dbg6 最小
|
||
复现实证),SSE 用例改为端点直调迭代 body_iterator + 模块级共享 event loop
|
||
(anyio portal 绑定首个 loop,跨 loop 死锁实证)。生产部署(uvicorn 真实网络
|
||
SSE)不受影响;如 TL 要求 TestClient 原生流测试,需另行排查 fastapi/anyio
|
||
版本组合。
|
||
2. **catalog 阶段数口径**:任务书口径 73;A1 交付 stage_image_map.json 实为 75
|
||
阶段(含 module=null 的 synteny_plot_revise 与 executable=false 的 msa/
|
||
enrichment)。kernel 对 module=null 阶段拼命令前置拦截(UnknownStageError),
|
||
catalog 全量返回 75。以 A1 交付物为准,口径差异记录备查。
|
||
3. **gene_family 链为 21 阶段**(A1 family_chain 实测 21,任务书口径约 18);
|
||
以 stage_image_map.json family_chain 字段为唯一事实源。
|
||
4. **FlowStore 生产数据未入库**:vstore/data/flow_docs 目录当前不存在(A4 自测
|
||
在 tmpdir 完成;真实语料 106 文件/724 块需 TL 部署时跑
|
||
vstore/scripts/ingest_flow_docs.py 入库)。planner 已按本地实例对接(加载成功
|
||
零块时检索空 → LLM 候选照常,降级链完整);生产前入库即可获得 KB 增强
|
||
(llm_rag source)。
|
||
5. **chat/stream 是规划入口**:plan_ready 后保持心跳连接,任务创建走
|
||
POST /jobs(P1 契约);会话级任务事件经 /jobs/{id}/events 订阅。若 TL 要求
|
||
chat/stream 单流贯穿任务事件(A3 前端形态),需 P2 加会话级订阅联动。
|
||
6. **报告登记 BFF 侧 doc_artifacts 落库**:bioflow_proxy.register_report 字段
|
||
(job_id/session_id/标题/md_path/图清单)已按约定实现;图清单字段当前存于
|
||
请求体(doc_artifacts 表无 figures 列,如需持久化图清单需 TL 裁决加列——已
|
||
在 payload 透传中保留)。与 A3 report 模板的 fig:// 渲染协调点:报告 HTML 内
|
||
fig://id 引用清单由生信服务 reports.extract_figure_refs 提供。
|
||
7. **意图词典判定为启发式快照**:与 cases_bioflow_intent.md 冻结表逐条对齐
|
||
(40 用例表全过);家族名语境词规则(「SPL 会议」不命中)为词典实现注意第
|
||
1/4 条的工程化解读,最终同表双跑一致性以 TC-BIO-INTENT-047(L2 用例)验收。
|
||
8. **事件持久化目录**:events/{job_id}.jsonl 与任务目录分离(bioflow_data/
|
||
jobs/events/);归档时打包进档案根。任务删除不清理事件文件(留审计),
|
||
如需一并删除交 TL 裁决。
|
||
9. **镜像 tag 后缀**:docker_image_tag_suffix 默认 "dev"(A1 交付物 :dev);
|
||
发布流水线(P2 FR-BIO-032 compile_bioflow.sh)需按终态 tag 覆盖环境变量。
|
||
10. **pytest.ini python_files 陷阱**:本仓库 pytest 9.1.1 下 `python_files =
|
||
["test_*.py"]`(列表形式)会导致目录级收集 0 用例(单文件显式传参正常),
|
||
已用字符串形式 `python_files = test_*.py` 规避并实证;写报告备案防踩。
|
||
|
||
## 5. 交付物清单
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| bioflow_service/app/{config,schemas,db,main,context}.py | 应用骨架(4 明文 + context) |
|
||
| bioflow_service/app/services/bioflow/*.py | 服务层 12 模块(零 pydantic) |
|
||
| bioflow_service/app/routers/{bioflow,biojobs,bioarchives}.py | 端点三层 |
|
||
| bioflow_service/build.sh / restart.sh | 编译白名单管线 / 重启脚本 |
|
||
| bioflow_service/pytest.ini | markers + python_files(字符串形式陷阱规避) |
|
||
| bioflow_service/tests/*.py | 10 文件 166 用例 |
|
||
| sdk/app/routers/bioflow_proxy.py | BFF 流式反代 + 报告登记 |
|
||
| sdk/app/main.py(+2 行)/ sdk/app/config.py(+2 键) | BFF 最小改动 |
|
||
| docs/team/report_bioflow_dev2.md | 本报告 |
|