1. 项目概述

在第一个项目中,我们构建了一个“知识型”的问答机器人。然而,现实世界中的许多任务不仅需要知识,还需要执行动作(Action),例如查询实时信息、操作数据库、调用服务API等。本项目将带领你构建一个更高级的AI形态——智能Agent (Intelligent Agent)

核心目标:

开发一个能够理解用户意图,并自主选择、调用外部工具(API)来完成特定任务的AI Agent。我们将以一个“智能助理”为应用场景,它能够回答实时天气和进行数学计算。

你将学习到的核心技术:

  1. Agentic Thinking (智能体思维):理解Agent的核心工作原理,特别是**ReAct (Reason + Act)**框架。
  2. Function Calling / Tool Calling:掌握如何让LLM生成结构化的函数调用请求,这是实现工具调用的关键技术。
  3. API集成与封装:学会如何将真实的外部API(无论是你自己的服务还是第三方服务)封装成LLM可以理解和使用的“工具”。
  4. Agent执行循环 (Execution Loop):编写代码来管理Agent的“思考-行动”循环,处理工具调用、结果返回和最终回复生成的全过程。
项目整体流程图
Agent执行循环
思考: 需要什么工具?
选择天气API
选择计算器
思考: 结果已知, 生成回复
LLM - Agent核心
工具选择
执行天气查询
执行数学计算
API返回天气结果
计算器返回数学结果
生成最终答案
用户输入
输出给用户

2. 核心概念:ReAct框架与Function Calling

2.1 ReAct框架

ReAct是Google提出的一个将LLM的推理 (Reasoning) 能力和行动 (Acting) 能力相结合的强大框架。它模仿人类解决问题的过程:

  1. Thought (思考):LLM首先分析当前任务和已有信息,思考下一步需要做什么。
  2. Action (行动):根据思考结果,LLM决定调用哪个工具,并生成调用该工具所需的参数。
  3. Observation (观察):执行工具后,系统将工具返回的结果(例如API的响应)作为“观察”信息,反馈给LLM。

LLM会重复这个“思考-行动-观察”的循环,直到它认为已经收集到足够的信息来回答用户最初的问题为止,然后生成最终答案。

2.2 Function Calling / Tool Calling

这是让ReAct框架落地的核心技术。现代的LLM(如OpenAI的GPT系列、Google的Gemini、Qwen等)都支持Function Calling功能。其工作流程如下:

  1. 定义工具:在向LLM发起请求时,我们不仅提供用户的提问,还提供一份详细的“工具清单”。这份清单用JSON Schema的格式描述了每个工具的名称、功能说明、以及所需的参数(参数名、类型、是否必需等)。
  2. LLM决策:LLM在理解用户问题后,会判断是否需要调用工具。如果需要,它会从清单中选择最合适的工具,并生成一个包含工具名和具体参数的JSON对象。
  3. 代码执行:我们的后端代码接收到这个JSON后,解析出工具名和参数,然后执行本地对应的函数(例如,调用真实的天气API)。
  4. 结果返回:将函数执行的结果(如天气信息)再发送给LLM,让它继续下一步的思考或生成最终回复。

3. 项目实战:构建智能助理Agent

3.1 环境准备

我们将使用OpenAI的API作为Agent的核心,因为它具有非常成熟和强大的Function Calling能力。你也可以使用支持此功能的其他模型API。

!pip install -q openai

3.2 定义工具(函数)

我们来定义两个本地函数,一个用于获取天气,一个用于计算。这些函数将作为我们的“工具”。

import json

# 工具1:获取实时天气
def get_current_weather(location: str, unit: str = "celsius"):
    """获取指定地点的实时天气信息"""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "temperature": "10", "unit": unit})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "temperature": "72", "unit": unit})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "temperature": "22", "unit": unit})
    else:
        return json.dumps({"location": location, "temperature": "unknown"})

# 工具2:计算器
def calculator(expression: str):
    """计算一个数学表达式的值"""
    try:
        # 使用eval是简化的做法,在生产环境中需要更安全的数学表达式解析器
        result = eval(expression)
        return json.dumps({"result": result})
    except Exception as e:
        return json.dumps({"error": str(e)})

3.3 构建Agent执行循环

