上一课的程序只能问一次就结束,体验很割裂。更奇怪的是,你告诉它「我叫小明」,下一句再问「我叫什么」,它会说「我不知道」。这一课,我们把这两件事一次性解决。
一、先让它能连续对话
只需要一个while循环。修改main.py:
from openai import OpenAI import os client = OpenAI( api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com" ) while True: user_input = input("你:") if user_input.lower() == "exit": break response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "user", "content": user_input} ] ) print("AI:", response.choices[0].message.content)运行后:
你:你好 AI:你好!有什么可以帮助你的? 你:什么是 Transformer? AI:Transformer 是一种…… 你:exit恭喜,你已经做出了一个最简单的AI Chatbot。
一句话概括:while True让程序不再「问完就跑」,而是持续等待你的输入。
二、但它为什么记不住你?
试着这样对话:
你:我叫小明。 AI:好的。 你:我叫什么? AI:我不知道。别急着怪模型笨。问题出在我们自己身上——每一次请求,其实都是全新的、独立的:
第一次请求: 用户 →「我叫小明」→ LLM 第二次请求: 用户 →「我叫什么?」→ LLM ← 它根本没见过第一句话模型没有记忆,它只看得见你这一次发给它的内容。第一次对话的内容,在第二次请求时压根没传过去。
一句话概括:模型不是失忆,是我们根本没把历史递给它。
三、引入「对话历史」
解决办法很简单:把每一轮对话都存进一个messages列表,每次请求都把整个历史一起发过去。
messages = [] while True: user_input = input("你:") if user_input.lower() == "exit": break # 1. 把你的话加入历史 messages.append({ "role": "user", "content": user_input }) # 2. 把整个历史发给模型 response = client.chat.completions.create( model="deepseek-chat", messages=messages ) answer = response.choices[0].message.content # 3. 把模型的回答也加入历史 messages.append({ "role": "assistant", "content": answer }) print("AI:", answer)现在再试:
你:我叫小明 AI:你好,小明! 你:我叫什么? AI:你叫小明。它记住了。因为每次请求,我们都把完整历史打包发给了模型。
这里有个关键角色:role
messages里每条消息都有一个role,它决定了这句话是谁说的:
| role | 含义 | 举例 |
|---|---|---|
| user | 用户说的话 | 「我叫小明」 |
| assistant | 模型说的话 | 「你好,小明!」 |
| system | 系统设定(可选) | 「你是一个专业助手」 |
一句话概括:Memory 的第一步,就是老老实实把对话历史存下来、每次都带上。
四、这就是 Agent 的「记忆」雏形
我们刚才做的messages列表,其实就是最朴素的 Memory。它不需要数据库,一个 Python 列表就够了。
随着项目变复杂,你会逐步升级它:
列表 memory → SQLite → PostgreSQL / Redis → 向量数据库 + Embedding → RAG但对初学者来说,先用最简单的方式跑通,比一步到位更重要。
一句话概括:先有记忆,再谈智能;能记住上下文,才谈得上真正的 Agent。
总结
这一课我们做了两件事:用while循环让它能连续聊天,用messages历史让它能记住上下文。
到这里,你的程序已经是一个像样的聊天机器人了。但它还只会「聊天」——它不能搜索,不会计算,不能替你做任何实际操作。下一课,我们迎来最关键的一次跨越:给 AI 装上工具,让它学会Tool Calling。
下一课预告
第4课:让 AI 学会用工具——Tool Calling 第一步(计算器)。