您当前的位置:首页 > 计算机 > 编程开发 > 人工智能

大模型函数调用实操

时间:03-23来源:作者:点击数:
城东书院 www.cdsy.xyz

引言

Function Calling 是一个允许大型语言模型(如 GPT)在生成文本的过程中调用外部函数或服务的功能。

Function Calling允许我们以 JSON 格式向 LLM 模型描述函数,并使用模型的固有推理能力来决定在生成响应之前是否调用该函数。模型本身不执行函数,而是生成包含_函数名称_和_执行函数所需的参数_的 JSON

function calling 执行原理

现在我们定义提示词像大语言模型问一下当前北京的天气?

因为 LLM 大语言模型缺乏实时数据,所以无法回答实时数据这种场景。这时候就需要用到 LLM 的 Function Calling 功能来帮助回答用户的问题

使用 OpenAI API function calling

OpenAI 的 function calling的核心是我们将Prompts 提示词和可用函数列表一起发送给LLM

OpenAI Chat Completions 接口

{
  "tool_choice": "auto",
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant."
    },
    {
      "role": "user",
      "content": "我想知道现在北京的天气状况"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "Get_Weather_For_City",
        "description": "获取指定城市的天气",
        "parameters": {
          "type": "object",
          "properties": {
            "cityName": {
              "type": "string",
              "description": "城市名"
            }
          }
        }
      }
    }
  ]
}

核心参数解释
tool_choice:

这个参数决定了模型是否应该自动选择是否调用函数。值为 "auto" 表示模型将根据情况自动决定是否调用函数。 默认情况下,如果请求中不存在任何函数,则将其设置为“none”,则设置为“auto”

tools

在 tools 部分定义了一个函数,这个函数可以被 OpenAI 的模型调用。以下是 tools 部分参数的简单解释:

  • type: 指定了这个工具的类型,这里是 "function",表示这是一个函数调用。
  • function: 包含函数的详细信息,是一个对象。
    • name: 函数的名称,这里是 "Get_Weather_For_City",这是调用时使用的函数名。
    • description: 函数的描述,这里是 "获取指定城市的天气",用于说明这个函数的作用。
    • parameters: 定义了函数调用时需要的参数,是一个对象。
      • type: 参数对象的类型,这里是 "object",表示参数是一个对象类型。
      • properties: 包含具体的参数定义,是一个对象,每个属性对应一个参数。
        • cityName: 这是一个参数的名称,表示城市名称。
          • type: 此参数的类型,这里是 "string",表示参数应该是一个字符串。
          • description: 参数的描述,这里是 "城市名",用于解释这个参数的意义。

这个 tools 部分定义了一个名为 Get_Weather_For_City 的函数,它需要一个名为 cityName 的字符串参数,用于指定想要查询天气的城市。当模型需要调用这个函数时,它将使用这个参数来获取相应的天气信息。

function calling 输出
{
  "id": "chatcmpl-9TOuIqnuMirU3BUDluCrHMTlsjz97",
  "object": "chat.completion",
  "created": 1716794282,
  "model": "gpt-4",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_DQU6OKHWyv3HVLyWVjSRqvwZ",
            "type": "function",
            "function": {
              "name": "Get_Weather_For_City",
              "arguments": "{\n  \"cityName\": \"北京\"\n}"
            }
          }
        ]
      },
      "logprobs": null,
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 83,
    "completion_tokens": 20,
    "total_tokens": 103
  },
  "system_fingerprint": null
}

最核心的方法是tool_calls回参里面返回了我们需要的方法名和一个 json 参数 比如"{\n \"cityName\": \"北京\"\n}"包含了我们的参数和值。

返回函数结果上下文
{
    "max_tokens": 3000,
    "tool_choice": "auto",
    "messages": [
        {
            "role": "system",
            "content": "You are a helpful assistant."
        },
        {
            "role": "user",
            "content": "我想知道北京的天气状况"
        },
        {
            "role": "assistant",
            "function_call": {
                "name": "Get_Weather_For_City",
                "arguments": "{\n  \"cityName\": \"北京\"\n}"
            }
        },
        {
            "role": "function",
            "name": "Get_Weather_For_City",
            "content": "27度,晴朗"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "Get_Weather_For_City",
                "description": "获取指定城市的天气",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "cityName": {
                            "type": "string",
                            "description": "城市名"
                        }
                    }
                }
            }
        },
        {

需要把上下文信息和function callingresult回答的信息传给LLM

  • ToolCall上下文信息
{
  "role": "assistant",
  "function_call": {
    "name": "Get_Weather_For_City",
    "arguments": "{\n  \"cityName\": \"北京\"\n}"
  }
}

  • ToolCallResponse
{
  "role": "function",
  "name": "Get_Weather_For_City",
  "content": "27度,晴朗"
}

LLM 输出

{
  "id": "chatcmpl-9TRZBqCcRMBYIojuZimio6GOpsTi4",
  "object": "chat.completion",
  "created": 1716804505,
  "model": "gpt-4",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "北京的天气状况是27度,晴朗。"
      },
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 133,
    "completion_tokens": 19,
    "total_tokens": 152
  },
  "system_fingerprint": null
}

到现在为止简单的function calling的简单调用已经完成了

