Skip to content

AI Agent Harness — 项目设计 ​

设计目标 ​

构建一个面向智能视频剪辑场景的 AI Agent 运行时框架,重点解决三个核心问题:

  1. Agent 可靠性:如何让 Agent 稳定完成多步骤任务而不陷入死循环或偏离目标
  2. 工具编排能力:如何安全、高效地调度和执行多种异构工具
  3. 生产级工程质量:可观测、可审计、可限制、可降级

系统架构 ​

┌────────────────────────────── Agent Harness ──────────────────────────────┐
│                                                                           │
│  ┌─────────────────────────── Control Layer ───────────────────────────┐  │
│  │                                                                     │  │
│  │   User Input ──▶ Input Guardrail ──▶ Router ──▶ Agent Loop         │  │
│  │                                        │           │                │  │
│  │                                        ▼           ▼                │  │
│  │                                   ┌─────────┐  ┌────────┐          │  │
│  │                                   │ Planner │  │ ReAct  │          │  │
│  │                                   │  Agent  │  │ Agent  │          │  │
│  │                                   └────┬────┘  └───┬────┘          │  │
│  │                                        │           │                │  │
│  │                                        ▼           ▼                │  │
│  │                              ┌─────────────────────────┐            │  │
│  │                              │    Tool Executor        │            │  │
│  │                              │  (sandbox + timeout)    │            │  │
│  │                              └────────────┬────────────┘            │  │
│  │                                           │                         │  │
│  │                              ┌────────────┼────────────┐            │  │
│  │                              ▼            ▼            ▼            │  │
│  │                         ┌────────┐  ┌─────────┐  ┌────────┐       │  │
│  │                         │ Video  │  │  RAG    │  │ Util   │       │  │
│  │                         │ Tools  │  │  Tool   │  │ Tools  │       │  │
│  │                         └────────┘  └─────────┘  └────────┘       │  │
│  │                                                                     │  │
│  └─────────────────────────────────────────────────────────────────────┘  │
│                                                                           │
│  ┌─────────────────────────── State Layer ─────────────────────────────┐  │
│  │                                                                     │  │
│  │   ┌──────────────┐   ┌───────────────┐   ┌──────────────────┐     │  │
│  │   │ Conversation │   │  Long-term    │   │  Execution       │     │  │
│  │   │   Memory     │   │   Memory      │   │   History        │     │  │
│  │   │ (sliding)    │   │  (vector DB)  │   │  (audit log)     │     │  │
│  │   └──────────────┘   └───────────────┘   └──────────────────┘     │  │
│  │                                                                     │  │
│  └─────────────────────────────────────────────────────────────────────┘  │
│                                                                           │
│  ┌─────────────────────────── Infra Layer ─────────────────────────────┐  │
│  │                                                                     │  │
│  │   ┌──────────┐   ┌────────────┐   ┌─────────┐   ┌────────────┐   │  │
│  │   │  Tracer  │   │   Metrics  │   │  Logger │   │  Config    │   │  │
│  │   │  (OTEL)  │   │(Prometheus)│   │  (slog) │   │  (YAML)   │   │  │
│  │   └──────────┘   └────────────┘   └─────────┘   └────────────┘   │  │
│  │                                                                     │  │
│  └─────────────────────────────────────────────────────────────────────┘  │
│                                                                           │
└───────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────── 外部接入 ──────────────────────────────────────┐
│                                                                           │
│   HTTP API (gin/chi)  ──  SSE Stream  ──  CLI (`agent run/chat/plan`)    │
│                                                                           │
└───────────────────────────────────────────────────────────────────────────┘

核心接口定义 ​

Agent — 顶层抽象 ​

go
type AgentConfig struct {
    Name        string
    Model       string           // LLM model ID
    SystemPrompt string
    Tools       []Tool
    MaxSteps    int              // ReAct 最大循环次数
    MaxTokens   int              // Token 预算上限
    Timeout     time.Duration    // 全流程超时
    Guardrails  []Guardrail
    Memory      MemoryStore
}

