第一章 初识智能体

一、智能体的运行机制

我们来探讨其核心的运行机制。智能体并非一次性完成任务,而是通过一个持续的循环与环境进行交互,这个核心机制被称为 智能体循环 (Agent Loop)。如图所示,该循环描述了智能体与环境之间的动态交互过程,构成了其自主行为的基础。

这个循环主要包含以下几个相互关联的阶段:

  1. 感知 (Perception):这是循环的起点。智能体通过其传感器(例如,API 的监听端口、用户输入接口)接收来自环境的输入信息。这些信息,即观察 (Observation),既可以是用户的初始指令,也可以是上一步行动所导致的环境状态变化反馈。
  2. 思考 (Thought):接收到观察信息后,智能体进入其核心决策阶段。对于 LLM 智能体而言,这通常是由大语言模型驱动的内部推理过程。如图所示,"思考"阶段可进一步细分为两个关键环节:
    • 规划 (Planning):智能体基于当前的观察和其内部记忆,更新对任务和环境的理解,并制定或调整一个行动计划。这可能涉及将复杂目标分解为一系列更具体的子任务。
    • 工具选择 (Tool Selection):根据当前计划,智能体从其可用的工具库中,选择最适合执行下一步骤的工具,并确定调用该工具所需的具体参数。
  3. 行动 (Action):决策完成后,智能体通过其执行器(Actuators)执行具体的行动。这通常表现为调用一个选定的工具(如代码解释器、搜索引擎 API),从而对环境施加影响,意图改变环境的状态。
  • 行动并非循环的终点。智能体的行动会引起环境 (Environment) 的状态变化 (State Change),环境随即会产生一个新的观察 (Observation) 作为结果反馈。这个新的观察又会在下一轮循环中被智能体的感知系统捕获,形成一个持续的"感知-思考-行动-观察"的闭环。智能体正是通过不断重复这一循环,逐步推进任务,从初始状态向目标状态演进。

二、智能体的感知与行动

在工程实践中,为了让 LLM 能够有效驱动这个循环,我们需要一套明确的交互协议 (Interaction Protocol) 来规范其与环境之间的信息交换。

在许多现代智能体框架中,这一协议体现在对智能体每一次输出的结构化定义上。智能体的输出不再是单一的自然语言回复,而是一段遵循特定格式的文本,其中明确地展示了其内部的推理过程与最终决策。

  • 这个结构通常包含两个核心部分:

    • Thought (思考):这是智能体内部决策的"快照"。它以自然语言形式阐述了智能体如何分析当前情境、回顾上一步的观察结果、进行自我反思与问题分解,并最终规划出下一步的具体行动。
    • Action (行动):这是智能体基于思考后,决定对环境施加的具体操作,通常以函数调用的形式表示。
  • 例如,一个正在规划旅行的智能体可能会生成如下格式化的输出:

    Thought: 用户想知道北京的天气。我需要调用天气查询工具。
    Action: get_weather("北京")

这里的Action字段构成了对外部世界的指令。一个外部的解析器 (Parser) 会捕捉到这个指令,并调用相应的get_weather函数。

行动执行后,环境会返回一个结果。例如,get_weather函数可能返回一个包含详细天气数据的 JSON 对象。然而,原始的机器可读数据(如 JSON)通常包含 LLM 无需关注的冗余信息,且格式不符合其自然语言处理的习惯。

因此,感知系统的一个重要职责就是扮演传感器的角色:将这个原始输出处理并封装成一段简洁、清晰的自然语言文本,即观察。

复制代码
Observation: 北京当前天气为晴,气温25摄氏度,微风。

这段Observation文本会被反馈给智能体,作为下一轮循环的主要输入信息,供其进行新一轮的Thought和Action。

综上所述,通过这个由 Thought、Action、Observation 构成的严谨循环,LLM 智能体得以将内部的语言推理能力,与外部环境的真实信息和工具操作能力有效地结合起来。

动手体验:5 分钟实现第一个智能体

在前面的小节,我们学习了智能体的任务环境、核心运行机制以及 Thought-Action-Observation 交互范式。理论知识固然重要,但最好的学习方式是亲手实践。在本节中,我们将引导您使用几行简单的 Python 代码,从零开始构建一个可以工作的智能旅行助手。这个过程将遵循我们刚刚学到的理论循环,让您直观地感受到一个智能体是如何"思考"并与外部"工具"互动的。让我们开始吧!

在本案例中,我们的目标是构建一个能处理分步任务的智能旅行助手。需要解决的用户任务定义为:"你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。"要完成这个任务,智能体必须展现出清晰的逻辑规划能力。它需要先调用天气查询工具,并将获得的观察结果作为下一步的依据。在下一轮循环中,它再调用景点推荐工具,从而得出最终建议。

1 准备工作