这是Agent的核心逻辑。我们将编写一个循环,来处理与LLM的交互、工具调用和结果反馈。

import os
from openai import OpenAI

# 确保你的OpenAI API密钥已设置为环境变量
# os.environ["OPENAI_API_KEY"] = "sk-..."
client = OpenAI()

# 步骤1:定义工具清单,供模型选择
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "获取指定地点的实时天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称,例如:San Francisco",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "calculator",
            "description": "计算一个数学表达式的值",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "要计算的数学表达式,例如:'5*2+10'",
                    },
                },
                "required": ["expression"],
            },
        },
    }
]

# 将本地函数映射到工具名
available_functions = {
    "get_current_weather": get_current_weather,
    "calculator": calculator,
}

def run_agent(user_prompt):
    print(f"\n--- 用户提问: {user_prompt} ---")
    messages = [{"role": "user", "content": user_prompt}]

    # 第一次调用模型
    response = client.chat.completions.create(
        model="gpt-4-turbo-preview",
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )
    response_message = response.choices[0].message
    messages.append(response_message) # 将模型的回复加入历史记录

    # 步骤2:检查模型是否决定调用工具
    tool_calls = response_message.tool_calls
    while tool_calls:
        print(f"--- 模型决策: 调用工具 {', '.join([tc.function.name for tc in tool_calls])} ---")
        # 步骤3:执行工具调用
        for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_to_call = available_functions[function_name]
            function_args = json.loads(tool_call.function.arguments)
            
            print(f"--- 正在执行: {function_name}({function_args}) ---")
            function_response = function_to_call(**function_args)
            print(f"--- 工具返回: {function_response} ---")
            
            # 将工具调用的结果加入历史记录
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response,
                }
            )
        
        # 步骤4:再次调用模型,并附上工具返回的结果
        print("--- 将工具结果返回给模型,让其继续思考 ---")
        second_response = client.chat.completions.create(
            model="gpt-4-turbo-preview",
            messages=messages,
            tools=tools,
            tool_choice="auto",
        )
        response_message = second_response.choices[0].message
        messages.append(response_message)
        tool_calls = response_message.tool_calls

    # 如果模型不再调用工具,则其最后的回复就是最终答案
    final_answer = response_message.content
    print(f"\n--- Agent最终回复: {final_answer} ---")
    return final_answer

# --- 运行Agent ---
run_agent("旧金山现在多少度?")
run_agent("东京10摄氏度,那换算成华氏度是多少?提示:F = C * 9/5 + 32")

3.4 运行结果分析

当你运行run_agent("东京10摄氏度,那换算成华氏度是多少?提示:F = C * 9/5 + 32")时,你会看到一个清晰的ReAct流程:

  1. 用户提问东京10摄氏度,那换算成华氏度是多少?提示:F = C * 9/5 + 32
  2. 模型第一次思考:模型发现它需要进行计算,但它自己不会算。它看到calculator工具可以帮助它。
  3. 模型行动:模型决定调用calculator工具,并生成调用参数{"expression": "10 * 9/5 + 32"}
  4. 代码执行:我们的Python代码执行calculator('10 * 9/5 + 32'),得到结果50.0
  5. 观察:工具返回结果{"result": 50.0}
  6. 模型第二次思考:模型收到了计算结果,现在它知道了答案。
  7. 生成最终回复:模型组织语言,生成最终答案:“东京10摄氏度换算成华氏度是50.0度。”

4. 总结与展望

本项目通过一个简单的智能助理,完整地展示了如何构建一个基于ReAct框架和Function Calling的智能Agent。这是通向更高级AI应用(如自主软件工程师、AI游戏角色、自动化流程机器人)的基石。

可以探索的扩展方向:

  • 更复杂的工具:集成数据库查询工具、代码执行工具、甚至是发送邮件的工具。
  • 多步推理:设计需要多次不同工具调用才能解决的复杂问题,观察Agent的规划能力。
  • Agent框架:学习使用LangChainLlamaIndex等成熟的Agent开发框架,它们封装了Agent的执行循环、工具管理、记忆模块等,能极大提高开发效率。
  • Agent的微调:对于特定领域的Agent,可以微调模型以提升其工具选择和使用能力,但这通常需要高质量的Agent轨迹数据(Thought-Action-Observation序列)。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