热门搜索:和平精英 原神 街篮2 

您的位置:首页 > > 教程攻略 > ai教程 >Day 4:让 Agent 记住你——短期记忆实现

Day 4:让 Agent 记住你——短期记忆实现

来源:互联网 更新时间:2026-06-09 07:26

Day 4:让 Agent 记住你——短期记忆实现

做了3天,你的Agent现在面临一个很尴尬的问题。 你告诉它:“我叫小明,我想了解Python。” 然后你问:“刚才我说我叫什么来着?” 它不知道。 因为它天生失忆。

为什么AI天生失忆

每次你调用OpenAI API,对AI来说都是一个全新的请求。 上一次调用发生了什么?它不知道。 API本身是无状态的,就像HTTP请求一样,每一次都是独立的。 那ChatGPT是怎么做到记住你之前说的话的? 本质很简单:它是在每次API请求时,把所有历史消息都重新带进去。 发给API的不只是你这次说的话,而是: ``` [你第1次说的话][AI第1次回答][你第2次说的话][AI第2次回答][你第3次说的话]←当前问题 ``` 这一长串消息全部塞进请求,AI就能“看到”之前发生了什么,就好像它记得一样。 记忆的本质:把历史消息带进每次请求。

短期记忆实现

新建 `memory/short_term.py`: ``` # memory/short_term.py from dataclasses import dataclass, field from typing import Literal MessageRole = Literal["system", "user", "assistant"] @dataclass class Message: role: MessageRole content: str @dataclass class ShortTermMemory: """保存对话历史,控制上限。system消息永远保留;超出上限时删除最旧的非system消息。""" max_messages: int = 20 _messages: list[Message] = field(default_factory=list) def add(self, role: MessageRole, content: str) -> None: self._messages.append(Message(role=role, content=content)) self._trim() def _trim(self) -> None: """超过上限时,删除最旧的非system消息。""" non_system = [m for m in self._messages if m.role != "system"] while len(non_system) > self.max_messages: for i, msg in enumerate(self._messages): if msg.role != "system": self._messages.pop(i) break non_system = [m for m in self._messages if m.role != "system"] def to_api_format(self) -> list[dict]: """转成OpenAI API需要的格式。""" return [{"role": m.role, "content": m.content} for m in self._messages] def clear_non_system(self) -> None: """清除对话历史(保留系统提示)。""" self._messages = [m for m in self._messages if m.role == "system"] def count(self) -> int: return len([m for m in self._messages if m.role != "system"]) ```

把记忆接入Agent

把 `agent.py` 里的函数改成一个类: ``` # agent.py import json import re from llm import chat from tool_registry import get_tools_description, execute_tool from memory.short_term import ShortTermMemory SYSTEM_PROMPT_TEMPLATE = """你是一个智能助手,可以使用工具,也能记住对话历史。 {tools_description} 每次回复必须是JSON,格式二选一: 使用工具:{{"action": "use_tool", "tool": "工具名", "params": {{"参数名": "参数值"}}}} 直接回答:{{"action": "answer", "content": "你的回答"}} 只返回JSON。""" def safe_parse_json(text: str) -> dict: try: return json.loads(text) except json.JSONDecodeError: pass match = re.search(r'{.*}', text, re.DOTALL) if match: try: return json.loads(match.group()) except json.JSONDecodeError: pass return {"action": "answer", "content": text} class Agent: def __init__(self) -> None: self.memory = ShortTermMemory(max_messages=20) # 系统提示只加一次,永远保留 self.memory.add("system", SYSTEM_PROMPT_TEMPLATE.format(tools_description=get_tools_description())) def chat(self, user_input: str) -> str: # 把用户消息存入记忆 self.memory.add("user", user_input) # 带上完整历史调用AI ai_response = chat(self.memory.to_api_format()) print(f"[AI决策]: {ai_response}") # 把AI回复也存入记忆 self.memory.add("assistant", ai_response) decision = safe_parse_json(ai_response) if decision["action"] == "answer": return decision.get("content", ai_response) if decision["action"] == "use_tool": tool_name = decision.get("tool", "") params = decision.get("params", {}) print(f"[执行工具]: {tool_name},参数:{params}") tool_result = execute_tool(tool_name, params) print(f"[工具结果]: {tool_result}") # 把工具结果存入记忆,让AI基于结果给出最终答案 self.memory.add("user", f"[工具 {tool_name} 返回结果]:{tool_result}\n请基于此结果,用自然语言回答用户的问题。") final = chat(self.memory.to_api_format()) final_parsed = safe_parse_json(final) final_text = final_parsed.get("content", final) self.memory.add("assistant", final_text) return final_text return f"(未知action:{decision.get('action')})" def clear(self) -> None: self.memory.clear_non_system() ``` 为什么要改成类? 因为现在Agent有了状态(记忆)。有状态的东西,用类来管理比用函数更自然。`self.memory` 跟着实例存在,跨多次 `chat()` 调用保持。

