Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.Net: Added example for chat completion with data and function calling #10261

Merged
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,70 @@ public async Task ExampleWithKernelAsync()
Console.WriteLine();
}

/// <summary>
/// This example shows how to use Azure OpenAI Chat Completion with data and function calling.
/// Note: Data source and function calling are not supported in a single request. Enabling both features
dmytrostruk marked this conversation as resolved.
Show resolved Hide resolved
/// will result in the function calling information being ignored and the operation behaving as if only the data source was provided.
/// To address this limitation, consider separating function calling and data source across multiple requests in your solution design.
/// </summary>
dmytrostruk marked this conversation as resolved.
Show resolved Hide resolved
[Fact]
public async Task ExampleWithFunctionCallingAsync()
{
Console.WriteLine("=== Example with Function Calling ===");

var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(
TestConfiguration.AzureOpenAI.ChatDeploymentName,
TestConfiguration.AzureOpenAI.Endpoint,
TestConfiguration.AzureOpenAI.ApiKey)
.Build();

// Import plugin.
kernel.ImportPluginFromType<DataPlugin>();

var chatHistory = new ChatHistory();

// First question without previous context based on uploaded content.
var ask = "How did Emily and David meet?";
chatHistory.AddUserMessage(ask);

// Enable data source.
var dataSource = GetAzureSearchDataSource();
var promptExecutionSettings = new AzureOpenAIPromptExecutionSettings { AzureChatDataSource = dataSource };

var chatCompletion = kernel.GetRequiredService<IChatCompletionService>();

var chatMessage = await chatCompletion.GetChatMessageContentAsync(chatHistory, promptExecutionSettings, kernel);

var response = chatMessage.Content!;

// Output
// Ask: How did Emily and David meet?
// Response: Emily and David, both passionate scientists, met during a research expedition to Antarctica.
Console.WriteLine($"Ask: {ask}");
Console.WriteLine($"Response: {response}");

// Chat history maintenance.
chatHistory.AddAssistantMessage(response);

// Disable data source and enable function calling.
promptExecutionSettings.AzureChatDataSource = null;
promptExecutionSettings.FunctionChoiceBehavior = FunctionChoiceBehavior.Auto();

ask = "Can I have their emails?";
dmytrostruk marked this conversation as resolved.
Show resolved Hide resolved
chatHistory.AddUserMessage(ask);

chatMessage = await chatCompletion.GetChatMessageContentAsync(chatHistory, promptExecutionSettings, kernel);

response = chatMessage.Content!;

// Output
// Ask: Can I have their emails?
// Response: Emily's email is [email protected] and David's email is [email protected].
Console.WriteLine($"Ask: {ask}");
Console.WriteLine($"Response: {response}");
}

/// <summary>
/// Initializes a new instance of the <see cref="AzureSearchChatDataSource"/> class.
/// </summary>
Expand Down Expand Up @@ -189,5 +253,30 @@ private void OutputCitations(IReadOnlyList<ChatCitation>? citations)
}
}

private sealed class DataPlugin
{
private readonly Dictionary<string, string> _emails = new()
{
["Emily"] = "[email protected]",
["David"] = "[email protected]",
};

[KernelFunction]
public List<string> GetEmails(List<string> users)
{
var emails = new List<string>();

foreach (var user in users)
{
if (this._emails.TryGetValue(user, out var email))
{
emails.Add(email);
}
}

return emails;
}
}

#pragma warning restore AOAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}
Loading