Stories

Detail Return Return

深入探討Function Calling:實現外部函數調用的工作原理 - Stories Detail

引言

Function Calling 是一個允許大型語言模型(如 GPT)在生成文本的過程中調用外部函數或服務的功能。
Function Calling允許我們以 JSON 格式向 LLM 模型描述函數,並使用模型的固有推理能力來決定在生成響應之前是否調用該函數。模型本身不執行函數,而是生成包含函數名稱執行函數所需的參數JSON

function calling 執行原理

現在我們定義提示詞像大語言模型問一下當前北京的天氣?

因為 LLM 大語言模型缺乏實時數據,所以無法回答實時數據這種場景。

我們用SK來測試一下

Console.WriteLine("===>沒有設置function calling=<===");
{
    var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(config.ModelId,
            endpoint: config.Endpoint,
    apiKey: config.ApiKey).Build();
    var template = "當前北京的天氣?";
    Console.WriteLine($"User: {template}");
    var function = kernel.CreateFunctionFromPrompt(template);
    var functionResult = await function.InvokeAsync(kernel);
    Console.WriteLine($"Assistant:{functionResult}");
}

輸出:

User: 當前北京的天氣?
Assistant:對不起,作為一個AI,我無法為你提供實時信息。你可以查看可信的天氣應用或網站來獲取當前北京的天氣。

這時候就需要用到 LLMFunction Calling 功能來幫助回答用户的問題

使用 OpenAI API function calling

OpenAIfunction 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跟大預言模型至少有兩次交互的的過程

總結

根據文檔中的描述,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 是最終接收到用户響應的用户。

這個流程圖是基於文檔內容的簡化表示,實際的系統可能包含更多的細節和步驟。

最後

本章的主要了解function calling及其工作原理的簡單介紹。在下一篇博客中,我們 x 學習在Semantic kernel下使用使用function calling

參考資料

openai-function-calling

user avatar dudu Avatar whuanle Avatar
Favorites 2 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.