type Agent interface {
    // 单轮执行 — 输入用户消息,返回最终回复
    Run(ctx context.Context, input string) (*AgentResult, error)
    // 流式执行 — 支持中间步骤回调
    RunStream(ctx context.Context, input string, onStep func(Step)) (*AgentResult, error)
    // 多轮对话
    Chat(ctx context.Context, sessionID string, input string) (*AgentResult, error)
}

type AgentResult struct {
    Output     string         // 最终回复文本
    Steps      []Step         // 执行步骤记录
    TokenUsage TokenUsage     // Token 消耗统计
    Duration   time.Duration  // 总耗时
    ToolCalls  int            // 工具调用次数
}

type Step struct {
    Type        StepType      // "thought" | "action" | "observation" | "plan"
    Content     string
    ToolName    string        // action 步骤的工具名
    ToolArgs    json.RawMessage
    ToolResult  string
    Timestamp   time.Time
    Duration    time.Duration
    TokensUsed  int
}

type StepType string

const (
    StepThought     StepType = "thought"
    StepAction      StepType = "action"
    StepObservation  StepType = "observation"
    StepPlan        StepType = "plan"
    StepFinalAnswer StepType = "final_answer"
)

LLM — 大模型通信层 ​

go
type Message struct {
    Role       string          // "system" | "user" | "assistant" | "tool"
    Content    string
    ToolCalls  []ToolCall      // assistant 的工具调用请求
    ToolCallID string          // tool 消息对应的调用 ID
}

type ToolCall struct {
    ID        string
    Name      string
    Arguments json.RawMessage
}

type ChatResponse struct {
    Content    string
    ToolCalls  []ToolCall
    Usage      TokenUsage
    FinishReason string       // "stop" | "tool_calls" | "length"
}

type TokenUsage struct {
    PromptTokens     int
    CompletionTokens int
    TotalTokens      int
}

type LLMClient interface {
    Chat(ctx context.Context, messages []Message, opts ...ChatOption) (*ChatResponse, error)
    ChatStream(ctx context.Context, messages []Message, onChunk func(string), opts ...ChatOption) (*ChatResponse, error)
}

type ChatOption func(*chatOptions)

func WithTools(tools []ToolSchema) ChatOption    { /* ... */ }
func WithTemperature(t float64) ChatOption       { /* ... */ }
func WithMaxTokens(n int) ChatOption             { /* ... */ }
func WithModel(model string) ChatOption          { /* ... */ }

Tool — 工具系统 ​

go
type Tool interface {
    Name() string
    Description() string
    Schema() *ToolParamSchema       // JSON Schema 参数描述
    Execute(ctx context.Context, args json.RawMessage) (*ToolOutput, error)
}

type ToolParamSchema struct {
    Type       string                    `json:"type"`       // "object"
    Properties map[string]ParamProperty  `json:"properties"`
    Required   []string                  `json:"required"`
}

type ParamProperty struct {
    Type        string   `json:"type"`
    Description string   `json:"description"`
    Enum        []string `json:"enum,omitempty"`
}

type ToolOutput struct {
    Content  string            // 工具执行结果(文本)
    Data     any               // 结构化数据(可选)
    Error    string            // 错误信息
    Metadata map[string]string // 追踪元数据
}

// ToolSchema 是传给 LLM 的工具描述格式(OpenAI function calling 格式)
type ToolSchema struct {
    Type     string      `json:"type"`     // "function"
    Function FunctionDef `json:"function"`
}

type FunctionDef struct {
    Name        string          `json:"name"`
    Description string          `json:"description"`
    Parameters  json.RawMessage `json:"parameters"`
}

Tool Registry — 工具注册中心 ​

go
type Registry interface {
    Register(tool Tool) error
    Unregister(name string) error
    Get(name string) (Tool, bool)
    List() []Tool
    Schemas() []ToolSchema           // 供 LLM 使用的 Schema 列表
    Execute(ctx context.Context, name string, args json.RawMessage) (*ToolOutput, error)
}

Tool Executor — 安全执行层 ​

go
type ExecutorConfig struct {
    Timeout        time.Duration          // 单次调用超时
    MaxRetries     int                    // 最大重试次数
    RetryBackoff   time.Duration          // 退避基数
    MaxConcurrency int                    // 最大并行工具调用数
    Sandbox        bool                   // 是否沙箱隔离
}

