Skip to content

Day 5:加记忆——让Agent记住对话

昨天的问题

用户:"查一下订单 #12345" → Agent:"已发货" 用户:"那能改地址吗?" → Agent:"?什么改地址?"

Agent 每一轮都像第一次见用户。没有记忆,多轮对话就是断的。

今天做什么

接入 Eino Memory,让 Agent 记住对话上下文。

代码

go
package main

import (
    "context"
    "fmt"
    "sync"

    "github.com/cloudwego/eino/schema"
)

// ===== 简易 Memory 实现 =====
type ConversationMemory struct {
    mu       sync.Mutex
    messages []*schema.Message
    maxSize  int
}

func NewMemory(maxSize int) *ConversationMemory {
    return &ConversationMemory{
        messages: make([]*schema.Message, 0),
        maxSize:  maxSize,
    }
}

func (m *ConversationMemory) Add(msg *schema.Message) {
    m.mu.Lock()
    defer m.mu.Unlock()
    m.messages = append(m.messages, msg)
    // 只保留最近 N 条
    if len(m.messages) > m.maxSize {
        m.messages = m.messages[len(m.messages)-m.maxSize:]
    }
}

func (m *ConversationMemory) Get() []*schema.Message {
    m.mu.Lock()
    defer m.mu.Unlock()
    result := make([]*schema.Message, len(m.messages))
    copy(result, m.messages)
    return result
}

// ===== 带记忆的 Agent =====
type CustomerServiceAgent struct {
    model  ChatModel
    memory *ConversationMemory
}

func (a *CustomerServiceAgent) Chat(ctx context.Context,
    question string) (string, error) {

    // 第一步:把用户消息加入记忆
    a.memory.Add(schema.UserMessage(question))

    // 第二步:构建 Prompt(包含历史对话)
    messages := []*schema.Message{
        schema.SystemMessage(systemPrompt),
    }
    messages = append(messages, a.memory.Get()...)

    // 第三步:让 LLM 生成回答
    result, err := a.model.Generate(ctx, messages)
    if err != nil {
        return "", err
    }

    // 第四步:把 AI 回答也加入记忆
    a.memory.Add(result)

    return result.Content, nil
}

func main() {
    ctx := context.Background()
    agent := &CustomerServiceAgent{
        model:  &MockChatModel{},
        memory: NewMemory(10),
    }

    // 模拟多轮对话
    dialogs := [][]string{
        {"查一下订单 #12345"},
        {"那能加急配送吗?"},
        {"算了,帮我看看退货流程"},
    }

    for _, msgs := range dialogs {
        for _, msg := range msgs {
            answer, _ := agent.Chat(ctx, msg)
            fmt.Printf("👤 用户: %s\n", msg)
            fmt.Printf("🤖 小智: %s\n\n", answer)
        }
        fmt.Println("--- 新会话 ---")
    }
}

运行

bash
go run main.go

你学到了什么

  1. Memory 的核心:存消息 → 取消息 → 拼进 Prompt。sync.Mutex 保证并发安全。
  2. 滑动窗口maxSize 限制记忆条数,防止上下文爆炸。
  3. 多轮对话:用户说"那能加急吗",Agent 从 Memory 里知道"那"指"订单 #12345"。

明天的预告

Agent 的工具是硬编码在代码里的。明天我们用 MCP 把工具标准化——让工具变成"即插即用"的接口。


Day 5 完成。你的 Agent 现在会记住对话了。