Files
PlantAI-rag-new/docs/CHANGELOG.md
T
jerryandClaude Fable 5 0875bb036c P0/M1: 四部分重构——frontend→ui、backend→sdk 改名 + 引用修复 + 骨架
- git mv 保留历史:ui/(Vue3+Vite)、sdk/(BFF 中间层)
- 路径语义修正:db_path/figures_cache 改相对 sdk/(BFF cwd),
  历史库 sdk/backend/data 迁移至 sdk/data/(会话/图片缓存无损)
- 引用修复 ~15 处:config.py、deploy/*.sh、vitest/playwright 配置、
  单测导入路径、docs、README、gitignore、.env.example
- 骨架:agent/{qa,methodology,legacy-rag,vendor}、knowledge/manifest.yaml、
  tooling/{compile,kb,crypto,assemble,audit,tools,scripts} + README
- 门禁验证:sdk pytest 125 通过、ui vitest 158 通过、
  生产 BFF 脚本重启四上游全绿 + 静态托管 + 会话库无损

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 12:56:47 +08:00

21 KiB
Raw Blame History

CHANGELOG.md —— 进度与决策记录(PM 独占写入)

2026-08-25

  • 计划批准:新前端 + 薄适配层方案获批。端口 8090(BFF)/ 5180(Vite dev),并行部署不切换。
  • M0 启动:远端目录树建立;8090/5180 端口复核空闲;本地 staging 目录 /Users/jerry/haiguji/PlantAI-rag-new/ 建立。
  • 契约文档定稿:PRD.md(81 个 FR)、API.md、UI_SPEC.md、ARCHITECTURE.md、TEST_PLAN.md 完成并锁定。
  • Mock 层完成:sdk/mock/mock_server.py + 21 个 fixtures(含 SSE 回放序列)。
  • 共享前端文件完成:ui/src/i18n/labels.js、ui/src/config/modes.js。
  • 环境就绪:plantai-bff conda 环境(3.11);npm 依赖 187 包(Vite 5.4.11/Vue 3.5.13);Playwright + Chromium headless shell 131 下载完成;mock server 在 8099 运行并全接口验证通过。
  • D0 探测完成(DISCOVERY.md,345 行)。契约偏差修正(基于真实上游):
    • Neo4j 当选 neo4j-plant-srt-direct-v1-full(bolt 18788,QA 7920 实际使用)。schema 为 canonical(SRT2CanonicalEntity/SRT2CanonicalAssertion),非假设的 :Entity;无全文索引,名字检索走 name_norm 前缀索引(0.09s)。
    • 抽取任务真实状态枚举 queued/running/completed/failed,无 progress 数值——BFF 按 stage 派生 progress_pct。
    • QA source 真实分数字段为 final_score;检索计划在 query_plan 键;native_graph_chains 为列表、graph_knowledge_chains 为 dict 双形态。归一化规则已更新。
    • 实测 search ≈92s(读超时调至 180s)、stream ≈37s。
    • processing-status/progress/summary/run-log 当前空数据(上游批次目录未配置),前端按空态处理。
  • 已知问题:QA 上游 DeepSeek LLM 余额不足(402 Insufficient Balance)——检索链路正常,chat 当前只出证据列表 fallback,无自然语言答案。需用户充值 DeepSeek 账户。开发不受阻(mock 覆盖);M2 验收对答案质量相应调整。
  • 上游重启记录:无。

M0 完成 → M1 启动(2026-08-25 晚)

  • M0 验收达成:契约文档、mock(8099 运行中且已按真实上游对齐:canonical schema / queued-runing 派生进度 / run-log JSON)、conda 环境、npm 依赖、Playwright、本地 staging + 远端副本、BFF 骨架 import 通过。
  • 本地开发环境补齐:.venv-backend(3.12,供后端 agent 本地自测)+ 本地 node_modules;deploy/sync.sh 排除规则修正(.venv-backend)。
  • 跨归属占位脚手架:sdk/app 全部模块 + ui main.js/App.vue 占位,由各 agent 在 M1 以真实实现替换。
  • M1 发射:A1/A2/A3(后端三线)+ B1/B2/B3(前端三线)+ T(测试用例)七个 agent 并行。前端三入口占位组件已由 PM 提供;文件归属含测试目录拆分(tests/ui/unit/b1|b2|b3,后端单测随代码 sdk/app/**/test_*.py)。
  • A1 完成(15 文件,29 单测全过):config/db/schemas/normalize/upstream/health/sessions/main + pyproject + run.sh + .env.example。7 条偏差全部 PM 裁决通过并回填 API.md(hop 中间态字段、来源聚合取首条、search answer 空串、PATCH 空 body 幂等、title_manual 保护、凭据仅入 BFF 配置、新增 python-multipart)。
  • 待办:A1 报告 A3 的 17 个测试失败(test_kg.py 用 ASGITransport 直挂裸 router 与 fastapi 0.141 不兼容;test_extraction.py 两处 respx 失败)——待 A3 汇报后统一派发。
  • B3 完成(工作台四 tab,54 单测全过,vite build 通过):BenchPanel/RetrievalPane/SourcesPane/SourceRow/ChainGroup/ExtractionPane/ProgressItem/KgPane/KgGraphView(手写 SVG 力导向,无第三方库)/KgEntityDetail/graphLayout/bench store/两 API 模块。15 条工作台文案已由 PM 合并进 labels.js,benchLabels.js 改为薄别名。
  • 集成对齐点(B3 提出,待各线就绪后统一处理):① chat store getter 名(currentEvents/currentMessage/messages,B2 确认);② bench 折叠由 B1 AppShell 控制(emit/props 接缝);③ pa-edge-grad SVG defs id 前缀;④ ExtractionPane 卸载时 stopPolling(BenchPanel onBeforeUnmount);⑤ kg 邻域深度 2 的 13s 提示已做。
  • A2 完成(QA 代理 + SSE 中继,36 单测全过):四端点 + STAGE_PHASE/STAGE_LABEL + 帧解析/重发/看门狗/重试。SSE 读超时采用 read=None + 应用层看门狗(producer task + Event.wait,规避 anyio.fail_after 毒化 generator 链的工程陷阱)。degraded 语义已 PM 裁决:仅 UPSTREAM_DOWN 为 true(API.md 已回填)。
  • A2 集成对齐点:A1 就绪后删除 qa.py/sse_relay.py 内本地等价实现(_fallback_normalize_qa 等),归一化以 A1 为准;真实上游冒烟(1.78MB search 响应、SSE 全流程)在远端做(本地 7920 不可达)。
  • A3 完成(图谱直连 + 抽取代理,88 单测全过):Neo4jService(实例回退 18788→19788→17687、TCP 预检、depth=1 绝不执行第二跳)+ 五 kg 端点 + ExtractionService(8000 主/7900 回落、progress_pct 派生、plan 409→null、spool 上传)+ 全套 respx/FakeDriver 单测。A1 报告的 17 个测试失败已被 A3 自行解决(测试切换到兼容 pytest-asyncio 的纯 async def)。5 条偏差全部 PM 裁决通过(count 语义、422 暂留原生格式待 M2 全局处理器收敛、plan 失败置 null 等,API.md 已回填)。
  • M2 集成前待办(PM 执行):① 补 pyproject dev 依赖 respx;② main.py 加全局 RequestValidationError 处理器(VALIDATION 信封);③ 删除 A2 本地等价实现切换 A1 normalize;④ 验证 A1 health 的 probe_neo4j 接缝;⑤ 远端真实 Neo4j/QA 冒烟。
  • 后端集成预检(PM,2026-08-25):三线代码合并后全量 pytest . = 119 passed(2.34s),仅有 5 个 deprecation warning(A1 main.py 的 on_event 弃用,建议转 lifespan——列入 M3 收尾清单,不影响功能)。后端三条线无测试冲突,接缝(config/upstream/envelope)互相兼容。
  • B1 完成(样式层 + 外壳 + 响应式 + 主题/健康 store,25 单测全过,build 通过 285KB/81KB):tokens 逐字复刻、四档断点、抽屉、覆盖层、visualViewport 键盘适配、http.js 统一错误。
  • PM 集成修复(B1 偏差裁决 + 接缝接线):① laptop 档折叠策略裁决为「首次进入无偏好时自动折叠,把手保留,用户显式展开被尊重」(CSS 改为响应 side-collapsed 状态 + AppShell watch tier);② AppShell 顶栏 title/status 接上 B2 sessions store(原返回 null);③ 移动端全屏覆盖层 tab 条接上 B3 bench store 的 setActiveTab(原点击无效);④ 验证:B1 25 测 + B3 54 测全过、build 通过。
  • B2 完成(会话与对话流式状态机,58 单测全过):chat store 全流程(落库→骨架→SSE→检查点→终态)、stop/retry/刷新恢复/揭示动画、sessions store、SseParser(多行 data/注释/CRLF/UTF-8 跨 chunk)、16 组件、markdown 消毒。手动冒烟:mock SSE 12 帧消费 + 18 模块 transform 全 200。
  • B2 偏差裁决 + PM 集成补丁:① labels 补 4 键(toolParams/toolResult/toolLog/graphSummary);② 消息内 tool 块无 API 产出路径——保留渲染器待数据源;③ checkpoint 时序(揭示完成才落终态)裁决通过;④ interrupted 为前端本地标注(后端枚举不变)裁决通过;⑤ 重试同位置替换、旧 DB 行不更新裁决通过;⑥ FR-CHAT-015 高亮链补全(bench store 加 highlightSource + setHighlightSource 2s 自动清除、SourcesPane 传 highlighted、SourceRow 滚动定位 + 2s 渐隐高亮)。验证:B3 54 测 + B2 58 测全绿。