type Executor interface {
    // 执行单个工具调用
    Execute(ctx context.Context, call ToolCall) (*ToolOutput, error)
    // 并行执行多个工具调用
    ExecuteBatch(ctx context.Context, calls []ToolCall) ([]*ToolOutput, error)
}

Planner — 任务规划器 ​

go
type Plan struct {
    Goal     string
    Steps    []PlanStep
    Created  time.Time
    Status   PlanStatus  // "active" | "completed" | "failed" | "replanning"
}

type PlanStep struct {
    ID          string
    Description string
    Tool        string           // 预期使用的工具
    Status      PlanStepStatus   // "pending" | "running" | "done" | "failed" | "skipped"
    Result      string
    DependsOn   []string         // 依赖的前置步骤 ID
}

type PlanStatus string

const (
    PlanActive     PlanStatus = "active"
    PlanCompleted  PlanStatus = "completed"
    PlanFailed     PlanStatus = "failed"
    PlanReplanning PlanStatus = "replanning"
)

type Planner interface {
    // 生成计划
    CreatePlan(ctx context.Context, goal string, availableTools []ToolSchema) (*Plan, error)
    // 重新规划(当某步骤失败或结果需要调整时)
    Replan(ctx context.Context, plan *Plan, observation string) (*Plan, error)
    // 获取下一个可执行步骤
    NextStep(plan *Plan) (*PlanStep, bool)
}

Memory — 记忆系统 ​

go
type MemoryStore interface {
    // ---- 短期记忆(对话上下文)----
    // 获取会话消息历史
    GetMessages(ctx context.Context, sessionID string, limit int) ([]Message, error)
    // 追加消息
    AddMessage(ctx context.Context, sessionID string, msg Message) error
    // 压缩/总结历史消息
    Compact(ctx context.Context, sessionID string) error
    
    // ---- 长期记忆(跨会话持久化)----
    // 存储记忆条目
    Store(ctx context.Context, entry MemoryEntry) error
    // 语义检索相关记忆
    Recall(ctx context.Context, query string, topK int) ([]MemoryEntry, error)
    // 清除会话
    Clear(ctx context.Context, sessionID string) error
}

type MemoryEntry struct {
    ID        string
    Content   string
    Type      MemoryType           // "fact" | "preference" | "episode"
    Metadata  map[string]string
    CreatedAt time.Time
    Score     float64              // 检索相关度(查询时填充)
}

type MemoryType string

const (
    MemoryFact       MemoryType = "fact"       // 事实知识
    MemoryPreference MemoryType = "preference" // 用户偏好
    MemoryEpisode    MemoryType = "episode"    // 历史操作
)

Guardrails — 安全护栏 ​

go
type Guardrail interface {
    Name() string
    // 检查用户输入
    ValidateInput(ctx context.Context, input string) *GuardrailResult
    // 检查 LLM 输出
    ValidateOutput(ctx context.Context, output *ChatResponse) *GuardrailResult
    // 检查工具调用
    ValidateToolCall(ctx context.Context, call ToolCall) *GuardrailResult
}

type GuardrailResult struct {
    Passed  bool
    Reason  string   // 不通过时的原因
    Action  GuardrailAction
}

type GuardrailAction string

const (
    ActionBlock    GuardrailAction = "block"    // 拦截,不继续执行
    ActionWarn     GuardrailAction = "warn"     // 警告但继续
    ActionRewrite  GuardrailAction = "rewrite"  // 改写后继续
)

// 预置 Guardrail 实现
type BudgetGuardrail struct {
    MaxSteps      int
    MaxTokens     int
    MaxToolCalls  int
}

type ContentGuardrail struct {
    BlockedPatterns []string        // 正则黑名单
    AllowedTools    []string        // 工具白名单
}

type LoopDetector struct {
    MaxRepeats    int               // 相同 tool call 最大重复次数
    WindowSize    int               // 检测窗口大小
}

Router — 意图路由 ​

go
type Route struct {
    Name        string
    Description string
    Agent       Agent              // 路由到的 Agent
    Condition   func(input string) bool
}

