docs: 添加双 Agent 协同实施方案

This commit is contained in:
hh
2026-07-17 18:14:54 +08:00
parent 2daf9b77e9
commit bfca22677c
4 changed files with 2829 additions and 0 deletions
@@ -0,0 +1,435 @@
# 平台套图 Agent TODO 代码实施计划
> 依据:`07_平台套图Agent_协同引入实施方案.md`
> 原则:一步一确认、公共运行时复用、先拆规则再编排、先人工采用再自动质检补图。
> 本文件是实施清单,不代表已经修改代码。
## 1. 强制确认机制
每一步必须经过两次用户确认:
```text
开始前:“确认开始 Pxx”
→ 只实施 Pxx
→ 汇报代码、migration、测试、风险、回滚
完成后:“确认完成 Pxx,进入 Pyy”
```
未收到完成确认,禁止实施下一步。禁止一次确认连续做多个步骤。
状态:`[ ] 未开始``[~] 实施中``[?] 待验收``[x] 已验收``[!] 阻塞`
## 2. 前置依赖
- [ ] 脚本计划 `S03` 的 AgentRun/AgentStep/AgentArtifact 已验收;
- [ ] 脚本计划 `S04` 的工具协议、权限、预算、恢复已验收;
- [ ] 若尚未建设,必须先单独确认实施 S03–S04;
- [ ] 平台套图不得复制另一套 Agent 基础设施。
## 3. 实施顺序
```text
P00 业务决策
→ P01 抽离平台规则
→ P02 抽离 PromptCompiler 和单图 Spec
→ P03 修正旧链路可追溯性
→ P04 建套图领域版本
→ P05 建 Context 与参考图硬门槛
→ P06 建确定性 KitPlan
→ P07 建模型路由和生成工具
→ P08 建 Coordinator MVP
→ P09 建 API 与前端采用
→ P10 建确定性质检
→ P11 接 OCR/视觉评估
→ P12 接单槽定向补图
→ P13 Handoff、回归和灰度
→ P14 旧编排退役评估
```
## 4. TODO 明细
### [ ] P00:确认平台套图首期口径
确认项:
- [ ] MVP 首期只做 4 张,还是直接支持 4/8/12;
- [ ] 各数量的必需槽位;
- [ ] 平台规则版本和首期平台范围;
- [ ] 无真实商品图必须阻塞;
- [ ] 文字政策:no_text/minimal/short_labels
- [ ] 用户明确模型与自动路由规则;
- [ ] 单图和整套预算;
- [ ] 首期人工采用,不自动发布;
- [ ] OCR/视觉评估放 MVP 后实施。
代码范围:无业务代码修改。
启动口令:`确认开始 P00`
完成口令:`确认完成 P00,进入 P01`
---
### [ ] P01:抽离平台规则服务
依赖:P00。
目标:只解耦,不改变旧 `mode=cover` 结果。
代码 TODO
- [ ]`services.py` 封装 `_PLATFORM_NAMES`
- [ ] 封装 `_PLATFORM_COVER_BLOCKS`
- [ ] 封装 `_COVER_SLOTS`
- [ ] 封装低密度、背景、负面规则;
- [ ] 新建 `PlatformRule/v1`
- [ ] 新建 `PlatformRuleProvider.get()`
- [ ] 记录 rule_version
- [ ] 旧提示词函数改为调用 Provider;
- [ ] 不迁数据库、不改页面。
测试:十个平台映射、规则快照、未知平台、旧 prompt 等价。
完成标准:平台规则有单一读取接口,旧行为不变。
启动口令:`确认开始 P01`
完成口令:`确认完成 P01,进入 P02`
---
### [ ] P02:抽离 PromptCompiler 与单图 Spec
依赖:P01。
目标:让规划与 Worker 执行解耦。
代码 TODO
- [ ] `PlatformKitSlot/v1`
- [ ] `ImageGenerationSpec/v1` 公共 Schema
- [ ] `compile_platform_image_spec()` 纯函数;
- [ ] 明确 references、roles、ratio、prompt、negative、rubric
- [ ] 编译结果不查库、不调用模型;
- [ ]`enqueue_standalone_images()``enqueue_standalone_image_spec()`
- [ ] Worker 优先执行已编译 spec
- [ ] 旧 cover 请求通过 legacy adapter 生成相同 spec
- [ ] 不新增 Agent Coordinator。
测试:Prompt 黄金快照、ratio 尺寸、reference 顺序、旧 cover 回归、重复 spec 幂等。
完成标准:单张平台图可由完整 spec 独立提交。
启动口令:`确认开始 P02`
完成口令:`确认完成 P02,进入 P03`
---
### [ ] P03:修正旧链路可追溯性和禁止隐式问题
依赖:P02。
目标:先修数据基础,不启用 Agent。
代码 TODO
- [ ] Asset metadata 增加 platform_id、slot、attempt、rule_version
- [ ] AITask 保存最终模型、最终 prompt/spec
- [ ] 纯文本调用明确传 ratio/size
- [ ] Agent 模式预留 `allow_text_fallback=false`
- [ ] 旧模式保持兼容但记录 fallback_reason
- [ ] platform_id team/输入校验;
- [ ] 前端展示实际模型;
- [ ] 不删除旧批次。
测试:metadata、比例、模型追溯、旧资产序列化、轮询结果。
启动口令:`确认开始 P03`
完成口令:`确认完成 P03,进入 P04`
---
### [ ] P04:建立 PlatformKitVersion/Item
依赖:P03。
代码 TODO
- [ ] `PlatformKitVersion` 模型和状态;
- [ ] `PlatformKitItem` 模型和状态;
- [ ] product/platform/version/plan/hash/run 字段;
- [ ] slot_id/order/goal/selected_asset/task/attempt/report
- [ ] 唯一约束和索引;
- [ ] Serializer 和只读查询服务;
- [ ] 采用事务服务;
- [ ] migration 正反向验证;
- [ ] 不改变 Asset 真相源。
测试:版本、槽位唯一、跨团队、采用事务、删除保护。
完成标准:能保存空计划和槽位,但尚不生成图片。
启动口令:`确认开始 P04`
完成口令:`确认完成 P04,进入 P05`
---
### [ ] P05ContextSnapshot 与真实参考图硬门槛
依赖:P04。
代码 TODO
- [ ] `PlatformKitAgentRequest/v1`
- [ ] `PlatformKitContextSnapshot/v1`
- [ ] 商品和卖点 team 校验;
- [ ] 真实上传图优先并排除 AI 图;
- [ ] 用户选图需属于商品;
- [ ] 保存 asset/file checksum
- [ ] `NO_REAL_PRODUCT_REFERENCE`
- [ ] 无图时 waiting_user 且不创建图片 AITask
- [ ] snapshot hash/stale 检查。
测试:无图、真实图、AI 图、跨团队、文件删除、商品修改。
完成标准:不给模型调用,也能得到完整 Context 或明确阻塞原因。
启动口令:`确认开始 P05`
完成口令:`确认完成 P05,进入 P06`
---
### [ ] P06:确定性 PlatformKitPlan MVP
依赖:P05。
目标:先不调用文本 Planner。
代码 TODO
- [ ] `PlatformKitPlan/v1`
- [ ] 按 P00 数量生成稳定 slot_id
- [ ] hero/scene/selling/detail/multi/promo 策略;
- [ ] 卖点 ID 分配;
- [ ] 每槽 goal/composition/text_policy/reference_roles/acceptance
- [ ] PlanValidator
- [ ] 必需槽位、数量、重复、卖点、文字、ratio 校验;
- [ ] 8/12 张不得简单复制完全相同槽位;
- [ ] 保存 plan/rule version。
测试:各数量、各平台、无卖点、多卖点、未知平台、重复槽位。
完成标准:规则即可生成可执行、可解释的套图计划。
启动口令:`确认开始 P06`
完成口令:`确认完成 P06,进入 P07`
---
### [ ] P07:模型能力路由和图片生成工具
依赖:P06。
代码 TODO
- [ ] `ModelRequirement`multi_reference/count/ratio/quality
- [ ] 包装现有 `resolve_image_model()`
- [ ] 明确模型能力不满足时停止;
- [ ] 禁止丢商品图后纯文降级;
- [ ] `quote_image_spec.v1`
- [ ] `generate_image_spec.v1`
- [ ] 每槽一条 AITask
- [ ] spec/idempotency/run/kit/slot 写入任务;
- [ ] 失败复用退款;
- [ ] 实际模型返回前端。
测试:Seedream/GPT、多参考、比例不支持、余额不足、重复提交、Provider 失败。
启动口令:`确认开始 P07`
完成口令:`确认完成 P07,进入 P08`
---
### [ ] P08PlatformKit Coordinator MVP
依赖:P07。
MVP 流程:
```text
collect_context
→ plan
→ validate_plan
→ quote
→ persist_kit
→ compile_specs
→ bounded_fan_out
→ wait_tasks
→ bind_assets
→ waiting_human
```
代码 TODO
- [ ] AgentRun(agent_type=platform_kit)
- [ ] 固定 DAG
- [ ] 同 Run 图片并发限制;
- [ ] 部分失败不取消成功槽;
- [ ] fan-in 和恢复;
- [ ] Item 状态与 AITask 同步;
- [ ] 取消后不创建新任务;
- [ ] 暂不自动质检、暂不补图;
- [ ] 不自动采用。
测试:正常、部分失败、断线恢复、重复 Worker、取消、预算不足。
启动口令:`确认开始 P08`
完成口令:`确认完成 P08,进入 P09`
---
### [ ] P09API 和前端人工采用闭环
依赖:P08。
代码 TODO
- [ ] 创建 PlatformKit AgentRun API
- [ ] Run/Step/Kit 查询;
- [ ] 补图前暂只支持手动 retry action
- [ ] 选择槽位候选;
- [ ] 整套采用 API
- [ ] 前端输入/计划/槽位进度;
- [ ] 实际模型与费用;
- [ ] 刷新恢复;
- [ ] feature flag
- [ ] legacy cover 入口仍可回退。
测试:team 权限、采用事务、页面恢复、前端 build、旧入口回归。
完成标准:MVP 可计划、生成、人工选择和采用。
启动口令:`确认开始 P09`
完成口令:`确认完成 P09,进入 P10`
---
### [ ] P10:确定性图片与整套质检
依赖:P09。
代码 TODO
- [ ] 文件可读、尺寸、ratio
- [ ] 文件重复/近重复基础检测;
- [ ] 槽位齐全;
- [ ] slot/order/count
- [ ] metadata/spec/asset 对齐;
- [ ] 整套缺图和重复构图 warning;
- [ ] `ImageEvaluationReport/v1` 基础结构;
- [ ] issue code/severity/repairable
- [ ] 不调用视觉模型。
测试:每项规则正反样例。
启动口令:`确认开始 P10`
完成口令:`确认完成 P10,进入 P11`
---
### [ ] P11OCR 与独立视觉评估
依赖:P10;用户单独确认评估模型和费用。
代码 TODO
- [ ] OCR Adapter
- [ ] 二维码、平台 Logo、乱码、价格和声明检查;
- [ ] 视觉评估 Tool
- [ ] 商品身份、构图、平台适配、槽位目标维度;
- [ ] 评估 AITask/费用;
- [ ] rubric/model/threshold version
- [ ] 规则 + OCR + 视觉结果汇总;
- [ ] 评估不可用时转 warning,不把图片删掉。
测试:mock OCR/VLM、错误码、超时、费用、低置信度。
启动口令:`确认开始 P11`
完成口令:`确认完成 P11,进入 P12`
---
### [ ] P12:单槽定向补图
依赖:P11。
代码 TODO
- [ ] issue code → RepairSpec
- [ ] 只修改相关 prompt 段;
- [ ] 每槽最多 2 attempts
- [ ] 只补 error 且 repairable
- [ ] 超自动预算先确认;
- [ ] 新候选不删除旧 Asset
- [ ] 补图后完整复检;
- [ ] 第二次失败停止;
- [ ] 前端展示修复原因和新增费用。
测试:变色、错字、裁切、重复构图、预算不足、达到上限。
启动口令:`确认开始 P12`
完成口令:`确认完成 P12,进入 P13`
---
### [ ] P13Handoff、完整回归和灰度
依赖:P09;如启用质检补图则还依赖 P10–P12。
代码 TODO
- [ ] `PlatformKitHandoff/v1`
- [ ] AgentArtifact 关联 Kit/Item/Asset/报告;
- [ ] adopt 前 snapshot hash
- [ ] 全流程集成测试;
- [ ] 指标:首轮通过率、补图率、采用率、费用、耗时;
- [ ] 团队 feature flag
- [ ] 发布和回滚说明;
- [ ] legacy 继续保留。
灰度每一级都需用户确认。
启动口令:`确认开始 P13`
完成口令:`确认完成 P13,进入 P14`
---
### [ ] P14:旧平台套图编排退役评估
依赖:P13 稳定运行约定周期。
先评估:旧 API 调用、活动 batch、历史资产、Agent 指标、回滚能力。
允许删除:旧页面直接循环批次、`index % 6` 编排、旧 cover 薄适配。
禁止删除:平台规则、PromptCompiler、图片 Worker、AITask、Asset、Billing、Provider。
启动口令:`确认开始 P14 评估`
删除口令:`确认执行旧平台套图编排下线`
完成口令:`确认完成 P14`
## 5. 每步完成汇报模板
```text
步骤:Pxx
状态:等待用户验收
本步改动文件:
数据库 migration
行为变化:
测试命令与结果:
未通过项/风险:
回滚方式:
明确未实施的后续步骤:
请确认:“确认完成 Pxx,进入 Pyy”
```
## 6. 推荐首次执行
先检查公共基础设施依赖,然后从 `P00` 开始。没有 `确认开始 P00` 不修改代码。
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,567 @@
# 视频项目—脚本 Agent TODO 代码实施计划
> 依据:`06_视频项目脚本Agent_协同引入实施方案.md`
> 原则:一步一确认、先解耦再新增、每步可测试可回滚、公共能力只建设一次。
> 本文件是实施清单,不代表已经修改代码。
## 1. 强制执行规则
每个 TODO 都执行以下闭环:
```text
1. 用户发送“确认开始 Sxx”
2. 只实施 Sxx 明确列出的范围
3. 执行本步骤测试和回归
4. 汇报文件、行为变化、测试结果、遗留风险
5. 用户发送“确认完成 Sxx,进入 Syy”
6. 才允许开始下一步
```
禁止:
- 一次确认后连续实施多个步骤;
- 未经确认顺手重构下一步代码;
- 测试未通过就标记完成;
- 为 Agent 重写 AITask、计费、Provider、资产和脚本版本;
- 在新链路稳定前删除旧入口;
- 把计划状态、测试结果或用户确认伪造为已完成。
状态标记:
```text
[ ] 未开始
[~] 已获开始确认,实施中
[?] 实施完成,等待用户验收
[x] 用户已验收
[!] 阻塞
```
## 2. 全局实施顺序
```text
S00 口径确认
→ S01 修正脚本输入契约
→ S02 解耦现有脚本生成内核
→ S03 建公共 Agent 数据骨架
→ S04 建公共工具与最小运行时
→ S05 建脚本 Snapshot/Brief
→ S06 建确定性校验器
→ S07 接入生成工具
→ S08 建脚本 Coordinator MVP
→ S09 建 API 与运行恢复
→ S10 接前端真实状态
→ S11 建 Handoff、采用前检查
→ S12 可选评审与一次修订
→ S13 灰度与完整回归
→ S14 旧编排退役评估
```
`S03S04` 是三个 Agent 共用的基础设施。平台套图和模特上身图计划只能复用,不得复制。
## 3. TODO 明细
### [ ] S00:冻结业务口径和基线
目标:在写代码前确认唯一规则,避免 Agent 固化当前矛盾。
确认项:
- [ ] 时长与镜数唯一口径:15/30/60 秒分别对应多少镜、每镜多长;
- [ ] `auto/theme/manual/revise/revise_segment` 的准确含义;
- [ ] “自带脚本”是原文进入模型整理,还是完全原样保存;
- [ ] 卖点必须使用真实 ID
- [ ] 用户明确模型与自动路由的优先级;
- [ ] 首期是否启用语义评审;
- [ ] 单次生成、评审、修订的预算上限;
- [ ] 仍由用户采用脚本。
代码范围:无业务代码修改;只允许补充决策记录。
验收产物:一份经过用户确认的决策表,后续 Schema 和测试引用同一口径。
启动口令:`确认开始 S00`
完成口令:`确认完成 S00,进入 S01`
---
### [ ] S01:修正脚本输入契约
依赖:S00 已验收。
目标:先解决卖点、时长、模式等数据问题,不引入 Agent。
代码 TODO
- [ ] 前端提交真实 `selected_selling_point_ids`
- [ ] 后端按 team 和 product 校验卖点 ID
- [ ] 保存卖点 ID、标题、内容快照;
- [ ] 建立唯一的 duration → shot_policy 转换函数;
- [ ] 明确 manual 模式,不再隐式落入 theme 分支;
- [ ] 为旧请求增加兼容适配和弃用日志;
- [ ] 补请求 Serializer/Schema 校验;
- [ ] 不改变旧脚本生成结果结构。
预计文件:
```text
core/frontend/src/routes/pipeline.tsx
core/frontend/src/api.ts
core/frontend/src/types.ts
core/backend/apps/projects/views.py
core/backend/apps/ai/script_agent.py
core/backend/apps/projects/tests.py
core/backend/apps/ai/tests.py
```
测试:
- [ ] 卖点跨商品/跨团队拒绝;
- [ ] 15/30/60 秒镜数一致;
- [ ] 五种模式请求分支正确;
- [ ] 旧请求仍可生成;
- [ ] 不新增重复计费。
完成标准:输入契约唯一,旧入口正常,所有相关测试通过。
启动口令:`确认开始 S01`
完成口令:`确认完成 S01,进入 S02`
---
### [ ] S02:拆出现有脚本生成内核
依赖:S01 已验收。
目标:只做重构,不改变用户可见行为,为 Agent 工具复用做准备。
代码 TODO
- [ ]`stream_script_agent()` 拆出上下文构建;
- [ ] 拆出 system/user messages 构建;
- [ ] 拆出单次 Provider 生成服务;
- [ ] 保留流式事件适配;
- [ ] 拆出 normalize/Schema 校验入口;
- [ ] 拆出未采用 ScriptVersion 保存服务;
- [ ]`script-agent-stream` 改为调用这些服务;
- [ ] 不新增 AgentRun,不改前端。
建议接口:
```text
build_script_generation_context()
build_script_messages()
generate_script_once()
normalize_script_result()
save_script_candidate()
```
测试:
- [ ] 重构前后同输入的 messages 等价;
- [ ] SSE 事件类型保持兼容;
- [ ] ScriptDraft、ScriptVersion、ScriptSegment 结构不变;
- [ ] 中断、失败、退款行为不变;
- [ ] 现有项目测试全过。
完成标准:旧入口只作为薄适配器,核心服务可独立测试。
启动口令:`确认开始 S02`
完成口令:`确认完成 S02,进入 S03`
---
### [ ] S03:建立公共 Agent 数据骨架
依赖:S02 已验收。
目标:创建三个 Agent 共用的最小运行记录,不加入具体脚本逻辑。
代码 TODO
- [ ] 新建 `apps/agents` Django app
- [ ] 新增 `AgentRun`
- [ ] 新增 `AgentStep`
- [ ] 新增 `AgentArtifact`
- [ ] 状态、agent_type、step_type 使用枚举;
- [ ] 加 team/user/scope、预算、停止原因、lock_version
- [ ] AgentStep 可关联 AITask
- [ ] 添加必要索引和唯一约束;
- [ ] 注册 admin 只读审计视图;
- [ ] 生成并检查 migration。
预计目录:
```text
core/backend/apps/agents/
core/backend/airshelf/settings/
```
测试:
- [ ] 模型约束和状态默认值;
- [ ] team 隔离;
- [ ] `(team, idempotency_key)` 唯一;
- [ ] Step 顺序/幂等唯一;
- [ ] 删除策略不误删 AITask/业务产物;
- [ ] migration 可正向/反向执行。
完成标准:只增加通用审计模型,不影响现有业务接口。
启动口令:`确认开始 S03`
完成口令:`确认完成 S03,进入 S04`
---
### [ ] S04:公共工具协议与最小运行时
依赖:S03 已验收。
目标:实现固定状态机所需的公共能力,不做通用自由 Agent 框架。
代码 TODO
- [ ] 定义 `AgentTool``ToolResult`、Schema 校验;
- [ ] 工具注册表;
- [ ] 只读/低风险写/付费/人工确认权限级别;
- [ ] AgentRun 状态迁移校验;
- [ ] Step 创建、开始、成功、失败幂等服务;
- [ ] 运行级预算与步骤上限;
- [ ] AITask 关联和费用汇总;
- [ ] 取消、恢复、stale 标记;
- [ ] 最小运行查询 Serializer
- [ ] 不实现模型自由 tool-calling 循环。
预计目录:
```text
core/backend/apps/agents/runtime.py
core/backend/apps/agents/registry.py
core/backend/apps/agents/policies.py
core/backend/apps/agents/permissions.py
core/backend/apps/agents/tools/base.py
core/backend/apps/agents/tests/
```
测试:
- [ ] 非法状态迁移拒绝;
- [ ] 重复执行同 Step 不产生副作用;
- [ ] 超预算停止;
- [ ] 取消后不创建新 Step
- [ ] waiting_task 恢复使用原 AITask
- [ ] 跨团队工具调用拒绝。
完成标准:可用假工具跑完一个固定 Run,未接任何业务 Agent。
启动口令:`确认开始 S04`
完成口令:`确认完成 S04,进入 S05`
---
### [ ] S05:脚本 ContextSnapshot 与 Brief
依赖:S04 已验收。
目标:建立脚本 Agent 稳定输入,不让 Coordinator 直接 ORM。
代码 TODO
- [ ] `ScriptAgentRequest/v1` Schema
- [ ] `ScriptContextSnapshot/v1` Schema
- [ ] `ScriptBrief/v1` Schema
- [ ] `get_project_script_context.v1` 工具;
- [ ] `get_product_context.v1` 工具;
- [ ] `get_source_script.v1` 工具;
- [ ] 冻结 project/product/selling points/source script 版本;
- [ ] 规则构建 Brief
- [ ] 返回结构化缺失项;
- [ ] 计算 snapshot hash。
测试:
- [ ] auto/theme/manual/revise/segment snapshot
- [ ] 商品、卖点和脚本 team 校验;
- [ ] 缺失字段返回固定错误码;
- [ ] 同输入 hash 稳定;
- [ ] 商品修改可检测 stale。
完成标准:不给模型调用,也能生成完整 Brief 或明确缺失项。
启动口令:`确认开始 S05`
完成口令:`确认完成 S05,进入 S06`
---
### [ ] S06:确定性脚本校验器
依赖:S05 已验收。
目标:把能用代码判断的规则从提示词和模型自检中移出。
代码 TODO
- [ ] `ScriptValidationReport/v1`
- [ ] JSON/字段类型检查;
- [ ] 镜数、总时长、单镜时长;
- [ ] 旁白字数;
- [ ] hook/pain/selling/cta 覆盖;
- [ ] 卖点覆盖;
- [ ] 实体与 `entity_refs`
- [ ] 商品事实、价格、认证、功效来源;
- [ ] 禁止词和绝对化表达;
- [ ] revise_segment 越界修改;
- [ ] issue code、severity、repairable。
测试:每个规则至少一个通过样例和一个失败样例。
完成标准:输入草稿可稳定得到可审计报告,不调用模型。
启动口令:`确认开始 S06`
完成口令:`确认完成 S06,进入 S07`
---
### [ ] S07:脚本生成工具接入 AITask
依赖:S06 已验收。
目标:把 S02 生成内核包装成受控付费工具。
代码 TODO
- [ ] `quote_text_generation.v1`
- [ ] `generate_script_draft.v1`
- [ ] 能力需求与实际 ModelConfig 记录;
- [ ] 用户明确模型时校验,不静默替换;
- [ ] 自动模式仅在 policy 允许时路由;
- [ ] 每次模型调用创建/关联一条 AITask;
- [ ] ToolResult 只返回 Draft 和任务摘要;
- [ ] Provider 失败复用现有退款;
- [ ] 输入快照和 prompt version 进入 request_payload。
测试:
- [ ] 明确模型/自动路由;
- [ ] 余额不足;
- [ ] Provider 失败;
- [ ] 契约异常;
- [ ] 重复工具执行不重复扣费。
完成标准:工具可独立生成 Draft,尚未自动保存和编排。
启动口令:`确认开始 S07`
完成口令:`确认完成 S07,进入 S08`
---
### [ ] S08:脚本 Coordinator MVP
依赖:S07 已验收。
目标:先实现最短闭环,不接语义评审和自动修订。
MVP 流程:
```text
collect_context
→ build_brief
→ quote
→ generate_once
→ normalize
→ validate
→ save_candidate
→ waiting_human
```
代码 TODO
- [ ] 固定状态迁移;
- [ ] 每一步对应 AgentStep
- [ ] 缺输入进入 waiting_user
- [ ] 超预算进入 waiting_approval
- [ ] AITask 执行时进入 waiting_task
- [ ] 校验失败保存报告并进入 needs_review
- [ ] 通过后保存未采用 ScriptVersion
- [ ] Run 可取消、恢复;
- [ ] 不自动 adopt。
测试:正常、缺输入、余额不足、生成失败、校验失败、取消、恢复、重复调度。
完成标准:后端测试中能完整运行一次 Agent MVP。
启动口令:`确认开始 S08`
完成口令:`确认完成 S08,进入 S09`
---
### [ ] S09Agent API、事件和恢复任务
依赖:S08 已验收。
目标:提供稳定 API,前端断线不影响 Agent。
代码 TODO
- [ ] 创建 ScriptAgentRun API
- [ ] Run/Steps 查询 API
- [ ] actions API:补输入、批预算、取消、请求修改;
- [ ] 事件查询 `after=sequence`
- [ ] 可选 SSE 仅投影数据库状态;
- [ ] Celery resume task
- [ ] 活动 Run 扫描和僵尸恢复;
- [ ] 同项目同 Agent 活动运行限制;
- [ ] API team/permission 校验。
测试:断线重连、重复创建、并发 action、越权、恢复不重复调用模型。
完成标准:不依赖浏览器连接即可完成 Run。
启动口令:`确认开始 S09`
完成口令:`确认完成 S09,进入 S10`
---
### [ ] S10:前端接入真实 Agent 状态
依赖:S09 已验收。
目标:在现有脚本页面灰度接入,不重做整页。
代码 TODO
- [ ] 新增 Agent API/types
- [ ] 输入摘要卡;
- [ ] 真实计划和 Step 状态;
- [ ] 缺失信息补充卡;
- [ ] 预算确认卡;
- [ ] 校验报告;
- [ ] 候选脚本和采用入口;
- [ ] 页面刷新恢复 Run
- [ ] feature flag 切换 Agent/legacy
- [ ] 移除 Agent 模式下的硬编码假“自检完成”。
测试:组件状态、刷新恢复、错误展示、legacy 页面不受影响;执行前端 build。
完成标准:灰度用户可以完成 MVP,旧入口仍可回退。
启动口令:`确认开始 S10`
完成口令:`确认完成 S10,进入 S11`
---
### [ ] S11Handoff、采用前检查和输入过期
依赖:S10 已验收。
目标:让下游读取结构化交接,不依赖 Agent 对话。
代码 TODO
- [ ] `ScriptHandoff/v1`
- [ ] required_assets/acceptance/open_questions
- [ ] AgentArtifact 关联 ScriptVersion 和报告;
- [ ] ScriptVersion metadata 写 run/schema/hash 摘要;
- [ ] `check_script_adoptable.v1`
- [ ] adopt 前比较 snapshot hash
- [ ] stale 禁止采用;
- [ ] 采用仍调用现有业务服务。
测试:Handoff Schema、过期输入、采用事务、下游实体/资产需求读取。
完成标准:采用脚本有可追溯 Handoff,Agent 不直接推进下一阶段。
启动口令:`确认开始 S11`
完成口令:`确认完成 S11,进入 S12`
---
### [ ] S12:可选语义评审与一次定向修订
依赖:S11 已验收;S00 已确认首期需要此能力。
目标:在 MVP 稳定后增加有限协作,不修改固定状态机边界。
代码 TODO
- [ ] `ScriptReviewReport/v1`
- [ ] `review_script_semantics.v1`
- [ ] 仅规则通过或指定 warning 时评审;
- [ ] `revise_script_draft.v1`
- [ ] 只传结构化 issue
- [ ] 自动修订最多一次;
- [ ] 修订后重新跑全部规则;
- [ ] 第二次仍失败进入 needs_review
- [ ] 评审/修订分别报价和关联 AITask。
测试:跳过评审、评审通过、定向修订、预算不足、达到上限。
完成标准:绝不形成无限评审/修订循环。
启动口令:`确认开始 S12`
完成口令:`确认完成 S12,进入 S13`
---
### [ ] S13:完整回归、指标和灰度
依赖:S11;如实施 S12 则还依赖 S12。
代码 TODO
- [ ] 全模式集成测试;
- [ ] 任务、退款、恢复、采用回归;
- [ ] 指标:契约通过率、事实错误率、卖点覆盖率、采用率、费用、耗时;
- [ ] feature flag 按团队灰度;
- [ ] 管理端能查询 Run/Step/AITask
- [ ] Agent 出错允许用户主动回旧入口;
- [ ] 完成发布/回滚说明。
灰度闸门:先内部团队,再小比例客户,再逐步默认开启;每一级都需要用户确认。
启动口令:`确认开始 S13`
完成口令:`确认完成 S13,进入 S14`
---
### [ ] S14:旧脚本编排退役评估
依赖:S13 已稳定运行至少一个约定观察周期。
本步骤默认只评估,不直接删除。
检查:
- [ ] 是否还有客户端调用 `script-agent-stream`
- [ ] 是否还有活动旧任务;
- [ ] Agent 成功率、费用、耗时、采用率达标;
- [ ] 历史任务和脚本可继续读取;
- [ ] 新生成内核已被工具复用;
- [ ] 回滚方案存在;
- [ ] 用户明确批准下线。
允许删除:旧前端入口、旧 SSE 编排薄壳、硬编码假步骤。
禁止删除:生成内核、normalize、ScriptVersion、AITask、计费、Provider、采用服务。
启动口令:`确认开始 S14 评估`
删除口令:`确认执行旧脚本编排下线`
完成口令:`确认完成 S14`
## 4. 每步完成汇报模板
```text
步骤:Sxx
状态:等待用户验收
本步改动文件:
行为变化:
数据库 migration:有/无
测试命令与结果:
未通过项:
遗留风险:
回滚方式:
未实施的下一步内容:
请确认:“确认完成 Sxx,进入 Syy”
```
## 5. 推荐首次执行
`S00` 开始。没有得到 `确认开始 S00` 前,不修改任何代码。
@@ -0,0 +1,792 @@
# 视频项目—脚本 Agent 协同引入实施方案
> 目标:在不推翻现有视频项目、脚本版本、AITask、计费和人工采用流程的前提下,把当前“一次模型生成脚本”升级为可暂停、可恢复、可审计、可校验、可有限修订的脚本 Agent。
> 架构原则:松耦合、高内聚、可复用、精简化、可扩展。
> 代码基线审阅时间:2026-07-17。
## 1. 结论先行
脚本 Agent 不应等同于“把现有提示词再加长”,也不应一次引入多个可自由互相调用的 Agent。推荐方案是:
```text
一个脚本领域协调器
+ 一组职责单一的协作节点
+ 一组受控业务工具
+ 现有模型、任务、计费和脚本版本能力
+ 确定性校验优先
+ 最多一次语义评审、一次定向修订
+ 用户最终采用
```
协作节点包括:上下文收集、Brief 规划、脚本生成、规则校验、语义评审、定向修订、交接包构建。只有“生成、语义评审、语义修订”可能调用模型;数据读取、字段校验、时长镜数、卖点覆盖、禁用词和落库都由确定性代码完成。
这套设计能让脚本功能真正具备 Agent 的核心特征:读取状态、形成计划、调用受控工具、观察校验结果、在预算内决定是否修订、保存过程和等待用户确认。同时避免无限循环、模型乱选工具、重复扣费和错误自动采用。
## 2. 当前代码基线与改造边界
### 2.1 当前链路
```text
pipeline.tsx 组装 prompt/mode/model
→ POST /api/projects/{id}/script-agent-stream/
→ projects/views.py::script_agent_stream
→ ai/script_agent.py::stream_script_agent
→ 固定 system + user messages
→ Provider 单次流式文本调用
→ normalize_draft
→ ScriptVersion + ScriptSegment
→ SSE 返回草稿
→ 用户调用 adopt-script
```
当前名称包含 `script_agent`,但核心仍是单次模型调用;没有独立运行状态、工具循环、校验决策、运行预算和恢复机制。
### 2.2 必须直接复用
| 能力 | 当前代码 | 新 Agent 用法 |
| --- | --- | --- |
| 商品、项目与阶段 | `apps/products``apps/projects` | 通过只读工具访问,不让 Agent 直接 ORM |
| 脚本模型调用 | `core/backend/apps/ai/script_agent.py` | 拆出纯生成服务,保留旧入口作回退 |
| 电商脚本 Skill | `script_agent.py` 当前 Skill 加载 | 作为可版本化领域提示模板 |
| 结构归一化 | `normalize_draft()` | 继续作为兼容层,不承担全部业务校验 |
| 脚本产物 | `ScriptVersion``ScriptSegment` | Agent 草稿仍落现有领域表 |
| 单次 AI 任务 | `AITask` | 每次生成/评审/修订各一条,不表示整个 Agent 运行 |
| 模型配置 | `ModelConfig`、Provider | 由模型路由器或用户明确选择 |
| 积分 | reserve/charge/release | 每个付费步骤继续走现有闭环 |
| 人工采用 | `adopt-script` | 首期保持,Agent 不自动推进阶段 |
| 前端流式展示 | `pipeline.tsx`、SSE | 改成 Agent 事件的展示层,不作为真实状态源 |
### 2.3 本次不做
- 不让脚本 Agent 自动生成图片、故事板或视频;
- 不自动采用脚本;
- 不让模型直接访问数据库或任意 HTTP;
- 不保存或展示模型完整思维过程;
- 不重写 Provider、计费、脚本版本和项目阶段;
- 不做多个自由对话 Agent 的互调网络;
- 不允许无限评审、无限修订或静默换模型。
## 3. 五项架构原则如何落到代码
| 原则 | 落地方式 | 禁止做法 |
| --- | --- | --- |
| 松耦合 | Agent 只依赖工具协议和领域契约;Provider、ORM、计费藏在工具实现后 | 协调器直接查表、直接请求火山接口 |
| 高内聚 | 脚本规划、脚本校验、脚本交接全部放在 script 领域目录 | 把脚本规则继续堆进通用 `services.py` |
| 可复用 | Run/Step、预算、权限、事件、模型路由、工具注册为公共基础设施 | 为脚本单独复制任务、计费、SSE 框架 |
| 精简化 | 固定状态机;首期 1 次生成、可选 1 次评审、最多 1 次修订 | 首期引入通用图式编排器或自由循环 |
| 可扩展 | 契约带 `schema_version`,工具带版本,策略由 policy 配置 | 依赖自然语言隐式约定字段 |
## 4. 推荐代码结构
建议新增独立 Django app `core/backend/apps/agents/`,公共运行能力与 AI Provider 分离:
```text
core/backend/apps/agents/
├─ apps.py
├─ models.py # AgentRun / AgentStep / AgentArtifact
├─ enums.py # agent_type、状态、step 类型
├─ registry.py # Agent 与工具注册表
├─ runtime.py # 状态机驱动、恢复、取消、步骤上限
├─ policies.py # 预算、重试、审批策略
├─ permissions.py # 工具权限和团队边界
├─ events.py # 运行事件投影,不保存模型思维过程
├─ routing.py # 能力需求 → ModelConfig
├─ schemas/
│ ├─ common.py
│ └─ script.py # ScriptAgentRequest/Brief/Report/Handoff
├─ tools/
│ ├─ base.py # ToolSpec、JSON Schema、执行结果
│ ├─ project.py # 项目只读工具
│ ├─ product.py # 商品上下文工具
│ ├─ models.py # 模型能力与报价工具
│ └─ script.py # 生成、保存、采用前检查
├─ script/
│ ├─ coordinator.py # 脚本 Agent 状态机
│ ├─ context.py # 输入快照和缺失项
│ ├─ brief.py # 确定性 Brief 构建
│ ├─ generator.py # 调用现有 script_agent 纯生成能力
│ ├─ validators.py # 确定性规则校验
│ ├─ reviewer.py # 可选语义评审
│ ├─ reviser.py # 定向修订,最多一次
│ ├─ handoff.py # 下游结构化交接包
│ └─ prompt_versions.py # 提示模板版本和兼容策略
├─ tasks.py # Celery 恢复/继续 AgentRun
├─ serializers.py
├─ views.py
├─ urls.py
└─ tests/
├─ test_runtime.py
├─ test_script_contracts.py
├─ test_script_agent.py
└─ test_script_tools.py
```
前端建议:
```text
core/frontend/src/
├─ api.ts # AgentRun API
├─ types.ts # 运行与契约类型
├─ routes/pipeline.tsx # 保留业务页面,替换提交适配器
└─ components/agent-run/
├─ run-progress.tsx # 计划和步骤状态
├─ validation-report.tsx # 错误/警告/通过项
├─ approval-card.tsx # 报价、采用、继续修订
└─ input-question-card.tsx # 澄清问题
```
脚本业务规则不放进 `components/agent-run`;公共组件只渲染通用状态。
## 5. 公共 Agent 运行数据
### 5.1 AgentRun
一个 `AgentRun` 表示一次完整脚本协作,不等于一次模型调用。
```text
id
team_id
created_by_id
agent_type script
scope_type project
scope_id project_id
goal 用户目标摘要
status created/collecting/waiting_user/planning/
waiting_approval/running/waiting_task/
validating/needs_review/succeeded/failed/
cancelled/budget_exhausted/stale
schema_version script-agent-request/v1
input_snapshot 冻结后的输入
policy_snapshot 本次预算和重试规则
plan 简短结构化计划
current_step
estimated_cost
actual_cost
stop_reason_code
stop_reason_message
lock_version 乐观锁,防并发继续
started_at/completed_at
```
### 5.2 AgentStep
```text
id
run_id
sequence
step_type collect/plan/tool/model/validate/review/
revise/persist/approval/handoff
name
tool_name/tool_version
input_summary 脱敏、可审计输入
output_summary 结构化摘要
status
idempotency_key 同一运行内唯一
ai_task_id 模型步骤关联现有 AITask
estimated_cost/actual_cost
attempt
error_code/error_message
started_at/completed_at
```
### 5.3 AgentArtifact
Agent 不复制完整脚本,只引用现有产物:
```text
run_id
step_id
artifact_type script_version / script_handoff /
validation_report / brief
object_type
object_id
version
summary
metadata
```
`ScriptVersion` 仍是脚本真相源;AgentArtifact 只是说明“哪个运行生成或检查了哪个版本”。
## 6. 输入契约
### 6.1 前端请求 `ScriptAgentRequest/v1`
```json
{
"schema_version": "script-agent-request/v1",
"project_id": "uuid",
"mode": "auto | theme | manual | revise | revise_segment",
"instruction": "用户补充主题或修改意见",
"source_script_version_id": null,
"target_segment_id": null,
"selected_selling_point_ids": ["uuid"],
"preferences": {
"style": "真实测评",
"character": "都市白领女性",
"duration_seconds": 30,
"aspect_ratio": "9:16"
},
"model_policy": {
"mode": "explicit | auto",
"model_config_id": "可选",
"quality": "standard",
"cost_ceiling_points": 30
},
"idempotency_key": "前端生成的 UUID"
}
```
关键修正:卖点必须传真实 ID,不再把标题装进 `selling_point_ids`;后端读取 ID 后保存卖点标题和内容快照,保证后续商品修改不改变本次运行事实。
### 6.2 冻结输入 `ScriptContextSnapshot/v1`
```json
{
"project": {
"id": "...",
"updated_at": "...",
"current_stage": "script",
"product_id": "..."
},
"product": {
"id": "...",
"updated_at": "...",
"title": "...",
"brand": "...",
"category": "...",
"description": "...",
"target_audience": "...",
"specs": {},
"selected_selling_points": [
{"id": "...", "title": "...", "content": "..."}
]
},
"creative": {
"mode": "theme",
"instruction": "早八通勤场景",
"style": "真实测评",
"character": "都市白领女性",
"duration_seconds": 30,
"aspect_ratio": "9:16",
"shot_policy": {"shot_count": 2, "shot_duration_seconds": 15}
},
"source_script": null
}
```
运行期间只使用 snapshot;保存前再比较 project/product `updated_at`。发生关键变更则运行转 `stale`,禁止直接采用旧结果。
## 7. 协作角色与职责边界
| 协作节点 | 类型 | 输入 | 输出 | 是否调用模型 |
| --- | --- | --- | --- | --- |
| ScriptCoordinator | 状态机 | AgentRun | 下一合法步骤 | 否 |
| ContextCollector | 工具组合 | project_id、request | ContextSnapshot、缺失项 | 否 |
| BriefBuilder | 领域规则 | ContextSnapshot | ScriptBrief | 首期否 |
| ScriptGenerator | 生成器 | Brief、输出契约 | ScriptDraft | 是,最多 1 次 |
| ContractNormalizer | 兼容器 | 模型原始文本 | 规范化草稿 | 否 |
| ScriptValidator | 规则引擎 | Draft、Snapshot | ValidationReport | 否 |
| SemanticReviewer | 独立评审 | Draft、rubric | ReviewReport | 可选,最多 1 次 |
| ScriptReviser | 修订器 | Draft、可修复问题 | 新 Draft | 是,最多 1 次 |
| DraftPersister | 领域服务 | Draft、reports | ScriptVersion | 否 |
| HandoffBuilder | 领域服务 | ScriptVersion、reports | ScriptHandoff | 否 |
这里的“协同”通过结构化产物完成,不传递长篇聊天历史,也不让节点自由决定调用任意下一节点。
## 8. Agent 状态机
```mermaid
stateDiagram-v2
[*] --> Collecting
Collecting --> WaitingUser: 必填事实缺失或口径冲突
WaitingUser --> Collecting: 用户补充
Collecting --> Planning: 上下文完整
Planning --> WaitingApproval: 超过自动预算或用户要求确认
Planning --> Generating: 预算内
WaitingApproval --> Generating: 用户批准
Generating --> WaitingTask: AITask 在执行
WaitingTask --> Validating: 生成完成
Validating --> Persisting: 无错误且无需语义评审
Validating --> Reviewing: 仅有语义风险
Validating --> Revising: 存在可自动修复问题且未修订
Reviewing --> Persisting: 通过或只有警告
Reviewing --> Revising: 可修复且未修订
Revising --> WaitingTask: 修订任务已提交
Validating --> NeedsReview: 不可修复或已达上限
Reviewing --> NeedsReview: 高风险或已达上限
Persisting --> HumanReview
NeedsReview --> HumanReview
HumanReview --> Succeeded: 用户采用
HumanReview --> Planning: 用户给出新修改意见
HumanReview --> Cancelled: 用户放弃
Succeeded --> [*]
```
每次恢复只根据数据库状态和最后成功步骤继续;SSE 断开不会取消后端运行。用户主动取消时,尚未提交的步骤停止;已提交 AITask 按现有任务能力取消或等待完成,但不得重复提交。
## 9. 工具接口设计
### 9.1 工具统一协议
```python
class AgentTool:
name: str
version: str
permission: str
input_schema: dict
output_schema: dict
def execute(self, context, arguments) -> ToolResult:
...
```
统一 `ToolResult`
```json
{
"ok": true,
"data": {},
"warnings": [],
"error": null,
"audit": {"source_versions": {}, "duration_ms": 12}
}
```
### 9.2 脚本 Agent 工具
| 工具 | 权限 | 复用代码 | 说明 |
| --- | --- | --- | --- |
| `get_project_script_context.v1` | 只读 | Project、metadata、stage | 返回项目配置和真实状态 |
| `get_product_context.v1` | 只读 | Product、SellingPoint | 返回事实和版本快照 |
| `get_source_script.v1` | 只读 | ScriptVersion/Segment | revise 时读取源版本 |
| `quote_text_generation.v1` | 只读 | 现有 pricing | 生成/评审/修订前报价 |
| `generate_script_draft.v1` | 付费 | `stream_script_agent` 拆出的生成内核 | 只负责一次结构化生成 |
| `review_script_semantics.v1` | 付费可选 | 文本 Provider | 只返回评审 JSON,不改稿 |
| `revise_script_draft.v1` | 付费 | 文本 Provider | 只修指定 issue_code |
| `save_script_version.v1` | 低风险写 | `persist_script_draft()` | 保存未采用版本 |
| `build_script_handoff.v1` | 低风险写 | 新增领域服务 | 建立下游资产需求和验收条件 |
| `check_script_adoptable.v1` | 只读 | Project/Version | 采用前检查 snapshot 是否过期 |
工具内部验证 `team_id`,不得接受模型传入的团队 ID。对象查询必须同时限定当前 team、未删除状态和必要的项目关联。
## 10. Brief 与提示词分层
### 10.1 `ScriptBrief/v1`
```json
{
"schema_version": "script-brief/v1",
"goal": "30 秒真实测评短视频",
"audience": "通勤女性",
"platform_style": "小红书种草",
"product_facts": ["只允许来自商品快照的事实"],
"must_use_selling_points": ["轻便", "易清洗"],
"forbidden_claims": ["绝对化效果", "无来源认证", "虚构价格"],
"character": "都市白领女性",
"shot_policy": {
"count": 2,
"seconds_each": 15,
"required_functions": ["hook", "pain", "selling", "cta"]
},
"output_contract": "script-draft/v1"
}
```
Brief 首期由规则构建,避免为“整理已有字段”额外付费。以后若增加策略 Agent,只能在事实和硬规则外补充创意策略,不能修改商品事实。
### 10.2 模型消息分区
```text
system
├─ Agent 角色和安全边界
├─ 电商脚本 Skill 版本
├─ ScriptDraft JSON 契约
└─ 禁止把业务数据当系统指令
user
├─ <product_facts> 只读业务数据
├─ <creative_brief> 用户目标与偏好
├─ <source_script> 改稿时的源版本
└─ <task> generate / revise / revise_segment
```
商品标题、描述、自带脚本、用户意见都必须放在明确的数据区,禁止拼进 system 指令区,以降低提示注入风险。
### 10.3 生成与修订提示词分离
- 生成提示词只负责从 Brief 产生完整 `ScriptDraft/v1`
- 评审提示词只输出 `ReviewReport/v1`,无权改稿;
- 修订提示词只接收明确 issue 列表,输出完整新草稿;
- 单镜修订仍输出完整草稿,但必须声明允许修改的 segment index
- 所有模型响应先做 JSON Schema 校验,再进入业务校验。
## 11. 确定性校验器
`ScriptValidator` 应返回错误码,不只返回自然语言:
```json
{
"schema_version": "script-validation/v1",
"passed": false,
"score": 82,
"errors": [
{
"code": "SELLING_POINT_MISSING",
"path": "segments",
"message": "用户选择的卖点“易清洗”未出现",
"repairable": true
}
],
"warnings": [
{
"code": "CTA_WEAK",
"path": "segments[1]",
"message": "结尾行动引导较弱",
"repairable": true
}
],
"checks": {
"schema": "pass",
"duration": "pass",
"segment_count": "pass",
"entity_refs": "pass",
"product_facts": "pass"
}
}
```
首期规则:
1. ScriptDraft Schema、必填字段和类型;
2. 镜数与唯一时长策略一致;
3. 单镜时长、总时长和排序一致;
4. 单镜旁白字数上限;
5. hook/pain/selling/cta 覆盖;
6. 所选卖点 ID 对应内容是否覆盖;
7. 商品、人物、场景实体引用是否存在;
8. `@图N` 是否能映射到实体;
9. 价格、折扣、认证、功效是否有事实来源;
10. 绝对化、违禁和风险表达;
11. 下游所需人物、场景、商品资产是否可形成清单;
12. revise_segment 是否误改其他镜头。
只有表达自然度、镜头连贯性、钩子吸引力、转化节奏等难以确定性判断的内容进入语义评审。
## 12. 语义评审与定向修订
### 12.1 何时评审
- 规则全部通过但策略配置要求高质量评审;
- 存在 `semantic_review_required` 类型警告;
- 用户选择 production 质量档;
- 不对所有普通运行强制增加一次模型费用。
### 12.2 `ScriptReviewReport/v1`
```json
{
"passed": true,
"dimensions": {
"hook": 4,
"continuity": 4,
"clarity": 5,
"conversion": 4,
"fact_safety": 5
},
"issues": [
{
"code": "HOOK_TOO_GENERIC",
"segment_index": 0,
"severity": "warning",
"repair_instruction": "保留商品事实,只改写前两句为通勤冲突"
}
]
}
```
评审器不能直接采用脚本,也不能自行调用修订。Coordinator 根据 policy、预算、问题是否可修复和剩余次数决定下一步。
### 12.3 修订边界
- 最多 1 次自动修订;
- 只传结构化 issue 和原草稿,不传冗长聊天记录;
- 修订后必须重新跑全部确定性规则;
- 不再递归进行第二次自动修订;
- 仍未通过则保存带报告的候选或进入 `needs_review`,交给用户。
## 13. 模型路由
Agent 声明能力,不直接写供应商名称:
```json
{
"capability": "text",
"requires": {
"structured_json": true,
"streaming": true,
"context_tokens_min": 16000
},
"preferences": {
"quality": "standard",
"cost_ceiling_points": 30
}
}
```
首期兼容策略:
- 用户明确选择豆包/Gemini:尊重选择,校验模型可用性;
- 用户选择“自动”:路由器按 capability、健康度、成本和历史契约通过率排序;
- 生成失败不自动跨模型重复扣费,除非错误明确属于可安全回退的 provider 暂时故障且 policy 允许;
- 连续结构失败最多改用一次严格 JSON 提示,不无限切换;
- 路由结果写入 AgentStep 和 AITask,页面展示实际模型。
## 14. 产物与下游交接
### 14.1 ScriptVersion
通过或带可接受警告的草稿使用现有 `persist_script_draft()` 保存:
- `ScriptVersion.is_adopted = false`
- `ScriptSegment` 保存逐镜字段;
- metadata 保存 hook、tone、entities
- 增加 `agent_run_id`、contract_version、validation_summary、source_snapshot_hash
- 不自动改变项目阶段。
### 14.2 `ScriptHandoff/v1`
```json
{
"schema_version": "script-handoff/v1",
"project_id": "...",
"script_version_id": "...",
"goal": "30 秒真实测评",
"product_fact_snapshot_hash": "...",
"segments": [
{
"index": 0,
"purpose": "hook+pain",
"duration_seconds": 15,
"entities": ["product_1", "person_1", "scene_1"],
"required_assets": [
{"entity_id": "product_1", "kind": "product", "view": "front"},
{"entity_id": "person_1", "kind": "person", "view": "portrait"}
],
"acceptance": ["商品前 3 秒内露出", "人物形象跨镜一致"]
}
],
"validation_report_id": "...",
"open_questions": [],
"user_approved": false
}
```
未来视觉资产 Agent、故事板 Agent 只读取这个交接包和已采用 ScriptVersion,不读取脚本 Agent 的聊天记录。
## 15. API 设计
建议新增:
```http
POST /api/projects/{project_id}/script-agent-runs/
GET /api/agent-runs/{run_id}/
GET /api/agent-runs/{run_id}/steps/
GET /api/agent-runs/{run_id}/events/?after={sequence}
POST /api/agent-runs/{run_id}/actions/
```
`actions`
```json
{"action": "provide_input", "payload": {...}}
{"action": "approve_budget"}
{"action": "request_revision", "instruction": "..."}
{"action": "adopt_artifact", "artifact_id": "..."}
{"action": "cancel"}
```
SSE 可保留为:
```http
GET /api/agent-runs/{run_id}/events/stream/?after={sequence}
```
但 SSE 只投影数据库状态;断线重连使用 `after` 续传。首期若不增加持久事件表,可用 AgentStep + Run 状态轮询实现,先保证恢复正确,再优化实时动画。
现有 `script-agent-stream` 保留为 feature flag 下的 legacy fallback,灰度稳定后再逐步下线。
## 16. 前端交互
保留当前脚本页面,不把整个页面改成聊天框。新增四类可验证卡片:
1. **输入摘要**:商品、卖点、时长、风格、人物、主题;
2. **执行计划**:收集 → 生成 → 校验 → 可选修订 → 保存;
3. **校验报告**:错误、警告、通过项、实际模型和费用;
4. **候选脚本**:版本差异、请求修改、采用。
当前页面“思考、自检完成”等文字必须改成真实状态:只有对应 AgentStep 成功才显示完成;不能再用前端硬编码步骤制造已校验的假象。
## 17. 幂等、并发、恢复和取消
- 创建运行使用 `(team_id, idempotency_key)` 唯一约束;
- 每个步骤使用 `(run_id, step_name, attempt)` 唯一幂等键;
- Coordinator 更新使用 `select_for_update` 或 lock_version
- 同一项目同一 agent_type 默认只允许一个活动运行;
- 付费步骤先创建 AgentStep,再创建/关联 AITask
- `waiting_task` 恢复时查询原 AITask,不新建任务;
- Worker 崩溃后由恢复任务扫描活动 Run;
- 用户取消只阻止后续步骤,已完成产物仍保留审计;
- 用户修改商品/项目后,旧运行输入 hash 不一致则标记 stale
- adopt 前再次执行 `check_script_adoptable`
## 18. 预算和权限
默认 policy
```json
{
"max_steps": 8,
"max_generation_calls": 1,
"max_review_calls": 1,
"max_revision_calls": 1,
"max_total_points": 60,
"auto_spend_points": 30,
"allow_model_fallback": false,
"require_human_adoption": true
}
```
权限分级:
- 自动允许:读项目/商品、构建 Brief、规则校验、保存检查报告;
- 预算内允许:生成、可选评审、一次修订;
- 必须确认:超自动预算、采用脚本、改变项目阶段;
- 禁止:外部发布、删除用户版本、绕过团队权限。
## 19. 错误分类与降级
| 错误 | 处理 |
| --- | --- |
| `CONTEXT_MISSING` | waiting_user,列出缺失字段 |
| `INPUT_STALE` | 标记 stale,要求基于新数据重开/刷新 |
| `MODEL_UNAVAILABLE` | 若用户明确模型则停止;自动模式可重新报价候选 |
| `CONTRACT_INVALID` | 使用 normalize 兼容一次;仍失败则停止 |
| `VALIDATION_FAILED` | 可修复且有预算则修订一次,否则 needs_review |
| `BUDGET_EXCEEDED` | waiting_approval/budget_exhausted |
| `CLIENT_DISCONNECTED` | 后端继续,前端可恢复 |
| `PROVIDER_ERROR` | AITask 现有退款;Run 记录错误,不重复扣费 |
旧生成入口始终可作为人工选择的回退,不由系统无提示自动切换。
## 20. 测试方案
### 20.1 单元测试
- Request/Snapshot/Brief/Draft/Handoff Schema
- 卖点 ID 与快照;
- 时长、镜数、字数、实体、CTA、风险词校验;
- revise_segment 不得修改其他镜;
- 工具 team 权限;
- 路由和预算策略;
- 状态机所有合法/非法迁移;
- 幂等键和重复 Celery 投递。
### 20.2 集成测试
- auto/theme/manual/revise/revise_segment 五种模式;
- 生成 → 校验通过 → 保存未采用版本;
- 生成 → 校验失败 → 修订一次 → 通过;
- 修订后仍失败 → needs_review
- SSE 断开后恢复;
- provider 失败退款;
- 项目中途修改导致 stale
- 用户采用后现有 `adopt-script` 同步镜头数量;
- legacy 与 Agent 灰度并存。
### 20.3 验收指标
- ScriptDraft 一次契约通过率;
- 商品事实错误率;
- 所选卖点覆盖率;
- 规则一次通过率;
- 自动修订成功率;
- 用户直接采用率;
- 采用前修改次数;
- 单次运行平均调用数、积分、耗时;
- 下游缺失实体/资产比例;
- 用户拒绝原因分布。
## 21. 分阶段实施
### 阶段 A:公共最小运行时
- AgentRun、AgentStep、AgentArtifact
- 固定状态机、幂等、恢复、取消;
- 工具注册、Schema、权限;
- 预算策略和 AITask 关联;
- 查询 API 和最小前端状态展示。
### 阶段 B:拆出现有脚本生成内核
-`stream_script_agent()` 中上下文、提示词、模型调用、归一化、持久化拆成可独立测试服务;
- 旧 API 继续调用这些服务;
- 不改变现有业务结果。
### 阶段 C:脚本 Agent MVP
- ContextSnapshot、Brief
- 生成一次;
- 确定性校验;
- 保存候选和 Handoff
- 人工采用;
- 不接语义评审和自动修订。
### 阶段 D:有限协同
- 可选语义评审;
- 最多一次定向修订;
- 报价和预算确认;
- 输入过期检查;
- 真实步骤 UI。
### 阶段 E:灰度与优化
- 团队 feature flag
- 对照旧链路采用率、费用和失败率;
- 根据 issue 数据优化规则,不靠盲目加提示词;
- 稳定后供项目导演 Agent 通过 Handoff 调用。
## 22. 一人串行开发工作量参考
以下为现有代码可复用、使用编码工具辅助、需求口径已确认后的研发量,不包含大规模 UI 重做和生产数据迁移异常处理:
| 工作 | 参考工期 |
| --- | ---: |
| 公共最小 AgentRun/Step/Artifact、状态机、工具协议 | 34 天 |
| 拆分现有脚本生成服务并保持旧接口兼容 | 1.5–2 天 |
| Snapshot、Brief、校验器、Handoff | 23 天 |
| Agent API、Celery 恢复、预算与幂等 | 2–3 天 |
| 前端真实步骤、报告、确认与恢复 | 2–3 天 |
| 语义评审和一次修订 | 1.5–2 天 |
| 单元/集成测试、灰度开关和修正 | 2–3 天 |
合计约 **1420 人天**。如果公共 Agent 基础设施已由平台套图或其他 Agent 建好,脚本领域自身约 **812 人天**。MVP 先不做语义评审与自动修订,可压缩到约 **913 人天(含公共最小运行时)**
## 23. 最终落地形态
```text
用户配置脚本目标
→ Script Agent 冻结项目和商品事实
→ 规则构建 Brief
→ 报价和模型路由
→ 生成完整 ScriptDraft
→ 确定性校验
→ 可选独立语义评审
→ 最多一次定向修订并重新校验
→ 保存未采用 ScriptVersion
→ 生成 ScriptHandoff
→ 用户确认采用
→ 下游视觉/故事板读取结构化交接包
```
这不是把现有“脚本助手”换一个名称,而是补齐运行状态、工具边界、观察校验、有限决策、预算、恢复和交接能力。实现后,脚本节点才具备受控 Agent 的实质,同时仍保持现有 AirShelf 项目流水线的稳定边界。