阶段 4:记忆、知识库系统与长期状态
📖 本阶段目标
- 理解 Agent 的记忆系统架构
- 掌握短期记忆和长期记忆的实现
- 学习 RAG(检索增强生成)技术
- 实践构建知识库问答 Agent
🧠 记忆系统架构
Agent 的记忆层次
┌─────────────────────────────────────────┐
│ 工作记忆 (Working Memory) │
│ 当前对话上下文,即时可用 │
│ Token 限制:4K-128K │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴───────────────────────┐
│ 短期记忆 (Short-term Memory) │
│ 最近的对话历史,会话级别 │
│ 存储:内存/Redis │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴───────────────────────┐
│ 长期记忆 (Long-term Memory) │
│ 持久化知识,跨会话可用 │
│ 存储:向量数据库 + 结构化数据库 │
└─────────────────────────────────────────┘
💾 短期记忆实现
1. 对话历史管理
# examples/stage4/conversation_memory.py
from typing import List, Dict
from collections import deque
class ConversationMemory:
"""对话记忆管理器"""
def __init__(self, max_messages=20, max_tokens=4000):
self.messages = deque(maxlen=max_messages)
self.max_tokens = max_tokens
self.system_message = None
def set_system_message(self, content: str):
"""设置系统消息"""
self.system_message = {"role": "system", "content": content}
def add_user_message(self, content: str):
"""添加用户消息"""
self.messages.append({"role": "user", "content": content})
def add_assistant_message(self, content: str):
"""添加助手消息"""
self.messages.append({"role": "assistant", "content": content})
def get_messages(self) -> List[Dict]:
"""获取所有消息(包括系统消息)"""
messages = []
if self.system_message:
messages.append(self.system_message)
messages.extend(list(self.messages))
return messages
def get_recent_messages(self, n=10) -> List[Dict]:
"""获取最近 n 条消息"""
messages = []
if self.system_message:
messages.append(self.system_message)
recent = list(self.messages)[-n:]
messages.extend(recent)
return messages
def clear(self):
"""清空对话历史"""
self.messages.clear()
def summarize_old_messages(self, llm_client):
"""总结旧消息以节省 token"""
if len(self.messages) < 10:
return
# 获取较旧的消息
old_messages = list(self.messages)[:5]
# 使用 LLM 生成摘要
summary_prompt = "请简要总结以下对话内容:\n\n"
for msg in old_messages:
summary_prompt += f"{msg['role']}: {msg['content']}\n"
# ... 调用 LLM 获取摘要
# summary = llm_client.chat(summary_prompt)
# 移除旧消息,保留摘要
for _ in range(5):
self.messages.popleft()
# 添加摘要作为系统消息
self.messages.appendleft({
"role": "system",
"content": f"之前的对话摘要:{summary}"
})
# 使用示例
if __name__ == "__main__":
memory = ConversationMemory(max_messages=10)
memory.set_system_message("你是一个有帮助的助手。")
memory.add_user_message("你好")
memory.add_assistant_message("你好!有什么可以帮助你的?")
memory.add_user_message("我想了解 Python")
memory.add_assistant_message("Python 是一种高级编程语言...")
print("所有消息:")
for msg in memory.get_messages():
print(f"{msg['role']}: {msg['content']}")
2. 会话状态管理
# examples/stage4/session_manager.py
import json
from datetime import datetime
from typing import Dict, Any
class SessionManager:
"""会话状态管理器"""
def __init__(self, session_id: str):
self.session_id = session_id
self.state = {
"created_at": datetime.now().isoformat(),
"last_active": datetime.now().isoformat(),
"context": {},
"metadata": {}
}
def set_context(self, key: str, value: Any):
"""设置上下文信息"""
self.state["context"][key] = value
self._update_activity()
def get_context(self, key: str, default=None) -> Any:
"""获取上下文信息"""
return self.state["context"].get(key, default)
def set_metadata(self, key: str, value: Any):
"""设置元数据"""
self.state["metadata"][key] = value
self._update_activity()
def _update_activity(self):
"""更新活动时间"""
self.state["last_active"] = datetime.now().isoformat()
def save(self, filepath: str):
"""保存会话状态"""
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(self.state, f, ensure_ascii=False, indent=2)
def load(self, filepath: str):
"""加载会话状态"""
with open(filepath, 'r', encoding='utf-8') as f:
self.state = json.load(f)
# 使用示例
if __name__ == "__main__":
session = SessionManager("user_123_session_1")
# 设置上下文
session.set_context("user_name", "张三")
session.set_context("topic", "Python 学习")
session.set_context("skill_level", "初学者")
# 设置元数据
session.set_metadata("language", "zh-CN")
session.set_metadata("device", "mobile")
# 保存
session.save("/tmp/session_user_123.json")
print(f"用户名: {session.get_context('user_name')}")
print(f"主题: {session.get_context('topic')}")
🗄️ 长期记忆与 RAG
1. 向量数据库基础
# examples/stage4/vector_store.py
from typing import List, Dict
import numpy as np
from openai import OpenAI
client = OpenAI()
class SimpleVectorStore:
"""简单的向量存储(实际应使用专业向量数据库)"""
def __init__(self):
self.documents = []
self.embeddings = []
self.metadata = []
def get_embedding(self, text: str) -> List[float]:
"""获取文本的向量表示"""
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
def add_document(self, text: str, metadata: Dict = None):
"""添加文档"""
embedding = self.get_embedding(text)
self.documents.append(text)
self.embeddings.append(embedding)
self.metadata.append(metadata or {})
def cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
"""计算余弦相似度"""
vec1 = np.array(vec1)
vec2 = np.array(vec2)
return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
def search(self, query: str, top_k: int = 3) -> List[Dict]:
"""搜索相关文档"""
query_embedding = self.get_embedding(query)
# 计算所有文档的相似度
similarities = []
for i, doc_embedding in enumerate(self.embeddings):
similarity = self.cosine_similarity(query_embedding, doc_embedding)
similarities.append({
"index": i,
"similarity": similarity,
"document": self.documents[i],
"metadata": self.metadata[i]
})
# 排序并返回 top_k
similarities.sort(key=lambda x: x["similarity"], reverse=True)
return similarities[:top_k]
# 使用示例
if __name__ == "__main__":
store = SimpleVectorStore()
# 添加文档
documents = [
"Python 是一种高级编程语言,由 Guido van Rossum 创建于 1991 年。",
"JavaScript 是一种用于网页开发的脚本语言,主要运行在浏览器中。",
"Java 是一种面向对象的编程语言,广泛用于企业级应用开发。",
"人工智能是计算机科学的一个分支,研究如何让机器模拟人类智能。"
]
for doc in documents:
store.add_document(doc, {"source": "knowledge_base"})
# 搜索
query = "什么是 Python?"
results = store.search(query, top_k=2)
print(f"查询: {query}\n")
for i, result in enumerate(results, 1):
print(f"结果 {i} (相似度: {result['similarity']:.4f}):")
print(f"{result['document']}\n")
2. RAG 系统实现
# examples/stage4/rag_agent.py
from openai import OpenAI
from typing import List, Dict
import json
client = OpenAI()
class RAGAgent:
"""检索增强生成 Agent"""
def __init__(self, vector_store):
self.vector_store = vector_store
def retrieve(self, query: str, top_k: int = 3) -> List[str]:
"""检索相关文档"""
results = self.vector_store.search(query, top_k)
return [r["document"] for r in results]
def generate_answer(self, query: str, context_docs: List[str]) -> str:
"""基于检索到的文档生成答案"""
context = "\n\n".join([f"文档 {i+1}: {doc}"
for i, doc in enumerate(context_docs)])
prompt = f"""
基于以下文档回答问题。如果文档中没有相关信息,请明确说明。
文档:
{context}
问题: {query}
请给出准确、简洁的答案。
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "你是一个知识问答助手,基于提供的文档回答问题。"},
{"role": "user", "content": prompt}
],
temperature=0.3
)
return response.choices[0].message.content
def answer(self, query: str) -> Dict:
"""完整的 RAG 流程"""
# 1. 检索
retrieved_docs = self.retrieve(query, top_k=3)
# 2. 生成
answer = self.generate_answer(query, retrieved_docs)
return {
"query": query,
"retrieved_documents": retrieved_docs,
"answer": answer
}
# 使用示例
if __name__ == "__main__":
# 初始化向量存储并添加文档
from vector_store import SimpleVectorStore
store = SimpleVectorStore()
# 添加知识库文档
knowledge_base = [
"Python 是一种解释型、面向对象的高级编程语言,由 Guido van Rossum 于 1991 年创建。它以简洁的语法和强大的功能而闻名。",
"Python 的主要特点包括:简洁易读的语法、丰富的标准库、跨平台兼容性、强大的第三方生态系统。",
"Python 常用于 Web 开发、数据分析、人工智能、自动化脚本等领域。",
"机器学习是人工智能的一个分支,它使计算机能够从数据中学习,而无需显式编程。",
"深度学习是机器学习的一个子领域,使用多层神经网络来处理复杂的数据。",
]
for doc in knowledge_base:
store.add_document(doc)
# 创建 RAG Agent
rag_agent = RAGAgent(store)
# 提问
questions = [
"Python 是什么时候创建的?",
"Python 有哪些特点?",
"什么是深度学习?"
]
for question in questions:
print("=" * 60)
print(f"问题: {question}")
print("-" * 60)
result = rag_agent.answer(question)
print("检索到的文档:")
for i, doc in enumerate(result["retrieved_documents"], 1):
print(f"{i}. {doc[:100]}...")
print(f"\n答案:\n{result['answer']}")
print()
📚 实践项目:个人笔记问答 Agent
# examples/stage4/note_agent.py
from openai import OpenAI
import os
from datetime import datetime
from typing import List, Dict
client = OpenAI()
class NoteAgent:
"""个人笔记管理和问答 Agent"""
def __init__(self, vector_store):
self.vector_store = vector_store
self.notes = []
def add_note(self, title: str, content: str, tags: List[str] = None):
"""添加笔记"""
note = {
"id": len(self.notes) + 1,
"title": title,
"content": content,
"tags": tags or [],
"created_at": datetime.now().isoformat()
}
self.notes.append(note)
# 添加到向量存储
full_text = f"{title}\n{content}"
self.vector_store.add_document(
full_text,
metadata={
"note_id": note["id"],
"title": title,
"tags": tags
}
)
return note
def search_notes(self, query: str, top_k: int = 5) -> List[Dict]:
"""搜索笔记"""
results = self.vector_store.search(query, top_k)
# 获取完整笔记信息
note_results = []
for result in results:
note_id = result["metadata"]["note_id"]
note = self.notes[note_id - 1]
note_results.append({
"note": note,
"similarity": result["similarity"]
})
return note_results
def answer_from_notes(self, question: str) -> Dict:
"""从笔记中回答问题"""
# 搜索相关笔记
relevant_notes = self.search_notes(question, top_k=3)
if not relevant_notes:
return {
"question": question,
"answer": "抱歉,我在你的笔记中没有找到相关信息。",
"sources": []
}
# 构建上下文
context = "\n\n".join([
f"笔记:{n['note']['title']}\n{n['note']['content']}"
for n in relevant_notes
])
# 生成答案
prompt = f"""
基于我的以下笔记内容回答问题:
{context}
问题:{question}
请基于笔记内容给出答案。如果笔记中没有相关信息,请说明。
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "你是一个个人笔记助手,帮助用户从笔记中找到信息。"},
{"role": "user", "content": prompt}
],
temperature=0.3
)
return {
"question": question,
"answer": response.choices[0].message.content,
"sources": [n["note"]["title"] for n in relevant_notes]
}
def summarize_notes_by_tag(self, tag: str) -> str:
"""总结某个标签的所有笔记"""
tagged_notes = [n for n in self.notes if tag in n.get("tags", [])]
if not tagged_notes:
return f"没有找到标签为 '{tag}' 的笔记。"
notes_content = "\n\n".join([
f"标题:{n['title']}\n内容:{n['content']}"
for n in tagged_notes
])
prompt = f"""
请总结以下关于 '{tag}' 的笔记:
{notes_content}
生成一个简洁的总结,提取主要观点和关键信息。
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.5
)
return response.choices[0].message.content
# 使用示例
if __name__ == "__main__":
from vector_store import SimpleVectorStore
# 创建笔记 Agent
store = SimpleVectorStore()
agent = NoteAgent(store)
# 添加笔记
agent.add_note(
"Python 基础",
"Python 是一种解释型语言,语法简洁。主要特点:动态类型、自动内存管理、丰富的库支持。",
tags=["编程", "Python"]
)
agent.add_note(
"机器学习入门",
"机器学习是 AI 的子领域。主要分类:监督学习、无监督学习、强化学习。常用库:scikit-learn, TensorFlow, PyTorch。",
tags=["AI", "机器学习"]
)
agent.add_note(
"Web 开发框架",
"Python Web 框架:Flask(轻量级)、Django(全栈)、FastAPI(异步高性能)。",
tags=["编程", "Python", "Web"]
)
# 问答
print("=== 笔记问答 ===\n")
result = agent.answer_from_notes("Python 有哪些 Web 框架?")
print(f"问题:{result['question']}")
print(f"答案:{result['answer']}")
print(f"来源:{', '.join(result['sources'])}")
print()
# 标签总结
print("=== 标签总结 ===\n")
summary = agent.summarize_notes_by_tag("Python")
print(f"'Python' 标签总结:\n{summary}")
🔧 高级技术
1. 分块策略
def chunk_text(text: str, chunk_size: int = 500, overlap: int = 50) -> List[str]:
"""将长文本分块"""
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - overlap # 重叠部分
return chunks
2. 混合检索
def hybrid_search(query: str, vector_store, keyword_index):
"""结合向量搜索和关键词搜索"""
# 向量检索
vector_results = vector_store.search(query, top_k=10)
# 关键词检索
keyword_results = keyword_index.search(query, top_k=10)
# 合并结果(可以使用 RRF 等算法)
combined_results = merge_results(vector_results, keyword_results)
return combined_results
✅ 阶段完成检查清单
- [ ] 理解 Agent 记忆系统的层次结构
- [ ] 实现了对话历史管理
- [ ] 掌握向量数据库的基本使用
- [ ] 理解 RAG 的工作原理
- [ ] 实现了基于 RAG 的问答系统
- [ ] 完成个人笔记 Agent 项目
- [ ] 了解文本分块和混合检索策略
🎯 下一步
完成本阶段后,进入 阶段 5:多 Agent 协同与角色体系,学习如何构建多 Agent 协作系统。
💡 小贴士:记忆是 Agent 的"经验积累",好的记忆系统让 Agent 越用越智能。推荐使用专业向量数据库如 Pinecone、Weaviate 或 Qdrant。