具体的流程可以总结为

image

可以看到function calling跟大预言模型至少有两次交互的的过程。

再举个实际代码Demo,例子中:通过提前写好的获取天气的function,让大模型自动调用获取天气的function,并给出问题答案。其中用户问题是:“通过未来5天深圳南山区的天气怎么样”。具体操作方法如下:

1、向 LLM 描述这个函数,函数描述的必备要素:函数名、函数的功能描述、函数的请求参数说明、函数的响应参数说明。获取天气的function的描述如下:

tools = [
{
        "type": "function",
        "function": {
            "name": "get_n_day_weather_forecast",
            "description": "获取最近n天的天气预报",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市或镇区 如:深圳市南山区",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "要使用的温度单位,摄氏度 or 华氏度",
                    },
                    "num_days": {
                        "type": "integer",
                        "description": "预测天数",
                    }
                },
                "required": ["location", "format", "num_days"]
            },
        }
    }
]

2、向LLM实例化传入tools这个参数,大模型则会知道拥有哪些参数可供使用。并且会根据用户的输入,推理出应该调用哪些函数,并将自然语言转成函数的请求参数,返回给请求方。

from openai import OpenAI

def chat_completion_request(messages, tools=None, tool_choice=None, model="gpt-3.5-turbo"):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice=tool_choice,
        )
        return response
    except Exception as e:
        print("Unable to generate ChatCompletion response")
        print(f"Exception: {e}")
        return e


if __name__ == "__main__":
    messages = []
    messages.append({"role": "system", "content": "不要假设将哪些值输入到函数中。如果用户请求不明确,请要求澄清"})
    messages.append({"role": "user", "content": "未来5天深圳南山区的天气怎么样"})
    chat_response = chat_completion_request(
        messages, tools=tools
    )

 tool_calls = chat_response.choices[0].message.tool_calls
 print("===回复===")
 print(tool_calls)	

得到的返回如下:

[
  {
    "id": "call_7qGdyUEWp34ihubinIUCTXyH",
    "function": {
      "arguments": {
        "location": "深圳市南山区",
        "format": "celsius",
        "num_days": 5
      },
      "name": "get_n_day_weather_forecast"
    },
    "type": "function"
  }
]

3、调用函数,并将函数调用结果返回给大模型,生成最终回复

# 执行函数
for tool_call in tool_calls:
    function = tool_call.function.name
    arguments_list = json.loads(tool_call.function.arguments)
    function_to_call = globals().get(function)
    result = function_to_call(**arguments_list)
    print("===" + function + "===")
    print(result)

    # 把函数调用结果加入到对话历史中
    messages.append(
        {
            "tool_call_id": tool_call.id,  # 用于标识函数调用的 ID
            "role": "user",
            "name": function,
            "content": "函数执行结果为:" + str(result)
        }
    )
# 函数执行结果传给LLM,组织成自然语言回复用户
chat_response = chat_completion_request(
    messages, tools=tools
)
print("===回复===")
print(chat_response.choices[0].message.content)

得到的结果如下:

===get_n_day_weather_forecast===
[{'date': '2023-04-01', 'location': '深圳市南山区', 'temperature': '20°C', 'description': '晴朗'}, {'date': '2023-04-02', 'location': '深圳市南山区', 'temperature': '21°C', 'description': '多云'}, {'date': '2023-04-03', 'location': '深圳市南山区', 'temperature': '22°C', 'description': '晴朗'}, {'date': '2023-04-04', 'location': '深圳市南山区', 'temperature': '23°C', 'description': '多云'}, {'date': '2023-04-05', 'location': '深圳市南山区', 'temperature': '24°C', 'description': '晴朗'}]
===回复===
未来5天深圳南山区的天气情况如下:
- 4月1日:晴朗,温度20°C
- 4月2日:多云,温度21°C
- 4月3日:晴朗,温度22°C
- 4月4日:多云,温度23°C
- 4月5日:晴朗,温度24°C

请注意天气预报仅供参考,实际情况可能会有所变化。

总结

根据文档中的描述,OpenAI的函数调用(function calling)过程可以简化为以下几个步骤,并且可以用一个流程图来表示:

image
  1. 用户提出问题。
  2. 系统接收到问题,并检查是否有可用的函数可以调用。
  3. 如果有,系统会生成一个工具调用请求(ToolCall),并发送给应用程序。
  4. 应用程序执行请求的函数,并返回结果。
  5. 系统将函数的响应(ToolCallResponse)发送回 LLM 模型。
  6. LLM 模型使用这个响应来生成最终的用户响应。

下面是一个简化的流程图,描述了上述过程:

在这个流程图中:

  • A 代表用户。
  • B 是用户提出的问题。
  • C 是 LLM 模型,它检查是否有函数可以调用。
  • D 是生成工具调用(ToolCall)的步骤。
  • E 是应用程序,它接收 ToolCall 并执行相应的函数。
  • F 是应用程序返回的 ToolCallResponse,即函数执行的结果。
  • G 是 LLM 模型,它使用 ToolCallResponse 来生成用户响应。
  • H 是最终接收到用户响应的用户。

这个流程图是基于文档内容的简化表示,实际的系统可能包含更多的细节和步骤。

城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