Agent 工作原理深度笔记:规划 + 工具 + 记忆

关键词:AI Agent、ReAct、工具调用、长期记忆、LangGraph、Multi-Agent


目录

  1. [什么是 AI Agent?](#什么是 AI Agent?)
  2. [Agent 的四大核心组件](#Agent 的四大核心组件)
  3. 规划(Planning):如何分解复杂任务
  4. [工具调用(Tool Use)](#工具调用(Tool Use))
  5. 记忆系统(Memory)
  6. 感知(Perception)
  7. [主流 Agent 框架对比](#主流 Agent 框架对比)
  8. [Multi-Agent 架构](#Multi-Agent 架构)
  9. [代码实战:从零构建 ReAct Agent](#代码实战:从零构建 ReAct Agent)
  10. [Agent 开发踩坑总结](#Agent 开发踩坑总结)

1. 什么是 AI Agent?

AI Agent 是以大语言模型为"大脑",能够自主感知环境、制定计划、调用工具并持续执行直到完成目标的系统。

普通 LLM 应用 vs Agent 的核心区别:

维度 普通 LLM AI Agent
执行方式 单次推理,一问一答 多步执行,持续行动
工具使用 可调用外部工具
规划能力 无(只是回答) 能分解任务、制定步骤
记忆 仅当前上下文窗口 短期+长期记忆
自主性 高(可自行决定下一步)

一个形象的类比:LLM 是一位博学的顾问,你问一次它答一次。Agent 是一位能独立完成任务的员工,你给它一个目标,它自己规划、查资料、写代码、验证结果,直到任务完成。


2. Agent 的四大核心组件

复制代码
┌─────────────────────────────────────────┐
│              AI Agent                   │
│                                         │
│  ┌─────────┐    ┌──────────────────┐   │
│  │  规划   │    │    工具集合       │   │
│  │Planning │    │  搜索/代码/API   │   │
│  └────┬────┘    └──────────────────┘   │
│       │                                │
│  ┌────▼────┐    ┌──────────────────┐   │
│  │  LLM   │◄──►│    记忆系统       │   │
│  │  大脑  │    │ 短期/长期/语义   │   │
│  └────┬────┘    └──────────────────┘   │
│       │                                │
│  ┌────▼────┐                           │
│  │  感知  │ ← 文本/图像/文件/API响应  │
│  └─────────┘                           │
└─────────────────────────────────────────┘

3. 规划(Planning):如何分解复杂任务

3.1 ReAct(Reasoning + Acting)

最经典的 Agent 规划范式,交替进行推理和行动:

复制代码
Thought: 我需要分析销售数据,首先要获取数据文件
Action: read_file("sales_2024.csv")
Observation: [返回 CSV 内容,100行数据]

Thought: 数据已获取,现在需要计算各季度总销售额
Action: python_execute("import pandas as pd; df = pd.read_csv(...)...")
Observation: Q1: 120万, Q2: 145万, Q3: 98万, Q4: 167万

Thought: 数据计算完成,Q4销售额最高,现在生成报告
Action: write_file("sales_report.md", "...")
Observation: 文件已保存

Final Answer: 2024年销售分析完成,Q4表现最佳,年度总额530万元...

3.2 Plan-and-Solve

先制定完整计划,再逐步执行(更适合复杂任务):

复制代码
Step 1: [规划阶段]
  问题:帮我研究并撰写一份关于AI Agent的市场报告
  
  计划:
  1. 搜索AI Agent市场规模数据
  2. 调研主要竞争厂商(OpenAI、Anthropic、Google)
  3. 分析技术趋势
  4. 撰写报告(5000字)
  5. 添加数据可视化

Step 2: [执行阶段]
  依次执行以上步骤...

3.3 Tree of Thought(ToT)

对于需要搜索最优路径的问题,探索多条思维路径并选择最佳:

python 复制代码
# 伪代码:ToT 搜索
def tree_of_thought(problem, max_depth=3, branching_factor=3):
    root = ThoughtNode(problem)
    
    for depth in range(max_depth):
        leaf_nodes = get_leaf_nodes(root)
        
        for node in leaf_nodes:
            # 并行生成多个子思路
            children = [generate_thought(node) for _ in range(branching_factor)]
            # 评估每个思路的价值
            scores = [evaluate_thought(child) for child in children]
            # 保留最优的
            node.children = prune(children, scores, keep_top=2)
    
    return find_best_path(root)

4. 工具调用(Tool Use)

4.1 Function Calling 原理

现代 LLM 的工具调用通过 Function Calling(也叫 Tool Use)实现:

python 复制代码
# 定义工具
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "搜索互联网获取最新信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索关键词"
                    }
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "execute_python",
            "description": "执行 Python 代码",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "要执行的Python代码"}
                },
                "required": ["code"]
            }
        }
    }
]

