Hello-Agents —— 01 初识智能体
1.什么是智能体
在探索任何一个复杂概念时,我们最好从一个简洁的定义开始。在人工智能领域,智能体被定义为任何能够通过传感器(Sensors)感知其所处环境(Environment),并自主地通过执行器(Actuators)采取行动(Action)以达成特定目标的实体。
智能体的四个基本要素可概括为:环境,即智能体所处并需要感知的外部世界;传感器,用于持续感知环境状态;执行器,用于对环境施加影响并采取行动;自主性,使智能体能够基于感知和内部状态独立决策,以达成目标,从而形成“感知→决策→行动”的闭环。
2. 智能体的核心组成
下图展示了四个核心组件之间的协作关系:大模型作为中枢负责理解与决策,规划负责拆解任务,工具负责执行具体操作,记忆负责保存上下文与经验。
flowchart TD
A[用户输入] --> B[大模型 LLM]
B --> C[规划 Planning]
C --> D[工具 Tools]
D --> E[执行结果]
E --> B
B --> F[记忆 Memory]
F --> B
B --> G[最终回答]
数据流向说明:用户输入首先进入大模型,大模型结合记忆中的上下文进行理解与推理,生成任务规划;规划进一步拆解为可执行的子步骤并调用相应工具;工具执行后把结果返回给大模型,大模型综合工具结果与记忆信息生成最终回答,同时将本次交互写入记忆,供后续任务复用。
一个完整的智能体通常由以下四个核心部分组成:
- 大模型(LLM):智能体的「大脑」,负责理解用户意图、生成推理和决策。
- 规划(Planning):将复杂任务拆解为可执行的子步骤,并决定执行顺序。
- 工具(Tools):智能体调用外部能力(如搜索、代码执行、API 调用)来完成具体操作。
- 记忆(Memory):保存短期对话上下文和长期经验,帮助智能体持续改进。
3. 智能体与普通程序的区别
普通程序按照预设逻辑线性执行,而智能体能够根据环境反馈动态调整策略。两者的关键差异体现在以下几个方面:
| 对比维度 | 普通程序 | 智能体 |
|---|---|---|
| 执行方式 | 固定流程 | 动态决策 |
| 环境感知 | 有限 | 持续感知与反馈 |
| 目标导向 | 完成指定步骤 | 自主拆解并达成目标 |
| 学习能力 | 无 | 可通过记忆与经验改进 |
4. 一个简单的智能体示例
4.1 提示工程(Prompt Engineering)
驱动真实 LLM 的关键在于提示工程(Prompt Engineering)。我们需要设计一个“指令模板”,告诉 LLM 它应该扮演什么角色、拥有哪些工具、以及如何格式化它的思考和行动。这是我们智能体的“说明书”,它将作为system_prompt传递给 LLM。
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[最终答案] 格式结束
请开始吧!
"""
4.2 工具函数构建
我们将构建 get_weather 使用免费的天气查询服务 wttr.in,它能以 JSON 格式返回指定城市的天气数据。同时我们定义一个新工具 get_attraction,它会根据城市和天气状况,在互联网上搜索合适的景点,新建tools.py文件
import requests
import os
from tavily import TavilyClient
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}"
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,
}
4.3 构建agent
我们将实现一个通用的客户端 OpenAICompatibleClient,它可以连接到任何兼容 OpenAI 接口规范的 LLM 服务。并整合所有组件到主循环中,并通过格式化后的 Prompt 驱动 LLM 进行决策。
import re
import os
from openai import OpenAI
from tools import available_tools
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 "错误:调用语言模型服务时出错。"
# --- 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)
4.4 agent 结果输出如下所示:
用户输入: 你好,请帮我查询一下今天北京的天气,然后根据天气推荐一个合适的旅游景点。
========================================
--- 循环 1 ---
正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 用户需要先了解北京今天的天气,我再根据天气推荐合适的旅游景点。现在先查询北京实时天气。
Action: get_weather(city="北京")
Observation: 北京当前天气:Smoky haze,气温22摄氏度
========================================
--- 循环 2 ---
正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 已获取北京当前天气为烟霾(Smoky haze),气温22摄氏度。烟霾天气不适合户外剧烈活动,接下来根据天气搜索合适的旅游景点。
Action: get_attraction(city="北京", weather="Smoky haze")
Observation: In smoky haze, visit Mutianyu Great Wall for less crowds, Forbidden City for history, and Universal Studios Beijing for fun.
========================================
--- 循环 3 ---
正在调用大语言模型...
大语言模型响应成功。
模型输出:
Thought: 已获取北京天气和景点推荐信息,可以给出最终推荐。
Action: Finish[北京今天天气为烟霾,气温22°C。烟霾天气建议减少户外长时间活动,推荐前往故宫博物院:可参观室内展览与历史文物,兼顾文化体验和避霾,是今天较合适的旅游景点。]
任务完成,最终答案: 北京今天天气为烟霾,气温22°C。烟霾天气建议减少户外长时间活动,推荐前往故宫博物院:可参观室内展览与历史文物,兼顾文化体验和避霾,是今天较合适的旅游景点。
更多推荐


所有评论(0)