Files

10 KiB
Raw Permalink Blame History

轻量版拓展分析自然语言触发 — 第一轮测试报告

  • 时间:2026-08-27
  • 被测提交:a60f45754(轻量拓展分析自然语言触发,4 文件 +813/-8,未 push)
  • 测试环境:/home/xzq/miniconda3/envs/plantai-bff/bin/python(Python 3.11.15 / pytest 9.1.1 / pytest-cov 7.1.0;本轮补充安装 pyyaml/openai/pandas/requests/openpyxl 后方可跑通 main.py 相关测试)

测试文件清单

文件 新增/追加 用例数 结果
tests/unit/test_extension_stage_lightweight_nl_intent.py 新增 58 全绿
tests/unit/test_extension_stage_lightweight_nl_backend.py 新增 18 全绿
tests/unit/test_extension_stage_lightweight_frontend_contract.py 追加 5 个测试(未删任何现有断言,原 15 → 现 20) 20 全绿

通过/失败数

组 结果
A 组(nl_intent 单元) 58 passed
B 组(main.py 后端集成) 18 passed
C 组(前端契约) 20 passed
新增三件套合计 96 passed
回归:Phase A 三件套(agent/input_binding/golden_runner_semantic) 6 passed
回归:test_agent_chat_actions + deepseek_semantics 46 passed
回归:全套 test_extension_stage_lightweight*.py 312 passed + 6 既有失败 + 1 skip

6 个既有失败(已在父提交 90f51ed60 干净 worktree 上逐一复现,与本改动无关,不拦路):

  1. test_extension_stage_lightweight_fact_contract.py::test_build_execution_facts_keeps_unmatched_outputs_without_guessing
  2. test_extension_stage_lightweight_runtime_binding.py::test_shell_patch_targets_record_hash_literal_kind_and_exact_count
  3. test_extension_stage_lightweight_runtime_binding.py::test_same_uploaded_path_in_two_steps_forms_one_safe_path_binding
  4. test_extension_stage_lightweight_runtime_binding.py::test_repeated_parameter_literal_across_facts_is_not_patchable
  5. test_extension_stage_lightweight_runtime_package.py::test_unrelated_implicit_output_remains_blocked
  6. test_extension_stage_lightweight_target_launchers.py::test_target_launchers_share_lightweight_extension_runtime_roots

覆盖率

python3 -m pytest --cov=gfa_core.extension_stage_lightweight.nl_intent --cov-report=term-missing tests/unit/test_extension_stage_lightweight_nl_intent.py

  • gfa_core/extension_stage_lightweight/nl_intent.py:187 stmts / 0 miss / 100%
  • 无未覆盖行(补测过程:93% → 98% → 99% → 100%,最终 0 遗漏)

失败用例+关键报错

本轮无功能缺陷导致的测试失败(测试自身两处断言问题已修复:集合类型断言、reason 前缀断言)。

重点验证结论(对应 developer 标记风险 R1-R4 + 测试要求 1-10)

R1 目录截断(P0 缺陷确认)

真实 store 实测:61 个 published 记录,_build_catalog 只放前 11 个即达 11276 字符,truncated=True。 「拓展分析」强触发词下 _rough_candidates 返回全部 61 个,但目录按目录名排序截断后 12_/13_/14_/15_/16_/17_/18_ 共 50 个扩展(含 manifestqc、tfbs、kaks_cis、motif、pav_cnv 等 18 案例中的后 7 个)LLM 完全不可见,任何消息都无法命中这些扩展。 测试固化:test_real_store_catalog_truncation_smoke、test_build_catalog_truncates_when_over_max_chars。

R2 中文关键词粗筛(缺陷确认)

真实 store 实测:「帮我做样本表校验」→ 0 候选、不调 LLM(function_summary 全英文,纯中文功能词无法命中 _summary_keywords 英文 token 与中文子串)。只有强触发词(拓展分析/扩展分析/extension)或工具词(hmmsearch/hmmer/blast/blastp)才能进 LLM。注意:工具词路径会把全部 61 个记录都当候选(无法按工具区分),再叠加 R1 截断,实际能解析的只有前 11 个。 测试固化:test_real_store_pure_chinese_function_words_miss_rough_candidates。

R3 prefill 字段位置(实现一致)

已验证:LightweightIntentResolution.prefill 在 dataclass 顶层;_match_lightweight_extension_intent 返回 dict 中 params.prefill(顶层副本)与 params.llm_slots;前端 openLightweightNlRunDialog 读 intentParams.llm_slots 的 input_overrides/parameter_overrides/explicit_prefix,不依赖顶层。C 组断言按实际实现写,无错位。

R4 extension_name 英文(产品缺陷候选,记录待验收)

已确认:extension_name 取 function_summary 英文首句(≤60 字符),后端 message 与前端向导标题会显示英文(如 "This tool searches sequences with hmmsearch.")。测试固化:test_resolution_uses_first_sentence_as_extension_name。建议后续加中文 display_name 映射。

