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 复制代码
=== 多轮对话 ===
丘吉尔是英国政治家、演说家...
他是英国人。
我们刚才聊的是丘吉尔。
相关推荐
ahauedu4 分钟前
SpringBoot 3.5.10引入springdoc-openapi-starter-webmvc-ui版本
java·spring boot·后端
未来龙皇小蓝13 分钟前
Spring内置常见线程池配置及相关概念
java·后端·spring·系统架构
Testopia13 分钟前
AI编程实例 - 基于时间序列分析的工厂设备预测性维护
人工智能·ai编程·#人工智能学习·#时间序列分析
测试_AI_一辰15 分钟前
Agent & RAG 测试工程 03:第一次为 RAG 写回归测试:防幻觉、保一致、守底线
人工智能·笔记·功能测试·测试用例·ai编程
新缸中之脑29 分钟前
Google:Rust实战评估
开发语言·后端·rust
一 乐43 分钟前
在线考试|基于springboot + vue在线考试系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
女王大人万岁1 小时前
Go标准库 path 详解
服务器·开发语言·后端·golang
qq_12498707531 小时前
基于spring boot的调查问卷系统的设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
Eaxker1 小时前
Java后端学习4:MySQL
后端·mysql
LuminescenceJ2 小时前
RPC通信中的Context上下文如何跨进程传递消息,gRPC为例分析
开发语言·网络·后端·网络协议·rpc·golang