初识智能体:从定义、运行机制到 5 分钟旅行助手

摘要:智能体不是只会聊天的模型,而是一个持续“感知、思考、行动、观察”的系统。本文从智能体的定义出发,梳理传统智能体到 LLM 智能体的演进,拆解它的任务环境与运行循环,最后用一份可运行的 Python 代码构建一个真实的旅行助手。


一、先建立一个心智模型:智能体在环境中闭环工作

在人工智能语境中,智能体可以被定义为一个能够通过传感器感知环境,并通过执行器自主采取行动,以达成特定目标的实体。

它有四个基本要素:

要素作用旅行助手中的例子
环境智能体所处并要影响的外部世界用户需求、天气、航班、景点信息
传感器从环境获取信息API、用户输入、搜索服务
执行器对环境施加影响调用天气查询、景点搜索、预订工具
自主性基于感知和内部状态独立决策根据天气动态调整推荐策略

一个智能体的最外层行为,可以抽象成这样一个闭环:

传感器感知

执行器行动

环境

智能体

决策:目标 + 内部状态 + 感知

这里最关键的不是“能调用某个 API”,而是“能根据目标持续调整下一步”。它不是严格按照写死的脚本执行,而是在观察结果之后继续决定下一步做什么。


二、从恒温器到学习型智能体:传统视角的四级演进

在 LLM 出现之前,传统智能体已经走过了一条从简单到复杂、从被动反应到主动学习的演进路线。

简单反射智能体
条件-动作规则

基于模型的反射智能体
维护世界模型

基于目标的智能体
搜索并规划路径

基于效用的智能体
多目标权衡

学习型智能体
通过经验修正策略

2.1 简单反射智能体

它的决策核心是工程师显式编写的“条件-动作”规则,只依赖当前感知。自动恒温器就是典型例子:室温高于设定值就启动制冷。

这种结构可靠、快速,但没有记忆和预测能力,遇到需要上下文的复杂任务就力不从心。

2.2 基于模型的反射智能体

为了解决“当前状态不够用”的问题,研究者引入了内部世界模型。它不只是看当前观察,还会维护一个对外部世界的持续估计。

例如车辆进入隧道后,摄像头暂时看不到前车,但内部模型仍然可以维持前车存在、速度与预估位置的判断。这让智能体拥有了一种初级记忆。

2.3 基于目标的智能体

仅理解世界还不够,智能体需要知道“我要达到什么目标”。基于目标的智能体会主动选择能导向未来目标状态的行动。

GPS 导航是经典例子:目标是到达公司,地图数据是世界模型,A* 等搜索算法负责规划路径。它的核心能力不再是被动响应,而是面向未来进行规划。

2.4 基于效用的智能体

现实目标经常互相冲突,例如既想时间最短,又想省油,还想避开拥堵。基于效用的智能体为不同的世界状态赋予效用值,目标是最大化期望效用,而不是仅仅到达某个状态。

2.5 学习型智能体

前面几类智能体的决策逻辑仍然依赖人类先验知识。学习型智能体增加了一个学习元件,通过观察行为结果不断修正策略。强化学习是最具代表性的路径。

AlphaGo Zero 就体现了这一点:从随机落子开始,通过大量自我对弈和奖励信号,逐渐发现超越人类既有知识的有效棋路。


三、LLM 驱动的新范式:从显式规则到通用大脑

以 GPT 为代表的大语言模型改变了智能体的构建方式。传统智能体的能力来自工程师的显式编程和知识构建,行为确定、边界清晰;LLM 智能体则通过海量数据预训练获得隐式世界模型和语言推理能力,可以处理高层级、模糊的自然语言指令。

3.1 传统智能体与 LLM 智能体的关键差异

维度传统智能体LLM 智能体
核心引擎规则、搜索、效用函数大语言模型
知识来源工程师显式建模海量数据预训练
输入形式结构化状态或特征自然语言、多模态
行为边界相对确定更灵活、更通用
复杂任务处理依赖人工拆解模型驱动规划与工具调用

一个“智能旅行助手”就能体现这种变化。传统做法是用户在天气、地图、订票网站之间切换,自己完成信息整合。LLM 智能体则可以接收“规划一次厦门之旅”,然后自行完成:

  1. 规划与推理:把目标拆成“确认偏好、查询目的地、制定行程、预订票务住宿”。
  2. 工具使用:发现信息缺口后调用天气 API,并根据“预报有雨”偏向推荐室内活动。
  3. 动态修正:收到“酒店超出预算”的反馈后,调整后续搜索条件。

