该教程旨在带大家从 0 起步,掌握用 Python 开发大模型应用的技能。若当前内容让你感到晦涩,可回溯本合集的前期文章,降低学习难度。
1. 为什么需要记忆?
1.1. 大模型无状态
每次请求独立,不会主动记住上一轮内容。
典型翻车场景:
用户:丘吉尔是谁?
用户:他哪国人? ← 模型不知"他"指谁
1.2. 解决思路
把历史对话当成消息列表的一部分塞给模型。
与小样本提示原理相同:
系统消息 → 历史消息 → 当前用户问题
2. 手动记忆 5 步流程
2.1. 环境
shell
pip install langchain langchain-deepseek
export DEEPSEEK_API_KEY=sk-xxx
2.2. 初始化记忆容器
python
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(return_messages=True) # 必须True
2.3. 查看当前记忆(空)
python
print(memory.load_memory_variables({}))
# → {'history': []}
2.4. 把一轮对话写进记忆
python
memory.save_context(
{"input": "丘吉尔是谁?"},
{"output": "英国政治家、演说家"}
)
写后再 load_memory_variables 可见两条消息对象。
2.5. 提示模板占位历史消息
python
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是历史问答助手,回答简洁。"),
MessagesPlaceholder(variable_name="history"), # 占位符
("human", "{input}")
])
2.6. 取历史 → 拼消息 → 调模型 → 写回新对话
python
from langchain_deepseek import ChatDeepSeek
llm = ChatDeepSeek(model="deepseek-chat", temperature=0)
def chat_with_memory(user_question: str) -> str:
history = memory.load_memory_variables({})["history"] # ① 取历史
messages = prompt.format_messages(history=history, input=user_question) # ② 拼消息
response = llm.invoke(messages) # ③ 调模型
memory.save_context({"input": user_question}, {"output": response.content}) # ④ 写回
return response.content
3. 多轮体验
python
print("=== 多轮对话 ===")
print(chat_with_memory("丘吉尔是谁?"))
print(chat_with_memory("他哪国人?")) # 利用上下文答"英国人"
print(chat_with_memory("我们刚才聊的是谁?")) # 仍能答"丘吉尔"
4. 完整可运行代码
python
from langchain.memory import ConversationBufferMemory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_deepseek import ChatDeepSeek
# ① 初始化记忆
memory = ConversationBufferMemory(return_messages=True)
# ② 提示模板占位
prompt = ChatPromptTemplate.from_messages([
("system", "你是历史问答助手,回答简洁。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
llm = ChatDeepSeek(model="deepseek-chat", temperature=0)
# ③ 记忆对话函数
def chat_with_memory(user_question: str) -> str:
history = memory.load_memory_variables({})["history"] # 取历史
messages = prompt.format_messages(history=history, input=user_question)
response = llm.invoke(messages)
# 写回记忆
memory.save_context({"input": user_question}, {"output": response.content})
return response.content
# ④ 多轮测试
if __name__ == "__main__":
print("=== 多轮对话 ===")
print(chat_with_memory("丘吉尔是谁?"))
print(chat_with_memory("他哪国人?"))
print(chat_with_memory("我们刚才聊的是谁?"))
运行结果示例:
diff
=== 多轮对话 ===
丘吉尔是英国政治家、演说家...
他是英国人。
我们刚才聊的是丘吉尔。