forked from admin/PlantAI-rag-new
docs(priv): 阶段0 私有资料问答文档先行——PRD §17 FR-PRIV-001~008 + UI_SPEC §9 + 原始测试计划 + 团队上下文 + A1/T1 任务书
用户需求:客户上传 PDF 等资料进行向量化并追加进向量库,且问答可检索。 决策:全局检索融合 / BFF 直连 DeepSeek 生成私有回答 / 两路并行展示(命中才显示) / 「我的资料」管理界面挂文档 TAB 空态。改动仅限本分支,QA 金标树与红线零改动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+22
@@ -396,3 +396,25 @@ SHELL: 001–007(7)|THEME: 001–006(6)|SESSION: 001–009(9)|
|
||||
**FR-BIO-032 发布与编译**:生信服务 .so 编译流水线(compile_bioflow.sh)+ 内核 4 镜像构建(build_all.sh)+ rag 侧 BIOFLOW_ENABLED 装配开关。(验收:两条流水线各自产出;SHA256SUMS 与泄露门禁通过)
|
||||
|
||||
BIO: 001–032(32)|上述 81 + BIO 32 = **合计 113 个功能点**。生信用例追溯必须覆盖全部 32 项 FR-BIO(规模与门禁见 TEST_PLAN §10)。
|
||||
## 17. FR-PRIV 私有资料问答(客户上传资料 → 向量化 → 追加向量库 → 问答可检索)
|
||||
|
||||
模块范围:客户通过对话输入框上传 PDF/DOCX/TXT 资料,资料向量化后追加进向量库(复用既有 docgen/vstore 上传链路);**任何问答提问同时并行检索私有资料**(全局融合),命中时在原 QA 答案后追加独立「私有资料参考」块(片段+相关度+带引用短答,两路并行不混排);未命中或服务故障用户无感;提供「我的资料」管理界面(列表+删除)。QA 8091 金标树零改动;私有资料回答由 BFF 新端点直连 DeepSeek 生成。
|
||||
|
||||
**FR-PRIV-001 上传入库(回归确认)**:客户拖拽 PDF/DOCX/TXT 到输入框 → `POST /api/docgen/library` → vstore `/api/vstore/ingest` 向量化加密入库 → BFF 落 doc_library。(验收:上传成功返回条目;「我的资料」列表可见;原有限制已解除——无大小/数量限制、有进度条)
|
||||
|
||||
**FR-PRIV-002 chunk 级索引**:入库时正文按段落聚合切块(目标 600 字/单块上限 8 段/相邻重叠 1 段/每文档上限 200 块,表格矩阵化参与),经 input 数组批量嵌入(batch 16 × 并发 4)追加进独立 chunk 索引(与原 doc 级 title 索引并存、互不影响)。(验收:ingest 响应含 chunk_count>0 且 chunk_ok=true;正文片段可被 search-chunks 命中;doc 级 /search 响应与改动前逐字段一致)
|
||||
|
||||
**FR-PRIV-003 全局并行检索**:ask/search 两模式提问同时触发私有资料检索(fire-and-forget,失败静默)。(验收:命中出块;未命中/服务故障零痕迹——不出现任何块与提示,原 QA 答案不受影响)
|
||||
|
||||
**FR-PRIV-004 私有资料回答**:BFF 新端点 `POST /api/qa/private` 检索 chunk 索引,命中则直连 DeepSeek 生成 300 字内带 `[资料n]` 引用的 markdown 短答(system 约束:只能依据资料回答、不得编造、不足则答「资料中未找到相关信息」)。(验收:answer 引用编号与 items 一一对应;未命中返回 hit:false;vstore/LLM 故障返回错误信封且前端静默)
|
||||
|
||||
**FR-PRIV-005 私有资料参考块**:命中时助手消息追加 `private_doc` 块(标题「私有资料参考」+ 短答 + 条目列表[编号、资料名、相关度、片段]);与 QA 答案两路并行不混排;终态持久化、刷新后完整恢复;流未收口时私有结果不被 complete 覆盖(pending+flush)。(验收:ask/search 两模式卡片并行展示;刷新恢复;竞态用例不丢块)
|
||||
|
||||
**FR-PRIV-006 我的资料管理**:文档 TAB 空态区展示「我的资料」列表(名称/大小/时间)与删除(二次确认;BFF doc_library 行删除 + vstore 密文与 chunk 联动删除)。(验收:列表加载正常;删除后列表刷新,且该资料不再被检索命中)
|
||||
|
||||
**FR-PRIV-007 存量重建与健康**:存量资料(现 210 条)经后台 CLI 重建 chunk 索引(不进 HTTP,避免超时);`/health` 暴露 chunk_count。(验收:重建完成后 chunk_count>0;重建期间 /health /search 保持可服务)
|
||||
|
||||
**FR-PRIV-008 降级与隔离**:私有检索/LLM 故障不影响原 QA 问答;docgen 模板检索(doc 级索引)行为零变化;QA 金标树(8091)与红线文件零改动。(验收:停 vstore 后 QA 问答照常;docgen 全链路回归通过;红线 diff 为空)
|
||||
|
||||
索引行追加:`PRIV: 001–008(8)|上述 113 + PRIV 8 = 合计 121 个功能点。私有资料用例追溯必须覆盖全部 8 项 FR-PRIV(用例表与门禁见 docs/PRIVATE_DOCS_TEST_PLAN.md)。`
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 私有资料问答(FR-PRIV)· 原始测试计划
|
||||
|
||||
> 本文件为本次调整的**原始测试计划**,工程内留存(docs/PRIVATE_DOCS_TEST_PLAN.md)。
|
||||
> 对应功能:客户上传 PDF 等资料 → 向量化 → 追加向量库 → 问答可检索(PRD §17 FR-PRIV-001~008)。
|
||||
> 用户纪律(2026-09-07):测试用例 100% 覆盖所调整内容;每轮测试均有过程记录(TEST_REPORT_R*.md);
|
||||
> 每轮完毕后统一修改再开新一轮,直至全部问题解决;TL 终验后把手工验收方法写入「PlantAI-new测试用例一览.xlsx」的知识库 sheet。
|
||||
|
||||
## 1. 调整内容范围(用例必须覆盖的全部对象)
|
||||
|
||||
| 层 | 内容 |
|
||||
|---|---|
|
||||
| vstore(P1) | chunks.py(build_chunks 切块参数/ChunkIndex upsert/remove/search/rebuild_all)、embed.py embed_batch_chunked(批量 16/并发 4/失败降级)、vault.py add/delete 钩子(chunk 失败不阻断 doc 级 + chunk_count/chunk_ok/chunk_error 返回)、api.py search-chunks/rebuild-chunks/health chunk_count、settings.py VSTORE_CHUNK_PATH、scripts/rebuild_chunks.py CLI、存量 210 条重建 |
|
||||
| BFF(P2) | services/privateqa.py(ask_private:检索→去重→拼上下文→DeepSeek 短答)、routers/private_docs.py(POST /api/qa/private 三态)、schemas.py(PrivateQARequest/PrivateDocItem/PrivateDocBlock 入 Block union)、main.py 路由注册、client.py search_chunks、llm.py complete_text timeout 参数 |
|
||||
| 前端(P3) | api/private.js askPrivate、chat.js _firePrivate/_appendPrivate/_flushPrivate(ask/search 两模式、retry、竞态 pending/flush、防重入)、AssistantMessage.vue private_doc 块分支、i18n/private.js、PrivateLibraryPane.vue、DocPane 空态挂载、api/docgen.js removeLibrary(204 处理) |
|
||||
| 回归红线 | docgen 模板检索(doc 级 /search 逐字段一致、上传/generate/导出全链路);QA 金标树 8091 零 diff;红线文件零 diff;BFF 编译白名单未扩大;断流崩溃场景不存在(新模块无 yield) |
|
||||
|
||||
## 2. 测试分层(沿用 TEST_PLAN §1)
|
||||
|
||||
- **L1 单元**:vstore(chunks/embed/vault 钩子)、BFF(privateqa 纯逻辑、schemas union 校验)、前端(chat store 竞态逻辑、http 封装)。
|
||||
- **L2 接口**:vstore 端点(search-chunks 三态/rebuild-chunks/health)、BFF /api/qa/private 三态 + docgen library CRUD 回归。
|
||||
- **L2s 部署冒烟**:vstore 明文部署重启、chunk 存量重建 CLI、BFF 编译部署重启、前端构建。
|
||||
- **L3 前端**:组件测试(private_doc 块渲染、PrivateLibraryPane、竞态场景)。
|
||||
- **L4 端到端**:浏览器实测 ask/search 两模式、上传→检索闭环、刷新恢复、删除联动。
|
||||
|
||||
## 3. 覆盖率判定(100% 的可验证判定)
|
||||
|
||||
1. **功能点追溯**:每个 FR-PRIV-001~008 在用例表至少 1 条用例,双向追溯完整(无孤儿用例)。
|
||||
2. **调整对象追溯**:§1 表格中每个调整文件/端点/函数至少 1 条用例(chunk 索引的切块参数边界、批量嵌入失败降级、to_thread 阻塞、pending/flush 竞态、防重入、204 空体、三态信封等均为显式用例)。
|
||||
3. **边界与异常**:空库检索、低分阈值(min_score=0.30 两侧)、超 top_k clamp、每文档 200 块上限、同 doc 去重(每 doc≤3 块)、12k 上下文截断、LLM 40s 超时、vstore 宕机、LLM 宕机、上传超长 PDF。
|
||||
4. **回归**:docgen doc 级检索响应逐字段、QA 8091 服务零改动(git diff 空)、红线文件 diff 空。
|
||||
|
||||
## 4. 环境与命令约定
|
||||
|
||||
- 服务器:ssh -p 26518 xzq@192.168.0.175(内网)或 8.163.92.8;仓库 /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new(分支 feature/bioflow-conversation-orchestration);部署树 /home/xzq/5090/teamWorkspace/zh/plantai-rag-new-deploy-unified。
|
||||
- vstore 测试:venv = /home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python;pytest 跑 vstore/tests/(新增 test_chunks.py);端点 curl http://127.0.0.1:8094。
|
||||
- BFF 测试:sdk 测试沿用既有 pytest 布局(services/test_*.py 同目录);端点 curl http://127.0.0.1:8090。
|
||||
- 前端测试:ui 下 vitest(npm test;新增 tests/private_docs/)。
|
||||
- 部署仅 TL 执行;agent 不 commit 不部署。
|
||||
|
||||
## 5. 轮次纪律(用户要求,铁律)
|
||||
|
||||
1. T1 按用例表逐轮执行 → 每轮产出 `docs/team/TEST_REPORT_PRIV_R{n}.md`(缺陷编号 BUG-PRIV-R{n}-{序号}:复现步骤/预期/实际/对应用例号)。
|
||||
2. 每轮全部问题**统一汇总**交 A1 修复 + 自测 → 交回 T1 复测(新轮次)。
|
||||
3. 缺陷分级:阻断(修复前不得进下一轮)/严重/一般/轻微(沿用 TEST_PLAN §4)。
|
||||
4. 循环直至某轮缺陷数为 0 → TL 终验。
|
||||
|
||||
## 6. 验收方式(TL 终验清单)
|
||||
|
||||
1. L1/L2/L3 全绿(pytest/vitest)。
|
||||
2. curl 端到端:upload→ingest(chunk_count>0)→search-chunks 命中(snippet/score)→/api/qa/private 三态→delete 联动消失→docgen /search 逐字段回归。
|
||||
3. 浏览器:ask+search 两模式私有卡片并行、未命中无感、刷新恢复、管理界面删除闭环。
|
||||
4. 回归:docgen 上传/generate/导出全链路;QA 金标树 git diff 空;红线文件 diff 空;白名单未扩大。
|
||||
5. 手工验收测试方法写入「PlantAI-new测试用例一览.xlsx」知识库 sheet(本地 docs/ 下)。
|
||||
|
||||
## 7. 用例规模预估
|
||||
|
||||
L1 单元 ~25(vstore 12 / BFF 8 / 前端 5);L2 接口 ~18(vstore 9 / BFF 9);L2s 部署冒烟 ~5;L3 前端 ~8;L4 端到端 ~6。合计约 **60 条**(TL 复查以双向追溯完整为准核定精确数)。
|
||||
@@ -316,3 +316,31 @@ B2/B3 组件必须复用 B1 在 `styles/base.css` 与原型中定义的类名,
|
||||
### 8.7 生信类名复用约定(在 §7 清单上追加)
|
||||
|
||||
`flow-path-card`、`flow-form-card`、`flow-file-card`、`bioflow-progress-card`、`flow-archive-card`、`biojobs-pane`、`bioarchive-pane`。其余(按钮/输入/进度条/徽章/面板容器)一律复用 §7 既有类名,不得另起炉灶。
|
||||
## 9. 私有资料问答组件规格(FR-PRIV)
|
||||
|
||||
### 9.1 私有资料参考块(`private-doc-block`,对话内)
|
||||
|
||||
| 元素 | 规格 |
|
||||
|---|---|
|
||||
| 卡体 | surface-1 + hairline,r-lg,padding 14px 16px,margin 14px 0(同 flow-path-card 卡体) |
|
||||
| 标题 | 「📚 私有资料参考」12.5px/600/ls .3px |
|
||||
| 短答区 | markdown 渲染(markdown-it + DOMPurify,同 text 块纪律),12.5px/1.65,最大宽 100% |
|
||||
| 条目行 | 上 1px hairline 分隔;编号 `[资料n]` 11px mono 相位色 `--pa-t-done` 底白字;资料名 12px ink 超长省略;相关度 11px mono ink-muted |
|
||||
| 片段区 | snippet 12px ink-muted,max-height 64px 溢出隐藏 + hover 展开 |
|
||||
| 空答态 | answer 为空时仅显示条目列表(不显示空白答区) |
|
||||
|
||||
### 9.2 我的资料面板(`private-library-pane`,文档 TAB 空态区)
|
||||
|
||||
| 元素 | 规格 |
|
||||
|---|---|
|
||||
| 挂载 | DocPane 空态区(`v-if="!docgen.activeArtifact"`)顶部;有活动文档时隐藏 |
|
||||
| 标题 | 「📁 我的资料」12.5px/600/ls .3px + 右侧条目计数 11px ink-subtle |
|
||||
| 列表项 | 复用 session-item 形态:名称 13px(超长省略)+ 大小/时间 11px ink-muted;hover 显示删除按钮 |
|
||||
| 删除按钮 | pane-btn 同款 12px;点击 window.confirm 二次确认后调 DELETE |
|
||||
| 空态 | 「尚无上传资料。在对话框拖拽 PDF / DOCX / TXT 上传。」12px ink-subtle |
|
||||
| 加载/错误态 | 加载中 11px ink-subtle;加载失败显示重试按钮(pane-btn) |
|
||||
|
||||
### 9.3 类名复用约定(在 §7 清单上追加)
|
||||
|
||||
`private-doc-block`、`private-library-pane`。其余(按钮/列表项/分隔线/徽章)一律复用 §7 既有类名。
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# 私有资料问答(FR-PRIV)· 团队共享上下文
|
||||
|
||||
> docs/private_docs_team_context.md —— A1(编码)与 T1(测试)开工前必读。仿 docgen_team_context.md 纪律。
|
||||
|
||||
## 1. 目标与范围(只做这些)
|
||||
|
||||
客户上传 PDF/DOCX/TXT → 向量化 → 追加向量库 → **问答可检索**(PRD §17 FR-PRIV-001~008)。四决策已拍板:全局检索融合;私有答案 BFF 直连 DeepSeek;两路并行展示(命中才显示);「我的资料」管理界面挂文档 TAB 空态。
|
||||
|
||||
## 2. 服务器事实(不可想当然)
|
||||
|
||||
- 仓库 `/home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new`(分支 feature/bioflow-conversation-orchestration,当前 HEAD 759427b);部署树 `/home/xzq/5090/teamWorkspace/zh/plantai-rag-new-deploy-unified`。
|
||||
- 端口:BFF 8090(0.0.0.0)、vstore 8094(127.0.0.1 单 worker 明文 Python)、QA 8091(金标树红线)。venv = /home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python(py3.12)。
|
||||
- vstore 数据根:deploy-unified/docgen/(vault 210 个 .enc + index/index.json);embed 走 Ollama(127.0.0.1:11434,bge-m3:567m 1024 维,实测单条 3.44s、input 数组 4 条 0.32s)。
|
||||
- 上传链路已存在(勿重造):BFF POST /api/docgen/library → vstore /api/vstore/ingest → doc_library 表;前端 uploadLibrary/listLibrary 已有。
|
||||
- 生产 .env 已配:VSTORE_BASE_URL、DOCGEN_LLM_*(deepseek-chat)。
|
||||
|
||||
## 3. 改动文件清单(只动这些;多动一个即违规)
|
||||
|
||||
vstore 侧(明文,不编译):`vstore/chunks.py`(新)、`vstore/embed.py`、`vstore/vault.py`、`vstore/api.py`、`vstore/settings.py`、`vstore/scripts/rebuild_chunks.py`(新)、`vstore/tests/test_chunks.py`(新,T1)。
|
||||
BFF 侧:`sdk/app/services/privateqa.py`(新)、`sdk/app/routers/private_docs.py`(新)、`sdk/app/schemas.py`、`sdk/app/main.py`、`sdk/app/services/docgen/client.py`、`sdk/app/services/docgen/llm.py`。
|
||||
前端:`ui/src/api/private.js`(新)、`ui/src/stores/chat.js`、`ui/src/components/chat/AssistantMessage.vue`、`ui/src/i18n/private.js`(新)、`ui/src/components/bench/PrivateLibraryPane.vue`(新)、`ui/src/components/bench/DocPane.vue`、`ui/src/api/docgen.js`、`ui/tests/private_docs/*`(新,T1)。
|
||||
文档(TL 独占):PRD.md、UI_SPEC.md、PRIVATE_DOCS_TEST_PLAN.md、team/ 下任务书与轮次报告。
|
||||
|
||||
## 4. 红线(零改动,diff 必须为空)
|
||||
|
||||
- QA 金标树 8091(agent/qa 与部署树 qa 全部文件)。
|
||||
- 前端:stores/modes.js、labels.js、bench.js、api/qa.js、sse/parser.js、PipelineCard.vue。
|
||||
- vstore:retrieval.py、parsing.py、backend.py、crypto.py(chunk 能力全部新写,不改造既有模块)。
|
||||
- sdk:routers/qa.py、services/sse_relay.py、tooling/compile/compile_sdk.sh 白名单(不动)。
|
||||
- docgen 既有行为:doc 级 title 检索、模板匹配、生成链路——行为零变化。
|
||||
|
||||
## 5. 技术纪律
|
||||
|
||||
- vstore 侧纯明文部署,禁止擅自引入新依赖(只用 faiss/numpy/pymupdf/python-docx/Ollama HTTP 既有件)。
|
||||
- BFF 新模块**禁止 yield/SSE**(Cython 协程取消断言会崩 BFF);新模块可编译 .so,不进白名单。
|
||||
- 服务层只用 dataclass/dict/stdlib;pydantic 只进 schemas.py。
|
||||
- 零硬编码:路径/URL 全部环境变量或设置推导(VSTORE_CHUNK_PATH 等)。
|
||||
- 嵌入纪律:批量数组(batch 16 × workers 4);失败重试一次仍失败降级零向量;chunk 失败不阻断 doc 级入库。
|
||||
- 同步阻塞:api.py 端点内同步段一律 `asyncio.to_thread`。
|
||||
|
||||
## 6. 纪律(同 docgen_team_context 十条)
|
||||
|
||||
1. 只动 §3 清单文件;2. 不 commit、不 push、不部署(TL 统一执行);3. 测试 agent 不修改任何产品代码;4. 不自连生产服务做破坏性操作(vstore 重启/重建由 TL 执行);5. 凭据不落文件不打印;6. 改动必须能说明对应哪个 FR-PRIV;7. 每轮测试产出轮次报告;8. 自测通过才交付;9. 有疑问先问 TL 不要自行裁决;10. 完成任务后回报 TL。
|
||||
@@ -0,0 +1,53 @@
|
||||
# 任务书 · A1(编码 agent)—— 私有资料问答 P1-P3 实现
|
||||
|
||||
> docs/team/brief_priv_a1.md | 开工前必读 docs/private_docs_team_context.md(改动清单/红线/纪律是硬约束)。
|
||||
> 权威规格:docs/PRD.md §17(FR-PRIV-001~008)、docs/UI_SPEC.md §9、实施方案(TL 已批准)。
|
||||
|
||||
## 任务
|
||||
|
||||
按三块实现「客户上传资料 → 问答可检索」闭环。全部代码写在服务器仓库 `/home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new`(feature/bioflow-conversation-orchestration 分支)。**不 commit、不部署、不碰清单外文件。**
|
||||
|
||||
### P1 vstore chunk 级索引(最大块)
|
||||
|
||||
1. 新 `vstore/chunks.py`:
|
||||
- 切块参数常量:`CHUNK_TARGET_CHARS=600`、`CHUNK_MIN_CHARS=120`、`CHUNK_MAX_PARAS=8`、`CHUNK_OVERLAP_PARAS=1`、`CHUNK_MAX_PER_DOC=200`、`CHUNK_MIN_SCORE=0.30`、`CHUNK_TOP_K_MAX=20`。
|
||||
- `build_chunks(title, outline, paragraphs, tables) -> list[Chunk]`:段落顺序聚合(≥600 字或满 8 段封块);相邻块重叠 = 前块最后 1 段作下块前缀;表格矩阵化为 `|a|b|` 行式文本段参与;首块前缀 `# {title}`;seq 从 0 起;截断 200 块。Chunk = dataclass(seq, text),chunk_id = `{doc_id}:{seq}`。
|
||||
- `class ChunkIndex`:三文件(`index.json` meta 行 / `index.faiss` faiss 二进制 / `texts.jsonl` 文本);`load()`;`upsert_document()`(替换语义:先移旧行过滤重建 faiss);`remove_document()`;`search(query_vector, top_k, min_score, doc_ids=None, exclude_template=False)` → `{"mode":"vector|empty","items":[{chunk_id,doc_id,seq,snippet,score,doc_name,doc_category,doc_tags,as_template,created_at}]}`(分数低于 min_score 全部丢弃→empty,**无降级档**);`rebuild_all()`;`count()`。单写锁;落盘 tmp + os.replace 原子切换(仿 retrieval.py 纪律)。
|
||||
2. `vstore/embed.py` 新增 `embed_batch_chunked(texts, batch_size=16, workers=4, url=None, model=None)`:Ollama /api/embed 的 **input 数组**批量(与现有 embed_batch 的单条循环区分),ThreadPoolExecutor workers 并发;单批失败重试一次仍失败该批降级零向量。保留 embed_batch 不动。测试注入钩子仿 set_embed_fn 模式。
|
||||
3. `vstore/vault.py`:`__init__` 加载 ChunkIndex(路径来自 settings);`add()` 在 doc 索引成功后追加:build_chunks → embed_batch_chunked → chunks.upsert_document;**chunk 任何失败只告警不阻断**,返回体追加 `chunk_count/chunk_ok/chunk_error`;`delete()` 连删 chunk 行;新增 `rebuild_chunks()`(遍历密文解密 → build_chunks → 批量嵌入 → rebuild_all,返回 {docs, chunks, duration_ms})。
|
||||
4. `vstore/api.py`:`GET /api/vstore/search-chunks?q&top_k&min_score&doc_ids&exclude_template`(top_k clamp 1..20;内部 `asyncio.to_thread` 包同步段;响应 `{ok, mode, query, count, items}`);`POST /api/vstore/rebuild-chunks`;`/health` 加 `chunk_count`。ingest 端点不变(扩展走 vault.add 返回体)。
|
||||
5. `vstore/settings.py`:新增 `VSTORE_CHUNK_PATH` env(默认 `{root}/chunks`)+ get_paths 暴露。
|
||||
6. 新 `vstore/scripts/rebuild_chunks.py`:CLI 重建(cwd=部署根加载 vstore/.env,用 CLI 参数或环境变量取路径),进度打印 + 汇总;供 TL 后台执行。
|
||||
7. 新 `vstore/tests/test_chunks.py` 由 T1 编写——你负责按 T1 用例自测通过。
|
||||
|
||||
### P2 BFF 私有问答端点
|
||||
|
||||
1. `sdk/app/schemas.py`(白名单明文):`PrivateQARequest(question, session_id=None, top_k=8, min_score=0.30)`;`PrivateDocItem(doc_id/name/seq/chunk_id/snippet/score/category/tags/created_at/ref,全默认值 extra="allow")`;`PrivateDocBlock(type: Literal["private_doc"], answer="", items=[])`;`PrivateDocBlock` 追加进 `Block = Union[...]` 末尾。
|
||||
2. `sdk/app/services/docgen/client.py` 新增 `async def search_chunks(query, *, top_k=8, min_score=0.30, timeout=12.0) -> dict`(GET /api/vstore/search-chunks;失败抛 DocgenUnavailable,同文件既有语义)。
|
||||
3. `sdk/app/services/docgen/llm.py`:`complete_text` 增可选 `timeout: float | None = None`(None 走 env 现行为;显式值覆盖),透传 _chat_once;docgen 既有调用零影响。
|
||||
4. 新 `sdk/app/services/privateqa.py`(dataclass/dict,无 pydantic,无 yield):
|
||||
- 常量:`PRIVATE_QA_LLM_TIMEOUT=40.0`、`PRIVATE_QA_MAX_CTX_CHARS=12000`、`PRIVATE_QA_PER_DOC_MAX=3`。
|
||||
- `async def ask_private(question, *, top_k=8, min_score=0.30) -> dict`:search_chunks → 空 `{hit:false, mode:"empty", answer:"", items:[]}` → 同 doc 按 score 序去重(每 doc≤3 块)再取 top_k → 上下文拼 `[资料n]《name》(相关度 x.xx)\nsnippet`(12k 预算截断)→ complete_text(system=「只能依据资料回答,不得编造;每个关键论断标注 [资料n];资料不足则答『资料中未找到相关信息』;300 字内简体中文 markdown」, temperature=0.2, max_tokens=800, timeout=40) → `{hit:true, mode:"vector", answer, items:[...带 ref], elapsed_ms}`。异常抛 DocgenUnavailable/Exception 由路由转信封。
|
||||
5. 新 `sdk/app/routers/private_docs.py`:`POST /api/qa/private`(body=PrivateQARequest);命中 `{ok:true,hit:true,mode,answer,items,elapsed_ms}`;未命中 `{ok:true,hit:false,mode:"empty",answer:"",items:[]}`;vstore 不可达 503 `UPSTREAM_DOWN`;LLM 失败 502 `UPSTREAM_ERROR`(信封复用 `{ok:false,error:{code,message,degraded}}`)。
|
||||
6. `sdk/app/main.py`:+1 行 include_router(放 docgen 之后)。
|
||||
|
||||
### P3 前端接线 + 管理界面
|
||||
|
||||
1. 新 `ui/src/api/private.js`:`askPrivate({question, session_id, top_k=8, min_score=0.30})`(POST /api/qa/private,timeout 60s)。
|
||||
2. `ui/src/stores/chat.js`:`send()` 内、_runStream/_runSearch 分发前插 `this._firePrivate(q, sessionId, aMsg)`(不 await)。三个新方法按已批准设计:`_firePrivate`(fetch→未命中/异常静默 return;命中→本轮上下文校验→流中暂存 `aMsg._privatePending` / 终态直挂+补 persist)、`_appendPrivate`(防重入:已有 private_doc 块只挂一次)、`_flushPrivate`。flush 挂点:_runStream onComplete 整体替换 blocks 之后、_runSearch blocks 赋值之后、两条 error 路径。
|
||||
3. `ui/src/components/chat/AssistantMessage.vue`:新增 `private_doc` 块分支(渲染顺序放 sources 之后):卡体 `private-doc-block`;标题「📚 私有资料参考」(i18n);answer markdown 消毒渲染;items 逐条(编号 `[资料n]`、名称、相关度、片段)。
|
||||
4. 新 `ui/src/i18n/private.js`:标题/相关度/管理界面文案(按 UI_SPEC §9.2 文案清单)。
|
||||
5. 新 `ui/src/components/bench/PrivateLibraryPane.vue`:组件内局部 state(listLibrary({}) 加载/删除后刷新/错误重试);删除 window.confirm → removeLibrary(id) → 刷新。挂 DocPane 空态区顶部(DocPane.vue `v-if="!docgen.activeArtifact"` 块内第一个子元素,其余空态内容不动)。
|
||||
6. `ui/src/api/docgen.js` 新增 `removeLibrary(id)`(DELETE;注意 204 空体——确认 http.js 对 204 的处理,异常时包装返回)。
|
||||
|
||||
## 自测要求(交付门槛)
|
||||
|
||||
- 本地跑通 vstore pytest(T1 用例全绿);python 语法/import 检查全部新文件。
|
||||
- 前端 `npm test` 相关用例全绿(T1 用例);`npm run build` 无错误。
|
||||
- BFF:schemas union 校验(用 TypeAdapter/MessageCreate 构造 private_doc 块通过);新模块无 yield(自查);python 语法检查。
|
||||
- 交付物:代码改动清单 + 自测结果(粘贴测试输出摘要)回报 TL。**不 commit、不部署。**
|
||||
|
||||
## 参考(只读)
|
||||
|
||||
- 已批准实施方案(TL 提供,含全部签名与 JSON 契约)。
|
||||
- 既有纪律与先例:sdk/app/services/sse_relay.py(原子写/帧格式)、vstore/retrieval.py(锁/rebuild 模式)、ui/src/stores/chat.js(sendDocgen 的 meta.library_ids 模式)、AssistantMessage.vue(sources 块分支写法)。
|
||||
@@ -0,0 +1,24 @@
|
||||
# 任务书 · T1(测试 agent)—— 私有资料问答测试用例编制与轮次执行
|
||||
|
||||
> docs/team/brief_priv_t1.md | 开工前必读 docs/private_docs_team_context.md。
|
||||
> 权威规格:docs/PRD.md §17(FR-PRIV-001~008)、docs/UI_SPEC.md §9、docs/PRIVATE_DOCS_TEST_PLAN.md(覆盖判据与轮次纪律)。
|
||||
|
||||
## 阶段 A:测试用例编制(先做,TL 复查达标前不得测试)
|
||||
|
||||
1. 编写 `docs/team/TEST_CASES_PRIVATE.md`:每条含 编号(TC-PRIV-{L层}-{序号})、对应 FR-PRIV 编号、前置条件、步骤、输入、期望输出、判据。
|
||||
2. **100% 覆盖判定(硬门禁)**:
|
||||
- 每个 FR-PRIV-001~008 至少 1 条且双向追溯(附追溯矩阵表);
|
||||
- 覆盖 §1 调整清单的每个文件/端点/函数:chunks 切块参数边界(600 字/8 段/1 段重叠/200 块上限/表格矩阵化/首块标题前缀)、ChunkIndex 增删改查与原子写、embed_batch_chunked(批量数组/并发/单批重试/降级零向量)、vault 钩子(chunk 失败不阻断 doc 级+返回字段)、search-chunks(三态/低分阈值 0.30 两侧/top_k clamp/doc_ids 过滤/exclude_template)、rebuild-chunks/health chunk_count、存量重建 CLI;BFF ask_private(去重每 doc≤3、12k 截断、LLM 超时 40s、异常抛类型)、/api/qa/private 三态信封(命中/未命中/503/502)、schemas union(private_doc 块校验+extra 未知字段)、llm timeout 参数兼容(None 走 env);前端 _firePrivate(命中/未命中/异常静默)、pending/flush 竞态(流未收口不丢块、onComplete 替换后仍出现)、_appendPrivate 防重入、ask/search 两模式与 retry 覆盖、AssistantMessage 块渲染(answer 空态、markdown 消毒)、PrivateLibraryPane(列表/删除/204/错误重试)。
|
||||
- 回归用例:docgen doc 级 /search 响应逐字段、上传/generate/导出;红线 diff 空(QA 8091、modes/labels/bench/api/qa/sse/parser/PipelineCard、retrieval/parsing/backend/crypto、qa.py/sse_relay.py、compile_sdk.sh 白名单)。
|
||||
3. 规模目标 ~60 条(TEST_PLAN §7 预估);完成后交 TL 复查,**不达标不进测试**。
|
||||
|
||||
## 阶段 B:轮次执行(TL 部署后)
|
||||
|
||||
1. 每轮按用例表全量执行(L1 pytest / L2 curl / L3 vitest / L4 浏览器由 TL 配合)。
|
||||
2. 每轮产出 `docs/team/TEST_REPORT_PRIV_R{n}.md`:执行摘要、通过/失败统计、缺陷清单(编号 BUG-PRIV-R{n}-{序号}:复现步骤/预期/实际/对应 TC 号)、阻断项。
|
||||
3. 每轮缺陷统一汇总交 TL → A1 修复+自测 → 下一轮复测。循环至某轮缺陷为 0。
|
||||
4. 轮次报告必须保留过程记录(执行命令、关键输出摘录、统计数字),供 TL 终验引用。
|
||||
|
||||
## 纪律
|
||||
|
||||
测试 agent 不修改任何产品代码(测试文件除外:vstore/tests/test_chunks.py、ui/tests/private_docs/ 由你编写);不 commit 不部署;不自连生产做破坏操作;有歧义先问 TL。
|
||||
Reference in New Issue
Block a user