05_记忆管理 - 让AI记住对话历史
本课程解决AI”健忘”的问题,教你使用LangChain的记忆系统让AI记住对话历史。你将学习四种记忆类型(缓冲、窗口、摘要、组合)的特点和应用场景,掌握如何在多用户场景下管理独立记忆,理解记忆与Token消耗的平衡。通过实战练习,构建具有连贯对话能力的聊天机器人。
🎯 学习目标
- 理解为什么AI需要记忆
 - 掌握不同类型的记忆机制
 - 学会在应用中集成记忆功能
 - 构建有记忆的聊天机器人
 
📖 核心概念
为什么需要记忆?
问题:AI没有记忆
1  | # 第一次对话  | 
生活类比:失忆的朋友
想象你和一个朋友聊天,但他每次都忘记之前说的话:
1  | 你:"我最喜欢吃pizza"  | 
AI的记忆系统
LangChain提供多种记忆类型:
1  | 1. 对话缓冲记忆 (ConversationBufferMemory)  | 
记忆的工作原理
1  | 用户输入  | 
💻 代码示例
参见各个示例文件:
01_buffer_memory.py- 对话缓冲记忆1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144"""
对话缓冲记忆
演示:完整记录所有对话历史
"""
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
def example1_basic_memory() -> None:
"""示例1:基础记忆使用"""
print("=== 示例1:基础对话记忆 ===\n")
# 创建记忆
memory = ConversationBufferMemory()
# 手动保存对话
memory.save_context(
{"input": "我叫张三"},
{"output": "你好张三!很高兴认识你。"}
)
memory.save_context(
{"input": "我今年25岁"},
{"output": "知道了,你今年25岁。"}
)
# 查看记忆
print("💭 记忆内容:")
print(memory.load_memory_variables({}))
print()
def example2_with_llm() -> None:
"""示例2:配合LLM使用记忆"""
print("=== 示例2:带记忆的对话 ===\n")
llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
# 创建记忆
memory = ConversationBufferMemory()
# 创建对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True # 显示详细过程
)
# 多轮对话
print("👤 用户:我叫李明")
response1 = conversation.predict(input="我叫李明")
print(f"🤖 AI:{response1}\n")
print("👤 用户:我喜欢编程")
response2 = conversation.predict(input="我喜欢编程")
print(f"🤖 AI:{response2}\n")
print("👤 用户:我叫什么名字?我有什么爱好?")
response3 = conversation.predict(input="我叫什么名字?我有什么爱好?")
print(f"🤖 AI:{response3}\n")
# 查看完整历史
print("📜 完整对话历史:")
print(memory.load_memory_variables({}))
def example3_memory_inspection() -> None:
"""示例3:检查记忆内容"""
print("\n=== 示例3:检查记忆 ===\n")
memory = ConversationBufferMemory()
# 添加几轮对话
conversations = [
("Python是什么?", "Python是一种编程语言"),
("它有什么特点?", "Python简洁易读,功能强大"),
("适合初学者吗?", "非常适合,语法简单")
]
for user_msg, ai_msg in conversations:
memory.save_context({"input": user_msg}, {"output": ai_msg})
# 查看记忆统计
history = memory.load_memory_variables({})
print(f"总对话轮数:{len(conversations)}")
print(f"\n历史记录:\n{history['history']}\n")
# 查看消息对象
print("消息列表:")
for msg in memory.chat_memory.messages:
print(f" {msg.__class__.__name__}: {msg.content}")
def example4_custom_keys() -> None:
"""示例4:自定义记忆键"""
print("\n=== 示例4:自定义键名 ===\n")
# 使用自定义键名
memory = ConversationBufferMemory(
memory_key="chat_history", # 历史记录的键名
input_key="user_input", # 用户输入的键名
output_key="ai_response", # AI输出的键名
return_messages=True # 返回消息对象而不是字符串
)
memory.save_context(
{"user_input": "你好"},
{"ai_response": "你好!有什么可以帮你的?"}
)
# 查看
variables = memory.load_memory_variables({})
print(f"键名:{list(variables.keys())}")
print(f"消息类型:{type(variables['chat_history'][0])}")
print(f"内容:{variables}")
def main() -> None:
"""主函数"""
example1_basic_memory()
print("\n" + "="*60 + "\n")
example2_with_llm()
print("\n" + "="*60 + "\n")
example3_memory_inspection()
print("\n" + "="*60 + "\n")
example4_custom_keys()
if __name__ == "__main__":
main()02_window_memory.py- 对话窗口记忆1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377"""
对话窗口记忆
演示:只保留最近N轮对话,控制Token消耗
"""
from langchain.memory import ConversationBufferWindowMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
def example1_basic_window_memory() -> None:
"""示例1:基础窗口记忆"""
print("=== 示例1:窗口记忆基础用法 ===\n")
# 创建窗口记忆,只保留最近3轮对话
memory = ConversationBufferWindowMemory(k=3)
# 手动添加对话
conversations = [
("我叫张三", "你好张三!"),
("我今年25岁", "知道了,你今年25岁"),
("我是程序员", "明白,你是程序员"),
("我喜欢Python", "很好,Python是很棒的语言"),
("我住在北京", "了解,你住在北京"),
]
for i, (user_msg, ai_msg) in enumerate(conversations, 1):
memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
print(f"第{i}轮对话后的记忆:")
history = memory.load_memory_variables({})
print(history["history"])
print("\n" + "-"*50 + "\n")
def example2_window_vs_buffer() -> None:
"""示例2:窗口记忆 vs 缓冲记忆对比"""
print("=== 示例2:窗口记忆 vs 缓冲记忆 ===\n")
from langchain.memory import ConversationBufferMemory
# 创建两种记忆
buffer_memory = ConversationBufferMemory()
window_memory = ConversationBufferWindowMemory(k=2)
# 添加5轮对话
conversations = [
("第1个问题", "第1个回答"),
("第2个问题", "第2个回答"),
("第3个问题", "第3个回答"),
("第4个问题", "第4个回答"),
("第5个问题", "第5个回答"),
]
for user_msg, ai_msg in conversations:
buffer_memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
window_memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
# 对比结果
print("📦 缓冲记忆(保留全部):")
buffer_history = buffer_memory.load_memory_variables({})
print(buffer_history["history"])
print()
print("🪟 窗口记忆(只保留最近2轮):")
window_history = window_memory.load_memory_variables({})
print(window_history["history"])
print()
# 统计消息数量
buffer_count = len(buffer_memory.chat_memory.messages)
window_count = len(window_memory.chat_memory.messages)
print(f"📊 统计:")
print(f" 缓冲记忆:{buffer_count}条消息")
print(f" 窗口记忆:{window_count}条消息")
print(f" 节省:{buffer_count - window_count}条消息")
def example3_with_chatbot() -> None:
"""示例3:窗口记忆配合聊天机器人"""
print("\n=== 示例3:带窗口记忆的聊天机器人 ===\n")
llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
# 创建窗口记忆,只保留最近3轮
memory = ConversationBufferWindowMemory(k=3)
# 创建对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=False
)
# 模拟多轮对话
questions = [
"你好,我叫李明",
"我今年30岁",
"我是软件工程师",
"我喜欢打篮球",
"我住在上海",
"我叫什么名字?", # 测试:超出窗口范围
"我多大了?", # 测试:在窗口范围内
"我喜欢什么运动?", # 测试:在窗口范围内
]
for i, question in enumerate(questions, 1):
print(f"第{i}轮对话")
print(f"👤 用户:{question}")
response = conversation.predict(input=question)
print(f"🤖 AI:{response}")
# 显示当前记忆状态
current_memory = memory.load_memory_variables({})
message_count = len(memory.chat_memory.messages)
print(f"📊 当前记忆:{message_count//2}轮对话")
print()
def example4_dynamic_window_size() -> None:
"""示例4:动态调整窗口大小"""
print("\n=== 示例4:动态窗口大小 ===\n")
llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
class DynamicWindowMemory:
"""动态窗口记忆管理器"""
def __init__(self, min_k: int = 2, max_k: int = 10):
self.min_k = min_k
self.max_k = max_k
self.current_k = min_k
self.memory = ConversationBufferWindowMemory(k=self.current_k)
def adjust_window_size(self, message_importance: str) -> None:
"""根据消息重要性调整窗口大小"""
if message_importance == "high" and self.current_k < self.max_k:
self.current_k += 1
print(f"📈 窗口扩大到 {self.current_k} 轮")
elif message_importance == "low" and self.current_k > self.min_k:
self.current_k -= 1
print(f"📉 窗口缩小到 {self.current_k} 轮")
# 重新创建记忆(保留现有消息)
old_messages = self.memory.chat_memory.messages
self.memory = ConversationBufferWindowMemory(k=self.current_k)
for msg in old_messages:
self.memory.chat_memory.add_message(msg)
def save_context(self, inputs: dict, outputs: dict, importance: str = "normal") -> None:
"""保存对话并调整窗口"""
self.memory.save_context(inputs, outputs)
self.adjust_window_size(importance)
# 测试
dynamic_memory = DynamicWindowMemory(min_k=2, max_k=5)
conversations = [
("你好", "你好!", "normal"),
("今天天气怎么样", "今天天气不错", "low"),
("帮我分析一下这份重要合同", "好的,我来分析...", "high"),
("合同第三条款有什么风险", "第三条款...", "high"),
("谢谢", "不客气", "low"),
]
for i, (user_msg, ai_msg, importance) in enumerate(conversations, 1):
print(f"\n第{i}轮:{user_msg} (重要性: {importance})")
dynamic_memory.save_context(
{"input": user_msg},
{"output": ai_msg},
importance
)
def example5_multi_user_window() -> None:
"""示例5:多用户窗口记忆管理"""
print("\n\n=== 示例5:多用户窗口记忆管理 ===\n")
from typing import Dict
class MultiUserWindowMemory:
"""多用户窗口记忆管理器"""
def __init__(self, default_k: int = 3):
self.default_k = default_k
self.memories: Dict[str, ConversationBufferWindowMemory] = {}
def get_memory(self, user_id: str, k: int = None) -> ConversationBufferWindowMemory:
"""获取用户的记忆"""
if user_id not in self.memories:
window_size = k if k else self.default_k
self.memories[user_id] = ConversationBufferWindowMemory(
k=window_size)
print(f"✨ 为用户 {user_id} 创建新记忆(窗口大小:{window_size})")
return self.memories[user_id]
def save_conversation(self, user_id: str, user_msg: str, ai_msg: str) -> None:
"""保存对话"""
memory = self.get_memory(user_id)
memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
def get_history(self, user_id: str) -> str:
"""获取对话历史"""
if user_id not in self.memories:
return "(无历史记录)"
memory = self.memories[user_id]
history = memory.load_memory_variables({})
return history["history"]
def get_stats(self) -> dict:
"""获取统计信息"""
return {
"total_users": len(self.memories),
"users": list(self.memories.keys())
}
# 测试多用户场景
manager = MultiUserWindowMemory(default_k=2)
# 用户A的对话
print("👤 用户A的对话:")
manager.save_conversation("user_A", "我叫Alice", "你好Alice!")
manager.save_conversation("user_A", "我是学生", "知道了")
manager.save_conversation("user_A", "我学计算机", "很好的专业")
print(f"用户A的历史:\n{manager.get_history('user_A')}\n")
# 用户B的对话
print("👤 用户B的对话:")
manager.save_conversation("user_B", "我是Bob", "你好Bob!")
manager.save_conversation("user_B", "我是工程师", "很高兴认识你")
print(f"用户B的历史:\n{manager.get_history('user_B')}\n")
# 统计信息
stats = manager.get_stats()
print(f"📊 系统统计:")
print(f" 总用户数:{stats['total_users']}")
print(f" 用户列表:{', '.join(stats['users'])}")
def example6_window_with_important_messages() -> None:
"""示例6:保留重要消息的窗口记忆"""
print("\n\n=== 示例6:智能窗口记忆(保留重要信息)===\n")
class SmartWindowMemory:
"""智能窗口记忆:自动保留重要信息"""
def __init__(self, k: int = 3):
self.k = k
self.memory = ConversationBufferWindowMemory(k=k)
self.important_messages = [] # 保留重要信息
def save_context(self, inputs: dict, outputs: dict, is_important: bool = False) -> None:
"""保存对话"""
# 保存到常规记忆
self.memory.save_context(inputs, outputs)
# 如果是重要信息,单独保存
if is_important:
self.important_messages.append({
"user": inputs["input"],
"ai": outputs["output"]
})
print(f"⭐ 标记为重要信息")
def get_context(self) -> str:
"""获取完整上下文(包括重要信息)"""
# 获取窗口记忆
recent = self.memory.load_memory_variables({})["history"]
# 添加重要信息
if self.important_messages:
important_context = "\n重要信息回顾:\n"
for msg in self.important_messages[-3:]: # 最多保留3条
important_context += f"- {msg['user']}: {msg['ai']}\n"
return important_context + "\n最近对话:\n" + recent
return recent
# 测试
smart_memory = SmartWindowMemory(k=2)
print("对话序列:\n")
# 对话1:重要 - 用户信息
print("1. 👤 我叫张伟,是产品经理")
smart_memory.save_context(
{"input": "我叫张伟,是产品经理"},
{"output": "你好张伟,很高兴认识你"},
is_important=True
)
# 对话2:普通
print("2. 👤 今天天气不错")
smart_memory.save_context(
{"input": "今天天气不错"},
{"output": "是的,很好的天气"}
)
# 对话3:普通
print("3. 👤 你喜欢什么颜色")
smart_memory.save_context(
{"input": "你喜欢什么颜色"},
{"output": "我喜欢蓝色"}
)
# 对话4:重要 - 业务信息
print("4. 👤 我们的产品订单号是ORD12345")
smart_memory.save_context(
{"input": "我们的产品订单号是ORD12345"},
{"output": "好的,我记下了订单号"},
is_important=True
)
# 对话5:普通
print("5. 👤 现在几点了")
smart_memory.save_context(
{"input": "现在几点了"},
{"output": "现在是下午3点"}
)
print("\n" + "="*60)
print("\n📝 当前上下文(包含重要信息):")
print(smart_memory.get_context())
def main() -> None:
"""主函数"""
example1_basic_window_memory()
print("\n" + "="*70 + "\n")
example2_window_vs_buffer()
print("\n" + "="*70 + "\n")
example3_with_chatbot()
print("\n" + "="*70 + "\n")
example4_dynamic_window_size()
print("\n" + "="*70 + "\n")
example5_multi_user_window()
print("\n" + "="*70 + "\n")
example6_window_with_important_messages()
if __name__ == "__main__":
main()03_summary_memory.py- 对话摘要记忆1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330"""
对话摘要记忆
演示:使用AI总结对话历史,节省Token
"""
from langchain.memory import ConversationSummaryMemory, ConversationSummaryBufferMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
def create_llm() -> ChatOpenAI:
"""创建LLM实例"""
return ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
def example1_basic_summary_memory() -> None:
"""示例1:基础摘要记忆"""
print("=== 示例1:摘要记忆基础 ===\n")
llm = create_llm()
# 创建摘要记忆
memory = ConversationSummaryMemory(llm=llm)
# 添加多轮对话
conversations = [
("我叫张三", "你好张三!"),
("我今年28岁", "知道了,你28岁"),
("我在一家科技公司工作", "很好的工作"),
("我负责产品设计", "产品设计是很重要的岗位"),
("我喜欢旅行和摄影", "很棒的爱好"),
]
print("添加对话中...\n")
for user_msg, ai_msg in conversations:
print(f"👤 {user_msg}")
print(f"🤖 {ai_msg}")
memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
print("\n" + "="*60)
print("\n📝 对话摘要:")
summary = memory.load_memory_variables({})
print(summary["history"])
print()
def example2_summary_vs_buffer() -> None:
"""示例2:摘要记忆 vs 缓冲记忆对比"""
print("\n=== 示例2:摘要记忆 vs 缓冲记忆 ===\n")
from langchain.memory import ConversationBufferMemory
llm = create_llm()
# 创建两种记忆
buffer_memory = ConversationBufferMemory()
summary_memory = ConversationSummaryMemory(llm=llm)
# 添加长对话
conversations = [
("早上好!", "早上好!"),
("我想咨询一下你们的产品", "当然,请问有什么可以帮您的?"),
("我对你们的旗舰产品感兴趣", "太好了,我为您介绍一下"),
("这个产品的主要功能是什么?", "主要功能包括A、B、C三个方面"),
("价格是多少?", "标准版价格是999元"),
("有优惠活动吗?", "目前有新用户8折优惠"),
("那我要购买标准版", "好的,我帮您下单"),
("什么时候能发货?", "我们会在24小时内发货"),
]
for user_msg, ai_msg in conversations:
buffer_memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
summary_memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
print("📦 缓冲记忆(完整对话):")
buffer_history = buffer_memory.load_memory_variables({})
print(buffer_history["history"])
buffer_length = len(buffer_history["history"])
print(f"\n长度:{buffer_length}个字符\n")
print("="*60 + "\n")
print("📄 摘要记忆(总结版):")
summary_history = summary_memory.load_memory_variables({})
print(summary_history["history"])
summary_length = len(summary_history["history"])
print(f"\n长度:{summary_length}个字符")
print(
f"节省:{buffer_length - summary_length}个字符 ({(1-summary_length/buffer_length)*100:.1f}%)")
def example3_summary_buffer_memory() -> None:
"""示例3:摘要缓冲记忆(最佳实践)"""
print("\n\n=== 示例3:摘要缓冲记忆 ===\n")
llm = create_llm()
# 创建摘要缓冲记忆
# 保留最近的消息作为缓冲,旧消息自动总结
memory = ConversationSummaryBufferMemory(
llm=llm,
max_token_limit=100 # 超过100个token就开始总结
)
# 创建对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=False
)
# 长对话
questions = [
"你好,我想了解一下编程",
"Python适合初学者吗?",
"Python有哪些主要应用领域?",
"我应该先学习哪些基础知识?",
"有什么好的学习资源推荐吗?",
"学习Python大概需要多长时间?",
"刚才你说Python适合初学者,能详细说说为什么吗?", # 测试:能否记住早期内容
]
for i, question in enumerate(questions, 1):
print(f"\n第{i}轮对话")
print(f"👤 用户:{question}")
response = conversation.predict(input=question)
print(f"🤖 AI:{response[:100]}...")
# 显示记忆状态
print(f"\n📊 当前记忆状态:")
memory_vars = memory.load_memory_variables({})
print(f" 记忆内容:{memory_vars['history'][:150]}...")
def example4_custom_summary_prompt() -> None:
"""示例4:自定义摘要提示词"""
print("\n\n=== 示例4:自定义摘要风格 ===\n")
from langchain.prompts import PromptTemplate
llm = create_llm()
# 自定义摘要提示词
summary_prompt = PromptTemplate(
input_variables=["summary", "new_lines"],
template="""
请用简洁的要点形式总结对话。
已有摘要:
{summary}
新对话内容:
{new_lines}
更新后的摘要(使用要点形式):
"""
)
# 创建带自定义提示词的摘要记忆
memory = ConversationSummaryMemory(
llm=llm,
prompt=summary_prompt
)
# 添加对话
conversations = [
("我是一名产品经理", "你好!"),
("我负责一款教育类APP", "听起来很有意义"),
("我们的用户主要是中小学生", "明白了"),
("最近在规划新功能", "有什么想法吗?"),
("想增加AI辅导功能", "很好的想法"),
]
for user_msg, ai_msg in conversations:
memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
print("📝 自定义风格的摘要:")
summary = memory.load_memory_variables({})
print(summary["history"])
def example5_incremental_summary() -> None:
"""示例5:增量摘要(观察摘要如何演化)"""
print("\n\n=== 示例5:观察摘要的演化过程 ===\n")
llm = create_llm()
memory = ConversationSummaryMemory(llm=llm)
conversations = [
("我是李华,来自北京", "你好李华!"),
("我在一家互联网公司工作", "很好"),
("我的职位是数据分析师", "了解了"),
("我主要负责用户行为分析", "这是重要的工作"),
("我们团队有10个人", "不小的团队"),
("我们最近在做一个新项目", "什么项目?"),
("是关于推荐系统优化的", "听起来很有挑战"),
("我们使用机器学习算法", "很前沿的技术"),
]
for i, (user_msg, ai_msg) in enumerate(conversations, 1):
print(f"\n第{i}轮对话:")
print(f"👤 {user_msg}")
print(f"🤖 {ai_msg}")
memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
# 显示当前摘要
if i % 3 == 0: # 每3轮显示一次摘要
summary = memory.load_memory_variables({})
print(f"\n📄 摘要(第{i}轮后):")
print(summary["history"])
print("="*60)
def example6_memory_management() -> None:
"""示例6:记忆管理策略"""
print("\n\n=== 示例6:智能记忆管理 ===\n")
llm = create_llm()
class SmartMemoryManager:
"""智能记忆管理器"""
def __init__(self, llm):
self.llm = llm
self.summary_memory = ConversationSummaryMemory(llm=llm)
self.message_count = 0
self.summary_interval = 5 # 每5轮总结一次
def add_conversation(self, user_msg: str, ai_msg: str) -> None:
"""添加对话"""
self.summary_memory.save_context(
{"input": user_msg},
{"output": ai_msg}
)
self.message_count += 1
# 定期总结
if self.message_count % self.summary_interval == 0:
print(f"\n⏰ 已进行{self.message_count}轮对话,生成摘要")
self.show_summary()
def show_summary(self) -> None:
"""显示摘要"""
summary = self.summary_memory.load_memory_variables({})
print(f"📄 摘要:{summary['history']}")
def get_stats(self) -> dict:
"""获取统计信息"""
summary = self.summary_memory.load_memory_variables({})
return {
"message_count": self.message_count,
"summary_length": len(summary["history"])
}
# 测试
manager = SmartMemoryManager(llm)
# 模拟长对话
topics = [
"Python基础",
"Web开发",
"数据库设计",
"API开发",
"测试",
"部署",
"性能优化",
]
for i, topic in enumerate(topics, 1):
print(f"\n第{i}轮:讨论{topic}")
manager.add_conversation(
f"我想学习{topic}",
f"好的,{topic}的关键点是..."
)
print("\n" + "="*60)
print("\n📊 最终统计:")
stats = manager.get_stats()
print(f" 总对话轮数:{stats['message_count']}")
print(f" 摘要长度:{stats['summary_length']}字符")
def main() -> None:
"""主函数"""
example1_basic_summary_memory()
print("\n" + "="*70 + "\n")
example2_summary_vs_buffer()
print("\n" + "="*70 + "\n")
example3_summary_buffer_memory()
print("\n" + "="*70 + "\n")
example4_custom_summary_prompt()
print("\n" + "="*70 + "\n")
example5_incremental_summary()
print("\n" + "="*70 + "\n")
example6_memory_management()
if __name__ == "__main__":
main()04_chatbot.py- 完整聊天机器人1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429"""
完整聊天机器人
演示:综合运用记忆功能构建实用的聊天机器人
"""
from langchain.memory import ConversationBufferWindowMemory
from langchain.chains import ConversationChain
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, AIMessage
from typing import Dict, Optional
from datetime import datetime
from dotenv import load_dotenv
import os
load_dotenv()
class SimpleChatBot:
"""简单聊天机器人"""
def __init__(self):
"""初始化聊天机器人"""
self.llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
self.memory = ConversationBufferWindowMemory(
k=10, # 保留最近10轮对话
return_messages=True
)
self.conversation = ConversationChain(
llm=self.llm,
memory=self.memory,
verbose=False
)
def chat(self, message: str) -> str:
"""发送消息并获取回复"""
response = self.conversation.predict(input=message)
return response
def clear_history(self) -> None:
"""清除对话历史"""
self.memory.clear()
print("✨ 对话历史已清除")
def show_history(self) -> None:
"""显示对话历史"""
messages = self.memory.chat_memory.messages
if not messages:
print("(暂无对话历史)")
return
print("\n📜 对话历史:")
for i, msg in enumerate(messages):
if isinstance(msg, HumanMessage):
print(f" {i+1}. 👤 {msg.content}")
elif isinstance(msg, AIMessage):
print(f" 🤖 {msg.content}")
class PersonalAssistant:
"""个人助手(记住用户信息)"""
def __init__(self):
"""初始化个人助手"""
self.llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
self.memory = ConversationBufferWindowMemory(
k=5,
return_messages=True,
memory_key="chat_history"
)
# 自定义提示词
self.prompt = ChatPromptTemplate.from_messages([
("system", """你是一个贴心的个人助手。
你的职责:
1. 记住用户告诉你的信息(名字、喜好、工作等)
2. 在回答时自然地使用这些信息
3. 主动关心用户
4. 提供有用的建议
请用友好、贴心的语气对话。
"""),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}")
])
def chat(self, message: str) -> str:
"""聊天"""
# 获取历史
history = self.memory.load_memory_variables({})
# 生成回复
messages = self.prompt.format_messages(
chat_history=history.get("chat_history", []),
input=message
)
response = self.llm.invoke(messages)
# 保存到记忆
self.memory.save_context(
{"input": message},
{"output": response.content}
)
return response.content
class MultiUserChatBot:
"""多用户聊天机器人"""
def __init__(self):
"""初始化多用户聊天机器人"""
self.llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
self.user_memories: Dict[str, ConversationBufferWindowMemory] = {}
self.user_info: Dict[str, dict] = {}
def get_or_create_memory(self, user_id: str) -> ConversationBufferWindowMemory:
"""获取或创建用户记忆"""
if user_id not in self.user_memories:
self.user_memories[user_id] = ConversationBufferWindowMemory(
k=5,
return_messages=True
)
self.user_info[user_id] = {
"created_at": datetime.now(),
"message_count": 0
}
print(f"✨ 为用户 {user_id} 创建新会话")
return self.user_memories[user_id]
def chat(self, user_id: str, message: str) -> str:
"""用户聊天"""
memory = self.get_or_create_memory(user_id)
# 创建对话链
conversation = ConversationChain(
llm=self.llm,
memory=memory,
verbose=False
)
# 获取回复
response = conversation.predict(input=message)
# 更新统计
self.user_info[user_id]["message_count"] += 1
self.user_info[user_id]["last_active"] = datetime.now()
return response
def get_user_stats(self, user_id: str) -> Optional[dict]:
"""获取用户统计"""
if user_id not in self.user_info:
return None
info = self.user_info[user_id]
memory = self.user_memories[user_id]
return {
"user_id": user_id,
"created_at": info["created_at"].strftime("%Y-%m-%d %H:%M:%S"),
"message_count": info["message_count"],
"last_active": info.get("last_active", info["created_at"]).strftime("%Y-%m-%d %H:%M:%S"),
"memory_size": len(memory.chat_memory.messages)
}
def list_users(self) -> list:
"""列出所有用户"""
return list(self.user_memories.keys())
def example1_simple_chatbot() -> None:
"""示例1:简单聊天机器人"""
print("=== 示例1:简单聊天机器人 ===\n")
bot = SimpleChatBot()
# 对话序列
messages = [
"你好!",
"我叫小明",
"我今年20岁",
"我是大学生",
"我叫什么名字?",
"我多大了?",
]
for msg in messages:
print(f"👤 用户:{msg}")
response = bot.chat(msg)
print(f"🤖 机器人:{response}\n")
# 显示历史
bot.show_history()
def example2_personal_assistant() -> None:
"""示例2:个人助手"""
print("\n\n=== 示例2:个人助手 ===\n")
assistant = PersonalAssistant()
conversations = [
"你好,我是张伟",
"我是一名软件工程师",
"我喜欢跑步和阅读",
"我最近在学习AI",
"能根据我的情况给些学习建议吗?",
]
for msg in conversations:
print(f"👤 用户:{msg}")
response = assistant.chat(msg)
print(f"🤖 助手:{response}\n")
def example3_multi_user_bot() -> None:
"""示例3:多用户聊天机器人"""
print("\n\n=== 示例3:多用户聊天机器人 ===\n")
bot = MultiUserChatBot()
# 用户A的对话
print("👤 用户A 的对话:")
print("-" * 50)
userA_messages = [
"你好,我是Alice",
"我是学生",
"我学的是计算机",
]
for msg in userA_messages:
print(f"Alice:{msg}")
response = bot.chat("userA", msg)
print(f"Bot:{response}\n")
# 用户B的对话
print("\n👤 用户B 的对话:")
print("-" * 50)
userB_messages = [
"Hi,我是Bob",
"我是工程师",
"我在做Web开发",
]
for msg in userB_messages:
print(f"Bob:{msg}")
response = bot.chat("userB", msg)
print(f"Bot:{response}\n")
# 继续用户A的对话
print("\n👤 用户A 继续对话:")
print("-" * 50)
print("Alice:我是做什么的?")
response = bot.chat("userA", "我是做什么的?")
print(f"Bot:{response}\n")
# 显示统计
print("\n📊 系统统计:")
print("-" * 50)
for user_id in bot.list_users():
stats = bot.get_user_stats(user_id)
print(f"\n用户:{stats['user_id']}")
print(f" 创建时间:{stats['created_at']}")
print(f" 消息数量:{stats['message_count']}")
print(f" 最后活跃:{stats['last_active']}")
print(f" 记忆大小:{stats['memory_size']}条消息")
def example4_interactive_chatbot() -> None:
"""示例4:交互式聊天机器人(命令行版)"""
print("\n\n=== 示例4:交互式聊天机器人 ===\n")
bot = SimpleChatBot()
print("💬 聊天机器人已启动!")
print("命令:")
print(" /history - 查看对话历史")
print(" /clear - 清除对话历史")
print(" /quit - 退出")
print("="*60 + "\n")
# 模拟交互(实际使用时可以用input())
demo_messages = [
"你好",
"我叫测试用户",
"/history",
"我叫什么名字?",
"/clear",
"我叫什么名字?",
"/quit"
]
for message in demo_messages:
print(f"👤 {message}")
if message == "/quit":
print("👋 再见!")
break
elif message == "/history":
bot.show_history()
elif message == "/clear":
bot.clear_history()
else:
response = bot.chat(message)
print(f"🤖 {response}")
print()
def example5_contextual_chatbot() -> None:
"""示例5:上下文感知的聊天机器人"""
print("\n\n=== 示例5:上下文感知聊天机器人 ===\n")
class ContextAwareChatBot:
"""上下文感知的聊天机器人"""
def __init__(self):
self.llm = ChatOpenAI(
base_url=os.getenv("ALIBABA_BASE_URL"),
api_key=os.getenv("ALIBABA_API_KEY"),
model="qwen-plus",
temperature=0.7,
)
self.memory = ConversationBufferWindowMemory(
k=5, return_messages=True)
self.context_info = {} # 存储提取的上下文信息
def extract_info(self, message: str, response: str) -> None:
"""从对话中提取关键信息"""
# 简化版:检测关键词
if "我叫" in message or "我是" in message:
# 提取名字(实际应该用NER)
if "我叫" in message:
name = message.split("我叫")[1].split()[0].strip(",。!")
self.context_info["name"] = name
if "岁" in message:
# 提取年龄
import re
age_match = re.search(r'(\d+)岁', message)
if age_match:
self.context_info["age"] = age_match.group(1)
def chat(self, message: str) -> str:
"""聊天"""
conversation = ConversationChain(
llm=self.llm,
memory=self.memory,
verbose=False
)
response = conversation.predict(input=message)
# 提取信息
self.extract_info(message, response)
return response
def show_context(self) -> None:
"""显示提取的上下文信息"""
print("\n📋 提取的上下文信息:")
if not self.context_info:
print(" (暂无)")
else:
for key, value in self.context_info.items():
print(f" {key}: {value}")
# 测试
bot = ContextAwareChatBot()
messages = [
"你好,我叫李华",
"我今年25岁",
"我是程序员",
]
for msg in messages:
print(f"👤 {msg}")
response = bot.chat(msg)
print(f"🤖 {response}\n")
bot.show_context()
def main() -> None:
"""主函数"""
example1_simple_chatbot()
print("\n" + "="*70 + "\n")
example2_personal_assistant()
print("\n" + "="*70 + "\n")
example3_multi_user_bot()
print("\n" + "="*70 + "\n")
example4_interactive_chatbot()
print("\n" + "="*70 + "\n")
example5_contextual_chatbot()
if __name__ == "__main__":
main()
🎨 记忆使用模式
模式1:简单对话机器人
1  | from langchain.memory import ConversationBufferMemory  | 
模式2:自定义记忆键
1  | memory = ConversationBufferMemory(  | 
模式3:持久化记忆
1  | # 保存到文件  | 
模式4:多会话记忆
1  | # 为不同用户维护独立记忆  | 
📊 记忆类型对比
| 类型 | 优点 | 缺点 | 使用场景 | 
|---|---|---|---|
| Buffer | 完整保留 实现简单  | Token消耗大 有长度限制  | 短对话 需要完整上下文  | 
| Window | Token可控 性能稳定  | 丢失旧对话 可能断上下文  | 长对话 只需近期上下文  | 
| Summary | Token最省 可处理长对话  | 可能丢失细节 需要额外调用  | 非常长的对话 成本敏感  | 
| SummaryBuffer | 灵活平衡 保留细节  | 实现复杂 需要调优  | 生产环境 企业应用  | 
🔍 常见问题
Q1: 记忆会一直增长吗?
是的,需要管理:
1  | # 方案1:使用窗口记忆  | 
Q2: 如何在重启后保留记忆?
1  | # 使用数据库或文件存储  | 
Q3: 记忆消耗太多Token怎么办?
优化策略:
1  | # 1. 使用窗口记忆限制轮数  | 
Q4: 多用户场景如何管理记忆?
1  | from langchain.memory import ConversationBufferMemory  | 
📝 练习任务
练习1:个人信息助手
创建一个记住用户信息的助手:
- 记住用户的名字、年龄、职业等
 - 在后续对话中使用这些信息
 - 能够更新信息
 
练习2:智能客服系统
创建带记忆的客服:
- 记住订单号、问题类型
 - 跨多轮对话解决问题
 - 可以回顾之前讨论的内容
 
练习3:学习伙伴
创建一个编程学习伙伴:
- 记住学习进度
 - 记住已经解释过的概念
 - 根据历史调整教学方式
 
🎯 检查清单
完成本课后,你应该能够:
- 理解AI记忆的重要性
 - 使用不同类型的记忆
 - 选择合适的记忆类型
 - 管理记忆的增长
 - 实现多用户记忆隔离
 - 持久化和恢复记忆
 
💡 核心要点
记忆让AI更智能
- 记住上下文
 - 提供连贯的对话体验
 
选择合适的记忆类型
- 短对话:Buffer
 - 长对话:Window或Summary
 - 生产环境:SummaryBuffer
 
注意Token消耗
- 记忆会消耗tokens
 - 需要定期清理或总结
 
多用户场景
- 隔离不同用户的记忆
 - 考虑持久化方案
 
📚 下一步
现在你已经学会了让AI记住对话,接下来学习如何让AI自主使用工具:
继续学习: 第6课:Agent和工具 →