第01章:AI Agent的本质——从LLM到自主行动系统

第01章:AI Agent的本质——从LLM到自主行动系统

LLM是大脑,但大脑本身不能行动。Agent是让大脑能感知世界、采取行动、记住经历的系统。理解这个区别,是构建有用Agent的第一步。


1.1 LLM vs Agent:一个关键的区分

很多工程师在第一次接触Agent时犯同一个错误:把LLM的局限当成Agent的局限

LLM(大语言模型)是一个函数:

输入(文本)→ LLM → 输出(文本)

它是无状态的、被动的、单次的。你问它,它答你,然后忘记了。

Agent是一个系统

感知(Perception)→ 规划(Planning)→ 行动(Action)→ 观察(Observation)
                           ↑                              |
                           └────────记忆(Memory)────────┘

Agent的关键特性:

  • 主动性:可以自主执行多步任务,不需要每步都有人类输入
  • 工具使用:可以调用外部工具(搜索/代码执行/API调用)
  • 状态保持:有记忆,能记住对话历史和任务进度
  • 目标导向:有一个目标,不断尝试直到完成

1.2 Agent的四个核心组件

from dataclasses import dataclass, field
from typing import Any

@dataclass
class AgentSystem:
    """
    AI Agent的四个核心组件
    
    这不是代码,是概念模型。
    后续每一章都会深入某个组件。
    """
    
    # 组件1:LLM核心(大脑)
    llm: Any  # GPT-4o / Claude / Gemini
    # 负责:理解输入、规划行动、生成回复
    
    # 组件2:工具(手脚)
    tools: list  # [web_search, code_executor, email_sender, ...]
    # 负责:与外部世界交互,获取信息,执行操作
    
    # 组件3:记忆(记忆系统)
    memory: Any  # 短期记忆 + 长期记忆 + 语义记忆
    # 负责:保持对话上下文,记住重要信息,检索相关经验
    
    # 组件4:规划/编排(工作流)
    orchestrator: Any  # ReAct / LangGraph / 自定义循环
    # 负责:决定执行顺序,处理错误,决定何时停止

1.3 第一个可运行的Agent

从最简单的Agent开始——一个能搜索网络并回答问题的Agent:

from openai import OpenAI
import json
import requests
from typing import Optional

# ====== 工具定义 ======

def web_search(query: str, max_results: int = 3) -> str:
    """
    搜索网络,返回相关结果
    实际使用Tavily API(比SerpAPI更适合AI Agent)
    """
    # 这里使用Tavily Search API
    TAVILY_API_KEY = "your_tavily_api_key"
    
    response = requests.post(
        "https://api.tavily.com/search",
        json={
            "api_key": TAVILY_API_KEY,
            "query": query,
            "max_results": max_results,
            "include_answer": True
        }
    )
    data = response.json()
    
    results = []
    if data.get("answer"):
        results.append(f"快速答案:{data['answer']}")
    
    for r in data.get("results", [])[:max_results]:
        results.append(f"来源:{r['url']}\n内容:{r['content'][:300]}")
    
    return "\n\n".join(results)


def calculate(expression: str) -> str:
    """安全地计算数学表达式"""
    try:
        # 只允许数学运算,防止代码注入
        allowed_chars = set("0123456789+-*/().% ")
        if not all(c in allowed_chars for c in expression):
            return "错误:只允许基本数学运算"
        result = eval(expression)
        return str(result)
    except Exception as e:
        return f"计算错误:{str(e)}"


# ====== 工具注册(OpenAI Function Calling格式) ======

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "搜索互联网获取最新信息。适合:当前事件、最新数据、事实核查",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "搜索查询词"
                    },
                    "max_results": {
                        "type": "integer",
                        "description": "返回结果数量,默认3",
                        "default": 3
                    }
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "计算数学表达式",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如 '2 + 3 * 4'"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

# 工具执行映射
TOOL_FUNCTIONS = {
    "web_search": web_search,
    "calculate": calculate
}


# ====== Agent核心循环 ======

