Skip to content

第二节:多轮聊天 02_chat.py ​

目标 ​

做一个命令行聊天机器人,能连续聊很多轮,并且记得前面说过的话。

要求 ​

  1. 启动后打印提示,然后反复等待输入。
  2. 输入 exit 退出。
  3. 每轮先把用户的话追加进 messages,再调用模型,最后把模型回答也追加进去。
  4. 每轮打印模型回答和本次 token 消耗(输入 / 输出 / 总数)。
  5. 验收:第一轮说"我叫老王",聊两句别的,再问"我叫什么",能答对即通过。

完整代码 ​

python
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # 加载 .env 配置

client = OpenAI(api_key=<redacted>("LLM_API_KEY"),
                base_url=os.getenv("LLM_BASE_URL"))

# 聊天记录:一开始只有一条系统提示,之后每轮不断往里追加
messages = [{"role": "system", "content": "你是一位耐心的 AI 老师"}]

print("开始聊天,输入 exit 退出")

while True:                       # 无限循环,直到用户输入 exit
    user_input = input("你:")    # 读取用户在命令行输入的一句话
    if user_input == "exit":
        break                     # 跳出循环,结束程序

    # 1. 把用户的话追加进 messages(role 用 "user")
    messages.append({"role": "user", "content": user_input})

    # 2. 调用模型:每次都把"完整的聊天记录"发过去,模型才能"记住"上下文
    resp = client.chat.completions.create(
        model=os.getenv("LLM_MODEL"),
        messages=messages,
    )

    # 3. 取出回答并打印,再以 "assistant" 角色追加进 messages
    answer = resp.choices[0].message.content
    print("AI:", answer)
    messages.append({"role": "assistant", "content": answer})

    # 4. 分开打印输入、输出和总 token,观察输入是如何逐轮增长的
    u = resp.usage
    print(f"输入 {u.prompt_tokens} + 输出 {u.completion_tokens} = {u.total_tokens}")

提交:

bash
git add .
git commit -m "02 多轮聊天"
git push

观察:LLM 的两个天生缺陷 ​

1. 不知道最新信息 ​

模型有知识截止日期,问它"今天几号"时会瞎猜。解决办法:

  • RAG:把外部资料检索后喂给它;
  • Function Calling:让它自己调用搜索、查时间等工具。

2. 聊天记录越来越长 ​

每轮都要重发完整历史,输入 token 不断增加,迟早超出上下文窗口,也越来越贵。常见解决办法:

  • 截断:只保留最近 N 轮;
  • 摘要:把早期对话压缩成一段摘要。

关于 token 统计:总 token 偶尔会比上一轮少:total_tokens = 输入 + 输出,回答短时输出少,总数就会降。某些中转平台的统计口径也可能不同,见踩坑记录。

👉 下一阶段:Embedding 与向量检索