Files
yingqing/docs/agents_todo/视频项目脚本Agent_协同引入实施方案.md

793 lines
28 KiB
Markdown
Raw Permalink 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.
# 视频项目—脚本 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 先不做语义评审与自动修订,可压缩到约 **9–13 人天(含公共最小运行时)**
## 23. 最终落地形态
```text
用户配置脚本目标
→ Script Agent 冻结项目和商品事实
→ 规则构建 Brief
→ 报价和模型路由
→ 生成完整 ScriptDraft
→ 确定性校验
→ 可选独立语义评审
→ 最多一次定向修订并重新校验
→ 保存未采用 ScriptVersion
→ 生成 ScriptHandoff
→ 用户确认采用
→ 下游视觉/故事板读取结构化交接包
```
这不是把现有“脚本助手”换一个名称,而是补齐运行状态、工具边界、观察校验、有限决策、预算、恢复和交接能力。实现后,脚本节点才具备受控 Agent 的实质,同时仍保持现有 AirShelf 项目流水线的稳定边界。