使用Semantic Kernel框架和C#.NET 实现大模型Function Calling

最近研究Function Call,总结了一篇文章,分享给大家

一、GPT-4中实现函数调用功能

定义函数:首先,开发一个函数。例如,一个获取天气信息的函数可能如下:

def get_current_weather(location, unit='Celsius'):
    # 此处实现获取天气信息的逻辑
    return {"location": location, "temperature": "22", "unit": unit, "description": "晴朗"}

描述函数:为GPT-4提供函数的描述,包括函数名称、功能描述以及参数信息。这有助于模型理解函数的用途和如何调用它。

function_descriptions = [
    {
        "name": "get_current_weather",
        "description": "获取指定地点的当前天气信息",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "地点名称"
                },
                "unit": {
                    "type": "string",
                    "enum": ["Celsius", "Fahrenheit"],
                    "description": "温度单位,默认为摄氏度"
                }
            },
            "required": ["location"]
        }
    }
]

与GPT-4交互:将用户输入、函数描述以及模型名称传递给GPT-4。模型将根据用户输入和函数描述,决定是否需要调用函数,并返回相应的响应。

import openai
import json

openai.api_key = 'YOUR_OPENAI_API_KEY'

def chat_with_gpt(messages, functions):
    response = openai.ChatCompletion.create(
        model="gpt-4-0613",
        messages=messages,
        functions=functions,
        function_call="auto"  # 模型将根据需要决定是否调用函数
    )
    return response

# 用户输入
user_message = {"role": "user", "content": "请告诉我北京的当前天气。"}

# 与模型交互
response = chat_with_gpt([user_message], function_descriptions)

处理模型响应:检查模型的响应,确定是否需要调用函数。如果模型返回了函数调用信息,则提取函数名称和参数,并调用相应的函数。

response_message = response["choices"][0]["message"]

if "function_call" in response_message:
    # 提取函数名称和参数
    function_name = response_message["function_call"]["name"]
    function_args = json.loads(response_message["function_call"]["arguments"])

    # 调用相应的函数
    if function_name == "get_current_weather":
        function_response = get_current_weather(
            location=function_args.get("location"),
            unit=function_args.get("unit", "Celsius")
        )

        # 将函数响应传递回模型,获取最终的回答
        messages = [
            user_message,
            response_message,  # 包含函数调用信息
            {
                "role": "function",
                "name": function_name,
                "content": json.dumps(function_response)
            }
        ]
        final_response = chat_with_gpt(messages, function_descriptions)
        answer = final_response["choices"][0]["message"]["content"]
        print(answer)
else:
    # 模型直接提供了回答
    answer = response_message["content"]
    print(answer)

GPT-4并不会直接执行函数调用,而是根据提供的函数描述,生成包含函数名称和参数的JSON对象。然后,我们需要在应用程序中解析该对象,并实际调用相应的函数。

根据函数返回的结果,放到Prompt中,调用大模型API,生成新的内容返回给用户。

二、使用Semantic Kernel框架和C#.NET 实现Function Calling

Semantic Kernel 框架中,大模型可以通过 Function Calling(函数调用)来执行插件(Plugins)中的功能。以下示例,展示如何在 Semantic Kernel 中让大模型调用一个 插件函数(Function Call)

设计一个计算插件,包含一个 add_numbers 方法,让大模型可以调用它来执行加法运算。

首先安装Semantic Kernel Nuget包

dotnet add package Microsoft.SemanticKernel

在 Semantic Kernel 中,插件就是一个包含方法的 C# 类,并使用 [KernelFunction] 进行标注。

using Microsoft.SemanticKernel;
using System.Threading.Tasks;

public class CalculatorPlugin
{
    [KernelFunction("add_numbers")]
    public int AddNumbers(int a, int b)
    {
        return a + b;
    }
}

Program.csMain 方法中,初始化 Semantic Kernel 并注册这个插件。

using System;
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;

class Program
{
    static async Task Main(string[] args)
    {
        // 1. 创建 Kernel 实例
        var kernel = Kernel.CreateBuilder()
            .AddOpenAIChatCompletion(
                "gpt-4-turbo",  // OpenAI 模型名称
                "your-openai-api-key") // 替换为你的 API Key
            .Build();

        // 2. 加载插件(CalculatorPlugin)
        var plugin = kernel.ImportPluginFromObject(new CalculatorPlugin(), "Calculator");

        // 3. 让大模型调用 `add_numbers`
        var result = await kernel.InvokeAsync("Calculator", "add_numbers", new()
        {
            { "a", 5 },
            { "b", 10 }
        });

        Console.WriteLine($"Function Call Result: {result}");
    }
}

执行 dotnet run,输出结果:Function Call Result: 15

代码执行原理说明

  • Semantic Kernel 提供了 插件(Plugins) 机制,让大模型可以调用 .NET 代码中的方法。
  • [KernelFunction("add_numbers")] 让大模型知道这个函数可以被调用。
  • kernel.ImportPluginFromObject(new CalculatorPlugin(), "Calculator")CalculatorPlugin 作为插件加载到 Semantic Kernel 里。
  • kernel.InvokeAsync("Calculator", "add_numbers", new() { { "a", 5 }, { "b", 10 } }) 让大模型调用 add_numbers 并传入参数。

 

周国庆

2025/3/18

 
posted @ 2025-03-18 08:36  Eric zhou  阅读(236)  评论(1编辑  收藏  举报
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy