使用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.cs
或 Main
方法中,初始化 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