制定 Provider 推理与正文分离改造方案
新增 Issue #331 的分步里程碑方案 明确策划 Agent 与 GameAgent 的兼容边界 补充验收标准、风险与回滚点
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
# 【里程碑】Provider 推理与正文分离及策划 Agent 展示
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 1.0 |
|
||||
| Status | proposed |
|
||||
| Date | 2026-09-14 |
|
||||
| Parent Spec | `docs/technical/【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md` |
|
||||
| Related Issue | `GenarrativeAI/Genarrative#331` |
|
||||
|
||||
## 一句话交付结果
|
||||
|
||||
让策划 Agent 能在流式回合中单独收到 Provider reasoning,并在 UI 中以默认折叠的思考过程展示;用户可见正文、工具调用和 GameAgent 现有行为保持不变。
|
||||
|
||||
## 背景与现状
|
||||
|
||||
- `platform-llm` 当前只向上层提供正文累计值、正文增量和结束状态。
|
||||
- Chat 兼容响应中的 `reasoning`、`reasoning_content` 以及 reasoning content part 会被正文提取器过滤。
|
||||
- Responses 响应中的 reasoning 类型 output item 也不会进入独立的上层字段。
|
||||
- 策划 Agent 已经预留 `DesignEvent.reasoningText`、`planningV2Reasoning` 和默认折叠 UI,但 Provider 解析链没有产出数据,因此折叠区通常不出现。
|
||||
- GameAgent 当前只消费 `delta_text`、`accumulated_text` 和 `finish_reason`,没有消费策划 Agent 的 `reasoningText`。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 为 Provider 流式响应增加独立 reasoning 增量和累计通道。
|
||||
2. 为非流式终态响应提供独立 reasoning 字段。
|
||||
3. 支持 Responses 和 Chat 兼容协议的 reasoning 解析。
|
||||
4. 仅由策划 Agent 显式启用 reasoning 捕获和 UI 转发。
|
||||
5. 保证 reasoning 不进入用户可见正文、工具调用参数或 GameAgent 消息流。
|
||||
6. 在无 reasoning、reasoning 解析异常、重试和工具调用共存场景下保持可恢复行为。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不改变 GameAgent 的正文展示、工具调用、`<think>` 过滤和运行时状态语义。
|
||||
- 不把 reasoning 自动拼接到 `delta_text`、`accumulated_text` 或正式 assistant 消息。
|
||||
- 不把 reasoning 作为新的业务消息类型写入策划会话历史。
|
||||
- 不新增通用 reasoning UI,不改造 Direct/Codex 的过程卡展示。
|
||||
- 不修改 Provider 请求模型、推理档位或 token 预算。
|
||||
- 不为 reasoning 增加新的 SpacetimeDB 表、公开 API 或持久化 schema。
|
||||
|
||||
## 受影响模块与边界
|
||||
|
||||
### Provider 共享层
|
||||
|
||||
`server-rs/crates/platform-llm` 负责协议解析和流式累计:
|
||||
|
||||
- `LlmStreamDelta` 增加 `reasoning_delta` 与 `accumulated_reasoning`。
|
||||
- `LlmRunResponse` 增加终态 reasoning 字段。
|
||||
- `LlmRunRequest` 增加默认关闭的 reasoning 捕获开关。
|
||||
- 正文提取继续排除隐藏 reasoning part;reasoning 进入旁路字段。
|
||||
- reasoning 解析失败只丢弃 reasoning,不影响正文和工具调用。
|
||||
|
||||
### 策划 Runtime
|
||||
|
||||
`apps/ai-game-creator-shell/src-tauri/src/agent/design_runtime.rs` 仅在策划专用请求中打开 reasoning 捕获:
|
||||
|
||||
- 流式 reasoning 更新映射到已有 `DesignEvent.reasoningText`。
|
||||
- 正文继续使用已有 `text` 事件。
|
||||
- 新回合、重试、项目切换和请求失败时清理旧 reasoning。
|
||||
- debug 记录与正文记录分开,内容受现有 debug 开关和长度限制约束。
|
||||
|
||||
### 其它调用方
|
||||
|
||||
GameAgent、Agent Interaction、Direct/Codex 适配层和通用 runtime 继续只读取正文字段。新增 reasoning 字段默认为空,不改变这些调用方的业务判断。
|
||||
|
||||
### 前端
|
||||
|
||||
复用现有 `ProjectSupervisorView` 的 `designReasoning` 和默认折叠 `<details>` 展示。只补事件生命周期和状态清理,不新建平行组件或平行状态协议。
|
||||
|
||||
## 分步实施方案
|
||||
|
||||
### 第一步:冻结共享契约与兼容开关
|
||||
|
||||
明确字段语义、空值语义和捕获开关:
|
||||
|
||||
- reasoning 字段只表示 Provider 返回的内部推理内容,不代表用户正文。
|
||||
- 捕获开关默认关闭;未启用时新增字段为空。
|
||||
- 正文、工具调用、finish reason 和 Responses 原生 output 的现有语义保持不变。
|
||||
- 该步只更新规范、类型定义和构造点,不接入策划 UI。
|
||||
|
||||
验收重点:所有现有 Rust 构造点可编译,GameAgent 现有调用仍只依赖正文字段。
|
||||
|
||||
### 第二步:实现 `platform-llm` 协议解析
|
||||
|
||||
分别补齐:
|
||||
|
||||
- Responses reasoning 增量事件;
|
||||
- Responses 终态 reasoning output item / summary;
|
||||
- Chat `reasoning`、`reasoning_content` 和 reasoning content part;
|
||||
- 正文与 reasoning 的独立累计;
|
||||
- reasoning 与正文、工具调用同时出现时的顺序和去重;
|
||||
- reasoning 解析失败时的降级行为。
|
||||
|
||||
Responses 的原生 output 仍按当前方式保留,用于后续 Responses 会话回放;新增 reasoning 字段只用于上层展示和调试消费。
|
||||
|
||||
验收重点:正文永远不含 reasoning;无 reasoning 的响应与当前行为一致。
|
||||
|
||||
### 第三步:补齐共享适配层并锁定 GameAgent 不变
|
||||
|
||||
更新 `LlmStreamDelta` 构造点、适配器和测试辅助函数,使它们为新增字段提供空值。检查并锁定:
|
||||
|
||||
- GameAgent 正文流不读取 reasoning;
|
||||
- 工具调用判断不读取 reasoning;
|
||||
- Direct/Codex 过程卡不显示 reasoning;
|
||||
- 通用 response stream 过滤逻辑不因新增字段改变。
|
||||
|
||||
验收重点:现有工具调用、正文流式、Direct 和 Agent Interaction 测试无行为回归。
|
||||
|
||||
### 第四步:接通策划 Runtime 与现有 UI
|
||||
|
||||
仅在策划 Agent Provider 请求中启用捕获开关:
|
||||
|
||||
- 收到 reasoning 增量时发出独立 `reasoningText`;
|
||||
- 收到正文增量时继续发出原有 `text`;
|
||||
- 重试时替换同一回合的临时 reasoning,不残留上一 attempt;
|
||||
- 正式回合结束后保留本回合展示,下一回合开始时清理;
|
||||
- UI 默认折叠,展开后显示累计 reasoning,不影响正文滚动和输入。
|
||||
|
||||
验收重点:策划 Agent 能看到独立 reasoning,正文气泡不重复、不混入推理文本。
|
||||
|
||||
### 第五步:完成回归、文档和验收证据
|
||||
|
||||
形成逐条证据矩阵,至少覆盖:
|
||||
|
||||
- Responses reasoning 增量和终态;
|
||||
- Chat reasoning 字段和 content part;
|
||||
- 正文与 reasoning 分离;
|
||||
- reasoning 与工具调用并存;
|
||||
- reasoning 解析失败降级;
|
||||
- 无 reasoning 兼容行为;
|
||||
- 策划 Runtime 事件映射和 UI 生命周期;
|
||||
- GameAgent 正文与工具调用回归。
|
||||
|
||||
## 契约与持久化策略
|
||||
|
||||
- 不修改 HTTP API、OpenAPI、SpacetimeDB schema 或生成绑定。
|
||||
- 不新增正式持久化字段;策划会话仍保存既有对话和 Responses 原生 output。
|
||||
- reasoning 捕获开关属于 Provider 请求的内部调用语义,默认关闭,不改变已有请求的默认指纹和展示行为。
|
||||
- reasoning 不作为下一轮普通用户可见正文回灌;Responses 原生 output 的恢复语义保持现状。
|
||||
|
||||
## 失败、重试与恢复
|
||||
|
||||
- reasoning 解析失败:保留正文和工具调用,reasoning 字段置空或保留已累计部分。
|
||||
- Provider 瞬态重试:reasoning 与正文使用同一回合、同一响应槽,新的 attempt 替换临时值。
|
||||
- 流中断:沿用现有 Provider 错误和策划会话恢复规则,不把未完成 reasoning 误判为正式消息。
|
||||
- UI 刷新或项目恢复:只从当前事件/状态恢复 reasoning,不隐式唤醒 Provider。
|
||||
|
||||
## 风险与回滚点
|
||||
|
||||
| 风险 | 控制措施 | 回滚点 |
|
||||
| --- | --- | --- |
|
||||
| 共享结构体新增字段导致构造点遗漏 | 先补齐所有构造点和编译检查 | 回退共享字段提交 |
|
||||
| Provider 把 reasoning 混入正文 | 保留独立提取器和正文过滤测试 | 关闭 reasoning 捕获开关 |
|
||||
| Responses summary 事件重复累计 | 以增量事件为主,终态仅做快照/兜底 | 关闭对应事件解析 |
|
||||
| GameAgent 意外展示 reasoning | 捕获默认关闭,调用方只读正文字段 | 回退策划开关,不影响共享解析 |
|
||||
| 重试残留旧 reasoning | 按回合和响应槽清理/替换 | 回退 UI 事件消费 |
|
||||
|
||||
## 验收命令
|
||||
|
||||
代码实现阶段按里程碑执行,不在本计划阶段运行业务测试。预计命令:
|
||||
|
||||
```text
|
||||
cargo test -p platform-llm
|
||||
cargo test -p ai-game-creator-shell
|
||||
npm run typecheck
|
||||
npm run check:encoding
|
||||
git diff --check
|
||||
```
|
||||
|
||||
文档阶段已要求补充运行:
|
||||
|
||||
```text
|
||||
npm run check:doc-index
|
||||
npm run check:encoding
|
||||
git diff --check
|
||||
```
|
||||
|
||||
## 当前状态与下一步
|
||||
|
||||
当前仅完成问题定位和方案设计,未修改业务代码。进入实现前应先评审本里程碑的字段语义、默认关闭策略、Responses 事件覆盖范围和 reasoning 是否进入 debug 记录;评审通过后再为单个里程碑建立对应的 `【实施计划】` 文档。
|
||||
Reference in New Issue
Block a user