为了能从 Python 程序中访问网络 API,我们需要一个 HTTP 库。requests是 Python 社区中最流行、最易用的选择。tavily-python是一个强大的 AI 搜索 API 客户端,用于获取实时的网络搜索结果,可以在官网注册后获取 API。openai是 OpenAI 官方提供的 Python SDK,用于调用 GPT 等大语言模型服务。请先通过以下命令安装它们:

复制代码
pip install requests tavily-python openai
1)指令模板

驱动真实 LLM 的关键在于提示工程(Prompt Engineering)。我们需要设计一个"指令模板",告诉 LLM 它应该扮演什么角色、拥有哪些工具、以及如何格式化它的思考和行动。这是我们智能体的"说明书",它将作为system_prompt传递给 LLM。

复制代码
AGENT_SYSTEM_PROMPT = """
你是一个智能旅行助手。你的任务是分析用户的请求,并使用可用工具一步步地解决问题。

# 可用工具:
- `get_weather(city: str)`: 查询指定城市的实时天气。
- `get_attraction(city: str, weather: str)`: 根据城市和天气搜索推荐的旅游景点。

# 行动格式:
你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:
Thought: [这里是你的思考过程和下一步计划]
Action: [这里是你要调用的工具,格式为 function_name(arg_name="arg_value")]

# 任务完成:
当你收集到足够的信息,能够回答用户的最终问题时,你必须在`Action:`字段后使用 `finish(answer="...")` 来输出最终答案。

请开始吧!
"""
(2)工具 1:查询真实天气

我们将使用免费的天气查询服务 wttr.in,它能以 JSON 格式返回指定城市的天气数据。下面是实现该工具的代码:

复制代码
import requests
import json

def get_weather(city: str) -> str:
    """
    通过调用 wttr.in API 查询真实的天气信息。
    """
    # API端点,我们请求JSON格式的数据
    url = f"https://wttr.in/{city}?format=j1"
    
    try:
        # 发起网络请求
        response = requests.get(url)
        # 检查响应状态码是否为200 (成功)
        response.raise_for_status() 
        # 解析返回的JSON数据
        data = response.json()
        
        # 提取当前天气状况
        current_condition = data['current_condition'][0]
        weather_desc = current_condition['weatherDesc'][0]['value']
        temp_c = current_condition['temp_C']
        
        # 格式化成自然语言返回
        return f"{city}当前天气:{weather_desc},气温{temp_c}摄氏度"
        
    except requests.exceptions.RequestException as e:
        # 处理网络错误
        return f"错误:查询天气时遇到网络问题 - {e}"
    except (KeyError, IndexError) as e:
        # 处理数据解析错误
        return f"错误:解析天气数据失败,可能是城市名称无效 - {e}"
(3)工具 2:搜索并推荐旅游景点

我们将定义一个新工具 search_attraction,它会根据城市和天气状况,互联网上搜索合适的景点:

复制代码
import os
from tavily import TavilyClient

def get_attraction(city: str, weather: str) -> str:
    """
    根据城市和天气,使用Tavily Search API搜索并返回优化后的景点推荐。
    """
    # 1. 从环境变量中读取API密钥
    api_key = os.environ.get("TAVILY_API_KEY")
    if not api_key:
        return "错误:未配置TAVILY_API_KEY环境变量。"

    # 2. 初始化Tavily客户端
    tavily = TavilyClient(api_key=api_key)
    
    # 3. 构造一个精确的查询
    query = f"'{city}' 在'{weather}'天气下最值得去的旅游景点推荐及理由"
    
    try:
        # 4. 调用API,include_answer=True会返回一个综合性的回答
        response = tavily.search(query=query, search_depth="basic", include_answer=True)
        
        # 5. Tavily返回的结果已经非常干净,可以直接使用
        # response['answer'] 是一个基于所有搜索结果的总结性回答
        if response.get("answer"):
            return response["answer"]
        
        # 如果没有综合性回答,则格式化原始结果
        formatted_results = []
        for result in response.get("results", []):
            formatted_results.append(f"- {result['title']}: {result['content']}")
        
        if not formatted_results:
             return "抱歉,没有找到相关的旅游景点推荐。"

        return "根据搜索,为您找到以下信息:\n" + "\n".join(formatted_results)

    except Exception as e:
        return f"错误:执行Tavily搜索时出现问题 - {e}"

最后,我们将所有工具函数放入一个字典,供主循环调用:

复制代码
# 将所有工具函数放入一个字典,方便后续调用
available_tools = {
    "get_weather": get_weather,
    "get_attraction": get_attraction,
}

2 接入大语言模型

当前,许多 LLM 服务提供商(包括 OpenAI、Azure、以及众多开源模型服务框架如 Ollama、vLLM 等)都遵循了与 OpenAI API 相似的接口规范。这种标准化为开发者带来了极大的便利。智能体的自主决策能力来源于 LLM。我们将实现一个通用的客户端 OpenAICompatibleClient,它可以连接到任何兼容 OpenAI 接口规范的 LLM 服务。

