Agent | openai function-calling |初战Agent Tool use👊

409 阅读4分钟

前言

书接上文 , 通过吴恩达教授 BUILD 2024演讲 , 了解到 Agent 的一个机制 —— TOOL USE

工具调用在 Agent 中十分常用 , 这里的工具我们可以理解为 API , 比如上文学到的应用案例 :

当你需要查询某个专业领域的数据时,AI代理可以自动访问相关的数据库,提取所需信息,并将其整合到最终答案中。

还有一个常用的例子 —— 天气的获取 ,我们可以使用特定的 API 获取天气 , 详细解释我在

豆包姐姐成功引起了我对LangChain的注意🤡! 中提及过 , 文章相关点如下 :

这是怎么做到的 ?

  • LLM 可以读懂我们的话(查询天气) ,
  • 并且做出决策(需要调用天气 API) ,
  • 最后采取行动(调用 API)

ta 到底怎么做到的 ? 玄学 ?

底层暂且不去探究 , 了解到 openai 支持 function-calling , 即函数调用 , 可以调用 API ,

我们一起试试 ~

探究

直接或者使用魔法上 openai 官网 , 找到如下 Function calling 示例

我们关注第一步 , 点进去康康 ~

Request 请求

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "What is the weather like in Boston?"}
  ],
  "functions": [
    {
      "name": "get_current_weather",
      "description": "Get the current weather in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"]
      }
    }
  ]
}'

Reponse 响应

{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "function_call": {
        "name": "get_current_weather",
        "arguments": "{ \"location\": \"Boston, MA\"}"
      }
    },
    "finish_reason": "function_call"
  }]
}

我们再把关注点放在Request 请求中下面这段代码 :

"functions": [
    {
      "name": "get_current_weather",
      "description": "Get the current weather in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"]
      }
    }
  ]

这段代码便是我们告诉 OpenAI 怎么调用 API 的描述信息 , 下面对字段进行解释

  1. name

这个名称需要与实际函数的名称一致,以便后续实现对函数名的调用。例如,在这里函数名为 get_current_weather,意味着这个函数将被用来获取某个地点的当前天气情况。

  1. description

这是语言模型决定是否调用该函数的唯一信息。这部分应清晰地表达函数的效果。例如,描述可以是 "Get the current weather in a given location",说明该函数用于获取给定位置的当前天气。

  1. parameters

使用通用的 JSON Schema 描述函数的各个参数。在我们这里使用了对象作为参数的输入,并且其中包含了两个键:

  • location 是一个字符串值,表示要查询天气的位置。提供了关于如何填写这个参数的例子和指导信息,例如 "The city and state, e.g. San Francisco, CA"。
  • unit 表示请求的温度单位。数据类型也是字符串,并且使用 enum 限制了可选的值只能是列表中的选项之一,在这里是摄氏度("celsius")或华氏度("fahrenheit")。
  1. required

这个键告知语言模型哪些参数是必须的。在这个例子中,只有 location 是必需的,而 unit 则是可选的。

把这些信息交给 openai , openai 就会帮我们去调用 , 下面写个 demo 模拟一下 ~

demo

编写 getCurrentWeather , 造假数据模拟 API

function getCurrentWeather({ location, unit="fahrenheit"}){
   const  weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["sunny", "windy"],
    }
    return JSON.stringify(weather_info);
}

定义给 openai 的信息

const tools = [
    {
      type: "function",
      function: {
        name: "getCurrentWeather",
        description: "Get the current weather in a given location",
        parameters: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "The city and state, e.g. San Francisco, CA",
            },
            unit: { 
              type: "string", 
              enum: ["celsius", "fahrenheit"],
              description: "The unit of temperature"
            },
          },
          required: ["location", "unit"],
        },
      },
    }
]

开始测试

 const messages = [
    {
        "role": "user",
        "content": "北京的天气怎么样"
    }
]

const result = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    messages,
    tools
  });
  console.log(result.choices[0]);

输出

{
  content_filter_results: {},
  finish_reason: "tool_calls",
  index: 0,
  message: {
    content: null,
    role: "assistant",
    tool_calls: [
      {
        function: {
          arguments: '{\n"location": "Beijing"\n}',
          name: "getCurrentWeather"
        },
        id: "xxxx",
        type: "function"
      }
    ]
  }
}

完整代码如下 :

import dotenv from 'dotenv';
import  OpenAI from 'openai';

// 加载环境变量
dotenv.config();

const openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
    baseURL: process.env.OPENAI_BASE_URL,
});

// 自定义函数:获取天气信息
function getCurrentWeather({ location, unit = "fahrenheit" }) {
    const weather_info = {
        location: location,
        temperature: "72", // 示例温度
        unit: unit,
        forecast: ["sunny", "windy"], // 示例预报
    };
    return JSON.stringify(weather_info);
}

// 定义工具列表,包括我们的自定义函数
const tools = [
    {
        type: "function",
        function: {
            name: "getCurrentWeather",
            description: "Get the current weather in a given location",
            parameters: {
                type: "object",
                properties: {
                    location: {
                        type: "string",
                        description: "The city and state, e.g. San Francisco, CA",
                    },
                    unit: {
                        type: "string",
                        enum: ["celsius", "fahrenheit"],
                        description: "The unit of temperature"
                    },
                },
                required: ["location"],
            },
        },
    }
];

// 假设的消息列表
const messages = [
    {
        role: "user",
        content: "北京的天气怎么样"
    }
];

const result = await openai.chat.completions.create({
  model: 'gpt-4',
  messages,
  tools
});
console.log(result.choices[0]);

总结

初探 Agent 的 TOOL USE , 尝试 openai 的 function-calling ~