← 返回上一页

第5章: 对话记忆管理:让AI多轮不跑偏(总结/压缩/持久化)

让AI记住你们的对话

🤔 为什么需要对话记忆?

❌ 没有记忆的对话

场景:你和AI聊天

你:我叫小明,今年25岁

AI:你好小明!很高兴认识你

你:我叫什么名字?

AI:抱歉,我不知道你的名字 😅

问题:AI完全忘记了刚才说的话!

✅ 有记忆的对话

场景:同样的对话,但AI有记忆

你:我叫小明,今年25岁

AI:你好小明!很高兴认识你

你:我叫什么名字?

AI:你叫小明,今年25岁 ✅

效果:AI记住了之前的对话内容!

🎯 记忆的重要性

  • 连贯对话:让对话像人与人之间一样自然流畅
  • 上下文理解:AI能理解"它"、"那个"等指代词
  • 个性化服务:记住用户偏好,提供更好的服务
  • 任务延续:可以继续之前未完成的任务

🧠 对话记忆的原理

大模型本身没有记忆!每次调用都是独立的。那怎么让它"记住"对话呢?

💡 核心思路:把历史对话一起发给模型

每次调用API时,不只发送当前问题,而是把之前的所有对话都发过去

第1轮对话

发送给API:

["我叫小明"]

AI回复:

"你好小明!"
第2轮对话

发送给API:

["我叫小明", "你好小明!", "我叫什么名字?"]

⚠️ 注意:包含了第1轮的对话!

AI回复:

"你叫小明"

💻 代码实现:最简单的记忆方式

使用列表保存历史对话,每次都发送完整历史。

📦 需要安装的库

text
pip3 install dashscope

方法1:手动管理消息列表

python
import dashscope
from dashscope import Generation
import os

# 设置API Key
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')

# 创建消息历史列表
messages = []

def chat(user_input):
    """带记忆的聊天函数"""
    # 1. 添加用户消息到历史
    messages.append({
        "role": "user",
        "content": user_input
    })
    
    # 2. 调用API,发送完整历史
    response = Generation.call(
        model='qwen-turbo',
        messages=messages,  # 发送所有历史消息
        result_format='message'
    )
    
    # 3. 获取AI回复
    assistant_message = response.output.choices[0].message.content
    
    # 4. 添加AI回复到历史
    messages.append({
        "role": "assistant",
        "content": assistant_message
    })
    
    return assistant_message

# 使用示例
print("=== 带记忆的对话 ===\n")

# 第1轮对话
response1 = chat("我叫小明,今年25岁,喜欢编程")
print(f"AI: {response1}\n")

# 第2轮对话
response2 = chat("我叫什么名字?")
print(f"AI: {response2}\n")

# 第3轮对话
response3 = chat("我今年多大?")
print(f"AI: {response3}\n")

# 第4轮对话
response4 = chat("我的爱好是什么?")
print(f"AI: {response4}\n")

# 查看完整的消息历史
print("=== 消息历史 ===")
for i, msg in enumerate(messages, 1):
    role = "用户" if msg["role"] == "user" else "AI"
    print(f"{i}. {role}: {msg['content']}")

✅ 运行结果

text
=== 带记忆的对话 ===

AI: 你好小明!很高兴认识你。编程是一项非常有趣和有用的技能。

AI: 你叫小明。

AI: 你今年25岁。

AI: 你的爱好是编程。

=== 消息历史 ===
1. 用户: 我叫小明,今年25岁,喜欢编程
2. AI: 你好小明!很高兴认识你。编程是一项非常有趣和有用的技能。
3. 用户: 我叫什么名字?
4. AI: 你叫小明。
5. 用户: 我今年多大?
6. AI: 你今年25岁。
7. 用户: 我的爱好是什么?
8. AI: 你的爱好是编程。

🎨 方法2:封装成类(更优雅)

把记忆管理封装成一个类,使用起来更方便。