M2 集成(2026-08-25 夜)

  • 真实栈部署:远端 BFF 8090(plantai-bff + python-multipart 补齐)、Vite dev 5180(代理→8090)、集成检查脚本 11/11 通过(健康/qa info/会话/Neo4j canonical/实体搜索/抽取/真实 search ≈90s)。
  • 修复两个集成接缝 bug:① A2 的 get_qa_client 误用 A1 的 async get_client() 返回 coroutine → 裁决为「QA 流式路径独立持有 read=None 的 client,不复用 A1 单例」(语义不同:SSE 长静默会被 300s 读超时误杀);② A3 _tcp_reachable 未解包 open_connection 的 (reader, writer) 元组。
  • PM 集成单点修改:main.py 转 lifespan + 全局 RequestValidationError→VALIDATION 信封;pyproject 补 respx;远端 @playwright/test 安装 + 根 node_modules symlink(T 方案 b)。
  • SSH 隧道三连坑(PM 记录,供后续复用):pkill 自匹配杀 shell(用 [x] 正则技巧);ExitOnForwardFailure 被配置里坏掉的 RemoteForward 15721 触发退出;ClearAllForwardings=yes 会清掉命令行自己的 -L。
  • 响应式断链缺陷(M2 核心 bug):真实浏览器中流水线相位卡冻结。六轮探针定位:fetch 层 12 个 progress + 3MB complete 全到达 → store 状态正确(探针直读 pinia)→ 唯一 PipelineCard props 已是 done 但 DOM textContent 冻结。根因:send()/retry() 里 const aMsg = newSkeletonMessage(); this.messages.push(aMsg) 后闭包持有 raw 对象,所有 SSE 相位突变作用在 raw target 上——Pinia reactive 代理读值正确但突变不触发渲染,子组件因 props 引用相等被 Vue 跳过 patch。B2 的 vitest 只断言 store 状态未测真实渲染链,故未暴露。修复:三处 push 后改持 this.messages[this.messages.length - 1](代理)。修复后 M2 验收 12/12 全过(相位推进 4 快照/47s、答案 690 字、来源、图谱、SQLite 刷新恢复、无 JS 错误)。
  • 诊断探针存档:deploy/m2_probe{1..6}.js(chunk 级/网络层/store 直读/组件 props/卡片枚举),保留备查。