4.2 常见工具类型

工具类别 示例 作用
搜索工具 Tavily Search、SerpAPI 获取最新网络信息
代码执行 Python REPL、E2B沙箱 运行代码、数据分析
文件操作 读/写文件、PDF解析 处理本地文件
API 调用 天气、股票、日历 接入外部服务
数据库 SQL 执行器 查询结构化数据
多模态 图片生成、OCR 处理非文本内容

4.3 工具设计原则

  1. 单一职责:每个工具只做一件事
  2. 清晰描述description 字段要精确,这是 LLM 决定是否调用的依据
  3. 容错处理:工具要有错误处理,返回格式化的错误信息
  4. 安全边界:代码执行工具要放在沙箱中运行

5. 记忆系统(Memory)

5.1 四种记忆类型

复制代码
记忆类型
├── 感知记忆(Sensory):当前输入的原始信息
├── 短期记忆(Short-term):当前对话的上下文窗口
├── 长期记忆(Long-term)
│   ├── 语义记忆:用户信息、偏好等结构化存储
│   ├── 情节记忆:过去的对话历史(向量检索)
│   └── 程序记忆:如何完成特定任务的知识
└── 外部记忆(External):文档库、数据库等

5.2 短期记忆(对话历史压缩)

上下文窗口有限,需要压缩历史对话:

python 复制代码
from langchain.memory import ConversationSummaryBufferMemory
from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

# 超过 token 限制时自动摘要旧对话
memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=2000,  # 超过此 token 数,旧对话自动摘要
    memory_key="chat_history",
    return_messages=True
)

5.3 长期记忆(向量存储)

将重要信息持久化到向量数据库:

python 复制代码
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from datetime import datetime


class AgentMemory:
    """Agent 长期记忆系统"""
    
    def __init__(self):
        self.embeddings = OpenAIEmbeddings()
        self.vectorstore = Chroma(
            collection_name="agent_memory",
            embedding_function=self.embeddings,
            persist_directory="./agent_memory_db"
        )
    
    def store(self, content: str, metadata: dict = None):
        """存储记忆"""
        meta = {"timestamp": datetime.now().isoformat()}
        if metadata:
            meta.update(metadata)
        
        self.vectorstore.add_texts(
            texts=[content],
            metadatas=[meta]
        )
    
    def recall(self, query: str, k: int = 3) -> list[str]:
        """检索相关记忆"""
        docs = self.vectorstore.similarity_search(query, k=k)
        return [doc.page_content for doc in docs]
    
    def get_relevant_context(self, query: str) -> str:
        """获取格式化的相关记忆"""
        memories = self.recall(query)
        if not memories:
            return ""
        return "相关历史记忆:\n" + "\n".join(f"- {m}" for m in memories)


# 使用
memory = AgentMemory()
memory.store("用户偏好使用简洁的代码风格,不喜欢冗余注释", {"type": "user_preference"})
memory.store("用户在做一个电商平台项目,使用 FastAPI + React", {"type": "project_context"})

