Appearance
第二节:多轮聊天 02_chat.py
目标
做一个命令行聊天机器人,能连续聊很多轮,并且记得前面说过的话。
要求
- 启动后打印提示,然后反复等待输入。
- 输入
exit退出。 - 每轮先把用户的话追加进
messages,再调用模型,最后把模型回答也追加进去。 - 每轮打印模型回答和本次 token 消耗(输入 / 输出 / 总数)。
- 验收:第一轮说"我叫老王",聊两句别的,再问"我叫什么",能答对即通过。
完整代码
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 与向量检索