轻量 AI Agent 入门:用 Python 写一个简单的工具调用智能体
1. 引言:不追框架,先懂思想
AI Agent(智能体)是近两年大模型应用领域最热的关键词之一。但很多入门教程一上来就甩出 LangChain、AutoGPT、AgentScope 等重量级框架,学习曲线陡峭,反而让人看不清 Agent 的本质。
这篇文章想做的,是剥掉框架的外壳,用几十行纯 Python 代码讲清楚 Agent 的核心思想:大模型不只是"说话",而是会思考、决策、调用工具,最后形成完整闭环。
读完你会发现,Agent 并没有那么神秘——它本质上就是"大模型 + 工具调用 + 循环反馈"的组合拳。
2. Agent 的核心思想:思考、决策、调用工具
2.1 普通大模型在做什么
当我们用 ChatGPT 这类产品提问时,对话流程大致是:
- 用户输入问题
- 大模型基于训练数据和上下文直接生成回答
- 返回结果
这个过程本质上是一个单次推理:模型只能"凭记忆"回答。遇到需要实时数据、私有数据或执行具体操作的任务时,它就会捉襟见肘。
2.2 Agent 增加了什么
Agent 在"大模型"外面包了一层行动能力。它的核心循环可以拆成三个环节:
- 思考(Reason):大模型理解用户意图,判断"这个问题我能不能直接回答?"
- 决策(Decide):如果不能直接回答,它决定"我需要调用哪个工具、传什么参数"
- 调用工具(Act):执行工具获取外部信息或完成操作,然后把结果反馈给大模型,由它整合生成最终回复
这个闭环可以反复进行,直到大模型认为信息足够、可以给出最终答案为止。
下面是 Agent 的完整工作流程图:
图中的关键在闭环:工具结果会再次进入大模型,形成"思考 → 调用 → 反馈 → 再思考"的循环,而不是一次就结束。
3. Agent 与普通对话机器人的区别
理解二者差异,是入门 Agent 的关键一步。下面这张对比图可以帮你快速建立认知:
具体差异可以归纳为三点:
| 对比维度 | 普通对话机器人 | AI Agent |
|---|---|---|
| 信息范围 | 仅凭模型参数记忆 | 可访问实时数据、私有系统 |
| 执行能力 | 只能"说",不能"做" | 可调用 API、查库、操作文件 |
| 推理模式 | 单次推理直接输出 | 多轮循环,直到任务完成 |
一句话总结:对话机器人是"只会说",Agent 是"既会想,也会做"。
4. 极简 Demo:用 Python 实现工具调用智能体
下面我们动手写一个最小可运行的 Agent。它不依赖任何 Agent 框架,只用 requests 直接调用 OpenAI 兼容接口,核心逻辑不到 60 行。
4.1 整体设计
我们的 Agent 只有一个工具:get_weather(查天气)。场景是:
- 用户问"北京今天天气怎么样?"
- 大模型发现自己不知道实时天气,于是决定调用
get_weather工具 - 工具返回结果后,大模型整合信息,生成自然语言回复
4.2 完整代码
import json
import requests
from typing import Optional
# ========== 配置区 ==========
API_URL = "https://api.openai.com/v1/chat/completions"
API_KEY = "你的-API-Key"
MODEL = "gpt-4o-mini" # 或任何支持 function calling 的模型
# ========== 定义工具 ==========
# 工具列表会直接告诉大模型:"我有这些能力,你可以按需调用"
TOOLS = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的实时天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,例如:北京"
}
},
"required": ["city"]
}
}
}
]
def get_weather(city: str) -> str:
"""本地工具函数:模拟天气查询(实际场景可替换为真实 API)"""
fake_db = {
"北京": "晴,25°C,空气质量优",
"上海": "多云,28°C,东南风 3 级",
"广州": "雷阵雨,30°C,湿度较大",
}
return fake_db.get(city, "晴转多云,23°C")
def call_llm(messages: list[dict], tools: Optional[list] = None) -> dict:
"""调用大模型,messages 为对话历史,tools 为可选工具列表"""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": MODEL,
"messages": messages,
}
if tools:
payload["tools"] = tools
payload["tool_choice"] = "auto" # 让模型自己决定是否调用工具
resp = requests.post(API_URL, headers=headers, json=payload, timeout=60)
resp.raise_for_status()
return resp.json()
def run_agent(user_question: str) -> str:
"""
Agent 主循环:
1. 大模型思考用户问题
2. 大模型决策:是否调用工具
3. 若调用,执行工具并把结果反馈给大模型
4. 大模型基于工具结果生成最终回复
"""
messages = [{"role": "user", "content": user_question}]
# ---- 第一轮:让大模型思考并决策 ----
response = call_llm(messages, tools=TOOLS)
message = response["choices"][0]["message"]
# 如果大模型决定调用工具
if message.get("tool_calls"):
# 把大模型的工具调用请求追加到对话历史
messages.append(message)
for tool_call in message["tool_calls"]:
func_name = tool_call["function"]["name"]
args = json.loads(tool_call["function"]["arguments"])
# 执行对应的本地工具
if func_name == "get_weather":
result = get_weather(args["city"])
else:
result = f"未知工具:{func_name}"
# 把工具执行结果反馈给大模型
messages.append({
"role": "tool",
"tool_call_id": tool_call["id"],
"content": result,
})
# ---- 第二轮:大模型基于工具结果生成最终回复 ----
response = call_llm(messages)
return response["choices"][0]["message"]["content"]
# 不需要工具时,直接返回第一轮的回答
return message["content"]
if __name__ == "__main__":
# 测试 1:需要调用工具的问题
print("Q: 北京今天天气怎么样?")
print("A:", run_agent("北京今天天气怎么样?"))
print("-" * 50)
# 测试 2:不需要工具的问题
print("Q: 用一句话解释什么是人工智能?")
print("A:", run_agent("用一句话解释什么是人工智能?"))
4.3 代码解读:三个关键点
第一,工具以结构化方式"声明"给大模型。 TOOLS 列表用 JSON Schema 描述了工具名称、用途和参数,大模型就是通过这份描述来理解"我什么时候该调它、传什么参数"。
第二,tool_choice 设为 "auto"。 这表示把决策权交给模型:它自己判断要不要调工具。这正是 Agent "决策"能力的体现。
第三,工具结果必须"喂回去"。 很多初学者容易漏掉这一步——调完工具就结束了。实际上,工具返回的结果要作为一条 role: "tool" 的消息追加回对话历史,再让大模型进行第二轮推理,它才能把"北京 25°C"这种原始数据转化为"北京今天晴朗,气温 25°C,适合出门"这样的自然语言回复。
4.4 运行效果预期
第一个问题会触发工具调用,Agent 返回类似:
北京今天天气晴朗,气温 25°C,空气质量优,适合户外活动。
第二个问题不需要工具,Agent 直接回答:
人工智能是让计算机系统模拟人类智能、完成学习与推理任务的技术。
5. 当前轻量 Agent 的局限性
这个 Demo 足够轻量、易理解,但它也诚实地暴露了轻量 Agent 的边界。了解这些局限,才能在实际项目中做出合理的技术选型。
5.1 单轮调用为主,难以处理复杂任务
我们的实现中,工具调用只走了一个循环。真实场景里,一个任务往往需要多轮、多工具协作,比如"先查用户信息 → 再查订单 → 最后生成报告"。这需要引入更复杂的状态管理和任务规划能力。
5.2 缺少记忆与上下文管理
Demo 没有持久化记忆。每次运行 run_agent 都是全新的对话。要让 Agent 记住"用户偏好、历史对话",需要额外的存储和检索方案。
5.3 没有错误处理与重试机制
工具执行失败、返回异常、参数错误等情况,Demo 都未处理。生产级 Agent 需要设计兜底策略:工具失败时要不要重试?要不要降级为"直接回答"?
5.4 安全性几乎为零
让大模型自由调用工具存在风险:它可能调用不该调用的接口、泄露敏感数据。真实系统必须加权限控制(白名单、鉴权)和人工确认环节。
5.5 没有并行与性能优化
当需要调用多个独立工具时,轻量实现是串行执行的。高效率 Agent 会考虑并行调用、结果聚合等优化手段。
小结:轻量 Agent 的价值在于帮助理解原理、快速验证想法。当需求变得复杂时,再引入成熟框架去解决工程化问题,是更务实的路径。
6. 总结
Agent 的核心并不神秘,本质上是一个循环:
思考 → 决策 → 调用工具 → 反馈 → 再思考
用几十行 Python 就能把这个闭环跑通。相比普通对话机器人,Agent 的核心突破在于获得了"行动"的能力——它不再只是回答问题,而是能够获取外部信息、操作真实系统。
建议你亲自动手把这套代码跑起来,然后试着扩展一个新工具(比如查股票、查快递),你会发现:所谓 Agent,不过是把大模型的"嘴",接上了真实世界的"手"。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)