class SimpleAgent:
    """
    最基础的Agent实现
    展示Agent的核心循环:思考→工具调用→观察→再思考
    """
    
    def __init__(self, model: str = "gpt-4o"):
        self.client = OpenAI()
        self.model = model
        self.system_prompt = """你是一个有用的AI助手,可以搜索网络和进行计算。
        
        当你需要获取最新信息时,使用web_search工具。
        当你需要计算时,使用calculate工具。
        
        始终基于工具返回的真实信息回答,不要编造信息。"""
    
    def run(self, user_message: str, max_iterations: int = 5) -> str:
        """
        Agent主循环
        
        循环逻辑:
        1. LLM决定是否需要调用工具
        2. 如果需要,执行工具,将结果返回给LLM
        3. LLM根据工具结果继续思考
        4. 直到LLM不再需要工具,给出最终回答
        """
        messages = [
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": user_message}
        ]
        
        for iteration in range(max_iterations):
            print(f"\n[迭代 {iteration + 1}]")
            
            # LLM决策:是否需要工具?
            response = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                tools=TOOLS,
                tool_choice="auto"  # 让LLM自己决定
            )
            
            message = response.choices[0].message
            
            # 情况1:LLM决定不需要工具,直接给出回答
            if not message.tool_calls:
                print(f"[最终回答] {message.content}")
                return message.content
            
            # 情况2:LLM要调用工具
            messages.append(message)
            
            for tool_call in message.tool_calls:
                tool_name = tool_call.function.name
                tool_args = json.loads(tool_call.function.arguments)
                
                print(f"[调用工具] {tool_name}({tool_args})")
                
                # 执行工具
                if tool_name in TOOL_FUNCTIONS:
                    tool_result = TOOL_FUNCTIONS[tool_name](**tool_args)
                else:
                    tool_result = f"工具 {tool_name} 不存在"
                
                print(f"[工具结果] {tool_result[:200]}...")
                
                # 将工具结果追加到对话
                messages.append({
                    "role": "tool",
                    "content": tool_result,
                    "tool_call_id": tool_call.id
                })
        
        return "达到最大迭代次数,任务未完成"


# ====== 使用示例 ======

if __name__ == "__main__":
    agent = SimpleAgent()
    
    # 测试1:需要搜索的问题
    result = agent.run("GPT-4o mini的价格是多少?和GPT-4o相比如何?")
    print(f"\n最终回答:{result}")
    
    # 测试2:需要计算的问题
    result = agent.run("如果我有1000美元,按5%年利率复利投资10年,最终会有多少钱?")
    print(f"\n最终回答:{result}")
    
    # 测试3:需要搜索+计算的问题
    result = agent.run("今天比特币的价格是多少?如果我在2020年初用1万美元买了比特币,现在值多少?")
    print(f"\n最终回答:{result}")

1.4 Agent的分类:从简单到复杂

AGENT_TAXONOMY = {
    "simple_tool_use": {
        "description": "单一LLM + 工具调用",
        "example": "上面的SimpleAgent",
        "complexity": "低",
        "use_cases": ["问答助手", "简单自动化任务"],
        "limitation": "单轮任务,没有持久记忆"
    },
    "react_agent": {
        "description": "思考-行动-观察的明确循环(第03章详解)",
        "complexity": "中",
        "use_cases": ["多步骤研究任务", "代码调试"],
        "advantage": "透明度高,每步都有明确的思考过程"
    },
    "plan_and_execute": {
        "description": "先生成完整计划,再按计划执行",
        "complexity": "中",
        "use_cases": ["结构化长任务", "项目分解"],
        "advantage": "适合长任务,减少中途偏离"
    },
    "multi_agent": {
        "description": "多个专业Agent协作(第07章详解)",
        "complexity": "高",
        "use_cases": ["复杂研究报告", "代码生成+审查+测试"],
        "advantage": "专业化分工,并行执行,更高质量"
    },
    "agentic_workflow": {
        "description": "确定性流程 + LLM决策节点(第06章LangGraph)",
        "complexity": "高",
        "use_cases": ["企业流程自动化", "生产级Agent"],
        "advantage": "可靠性最高,适合生产环境"
    }
}

1.5 Agent的核心挑战

在进入实现之前,必须正视Agent当前的局限性:

