Files
PlantAI-rag-new/docs/team/brief_dev1_p1.md
jerryandClaude Fable 5 8467dec3a8 fix(bff): 断流崩溃根治——SSE 取消链模块明文化 + 团队文档归档
客户端中途断开流时 Cython 协程 __Pyx_Coroutine_SendEx 断言 abort 整个 BFF。
证据链:3.2.8 崩 db.c / 3.3.0 仍崩(升级无效) / db 明文后迁移 sse_relay.c,
证明取消链上任意 Cython 协程均可触发。最终把 db.py/qa.py/sse_relay.py
加入编译白名单(明文),隔离实例断流探针 10/10 存活,生产同构建实测通过。
代价:3 模块失去编译硬化(无凭据内容),编译模块 30->27。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-03 21:13:56 +08:00

51 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 任务书:开发 agent-1 —— P1 后端服务层(vstore 独立包 + BFF services/docgen)
## 前置必读
1. docs/docgen_team_context.md(服务器环境事实 + 团队纪律,全部遵守)
2. 本任务书 + 模块职责边界
## 职责范围(只改这些文件,不越界)
A. 新增 vstore 独立包(仓库根 /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new/vstore/):
- pyproject.toml(依赖:fastapi/uvicorn/httpx/cryptography/faiss-cpu/numpy/python-docx/pymupdf/PyYAML,版本对齐 venv 已装)
- vstore/settings.py —— VstorePaths dataclass + 限额常量(MAX_ATTACH_COUNT=5、MAX_ATTACH_BYTES=20MB、MAX_ATTACH_CHARS=60000、MAX_SECTIONS=12、MAX_OUTLINE_CHUNKS=3);env 键:VSTORE_KEY(Fernet key,必填)、VSTORE_ROOT、VSTORE_VAULT_PATH、VSTORE_INDEX_PATH(可覆盖:本地路径或 http(s):// URL)、VSTORE_EMBED_URL(默认 http://127.0.0.1:11434)、VSTORE_EMBED_MODEL(默认 bge-m3:567m)
- vstore/crypto.py —— Fernet 封装 encrypt_bytes/decrypt_bytes;.enc 落盘;secure_delete
- vstore/parsing.py —— extract_docx->{outline, paragraphs, tables, style_hints}、extract_pdf(pymupdf ≤300页)、extract_text_file(utf-8→gb18030)、outline_to_markdown、outline_to_embedding_chunks(>7500字符按节切块≤3)
- vstore/embed.py —— embed_batch(texts):httpx 并发≤8 调 ollama /api/embed(url/model 由 settings)
- vstore/backend.py —— parse_backend(spec)->LocalBackend|RemoteBackend:含 :// 且 scheme http/https → RemoteBackend(vault/index 操作转 HTTP 指向远程根,接口语义与本地一致);其余(含 file://)→ LocalBackend(本机磁盘);启动握手校验(/health + 空检索),失败日志告警并拒绝(抛异常阻止启动)
- vstore/vault.py —— 单一主库:add(file_bytes, filename, meta, as_template)->id(解析→提取→嵌入→加密落盘→索引;原文不出函数,末尾丢弃);get_decrypted(id);delete(id);list/search(meta)
- vstore/retrieval.py —— faiss IndexFlatIP + index.json 单一事实源(行号==json 下标);search(q, top_k, category, as_template) 三档降级(向量→meta 关键词→最新8条);增量写锁 + rebuild 临时索引 os.replace 原子切换
- vstore/api.py —— FastAPI app:POST /api/vstore/ingest(multipart: file+name/category/description/tags/as_template)→{ok,item:{id,name,as_template,embed_chunks}};GET /api/vstore/search?q&top_k&category&as_template→{ok,mode,items[]};GET /api/vstore/documents/{id}(明文全文+outline+meta,仅生成时取);GET /api/vstore/documents/{id}/style(docx 样式提取);DELETE /api/vstore/documents/{id};POST /api/vstore/rebuild-index;GET /api/vstore/health
- vstore/tests/ —— 单元测试:crypto 加解密、vault 加密落盘无明文断言(tmpdir + 假 embed,不碰真 ollama)、retrieval 假 embed、backend 路径解析三形态(裸路径/file:///http(s)://)+ 远程握手失败拒绝、api 端点(FastAPI TestClient)
B. 新增 sdk/app/services/docgen/(BFF 侧纯生成/导出,不含存储检索):
- settings.py —— DocgenPaths + 限额常量(与 vstore 对齐)
- client.py —— vstore HTTP 客户端(httpx.AsyncClient,超时/重试;方法 ingest/search/get_document/get_style/delete/rebuild/health;所有失败路径不抛未捕获异常,返回错误结构供上层兜底)
- parsing.py —— BFF 侧样式提取 extract_docx_style(bytes)->style_hints(python-docx,供导出对齐)
- llm.py —— complete_text(system,user,*,temperature=0.3,max_tokens=8000)->str;complete_json(...)(response_format json_object + 一次 JSON 修复重试);3 次指数退避 1.5s/3s/6s(429/5xx/超时);httpx 裸调(不用 openai SDK——阻塞事件循环);env 键 DOCGEN_LLM_BASE_URL/DOCGEN_LLM_API_KEY/DOCGEN_LLM_MODEL/DOCGEN_LLM_TIMEOUT=300
- intent.py —— 服务端意图路由 route(text, has_attachments, has_active_artifact)->qa|docgen|edit|export。规则词典法:漏判安全(不命中一律 qa)。优先级:导出词(导出/转成/下载+格式词 pdf/docx/word)→ 编辑词(改/加/删/润色+当前有活动文档)→ 写文档意图(写类动词:写/拟/起草/生成/撰写/帮我写/给我写 + 文档类型词词典 + 量词 一篇/一份/一个/一则 等)→ 附件信号(has_attachments + 写类动词)→ qa。文档类型词:论文/报告/通知/通告/公告/请示/批复/函/申请书/申报书/标书/合同/协议/方案/计划/总结/汇报/讲话稿/致辞/证明/纪要/简报/材料/说明书/指南/申请书等。**词典与判定规则要和前端一致(同一条用例表两边测)**
- md2docx.py —— 行级状态机→Word 内建样式(Normal/Heading 1-3/List Bullet/List Number/Table Grid/Quote);中文:正文宋体/标题黑体,font.name 与 w:eastAsia 同时设置;表格表头加粗灰底
- md2pdf.py —— markdown-it-py 出 HTML → PyMuPDF Story→PDF;字体用 /usr/share/fonts 真实文件(NotoSansCJK/NotoSerifCJK/wps-office),禁用内置 CJK;若 Story 路线中文异常,降级自写排版器(标题/段落/表格画线)
- pipeline.py —— run_generate(db, description, library_ids, template_id)->dict:经 client 取明文(vstore 解密)→ 选模版(指定>检索 as_template=true>跳过)→ 大纲(模版 outline 裁剪≤12 节;无模版 complete_json 出 {title,sections[]},失败重试1次再失败六段式默认)→ 逐节生成合并(单节失败重试2次仍失败占位)→ humanize 按行保护(标题/表格/列表行原样,只 humanize 正文段;humanize 现成函数见 sdk/app/services/,只调用不修改)→ md+docx 落盘 → 写 doc_artifacts 表(表结构由 dev2 定,用 CREATE IF NOT EXISTS + 宽松字段,dev1 用 dict 方式按约定字段读写,先跟 dev2 对齐字段名,见下方【跨模块契约】)
- editor.py —— apply_edit(md, instruction)->str(当前文档全文 + 只输出完整新 md;长文档分段改);smart_export(md, format, template_style)->Path
- 单元测试 sdk/app/services/test_docgen_*.py —— intent 路由 20-30 用例(与前端同用例表)、client 假 vstore(httpx MockTransport 或 monkeypatch)、md2docx(打开验证段落/样式/中文字体)、md2pdf 冒烟(tmpdir)、pipeline mock LLM 全流程(monkeypatch llm + client)、editor(mock LLM)
## 【跨模块契约】(与 dev2 对齐,dev2 会在 sdk/app/db.py 建表)
- doc_library 表字段:id TEXT PK、name、category、tags、description、as_template INTEGER、enc_path、embed_sha、active、created_at
- doc_artifacts 表字段:id TEXT PK、session_id、status、title、template_name、md_path、docx_path、pdf_path、error、created_at
- BFF->vstore 全部经 client.py;router 层(dev2)只 import client.py 与 pipeline/editor
- 错误信封沿用现有格式(见 sdk/app/routers/ 现有代码,dev2 负责)
## 【纪律再强调】
- 不碰生产运行中的服务(8090/8091 等);不自行部署;单元测试只用 tmpdir/mock/fixture,不依赖 ollama/LLM 真调用
- 只动本任务书列出的文件;发现需要改其他文件 → 记入报告交 TL 裁决
- 不用 pydantic 模型(服务层只用 dataclass/dict)——Cython 编译纪律
- 不 commit、不 push、不 touch 部署树
## 【自测要求】
- 每个模块写完即写对应单元测试并跑通:cd /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new && /home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python -m pytest vstore/tests/ sdk/app/services/test_docgen_*.py -q(排除依赖 ollama/LLM 的用例,用 mock)
- 自测结果写入 docs/team/report_dev1.md(列出:完成模块清单、每个测试文件与用例数、通过数、已知限制)
## 【完成标准】
报告写入 docs/team/report_dev1.md 后,通过 /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new/docs/team/report_dev1.md 的方式让 TL 知道(在你的最终回复中明确写「DEV1 P1 完成」+ 报告路径 + 自测通过数)
【重要补充】意图路由的规范词典与 30 条用例表已冻结于 docs/team/cases_intent.md(唯一事实源)——intent 实现与测试一律以它为准,不得自造词典/自造用例。