python
class ChatWithMemory:
    """带记忆的聊天类"""
    
    def __init__(self, system_prompt=None):
        """初始化
        
        Args:
            system_prompt: 系统提示词,定义AI的角色和行为
        """
        self.messages = []
        
        # 如果有系统提示词,添加到消息列表开头
        if system_prompt:
            self.messages.append({
                "role": "system",
                "content": system_prompt
            })
    
    def chat(self, user_input):
        """发送消息并获取回复"""
        # 添加用户消息
        self.messages.append({
            "role": "user",
            "content": user_input
        })
        
        # 调用API
        response = Generation.call(
            model='qwen-turbo',
            messages=self.messages,
            result_format='message'
        )
        
        # 获取并保存AI回复
        assistant_message = response.output.choices[0].message.content
        self.messages.append({
            "role": "assistant",
            "content": assistant_message
        })
        
        return assistant_message
    
    def get_history(self):
        """获取对话历史"""
        return self.messages
    
    def clear_history(self):
        """清空对话历史(保留system消息)"""
        system_messages = [msg for msg in self.messages if msg["role"] == "system"]
        self.messages = system_messages
    
    def get_message_count(self):
        """获取消息数量"""
        return len(self.messages)

# 使用示例
print("=== 创建一个Python助手 ===\n")

# 创建带系统提示词的聊天
assistant = ChatWithMemory(
    system_prompt="你是一个Python编程助手,擅长解答Python相关问题。"
)

# 多轮对话
print(f"AI: {assistant.chat('什么是列表?')}\n")
print(f"AI: {assistant.chat('它和元组有什么区别?')}\n")
print(f"AI: {assistant.chat('给我举个例子')}\n")

# 查看消息数量
print(f"当前消息数量:{assistant.get_message_count()}")

🎮 实战案例:AI猜数字游戏

现在我们学会了对话记忆管理,让我们用它来实现一个有趣的游戏! 这个案例完美展示了为什么需要记忆:AI需要记住之前的猜测,才能给出正确的提示。

🎯 游戏规则

  • AI在心里想一个1-100之间的数字
  • 玩家猜测数字
  • AI告诉玩家:太大了、太小了、或猜对了
  • 关键:AI需要记住之前的猜测次数!

💻 完整代码(简化版)

重点关注如何使用messages保存对话历史,其他代码都是辅助功能。

python
#!/usr/bin/env python3
"""AI猜数字游戏 - 展示对话记忆的重要性"""

import os
from dashscope import Generation
from http import HTTPStatus


# 游戏Prompt
GAME_PROMPT = """你是一个猜数字游戏的主持人。

游戏规则:
1. 你在心里想一个1-100之间的整数(不要告诉我)
2. 我会猜测数字
3. 你告诉我:太大了、太小了、或猜对了
4. 记录我猜了几次

要求:态度友好、使用emoji、每次给出明确提示"""


def chat_with_ai(messages):
    """调用AI - 核心函数"""
    response = Generation.call(
        model='qwen-plus',
        api_key=os.getenv('DASHSCOPE_API_KEY'),
        messages=messages,
        temperature=0.8,
        result_format='message'
    )
    
    if response.status_code == HTTPStatus.OK:
        return response.output.choices[0].message.content
    return "错误"


def play_game():
    """开始游戏"""
    print("🎮 AI猜数字游戏\n")
    
    # 【核心】创建消息历史列表
    messages = [
        {'role': 'system', 'content': GAME_PROMPT}
    ]
    
    # AI开场白
    ai_msg = chat_with_ai(messages)
    print(f"🤖 AI: {ai_msg}\n")
    messages.append({'role': 'assistant', 'content': ai_msg})
    
    # 游戏循环
    while True:
        guess = input("👤 你的猜测: ").strip()
        if not guess:
            continue
        
        # 【核心】添加用户消息到历史
        messages.append({'role': 'user', 'content': guess})
        
        # 【核心】发送完整历史给AI
        ai_msg = chat_with_ai(messages)
        print(f"🤖 AI: {ai_msg}\n")
        
        # 【核心】保存AI回复到历史
        messages.append({'role': 'assistant', 'content': ai_msg})
        
        # 检查是否猜对
        if '恭喜' in ai_msg or '猜对' in ai_msg:
            break
    
    print("👋 游戏结束!")


