Files
semantic-kernel/dotnet/samples/KernelSyntaxExamples/Example59_OpenAIFunctionCalling.cs
T
Stephen Toub 0772d0137e .Net: Add missing XxFromFunctions members (#4549)
Following the same pattern used by FromType and FromObject
2024-01-11 13:35:33 +00:00

136 lines
6.0 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.AI.OpenAI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
// This example shows how to use OpenAI's tool calling capability via the chat completions interface.
public static class Example59_OpenAIFunctionCalling
{
public static async Task RunAsync()
{
// Create kernel.
IKernelBuilder builder = Kernel.CreateBuilder();
// We recommend the usage of OpenAI latest models for the best experience with tool calling.
// i.e. gpt-3.5-turbo-1106 or gpt-4-1106-preview
builder.AddOpenAIChatCompletion("gpt-3.5-turbo-1106", TestConfiguration.OpenAI.ApiKey);
builder.Services.AddLogging(services => services.AddConsole().SetMinimumLevel(LogLevel.Trace));
Kernel kernel = builder.Build();
// Add a plugin with some helper functions we want to allow the model to utilize.
kernel.ImportPluginFromFunctions("HelperFunctions", new[]
{
kernel.CreateFunctionFromMethod(() => DateTime.UtcNow.ToString("R"), "GetCurrentUtcTime", "Retrieves the current time in UTC."),
kernel.CreateFunctionFromMethod((string cityName) =>
cityName switch
{
"Boston" => "61 and rainy",
"London" => "55 and cloudy",
"Miami" => "80 and sunny",
"Paris" => "60 and rainy",
"Tokyo" => "50 and sunny",
"Sydney" => "75 and sunny",
"Tel Aviv" => "80 and sunny",
_ => "31 and snowing",
}, "Get_Weather_For_City", "Gets the current weather for the specified city"),
});
Console.WriteLine("======== Example 1: Use automated function calling with a non-streaming prompt ========");
{
OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
Console.WriteLine(await kernel.InvokePromptAsync("Given the current time of day and weather, what is the likely color of the sky in Boston?", new(settings)));
Console.WriteLine();
}
Console.WriteLine("======== Example 2: Use automated function calling with a streaming prompt ========");
{
OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
await foreach (var update in kernel.InvokePromptStreamingAsync("Given the current time of day and weather, what is the likely color of the sky in Boston?", new(settings)))
{
Console.Write(update);
}
Console.WriteLine();
}
Console.WriteLine("======== Example 3: Use manual function calling with a non-streaming prompt ========");
{
var chat = kernel.GetRequiredService<IChatCompletionService>();
var chatHistory = new ChatHistory();
OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.EnableKernelFunctions };
chatHistory.AddUserMessage("Given the current time of day and weather, what is the likely color of the sky in Boston?");
while (true)
{
var result = (OpenAIChatMessageContent)await chat.GetChatMessageContentAsync(chatHistory, settings, kernel);
if (result.Content is not null)
{
Console.Write(result.Content);
}
List<ChatCompletionsFunctionToolCall> toolCalls = result.ToolCalls.OfType<ChatCompletionsFunctionToolCall>().ToList();
if (toolCalls.Count == 0)
{
break;
}
chatHistory.Add(result);
foreach (var toolCall in toolCalls)
{
string content = kernel.Plugins.TryGetFunctionAndArguments(toolCall, out KernelFunction? function, out KernelArguments? arguments) ?
JsonSerializer.Serialize((await function.InvokeAsync(kernel, arguments)).GetValue<object>()) :
"Unable to find function. Please try again!";
chatHistory.Add(new ChatMessageContent(
AuthorRole.Tool,
content,
metadata: new Dictionary<string, object?>(1) { { OpenAIChatMessageContent.ToolIdProperty, toolCall.Id } }));
}
}
Console.WriteLine();
}
Console.WriteLine("======== Example 4: Use automated function calling with a streaming chat ========");
{
OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
var chat = kernel.GetRequiredService<IChatCompletionService>();
var chatHistory = new ChatHistory();
while (true)
{
Console.Write("Question (Type \"quit\" to leave): ");
string question = Console.ReadLine() ?? string.Empty;
if (question == "quit")
{
break;
}
chatHistory.AddUserMessage(question);
StringBuilder sb = new();
await foreach (var update in chat.GetStreamingChatMessageContentsAsync(chatHistory, settings, kernel))
{
if (update.Content is not null)
{
Console.Write(update.Content);
sb.Append(update.Content);
}
}
chatHistory.AddAssistantMessage(sb.ToString());
Console.WriteLine();
}
}
}
}