context = memory.get_relevant_context("帮我写一个用户认证接口")
print(context)
# 相关历史记忆:
# - 用户偏好使用简洁的代码风格,不喜欢冗余注释
# - 用户在做一个电商平台项目,使用 FastAPI + React

6. 感知(Perception)

现代 Agent 越来越多支持多模态输入:

python 复制代码
from openai import OpenAI
import base64

client = OpenAI()

def analyze_image(image_path: str, question: str) -> str:
    """Agent 感知图像内容"""
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode()
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{image_data}"}
                },
                {"type": "text", "text": question}
            ]
        }]
    )
    return response.choices[0].message.content

7. 主流 Agent 框架对比

框架 特点 适合场景
LangChain 生态完善,组件丰富 快速原型
LangGraph 图状态机,可控性强 复杂工作流
CrewAI Multi-Agent 角色协作 团队协作任务
AutoGen 多 Agent 对话框架 自动化编程
Dify 低代码,可视化 非开发者用户
自研 完全可控 生产级、特殊需求

8. Multi-Agent 架构

8.1 为什么需要多 Agent?

单个 Agent 处理复杂任务时面临:

  • 上下文窗口限制
  • 任务过于复杂,难以规划
  • 不同子任务需要不同专业能力

8.2 常见 Multi-Agent 模式

监督者模式(Supervisor)

复制代码
用户需求
    ↓
[监督者 Agent](任务分配)
  ├── [研究员 Agent](收集信息)
  ├── [分析师 Agent](数据分析)
  └── [写作 Agent](生成报告)
    ↓
最终输出

流水线模式(Pipeline)

复制代码
[爬虫 Agent] → [清洗 Agent] → [分析 Agent] → [报告 Agent]

8.3 CrewAI 多 Agent 示例

python 复制代码
from crewai import Agent, Task, Crew, Process

# 定义 Agent 角色
researcher = Agent(
    role="市场研究员",
    goal="收集最新的 AI Agent 市场数据",
    backstory="你是一位经验丰富的市场研究员,擅长数据收集和信息整合",
    tools=[search_tool],
    verbose=True
)

analyst = Agent(
    role="数据分析师",
    goal="分析研究数据,找出关键趋势",
    backstory="你是一位精通数据分析的专家,善于从数据中发现规律",
    verbose=True
)

writer = Agent(
    role="报告撰写专家",
    goal="将分析结果写成清晰专业的报告",
    backstory="你是一位专业的商业报告撰写者",
    verbose=True
)

# 定义任务
research_task = Task(
    description="搜集2024年AI Agent市场规模、主要玩家和增长趋势数据",
    agent=researcher,
    expected_output="结构化的市场数据摘要"
)

analysis_task = Task(
    description="基于收集的数据,分析市场机会和风险",
    agent=analyst,
    expected_output="SWOT分析和关键洞察"
)

writing_task = Task(
    description="整合研究和分析结果,撰写2000字的市场报告",
    agent=writer,
    expected_output="完整的市场分析报告"
)

# 创建 Crew
crew = Crew(
    agents=[researcher, analyst, writer],
    tasks=[research_task, analysis_task, writing_task],
    process=Process.sequential  # 顺序执行
)

result = crew.kickoff()
print(result)

9. 代码实战:从零构建 ReAct Agent

python 复制代码
"""
从零实现一个 ReAct Agent(不依赖 LangChain)
"""

import json
import re
from openai import OpenAI
from typing import Callable


# ===== 工具定义 =====
def calculator(expression: str) -> str:
    """计算数学表达式"""
    try:
        result = eval(expression, {"__builtins__": {}}, {})
        return str(result)
    except Exception as e:
        return f"计算错误: {e}"


def get_weather(city: str) -> str:
    """获取城市天气(模拟)"""
    weather_data = {
        "北京": "晴天,气温22°C,湿度40%",
        "上海": "多云,气温25°C,湿度70%",
        "广州": "阵雨,气温28°C,湿度85%",
    }
    return weather_data.get(city, f"未找到 {city} 的天气数据")