复制代码
from openai import OpenAI

class OpenAICompatibleClient:
    """
    一个用于调用任何兼容OpenAI接口的LLM服务的客户端。
    """
    def __init__(self, model: str, api_key: str, base_url: str):
        self.model = model
        self.client = OpenAI(api_key=api_key, base_url=base_url)

    def generate(self, prompt: str, system_prompt: str) -> str:
        """调用LLM API来生成回应。"""
        print("正在调用大语言模型...")
        try:
            messages = [
                {'role': 'system', 'content': system_prompt},
                {'role': 'user', 'content': prompt}
            ]
            response = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                stream=False
            )
            answer = response.choices[0].message.content
            print("大语言模型响应成功。")
            return answer
        except Exception as e:
            print(f"调用LLM API时发生错误: {e}")
            return "错误:调用语言模型服务时出错。"

要实例化此类,您需要提供三个信息:API_KEY、BASE_URL 和 MODEL_ID,具体值取决于您使用的服务商(如 OpenAI 官方、Azure、或 Ollama 等本地模型),如果暂时没有渠道获取,可以参考

3 执行行动循环

下面的主循环将整合所有组件,并通过格式化后的 Prompt 驱动 LLM 进行决策。

复制代码
import re

# --- 1. 配置LLM客户端 ---
# 请根据您使用的服务,将这里替换成对应的凭证和地址
API_KEY = "YOUR_API_KEY"
BASE_URL = "YOUR_BASE_URL"
MODEL_ID = "YOUR_MODEL_ID"
TAVILY_API_KEY="YOUR_Tavily_KEY"
os.environ['TAVILY_API_KEY'] = "YOUR_TAVILY_API_KEY"

llm = OpenAICompatibleClient(
    model=MODEL_ID,
    api_key=API_KEY,
    base_url=BASE_URL
)

# --- 2. 初始化 ---
user_prompt = "你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。"
prompt_history = [f"用户请求: {user_prompt}"]

print(f"用户输入: {user_prompt}\n" + "="*40)

# --- 3. 运行主循环 ---
for i in range(5): # 设置最大循环次数
    print(f"--- 循环 {i+1} ---\n")
    
    # 3.1. 构建Prompt
    full_prompt = "\n".join(prompt_history)
    
    # 3.2. 调用LLM进行思考
    llm_output = llm.generate(full_prompt, system_prompt=AGENT_SYSTEM_PROMPT)
    # 模型可能会输出多余的Thought-Action,需要截断
    match = re.search(r'(Thought:.*?Action:.*?)(?=\n\s*(?:Thought:|Action:|Observation:)|\Z)', llm_output, re.DOTALL)
    if match:
        truncated = match.group(1).strip()
        if truncated != llm_output.strip():
            llm_output = truncated
            print("已截断多余的 Thought-Action 对")
    print(f"模型输出:\n{llm_output}\n")
    prompt_history.append(llm_output)
    
    # 3.3. 解析并执行行动
    action_match = re.search(r"Action: (.*)", llm_output, re.DOTALL)
    if not action_match:
        print("解析错误:模型输出中未找到 Action。")
        break
    action_str = action_match.group(1).strip()

    if action_str.startswith("finish"):
        final_answer = re.search(r'finish\(answer="(.*)"\)', action_str).group(1)
        print(f"任务完成,最终答案: {final_answer}")
        break
    
    tool_name = re.search(r"(\w+)\(", action_str).group(1)
    args_str = re.search(r"\((.*)\)", action_str).group(1)
    kwargs = dict(re.findall(r'(\w+)="([^"]*)"', args_str))

    if tool_name in available_tools:
        observation = available_tools[tool_name](**kwargs)
    else:
        observation = f"错误:未定义的工具 '{tool_name}'"

    # 3.4. 记录观察结果
    observation_str = f"Observation: {observation}"
    print(f"{observation_str}\n" + "="*40)
    prompt_history.append(observation_str)

通过以上步骤,我们构建了一个完整的、由真实 LLM 驱动的智能体。其核心在于"工具"和"提示工程"的结合,这正是当前主流智能体框架(如 LangChain、LlamaIndex 等)的设计精髓。

4 运行案例分析

以下输出完整地展示了一个成功的智能体执行流程。通过对这个三轮循环的分析,我们可以清晰地看到智能体解决问题的核心能力。

复制代码
用户输入: 你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。
========================================
--- 循环 1 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 首先需要获取北京今天的天气情况,之后再根据天气情况来推荐旅游景点。
Action: get_weather(city="北京")

