Semantic Kernel对接本地LLM无法调用插件的问题及临时解法
本地LLM对接Semantic Kernel的函数调用问题排查与临时解决方法
问题背景
我正在开发首个AI演示项目,目标是用Semantic Kernel对接本地部署的LLM实现函数调用。目前能正常获取LLM的响应,但插件调用失败——虽然插件已作为工具包含在发送给LLM的JSON请求中:
"tools": [ { "type": "function", "function": { "description": "获取灯光列表及其当前状态", "name": "Lights-get_lights", "parameters": { "type": "object", "required": [], "properties": {} } } } ]
但LLM始终无法通过Kernel调用插件函数获取数据。我试过Llama-3.2-3B-Instruct、Phi-3-mini-4k-instruct等模型,用LM Studio托管本地服务器,作为LLM新手,不清楚遗漏了哪些关键步骤。
原方案代码
Program.cs
var messageAPIPlatform = "LocalAI"; var url = "http://localhost:1234/v1"; var modelId = "llama-3.2-3b-instruct"; Console.WriteLine($"使用本地{messageAPIPlatform}的示例"); #pragma warning disable SKEXP0010 var kernel = Kernel.CreateBuilder() .AddOpenAIChatCompletion( modelId: modelId, apiKey: null, endpoint: new Uri(url)) .Build(); var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>(); kernel.Plugins.AddFromType<LightsPlugin>("Lights"); // 启用规划 #pragma warning disable SKEXP0001 OpenAIPromptExecutionSettings settings = new OpenAIPromptExecutionSettings() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions, Temperature = .1, ChatSystemPrompt = """ 你是一个大语言模型助手,会通过插件与软件交互。 """ }; // 创建对话历史存储 var history = new ChatHistory(); // 启动交互式对话 string? userInput; do { // 收集用户输入 Console.Write("用户 > "); userInput = Console.ReadLine(); // 添加用户消息到历史 history.AddUserMessage(userInput); // 获取AI响应 var result = await chatCompletionService.GetChatMessageContentAsync( history, executionSettings: settings, kernel: kernel); // 打印结果 Console.WriteLine("助手 > " + result); // 将助手消息添加到对话历史 history.AddMessage(result.Role, result.Content ?? string.Empty); } while (userInput is not null);
LightsPlugin.cs
public class LightsPlugin { // 灯光模拟数据 private readonly List<LightModel> lights = new() { new LightModel { Id = 1, Name = "台灯", IsOn = false }, new LightModel { Id = 2, Name = " porch灯", IsOn = false }, new LightModel { Id = 3, Name = "吊灯", IsOn = true } }; [KernelFunction("get_lights")] [Description("获取灯光列表及其当前状态")] [return: Description("灯光数组")] public async Task<List<LightModel>> GetLightsAsync() { return lights; } [KernelFunction("change_state")] [Description("修改灯光状态")] [return: Description("更新后的灯光状态;如果灯光不存在则返回null")] public async Task<LightModel?> ChangeStateAsync(int id, bool isOn) { var light = lights.FirstOrDefault(light => light.Id == id); if (light == null) { return null; } // 更新灯光状态 light.IsOn = isOn; return light; } }
当询问灯光状态时,LLM只会回复无法回答该问题,不会调用GetLightsAsync()方法。
尝试过的其他方案
OllamaConnector
试过Ollama函数调用的官方示例,但未成功,使用的是最新版Semantic Kernel和Ollama。
临时解决方法(基于旧版Semantic Kernel)
最终通过Ollama实现了函数调用,核心修改点如下:
- 用
ChatCompletionAgent替代ChatCompletionService发送请求 - 将Semantic Kernel对象绑定到
ChatCompletionAgent - 使用
KernelPluginFactory创建插件,而非KernelBuilder.AddFromType - 仍使用
OpenAiChatCompletion(原本以为应该用OllamaConnector) - 必须降级Semantic Kernel到1.18.2版本才能使用
ChatCompletionAgent
该方案并不完美,依赖旧版本库且不符合官方最新指南,但这是目前唯一能让LLM调用函数的方式。
临时解决代码
var modelId = "llama3.2"; var baseUrl = "http://localhost:11434"; var httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(2) }; var builder = Kernel.CreateBuilder().AddOpenAIChatCompletion(modelId: modelId!, apiKey: null, endpoint: new Uri(baseUrl!), httpClient: httpClient); var kernel = builder.Build(); var hostName = "AI助手"; var hostInstructions = @"你是一个友好的助手"; var settings = new OpenAIPromptExecutionSettings() { Temperature = 0.1, ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions, }; ChatCompletionAgent agent = new() { Instructions = hostInstructions, Name = hostName, Kernel = kernel, Arguments = new(settings), }; KernelPlugin lightsPlugin = KernelPluginFactory.CreateFromType<LightsPlugin>(); agent.Kernel.Plugins.Add(lightsPlugin); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("助手: 你好,我是你的AI助手,有什么可以帮你的?"); AgentGroupChat chat = new(); while (true) { Console.ForegroundColor = ConsoleColor.White; Console.Write("用户: "); await InvokeAgentAsync(Console.ReadLine()!); } async Task InvokeAgentAsync(string question) { chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, question)); Console.ForegroundColor = ConsoleColor.Green; await foreach (ChatMessageContent content in chat.InvokeAsync(agent)) { Console.WriteLine(content.Content); } } #pragma warning restore SKEXP0010 #pragma warning restore SKEXP0110
待解答疑问
仍想了解原方案失效的具体原因。
内容的提问来源于stack exchange,提问作者Oreth
相关产品推荐
相关产品推荐

