feat(inference): chat_structured 接入 jsonschema 真校验(T1 架构审查整改)

- pyproject.toml 新增 jsonschema>=4.23 依赖
- engine.py: json.loads 后 jsonschema.validate,校验失败按解析失败重试(带错误信息)
- 新增 3 用例:违规重试成功/耗尽 parse_error 含详情/合法一次通过
- 全量 163 passed / 100.00% 覆盖(936 stmts/238 br),fail_under=99 达标
This commit is contained in:
lhl
2026-08-12 09:32:02 +08:00
parent 0a79b07356
commit 25fc472d9b
5 changed files with 241 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
# 整体架构工程审查报告(plan-eng-review
> 版本: v1.0 | 日期: 2026-08-11 | 状态: 已裁定
>
> 审查技能: gstack `plan-eng-review`version 1.0.0| 审查对象: 整体架构全景(docs/design.md + agent-runtime-design.md + rag-layer-design.md + api-design.md + implementation-plan.md| 当前进度: Phase3 Word 解析收尾(160 tests / 100%
---
## 1. 审查范围与裁定摘要
本次审查锁定**整体架构全景**,目标为后续 Phase4-6RAG / Impact / Writer / Web UI)实施提供架构定论。
| 审查阶段 | 结果 |
|---------|------|
| Step 0 Scope Challenge | **范围缩减**:移除 Qdrant 切换抽象 + Redis/Valkey 双实现(单一 Chroma + InMemoryQueue|
| Section 1 Architecture | 7 个 issue,全部裁定 |
| Section 2 Code Quality | 3 个 issue,全部裁定 |
| Section 3 Test Review | 覆盖图完成,无独立缺口(随架构裁定覆盖)|
| Section 4 Performance | 2 个 issue,全部裁定 |
| Outside Voice | 独立挑战完成,8 项全部接受 |
---
## 2. Step 0: Scope Challenge 裁定
**复杂度检查触发**(全架构远超 8 文件/2 服务阈值),发现 2 处过度设计:
| # | 过度设计点 | 裁定 |
|---|-----------|------|
| S1 | Qdrant 可切换抽象(rag-layer §9 StorageAdapter| **移除** — v1 单机竞赛场景 Chroma 嵌入式足够(搜索验证:<10 万向量 Chroma 正确默认)|
| S2 | Redis/Valkey TaskQueue 双实现(api-design §5| **移除** — v1 InMemoryQueue 满足演示需求,抽象接口保留但双实现不建 |
> Search Check 结论:手写 RAGchromadb+rank_bm25+RRF)与 2026 主流实践一致;Chroma 嵌入式对小规模规则库正确。
---
## 3. Section 1: Architecture Review7 issue 全裁定)
| # | 严重度 | 置信度 | 发现 | 裁定 |
|---|--------|--------|------|------|
| I1 | P1 | 9/10 | `chat_structured` 无真正 schema 校验(engine.py:160 直接 json.loads 返回)| **加 jsonschema 真校验**(失败→带错误重试→parse_error+校验详情)|
| I2 | P2 | 8/10 | 解析重试路径硬编码首选模型,从不降级(engine.py:155| **解析重试也走降级链**primary→fallback|
| I3 | P1 | 7/10 | 状态机 8 状态无 cancelled/aborted 定义,但 api 有 cancel 端点 | **加 cancelled+resume 状态**cancelled 终态 + resume 回到中断前)|
| I4 | P2 | 7/10 | design §8.1 宣称「引擎统一注入防护」但 engine.py 无实现 | **引擎层统一防护**(边界包裹+系统指令恒定性,全 Agent 生效)|
| I5 | P2 | 8/10 | config.py 残留 QdrantStoreConfigL95-103/ redis_urlL38-41)死配置 | **删死配置+同步文档** |
| I6 | P2 | 7/10 | RAG 设计缺 rerank 精排(2026 主流实践为 向量→rerank→精排)| **v1 加 rerank**bge-reranker-v2-m3|
| I7 | P3 | 5/10 | 三层记忆 + DataGate + AgentState 对单进程场景可能过度 | **完整实现**(用户认为记忆系统是核心价值)|
## 4. Section 2: Code Quality Review3 issue 全裁定)
| # | 严重度 | 置信度 | 发现 | 裁定 |
|---|--------|--------|------|------|
| I8 | P2 | 9/10 | SourceParser 三重复制校验(source_aggregator.py:39-66 DRY 违规)| **提取 _validate_path helper** |
| I9 | P2 | 8/10 | client.py:82 time.sleep 阻塞 asyncio 任务池 + client 生命周期未闭环 | **全异步化**AsyncClient + asyncio.sleep + async 上下文)|
| I10 | P3 | 6/10 | chat_structured 重复调用 _model_names(None)[0]4 处)| **随 I2 一并修** |
## 5. Section 3: Test Review
已实现部分 **160 tests / 100% 覆盖**fail_under=99 门禁生效),FakeLLMClient 注入模式成熟。覆盖图确认关键测试缺口集中在**已裁定架构变更**(jsonschema/降级链/注入防护/异步化需测试先行)与后续阶段(RAG chunker/检索 eval、状态机、渲染链路 E2E)。
## 6. Section 4: Performance Review2 issue 全裁定)
| # | 严重度 | 置信度 | 发现 | 裁定 |
|---|--------|--------|------|------|
| I11 | P2 | 7/10 | token.py:18 cl100k_base 对 CJK 严重低估 token 数 → 裁剪策略失效 | **CJK 保守估算**(模型 tokenizer 优先,退化 CJK 字符×1.5|
| I14 | P2 | 7/10 | Writer 逐章串行生成 3-5 分钟 | **保持串行+文档约束**(章间引用需前章摘要,并行复杂;UI 预估时长提示)|
## 7. Outside Voice(独立挑战,8 项全接受)
| # | 发现 | 裁定 |
|---|------|------|
| OV1 | 审查决策未写回执行文档(rag-layer/api-design/runtime/plan 仍含双实现描述,Phase4 会重建放弃的抽象)| 接受:T5 同步修订四处文档 |
| OV2 | bge-small-zh-v1.5 面向中文,实际语料为日文 | 接受:T11 切换 bge-m3+日文样本验证 |
| OV3 | 可追溯性标准未操作性定义(URI 格式不一致、无 resolver、QA#8 可作弊)| 接受:T12 统一 URI+resolver+强验证 |
| OV4 | 成功标准无量度(无黄金集/评分器)| 接受:T13 建立黄金集+评分器 |
| OV5 | DataGate 是原则非机制,1000 行 Excel 上下文爆炸 | 接受:T14 机制化+规模测试前置 |
| OV6 | QA 循环无边界 + 自校验盲区(DeepSeek 检查 DeepSeek| 接受:T15 护栏+QA 走 fallback_model |
| OV7 | 崩溃恢复只到会话级,任务层丢数据 | 接受:T16 任务级持久化 |
| OV8 | 最难成功标准(格式精度)排关键路径末尾 | 接受:T17 docx 注入原型提前 |
---
## 8. Required Outputs
### 8.1 NOT in scope(本次审查明确延后)
| 项 | 延后理由 |
|----|---------|
| Qdrant/QdrantAdapter | 与 S1 裁定一致,移除(v2 触发项)|
| Redis/Valkey Queue 实现 | 与 S2 裁定一致,接口保留(v2 触发项)|
| LLM 调用缓存 | design §9.2 已列 v2,识别为有意延期 |
| 成本/限流监控 | design §9.1 v2 预留 |
| Type C 参考设计文档 RAG | rag-layer §1.1 已声明可选增强,初期聚焦 Type A+B |
| 多用户并发隔离 | v1 单用户演示,多用户隔离基线保留(§8.2)|
### 8.2 What already exists(设计复用核查)
| 已实现 | 复用情况 |
|--------|---------|
| InferenceEngineM3.1| ✅ 设计直接复用;需按 I1/I2/I4/I9 加固 |
| Excel/Word/混合 ParserPhase2/2.5/3| ✅ 设计直接复用;I8 微重构 |
| PromptRegistry / token 估算 | ✅ 复用;I11 修正估算 |
| 7 个脱敏真实样本(samples/| ✅ T13 黄金集基础 |
| config 三 yaml + env 覆盖 | ✅ 复用;I5 清理死配置 |
### 8.3 失败模式(关键路径)
| 路径 | 失败场景 | 测试覆盖 | 错误处理 | 用户可见性 |
|------|---------|---------|----------|-----------|
| chat_structured 输出不合 schema | LLM 返回缺字段 JSON → 消费方 KeyError | I1 修复后新增 | I1 修复后 parse_error | ✅ 重试后显示失败 |
| 解析重试主模型弱 | 重试 2 次全败 → 无降级 | I2 修复后新增 | I2 修复后 fallback | ✅ 降级事件可见 |
| 用户取消生成 | 状态悬置无定义 | I3 修复后新增 | I3 修复后 cancelled | ✅ cancel 端点语义明确 |
| 恶意规则文档注入 | 规则含「忽略以上指令」→ 污染输出 | I4 修复后新增 | I4 修复后引擎级阻断 | ⚠️ 需测试验证 |
| 日文长文本超上下文 | 裁剪低估 → API 超限拒绝 → 重试循环 | I11 修复后新增 | I11 修复后裁剪准确 | ✅ 重试机制 |
| 服务重启丢进行中任务 | 中断后重复章节或卡死 | OV7(T16) 后新增 | 需任务落盘 | ⚠️ 当前**静默失败** |
### 8.4 Worktree 并行化策略
```
Lane A(前端+编排):T3 状态机 → T14 DataGate → T16 任务持久化(共享 orchestrator/
Lane BRAG 独立) T6 rerank → T11 bge-m3(共享 rag/,不与 A 冲突)
Lane C(推理加固) T1 jsonschema → T2 降级链 → T4 注入防护 → T8 异步 → T9 token(共享 inference/,串行)
Lane D(基础设施) T7 helper / T5 死配置 / T10 文档 / T12 resolver / T13 黄金集 / T15 QA / T17 原型
```
执行序:**C(加固核心)先于一切** → A + B 并行 → D 穿插。Lane C 与 A 共享引擎层,建议 C 完成后 A 再启动。
---
## 9. Implementation Tasks17 项)
全部任务已输出至 `~/.gstack/projects/unknown/tasks-eng-review-20260811-160000.jsonl`/autoplan 可聚合)。
- [ ] **T1 (P1, human: ~2h / CC: ~20min)** — inference — chat_structured 接入 jsonschema 真校验
- [ ] **T2 (P1, human: ~1.5h / CC: ~15min)** — inference — 解析重试降级链 + 模型名局部变量
- [ ] **T3 (P1, human: ~3h / CC: ~40min)** — orchestrator — 状态机 cancelled+resume
- [ ] **T4 (P1, human: ~3h / CC: ~30min)** — inference — 引擎层统一注入防护
- [ ] **T5 (P2, human: ~1h / CC: ~10min)** — config — 删死配置+同步文档(含 OV1)
- [ ] **T6 (P2, human: ~4h / CC: ~45min)** — rag — v1 rerank 精排
- [ ] **T7 (P2, human: ~30min / CC: ~5min)** — parsers — 提取 _validate_path helper
- [ ] **T8 (P1, human: ~5h / CC: ~1h)** — inference — LLM 客户端全异步化
- [ ] **T9 (P2, human: ~1h / CC: ~15min)** — inference — CJK 保守 token 估算
- [ ] **T10 (P3, human: ~1h / CC: ~10min)** — documentation — Writer 串行约束写回
- [ ] **T11 (P2, human: ~3h / CC: ~30min)** — rag — bge-m3 + 日文样本验证(OV2
- [ ] **T12 (P1, human: ~6h / CC: ~1.5h)** — provenance — URI 统一+resolverOV3
- [ ] **T13 (P1, human: ~8h / CC: ~2h)** — eval — 黄金集+评分器(OV4)
- [ ] **T14 (P2, human: ~5h / CC: ~1h)** — orchestrator — DataGate 机制化(OV5
- [ ] **T15 (P2, human: ~3h / CC: ~40min)** — qa — QA 护栏+fallback 路由(OV6
- [ ] **T16 (P2, human: ~6h / CC: ~1.5h)** — orchestrator — 任务级持久化(OV7
- [ ] **T17 (P1, human: ~6h / CC: ~1.5h)** — writer — docx 注入原型提前(OV8
---
## 10. 完成摘要(Completion Summary
- Step 0 Scope Challenge: **范围缩减**(移除 2 处双实现抽象)
- Architecture Review: 7 issues found(全部裁定)
- Code Quality Review: 3 issues found(全部裁定)
- Test Review: 覆盖图已产出,0 独立缺口(随架构裁定覆盖)
- Performance Review: 2 issues found(全部裁定)
- NOT in scope: 已写入(§8.1
- What already exists: 已写入(§8.2
- TODOS.md: N/A(项目无此文件;17 项任务已入 JSONL)
- Failure modes: 6 条关键路径记录,1 处**临界缺口**(重启丢任务静默失败 → T16 修复)
- Outside voice: 已运行(Claude 子代理),8 项全部接受
- Parallelization: 4 lanesC→(A+B) 并行,D 穿插
- Lake Score: 17/17 推荐选择完整方案
---
## GSTACK REVIEW REPORT
| Review | Trigger | Why | Runs | Status | Findings |
|--------|---------|-----|------|--------|----------|
| CEO Review | `/plan-ceo-review` | Scope & strategy | 0 | — | — |
| Codex Review | `/codex review` | Independent 2nd opinion | 0 | — | — |
| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 1 | ISSUES_OPEN | 11 issues + 8 outside voice |
| Design Review | `/plan-design-review` | UI/UX gaps | 0 | — | — |
| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | — | — |
- **CROSS-MODEL:** Outside voiceClaude 子代理)与主审查交叉验证——OV1 为已裁定项的执行监督,OV2/3/4/5/6/7/8 为互补新发现,无实质分歧。
- **VERDICT:** ENG REVIEW 完成(11 issues + 8 findings 全部裁定,待实施后复核)。**eng review not yet CLEAR — 需任务实施后重跑确认。**
**UNRESOLVED DECISIONS:**
- 无(全部 19 项裁定完成)