更新main.py

``` # main.py from agent import Agent def main() -> None: print("=== Day 4 Agent:有记忆了!===") print("命令:/clear 清除记忆 | quit 退出\n") agent = Agent() while True: user_input = input("你:").strip() if not user_input: continue if user_input.lower() in ("quit", "exit"): print("再见!") break if user_input.lower() == "/clear": agent.clear() print("记忆已清除,开始新对话。\n") continue result = agent.chat(user_input) print(f"Agent:{result}") print(f"(当前记忆:{agent.memory.count()} 条消息)\n") if __name__ == "__main__": main() ```

效果演示

``` 你:我叫小明,我在学Python Agent:你好小明!Python是一门很棒的编程语言... (当前记忆:2 条消息) 你:刚才我说我叫什么名字? Agent:你说你叫小明,并且正在学习Python。 (当前记忆:4 条消息) 你:/clear 记忆已清除,开始新对话。 你:我叫什么名字? Agent:您还没有告诉我您的名字。 (当前记忆:2 条消息) ```

为什么需要max_messages上限

每条消息都占用token(AI的“计费单位”)。 对话越长,每次请求携带的token越多,两个后果: 1. 费用增加(按token计费) 2. 超过模型上限会报错(gpt-4o-mini上限128K token,很难超,但别的模型可能更小) `max_messages=20` 是个合理默认值。超过就自动删最旧的消息。 System消息为什么永远保留? System消息里有工具说明和行为规范。如果被删掉,AI就不知道有哪些工具可以用了。所以删消息时跳过system。

一个常见误解

有人以为“记忆”是AI把对话内容“学进去了”。 不是的。 每次对话结束,这些消息就消失了。下次新建一个 `Agent()` 对象,记忆是空的。 这叫短期记忆(Session Memory)——只在当前会话里有效。 如果你想让记忆跨会话持久化(比如第二天还记得你上次说的话),需要把消息存到文件或数据库,这是长期记忆,是更进阶的话题。

今天的项目结构

``` my_agent/ ├── .env ├── llm.py ├── agent.py # 重构成Agent类,集成记忆 ├── tool_registry.py ├── memory/ │ ├── __init__.py │ └── short_term.py # 新增:短期记忆 ├── tools/ │ ├── __init__.py │ ├── search.py │ ├── weather.py │ ├── calculator.py │ └── datetime_tool.py └── main.py ```

小结

今天做了一件看起来简单但非常重要的事: 让AI “记住”对话历史,本质是把历史消息带进每次API请求。 这是所有对话型AI应用的基础机制,包括ChatGPT本身。 `ShortTermMemory` 这个类,你在LangChain里会看到对应的 `ConversationBufferMemory`,在OpenAI Assistants API里会看到 `thread`——都是同一个思路,只是封装程度不同。 明天,Day 5:《Agent Loop——整个系列里最关键的一天》 Agent真正的力量,在于它能反复思考、反复使用工具,直到任务完成。 这就是ReAct模式。明天讲。 *代码在GitHub,文末有链接。*

热门手游

手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc