Agent 示例

多轮对话

保持上下文的连续对话

多轮对话示例

展示如何进行多轮对话,Agent 自动维护历史上下文。

完整代码

package main

import (
    "bufio"
    "context"
    "fmt"
    "log"
    "os"
    "strings"

    "github.com/astercloud/aster/pkg/agent"
    "github.com/astercloud/aster/pkg/provider"
    "github.com/astercloud/aster/pkg/sandbox"
    "github.com/astercloud/aster/pkg/store"
    "github.com/astercloud/aster/pkg/tools"
    "github.com/astercloud/aster/pkg/types"
)

func main() {
    ctx := context.Background()

    // 创建依赖
    deps := &agent.Dependencies{
        ToolRegistry:     tools.NewRegistry(),
        SandboxFactory:   sandbox.NewFactory(),
        ProviderFactory:  provider.NewMultiProviderFactory(),
        Store:            store.NewMemoryStore(),
        TemplateRegistry: agent.NewTemplateRegistry(),
    }

    // 创建 Agent
    ag, err := agent.Create(ctx, &types.AgentConfig{
        TemplateID: "assistant",
        ModelConfig: &types.ModelConfig{
            Provider: "anthropic",
            Model:    "claude-sonnet-4-5",
            APIKey:   os.Getenv("ANTHROPIC_API_KEY"),
        },
    }, deps)
    if err != nil {
        log.Fatal(err)
    }
    defer ag.Close()

    // 交互式对话循环
    scanner := bufio.NewScanner(os.Stdin)
    fmt.Println("开始对话(输入 'quit' 退出)")
    fmt.Println("=====================================")

    for {
        fmt.Print("\n你: ")
        if !scanner.Scan() {
            break
        }

        input := strings.TrimSpace(scanner.Text())
        if input == "" {
            continue
        }
        if input == "quit" || input == "exit" {
            fmt.Println("再见!")
            break
        }

        // 发送消息
        result, err := ag.Chat(ctx, input)
        if err != nil {
            log.Printf("错误: %v", err)
            continue
        }

        // 打印响应
        fmt.Printf("\nAgent: %s\n", result.Message.Content)

        // 显示 Token 使用
        status := ag.Status()
        fmt.Printf("[消息数: %d, Token: %d]\n",
            status.MessageCount,
            result.Usage.TotalTokens)
    }
}

运行示例

export ANTHROPIC_API_KEY="sk-ant-xxx"
go run main.go

对话示例

开始对话(输入 'quit' 退出)
=====================================

你: 我叫小明,今年25岁

Agent: 你好小明!很高兴认识你。25岁正是充满活力和可能性的年纪,有什么我可以帮助你的吗?
[消息数: 2, Token: 89]

你: 我几岁了?

Agent: 根据你刚才说的,你今年25岁。
[消息数: 4, Token: 67]

你: 我的名字是什么?

Agent: 你的名字是小明。
[消息数: 6, Token: 56]

你: quit
再见!

关键点

  1. 自动上下文:Agent 自动维护对话历史
  2. 消息计数Status() 可以查看当前消息数
  3. 持久化:消息历史保存在 Store 中

查看对话历史

// 获取 Agent 状态
status := ag.Status()
fmt.Printf("消息数: %d\n", status.MessageCount)
fmt.Printf("步数: %d\n", status.StepCount)

// 如果需要访问原始消息,可以从 Store 读取
// (需要 Agent 暴露相应接口)

上下文总结

当对话历史过长时,使用 Summarization 中间件自动总结:

ag, err := agent.Create(ctx, &types.AgentConfig{
    TemplateID: "assistant",
    ModelConfig: modelConfig,
    Middlewares: []string{"summarization"},  // 启用自动总结
    MiddlewareConfigs: map[string]*types.MiddlewareConfig{
        "summarization": {
            Settings: map[string]interface{}{
                "message_threshold": 20,  // 超过 20 条消息时总结
                "keep_recent": 5,         // 保留最近 5 条
            },
        },
    },
}, deps)

流式多轮对话

结合流式输出和多轮对话:

for {
    fmt.Print("\n你: ")
    scanner.Scan()
    input := scanner.Text()

    if input == "quit" {
        break
    }

    // 使用流式输出
    eventCh := ag.Subscribe([]types.AgentChannel{types.ChannelProgress}, nil)

    go func() {
        fmt.Print("Agent: ")
        for envelope := range eventCh {
            if envelope.Event.Type == types.EventTypeTextDelta {
                fmt.Print(envelope.Event.TextDelta)
            }
        }
        fmt.Println()
    }()

    ag.Send(ctx, input)

    // 等待完成...
}

相关资源