【Hello-Agents】学习笔记(一)

1、什么是智能体

在人工智能领域,智能体被定义为任何能够通过传感器 (Sensors)感知其所处环境(Environment) ,并自主 地通过执行器 (Actuators)采取行动(Action)以达成特定目标的实体。

该定义包含了四个要素:

  • 环境:环境是智能体所处的外部世界。对于自动驾驶汽车,环境是动态变化的道路交通。
  • 感知能力:持续感知环境状态的传感器(摄像头、麦克风、雷达等)或各类应用程序编程接口(API)返回的数据流。
  • 执行器:智能体需要通过执行器来改变环境状态,执行器可以是物理设备(机械臂、方向盘)或虚拟工具(执行一段代码,调用一个服务)。
  • 自主性:自主性是智能体"智能"的基础。智能体并非只是被动响应外部刺激或严格执行预设指令的程序,它能够基于其感知和内部状态进行独立决策,以达成其设计目标。

2、传统智能体

传统智能体演进从结构最简单的反射智能体开始,他们的决策核心由工程师明确设计的"条件---行动"规则构成,这种智能体完全依赖当前的感知输入,不具备记忆和预测能力。

它的局限性引出了一个关键问题:如果环境的当前状态不足以作为决策的全部依据,智能体该怎么办?

研究者引入了"状态"的概念,发展出基于模型的反射智能体。这类智能体拥有一个内部的世界模型,用于追踪和理解环境中那些无法被直接感知的方面。这个内部模型让智能体拥有了初级的"记忆",使其决策不再仅仅依赖于瞬时感知,而是基于一个更连贯、更完整的世界状态理解。

然而,仅仅理解世界还不够,智能体需要有明确的目标。

于是出现了基于目标的智能体。与前两者不同,它的行为不再是被动地对环境做出反应,而是主动地、有预见性地选择能够导向某个特定未来状态的行动。

更进一步,现实世界的目标往往不是单一的。

当多个目标需要权衡时,**基于效用的智能体(Utility-Based Agent)**便随之出现。它为每一个可能的世界状态都赋予一个效用值,这个值代表了满意度的高低。智能体的核心目标不再是简单地达成某个特定状态,而是最大化期望效用。

至此,我们讨论的智能体虽然功能日益复杂,但其核心决策逻辑,无论是规则、模型还是效用函数,依然依赖于人类设计师的先验知识。如果智能体能不依赖预设,而是通过与环境的互动自主学习呢?

这便是**学习型智能体(Learning Agent)的核心思想,而强化学习(Reinforcement Learning, RL)**是实现这一思想最具代表性的路径。一个学习型智能体包含一个性能元件和一个学习元件。学习元件通过观察性能元件在环境中的行动所带来的结果来不断修正性能元件的决策策略。

3、LLM智能体

传统智能体的能力源于工程师的显式编程与知识构建,其行为模式是确定且有边界的;而 LLM 智能体则通过在海量数据上的预训练,获得了隐式的世界模型与强大的涌现能力,使其能够以更灵活、更通用的方式应对复杂任务。

当接收到"规划一次厦门之旅"这样的模糊指令时,LLM智能体的工作方式体现了以下几点:

  • 规划与推理 :智能体首先会将这个高层级目标分解为一系列逻辑子任务,例如:[确认出行偏好] -> [查询目的地信息] -> [制定行程草案] -> [预订票务住宿]。这是一个内在的、由模型驱动的规划过程。
  • 工具使用:在执行规划时,智能体识别到信息缺口,会主动调用外部工具来补全。例如,它会调用天气查询接口获取实时天气,并基于"预报有雨"这一信息,在后续规划中倾向于推荐室内活动。
  • 动态修正 :在交互过程中,智能体会将用户的反馈(如"这家酒店超出预算")视为新的约束,并据此调整后续的行动,重新搜索并推荐符合新要求的选项。整个"查天气 → 调行程 → 订酒店"的流程,展现了其根据上下文动态修正自身行为的能力。

