Files
mnote/design/10-review/done/09-page-ai-fast-block-edit-runtime-review.md
T
lix-2026 1882db7681 收口 MNote P0 P1 P2 审查尾项
- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目
- 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线
- 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径

验证:
- cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1
- cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1
- git diff --check
- git diff --cached --check
- codegraph index . --force && codegraph status .
- codegraph sync . && codegraph status .
2026-06-01 09:29:12 +08:00

271 lines
9.5 KiB
Markdown
Raw 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.
# 09 页面 AI 快速块编辑 Runtime Review
> 状态:`done`
>
> 日期:2026-05-16
>
> 关联主线:
> - `design/old/07-ai/process/7-10-page-block-ai-tooling-execution-checklist-v1.md`
> - `design/07-ai/reference/7-12-page-ai-hermes-tool-routing-and-review-surface-v1.md`
> - `design/07-ai/done/7-9-page-block-ai-tooling-roadmap-v1.md`
> - `design/05-editor-mainline/done/5-13-page-block-identity-and-command-contract-v1.md`
---
## 0. 归档说明
本文件是 2026-05-16 的页面 AI fast block edit 历史审查快照。其记录的 `local_rule` / `doc_apply_block_ops` 快路径曾被后续 `mnote.doc.markdown_edit` 阶段替代,但该阶段也已被 local-first agent 文件编辑控制面覆盖;本文不再作为当前 runtime 口径。
2026-06-01 当前有效口径:local-first 普通 Markdown 编辑默认走授权文件引用 + allowed roots/files + agent 原生 patch/diff + watcher/BufferStore/Page Aggregate 同步;`mnote.doc.markdown_edit` 只保留为 remote/cloud/compat fallback 或结构校验辅助。
当前有效口径见:
- [10-current-mnote-ai-runtime-review-v1](./10-current-mnote-ai-runtime-review-v1.md)
- [11-current-full-architecture-review-v1](./11-current-full-architecture-review-v1.md)
- [7-18 AI markdown_edit 阶段状态合同漂移](../../../bugs/07-ai/done/7-18-ai-markdown-edit-phase-state-contract-drift-v1.md)
- [7-20 page_ai_workflow 绕过 Hermes tool executor / audit / toggle](../../../bugs/07-ai/done/7-20-page-ai-workflow-bypasses-hermes-tool-executor-v1.md)
归档时的历史结论:`page-ai/block-edit-workflow` 仍是简单编辑 fast-path 入口,但当时实现应通过模型生成 markdown search/replace / full_content 后调用 `mnote.doc.markdown_edit`,并复用统一 mnote tool executor`mnote.doc.apply_block_ops` / `mnote.block.*` 只作为结构性块操作辅助。该结论不指导当前 local-first 新实现。
## 1. 本轮结论
页面 AI 块写入的慢点不在 Rust 块工具本身,也不在 Convex 持久化本身。
本轮真实浏览器 smoke 显示:
- 旧路径:页面 AI 先调用 `/api/page-ai/block-edit-workflow`,快路径模型阶段耗时约 `7695ms`,随后因模型输出的块定位未命中 projection,`doc_apply_block_ops` 返回 `mnote_block_not_found`,前端继续 fallback 到 `/api/hermes/client/runs`,最终由 Hermes agent 调 `mnote.doc.apply_block_ops` 写入,总可见耗时约 `13246ms`
- 新路径:同一类简单中文块操作先由 mnote 本地 planner 解析为 `replace/insert_after/delete` operations,再直接调用 Rust `doc_apply_block_ops`。浏览器 smoke 回读可见耗时 `788ms`;后端日志显示 `operation_source=local_rule``model_ms=0``apply_ms=42``total_ms=42`,且未进入 `/api/hermes/client/runs`
因此,当前要继续做的是 Hermes 工具路由、上下文冻结、dry-run/review 与 Rust 写入校验基建,而不是继续让 Hermes agent 反复执行同一个端到端动作,也不是在 mnote 内新建第二套 AI runtime。
---
## 2. 慢的直接原因
### 2.1 通用 agent 编排链路太长
旧页面 AI 编辑链路实际包含:
```text
浏览器输入
-> Hermes session/profile/tools 初始化
-> 模型理解页面任务
-> 模型选择工具
-> 工具调用
-> 回读或继续推理
-> 最终回复
```
这适合复杂任务,但不适合“把 A 替换为 B / 在 A 后插入 C / 删除 D”这类明确块操作。
### 2.2 模型直接产 operations 不够可靠
本轮快路径第一版已经绕开 Hermes agent,但仍让 DeepSeek 直接根据 `page_xml/page_text` 生成 operations。失败点是:
```text
model_ms ~= 7695
operations = 3
apply -> mnote_block_not_found
fallback -> Hermes agent
```
说明模型输出了看似正确的操作数,但 block 定位信息没有命中当前 Page Aggregate projection。这个问题不能靠增加 smoke 次数解决,必须让 mnote runtime 在模型前后都掌握定位与校验。
### 2.3 失败后 fallback 放大了耗时
第一版前端逻辑在快路径失败时继续进入 `/api/hermes/client/runs`。这导致一次用户请求可能经历:
```text
快路径模型失败成本 + Hermes agent 成功成本
```
本轮已改为:只有后端明确返回 `page_ai_workflow_not_block_edit` 才允许 fallback;其他快路径错误直接在本轮 run 中失败展示,避免重复写入和重复等待。
---
## 3. 已完成的修正
### 3.1 页面 AI 快速块编辑 route
已新增并接入:
- `POST /api/page-ai/block-edit-workflow`
- 文件:`rust/crates/mnote-web/src/routes/page_ai_workflow.rs`
该 route 负责:
- 接收当前页面冻结后的 `mnote.page_ai_context.v1`
- 为明确中文编辑语句先走本地 operation planner。
- 无法本地解析时才调用小模型生成 operations。
- 最终统一走 `mnote.doc.apply_block_ops`,由 Rust 生成 canonical content 并保存。
### 3.2 简单块操作本地 planner
已支持这类明确表达:
```text
把「A」替换为「B」;
在「C」后插入「D」;
删除「E」。
```
输出直接是:
```json
[
{"op":"replace","matchText":"A","content":"B"},
{"op":"insert_after","matchText":"C","content":"D"},
{"op":"delete","matchText":"E"}
]
```
该层的目的不是做通用自然语言理解,而是把高频、低歧义、可确定的块编辑从模型路径剥离出来。
### 3.3 快路径可观测性
后端日志已记录:
- workflow started/completed
- operation source`local_rule``model`
- operations 数量
- model 耗时
- apply 耗时
- total 耗时
smoke 也已在失败时写出 evidence JSON,并记录 `/api/page-ai/*``/api/hermes/client/*` 请求/响应。
---
## 4. 验证证据
命令:
```bash
cargo test -p mnote-web page_ai_workflow -- --nocapture
cargo test -p mnote-web hermes_tools -- --nocapture
MNOTE_PAGE_AI_FAST_TIMEOUT_MS=60000 node scripts/task-page-ai-block-edit-workflow-smoke.js
```
结果:
- `page_ai_workflow`2 passed。
- `hermes_tools`22 passed。
- 浏览器 smoke:通过。
最新浏览器 evidence
```text
/mnt/Data1T/mnote/tmp/page-ai-block-edit-workflow-smoke/mp86uciu.json
```
关键值:
```json
{
"timingsMs": {
"pageAiWriteVisible": 788
},
"usedFastWorkflow": true,
"usedHermesRun": false,
"finalTexts": [
"第一段 mp86uciu",
"插入段 mp86uciu",
"第二段已修改 mp86uciu"
]
}
```
后端关键日志:
```text
operation_source="local_rule"
model_ms=0
apply_ms=42
total_ms=42
```
---
## 5. 剩余问题
### 5.1 不能把本地 planner 当成完整 AI runtime
当前本地 planner 只覆盖低歧义中文引号表达。它证明了正确的 runtime 方向,但不是最终答案。
需要继续建设:
- PageAIContextBuilder:冻结 selection/page context,减少模型输入。
- PageAIIntentParser:先判定是明确块操作、结构化改写、摘要问答、还是复杂编辑。
- PageAIOperationPlanner:把明确操作转成 `mnote.doc.apply_block_ops`,复杂操作才调用小模型。
- PageAIOperationValidator:模型输出后必须用 projection 校验 blockId/matchText/allowedTargetBlockIds。
- PageAIApplyController:统一处理 yolo 写入、失败展示、回读验证、审计日志。
### 5.2 模型输出 operations 仍需修
当请求不能被本地 planner 解析时,仍会调用模型。该路径必须补:
- 输出 schema 更严格,禁止模型臆造 blockId。
- 优先 `matchText` 或由服务端根据 text resolve block,而不是信任模型 blockId。
- 模型输出后做 dry-run validate,不命中时不要 fallback Hermes agent 重新跑。
- 把 validation error 反馈给用户或进入后续 clarify/retry,而不是隐式整页写。
### 5.3 Hermes agent 不应承担短路径编辑
Hermes 仍适合:
- 多步骤页面理解。
- 跨页面检索。
- 工具不可直接表达的复杂任务。
- 外部 skill/plugin 编排。
但对当前页面小段落块增删改,mnote 自己的 runtime 应该在浏览器/Rust route 内完成 `intent -> operations -> apply -> readback`
---
## 6. 下一步建议
优先级应从“继续 smoke”切到“补 AI runtime 基建”:
1. `PageAIIntentParser`
- 输入:用户 prompt、scope、selection、page context。
- 输出:`direct_block_ops | model_block_ops | question | unsupported`
- 目标:不让每条简单编辑都进入 Hermes agent。
2. `PageAIOperationPlanner`
- 扩展当前本地 planner。
- 支持常见中文/英文明确表达。
- 支持选区内“改成/润色/拆成列表”等可控操作。
3. `PageAIOperationValidator`
- 所有 operations apply 前先 resolve projection。
- 对 blockId、matchText、allowedTargetBlockIds、editable、children、revisionRef 做统一校验。
- 失败返回结构化错误,不 fallback 通用 agent。
4. `PageAIApplyController`
- 统一 yolo 模式下的写入、回读、状态展示和失败提示。
- 后续再接 preview/review session,而不是现在把 review 作为默认阻塞。
5. 模型路径瘦身
- 对必须调用小模型的任务,发送 `page_xml/text + allowed operations schema`
- 模型只负责生成候选 operations;最终定位、校验和写入仍由 Rust runtime 负责。
---
## 7. 当前判断
小段落编辑低于 10s 已经被证明可达,且当前 smoke 为 `788ms`
下一阶段的关键不是再证明“能写”,而是把这条快路径产品化:
```text
用户意图
-> mnote intent/parser
-> operation planner
-> projection validator
-> Rust apply
-> readback
-> UI 状态/审计
```
Hermes agent 应从默认编辑执行器退回到复杂任务编排器。