M3 功能面补齐(2026-08-25 深夜)

  • 真实 KG 数据缺陷修复(PM):① 邻域 0 边——真实库边属性无 source_canonical_id/target_canonical_id(端点在两端节点上),A3 组装代码从边读这两个键恒 None;改为 Cypher 投影时用 startNode(r)/endNode(r) 注入;② overview 0/0——1644 万边 COUNT 聚合冷缓存超过 10s 查询超时,新增 OVERVIEW_QUERY_TIMEOUT=60s 用于 overview 两查询;③ 自环边(真实库 gene_structure 等实体自身关系)在组装层过滤。验证:overview 200/200(gene 35 万)、邻域 21 节点 8 边 0 自环。
  • 部署工具:deploy/bff_restart.sh(setsid 脱离 SSH + [u] pkill 技巧,解决 SSH 后台挂起坑)。
  • M3 响应式接线修复(PM):① 平板档汉堡/工作台按钮不可见——responsive.css 规则写 .top-bar.has-tools 但该类挂在 .app-shell 上,选择器永不匹配;② 手机档工作台按钮开的是右抽屉而非全屏覆盖层——openBench() 未按 tier 分派;③ 覆盖层内两套 tab 条重复——隐藏 BenchPanel 内部那套保留外壳 tab 条(含关闭按钮)。
  • M3 验收 16/16 通过:真实 KG(实体搜索/邻域图谱/抽取任务列表)、平板抽屉(打开/Esc 关闭)、手机档(底栏隐藏/覆盖层打开/tab 切换)、主题切换(浅色 canvas 精确 #F6F8FC)。三档视口截图存 artifacts/m3/。

M4 测试轮次(2026-08-25 凌晨)

  • R1 全量结果:L1+L2 后端 119/119(行覆盖 87% 达标);L3+L4 前端 137/137(81.54% 达标);L5 Playwright 三档 19 pass/17 fail/12 skip → 收敛 8 缺陷;L2s 上游 smoke 7/7;FR 追溯主门禁 81/81 双向零失配。
  • R1 缺陷 8 项已批量派发:BUG-R1-07 Blocker(http.js 30s 读超时 < search 92s)→ B1;BUG-R1-01 Major(kg 搜索丢 q 参数)→ B1;BUG-R1-02/03/04/05/06 Major(会话高亮/删除死代码/QA 降级未禁用/错误信封误显示/markdown 零调用)→ B2;BUG-R1-08 Minor(health 索引误报)→ A3。
  • T 侧环境说明:远端补装 pytest-cov;曾误 --save-dev 动 package.json 已还原(md5 一致);证据归档 ~/5090/teamWorkspace/zh/r1_test_evidence/。
  • R1 修复进展:A3 已交付 BUG-R1-08(probe 列表全等比较误报索引缺失——真实实例另有 canonical_id 约束索引;改为成员判断 + 2 锁定单测,23/90 过,真实冒烟 detail:None)。B1 已交付 BUG-R1-01/07(http.js 默认超时 600s 覆盖 API.md 全表、get 增 query 序列化、FormData 走 multipart;32 测过;隧道实测 KG 搜索 17 条含 q 参数、search 47.7s 不自断)。B2 已交付 BUG-R1-02~06(selectSession 同步 activeId;SessionItem 删除按钮+右键+确认弹层 Teleport;ChatPanel 接 health store 降级禁用;err.code 优先映射 + errText 透传;qaToBlocks/_finalizeReveal 走 renderMarkdown;70 测过,全前端 156 测)。
  • R1 修复集成(PM):本地全量回归后端 121 测/前端 156 测全绿;mock 本地远端 md5 一致;BFF 重启后 health 无索引误报;R2 全量回归已派发 T。
  • R2 全量回归通过(T):后端 121/121、前端 156/156、Playwright 48 条(35 pass/12 skip 依赖充值/1 flake 复跑通过)、上游 smoke 7/7、行覆盖 87%/80.59%、FR 追溯 81/81。R1 八缺陷全确认修复(含 E2E-01 刷新恢复补验三档全通)。无新缺陷。唯一失败为环境性 flake(tablet 主流程 300s 超时,单独复跑 52.3s 通过,上游 QA 串行排队所致)。T 清理了全部测试污染会话数据。
  • M4 判定(PM):主/辅门禁全达标、产品用例全 pass → 按 TEST_PLAN 纪律收尾。收尾前采纳两处加固:① E2E 真实流超时 480s/终态等待 360s(T 测试代码);② Vite 忽略 coverage 目录(测试期覆盖率文件触发 198 次页面重载,干扰 E2E 与浏览器访问)。
  • M5 最终验收通过(PM,2026-08-25):deploy/m5_acceptance.js 15/15 全过。生产形态打通(BFF 8090 单进程静态托管,修复 dist 路径解析:sdk/ui/dist → 项目根;sync 排除 dist 需单独同步)。真实 SQLite 历史恢复(相位卡 5/5、引用 chip 高亮定位)、真实问答全链路(答案 698 字 + 4 引用)、三档视口档位全正确。docs/ACCEPTANCE.md 归档。项目收官——遗留唯一外部依赖:DeepSeek 余额(充值即恢复,零代码改动)。

DeepSeek 恢复与 QA 修复(2026-08-25 下午)

  • 诊断:用户充值后 QA 仍 402。实测三个 DeepSeek key:QA 旧 key(sk-9d70bc)与 PlantAI-rag key(sk-9de0a3)余额均不足;PlantAI-dev 的 NEW_API_KEY(sk-9c0235)余额充足。用户指示用该 key。
  • 手工重启的弯路(PM 记录,教训):① 整行 shlex.quote 导致 source 时变量全失效;② 保留旧进程 CONDA_*/PATH 污染新 shell 致 conda activate 崩溃;③ source 缺 set -a 导致变量不 export 进 uvicorn;④ runtime env 文件缺 V15_QDRANT_URL 等进程内联覆盖项。最终用户提供官方管理脚本解决。
  • 正确路径:~/5090/PlanAI-cooperate/RAG/rag-develop/start_plantAI_RAG.sh 统一管理 QA(7920)/Neo4j(18788)/Qdrant(26333)/方法学(8000)/Ollama。换 key = 更新 runtime/qa_v1_1_73.env(已完成,备份 .bak_oldkey)+ 官方脚本 start。脚本显式 QA_V1_LLM_MODEL=deepseek-chat(flash 模型在新 key 下输出截断)、嵌入服务 QA_V1_EMBED_URL=Ollama bge-m3、BGE CUDA 等全套配置。
  • 验证结果:PlantAI-rag-new 问答——自然语言答案 1379 字 + 15 条来源(degraded_execution=False);PlantAI-dev 知识问答——success:True + 2671 字答案 + 14 来源(需把 QA_V1_1_73_TIMEOUT 从 300 提到 600,完整链路实测 216~273s;已写入 .env 并重启 9011,备份 .env.bak_qa_timeout)。
  • PlantAI-dev 9011:仍用手动方式重启(官方 manage_plantai.sh 默认管 9000 端口),source .env + set -a 后 uvicorn 拉起,已验证 env 含新超时与 7920 地址。
  • 运维提示:QA 服务重启一律走官方脚本 bash start_plantAI_RAG.sh restart|start|verify,不要手工起进程。

QA 提速三项(2026-08-26,用户批准方案 2/3/4,否决 1 不改跳数)

  • 方案 2 证据量下调:探索发现上游 QA_V1_MAX_EVIDENCE 环境变量是死代码(pipeline 无消费者),真正决定 LLM 证据量的是请求级 ablation 透传(默认 top_k_for_llm=30)。已在 modes.js 的 ask/plan 加 ablation:{top_k_for_llm:20, graph_min_evidence:10}(配套下调防图证据挤压),evidence_first:true。API.md 契约已同步。
  • 方案 4 Neo4j 扩容:deploy/neo4j_recreate.sh 固化重建命令(原容器手工 docker run 创建、命令已丢失)。已执行:heap 4G→8G/12G→24G、pagecache 保持 24G(数据仅 14G)、dbms.memory.transaction.total.max 显式 16G。实体 3,820,996 / 断言 8,246,875 校验通过,QA 已恢复。踩坑:Neo4j env 映射规则(单下划线→点、双下划线→下划线),total__max 写成 total_max 才正确。
  • 方案 3 两级体验:BFF relay_stream 加 evidence_first 并发打上游 /search,归一化后作为非终态 event: evidence 帧在 progress 与 complete 之间先推(search 失败静默降级、complete 后不再注入);qa.py 剥离 evidence_first 防上游 422;前端 api/qa.js 加 evidence dispatch、chat.js 加 onEvidence(_evidenceOnce 守卫,挂 sources/graph 块 + 生成相位 desc 更新,complete 整体替换自动覆盖保证引用编号)。测试:后端 125 测 / 前端 158 测全过。
  • 集成验证(2026-08-26):接口级 SSE 实测帧序列 = 20 progress + 1 evidence(第 5 帧)+ 1 complete(第 22 帧)——证据先于终态约 3 分钟到达。M5 回归 12/13(唯一失败项是历史会话数据相关的引用 chip 条件检查,非产品回归;真实问答三项全过:答案 616 字 + 相位全 done + 3 引用 chip)。
  • 运维备注:远端 sync.sh 的 --delete 偶尔会把新文件漏掉(scp 直传兜底);公网 SSH 间歇性 Connection reset,长任务一律 setsid ... > /tmp/xxx.log & disown 后台化再轮询。

多流重构:切换会话不再中断(2026-08-26 用户反馈)

  • 行为变更:原 FR-SESSION-004「切会话即中断」废止。新行为:切换会话时流在后台继续(sessionMsgs 按会话缓存消息数组,流回调持续写入;streamCtx 每会话独立持有 AbortController/检查点/事件/揭示状态),切回时直接拿实时数组。stop/重试只作用于当前会话的流。busy/currentMessage/currentEvents/reveal 改为从当前会话 ctx 派生的 getter。
  • 踩坑(Pinia reactive 代理陷阱):_finishCtx 用 streamCtx[sessionId] === ctx 判断清理——读出的代理对象与闭包持有的 raw ctx 恒不相等,清理永远失败、busy 永远 true。修复为按 key 删除。
  • currentEvents 保留:终态后 ctx 被清理,事件快照保留到 lastEvents,bench 阶段卡在完成后持续可看。
  • 测试:chat.store 19 测全过(重写「切会话中断」为「切走后台继续」),全前端 158 测全过。已部署(index-DTp5vppj.js)。

图文并茂长篇回复(2026-08-28,用户要求 5000 字以上)

  • 上游镜像改造(用户批准 docker commit 方案):快照 :20260828-orig 回滚锚点 → 修改 answer_composer.py(删 short paragraphs 约束、加「至少 5000 中文字」目标 + [[FIG:PMCID]] 图片位置标记指令、max_tokens 3500→12000)→ 提交 :20260828-longanswer → 同名重建。踩坑:原部署的 ./models 挂载目录是空的(reranker 模型从来不在里面),导致 /chat 500("Repo id must be in the form...")——重建时补挂真实模型 /home/xzq/5090/PlantAI-rag/bge-reranker-base:/models/bge-reranker-base:ro。QA_V1_LLM_TIMEOUT=300 经环境变量注入。
  • BFF 图片服务:services/figures.py(本地 MinerU 索引 + Europe PMC fullTextXML 解析 + license 查询 resultType=CORE)+ routers/figures.py(/api/figures/{pmcid} 清单 + /api/figures/proxy 图片代理带磁盘缓存)。踩坑:graphic 正则误抓许可链接/PDF(需 content-type="image" 过滤);/proxy 路由被 /{pmcid} 捕获(声明顺序修正)。
  • 注入逻辑:normalize.inject_figure_markdown(纯同步,figures_map 注入)+ sse_relay._inject_figures_async(异步预取)+ qa.py /chat 同步端点同样注入。LLM 输出 [[FIG:PMCID]] 标记 → BFF 解析替换为 ![]() 图注块;无标记时按 [PMID: xxx] 引用位置兜底注入;总图数上限 8。
  • 前端:markdown.js image 规则 → <figure class="md-figure"> 图注块(caption 带许可);AssistantMessage 点击放大遮罩(Teleport + Esc/点击关闭)+ capture 委托的加载失败隐藏。
  • 看门狗适配长文:STREAM_IDLE_TIMEOUT 240s → 1200s——长文时代上游图检索静默期可超 240s(高负载下更久),原值会误判超时掐断正常流。
  • 最终端到端验证(真实 QA + 真实图片):答案 9938 字 / 17 小节 / 8 张图片注入 / 无 FIG 残留,final_answer 43.9s。m5 回归 8/8 通过(真实问答项在负载 62+ 时超过旧 360s 超时,属测试阈值问题已调 900s;功能经独立验证通过)。
  • 已知权衡:高负载下(服务器被同事 iqtree/MinerU 任务挤占时)单次完整问答可能 5-15 分钟——这是上游图检索是 CPU 密集串行链路的固有特性,错峰使用体验最佳。