核心不再只是写代码,而是引导一个通用大脑去规划、行动和学习。

3.2 三种分类视角

按内部决策架构分类

这个视角来自经典 AI 教材的框架:从反应式智能体、模型式智能体,到基于目标、基于效用的智能体。学习能力则是一种可以叠加在上述任何类型上的元能力。

按时间与反应性分类

决策速度与规划深度之间存在权衡:

类型特点优点缺点
反应式感知后立即行动快、开销低短视,容易陷入局部最优
规划式行动前探索和评估未来有战略、有远见耗时、计算成本高
混合式快速反应与长远规划结合兼顾灵活性目标性架构更复杂

反应式智能体
感知 -> 行动

混合式智能体
规划与反应微循环

规划式智能体
建模 -> 搜索 -> 评估

适合真实复杂任务

现代 LLM 智能体通常采用混合式运作:在“思考”阶段进行规划,在“行动”与“观察”阶段与环境快速交互,将一个长期目标拆成一系列“规划-反应”微循环。

按知识表示分类

知识到底以什么形式存在于智能体中,是人工智能长期讨论的核心问题:

亚符号主义
神经网络、统计模式

神经符号主义
模式识别 + 逻辑推理

符号主义
规则、知识图谱、逻辑操作

  • 亚符号主义:知识隐式分布在神经网络中,擅长模式识别,但可解释性较弱。
  • 符号主义:知识表现为人类可读的符号和逻辑规则,可解释,但依赖完备规则体系。
  • 神经符号主义:融合两者优势。LLM 智能体就是一个很好的实践,它用神经网络完成语言理解,又通过结构化计划、API 调用等符号化中间步骤完成推理。

四、用 PEAS 和 Agent Loop 理解智能体如何运行

4.1 PEAS:把一个任务环境说清楚

分析智能体时,常用 PEAS 模型描述任务环境,即性能度量、环境、执行器和传感器。

Performance
性能度量

任务环境定义

Environment
环境

Actuators
执行器

Sensors
传感器

以旅行助手为例:

PEAS 项旅行助手的描述
性能度量推荐是否贴合用户偏好、行程是否可行、响应是否及时
环境天气、航班、酒店、景点、价格与余票等实时信息
执行器天气查询、景点搜索、票务预订、自然语言回复
传感器用户输入、API 返回结果、环境变化反馈

LLM 智能体所处的数字环境通常具有这些特性:

  • 部分可观察:一次 API 调用只能看到部分数据,而不是全部实时状态。
  • 随机性:相邻两次票价查询结果可能不同。
  • 多智能体:其他用户、自动化脚本、航司动态调价系统都可能改变环境。
  • 序贯与动态:当前动作会影响未来,环境也可能在决策期间发生变化。

4.2 Agent Loop:感知、思考、行动、观察

智能体不是一次性完成任务的函数,而是一个持续循环:

智能体环境智能体环境Observation(用户请求或环境反馈)Thought(规划 + 工具选择)Action(调用工具 / 改变环境)Observation(工具结果 / 环境状态变化)Thought(综合观察,调整下一步)

这个循环可以拆成四个阶段:

  1. 感知:通过传感器接收观察信息。
  2. 思考:LLM 基于观察和内部记忆更新计划,并选择下一步工具及参数。
  3. 行动:通过执行器调用工具,改变环境状态。
  4. 观察:环境返回新的状态,成为下一轮循环的输入。

五、Thought、Action、Observation:LLM 与外部世界之间的协议

现代智能体框架需要给 LLM 一个明确的输出协议。一次输出不再是单纯的自然语言回复,而是同时包含内部推理和下一步决策。

一个旅行智能体可能输出:

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

外部解析器捕获 Action,调用对应函数。函数返回的原始 JSON 通常含有冗余信息,感知层会把它转换成更适合下一轮推理的观察:

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

随后,这段观察会进入下一轮循环,成为新的输入。

Thought
内部推理

Action
函数调用

Environment / Tool
工具执行

Observation
结果观察

这就是 LLM 智能体把语言推理能力与外部工具能力结合起来的最小闭环。


六、动手实现:5 分钟构建一个智能旅行助手