type Router interface {
    // 根据用户输入选择合适的 Agent
    Route(ctx context.Context, input string) (Agent, error)
    // 注册路由
    AddRoute(route Route)
}

关键算法设计 ​

1. ReAct 控制循环 ​

go
func (a *ReactAgent) Run(ctx context.Context, input string) (*AgentResult, error) {
    ctx, cancel := context.WithTimeout(ctx, a.config.Timeout)
    defer cancel()
    
    // 初始化追踪
    ctx, span := tracer.Start(ctx, "agent.run")
    defer span.End()
    
    messages := a.buildInitialMessages(input)
    var steps []Step
    budget := &tokenBudget{max: a.config.MaxTokens}
    
    for step := 0; step < a.config.MaxSteps; step++ {
        // ---- Guardrail: 预算检查 ----
        if err := a.checkBudget(budget); err != nil {
            return a.buildResult(steps, budget, err), nil
        }
        
        // ---- Reason: 调用 LLM ----
        resp, err := a.llm.Chat(ctx, messages, WithTools(a.registry.Schemas()))
        if err != nil {
            return nil, fmt.Errorf("step %d llm chat: %w", step, err)
        }
        budget.add(resp.Usage)
        
        // ---- 终止条件: 无 tool call = 最终回答 ----
        if len(resp.ToolCalls) == 0 {
            steps = append(steps, Step{
                Type: StepFinalAnswer, Content: resp.Content,
            })
            return a.buildResult(steps, budget, nil), nil
        }
        
        // ---- Act: 执行工具调用 ----
        messages = append(messages, assistantMsg(resp))
        
        for _, call := range resp.ToolCalls {
            // Guardrail: 工具调用检查
            if err := a.validateToolCall(ctx, call); err != nil {
                messages = append(messages, toolErrorMsg(call.ID, err))
                continue
            }
            
            // 循环检测
            if a.loopDetector.IsLoop(call) {
                return a.buildResult(steps, budget, ErrLoopDetected), nil
            }
            
            // 执行
            output, err := a.executor.Execute(ctx, call)
            observation := formatObservation(output, err)
            
            steps = append(steps, Step{
                Type: StepAction, ToolName: call.Name,
                ToolArgs: call.Arguments, ToolResult: observation,
            })
            
            messages = append(messages, toolMsg(call.ID, observation))
        }
    }
    
    return a.buildResult(steps, budget, ErrMaxStepsExceeded), nil
}

2. Plan-and-Execute 流程 ​

go
func (a *PlanExecuteAgent) Run(ctx context.Context, input string) (*AgentResult, error) {
    // Phase 1: 制定计划
    plan, err := a.planner.CreatePlan(ctx, input, a.registry.Schemas())
    if err != nil {
        return nil, fmt.Errorf("create plan: %w", err)
    }
    
    var steps []Step
    steps = append(steps, Step{Type: StepPlan, Content: formatPlan(plan)})
    
    // Phase 2: 逐步执行
    for {
        planStep, hasNext := a.planner.NextStep(plan)
        if !hasNext {
            break
        }
        
        planStep.Status = "running"
        
        // 用 ReAct Agent 执行单步
        result, err := a.stepExecutor.Run(ctx, planStep.Description)
        if err != nil {
            planStep.Status = "failed"
            planStep.Result = err.Error()
            
            // Phase 3: 重新规划
            plan, err = a.planner.Replan(ctx, plan, 
                fmt.Sprintf("Step '%s' failed: %s", planStep.Description, err))
            if err != nil {
                return nil, fmt.Errorf("replan: %w", err)
            }
            steps = append(steps, Step{Type: StepPlan, Content: formatPlan(plan)})
            continue
        }
        
        planStep.Status = "done"
        planStep.Result = result.Output
        steps = append(steps, result.Steps...)
    }
    
    // Phase 4: 总结
    summary, err := a.summarize(ctx, plan, steps)
    if err != nil {
        return nil, err
    }
    
    return &AgentResult{Output: summary, Steps: steps}, nil
}

3. 并行 Tool 执行 ​

