自主完成复杂任务的AI系统
基于规则直接响应
条件→动作
维护环境模型
状态→模型→动作
搜索目标路径
目标→规划→执行
分治策略
分解→解决→整合
从经验学习
试错→强化→改进
协作与通信
分工→协作→共识
智能体可调用的外部能力
存储对话历史和经验
引导智能体行为模式
决策循环和执行逻辑
AI智能体需要记忆来保持上下文一致性、学习用户偏好、在多轮对话中积累知识。没有记忆,智能体每次都是"从零开始"。
| 记忆类型 | 作用 | 存储方式 | 生命周期 |
|---|---|---|---|
| 工作记忆 | 当前任务执行过程中的中间状态 | 变量、内存 | 任务内 |
| 短期记忆 | 当前对话的上下文 | 对话历史(窗口) | 会话内 |
| 长期记忆 | 跨会话的知识和经验 | 向量数据库、文件 | 永久 |
最基础的记忆方式,直接保存用户和AI的所有对话记录。
# 对话历史示例
messages = [
{"role": "system", "content": "你是一个有帮助的助手"},
{"role": "user", "content": "我叫张三"},
{"role": "assistant", "content": "你好张三,很高兴认识你!"},
{"role": "user", "content": "我刚才说的名字是什么?"}, # 需要记住上面的对话
]
# 问题:对话太长会超出上下文限制
# 解决方案:滑动窗口、摘要压缩
当对话超过模型上下文限制时,需要管理窗口大小。
from collections import deque
class ConversationWindow:
"""滑动窗口管理对话历史"""
def __init__(self, max_tokens: int = 4000):
self.max_tokens = max_tokens
self.messages = deque()
def add_message(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
self._trim()
def _trim(self):
"""裁剪超出限制的消息"""
while self._estimate_tokens() > self.max_tokens and len(self.messages) > 1:
# 移除最旧的消息(保留system消息)
if self.messages[0]["role"] == "system":
self.messages.popleft()
self.messages.popleft()
else:
self.messages.popleft()
def _estimate_tokens(self) -> int:
# 简单估算:1 token ≈ 4 字符
return sum(len(m["content"]) // 4 for m in self.messages)
def get_context(self) -> list:
return list(self.messages)
# 使用
window = ConversationWindow(max_tokens=4000)
window.add_message("user", "我叫张三")
window.add_message("assistant", "你好张三!")
window.add_message("user", "帮我查下天气") # 如果超限,会自动裁剪
定期将长对话压缩成摘要,减少token消耗同时保留关键信息。
class SummarizedConversation:
"""对话摘要模式"""
def __init__(self, llm):
self.llm = llm
self.summary = ""
self.recent_messages = [] # 保留最近N条消息
self.summary_threshold = 10 # 多少条消息后摘要
def add_message(self, role: str, content: str):
self.recent_messages.append({"role": role, "content": content})
# 达到阈值时生成摘要
if len(self.recent_messages) >= self.summary_threshold:
self._generate_summary()
self.recent_messages = [] # 清空只保留摘要
def _generate_summary(self):
"""调用LLM生成摘要"""
prompt = f"请简要总结以下对话的核心要点(不超过100字):\n"
for msg in self.recent_messages:
prompt += f"{msg['role']}: {msg['content']}\n"
self.summary = self.llm.call(prompt)
print(f"📝 生成摘要: {self.summary}")
def get_context(self) -> list:
context = [{"role": "system", "content": f"会话摘要: {self.summary}"}]
context.extend(self.recent_messages)
return context
将重要信息存入向量数据库,支持语义检索。
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.schema import Document
class VectorMemory:
"""向量数据库记忆"""
def __init__(self):
self.embeddings = OpenAIEmbeddings()
self.vectorstore = None
def add(self, text: str, metadata: dict = None):
"""添加记忆"""
doc = Document(page_content=text, metadata=metadata or {})
if self.vectorstore is None:
self.vectorstore = FAISS.from_documents([doc], self.embeddings)
else:
self.vectorstore.add_documents([doc])
def search(self, query: str, k: int = 3) -> list:
"""语义检索相关记忆"""
if self.vectorstore is None:
return []
results = self.vectorstore.similarity_search(query, k=k)
return [doc.page_content for doc in results]
def save(self, path: str):
"""持久化保存"""
self.vectorstore.save_local(path)
def load(self, path: str):
"""加载已有记忆"""
self.vectorstore = FAISS.load_local(path, self.embeddings)
# 使用示例
memory = VectorMemory()
# 保存用户偏好
memory.add(
"用户喜欢简洁的技术方案,不喜欢太复杂的架构",
metadata={"type": "preference", "topic": "architecture"}
)
memory.add(
"用户主要使用Python开发",
metadata={"type": "preference", "topic": "language"}
)
# 检索相关记忆
related = memory.search("应该用什么语言开发新项目?")
# 返回: ["用户主要使用Python开发", ...]
适合存储明确的结构化信息(用户信息、配置等)。
import json
from datetime import datetime
class StructuredMemory:
"""结构化记忆存储"""
def __init__(self, storage_path: str = "memory.json"):
self.storage_path = storage_path
self.data = self._load()
def _load(self) -> dict:
try:
with open(self.storage_path, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return {"users": {}, "preferences": {}, "knowledge": []}
def save(self):
with open(self.storage_path, "w", encoding="utf-8") as f:
json.dump(self.data, f, ensure_ascii=False, indent=2)
def set_user_info(self, user_id: str, key: str, value):
"""保存用户信息"""
if user_id not in self.data["users"]:
self.data["users"][user_id] = {}
self.data["users"][user_id][key] = value
self.save()
def get_user_info(self, user_id: str, key: str, default=None):
"""获取用户信息"""
return self.data["users"].get(user_id, {}).get(key, default)
def add_knowledge(self, fact: str, category: str):
"""添加知识"""
self.data["knowledge"].append({
"fact": fact,
"category": category,
"timestamp": datetime.now().isoformat()
})
self.save()
def get_knowledge(self, category: str = None) -> list:
"""获取知识"""
if category:
return [k for k in self.data["knowledge"] if k["category"] == category]
return self.data["knowledge"]
# 使用
memory = StructuredMemory("user_memory.json")
memory.set_user_info("user_123", "name", "张三")
memory.set_user_info("user_123", "language", "Python")
memory.add_knowledge("项目使用FastAPI框架", "tech_stack")
memory.add_knowledge("数据库是PostgreSQL", "tech_stack")
结合短期记忆和长期记忆,根据重要性自动分层。
class HybridMemory:
"""混合记忆系统:短期 + 长期"""
def __init__(self):
# 短期记忆:对话窗口
self.short_term = ConversationWindow(max_tokens=2000)
# 长期记忆:向量存储
self.long_term = VectorMemory()
# 重要信息:需要存入长期记忆
self.important_patterns = ["偏好", "喜欢", "讨厌", "记住", "以后"]
self.llm = None # 需要注入LLM用于判断重要性
def add_message(self, role: str, content: str):
# 1. 加入短期记忆
self.short_term.add_message(role, content)
# 2. 判断是否需要存入长期记忆
if self._is_important(content):
self._store_to_long_term(content, role)
def _is_important(self, content: str) -> bool:
"""判断内容是否重要"""
# 方式1:关键词匹配
for pattern in self.important_patterns:
if pattern in content:
return True
# 方式2:LLM判断(更准确但更慢)
# return self.llm.judge_importance(content)
return False
def _store_to_long_term(self, content: str, role: str):
"""存储到长期记忆"""
self.long_term.add(
text=f"{role}: {content}",
metadata={"timestamp": datetime.now().isoformat()}
)
print(f"💾 已存入长期记忆: {content[:50]}...")
def retrieve_context(self, current_query: str) -> list:
"""获取当前上下文"""
# 1. 获取短期记忆(对话历史)
short_context = self.short_term.get_context()
# 2. 检索长期记忆(相关知识)
long_context = self.long_term.search(current_query, k=3)
# 3. 合并
result = short_context.copy()
if long_context:
result.append({
"role": "system",
"content": f"相关记忆: {'; '.join(long_context)}"
})
return result
# 使用
memory = HybridMemory()
# 对话
memory.add_message("user", "我叫张三,从事Python开发")
memory.add_message("assistant", "好的张老师,很高兴认识你!")
memory.add_message("user", "帮我写个排序算法") # "从事Python开发"会被存入长期记忆
# 检索
context = memory.retrieve_context("排序算法")
# 自动包含用户是Python开发者的信息
| 场景 | 推荐方案 | 注意事项 |
|---|---|---|
| 单轮问答 | 无需记忆 | 简洁高效 |
| 简单多轮对话 | 对话历史窗口 | 控制窗口大小 |
| 复杂任务 | 工作记忆 + 对话摘要 | 定期压缩 |
| 个性化助手 | 混合记忆(短期+长期) | 向量检索 |
| 知识库问答 | RAG(向量检索) | 定期更新 |
| 工具类型 | 示例 | 用途 |
|---|---|---|
| 搜索 | SerpAPI, Wikipedia | 网络信息查询 |
| 计算 | Python REPL, Calculator | 数学计算 |
| 数据库 | SQL, MongoDB | 数据查询 |
| API | HTTP请求 | 第三方服务 |
| 文件 | 读/写文件 | 文档处理 |
多轮对话、问题解答
信息搜集、分析总结
代码编写、调试、测试
内容创作、编辑校对
自动化流程编排
信息抓取、整理
"""
ReAct智能体实现:Thought → Action → Observation → ...
- 搜索工具
- 计算工具
- 文件读取工具
- 智能体核心逻辑
"""
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
import json
import math
import re
class ActionType(Enum):
SEARCH = "search"
CALCULATE = "calculate"
READ_FILE = "read_file"
LIST_FILES = "list_files"
FINISH = "finish"
@dataclass
class Action:
type: ActionType
input: str
@dataclass
class Step:
thought: str
action: Optional[Action]
observation: str
class Tool:
"""工具基类"""
@property
def name(self) -> str:
raise NotImplementedError
@property
def description(self) -> str:
raise NotImplementedError
def execute(self, input: str) -> str:
raise NotImplementedError
class SearchTool(Tool):
"""搜索工具(模拟)"""
@property
def name(self) -> str:
return "search"
@property
def description(self) -> str:
return "搜索网络信息,返回相关结果"
def execute(self, query: str) -> str:
# 模拟搜索结果
knowledge_base = {
"人工智能": "AI是 Artificial Intelligence 的缩写,研究让机器具有智能的科学。",
"机器学习": "Machine Learning,让计算机从数据中学习规律的技术。",
"深度学习": "Deep Learning,使用多层神经网络的机器学习方法。",
"python": "Python是一种流行的编程语言,适合AI开发。",
"langchain": "LangChain是一个LLM应用开发框架。"
}
for key, value in knowledge_base.items():
if key in query.lower():
return value
return f"关于'{query}'的搜索结果:这是一条模拟的搜索结果。"
class CalculatorTool(Tool):
"""计算工具"""
@property
def name(self) -> str:
return "calculate"
@property
def description(self) -> str:
return "执行数学计算,支持四则运算和函数"
def execute(self, expression: str) -> str:
try:
# 安全计算
allowed_chars = set("0123456789+-*/(). ")
if not all(c in allowed_chars for c in expression):
return "错误:包含不允许的字符"
result = eval(expression)
return f"计算结果: {result}"
except Exception as e:
return f"计算错误: {e}"
class FileTool(Tool):
"""文件操作工具"""
def __init__(self):
self.files = {
"readme.txt": "这是一个示例文件。\n包含多行文本。",
"notes.txt": "待办事项:\n1. 学习AI\n2. 实践项目"
}
@property
def name(self) -> str:
return "read_file"
@property
def description(self) -> str:
return "读取文件内容"
def execute(self, filename: str) -> str:
if filename in self.files:
return self.files[filename]
return f"文件不存在: {filename}"
class ListFilesTool(Tool):
"""列出文件工具"""
@property
def name(self) -> str:
return "list_files"
@property
def description(self) -> str:
return "列出可用文件"
def execute(self, input: str) -> str:
return "可用文件: readme.txt, notes.txt"
class ReActAgent:
"""ReAct智能体 - Reasoning + Acting"""
def __init__(self, tools: List[Tool], max_steps: int = 10):
self.tools = {tool.name: tool for tool in tools}
self.max_steps = max_steps
self.history: List[Step] = []
def think(self, query: str) -> str:
"""生成思考(使用LLM时这里是LLM调用)"""
# 简化版:基于规则生成思考
history_text = "\n".join([
f"思考: {step.thought}\n行动: {step.action}\n观察: {step.observation}"
for step in self.history[-3:]
]) if self.history else "无历史"
prompt = f"""你是一个ReAct智能体,需要通过思考和行动来回答问题。
任务:{query}
历史:
{history_text}
请按照以下格式思考下一步:
Thought: [分析当前情况,决定下一步行动]
Action: [工具名称]([参数]) 或 Finish([最终答案])
可用的工具:
{self._format_tools()}"""
# 这里简化处理,实际应调用LLM
return self._simple_reasoning(query)
def _simple_reasoning(self, query: str) -> str:
"""简化推理逻辑(实际使用LLM)"""
query_lower = query.lower()
# 检查是否需要搜索
if any(kw in query_lower for kw in ["什么", "定义", "解释", "介绍"]):
if "计算" in query or any(op in query for op in ["+", "-", "*", "/", "×", "÷"]):
return "我需要先提取表达式,然后使用计算工具。"
return "我需要搜索相关信息来回答这个问题。"
# 检查是否需要文件
if any(kw in query_lower for kw in ["文件", "内容", "read"]):
return "我需要读取文件来获取信息。"
# 检查是否完成
if any(kw in query_lower for kw in ["谢谢", "好的", "明白了"]):
return "Finish(任务完成)"
return "我需要搜索更多信息来回答这个问题。"
def _format_tools(self) -> str:
return "\n".join([f"- {t.name}: {t.description}" for t in self.tools.values()])
def parse_action(self, thought: str) -> Tuple[Optional[Action], str]:
"""解析行动"""
# 检查是否结束
if "Finish(" in thought:
answer = re.search(r'Finish\((.+?)\)', thought)
return Action(ActionType.FINISH, answer.group(1) if answer else ""), "finished"
# 解析行动
for tool_name in self.tools:
if f"{tool_name}(" in thought:
param = re.search(rf'{tool_name}\((.+?)\)', thought)
return Action(ActionType(tool_name), param.group(1) if param else ""), tool_name
return None, "continue"
def run(self, query: str) -> str:
"""执行ReAct循环"""
self.history = []
current_query = query
for step_num in range(self.max_steps):
print(f"\n🔄 步骤 {step_num + 1}")
# 1. Thought
thought = self.think(current_query)
print(f"💭 Thought: {thought}")
# 2. Parse Action
action, status = self.parse_action(thought)
observation = ""
# 3. Action & Observation
if action and action.type != ActionType.FINISH:
print(f"⚡ Action: {action.type.value}[{action.input}]")
tool = self.tools.get(action.type.value)
if tool:
observation = tool.execute(action.input)
else:
observation = "未知工具"
print(f"👀 Observation: {observation}")
elif status == "finished":
print(f"✅ 完成: {action.input}")
return action.input
# 4. 记录步骤
self.history.append(Step(thought, action, observation))
# 5. 更新查询(包含观察结果)
current_query = f"基于观察:{observation}\n继续回答:{query}"
return "达到最大步数限制"
# 使用示例
def main():
# 1. 创建工具
tools = [
SearchTool(),
CalculatorTool(),
FileTool(),
ListFilesTool()
]
# 2. 创建智能体
agent = ReActAgent(tools, max_steps=6)
# 3. 测试不同任务
test_queries = [
"什么是人工智能?",
"计算 25 * 4 + 10",
"readme.txt的内容是什么?"
]
for query in test_queries:
print(f"\n{'='*50}")
print(f"📝 任务: {query}")
print("="*50)
result = agent.run(query)
print(f"\n🎯 最终答案: {result}")
main()