总而言之,我们正从开发专用自动化工具 转向构建能自主解决问题的系统。核心不再是编写代码,而是引导一个通用的"大脑"去规划、行动和学习。

4、智能体分类

4.1、基于内部决策架构分类
  • 反应式智能体
  • 模型式智能体
  • 基于目标智能体
  • 基于效用智能体
  • 学习型智能体
4.2、基于时间预反应性分类
  • 反应式智能体:速度快、计算开销低。
  • 规划式智能体:在行动前会进行复杂的思考和规划。
  • 混合式智能体:复杂任务,既需要及时反应,也需要长远规划。现代智能体是混合式智能体。

规划(Reasoning) :在"思考"阶段,LLM 分析当前状况,规划出下一步的合理行动。这是一个审议过程。

反应(Acting & Observing) :在"行动"和"观察"阶段,智能体与外部工具或环境交互,并立即获得反馈。这是一个反应过程。

4.3、基于知识表示分类
  • 符号主义AI:智能源于对符号的逻辑操作。这里的符号是人类可读的实体(如词语、概念),操作则遵循严格的逻辑规则。
  • 亚符号主义AI:知识并非显式的规则,而是内隐地分布在一个由大量神经元组成的复杂网络中,是从海量数据中学习到的统计模式。神经网络和深度学习是其代表。
  • 神经符号主义AI:既能像神经网络一样从数据中学习,又能像符号系统一样进行逻辑推理的混合智能体。它试图弥合感知与认知、直觉与理性之间的鸿沟。

5、智能体协作模式

基于智能体在任务中的角色和自主性程度,其协作模式主要分为两种:

  • 一种是作为高效工具,深度融入我们的工作流;

    智能体被深度集成到开发者的工作流中,作为辅助工具。

  • 另一种则是作为自主的协作者,与其他智能体协作完成复杂目标。

    在这种模式下,我们不再是手把手地指导 AI 完成每一步,而是将一个高层级的目标委托给它。智能体会像一个真正的项目成员一样,独立地进行规划、推理、执行和反思,直到最终交付成果。

    自主协作模式架构范式可归纳为以下几个主流方向:

    • 单智能体自主循环:其核心是一个通用智能体通过"思考-规划-执行-反思"的闭环,不断进行自我提示和迭代,以完成一个开放式的高层级目标。
    • 多智能体协作:当前最主流探索方向,旨在通过模拟人类团队的协作模式来解决复杂问题。
    • 高级控制流架构:诸如 LangGraph 等框架,则更侧重于为智能体提供更强大的底层工程基础。它将智能体的执行过程建模为状态图(State Graph),从而能更灵活、更可靠地实现循环、分支、回溯以及人工介入等复杂流程。

**Workflow和Agent的差异:**Workflow 是让 AI 按部就班地执行指令,而 Agent 则是赋予 AI 自由度去自主达成目标。

6、实践:5分钟实现一个智能旅游助手

6.1、目标

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

6.2、实现
6.2.1 指令模板

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

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

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

# 行动格式:
你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:
Thought: [这里是你的思考过程和下一步计划]
Action: 你决定采取的行动,必须是以下格式之一:
- `function_name(arg_name="arg_value")`:调用一个可用工具。
- `Finish[最终答案]`:当你认为已经获得最终答案时。
- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。

请开始吧!
"""
6.2.2 定义工具集
python 复制代码
# tools/get_weather_tool.py
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}"
python 复制代码
# tools/search_attraction_tool.py
import os
from tavily import TavilyClient

def get_attraction(city: str, weather: str) -> str:
    """
    根据城市和天气,使用Tavily Search API搜索并返回优化后的景点推荐。
    """
    # 1. 设置API密钥
    api_key = 'YOUR_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}"
python 复制代码
# tools/tools_dic.py
from .get_weather_tool import get_weather
from .search_attraction_tool import get_attraction

# 将所有工具函数放入一个字典,方便后续调用

available_tools = {
  "get_weather": get_weather,
  "get_attraction": get_attraction
}
6.2.3、实现LLM客户端
python 复制代码
# llm_client.py
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.2.4、实现执行器
python 复制代码
# executor.py
import re
import os
from llm_client import OpenAICompatibleClient
from tools.tools_dic import available_tools

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

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

# 行动格式:
你的回答必须严格遵循以下格式。首先是你的思考过程,然后是你要执行的具体行动,每次回复只输出一对Thought-Action:
Thought: [这里是你的思考过程和下一步计划]
Action: 你决定采取的行动,必须是以下格式之一:
- `function_name(arg_name="arg_value")`:调用一个可用工具。
- `Finish[最终答案]`:当你认为已经获得最终答案时。
- 当你收集到足够的信息,能够回答用户的最终问题时,你必须在Action:字段后使用 Finish[最终答案] 来输出最终答案。

请开始吧!
"""

