From e641c8b9ab558602320e1f865ce25b92443301f9 Mon Sep 17 00:00:00 2001 From: potaser Date: Wed, 5 Aug 2026 09:40:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BD=BB=E9=87=8F=E6=8B=93=E5=B1=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=20+=20WGS2GWAS=20=E9=98=B6=E6=AE=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20+=20=E7=BB=93=E6=9E=9C=E5=8C=BA=E5=9F=9F=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20+=20=E7=89=A9=E7=A7=8D=E8=A7=92=E8=89=B2=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=A2=9E=E5=BC=BA=20+=20=E4=BC=9A=E8=AF=9D=20Job=20?= =?UTF-8?q?=E9=9A=94=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【轻量拓展分析】 - 新增 gfa_core/extension_stage_lightweight/ 核心模块,支持用户上传代码/数据/原始命令 - 前端卡片式交互流程:候选核对 → 验证 → 结果审查 → 授权发布 → 运行 - Celery 不受限任务 + 轮询机制 + sessionStorage 操作恢复 - 启动脚本新增 BBAV5_LIGHTWEIGHT_* 环境变量 【WGS2GWAS 支持】 - 新增 13 个 WGS 阶段定义(QC → MAF/Missing Filter) - email_haplotype_region.py 新增 LTR-RT 分析功能 【结果区域重构】 - 单层折叠 → 三组双层折叠:RNA-seq / 基因家族 / WGS2GWAS - 结果按执行时间排序,保留最新尝试 【物种角色解析增强】 - 新增 _resolve_subfamily_request_species_roles() - 支持 reference 角色的识别 - 直接 stage 请求保留 intent 中的物种角色 【会话 Job 隔离】 - rebind_job() 跨 job 时创建新会话,返回新 conversation_id 【前端交互增强】 - RAG 文献问答模式 - NL 触发 config/samples 自动填写、亚家族确认表、基因家族成员确认表 - 执行状态从后端 resource_tasks 恢复 Co-Authored-By: Claude Opus 5 (1M context) --- apps/web/pipeline_backend.py | 32 +- apps/web/vue3/index.html | 1195 +++++++++- apps/web/vue3/main.py | 216 +- celery_app.py | 4 + .../extension_stage/raw_package_normalizer.py | 182 ++ .../extension_stage_lightweight/__init__.py | 20 + gfa_core/extension_stage_lightweight/api.py | 739 ++++++ .../command_model.py | 454 ++++ .../confirmation.py | 181 ++ .../extension_stage_lightweight/converter.py | 207 ++ .../deepseek_semantics.py | 397 ++++ .../extension_stage_lightweight/evidence.py | 176 ++ .../process_control.py | 389 +++ .../runtime_binding.py | 2105 +++++++++++++++++ .../semantic_model.py | 410 ++++ .../semantic_repair.py | 376 +++ .../extension_stage_lightweight/service.py | 795 +++++++ gfa_core/gene_family_scope.py | 1 + gfa_core/gene_family_stage_context.py | 2 +- gfa_core/mas/agents/router_runtime.py | 22 + gfa_core/mas/artifact_resolver.py | 1 + gfa_core/mas/persistent_conversation.py | 29 +- gfa_core/mas/tools/stage_tools.py | 1 + start_celery_9000.sh | 4 + start_plantai_9000.sh | 4 + tasks.py | 31 +- tests/unit/test_autofill_entrypoints.py | 33 +- .../test_extension_stage_lightweight_api.py | 930 ++++++++ ...tension_stage_lightweight_command_model.py | 373 +++ ...xtension_stage_lightweight_confirmation.py | 287 +++ ...on_stage_lightweight_deepseek_semantics.py | 364 +++ ...st_extension_stage_lightweight_evidence.py | 99 + ...tension_stage_lightweight_fact_contract.py | 123 + ...ion_stage_lightweight_frontend_contract.py | 250 ++ ...nsion_stage_lightweight_process_control.py | 583 +++++ ...tage_lightweight_raw_package_normalizer.py | 62 + ...test_extension_stage_lightweight_replay.py | 96 + ...nsion_stage_lightweight_runtime_binding.py | 467 ++++ ...ge_lightweight_runtime_binding_resolver.py | 630 +++++ ...nsion_stage_lightweight_runtime_package.py | 1459 ++++++++++++ ...ension_stage_lightweight_semantic_model.py | 472 ++++ ...nsion_stage_lightweight_semantic_repair.py | 477 ++++ ...est_extension_stage_lightweight_service.py | 576 +++++ ...tension_stage_lightweight_shell_binding.py | 57 + ...ension_stage_lightweight_shell_pipeline.py | 41 + ...sion_stage_lightweight_target_launchers.py | 25 + .../test_frontend_cpu_monitor_contract.py | 13 + ...t_frontend_execution_indicator_recovery.py | 40 + .../test_gene_family_scope_reference_roots.py | 11 + ...t_persistent_conversation_job_isolation.py | 53 + tests/unit/test_result_browser_persistence.py | 77 + .../unit/test_stage_tool_tree_passthrough.py | 62 + tests/unit/test_subfamily_prediction_plan.py | 290 +++ 53 files changed, 15831 insertions(+), 92 deletions(-) create mode 100644 gfa_core/extension_stage/raw_package_normalizer.py create mode 100644 gfa_core/extension_stage_lightweight/__init__.py create mode 100644 gfa_core/extension_stage_lightweight/api.py create mode 100644 gfa_core/extension_stage_lightweight/command_model.py create mode 100644 gfa_core/extension_stage_lightweight/confirmation.py create mode 100644 gfa_core/extension_stage_lightweight/converter.py create mode 100644 gfa_core/extension_stage_lightweight/deepseek_semantics.py create mode 100644 gfa_core/extension_stage_lightweight/evidence.py create mode 100644 gfa_core/extension_stage_lightweight/process_control.py create mode 100644 gfa_core/extension_stage_lightweight/runtime_binding.py create mode 100644 gfa_core/extension_stage_lightweight/semantic_model.py create mode 100644 gfa_core/extension_stage_lightweight/semantic_repair.py create mode 100644 gfa_core/extension_stage_lightweight/service.py create mode 100644 tests/unit/test_extension_stage_lightweight_api.py create mode 100644 tests/unit/test_extension_stage_lightweight_command_model.py create mode 100644 tests/unit/test_extension_stage_lightweight_confirmation.py create mode 100644 tests/unit/test_extension_stage_lightweight_deepseek_semantics.py create mode 100644 tests/unit/test_extension_stage_lightweight_evidence.py create mode 100644 tests/unit/test_extension_stage_lightweight_fact_contract.py create mode 100644 tests/unit/test_extension_stage_lightweight_frontend_contract.py create mode 100644 tests/unit/test_extension_stage_lightweight_process_control.py create mode 100644 tests/unit/test_extension_stage_lightweight_raw_package_normalizer.py create mode 100644 tests/unit/test_extension_stage_lightweight_replay.py create mode 100644 tests/unit/test_extension_stage_lightweight_runtime_binding.py create mode 100644 tests/unit/test_extension_stage_lightweight_runtime_binding_resolver.py create mode 100644 tests/unit/test_extension_stage_lightweight_runtime_package.py create mode 100644 tests/unit/test_extension_stage_lightweight_semantic_model.py create mode 100644 tests/unit/test_extension_stage_lightweight_semantic_repair.py create mode 100644 tests/unit/test_extension_stage_lightweight_service.py create mode 100644 tests/unit/test_extension_stage_lightweight_shell_binding.py create mode 100644 tests/unit/test_extension_stage_lightweight_shell_pipeline.py create mode 100644 tests/unit/test_extension_stage_lightweight_target_launchers.py create mode 100644 tests/unit/test_frontend_cpu_monitor_contract.py create mode 100644 tests/unit/test_frontend_execution_indicator_recovery.py create mode 100644 tests/unit/test_gene_family_scope_reference_roots.py create mode 100644 tests/unit/test_persistent_conversation_job_isolation.py create mode 100644 tests/unit/test_result_browser_persistence.py create mode 100644 tests/unit/test_stage_tool_tree_passthrough.py diff --git a/apps/web/pipeline_backend.py b/apps/web/pipeline_backend.py index d4c12267a..7834670b4 100644 --- a/apps/web/pipeline_backend.py +++ b/apps/web/pipeline_backend.py @@ -1073,14 +1073,22 @@ def resolve_scoped_protein_fasta_from_phylogeny( ) -def resolve_scoped_tree_from_phylogeny( - ws: Path, - final_dir: Path, - prefix: str, - scope_path: Path, -) -> tuple[Path, dict]: - scope_data = read_scope(scope_path) - manifest_candidates = stage_manifest_candidates(final_dir, "phylogeny", prefix, scope_data) +def resolve_scoped_tree_from_phylogeny( + ws: Path, + final_dir: Path, + prefix: str, + scope_path: Path, + explicit_tree_file: str = "", +) -> tuple[Path, dict]: + scope_data = read_scope(scope_path) + if explicit_tree_file: + selected_tree = Path(explicit_tree_file).expanduser() + if not selected_tree.is_absolute(): + selected_tree = ws / selected_tree + if selected_tree.exists() and selected_tree.stat().st_size > 0: + return selected_tree.resolve(), scope_data + raise FileNotFoundError(f"Specified scoped tree file not found: {explicit_tree_file}") + manifest_candidates = stage_manifest_candidates(final_dir, "phylogeny", prefix, scope_data) for manifest_file in manifest_candidates: if not manifest_file.exists(): @@ -8261,7 +8269,13 @@ def run_stage( if member_set_id: cmd += ["--member-set-id", member_set_id] try: - motif_tree_file, _motif_scope_data = resolve_scoped_tree_from_phylogeny(ws, final_dir, prefix, scope_path) + motif_tree_file, _motif_scope_data = resolve_scoped_tree_from_phylogeny( + ws, + final_dir, + prefix, + scope_path, + explicit_tree_file=tree_file, + ) cmd += ["--tree", str(motif_tree_file)] motif_scope_id = str(_motif_scope_data.get("scope_id") or "") except Exception as exc: diff --git a/apps/web/vue3/index.html b/apps/web/vue3/index.html index a4a27f036..c1acbfe65 100644 --- a/apps/web/vue3/index.html +++ b/apps/web/vue3/index.html @@ -1383,6 +1383,7 @@ 名称 + 原始命令 环境 @@ -1405,6 +1406,13 @@ 移除 + 服务器测试数据路径 + +
生成并发布 + + 运行已发布 + 运行结果
@@ -2136,8 +2147,51 @@ +
+
+
AI
+
+
+
+
{{ card.title }}
+
{{ card.purpose }}
+
+ {{ card.status_label || card.status }} +
+
{{ card.summary }}
+ + + + +
{{ card.collapsed_summary }}
+ +
{{ card.error }}
+
+ Yes,确认无误 + 取消 + 提出修订意见 + 重新生成说明 + 开始验证 + 结果无误,继续 + 授权发布 + 确认执行 +
+
+
+
+ -
+
{{ nlStatusText || '正在处理请求...' }}
@@ -2230,7 +2284,7 @@
-
+
⏳
- {{ (currentTask && currentTask.stage ? currentTask.stage : (currentBatchStage || confirmParams.stage || 'analysis')).toUpperCase() }} Executing + {{ executionIndicatorStage.toUpperCase() }} Executing
- ⏱️ {{ executeElapsed }}s | {{ isBatchExecuting ? 'Batch / methodology queue' : 'Refresh every 5s' }} + ⏱️ {{ executionIndicatorElapsed }}s | {{ executionIndicatorStatusText }}
@@ -2284,9 +2338,20 @@
- + + + + - +