Files
PlantAI-rag-new/docs/DEBUG_RECORD_r4_20260912.md

15 KiB

缺陷记录(Debug Record):r4 六项缺陷修复与 176 部署(2026-09-11 → 09-12)

  • 记录范围:2026-09-11 手工测试《PlantAI-rag-new知识问答部分测试问题一览_20260911.xlsx》6 项缺陷(#27/#28/#32/#38/#47/#52)全流程 + 修复过程中暴露的 3 项过程问题 + 环境/部署问题(175 三次宕机、figures 路径漂移、PMC 超时、部署三事故)
  • 修复组织:TL 计划 → 测试 agent 用例(acceptance-r4-20260911.md)→ Dev-F/Dev-B1/Dev-B2 并行 worktree → TL 合并 → 全套测试 → dev 栈重建 → T 复测 → TL 验收 → push → 编译打包 → 176 部署 → S2 终验
  • 代码基线:feature/bioflow-conversation-orchestration @ 7840527 → 终态 @ faa8686(已 push),tag bugfix-r4-20260912
  • 验收依据:docs/acceptance-r4-20260911.md(测试 agent 编制 + TL 第 10 节实测记录)

时间线(commit 序)

时间 commit 内容
09-11 夜 75877ec Dev-F:前端四项(#27 fallback/缓存失效、#32 空态提示、#47b 状态机、#52a 意图词典)
09-11 夜 00eb0bc/28bee31/f18286f Dev-B1:#27 title 回填、#28 阈值初版、#47a DOCX 同源解析、intent.py 词典
09-11 夜 3889a2a/60f7360/b5dc12e Dev-B2:#38 mineru 重试、#52b 内容去重、#52c doc 聚合
09-11 夜 c620461/025e2d5 TL 合并 backend2/backend1
09-11 夜 8d04eb6 恢复 methodology_routes.py 执行位(backend2 合并引入 mode 变更)
09-11 夜 1fe80b2/aec01ca #28 v2:双域阈值+检索模式免 LLM 免 rerank(含 amend 补参数链路)
09-11 夜 0252d52 #28 v3:检索模式关闭图证据检索(use_neo4j)
09-11 夜 d54419f chat 空 sources 根治:paper_id 派生 DOI/PMCID 回填引用
09-12 凌晨 04bf099 DEPLOY_FLOW §5e/5f/5g 增补(部署文档)
09-12 凌晨 8e4fce0 figures PMC 超时 5s→15s
09-12 凌晨 faa8686 figures 冷连接自动重试(终态,tag 指向)

一、六项手工测试缺陷(问题清单 Excel)

#27 会话级聚合后右侧文献来源「显示串行」

  • 根因:message 级 sources items 的 title 为空 → SourceRow 渲染出正文片段开头(如 "RESEARCH ARTICLE..."),视觉上串行/混乱。会话级聚合本身正常。
  • 修复:①后端 normalize_source title 空时按「顶层标题类字段 → metadata 标题类字段 → 顶层 source(实体名)」回填,正文字段显式排除;②前端 SourceRow displayTitle 兜底(title > badgeTitle > i18n「(无标题)」);③bench store sourcesStale 标记 + chat 终态触发强制重拉。
  • 验证:S1 arginine 30 条 empty_titles=0/30,score 0.694 保留;S2 同过。

#28 空态:无关问题返回 30 条无关文献(三轮回改)

  • 根因(三层):①检索链无相关性下限,「景甜是谁」30 条 final_score 全 0.19-0.20 也入选;②r3 #28 只关了 native_chain 多跳链,漏关 use_neo4j 图证据种子检索——正常问题 arginine 在 13M 断言库上图检索 150s+ 超时(r3 验收那条「120.03s→200 degraded」正是此因,当时只验了降级契约没追根因);③search 模式在 LLM 可用时仍跑 draft/planner 两次 LLM 调用,纯浪费。
  • 修复:v1(0.25 双保险)→ 域错配被 TL 实测推翻(Qdrant vector 域垃圾分实测 0.32-0.34,高于 0.25,过滤无效且 120 候选全进 CPU rerank 卡 10 分钟);v2=双域阈值(vector 0.45 env QA_MIN_VECTOR_SCORE 仅检索模式 / final 0.25 env QA_MIN_SOURCE_SCORE chat 模式)+检索模式强制免 LLM 免 rerank;v3=检索模式强制 use_neo4j=False(性能红线,用户 ablation 不得重开)。
  • 验证:景甜 0.86s 空态(degraded 无,非降级)/ arginine 0.82s 30 条;S2 176 上 4.1s/1.2s。

#32 知识图谱 TAB 搜索「水稻」无响应(被误读为超时)

  • 根因:非超时——后端 200 返回空 results(实测 0.022s),前端成功空结果时无任何提示被误读为超时;「水稻」在英文库无命中属正常。
  • 修复:KgPane 空结果提示「未找到相关实体」(新增 i18n kgNoResult,与 kgEmpty/kgDown 三态互斥)。
  • 验证:S1 0.38s 空态+提示;S2 0.007s。

#38 MinerU 上传提取被瞬间打断(exit 1 无原因)

  • 根因(机制级):任务在最早阶段抛出无消息异常 → API task.error 空串 → CLI 空 message;API 异常日志打 stdout 被块缓冲、CLI 失败后立即杀 API 进程,真因永久丢失。触发因素:176 失败窗口 74 秒前 GPU 显示器重配置(gnome/GDM/NVIDIA DFP 重连),mineru 启动期有设备探测。
  • 修复:①PYTHONUNBUFFERED=1(两树);②returncode≠0 且 job.log 无 doc_analyze_streaming 行 → 启动期失败自动重试 1 次;③重试仍失败 → 中文可读错误(附原始日志尾部)。
  • 验证:175 上真实触发(见「环境问题 E-2」):缺 accelerate → 自动重试+中文错误全链落地;装后全链 completed 100%。
  • 遗留建议(未执行):176 去桌面化(systemctl set-default multi-user.target)根治 GPU 显示重配置干扰,待用户决策。

#47 DOCX 格式不一致 + 关闭文档后再返回看不到

  • #47a 根因:html2docx 红头样式硬编码 22pt/FF0000,与模板 CSS(30px/#c00000)不一致。
  • #47a 修复:新增 html_css.py 安全子集 CSS 解析器,红头/标题从 render_html 产物解析,失败回退常量;导出 docx 与 PDF 同源。
  • #47b 根因:docgen store 的 fetchHtml 无序号守卫——文档 A 关闭后其迟到 html 响应把已清空的 html/css/templateKey 写回。
  • #47b 修复:close()/open()/adoptArtifact 的序号换代+在途响应作废。
  • 验证:DOCX 红头 #C00000/22.5pt 居中、h1 16.5pt;状态机单测 7 例。

#52 上传资料后可问答但无法「总结论文」

  • 根因(三层):①WRITE_VERB 缺「总结/概括/归纳」→ 路由到 QA 而非 docgen;②vault.add 无内容去重,同 PDF 传 4 次 = 800 chunk 挤爆检索预算;③_pick_items 先按 score 取 top_k 再每 doc ≤3 去重,作者页重复块占满名额、正文块从未进入上下文。
  • 修复:①前后端词典同步补三词(intent.js+intent.py+cases_intent.md,带「动词自指保护」防无附件纯总结问句误进 docgen);②vault.add 按内容 SHA256 去重(同内容覆盖旧 doc_id+清理旧 chunk);③_pick_items 先按 doc_id 聚合(doc 级 max score 取 top 文档)再取组内最相关块(≤3,组内近重复指纹只取 1)。
  • 验证:「帮我总结论文」→ docgen 202;同 PDF 传 2 次 vstore 仅 1 doc_id(34 chunk 不翻倍);私有问答 hit:true 3 块引正文。

二、修复过程中暴露的问题(过程问题)

P-1 #28 v1 域错配(TL 实测推翻)

Dev-B1 初版把 0.25 同时用于 Qdrant score_threshold 与 final 门。TL 在 dev 环境实测:「景甜是谁」Qdrant vector_score 垃圾带 0.32-0.34(非 docstring 声称的 <0.2),0.25 阈值形同虚设,120 候选全进 CPU rerank 卡 10 分钟+。教训:阈值必须按域实测校准,检索前置过滤与后置门是两个域、两组数据。终稿见 #28。

P-2 r3 遗留:search 模式图检索漏关

r3(2026-09-10)#28 的修复语义是「检索模式只走 Qdrant 向量」,但只关了 native_chain(多跳链),漏关 use_neo4j(图证据种子检索)。r3 验收时的「120.03s 超时降级」记录被当作契约验收通过,没有追到根因。本轮 v3 修复(arginine 150s+→0.82s)。教训:降级契约验收不能替代性能根因排查。

P-3 chat 空 sources 回归(r3 环境既有隐患)

dev 9271 上新代码 chat 全链 sources=0:rerank 审计 bge 全 0.02-0.05(空 evidence 输入)、rrf 全 0。TL 探针定界:reranker 模型正常(有正文 logit +6.73/空正文 -3.07),空正文 sigmoid 0.044 与审计吻合 → 进入 rerank 的 136 条候选全是无 evidence 的归一化图断言。根因:175 未配 paper metadata registry,Qdrant 条目无 pmid 被 public_citation 过滤(244→136),剩下图断言 evidence 天然为空;176 配了 registry 所以 r3 一直正常(r3 在 175 只验收过 search 免 rerank 路径)。修复:paper_id 派生 DOI/PMCID 回填(d54419f)。教训:同一修复在不同环境(有无 registry)行为分叉,验收环境必须覆盖两种形态。

P-4 Dev-B1 v2 首提交补丁脚本中途中断

v2 首次 commit 落盘后发现 direct_flow_retriever 的参数三处(签名/audit/调用点)因补丁脚本中断未写入,真实 search 路径会 TypeError。已 amend 补齐+透传单测。教训:批量补丁脚本需落盘校验+端到端冒烟。

P-5 QA 带 session_id 的 search 异常慢

测试 agent 复测中观测:带 session_id 的 search 81s/120s+,无 session_id 同题仅 2s(疑历史注入链路)。QA 重启后未复现,未追到根因,记录待察。

P-6 chat 流一次卡「开始生成答案」

dev QA 进程陈旧状态下 chat/stream 在证据采纳后卡死 30 分钟(单线程 107% CPU 无网络等待)。重启 QA 后不复现(非流式 55.7s/流式 68.2s 正常)。记录为一次性进程状态异常,未追到根因。

P-7 私有问答 §6-3 例句「总结这篇论文」返回合法空态

验收文档原例句在修复后返回 hit:false/mode:empty——全链路正常(检索有货 0.45-0.48,但 top 块是作者列表/表头无方法结论语义,LLM 自谦答语被 R1-03 改判)。属 TL 裁决语义内的合法空态,非回归;S2 终验改用 TL 原题。教训:验收用例例句要选语义能被库内容回答的。


三、环境与部署问题

E-1 175 机器三次宕机(2026-09-11 全天)

15:01(疑旧仓 PlantAI-rag 的 8000 进程 89.9% CPU 拖垮用户态)、17:44、~18:50 三次宕机/重启。规律:数据库层(systemd neo4j/qdrant)自愈,应用层(生产 8090 栈与 dev 栈)需手动拉起。dev 栈重建脚本 /Users/jerry/haiguji/r4-dev-stack.sh(幂等:Ollama/QA 9271/methodology 9272/legacy 9273/vstore 9274/BFF 9090/vite 5180)。恢复探测用「ping + ssh banner」双信号(仅 TCP 通不代表 sshd 活)。风险提示:修复期间全部 commit 只存在于 175 本地,宕机三次无远程备份,若硬件持续故障有丢失风险(r4 已 push 消除)。

E-2 175 minerupy312 缺 accelerate

MinerU hybrid 后端在 175 启动期抛 ValueError: requires accelerate(torch 2.11 新版本要求)——恰好真实触发并端到端验证了 #38 的「自动重试+中文可读错误」链路。已补装 accelerate 1.15.0。部署 176 时需同步确认(176 的 mineru-cpu 环境为 CPU pipeline 后端,是否需 accelerate 待验)。

E-3 176 figures 本地图片源静默失效(路径漂移)

三条件缺二:install/sdk/.env 无 PLANTAI_FIGURES_MINERU_ROOT/REGISTRY 两键(代码 r3 已 env 化,部署漏配)、176 无 registry 文件 → _build_local_index 静默降级,所有答案配图走 PMC 外网。排查陷阱:strings 探 .so 探不到 env 键(字符串在 C 编译的别的段)→ 一度误判「176 装的是旧代码」;运行时加载模块实测 env 覆盖完好才纠正。教训:cython 产物验证必须运行时加载,不能 strings。修复:registry p2p 传 176(16.9MB/31288 行)+env 两键+BFF 重启。已知限制:176 上 58 个任务的 paper_id 全是 demo_paper/e2e_check 测试值,不在 registry,真实论文上传后本地索引才会生效。

E-4 figures PMC 外网:5s 超时 + 冷连接间歇失败 + 整体吞掉

176→EBI 实测:冷连接首次 TLS 握手 10s+ 超时、重连即 1.6-2.2s(5 连测 1 败 4 成)。两个缺陷叠加:①EXTERNAL_TIMEOUT=5.0 必超时;②_epmc_figures 外层 except 把已解析成功的图片一起吞掉(license 查询失败不应牺牲图片)。修复:15s + 失败自动重试一次(冷连接热路径)。验证:PMC6461668 2.4s 返回 4 图 + license cc by。

E-5 部署三事故:rsync --delete 误删 176 本地产物

源构建树(175 tooling/build/install)不含三个 176 本地产物,rsync -az --delete 全部删除:

  1. install/venv(1.8G Python 环境)→ 用 mineru-cpu python 建新 venv(--system-site-packages 复用 fastapi/uvicorn/torch 等)+pip 补 neo4j/qdrant-client/faiss-cpu/pymupdf 恢复;
  2. install/sdk/data(plantai.db/docgen/figures_cache)→ 从 install.bak 恢复;
  3. install/.env(vstore 的 VSTORE_* 键)→ 从 install.bak 恢复。 教训(已写入 DEPLOY_FLOW):后续部署 rsync 必须 exclude venv/sdk/data/.env(以及 qa/methodology/legacy-rag/vstore 各 env),或改用备份恢复流程。

E-6 start_all.sh 不杀在跑的 BFF + kill 误中 wrapper

start_all 内 uvicorn 起新进程时 8090 被旧进程占住 → 新进程静默退出,自检看到的是旧进程(新 env 永不生效)。杀进程用 pgrep -f 会误中 bash wrapper 而漏掉 uvicorn 本体。正解:lsof -ti tcp:8090 拿准确监听 PID。已写入 DEPLOY_FLOW §5f。

E-7 vstore 空库假象(install/.env 丢失连锁)

install/.env 被删后 vstore_restart 启动的进程无 VSTORE_* env,chunk 路径回落相对默认(data/vstore/chunks),health 显示 0/0——数据完好(1010 chunk 在 /srv/plantai/docgen)。恢复 .env+手动带 env 重启后 214/1010。教训:health 计数异常先查进程 environ,再怀疑数据。

E-8 176 vstore 存量数据全是压测样例(业务预期,非缺陷)

1010 chunk 全部来自 DOCGEN_PERF 批量压测与 TL 验收占位样例,无真实用户资料。私有 QA 对无关问句返回合法空态正确;对样例相关问句实测命中(hit:true、8 引用)。真实上传后才有业务数据。

E-9 175 主仓 QA env 端口为容器时代旧值

agent/qa/env/prod.env 的 NEO4J_URI=19788/QDRANT=27333 是容器时代旧值,175 现网裸进程是 19888/27433(部署树 env 已修正,主仓 env 未同步)。dev env 生成时需覆盖。主仓 env 文件修正属待办(影响未来裸跑主仓源码的场景)。

E-10 外网环境接入(跳板机方案)

本机不在内网时,经《海古纪/服务器/跳板机接入方案.md》:公网 ssh -p 26518 xzq@8.163.92.8(= 跳板机 A DNAT 隧道 → 175 本机 sshd)、ssh -p 26518 xzq@8.138.231.183(= 跳板机 B → 176),凭据用目标机账号。175 的 22 端口已关闭(sshd 仅 26518),ssh config 的 Port 26518 是正确的,勿改。


四、验证账与终态

  • 单测全绿:vitest 373 + r3debug 68(含 r4fixes 31)+ sdk 306 + vstore 106 + qa score_gate 9 + mineru retry 16(两树 8+8)+ html2docx 12 + privateqa 8 + intent 59。
  • S1 复测:测试 agent 六项全过、零缺陷单(API 复验 + 源码断言 + 单测三源)。
  • S2 终验(176 生产实测):#28 景甜 4.1s 空态/arginine 1.2s 30 条;#32 KG 0.007s;#27 30 条 title 全非空;chat 92s/16 sources/4333 字;figures PMC 4 图 cc-by + 本地源配置就位(受控验证 source:local);vstore 214/1010;私有 QA 命中;nginx 80 200。
  • 终态:175 feature @ faa8686(已 push)+ tag bugfix-r4-20260912;176 五服务(8090-8094)五上游全 ok,代码与 faa8686 等价(figures 两个补丁单独重编 sdk 同步)。
  • 回归矩阵:chat.js 动画未动;docgen 改动覆盖生成/导出/资料库;intent 双端词典一致;neo4j canonical 分支零改动;检索模式改动不影响 chat 全链。

附:关键修复文件索引

  • 前端:ui/src/components/bench/{SourceRow,KgPane,DocPane}.vue、ui/src/stores/{bench,docgen,chat}.js、ui/src/intent.js、ui/src/i18n/labels.js
  • 后端:sdk/app/services/{normalize.py,figures.py,privateqa.py,docgen/html2docx.py,docgen/html_css.py,docgen/intent.py,docgen/converter.py}、sdk/app/routers/docgen.py、vstore/vault.py、agent/qa/src/rag/qa_v1_1_73/{pipeline.py,score_gate.py,direct_flow_retriever.py}、agent/{methodology,legacy-rag}/api/methodology_routes.py
  • 文档:docs/acceptance-r4-20260911.md、docs/DEPLOY_FLOW.md(§5e/5f/5g)、本文