go
func (e *toolExecutor) ExecuteBatch(ctx context.Context, calls []ToolCall) ([]*ToolOutput, error) {
    results := make([]*ToolOutput, len(calls))
    
    g, gctx := errgroup.WithContext(ctx)
    g.SetLimit(e.config.MaxConcurrency) // 并发度限制
    
    for i, call := range calls {
        i, call := i, call
        g.Go(func() error {
            output, err := e.executeWithRetry(gctx, call)
            if err != nil {
                results[i] = &ToolOutput{Error: err.Error()}
                return nil // 不中断其他 tool
            }
            results[i] = output
            return nil
        })
    }
    
    _ = g.Wait()
    return results, nil
}

func (e *toolExecutor) executeWithRetry(ctx context.Context, call ToolCall) (*ToolOutput, error) {
    var lastErr error
    for attempt := 0; attempt <= e.config.MaxRetries; attempt++ {
        if attempt > 0 {
            time.Sleep(e.config.RetryBackoff * time.Duration(1<<(attempt-1)))
        }
        
        callCtx, cancel := context.WithTimeout(ctx, e.config.Timeout)
        output, err := e.registry.Execute(callCtx, call.Name, call.Arguments)
        cancel()
        
        if err == nil {
            return output, nil
        }
        lastErr = err
    }
    return nil, fmt.Errorf("after %d retries: %w", e.config.MaxRetries, lastErr)
}

4. 循环检测算法 ​

go
type LoopDetector struct {
    window    []callSignature
    maxSize   int
    threshold int // 相同签名出现次数阈值
}

type callSignature struct {
    Name string
    Args string // args 的哈希
}

func (d *LoopDetector) IsLoop(call ToolCall) bool {
    sig := callSignature{
        Name: call.Name,
        Args: hashArgs(call.Arguments),
    }
    
    d.window = append(d.window, sig)
    if len(d.window) > d.maxSize {
        d.window = d.window[1:]
    }
    
    count := 0
    for _, s := range d.window {
        if s == sig {
            count++
        }
    }
    
    return count >= d.threshold
}

视频剪辑 Agent 场景设计 ​

用户交互流程 ​

用户: "帮我把这段5分钟的vlog剪成一个30秒的精华版,加上字幕和轻快的背景音乐"
    │
    ▼ [意图路由]
路由到 PlanExecuteAgent(多步骤复杂任务)
    │
    ▼ [Plan 阶段]
Plan:
  1. 分析视频内容,识别精彩片段 (analyze_video)
  2. 选择最佳片段组合,凑够30秒 (select_segments)
  3. 拼接选中片段并添加转场 (concat_videos)
  4. 生成字幕 (generate_subtitles)
  5. 推荐并添加背景音乐 (recommend_bgm → add_audio)
  6. 导出最终视频 (export_video)
    │
    ▼ [Execute 阶段 — 逐步执行]
Step 1: analyze_video("vlog.mp4", type="highlight")
  → 识别到 8 个精彩片段,含情绪标注

Step 2: select_segments(segments=[...], target=30s, priority="energy")
  → 选择 4 个高能片段,总时长 31.2s

Step 3: concat_videos(segments=[...], transition="crossfade")
  → 拼接完成,生成 highlight_draft.mp4

Step 4: generate_subtitles("highlight_draft.mp4", lang="zh")
  → 生成字幕文件 highlight_draft.srt

Step 5: recommend_bgm(mood="upbeat", duration=31)
  → 推荐 3 首 BGM,自动选择最匹配的

Step 6: export_video(project=..., format="mp4", quality="1080p")
  → 导出完成: output/vlog_highlight_30s.mp4
    │
    ▼ [回复用户]
"已完成!我把vlog剪成了30秒精华版:
 - 选择了4个高能片段(骑行画面、日落、美食、笑脸)
 - 添加了淡入淡出转场
 - 自动生成了中文字幕
 - 配了一首轻快的BGM
 输出文件: output/vlog_highlight_30s.mp4"

工具实现示例 ​

go
type AnalyzeVideoTool struct{}

func (t *AnalyzeVideoTool) Name() string        { return "analyze_video" }
func (t *AnalyzeVideoTool) Description() string {
    return "分析视频内容,识别场景、人物、情绪和精彩片段"
}