测试要求 1-10 覆盖情况

  1. 无触发词 → extension_id None 且 client_factory 计数为 0(参数化 3 条消息)✅
  2. 触发词 + 无 records → 不调 LLM(reason=no_published_records)✅
  3. _build_catalog:只含 replaceable inputs 的 {path,role,description}、剔 locked input、parameter 无 value、含 function_summary、超长截断置 truncated ✅
  4. _sanitize_resolution:编造 path/fact_id/extension_id/非 str value/confidence 非法 → None+原因(参数化 7 种非法输入 + 4 种非对象);合法 → 正确映射 ✅
  5. LLM 抛异常/坏 JSON/缺 choices → None resolution 不抛(reason=llm_unavailable_or_invalid 或 invalid_resolution: 前缀)✅
  6. happy path:「使用 HMM 拓展分析对刚上传的文件进行分析,参数 e-value=1e-5」→ input_overrides/parameter_overrides/confidence/prefill 全对 ✅
  7. load_published_lightweight_records:published/confirmation_pending/baseline_failed/坏 JSON/非对象 → 只返回 published;坏 store 根返回 [] ✅
  8. job_file_hints 进入 LLM user 消息 JSON(并测 MAX_JOB_FILE_HINTS 截断 200)✅
  9. 参数值约束:sanitize 只做结构校验(fact_id 合法即收),不校验"参数是否在用户消息中出现"(prompt 层约束),测试固化该行为 ✅
  10. 覆盖率 100%(见上)✅

B 组关键用例

  • _match_lightweight_extension_intent:命中返回 lightweight:True/llm_slots/extension_store/prefill/confidence/parse_reason;空 store、resolution None、extension_id None → 均返回 {} ✅
  • 回退三处:Phase A 命中不标 lightweight;Phase A 空列表 → 回退轻量(三个空返回点中 candidates 为空与 trigger 为空两处直接测到;rnaseq 短路点静态确认回退存在,未单独构造 rnaseq 消息,因为该消息本身也不命中轻量粗筛)✅
  • _lightweight_job_file_hints:input+workspace 相对路径、空 job_id → []、200 上限 ✅
  • import-paths 端点:合法 /home/xzq/ 下文件复制进 _nl_imports、同名冲突加 _1 后缀、前缀外路径 400、不存在路径 400、空 job_id 400 ✅(注:source 必须在 /home/xzq/ 下构造,tmp_path 在 /tmp 会被前缀校验拒绝)
  • _run_agent_chat 短路:预闸命中 + 轻量 intent → action="propose_extension_stage"、model_used="rule",且 monkeypatch 证明未触碰 LLMManager/RouterAgent(会抛异常);预闸不命中 → 走正常 MainAgent 流程 ✅
  • /api/agent/plan 守卫端到端:轻量 intent 不调 _extension_stage_plan_response;Phase A 命中正常调用 ✅

遗留问题清单

编号 位置 现象 建议修复
1(P0) gfa_core/extension_stage_lightweight/nl_intent.py _build_catalog(约 128-173 行) 真实 store 61 个 published 记录只进前 11 个即截断(11276/12000 字符),目录按目录名排序,12_ 及以后的 50 个扩展(含 18 案例中 12-18 的 7 类)LLM 不可见,「拓展分析」强触发词下也永远无法命中 截断策略需改为"全部进目录、按相关性排序"或"先粗筛再目录化"(按关键词把候选缩到相关子集),至少保证 18 案例的功能词能进目录;12_ 以后的扩展在截断前应有兜底(如只放 extension_id+summary 的轻量条目)
2(P1) 同文件 _rough_candidates(约 108-122 行) 纯中文功能词(如"样本表校验")0 候选不调 LLM,只能靠强触发词或英文工具词进入;工具词 hmmsearch/hmmer/blast 路径会把全部 61 个记录都当候选(不按工具区分) 中文 summary 子串匹配对 18 案例 prompt 影响需产品确认;工具词路径建议按工具名映射到对应扩展(如 hmmsearch → 03_ 系列),或至少接受"全候选+目录排序优化"
3(P1) gfa_core/extension_stage_lightweight/nl_intent.py _rough_candidates(约 113-114 行) str(record.get("extension_id")) 对缺失 id 的记录产出 "None" 字符串候选 改为 record.get("extension_id") and str(...) 过滤,或直接 [r["extension_id"] for r in records if r.get("extension_id")]
4(P2) 同文件 resolve_lightweight_extension_intent(约 265-346 行) extension_name 取 function_summary 英文首句(≤60),后端 message 与前端向导标题显示英文 产品验收时确认是否需中文 display_name 映射;若需,在 record 或 catalog 层加中文名字段
5(P2) apps/web/vue3/main.py nl_import_paths(约 4449-4512 行) 目录导入用 shutil.copytree(dirs_exist_ok=True) 合并进目标目录,且同名目录无冲突后缀(与文件路径的 _1 后缀策略不一致);多路径循环中前一个成功、后一个 400 时已复制的文件不回滚 目录同名冲突建议同样加后缀;整体事务性按需评估(低风险,向导场景可接受部分成功)
6(P3/信息) 全套 lightweight 回归 6 个既有失败(见上清单),父提交 90f51ed60 复现,与本改动无关 不拦路;建议另开任务修复
7(P3/信息) 测试环境 plantai-bff 环境缺 pyyaml/openai/pandas/requests/openpyxl,main.py 相关测试此前跑不通(test_agent_chat_actions 修复前 27 failed) 已补充安装;建议把依赖清单写进仓库 requirements 或测试文档

测试环境备注

  • 本轮在 plantai-bff conda 环境补充安装了:pyyaml、openai、pandas、requests、openpyxl(均为项目既有依赖,纯 pip 安装,未动仓库文件)。
  • 验证既有失败时在父提交 90f51ed60 建了临时 worktree,验证后已删除(git worktree remove --force)。
  • 工作区改动仅限测试文件:tests/unit/test_extension_stage_lightweight_nl_intent.py(新增)、tests/unit/test_extension_stage_lightweight_nl_backend.py(新增)、tests/unit/test_extension_stage_lightweight_frontend_contract.py(追加 5 个测试,现有断言未删)。开发代码未触碰,未 push。