AGENT_CHALLENGES = {
    "reliability": {
        "problem": "LLM在复杂任务中会出错、绕路、幻觉",
        "current_reality": "State of the art的Agent在复杂任务上成功率约50–70%",
        "mitigation": [
            "任务分解(把大任务拆成小任务)",
            "验证节点(每步关键操作都验证结果)",
            "人工审批(关键决策点让人类介入)"
        ]
    },
    "cost": {
        "problem": "多轮LLM调用 + 工具调用成本快速积累",
        "example": "一个10步的研究任务,用GPT-4o可能花$0.5–2",
        "mitigation": [
            "使用更便宜的模型做简单步骤(GPT-4o mini)",
            "缓存LLM响应",
            "合理设置最大迭代次数"
        ]
    },
    "latency": {
        "problem": "多步串行执行,总延迟 = 每步延迟之和",
        "example": "10步 × 每步3秒 = 30秒,用户体验差",
        "mitigation": [
            "流式输出(streaming)让用户看到进度",
            "可并行的步骤并行执行",
            "缓存重复的工具调用"
        ]
    },
    "security": {
        "problem": "Agent可以执行任意代码/API调用,有安全风险",
        "examples": ["Prompt注入攻击", "工具滥用", "数据泄露"],
        "mitigation": [
            "工具沙箱(限制工具的能力范围)",
            "人工审批节点(危险操作必须人工确认)",
            "输入/输出过滤(第09章详解)"
        ]
    }
}

1.6 选择合适的Agent框架

FRAMEWORK_COMPARISON = {
    "raw_openai_api": {
        "pros": ["最灵活", "无额外依赖", "最好理解底层"],
        "cons": ["需要自己实现所有东西"],
        "use_when": "学习阶段 / 简单单步Agent"
    },
    "langchain": {
        "pros": ["生态最大", "工具最多", "文档最完善"],
        "cons": ["抽象层太多", "调试困难", "版本更新频繁"],
        "use_when": "快速原型 / 需要大量现成工具"
    },
    "langgraph": {
        "pros": ["状态机模型", "适合复杂工作流", "循环控制完善"],
        "cons": ["学习曲线"],
        "use_when": "生产级Agent / 需要精确控制执行流程"
    },
    "crewai": {
        "pros": ["多Agent协作直观", "角色定义清晰"],
        "cons": ["不如LangGraph灵活"],
        "use_when": "多Agent协作场景 / 角色化任务"
    },
    "autogen": {
        "pros": ["多Agent对话自然", "微软维护"],
        "cons": ["对话型不适合结构化工作流"],
        "use_when": "多Agent讨论/辩论场景"
    }
}

# 本书选择
BOOK_FRAMEWORK_CHOICES = {
    "chapters_1_4": "原生OpenAI API(理解底层)",
    "chapters_5_6": "LangChain + LangGraph",
    "chapter_7": "CrewAI + AutoGen",
    "chapters_8_12": "生产架构(框架无关)"
}

1.7 Agent评估的基础框架

在开始构建之前,先建立评估框架——这决定了你能否知道你的Agent"够好了":

AGENT_EVALUATION_FRAMEWORK = {
    "task_success_rate": {
        "definition": "完全正确完成任务的比例",
        "target": "生产环境至少95%",
        "how_to_measure": "准备100个有标准答案的测试用例"
    },
    "tool_call_accuracy": {
        "definition": "工具调用是否合适(调用了正确的工具,参数正确)",
        "target": ">98%",
        "how_to_measure": "记录工具调用日志,人工抽样审查"
    },
    "cost_per_task": {
        "definition": "完成一个标准任务的平均LLM成本",
        "target": "根据商业模式确定上限",
        "how_to_measure": "通过LLM provider的用量统计"
    },
    "latency_p95": {
        "definition": "95%的任务完成时间",
        "target": "根据用户体验要求确定(通常<30秒)",
        "how_to_measure": "在生产环境记录任务开始到完成时间"
    },
    "hallucination_rate": {
        "definition": "Agent给出事实性错误信息的比例",
        "target": "<1%(关键领域)",
        "how_to_measure": "抽样人工审查 + 自动化事实核查"
    }
}

本章小结

  1. Agent = LLM + 工具 + 记忆 + 规划,是一个系统,不只是一个更好的LLM调用
  2. Agent的核心循环:感知→规划→行动→观察→(记忆更新)→循环
  3. 第一个可运行的Agent只需要:LLM + 工具定义 + 工具执行映射 + 主循环
  4. Agent的核心挑战:可靠性、成本、延迟、安全——这些都有工程解法
  5. 在选框架之前先理解底层:原生API → LangChain → LangGraph

行动项:运行本章的SimpleAgent代码(需要OpenAI API Key和Tavily API Key),用3个不同类型的问题测试它,观察它是否正确决定何时使用哪个工具。