func (t *AnalyzeVideoTool) Schema() *ToolParamSchema {
    return &ToolParamSchema{
        Type: "object",
        Properties: map[string]ParamProperty{
            "video_path": {Type: "string", Description: "视频文件路径"},
            "analysis_type": {
                Type:        "string",
                Description: "分析类型",
                Enum:        []string{"highlight", "scene", "face", "emotion"},
            },
        },
        Required: []string{"video_path", "analysis_type"},
    }
}

func (t *AnalyzeVideoTool) Execute(ctx context.Context, args json.RawMessage) (*ToolOutput, error) {
    var params struct {
        VideoPath    string `json:"video_path"`
        AnalysisType string `json:"analysis_type"`
    }
    if err := json.Unmarshal(args, &params); err != nil {
        return nil, fmt.Errorf("parse args: %w", err)
    }
    
    // 实际场景中这里调用视频分析服务/模型
    // MVP 阶段使用模拟数据
    result := analyzeVideoSimulated(params.VideoPath, params.AnalysisType)
    
    return &ToolOutput{
        Content: result.Summary,
        Data:    result,
    }, nil
}

可观测性设计 ​

Trace 追踪 ​

每次 Agent 执行产生一条完整 Trace,包含:

Trace: agent.run (总耗时 12.3s)
├── Span: agent.plan (1.2s)
│   └── Span: llm.chat (1.1s) [model=gpt-4, tokens=850]
├── Span: agent.execute_step.1 (3.5s)
│   ├── Span: llm.chat (1.0s) [tokens=420]
│   └── Span: tool.analyze_video (2.4s) [status=ok]
├── Span: agent.execute_step.2 (2.1s)
│   ├── Span: llm.chat (0.9s) [tokens=380]
│   └── Span: tool.select_segments (1.1s) [status=ok]
├── Span: agent.execute_step.3 (4.2s)
│   ├── Span: llm.chat (0.8s) [tokens=350]
│   └── Span: tool.concat_videos (3.3s) [status=ok]
└── Span: agent.summarize (1.3s)
    └── Span: llm.chat (1.2s) [tokens=290]

Metrics 指标 ​

指标类型说明
agent_runs_totalCounterAgent 执行次数(成功/失败)
agent_steps_totalCounter总步骤数
agent_duration_secondsHistogram执行耗时分布
agent_tokens_usedCounterToken 消耗量
tool_calls_totalCounter工具调用次数(按 tool name)
tool_duration_secondsHistogram工具执行耗时
tool_errors_totalCounter工具调用错误次数
guardrail_blocks_totalCounter护栏拦截次数
loop_detections_totalCounter循环检测触发次数

HTTP API 设计 ​

接口列表 ​

POST /api/v1/agent/run          — 同步执行(短任务)
POST /api/v1/agent/run/stream   — SSE 流式执行(长任务)
POST /api/v1/agent/chat         — 多轮对话
GET  /api/v1/agent/sessions/:id — 获取会话历史
DELETE /api/v1/agent/sessions/:id — 清除会话

POST /api/v1/tools              — 注册工具(动态)
GET  /api/v1/tools              — 列出已注册工具
DELETE /api/v1/tools/:name      — 注销工具

GET  /api/v1/health             — 健康检查
GET  /metrics                   — Prometheus 指标

流式输出格式(SSE) ​

event: step
data: {"type":"plan","content":"制定计划:1. 分析视频 2. 选择片段 ..."}

event: step
data: {"type":"action","tool":"analyze_video","args":{"video_path":"...","analysis_type":"highlight"}}

event: step
data: {"type":"observation","content":"找到8个精彩片段..."}

event: step
data: {"type":"action","tool":"select_segments","args":{...}}

event: done
data: {"output":"已完成!...","token_usage":{"total":2100},"duration":"12.3s"}

开发分期 ​

Phase 1:Core Loop(第1-2周) ​

目标:跑通 ReAct 循环,能通过 CLI 与 Agent 对话并调用工具

  • [x] 项目骨架搭建(Go module + Makefile)
  • [ ] LLM Client 接口 + OpenAI 实现(支持 function calling)
  • [ ] Tool 接口 + Registry + 3 个示例工具
  • [ ] ReAct 控制循环核心逻辑
  • [ ] 循环检测 + MaxSteps 限制
  • [ ] CLI: agent chat 交互模式
  • [ ] 基础单元测试

