19-day5-对比 有记忆 vs 无记忆
🧪 对比:有记忆 vs 无记忆
两个脚本:
agent_without_memory.py:每次对话都“失忆”agent_with_memory.py:记住之前的对话(即你已有的程序)
第一步:准备两个脚本
✅ 脚本1:无记忆版(agent_without_memory.py)
# agent_without_memory.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
load_dotenv()
llm = ChatOpenAI(
model="qwen-max",
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0.7
)
# 注意:这里没有 MessagesPlaceholder,也没有历史
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个 AI 助手。"),
("human", "{input}")
])
chain = prompt | llm
if __name__ == "__main__":
print("🤖 无记忆 Agent 启动!输入 'quit' 退出。\n")
while True:
user_input = input("👤 你: ")
if user_input.strip().lower() == "quit":
break
response = chain.invoke({"input": user_input})
print(f"🤖 Agent: {response.content}\n")
🔍 关键点:每次只传当前问题,不带历史 → 模型不知道之前聊过什么。
✅ 脚本2:有记忆版(agent_with_memory.py)
就是你已经写好的那个(确保包含 .env 和依赖)。为方便对比,这里再精简确认一下核心逻辑:
# agent_with_memory.py(简化确认版)
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
load_dotenv()
llm = ChatOpenAI(
model="qwen-max",
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0.7
)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有记忆的 AI 助手。请记住用户之前说过的话。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | llm
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
with_message_history = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="input",
history_messages_key="history",
)
if __name__ == "__main__":
print("🤖 有记忆 Agent 启动!输入 'quit' 退出。\n")
while True:
user_input = input("👤 你: ")
if user_input.strip().lower() == "quit":
break
response = with_message_history.invoke(
{"input": user_input},
config={"configurable": {"session_id": "test123"}}
)
print(f"🤖 Agent: {response.content}\n")
第二步:运行对比测试
在终端中分别运行两个程序,用相同的对话流程测试:
🔹 测试流程(对两个 Agent 都执行):
- 输入:
我叫李明 - 输入:
我叫什么名字? - 输入:
刚刚我说了什么?
第三步:对比
| 步骤 | 无记忆 Agent (agent_without_memory.py) |
有记忆 Agent (agent_with_memory.py) |
|---|---|---|
| 1. 我叫李明 | 👉 回复:“你好!” 或 “知道了。”(但不会记住) | 👉 回复:“你好,李明!” |
| 2. 我叫什么名字? | ❌ 回复:“我不知道你的名字。”或瞎猜:“你没告诉我。” | ✅ 回复:“你叫李明。” |
| 3. 刚刚我说了什么? | ❌ 回复:“我不记得了。”或胡说八道 | ✅ 回复:“你刚刚说你叫李明。” |
💡 这就是上下文缺失 vs 上下文完整的直接体现!
第四步:讨论点
-
为什么无记忆版答不上来?
→ 因为它每次只看到当前一句话,像一个“金鱼记忆”的人。 -
有记忆版是怎么做到的?
→ 它把之前的对话拼在新问题前面,一起发给大模型,相当于“复习聊天记录”。 -
这种记忆是永久的吗?
→ 不是!程序一关,内存清空,记忆就没了(除非用数据库保存)。 -
有没有代价?
→ 有!对话越长,发送的文本越多,消耗的 token 越多,速度变慢,费用增加。
✅ 小结
| 特性 | 无记忆 Agent | 有记忆 Agent |
|---|---|---|
| 实现复杂度 | 简单 | 中等 |
| 对话连贯性 | 差 | 好 |
| 适用场景 | 单次问答(如查天气) | 多轮对话(如客服、助手) |
| Token 消耗 | 低 | 随对话指数级增长 |
浙公网安备 33010602011771号