Skip to content

Commit 919b544

Browse files
committed
docs(ai): AI 精修非功能扩展设计——任务中心化+协议v2+评测框架 (P0契约实证)
1 parent 6b8dd72 commit 919b544

1 file changed

Lines changed: 212 additions & 0 deletions

File tree

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# 头脑风暴记录:AI 精修非功能扩展 + 全链路问题修复(v0.8.0 补强)
2+
3+
## 基本信息
4+
5+
| 字段 | 内容 |
6+
|------|------|
7+
| 主题 | AI 精修「能用、用得好、用得顺」——全链路问题检测 + 非功能扩展设计(任务中心化 + 协议 v2 + 评测框架) |
8+
| 日期 | 2026-08-21 |
9+
| 参与者 | 用户 + AI 代理(对话式多轮) |
10+
| 目标 | 产出 AI 精修补强设计:P0/P1 问题修复全量纳入 + 非功能扩展(任务中心/并发重试/成本控制/质量评测/可观测性)按里程碑分层交付 |
11+
| 关联 | [v0.8.0 规划](../versions/v0.8.0.md) · [v0.8 AI 精修头脑风暴归档(2026-08-19)](../2026-08-19/brainstorming-v0.8-ai-note-refine.md) · REQ-141/142/143/144/145/147 · ADR-010(AI 为增强层·本地兜底铁律) |
12+
13+
---
14+
15+
## 1. 问题定义
16+
17+
### 核心问题
18+
v0.8.0 的 AI 精修/知识补充代码建设完成,但**真机不可用**:AI 调用有记录(SiliconFlow 侧产生费用)而返回结果未被实际使用(前端永久"排队中");此外存在丢图、成本失真、零审计、配额失控、切片结构错乱等 P1 问题,非功能扩展(任务可恢复性/并发/评测)为零。
19+
20+
### 检测方法
21+
- 全链路代码审查:前端(AiRefineCard/EnrichPanel/AiServicePanel/NotePreviewView/types.ts)→ 命令层(commands_ai_refine/commands_ai_enrich/commands_ai_settings)→ 任务状态机(ai_task)→ 云端适配器(ai_client/ai_note_refine/ai_note_enrich)→ 协议校验(ai_refine_protocol/ai_enrich_protocol)→ 落库(ai_refine_apply/versioned_save/db_ai_usage)
22+
- 契约实证:临时单测实测 serde 序列化输出(已还原)
23+
- 文档对照:v0.8.0 规划验收项逐条核对
24+
25+
### 关键现状(检测结论)
26+
- **P0 契约断裂(已实证)**:`AiTaskState` 带 `#[serde(rename_all = "camelCase")]`,枚举变体名被小写化(`"succeeded"`/`{"running":..}`/`{"failed":..}`/`"pending"`);前端按 PascalCase 比较(`st === "Succeeded"`、`"Running" in st`、`"Failed" in st`)→ **全部失配**。任务后台真实执行成功(有调用记录、产生费用),前端永不进成功分支 → 永久"排队中" → 结果永不取回/展示/采纳。30s 卡住检测同样失效(`st !== "Pending"` 恒 true)。
27+
- **P0 附:失败原因契约错位**:`AiTaskFailure` camelCase 输出 `{"insufficientBalance":..}`/`{"invalidResponse":..}`,前端期待 `"balance"`/`"invalid"` → 引导文案错位。
28+
- **P1 丢图**:规则草稿含 `- ![画面 N](session-images/...)` 配图行,精修协议仅 5 种文本块、无 image 类型 → 精修版配图全丢。
29+
- **P1 成本失真**:估算只按输入字符;**无模型→单价映射**,切付费模型后确认弹窗仍显示 ¥0 → 实际扣费无感知。
30+
- **P1 零审计**:精修/补充调用不上 `ai_audit_list`(仅余额/测试连接/复核有记录)→ REQ-140 轨迹可见化缺失。
31+
- **P1 配额失控**:精修/补充不消费 DailyQuota;「记住此选择」后完全跳过确认 → 无限烧钱;无任务去重,双击/重进可重复扣费。
32+
- **P1 切片上下文丢失**:多片独立请求,每片输出完整章节结构,合并仅 `\n\n` 拼接 → 章节标题重复、结构错乱。
33+
- **P1 一片失败=全任务失败**:REQ-145「部分失败可单独重试」未实现。
34+
- **P1 任务结果内存态**:任务注册表在 AppState 内存,重启即失。
35+
- **已做对**:授权红线(enabled+authorized 双 gate)、DPAPI 密钥、余额查询+低余额提醒、schema 强校验、降级本地规则版保留、版本链+回滚+成本落库、事件+轮询双通道、闭包 ref 修复、trim_tasks 容量守卫。
36+
37+
### 约束条件
38+
- 本地优先 + AI 为增强层;数据不出本机;AI 调用须用户授权且默认关闭(AGENTS.md 铁律)
39+
- Windows 桌面(Tauri 2 + Rust + React);单文件 ≤300 行;Rust 侧有 1271 测试基线
40+
- 范围纪律:不铺开新 AI 能力(问答/VLM/闪卡仍排除),聚焦精修/补充一条线做深
41+
- 网络环境:本机 TLS 拦截,新增 crate 依赖受限(DPAPI 先例)
42+
43+
### 成功标准
44+
1. 真机精修全流程走通:预估→确认→任务→diff→采纳落库,无"排队中"卡死
45+
2. 精修版不丢配图;成本显示真实(模型单价映射);精修/补充调用上审计
46+
3. 任务结果重启可恢复;完成通知可见;长笔记并发提速;单片失败可重跑
47+
4. 协议 v2 向后兼容;结构回归评测全绿;现有 1271 测试不劣化
48+
49+
---
50+
51+
## 2. 发散阶段(用户裁决的扩展方向)
52+
53+
| # | 方向 | 内容 | 裁决 |
54+
|---|------|------|------|
55+
| 1 | 修复优先 | P0 契约断裂 + P1 全量修复(丢图/成本/审计/配额/去重/切片上下文) | ✅ 全量纳入 |
56+
| 2 | 任务中心与可恢复性 | 任务记录持久化(SQLite)+ 结果重启恢复 + 完成通知 | ✅ 全量纳入 |
57+
| 3 | 并发与重试 | 切片并发 2-3 + 单片重试 + 任务去重 | ✅ 全量纳入 |
58+
| 4 | 成本控制完整化 | 模型→单价映射表 + 余额预校验硬拦截 | ✅ 硬拦截 + 单价映射 |
59+
| 5 | 质量评测基准 | golden 结构回归评测(内置小样本集,不联网) | ✅ 结构回归(模型对比/人工评分不做) |
60+
| 6 | 可观测性 | 精修/补充上审计 + 用量概览(任务表聚合) | ✅ 全量纳入 |
61+
| 7 | 全局任务面板 | 前端历史任务列表/查看结果/重跑 | ✅ 纳入 |
62+
| 8 | 架构取向 | 方案 C:任务中心化 + 协议 v2 + 评测框架全量重构 | ✅ 用户裁决 C |
63+
64+
### 灵感触发(市场对照)
65+
- 通义听悟/Otter 系:异步任务 + 完成通知是标配 → 本次 B3 完成通知落地
66+
- NotebookLM citation:AI 输出可溯源是信任核心 → 本次 image 块溯源 + 片间上下文防结构漂移
67+
- llm-ux-patterns:token-cost transparency + quota fallback → 本次单价映射 + 硬拦截 + 配额接入
68+
69+
---
70+
71+
## 3. 收敛阶段(设计定稿)
72+
73+
### 总体架构:任务中心化(方案 C)
74+
75+
**核心洞察**:P0/P1 多数问题(契约断裂、零审计、无去重、结果易失、无重试)同根——任务注册表是无持久化的内存 HashMap。以「持久化任务中心」为支点,修复项与扩展项统一承接,一次架构动作解决全部问题。
76+
77+
### 3.1 修复层(F0 + F1)
78+
79+
**A1 契约断裂修复(P0,ai_task.rs)**
80+
- `AiTaskState`:去掉 `rename_all = "camelCase"` → 变体名恢复 PascalCase(Pending/Running/Succeeded/Failed),字段保持 snake_case(finished_slices/total_slices)→ 与前端 types.ts 逐字匹配
81+
- `AiTaskFailure`:保持 camelCase,显式 rename 两个变体:`InsufficientBalance → "balance"`、`InvalidResponse → "invalid"` → 与前端四类出口对齐
82+
- **不动** `AiTaskHandle`(taskId camelCase 契约 2026-08-21 已修正确,勿改)
83+
- **新增契约快照单测**:断言 serde 序列化输出等于前端期望 JSON 字面量(本次事故教训,防再断裂)
84+
85+
**A2 丢图修复(双层)**
86+
- 协议 v2 增加 image 块(见 3.3 C2)
87+
- 降级路径:本地合并——精修落库时把规则版 `- ![画面 N](...)` 配图行按章节锚点合并回精修版(协议未返回 image 块时启用,零模型成本)
88+
89+
**A3 成本失真修复(ai_cost.rs)**
90+
- 新增模型→单价映射表(内置:免费档 ¥0、DeepSeek-V3/Qwen3-235B 实测价格;设置页可编辑;env 覆盖保留)
91+
- 预估 = 输入token×单价 + 输出token×单价(输出按输入比例系数粗估)
92+
- 确认弹窗/成本落库统一用映射表单价 → 消灭「切付费模型仍显示 ¥0」
93+
94+
**A4 审计补齐(commands_ai_refine / commands_ai_enrich)**
95+
- 任务完成/失败时 push_audit(op 类型 + task_id + 结果 + 成本)→ 本地审计列表可见精修/补充调用轨迹
96+
97+
**A5 配额接入 + 任务去重**
98+
- 精修/补充任务启动时消费 DailyQuota(按片计,耗尽 → 明确拦截引导)
99+
- 同 session/note 存在进行中任务时拒绝重复启动(防双击/重进重复扣费)
100+
101+
### 3.2 任务中心(F2)
102+
103+
**B1 SQLite 任务表(新表 ai_tasks,迁移)**
104+
- 字段:task_id, op_type(refine|enrich), ref_id(session/note), state, result_json, cost_yuan, elapsed_ms, model, error, created_at, finished_at
105+
- 状态流转与内存注册表同步写(锁内 read-modify-write;写库失败不阻断 AI 调用——内存注册表继续 + 明确日志,见 H2)
106+
107+
**B2 结果恢复**
108+
- 应用启动时从 ai_tasks 恢复未采纳的成功结果 → 前端任务面板可见历史结果,重启不丢
109+
- 保留策略:每类型保留最近 50 条,超限清理旧终态任务(防表膨胀)
110+
111+
**B3 全局任务面板 + 完成通知**
112+
- 前端新增「AI 任务」视图(设置页 Tab 或独立面板):历史任务列表(时间/类型/状态/成本/模型)、查看结果(diff 预览复用)、重跑入口
113+
- 完成通知:ai:task-update 事件全局监听 + 顶栏角标/提示(跨卡片生效,REQ-145「完成通知」真正落地)
114+
115+
**B4 并发与单片重试**
116+
- 切片并发 2-3(配额计数并发安全改造——v0.8.0 开放问题「切片并发 vs 每日配额」一并解决)
117+
- 单片失败自动重试 1 次(幂等片)→ 仍失败则保留已成功片 + 标记部分成功(partial_failed:x/y 片成功,可重跑失败片;REQ-145 兑现)
118+
119+
### 3.3 协议 v2(F3)
120+
121+
**C1 版本化与向后兼容**
122+
- 响应增加 schema_version: u32(缺省=1,v2 显式=2)
123+
- 反序列化宽容:v1 响应(无 version 字段)仍按 v1 解析 → 旧任务结果/缓存不崩
124+
125+
**C2 image 块类型**
126+
- AiRefineBlockType 增加 Image:content 为本地配图引用(session-images/{sid}/{rel} 相对路径)
127+
- 提示词 v2(note_refine.json)输出约束增加 image 块说明:配图行必须原样保留为 image 块,不得改写路径
128+
- 校验:content 非空、路径须匹配 session-images/ 前缀(防注入)、每节 image 块数 ≤ 5
129+
- to_markdown 渲染为 `- ![画面 N](session-images/...)` 原行 → diff 预览/落库保留配图
130+
131+
**C3 片间上下文字段**
132+
- AiRefineRequest 增加:slice_index, slice_total, prev_summary(前片结尾 200 字摘要), next_summary
133+
- 提示词约束:本片只整理 content 对应内容,沿用 chapters 全局章节,禁止发明新章节标题
134+
- 合并逻辑升级为「按全局章节归并」(同标题节合并块,不重复输出标题)
135+
136+
### 3.4 成本拦截完整化(F3)
137+
138+
**D1 启动前硬拦截**
139+
- 流程:预估(映射表单价)→ 查余额 → 余额 < 预估×安全系数1.2 → 拒绝启动 + 三出口引导(充值/切免费档模型/放弃)
140+
- 前端确认弹窗同步显示「余额不足将无法启动」提示
141+
142+
**D2 单价映射表**
143+
- 内置表:免费档 ¥0、DeepSeek-V3-0324/Qwen3-235B-A22B 实测价(未知模型回退 ¥0 + 警告「该模型单价未登记,费用可能不准确」)
144+
- 设置页「AI 服务」可编辑单价表(存 ai_settings.json);env SILICONFLOW_PRICE_PER_1M_TOKENS 仍可整体覆盖(开发路径)
145+
146+
### 3.5 评测框架(F3)
147+
148+
**E1 内置样本集(src-tauri/fixtures/refine_golden/)**
149+
- 3-5 个典型样本:网课讲义式(含术语/章节)、实操步骤式、口播摘要式、含表格+公式+配图场景(覆盖 image 块回归)
150+
- 每样本 = 输入(切片 markdown + profile + glossary + chapters)+ 期望断言(章节集合、配图保留、块类型合法、schema_version=2)
151+
152+
**E2 回归测试(refine_golden_tests.rs)**
153+
- 走 mock 适配器全链路(不联网):mock v2 响应 → 协议校验 → to_markdown → 断言结构不漂移
154+
- 提示词 golden 冒烟:固定样本断言输出结构(防提示词改动破坏契约)
155+
156+
### 3.6 可观测性(F3)
157+
158+
**G1** 任务表即用量数据源:聚合 SQL(按日/按类型:次数/费用/耗时/模型)→ 设置页「用量概览」小卡(不建完整报表页,YAGNI)
159+
**G2** 审计补齐后 ai_audit_list 统一展示全部 AI 调用轨迹
160+
161+
### 3.7 错误处理与测试总纲
162+
163+
**H1** 每层错误归一 AiTaskFailure(四类 + server/invalid),任务表记录 error 原文
164+
**H2** 新边界:任务表写入失败 → 内存注册表继续(不阻断 AI 调用)+ 明确日志;恢复时以任务表为准
165+
**H3** 单片重试仍失败 → partial_failed(保留已成功片,前端显示「部分成功:x/y 片,可重跑失败片」)
166+
167+
**I1** 契约快照测试(A1,本次事故教训):serde 输出 = 前端期望 JSON 字面量
168+
**I2** 协议 v2:image 块校验/片间字段/版本兼容单测
169+
**I3** 任务中心:CRUD/恢复/保留策略/并发计数单测(内存库)
170+
**I4** 评测回归(E2):mock 全链路 golden
171+
**I5** 前端:无 Vitest 基建维持真机手动清单(契约测试已在 Rust 侧兜底)
172+
**I6** 回归:cargo test + cargo clippy 全绿;现有 1271 测试不劣化
173+
174+
---
175+
176+
## 4. 里程碑分层(一份设计,分批交付)
177+
178+
| 里程碑 | 内容 | 验收 |
179+
|--------|------|------|
180+
| F0 修复快线(先行,可单独发版) | A1 契约断裂 + 契约快照单测 | 真机精修全流程走通(排队中→diff→采纳) |
181+
| F1 修复补齐 | A2-A5(丢图降级、成本映射、审计、配额去重) | 精修不丢图、成本显示真实、审计可见、无重复扣费 |
182+
| F2 任务中心 | B1-B4(任务表/恢复/面板/通知/并发重试) | 重启恢复结果、全局面板可用、完成通知可见、长笔记并发提速 |
183+
| F3 协议 v2 + 评测 | C1-C3 + D + E + G | 配图经 image 块保留、切片结构不乱、单价映射生效、回归全绿 |
184+
185+
## 5. 行动计划
186+
187+
| 项 | 下一步 | 负责人 | 截止 |
188+
|----|--------|--------|------|
189+
| 设计文档 | 本文件落库 + commit | AI 代理 | 2026-08-21 |
190+
| F0 修复快线 | 契约修复 + 快照单测 + 真机验证 | AI 代理 | F0 门禁 |
191+
| F1 修复补齐 | 丢图降级/成本映射/审计/配额去重 | AI 代理 | F1 门禁 |
192+
| F2 任务中心 | ai_tasks 表/恢复/面板/通知/并发 | AI 代理 | F2 门禁 |
193+
| F3 协议 v2 + 评测 | image 块/片间上下文/单价拦截/golden | AI 代理 | F3 门禁 |
194+
| 真机验收 | 用户真机走通「精修→采纳→版本时间线」全链 | 用户 | 每里程碑 |
195+
196+
## 6. 遗留问题 / 风险
197+
198+
- [ ] 输出 token 估算系数(输入→输出比例)需实测校准(golden 冒烟附带测量)
199+
- [ ] 切片并发 2-3 对 DeepSeek 长输出的实际提速效果待真机验证
200+
- [ ] 单价映射表内置价格需按 2026-08 实测定档(免费档已验证 ¥0)
201+
- [ ] ai_tasks 表保留策略(50 条/类型)与磁盘占用实测
202+
- [ ] 前端任务面板交互形态(Tab vs 独立面板)真机评审
203+
204+
## 7. 回顾
205+
206+
### 本次头脑风暴效果
207+
- 产出:全链路检测报告(P0 契约实证 + P1 八项 + 已做对清单)+ 方案三选(用户裁决 C)+ 六轴扩展全量收敛 + 里程碑四层设计
208+
- 关键转折:契约断裂的**实证**(临时单测实测 serde 输出)把「调用有记录但结果未使用」从现象变为根因;「任务注册表无持久化」洞察让修复与扩展统一到任务中心一个支点
209+
210+
### 改进建议
211+
- 真机问题应先做契约层实证再发散(本次 serde 实测直接锁定根因,避免在错误方向上设计)
212+
- 扩展方向全量裁决时明确「不做」清单(模型对比/人工评分/完整报表页已排除),保持窄而深

0 commit comments

Comments
 (0)