手写一个 AI Agent:从 Function Calling 到自动化任务链

Agent 这个词现在到处都是,但很多教程要么只讲概念,要么直接上 LangChain 框架,跳过了最关键的底层机制。

这篇文章从零手写一个 Agent,不用任何框架,只用大模型原生的 Function Calling。搞懂这个,框架只是语法糖。

Function Calling 是什么

普通对话:你问模型问题,它给你文字回答。

Function Calling:你告诉模型「我有这些工具可以用」,模型推理时会说「我想调用 XX 工具,参数是 YY」,你执行这个调用,把结果返回,模型继续推理。

这就是 Agent 的核心------模型驱动工具调用,形成「推理→行动→观察」的循环。

实现步骤

1. 定义工具

python 复制代码
import json
from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "搜索互联网获取最新信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {"type": "string", "description": "数学表达式"}
                },
                "required": ["expression"]
            }
        }
    }
]

2. 实现工具函数

python 复制代码
def search_web(query: str) -> str:
    # 实际可接 Tavily、SerpAPI 等
    return f"搜索 '{query}' 的结果:相关信息..."

def calculate(expression: str) -> str:
    try:
        allowed = set('0123456789+-*/()., ')
        if not all(c in allowed for c in expression):
            return "错误:包含不允许的字符"
        return str(eval(expression))
    except Exception as e:
        return f"计算错误: {e}"

def execute_tool(name: str, args: dict) -> str:
    if name == "search_web": return search_web(**args)
    if name == "calculate": return calculate(**args)
    return f"未知工具: {name}"

3. Agent 主循环

python 复制代码
def run_agent(user_input: str, max_steps: int = 10) -> str:
    messages = [
        {"role": "system", "content": "你是有用的助手,可以使用工具回答问题。"},
        {"role": "user", "content": user_input}
    ]
    for step in range(max_steps):
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=tools,
            tool_choice="auto"
        )
        message = response.choices[0].message
        if not message.tool_calls:
            return message.content   # 无工具调用 = 最终答案
        messages.append(message)
        for tc in message.tool_calls:
            args = json.loads(tc.function.arguments)
            result = execute_tool(tc.function.name, args)
            messages.append({
                "role": "tool",
                "tool_call_id": tc.id,   # 必须和 tool_call id 对应
                "content": result
            })
    return "达到最大步数"

运行效果

css 复制代码
Step 1: 调用 search_web({'query': '苹果公司市值'})
Step 2: 调用 calculate({'expression': '3.5 * 7.2'})
Step 3: 最终回答:苹果市值约 3.5 万亿美元,折合人民币约 25.2 万亿元。

模型自己决定了先搜索再计算------这就是自主推理链。

关键细节

消息历史不能丢 --- 每次工具调用后,模型的决策和工具返回都要加进 messages,下一步推理依赖完整上下文。

tool_call_id 必须对应 --- tool 角色消息里的 id 必须和 message.tool_calls 里一一对应,多工具并发时尤其要注意。

max_steps 防死循环 --- 设步数上限是必要的安全措施。

扩展方向

  • 并行工具调用:GPT-4 支持一次返回多个 tool_call,可并发执行
  • 持久化记忆:把历史存 DB,跨会话保持上下文
  • 多 Agent 协作:一个 Agent 把另一个 Agent 当工具调用

Agent 开发的系统性内容,gufacode.com 的 AI Agent 教程从基础到多 Agent 协作都有,写法偏工程实战,可以去翻翻。


Function Calling 搞懂之后,LangChain 的 Agent 部分就透明了------它只是把这个循环封装起来。先手写一遍再用框架,能省很多排查问题的时间。

相关推荐
Merrill_hh32 分钟前
Python环境搭建
python
用户0190275816137 分钟前
如何用 Python 回测布林带突破策略?
python
4SAPI1 小时前
企业Agent落地选型:大模型API接入方案迁移实践与稳定性评估
人工智能·python·php
用户019027581611 小时前
如何用 Python 计算 CR 能量指标(中间意愿指标)?
python
曲径海盗1 小时前
【Python 学习第 34 天】条件判断 if/else
python·学习笔记·编程入门
用户6602676118791 小时前
重试不重复下单还不够:同一幂等键换了参数,应该返回什么?
python
五网1 小时前
用Python搭建创业项目财务测算模型:CAC、LTV、盈亏平衡点一键算出(附完整代码)
python
用户6602676118791 小时前
登录成功就能读取任意任务 ID 吗?给 SaaS 读写加上租户范围
python
用户7624117567051 小时前
第十五章 数据分析
python·数据分析
2601_961963382 小时前
电子合同检索与全文搜索怎么测、怎么选:六个指标 + 五家平台对比 + 八个自测问题
数据库·后端·python·django·智能合约