【Agent开发第三期】短期记忆history,让模型“记住“上一句
文章目录一、前言二、概念对齐:为什么回灌能让模型记住2.1 回顾:模型为什么失忆2.2 回灌历史:从一句话到完整历史2.3 一张表看清三期演进2.4 本期的组装公式三、动手做:从金鱼记忆到短期记忆3.1 维护一个 messages 列表3.2 上下文长度限制:历史不能无限长3.3 reset 和 history 命令3.4 自动演示:对比第 02 期的金鱼记忆四、跑起来:短期记忆的实际体验4.1 为什么回灌历史能让模型记住?4.2 token 增长可视化4.3 调用流程(与前两期一致)五、执行脚本六、总结一、前言第 02 期你跑通了循环对话,但模型有金鱼记忆——你上一句说我叫张三,下一句问我姓什么,它答不上来。明明刚说过,转头就忘。根本原因:每次调用messages里只传当前这一句,模型看不到历史。这不是模型笨,是你没把历史喂给它。这一期我们就动手维护一份messages列表,每次调用把完整对话历史回灌进去,让模型真正记住上一句。同时引入上下文长度限制——历史不能无限长,这是个新问题。看完你就能:用 messages 列表维护完整对话历史理解回灌历史为什么能让模型记住用 token 计数直观看到上下文在增长加一个最简单的上下文长度限制,防止历史无限膨胀本文是 Agent 教学系列第 03 期的实战笔记,干货为主,偶尔自嘲,各位看官将就着看。二、概念对齐:为什么回灌能让模型记住2.1 回顾:模型为什么失忆上一期讲过,模型 API 是无状态的——每次请求都被当成全新对话,服务器不保存任何上下文。所以连续对话的幻觉,是客户端伪造出来的:你自己维护一份历史,每次请求把整段历史一起发过去。但第 02 期我们故意没这么做——messages里永远只有当前这一句,专门让你踩一脚金鱼记忆。这一期补上。2.2 回灌历史:从一句话到完整历史核心改动就一处:把chat()的入参从一句话变成完整 messages 列表。defchat(messages:list[dict])-tuple[str,int,int]:responseclient.chat.completions.create(modelMODEL,messagesmessages,# ← 完整历史,不再只传当前一句max_tokens1000,)...每次对话的流程:用户输入 →{role: user, content: 输入}加入 messages调用 API,把完整 messages 发过去模型回复 →{role: assistant, content: 回复}也加入 messages下一次调用,messages 里已经带着之前的全部问答这样模型每次都能看到完整上下文,金鱼记忆问题解决。2.3 一张表看清三期演进第 01 期第 02 期第 03 期调用方式单次一问一答while 循环while 循环 历史回灌messages 数组只传当前一句只传当前一句完整对话历史记忆能力无无(故意暴露痛点)有(短临记忆)token 观察无每次 prompt 都很小prompt 随历史增长2.4 本期的组装公式短期记忆 messages[] 回灌 上下文长度限制把历史塞进去,模型就记住了;但历史不能无限长,得加个上限。三、动手做:从金鱼记忆到短期记忆3.1 维护一个 messages 列表用一个 list 在内存里维护对话历史,角色严格按user/assistant交替:messages:list[dict][]# 用户输入messages.append({role:user,content:user_input})# 调用 API(传完整历史)answer,p,cchat(messages)# 模型回复也加回历史messages.append({role:assistant,content:answer})这样下一次调用时,messages 里已经带着之前的全部问答,模型能看到上下文。3.2 上下文长度限制:历史不能无限长历史一直累积,prompt_tokens会越滚越大,最终触发模型的上下文长度上限(DeepSeek 通常 64K token)。本期用最简单的截断策略:MAX_ROUNDS10# 1 轮 1 user 1 assistantdeftrim_history(messages:list[dict])-list[dict]:roundssum(1forminmessagesifm[role]user)ifroundsMAX_ROUNDS:returnmessages excess_roundsrounds-MAX_ROUNDS cutexcess_rounds*2# 每轮 2 条returnmessages[cut:]超过 10 轮时,删掉最早的一轮,保留最近 10 轮。简单粗暴,但有边界。第 07 期会升级为 compact 压缩策略(把旧对话摘要成一段,而非直接删),本期先解决有没有的问题。3.3 reset 和 history 命令reset:清空 messages 列表,重新开始(第 02 期埋的伏笔,这期兑现)history:打印当前 messages 列表,直观看到[user, assistant, user, assistant, ...]的结构这两个命令不是花架子,是帮你调试和理解历史是怎么组织的。3.4 自动演示:对比第 02 期的金鱼记忆程序跑起来会先自动问两个问题(和第 02 期一模一样):“我叫张三,是一名 Python 后端工程师” —— 告诉模型信息“我姓什么?我是做什么工作的?” —— 看它能否接住这次模型应该能答上来——因为 messages 里带着上一轮的问答。同时你会看到第 2 轮的prompt_tokens比第 2 期大,因为历史一起发了过去。四、跑起来:短期记忆的实际体验4.1 为什么回灌历史能让模型记住?模型本身是无状态的,但每次调用都会读到你传入的完整messages。只要历史在 messages 里,模型就能看到之前说过什么。第 1 轮: messages [user: 我叫张三] → 模型回复 你好,张三! messages [user: 我叫张三, assistant: 你好,张三!] 第 2 轮: messages [user: 我叫张三, assistant: 你好,张三!, user: 我姓什么?] → 模型能看到前两条,答 你姓张4.2 token 增长可视化对比第 02 期,本期的prompt_tokens会明显更大,因为历史一起发了过去:轮次第 02 期 prompt_tokens第 03 期 prompt_tokens第 1 轮~10(一句话)~10(一句话)第 2 轮~10(还是一句话)~30(含第 1 轮的问答)第 5 轮~10~150(含前 4 轮)这就是上下文长度问题的由来——历史越多,token 越贵,也越容易触顶。4.3 调用流程(与前两期一致)你的代码 → openai SDK → HTTPS 请求(带完整 messages) → DeepSeek → 推理 → 返回 JSON usage相比第 02 期,唯一的差异是:请求体里的messages从一句话变成了完整历史。五、执行脚本#!/usr/bin/env python3step03_history.py — 第 03 期:短期记忆 history 本期目标: 1. 维护一个 messages 列表,每次调用把完整对话历史回灌进去 2. 让模型真正记住上一句,解决第 02 期的金鱼记忆 3. 引入上下文长度限制,历史不能无限长——超限时做最简单的截断 累积式:step03 step02 messages[] 回灌 上下文长度限制 (尚未做记忆压缩/长期记忆,后续第 07 期解决) 运行: python code/step03_history.py importosfromdotenvimportload_dotenvfromopenaiimportOpenAIfromprompt_toolkitimportpromptfromprompt_toolkit.historyimportInMemoryHistory load_dotenv()# 1. 初始化客户端(与第 01/02 期一致)clientOpenAI(api_keyos.environ[DEEPSEEK_API_KEY],base_urlos.environ.get(DEEPSEEK_BASE_URL,https://api.deepseek.com),)MODELos.environ.get(DEEPSEEK_MODEL,deepseek-chat)# 上下文长度上限(轮数,1 轮 1 user 1 assistant)MAX_ROUNDS10defchat(messages:list[dict])-tuple[str,int,int]:带历史回灌的对话:传入完整 messages 列表,返回 (回答, prompt_tokens, completion_tokens)。responseclient.chat.completions.create(modelMODEL,messagesmessages,max_tokens1000,)answerresponse.choices[0].message.content usageresponse.usagereturnanswer,usage.prompt_tokens,usage.completion_tokensdeftrim_history(messages:list[dict])-list[dict]:上下文长度限制:超过 MAX_ROUNDS 轮时,从最早的一轮开始截断。roundssum(1forminmessagesifm[role]user)ifroundsMAX_ROUNDS:returnmessages excess_roundsrounds-MAX_ROUNDS cutexcess_rounds*2returnmessages[cut:]defmain():print(*60)print(第 03 期:短期记忆 history —— 让模型记住上一句)print(*60)print(f当前模型:{MODEL})print(fAPI 地址:{client.base_url})print(f上下文上限:{MAX_ROUNDS}轮(超出自动截断最早))print(*60)# 2. 自动演示:对比第 02 期的金鱼记忆 demo_questions[我叫张三,是一名 Python 后端工程师,我姓什么?我是做什么工作的?,]print(\n[自动演示] 同样两个问题,这次模型能否记住上一句:\n)messages:list[dict][]fori,qinenumerate(demo_questions,1):print(f[问题{i}]{q})messages.append({role:user,content:q})try:answer,p,cchat(messages)print(f[回答]{answer})print(f[token] prompt{p}completion{c}total{pc})print(f[历史] 当前 messages 共{len(messages)}条)messages.append({role:assistant,content:answer})exceptExceptionase:print(f[出错]{e})returnprint(-*60)print(\n 对比第 02 期:这次模型答上来了——因为 messages 里带着上一轮的问答,模型看到了完整上下文。\n 但注意 prompt_tokens 比第 02 期大,因为历史一起发了过去。\n)# 3. 交互式对话(带历史回灌)print(*60)print(现在进入自由对话(有记忆,但超过 10 轮自动截断最早))print(输入 quit 退出 / 输入 reset 清空历史 / 输入 history 查看历史)print(←/→ 移动光标,↑/↓ 翻历史,Ctrl-C 作废当前行重输)print(*60)total_prompt0total_completion0cli_historyInMemoryHistory()whileTrue:try:user_inputprompt(\n你: ,historycli_history).strip()except(EOFError,KeyboardInterrupt):print( (本行作废,重新输入))continueifuser_input.lower()in(quit,exit,q):print(f\n[本次会话 token 汇总] prompt{total_prompt}fcompletion{total_completion}total{total_prompttotal_completion})print(f[历史] 退出时共{len(messages)}条消息)print(再见!)breakifuser_input.lower()reset:messages.clear()total_prompt0total_completion0print([提示] 历史已清空,重新开始对话。)continueifuser_input.lower()history:print(f[历史] 共{len(messages)}条消息:)foridx,minenumerate(messages):rolem[role]contentm[content][:50](...iflen(m[content])50else)print(f{idx:2d}. [{role:9s}]{content})continueifnotuser_input:continuemessages.append({role:user,content:user_input})messagestrim_history(messages)try:answer,p,cchat(messages)total_promptp total_completionc messages.append({role:assistant,content:answer})print(fAlex:{answer})print(f[token] 本次 prompt{p}completion{c}f累计 total{total_prompttotal_completion})print(f[历史] 当前{len(messages)}条消息f({sum(1forminmessagesifm[role]user)}轮))exceptExceptionase:messages.pop()print(f[出错]{e})if__name____main__:main()六、总结一句话回顾:模型本身无记忆,记忆是你用 messages 列表喂给它的。三个关键动作记牢:维护 messages 列表→ 每轮把 user assistant 都加进去回灌历史→ 调用时传完整 messages,模型就能看到上下文上下文限制→ 历史不能无限长,超限时截断最早(下期升级为压缩)一行代码记住本期:messages.append({role:assistant,content:answer})# ← 回复也加回历史把模型回复也加入 messages,下一轮调用时它就记住了。适用场景:这篇适合刚跑通第 02 期、想让模型真正记住对话的人。下一期预告:第 04 期——System Prompt 人设。我们用templates/SOUL.md给 Agent 设定技术助理 Alex的角色,对比有无 system prompt 时的行为差异。同时 system prompt 会成为 messages 列表的第一条,进一步影响上下文。感谢各位看官的一路陪伴,大家都再接再厉!

相关新闻

【LangChain实战】彻底搞懂 Runnable 与 LCEL:从基础单链到 RAG 复杂管道

【LangChain实战】彻底搞懂 Runnable 与 LCEL:从基础单链到 RAG 复杂管道

在构建基于大语言模型(LLM)的应用时,我们经常需要处理 Prompt 模板、Chat Model、Output Parser 以及 Retriever 等核心组件。如果每次都通过手动一步步调用这些组件,代码不仅啰嗦,还难以维护和复用。为了解决这个问题…

2026/8/4 10:33:30 阅读更多 →
A05 | 硬件安全指标体系:PMHF、SPFM、LFM 三大指标的本质与计算

A05 | 硬件安全指标体系:PMHF、SPFM、LFM 三大指标的本质与计算

1. 开篇——一个数字决定的命运2020 年,某国内 Tier 1 供应商的制动 ECU 项目进入最终评审阶段。硬件设计团队信心满满——原理图评审通过、EMC 测试通过、环境可靠性测试通过。然而在功能安全评审会上,一个数字像一盆冷水浇下来:PMHF 计算结…

2026/8/4 5:35:21 阅读更多 →
NVIDIA Skills:Jetson平台AI应用快速原型开发实战指南

NVIDIA Skills:Jetson平台AI应用快速原型开发实战指南

1. 从“想法”到“原型”的加速器:为什么是NVIDIA Skills?在嵌入式AI和边缘计算领域,Jetson系列开发板以其强大的GPU算力和紧凑的形态,成为了机器人、无人机、智能相机等众多创新项目的核心大脑。然而,对于很多开发者&…

2026/8/2 3:25:43 阅读更多 →

最新新闻

从“听人说”到“自己验”:一套珠宝玉石选品的可验证框架

从“听人说”到“自己验”:一套珠宝玉石选品的可验证框架

0x00 场景:一次典型的“信息不对称”决策 去年想给妈妈买只玉镯。网上刷到某“大师款”——直播画面里灯光打得恰到好处,主播手持强光手电对着镯子照得满屏翠绿,喊着“收藏级”。冲动下单,到手发现颜色发闷,证书上的检…

2026/8/4 12:39:24 阅读更多 →
如何在Apple Silicon Mac上运行iOS游戏:PlayCover完整指南

如何在Apple Silicon Mac上运行iOS游戏:PlayCover完整指南

如何在Apple Silicon Mac上运行iOS游戏:PlayCover完整指南 【免费下载链接】PlayCover Community fork of PlayCover 项目地址: https://gitcode.com/gh_mirrors/pl/PlayCover 想在M1/M2 Mac上畅玩《原神》《崩坏:星穹铁道》等热门iOS游戏吗&…

2026/8/4 12:39:24 阅读更多 →
商用密码安全评估题库解析与SM4算法考点精讲

商用密码安全评估题库解析与SM4算法考点精讲

1. 项目背景与行业需求 商用密码应用安全性评估作为信息安全领域的重要分支,近年来随着相关法规政策的密集出台,正在经历快速发展的阶段。2020年1月实施的《密码法》明确规定了商用密码应用安全性评估的法律地位,将其作为关键信息基础设施安全…

2026/8/4 12:39:24 阅读更多 →
从音乐囚徒到自由播放:3步解锁网易云NCM加密格式终极指南

从音乐囚徒到自由播放:3步解锁网易云NCM加密格式终极指南

从音乐囚徒到自由播放:3步解锁网易云NCM加密格式终极指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的歌曲只能在特定App播放而烦恼吗?你是否遇到过想把心爱的音乐传到车载音响或分…

2026/8/4 12:39:23 阅读更多 →
基于SpringBoot的B2C商城系统设计与实现

基于SpringBoot的B2C商城系统设计与实现

1. 项目概述 这个基于JavaSpringBoot的商城管理系统是一个典型的B2C电子商务平台实现方案,特别适合计算机相关专业毕业生作为毕业设计选题。我去年指导过三个类似项目,发现这种电商系统既能体现全栈开发能力,又不会过于复杂导致无法完成。 系…

2026/8/4 12:39:23 阅读更多 →
告别网盘限速困扰:9大主流平台直链下载全攻略

告别网盘限速困扰:9大主流平台直链下载全攻略

告别网盘限速困扰:9大主流平台直链下载全攻略 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅…

2026/8/4 12:38:23 阅读更多 →

日新闻

AI Agent白手起家26: 使用标准事件驱动大模型实践

AI Agent白手起家26: 使用标准事件驱动大模型实践

纲要 练习目标:掌握大模型标准事件的调用回顾 LangChain 中的核心标准事件 invokestreambatchastream_eventswith_structured_output 环境准备实战代码:多种事件调用对比 同步调用与流式输出批量处理异步事件流监听结构化输出 运行说明与预期结果总结与扩…

2026/8/4 0:00:40 阅读更多 →
dealsea是什么?跨境卖家必知的美国deal站入门指南

dealsea是什么?跨境卖家必知的美国deal站入门指南

说实话,第一次听说美国这个老牌折扣网站的跨境卖家,十个有八个会问同一个问题:这个平台到底是干嘛的?我见过一个做家居出口的朋友,他在亚马逊上月销二十万美金,却从来没用过它。我给他看了首页——一屏一屏…

2026/8/4 0:01:40 阅读更多 →
清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

通讯作者:邓兵、刘建国通讯单位:清华大学DOI:https://doi.org/10.1021/acs.est.6c00603研究背景稀土元素(REEs)是清洁能源技术与电子器件不可或缺的核心原料,然而传统提取方式依赖能耗高、排放大的采矿与强…

2026/8/4 0:01:40 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/4 11:41:39 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/4 5:26:40 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/3 13:07:03 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/3 8:27:36 阅读更多 →