下面使用 LLM 完成“查询北京天气,再推荐景点”的两步任务,代码结构正好对应前面的 Agent Loop。

6.1 安装依赖

pip install requests tavily-python openai

6.2 指令模板

驱动真实 LLM 的关键是提示工程。这个模板告诉模型它扮演什么角色、拥有哪些工具,以及如何格式化 Thought 和 Action。

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

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

# 输出格式要求:
你的每次回复必须严格遵循以下格式,包含一对Thought和Action:

Thought: [你的思考过程和下一步计划]
Action: [你要执行的具体行动]

Action的格式必须是以下之一:
1. 调用工具:function_name(arg_name="arg_value")
2. 结束任务:Finish[最终答案]

# 重要提示:
- 每次只输出一对Thought-Action
- Action必须在同一行,不要换行
- 当收集到足够信息可以回答用户问题时,必须使用 Action: Finish[最终答案] 格式结束

请开始吧!
"""

6.3 工具一:查询真实天气

import requests

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}"

6.4 工具二:搜索并推荐旅游景点

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,
}

6.5 接入大语言模型

很多服务都遵循 OpenAI 接口规范。下面的客户端可以连接 OpenAI、Azure,以及 Ollama、vLLM 等兼容服务。

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 "错误:调用语言模型服务时出错。"

6.6 执行行动循环

下面的主循环整合模型、提示和工具,完成“调用 LLM 思考、解析 Action、执行工具、记录 Observation”的完整过程。

否

是

是

否

初始化 Prompt History

调用 LLM 生成 Thought / Action

Action 可解析?

写入错误 Observation

是否 Finish?

输出最终答案并退出

按名称调用工具

写入 Observation

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:
        observation = "错误: 未能解析到 Action 字段。请确保你的回复严格遵循 'Thought: ... Action: ...' 的格式。"
        observation_str = f"Observation: {observation}"
        print(f"{observation_str}\n" + "="*40)
        prompt_history.append(observation_str)
        continue
    action_str = action_match.group(1).strip()

    if action_str.startswith("Finish"):
        final_answer = re.match(r"Finish\[(.*)\]", 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)

6.7 运行结果

一个成功的执行流程可能像下面这样,三个循环依次完成“查天气、推荐景点、生成最终答案”:

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

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

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

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

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

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

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

这个案例集中展示了基于 Thought-Action-Observation 范式的四项能力:任务分解、工具调用、上下文理解和结果合成。


七、Workflow 与 Agent:按部就班与目标自治

虽然两者都在做自动化,但底层逻辑不同。简单说,Workflow 是让 AI 按部就班执行指令,Agent 是赋予 AI 自由度去自主达成目标。

维度WorkflowAgent
控制方式预先定义的步骤和分支LLM 根据目标动态规划
适应变化弱,依赖已有规则强,可根据反馈调整
适用场景规则清晰、流程稳定的任务模糊目标、动态信息、多步骤决策
典型例子费用报销审批智能旅行助手

稳定、可预测

灵活、可调整

Workflow
固定步骤 + 条件分支

任务自动化

Agent
目标 + 感知 + 推理 + 工具

Workflow 的优势在于稳定、可预测、容易审计;Agent 的价值在于处理没有写死规则的新情况。以旅行助手为例,如果天气是晴天,它推荐颐和园;如果天气变成雨天,它会自主推理并推荐国家博物馆等室内场所,而无需预先编写 if 天气=晴天 then 推荐颐和园 的规则。


八、小结

智能体的核心不是“会调用工具”,而是拥有一个持续的感知、思考、行动、观察循环:

  • 定义上,它通过传感器感知环境,通过执行器行动,并自主达成目标。
  • 传统智能体沿着“反射、模型、目标、效用、学习”逐步演进。
  • LLM 智能体用通用语言模型作为决策核心,让模糊的自然语言指令可以被逐步拆解和执行。
  • PEAS 描述任务环境,Agent Loop 描述运行机制,Thought-Action-Observation 则是工程落地中的最小交互协议。
  • 一个最小旅行助手只需要指令模板、两个工具、一个 OpenAI 兼容客户端,以及一个解析和执行循环。

把这套结构真正跑通,后面再看 LangChain、LangGraph、CrewAI 等多智能体框架时,会更容易理解它们究竟在替你封装什么。

Logo

更多推荐