def search(query: str) -> str:
    """模拟搜索引擎"""
    return f"[搜索结果模拟] 关于'{query}'的搜索结果:这里是相关信息摘要..."


# ===== ReAct Agent 实现 =====
class ReactAgent:
    
    TOOLS = {
        "calculator": calculator,
        "get_weather": get_weather,
        "search": search,
    }
    
    SYSTEM_PROMPT = """你是一个智能助手,可以使用以下工具:
    
- calculator(expression): 计算数学表达式,如 calculator("2 + 3 * 4")
- get_weather(city): 获取城市天气,如 get_weather("北京")
- search(query): 搜索信息,如 search("AI Agent最新进展")

请按照以下格式输出:
Thought: [你的推理过程]
Action: tool_name(参数)
Observation: [等待工具返回结果]
...(可多轮)
Final Answer: [最终回答]

重要:一次只调用一个工具,等待 Observation 后再继续。"""

    def __init__(self):
        self.client = OpenAI()
        self.max_steps = 10
    
    def _parse_action(self, text: str):
        """解析 Action: tool_name(args) 格式"""
        pattern = r'Action:\s*(\w+)\(([^)]*)\)'
        match = re.search(pattern, text)
        if match:
            tool_name = match.group(1)
            args = match.group(2).strip().strip('"\'')
            return tool_name, args
        return None, None
    
    def run(self, user_input: str) -> str:
        """运行 Agent"""
        messages = [
            {"role": "system", "content": self.SYSTEM_PROMPT},
            {"role": "user", "content": user_input}
        ]
        
        for step in range(self.max_steps):
            response = self.client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
                stop=["Observation:"],  # 在 Observation 处停止,等待工具调用
                temperature=0,
            )
            
            assistant_text = response.choices[0].message.content
            messages.append({"role": "assistant", "content": assistant_text})
            
            # 检查是否有最终答案
            if "Final Answer:" in assistant_text:
                final = assistant_text.split("Final Answer:")[-1].strip()
                return final
            
            # 解析并执行工具调用
            tool_name, args = self._parse_action(assistant_text)
            
            if tool_name and tool_name in self.TOOLS:
                result = self.TOOLS[tool_name](args)
                observation = f"Observation: {result}\n"
                print(f"[调用工具] {tool_name}({args}) → {result}")
                messages.append({"role": "user", "content": observation})
            else:
                messages.append({"role": "user", "content": "Observation: 无效的工具调用,请重试\n"})
        
        return "达到最大步骤数,任务未完成"


# ===== 测试 =====
if __name__ == "__main__":
    agent = ReactAgent()
    
    test_questions = [
        "北京现在天气怎么样?气温换算成华氏度是多少?",
        "搜索一下AI Agent的最新进展,并计算 2^10 的值",
    ]
    
    for q in test_questions:
        print(f"\n{'='*50}")
        print(f"问题:{q}")
        print(f"{'='*50}")
        answer = agent.run(q)
        print(f"最终答案:{answer}")

10. Agent 开发踩坑总结

常见问题与解决方案

问题 原因 解决方案
Agent 陷入循环 没有停止条件 设置最大步骤数 + 检测重复 Action
工具调用格式错误 LLM 输出不稳定 使用 Function Calling API,更可靠
长任务上下文溢出 消息历史过长 对历史消息进行摘要压缩
并发 Agent 冲突 共享状态被并发修改 使用锁或消息队列隔离状态
推理费用过高 多步骤消耗大量 Token 减少工具选项,优化 System Prompt

Agent 可靠性提升技巧

  1. Human-in-the-loop:关键操作(发邮件、删除文件)前请求人工确认
  2. 工具调用日志:记录所有工具调用,便于调试和审计
  3. 超时机制:每个工具调用设置超时时间
  4. 幂等性设计:确保工具可以安全地重复调用