# --- 1. 配置LLM客户端 ---
# 请根据您使用的服务,将这里替换成对应的凭证和地址
API_KEY = "YOUR_API_KEY"
BASE_URL = "YOUR_LLM_BASE_URL"
MODEL = "YOUR_MODEL_NAME"

llm = OpenAICompatibleClient(
    model=MODEL,
    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.3、执行结果
shell 复制代码
$ python  executor.py
用户输入: 你好,请帮我查询一下今天苏州的天气,然后根据天气推荐一个合适的旅游景点。
========================================
--- 循环 1 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 我需要先查询苏州今天的天气情况,然后根据天气情况推荐合适的旅游景点。
Action: get_weather(city="苏州")

Observation: 苏州当前天气:Overcast,气温4摄氏度
========================================
--- 循环 2 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 苏州当前天气为阴天,气温4摄氏度,较为寒冷。在这种天气下,适合推荐一个室内或有遮蔽的景点,以避免寒冷和阴天带来
的不适。
Action: get_attraction(city="苏州", weather="Overcast")

Observation: 在苏州,昆山博物馆和平江石桥在阴天仍然值得一游,因为它们提供室内体验,不受天气影响。
========================================
--- 循环 3 ---

正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 根据苏州的天气情况(阴天,气温4摄氏度),推荐一个适合的室内或有遮蔽的旅游景点。昆山博物馆和平江石桥都是不错的
选择,尤其适合在寒冷阴天游览。
Action: Finish[在苏州阴天且气温较低的情况下,推荐您前往昆山博物馆或平江石桥游览,这两个景点提供舒适的室内或遮蔽环境,
适合当前天气。]

任务完成,最终答案: 在苏州阴天且气温较低的情况下,推荐您前往昆山博物馆或平江石桥游览,这两个景点提供舒适的室内或遮蔽环
境,适合当前天气。

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

Hello-Agents原链接:

https://datawhalechina.github.io/hello-agents/#/

相关推荐
doiito9 小时前
【Agent Harness】Gliding Horse 上下文感知与智能压缩:让 Agent 的“注意力”永不偏移
ai·rust·架构设计·系统设计·ai agent
doiito1 天前
【Agent Harness】Gliding Horse L2 作战地图深度优化:给多 Agent 上下文装上“精准导航”
ai·rust·架构设计·系统设计·ai agent
lincats3 天前
Claude Code项目越写越乱?这套清理流程能救你
ai·ai agent·claude code
doiito3 天前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
lincats4 天前
Claude Code再强,也有这7件事做不了
ai agent·deepseek·claude code
RainCity4 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
doiito4 天前
【Agent Harness】Gliding Horse 的 L2 作战地图:让多 Agent 协作从“摸黑”变成“透明”
ai·rust·架构设计·系统设计·ai agent
doiito6 天前
【Agent Harness】Gliding Horse 工具结果压缩体系:如何用“指针”驯服上下文膨胀
ai·rust·架构设计·系统设计·ai agent
doiito7 天前
【Agent Harness】Gliding Horse 上下文动态感知与智能压缩:让 Agent 真正“听得进”每一句话
ai·rust·架构设计·系统设计·ai agent
doiito8 天前
【Agent Harness】Gliding Horse 记忆系统深度剖析:像 CPU 一样思考的 AI 记忆架构
ai·rust·架构设计·系统设计·ai agent