第03章:多轮对话与上下文管理——让AI记住你说过的每句话

第03章:多轮对话与上下文管理——让AI记住你说过的每句话


3.1 单轮 vs 多轮:一个问题的两种命中的差距

单轮对话(每次都是新的上下文):

你:帮我分析这份数据
AI:[分析]
你:按月份拆开看
AI:[不知道你在说哪份数据]

多轮对话(有上下文记忆):

你:帮我分析这份销售数据
AI:[分析完成]
你:按月份拆开看
AI:[基于之前的数据,按月份分析] ✅
你:哪个月表现最差,分析原因
AI:[结合前两轮的数据,给出分析] ✅✅

多轮对话的核心价值:让AI的每次回复都基于之前所有对话的积累。


3.2 对话上下文管理的基本原理

AI的"记忆"来自两部分:

1. System Prompt(系统提示词):开场设定,只读一次
2. Conversation History(对话历史):每次对话都带上

AI并不是真的"记住"了——而是每次请求都会把历史对话一起发过去。

所以优化的关键是:管理对话历史的长度、结构和质量


3.3 策略一:自动摘要压缩

对话超过一定轮数后,把历史对话压缩成摘要,保留关键信息:

import anthropic

client = anthropic.Anthropic()
MAX_TOKENS_PER_TURN = 4000  # 保守限制

def compress_conversation(conversation_history):
    """
    当对话历史超过阈值时,压缩为摘要
    """
    total_tokens = sum(len(msg["content"]) // 4 for msg in conversation_history)

    if total_tokens < MAX_TOKENS_PER_TURN:
        return conversation_history  # 不需要压缩

    # 调用AI压缩历史
    compression_prompt = f"""
以下是一段AI对话历史,请压缩为一段不超过300字的摘要,
保留所有关键信息、决定、用户偏好和待处理事项。

对话历史:
{chr(10).join([f"用户:{m['user']}\nAI:{m['assistant']}" for m in conversation_history])}

摘要格式:
关键背景:[...]
用户偏好:[...]
已完成事项:[...]
待处理事项:[...]
"""
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=500,
        messages=[{"role": "user", "content": compression_prompt}]
    )

    compressed = [{
        "role": "user",
        "content": "[以上对话已压缩为摘要]",
        "summary": response.content[0].text
    }, {
        "role": "assistant",
        "content": "[对话已压缩,保留关键信息以便继续]"
    }]

    return compressed

3.4 策略二:长期记忆注入

除了对话历史,还有一个更持久的记忆层:长期记忆

# 长期记忆存储(PostgreSQL / Redis / 文件都可以)
def save_long_term_memory(user_id, key, value):
    conn = get_db_conn()
    conn.execute("""
        INSERT INTO user_memory (user_id, memory_key, memory_value, updated_at)
        VALUES (%s, %s, %s, NOW())
        ON CONFLICT (user_id, memory_key)
        DO UPDATE SET memory_value = %s, updated_at = NOW()
    """, (user_id, key, value, value))
    conn.commit()

def load_long_term_memory(user_id):
    conn = get_db_conn()
    rows = conn.execute("""
        SELECT memory_key, memory_value FROM user_memory
        WHERE user_id = %s
    """, (user_id,)).fetchall()
    return {row["memory_key"]: row["memory_value"] for row in rows}

# 在每次对话开始时,把长期记忆注入上下文
def build_system_prompt_with_memory(user_id):
    memory = load_long_term_memory(user_id)

    memory_section = ""
    if memory:
        memory_section = "\n\n## 关于用户的长期记忆(请在回复时参考):\n"
        for key, value in memory.items():
            memory_section += f"- {key}:{value}\n"

    return f"""
你是一名专业的AI助手,名字叫小明。

你的特点是:
- 专业、简洁、有耐心
- 回答问题时直接给结论,再解释原因
- 遇到不确定的事情,明确告知用户而不是胡乱猜测
{user_id}
你与用户有过一段合作历史,以下是相关信息:
{memory_section}
"""

3.5 策略三:Session 分层设计

不同类型的对话,适合放在不同的Session里:

Session A(日常助理)
  → 帮我查天气、设提醒、发消息

Session B(专业工作)
  → 数据分析、报告撰写、代码审查

Session C(长期项目)
  → 产品规划、战略讨论、创意发散

同一Session内的事项才有上下文继承。 日常闲聊不要和专业工作混在一起,否则AI既记不住你喜欢的风格,也没法专注专业判断。


3.6 实战:用 OpenClaw 实现多轮记忆

# 在 OpenClaw 的 skill 配置里启用对话记忆
SKILL_MEMORY_CONFIG = {
    "memory_enabled": True,
    "memory_backend": "postgresql",  # 或 redis / file
    "memory_table": "conversation_memory",
    "auto_compress_after_turns": 10,
    "compress_threshold_tokens": 6000,
    "long_term_memory_keys": [
        "user_preferences",
        "onboarding_completed",
        "active_projects",
        "important_context"
    ]
}
CREATE TABLE conversation_memory (
    id SERIAL PRIMARY KEY,
    user_id VARCHAR(100),
    session_id VARCHAR(100),
    turn_number INTEGER,
    user_message TEXT,
    ai_response TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE user_long_term_memory (
    id SERIAL PRIMARY KEY,
    user_id VARCHAR(100),
    memory_key VARCHAR(100),
    memory_value TEXT,
    confidence FLOAT DEFAULT 1.0,
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(user_id, memory_key)
);

3.7 常见问题

Q:AI忘记了之前说过的事情怎么办? A:主动在对话开头提醒它,比如"继续上次我们讨论的XX项目"。

Q:对话太长了,速度变慢怎么办? A:用自动摘要压缩策略(本章3.3节),把超过10轮的历史压缩成摘要。

Q:不同设备/平台之间记忆能同步吗? A:把记忆存储在后端数据库(PostgreSQL/Redis),而不是前端Session。


落地动作

  1. 检查你当前使用的AI工具,支持多少轮上下文,接近上限时如何处理
  2. 设计你的Session分层结构(日常/专业/项目分离)
  3. 在数据库里建立 user_long_term_memory 表,存3个你最常用的用户偏好
  4. 写一个对话摘要函数,在超过10轮时自动触发压缩
  5. 测试"跨Session连续性":在上一个Session里告诉AI一个偏好,在新的Session里验证它是否记住了