Phase 2:Planning & Memory(第3周) ​

目标:支持 Plan-and-Execute 模式 + 对话记忆

  • [ ] Planner 接口 + LLM-based 实现
  • [ ] Plan-and-Execute Agent
  • [ ] 短期记忆(滑动窗口 + 消息压缩)
  • [ ] 长期记忆(Qdrant 向量存储)
  • [ ] 意图路由器(简单 → ReAct,复杂 → Plan-and-Execute)
  • [ ] CLI: agent plan "任务描述" 查看计划

Phase 3:Video Tools + RAG 集成(第4周) ​

目标:完整的视频剪辑场景工具链 + RAG 知识库作为 Tool

  • [ ] 视频分析 Tool(模拟实现 → 后续接真实服务)
  • [ ] 场景分割 Tool
  • [ ] 字幕生成 Tool
  • [ ] BGM 推荐 Tool
  • [ ] 视频拼接/裁剪 Tool
  • [ ] RAG 知识查询 Tool(对接前一个项目)
  • [ ] 端到端场景测试

Phase 4:Production Ready(第5周) ​

目标:可部署的 HTTP 服务 + 完整可观测性

  • [ ] Guardrails 框架(Budget / Content / LoopDetect)
  • [ ] OpenTelemetry 全链路追踪
  • [ ] Prometheus 指标暴露
  • [ ] HTTP API + SSE 流式输出
  • [ ] Docker 部署方案
  • [ ] 性能基准测试
  • [ ] 评估框架:Agent 任务完成率量化

项目目录结构 ​

agent-harness/
├── cmd/
│   └── agent/
│       └── main.go              # CLI 入口
├── internal/
│   ├── agent/
│   │   ├── react.go             # ReAct Agent 实现
│   │   ├── plan_execute.go      # Plan-and-Execute Agent
│   │   └── router.go            # 意图路由
│   ├── llm/
│   │   ├── client.go            # LLM 接口定义
│   │   └── openai.go            # OpenAI 实现
│   ├── tool/
│   │   ├── registry.go          # Tool 注册中心
│   │   ├── executor.go          # 安全执行器
│   │   └── builtin/             # 内置工具
│   │       ├── analyze_video.go
│   │       ├── split_scenes.go
│   │       ├── generate_subtitles.go
│   │       ├── recommend_bgm.go
│   │       ├── concat_videos.go
│   │       ├── export_video.go
│   │       └── rag_query.go
│   ├── memory/
│   │   ├── store.go             # Memory 接口
│   │   ├── sliding_window.go    # 滑动窗口实现
│   │   └── vector.go            # 向量长期记忆
│   ├── planner/
│   │   └── llm_planner.go       # LLM 规划器
│   ├── guardrail/
│   │   ├── guardrail.go         # Guardrail 接口
│   │   ├── budget.go            # Token 预算
│   │   ├── content.go           # 内容安全
│   │   └── loop_detect.go       # 循环检测
│   └── observe/
│       ├── tracer.go            # OpenTelemetry
│       └── metrics.go           # Prometheus
├── api/
│   └── server.go                # HTTP 服务
├── configs/
│   └── default.yaml             # 默认配置
├── eval/
│   ├── testcases/               # 评估测试集
│   └── runner.go                # 评估运行器
├── Makefile
├── Dockerfile
└── go.mod

评估方案 ​

Agent 任务完成度评测 ​

指标含义计算方式
Task Completion Rate任务完成率成功完成数 / 总任务数
Step Efficiency步骤效率最优步数 / 实际步数
Tool Accuracy工具调用准确率正确 tool call / 总 tool call
Plan Quality计划质量(Plan 模式)LLM-as-Judge 评分
Token EfficiencyToken 使用效率任务质量 / Token 消耗

评估命令 ​

bash
# 运行评估测试集
agent eval --testset=eval/testcases/video_editing.json

# 对比 ReAct vs Plan-and-Execute
agent eval --agent=react --agent=plan_execute --compare

# 压力测试
agent bench --concurrency=10 --duration=60s

持续学习,持续构建。