009.LangChain 手动记忆全流程

该教程旨在带大家从 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 复制代码
=== 多轮对话 ===
丘吉尔是英国政治家、演说家...
他是英国人。
我们刚才聊的是丘吉尔。
相关推荐
Setsuna_F_Seiei5 小时前
前端的 AI 学习之路 02 之 Provider 与 Structured Output - 规范化模型输入输出
人工智能·agent·ai编程
Setsuna_F_Seiei6 小时前
前端的 AI 学习之路 01 之 Agent API 调用 - 和 Agent 的基础对话
前端·人工智能·ai编程
覆东流6 小时前
7.Java数组
java·开发语言·后端
threerocks6 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
JavaPub-rodert6 小时前
王仕宇在 Go Context 如何解决协程泄漏与超时控制
开发语言·后端·golang·iphone·javapub·王仕宇
深漂的华哥7 小时前
Ruoyi-Plus前后端分离场景下,数据加密传输
java·spring boot·后端·开源·maven·ruoyi
why技术8 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
学习星球8 小时前
Qwik 框架入门实战:从开源项目 Qwik City 开始,用可恢复性替代水合
后端·前端框架·开源·c5全栈
Jooolin9 小时前
AI项目实战日记ep1:从零做一个 AI 日志分析助手
ai编程
小虎AI生活10 小时前
用 WorkBuddy 三个 Skill 串起一条流水线:8 张随手拍照片 30 分钟变口播视频
ai编程