if __name__ == "__main__":
    play_game()

🚀 运行效果

text
🎮 AI猜数字游戏

🤖 AI: 嗨!欢迎来到猜数字游戏!🎉 我已经想好了一个1-100之间的数字,来猜猜看吧!

👤 你的猜测: 50
🤖 AI: 50!🤔 有点大了哦~试试更小的数字!这是第1次猜测~

👤 你的猜测: 25
🤖 AI: 25!太小啦~📈 往大一点想!这是第2次猜测~

👤 你的猜测: 37
🤖 AI: 37!还是小了一点~📈 继续往上!第3次了~

👤 你的猜测: 43
🤖 AI: 43!有点大了~📉 往小调整!第4次~

👤 你的猜测: 40
🤖 AI: 40!还是小了~📈 再大一点!第5次~

👤 你的猜测: 42
🤖 AI: 🎉🎉🎉 恭喜你!猜对啦!答案就是42!你用了6次就猜中了,太棒了!👏

👋 游戏结束!

💡 代码核心要点

1. 创建消息历史列表
text
messages = [
    {'role': 'system', 'content': GAME_PROMPT}
]

这个列表保存所有对话,让AI能"记住"之前的猜测。

2. 添加用户消息
text
messages.append({'role': 'user', 'content': guess})

每次猜测都要添加到历史中。

3. 发送完整历史
text
response = Generation.call(
    model='qwen-turbo',
    messages=messages,  # 发送所有历史消息
    result_format='message'
)

关键!每次都把完整历史发给AI。

4. 保存AI回复
text
messages.append({'role': 'assistant', 'content': ai_msg})

AI的回复也要保存,下次调用时会用到。

🤔 思考:如果没有记忆会怎样?

如果每次调用只发送当前猜测,不发送历史:

  • ❌ AI不知道你之前猜过什么
  • ❌ AI无法统计猜测次数
  • ❌ AI可能给出矛盾的提示
  • ❌ 游戏根本无法进行!

这就是为什么对话记忆如此重要!

🎨 扩展练习

尝试修改Prompt,实现不同的游戏变体:

  • 限制次数:只能猜7次,超过就失败
  • 给范围提示:每次告诉玩家答案在哪个范围
  • 改变风格:让AI变成搞笑主持人

💡 只需修改GAME_PROMPT,代码逻辑不变!

📚 课后习题与面试题

请认真完成以下练习,巩固对话记忆管理核心知识

⚠️ 重要提示:这些题目涵盖了面试常见考点,请务必掌握!

🎯 基础练习题

1. 为什么大语言模型需要对话记忆管理?如果不管理会出现什么问题?

2. 在messages数组中,有哪几种角色(role)?每种角色的作用是什么?

3. 请写出实现对话记忆的基本步骤(用代码或伪代码)。

🚀 进阶练习题

4. 对话历史越来越长会带来什么问题?如何解决?

5. 实现一个简单的对话历史管理类,要求支持添加消息、获取历史、限制长度。

💼 面试常见题

6. 如果用户刷新页面,对话历史会丢失吗?如何持久化保存?

7. 在生产环境中,如何设计一个高效的对话记忆系统?需要考虑哪些因素?

💡 学习建议

  • 动手实践:自己写一个简单的对话机器人,体会记忆管理的重要性
  • 测试边界:尝试让对话历史超出token限制,观察会发生什么
  • 优化策略:实现不同的历史压缩方案,比较效果
  • 阅读源码:研究LangChain等框架的记忆管理实现
  • 关注成本:计算不同策略下的token消耗和API费用
← 上一章 下一章 →