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 复制代码
=== 多轮对话 ===
丘吉尔是英国政治家、演说家...
他是英国人。
我们刚才聊的是丘吉尔。
相关推荐
独泪了无痕3 小时前
Spring Data Redis 快速上手
spring boot·redis·后端
m0_639906947 小时前
Linux 操作系统入门:目录结构、服务排查常用命令、Shell 脚本基础
linux·运维·后端
holly就是我7 小时前
AI 编程助手为什么跑偏?用开源 ccglass 看清 Prompt、工具调用和 Token 消耗
人工智能·后端
鸿蒙开发7 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
用户788477316347 小时前
小程序后端三选一:云开发、.NET WebAPI、Node,我按客户现状分了三种答案
后端
择势7 小时前
从零散提效到体系化协作:iOS 团队 AI 研发工作流完整实践
ai编程
aiopencode7 小时前
局域网设备抓包怎么做?用 TraceEagle 抓电视、游戏机和 IoT 流量
后端·ios
智驭未来掌门人7 小时前
CLion 开发 Qt 项目的优势
后端
EnCi Zheng8 小时前
后端怎么把AI接口稳定安全低成本接进业务:超时重试、密钥隔离与成本熔断清单
人工智能·后端·安全·架构·api
Bazingga8 小时前
从一家酒店讲懂Docker
后端