Observation: 北京当前天气:Sunny,气温26摄氏度
========================================      
--- 循环 2 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 现在已经知道了北京今天的天气是晴朗且温度适中,接下来可以基于这个信息来推荐一个适合的旅游景点了。
Action: get_attraction(city="北京", weather="Sunny")

Observation: 北京在晴天最值得去的旅游景点是颐和园,因其美丽的湖景和古建筑。另一个推荐是长城,因其壮观的景观和历史意义。
========================================
--- 循环 3 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 已经获得了两个适合晴天游览的景点建议,现在可以根据这些信息给用户提供满意的答复。
Action: finish(answer="今天北京的天气是晴朗的,气温26摄氏度,非常适合外出游玩。我推荐您去颐和园欣赏美丽的湖景和古建筑,或者前往长城体验其壮观的景观和深厚的历史意义。希望您有一个愉快的旅行!
")

任务完成,最终答案: 今天北京的天气是晴朗的,气温26摄氏度,非常适合外出游玩。我推荐您去颐和园欣赏美丽的湖景和古建筑,或者前往长城体验其壮观的景观和深厚的历史意义。希望您有一个愉快的旅行!

这个简单的旅行助手案例,集中演示了基于Thought-Action-Observation范式的智能体所具备的四项基本能力:任务分解、工具调用、上下文理解和结果合成。正是通过这个循环的不断迭代,智能体才得以将一个模糊的用户意图,转化为一系列具体、可执行的步骤,并最终达成目标。

5 Workflow 和 Agent 的差异

在理解了智能体作为"工具"和"协作者"两种模式后,我们有必要对 Workflow 和 Agent 的差异展开讨论,尽管它们都旨在实现任务自动化,但其底层逻辑、核心特征和适用场景却截然不同。

简单来说,Workflow 是让 AI 按部就班地执行指令,而 Agent 则是赋予 AI 自由度去自主达成目标。

如图所示,工作流是一种传统的自动化范式,其核心是对一系列任务或步骤进行预先定义的、结构化的编排。它本质上是一个精确的、静态的流程图,规定了在何种条件下、以何种顺序执行哪些操作。一个典型的案例:某企业的费用报销审批流程。员工提交报销单(触发)-> 如果金额小于 500 元,直接由部门经理审批 -> 如果金额大于 500 元,先由部门经理审批,再流转至财务总监审批 -> 审批通过后,通知财务部打款。整个过程的每一步、每一个判断条件都被精确地预先设定。

  1. 与工作流不同,基于大型语言模型的智能体是一个具备自主性的、以目标为导向的系统。它不仅仅是执行预设指令,而是能够在一定程度上理解环境、进行推理、制定计划,并动态地采取行动以达成最终目标。LLM 在其中扮演着"大脑"的角色。一个典型的例子,便是我们写的智能旅行助手。当我们向它下达一个新指令,例如:"你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。" 它的处理过程充分展现了其自主性:
  2. 规划与工具调用: Agent 首先会把任务拆解为两个步骤:① 查询天气;② 基于天气推荐景点。随即,它会自主选择并调用"天气查询 API",并将"北京"作为参数传入。
    推理与决策: 假设 API 返回结果为"晴朗,微风"。Agent 的 LLM 大脑会基于这个信息进行推理:"晴天适合户外活动"。接着,它会根据这个判断,在它的知识库或通过搜索引擎这个工具中,筛选出北京的户外景点,如故宫、颐和园、天坛公园等。
  3. 生成结果: 最后,Agent 会综合信息,给出一个完整的、人性化的回答:"今天北京天气晴朗,微风,非常适合户外游玩。为您推荐前往【颐和园】,您可以在昆明湖上泛舟,欣赏美丽的皇家园林景色。"
  4. 在这个过程中,没有任何写死的if天气=晴天 then 推荐颐和园的规则。如果天气是"雨天",Agent 会自主推理并推荐国家博物馆、首都博物馆等室内场所。这种基于实时信息进行动态推理和决策的能力,正是 Agent 的核心价值所在。
相关推荐
百锦再5 小时前
国产数据库的平替亮点——关系型数据库架构适配
android·java·前端·数据库·sql·算法·数据库架构
晨曦夜月6 小时前
笔试强训day5
数据结构·算法
H_z___6 小时前
Hz的计数问题总结
数据结构·算法
她说彩礼65万6 小时前
C# 反射
java·算法·c#
练习时长一年6 小时前
LeetCode热题100(搜索插入位置)
数据结构·算法·leetcode
hz_zhangrl6 小时前
CCF-GESP 等级考试 2025年9月认证C++六级真题解析
c++·算法·青少年编程·程序设计·gesp·2025年9月gesp·gesp c++六级
喇一渡渡6 小时前
Java力扣---滑动窗口(1)
java·算法·排序算法
net3m336 小时前
雅特力单片机用串口USART_INT_TDE中断比用USART_INT_TRAC的 发送效率要高
java·开发语言·算法