理论部分

很多人第一次写多轮对话,会误以为“模型记住了刚才聊过的内容”。但从 API 的角度看,多轮对话的本质其实是:

每一轮请求都把历史消息一起发给模型

也就是说:

  • 模型没有“长期记忆”(默认情况下不会跨请求自动保存)
  • 我们看到的“记住上下文”,来自我们在每次调用时携带的 messages
  • 所谓“对话状态”,就是我们在本地维护的一份 messages 列表

在常见的对话接口里,输入是一个消息列表 messages,每条消息包含:

  • role:消息角色,常见为 system / user / assistant
  • content:消息内容

多轮对话要跑起来,有一个关键点:

每轮把用户输入 append 进 messages,拿到模型输出后,也要把 assistant 输出 append 进 messages。否则模型下一轮就“忘了自己刚刚说了什么”。


实践部分

本案例做什么

实现一个命令行聊天机器人,支持我们在终端连续输入多轮消息:

  1. 初始化 messages,用 system 设定角色
  2. 循环读取用户输入,追加到 messages
  3. 调用模型生成回答,并将回答追加到 messages
  4. 支持输入 exit/quit/退出 结束对话,支持 Ctrl + C 强制退出

主要代码

本篇直接使用项目脚本:src/1.3_chatbot.py

import os
from dotenv import load_dotenv
from openai import OpenAI

# 加载配置
load_dotenv()
client = OpenAI(
    api_key=os.getenv("ZHIPUAI_API_KEY"),
    base_url=os.getenv("ZHIPUAI_BASE_URL")
)

def main():
    # 1. 初始化对话历史
    # system: 设置模型的“人设”
    messages = [
        {"role": "system", "content": "你是一个暴躁的四川厨师,说话带口音。"}
    ]

    print("=== 🤖 智能聊天机器人 (输入 'exit' 或 'quit' 退出) ===")

    while True:
        # 2. 获取用户输入
        try:
            user_input = input("\n👤 你: ")
        except KeyboardInterrupt:
            # 处理 Ctrl+C 强制退出
            print("\n👋 再见!")
            break

        if user_input.lower() in ["exit", "quit", "退出"]:
            print("👋 聊得很开心,下次见!")
            break
        
        if not user_input.strip():
            print("⚠️ 请输入内容...")
            continue

        # 3. 将用户输入加入历史
        messages.append({"role": "user", "content": user_input})

        try:
            # 4. 调用 API
            # print("Thinking...", end="", flush=True) # 简单的等待提示
            response = client.chat.completions.create(
                model="glm-4-flash",
                messages=messages,
                temperature=0.9,
                stream=False
            )

            # 5. 获取回答并展示
            assistant_content = response.choices[0].message.content
            print(f"\n🤖 AI: {assistant_content}")

            # 6. 【关键】将 AI 的回答也加入历史
            # 如果不加这一步,模型下一轮就会忘记它刚才说了什么
            messages.append({"role": "assistant", "content": assistant_content})

        except Exception as e:
            print(f"\n❌ 发生错误: {e}")
            # 发生错误时,建议把刚才导致错误的用户输入移除,防止卡死
            messages.pop()

if __name__ == "__main__":
    main()

运行方式

在项目根目录执行:

python3 src/1.3_chatbot.py

运行结果示例

运行后会看到类似交互(回答内容每次会不同):

=== 🤖 智能聊天机器人 (输入 'exit' 或 'quit' 退出) ===

👤 你: 我想学做番茄炒蛋

🤖 AI: ...

👤 你: 那第一步应该做什么?

🤖 AI: ...

👤 你: exit
👋 聊得很开心,下次见!

如果出现报错:

  • 提示缺少 ZHIPUAI_API_KEY:先确认第 2 篇的 .env 配置是否正确
  • 依赖缺失(例如 openai/dotenv):确认已安装依赖并激活虚拟环境
  • 网络相关错误:确认网络/代理配置与 ZHIPUAI_BASE_URL 可访问

总结

这一篇我们完成了一个最小可用的多轮对话机器人,并理解了多轮对话的核心:对话状态由我们维护,每轮请求都要携带历史消息

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