-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added console chat app. uses semantic kernel, kernel memory and plugins.
- Loading branch information
1 parent
6c82c01
commit cef888e
Showing
4 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<NoWarn>SKEXP0042</NoWarn> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.28.240212.1" /> | ||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.AzureAISearch" Version="0.28.240212.1" /> | ||
<PackageReference Include="Microsoft.KernelMemory.SemanticKernelPlugin" Version="0.28.240212.1" /> | ||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.3.0" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AzureAISearch" Version="1.3.1-alpha" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Functions.OpenAPI" Version="1.0.0-beta8" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Planners.Handlebars" Version="1.3.0-preview" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Planners.OpenAI" Version="1.3.0-preview" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Memory" Version="1.3.1-alpha" /> | ||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.OpenApi" Version="1.3.0-alpha" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.8.34511.84 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chat.SK", "Chat.SK.csproj", "{F9E08994-3C60-4BA5-8A12-2636BB57E200}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{F9E08994-3C60-4BA5-8A12-2636BB57E200}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{F9E08994-3C60-4BA5-8A12-2636BB57E200}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{F9E08994-3C60-4BA5-8A12-2636BB57E200}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{F9E08994-3C60-4BA5-8A12-2636BB57E200}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {3B750AC7-CD92-407F-AB2D-FA821171F64A} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
using Microsoft.KernelMemory; | ||
using Microsoft.SemanticKernel; | ||
using Microsoft.SemanticKernel.ChatCompletion; | ||
using Microsoft.SemanticKernel.Connectors.OpenAI; | ||
using System.ComponentModel; | ||
|
||
// Disable warnings related to Semantic Kernel | ||
#pragma warning disable SKEXP0003 | ||
#pragma warning disable SKEXP0010 | ||
#pragma warning disable SKEXP0011 | ||
#pragma warning disable SKEXP0021 | ||
#pragma warning disable SKEXP0052 | ||
#pragma warning disable SKEXP0060 | ||
#pragma warning disable SKEXP0061 | ||
|
||
// Azure OpenAI Variables | ||
var apiKey = ""; | ||
var deploymentChatName = ""; | ||
var deploymentEmbeddingName = ""; | ||
var endpoint = ""; | ||
|
||
// Azure AI Search Variables | ||
string searchApiKey = ""; | ||
string searchEndpoint = ""; | ||
|
||
|
||
var builder = Kernel.CreateBuilder(); | ||
|
||
builder | ||
.AddAzureOpenAIChatCompletion( | ||
deploymentChatName, | ||
endpoint, | ||
apiKey); | ||
|
||
var kernel = builder.Build(); | ||
|
||
var embeddingConfig = new AzureOpenAIConfig | ||
{ | ||
APIKey = apiKey, | ||
Deployment = deploymentEmbeddingName, | ||
Endpoint = endpoint, | ||
APIType = AzureOpenAIConfig.APITypes.EmbeddingGeneration, | ||
Auth = AzureOpenAIConfig.AuthTypes.APIKey | ||
}; | ||
|
||
var chatConfig = new AzureOpenAIConfig | ||
{ | ||
APIKey = apiKey, | ||
Deployment = deploymentChatName, | ||
Endpoint = endpoint, | ||
APIType = AzureOpenAIConfig.APITypes.ChatCompletion, | ||
Auth = AzureOpenAIConfig.AuthTypes.APIKey | ||
}; | ||
|
||
var kernelMemory = new KernelMemoryBuilder() | ||
.WithAzureOpenAITextGeneration(chatConfig) | ||
.WithAzureOpenAITextEmbeddingGeneration(embeddingConfig) | ||
.WithAzureAISearchMemoryDb(searchEndpoint, searchApiKey) | ||
.Build<MemoryServerless>(); | ||
|
||
// Import a document to the memory, e.g. Expense Policy PDF document | ||
await kernelMemory.ImportDocumentAsync("CHANGE_ME: FILE_LOCATION.pdf", documentId: "doc001"); | ||
|
||
// Import the memory plugin | ||
var plugin = new MemoryPlugin(kernelMemory, waitForIngestionToComplete: true); | ||
kernel.ImportPluginFromObject(plugin, "memory"); | ||
|
||
// Import the VCard plugin | ||
kernel.ImportPluginFromType<VCardPlugin>(); | ||
|
||
ChatHistory history = []; | ||
|
||
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>(); | ||
|
||
Console.WriteLine("Hello! This is a chat console."); | ||
Console.WriteLine(string.Empty); | ||
|
||
var system = $@" | ||
CHANGE_ME: WRITE YOUR ASSISTANT SYSTEM PROMPT HERE | ||
"; | ||
|
||
history.AddMessage(AuthorRole.System, system); | ||
|
||
// Enable auto function calling | ||
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() | ||
{ | ||
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions | ||
}; | ||
|
||
while (true) | ||
{ | ||
Console.WriteLine(string.Empty); | ||
Console.ForegroundColor = ConsoleColor.Yellow; | ||
Console.Write("Input > "); | ||
var message = Console.ReadLine(); | ||
Console.ResetColor(); | ||
|
||
// Prompt the message to the kernel memory | ||
var prompt = $@" | ||
Question to Kernel Memory: {message} | ||
Kernel Memory Answer: {{memory.ask}} | ||
"; | ||
|
||
history.AddMessage(AuthorRole.User, prompt); | ||
|
||
var result = await chatCompletionService.GetChatMessageContentAsync(history, openAIPromptExecutionSettings, kernel); | ||
|
||
Console.WriteLine(string.Empty); | ||
Console.WriteLine(string.Empty); | ||
Console.Write("Assistant > "); | ||
Console.WriteLine(result.Content); | ||
|
||
history.AddMessage(AuthorRole.Assistant, result.Content); | ||
} | ||
|
||
public class VCardPlugin | ||
{ | ||
const string FunctionModelDescription = @" | ||
- This function creates a request for a Virtual Card. | ||
- You must always ask for the user approval before creating a virtual card. | ||
- You must always ask for the user policy details before creating a virtual card. | ||
- You must always ask for the number of days of travel before creating a virtual card. | ||
- You must always request the ammount to be created. | ||
- If the ammount is bigger than the allowed from the policy deny the request. | ||
"; | ||
|
||
[KernelFunction, Description(FunctionModelDescription)] | ||
public string CreateCard(int ammount, int days) | ||
{ | ||
Random random = new Random(); | ||
string cardNumber = "5" + random.Next(1, 6).ToString() + string.Concat(Enumerable.Range(0, 14).Select(n => random.Next(0, 10).ToString())); | ||
|
||
// Calculate the Luhn check digit | ||
int sum = 0; | ||
for (int i = 0; i < 15; i++) | ||
{ | ||
int digit = int.Parse(cardNumber[i].ToString()); | ||
if (i % 2 == 0) | ||
{ | ||
digit *= 2; | ||
if (digit > 9) | ||
{ | ||
digit -= 9; | ||
} | ||
} | ||
sum += digit; | ||
} | ||
|
||
int checkDigit = (10 - (sum % 10)) % 10; | ||
cardNumber += checkDigit.ToString(); | ||
|
||
// Generate a random expiry date in the future | ||
int expiryMonth = random.Next(1, 13); // Month is between 1 and 12 | ||
int expiryYear = DateTime.Now.Year + random.Next(1, 6); // Year is between now and 5 years from now | ||
|
||
// Generate a random 3-digit CVC | ||
int cvc = random.Next(100, 1000); // CVC is a 3-digit number | ||
|
||
Console.ForegroundColor = ConsoleColor.DarkBlue; | ||
Console.WriteLine($"[Card created with ammount {ammount} for {days} days]"); | ||
Console.WriteLine($"Card Number: {cardNumber}"); | ||
Console.WriteLine($"Expiry Date: {expiryMonth:D2}/{expiryYear}"); | ||
Console.WriteLine($"CVC: {cvc}"); | ||
Console.ResetColor(); | ||
|
||
return "Virtual Card created successfully."; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Intro | ||
|
||
This application is a .NET console chat application. | ||
|
||
The application replicates a chat application where the AI assistant uses techniques like RAG and automatic function calling to assist the user. | ||
An example scenario would be an internal chat app where the user can ask questions about the companies expense/travel policies and request a creation of virtual card to use in a trip. | ||
|
||
The main goal is to: | ||
|
||
- Integrate a semantic kernel memory into the application, which will allow the LLM to remember and recall information from Azure AI Search. | ||
- Demonstrate how to implement plugins in a semantic kernel enabled app. | ||
|
||
Requirements: | ||
|
||
- a Azure OpenAI Service. | ||
- a Azure AI Search Service. | ||
- some public document to be indexed in the Azure AI Search Service. | ||
|
||
## Main Project Structure | ||
|
||
### Chat.SK | ||
|
||
Main project that contains the chat application. It uses the Semantic Kernel and Kernel Memory nuget packages. | ||
|
||
## Running the Application | ||
|
||
Steps: | ||
|
||
1. Update the variables for Azure Open Ai and AI Search in `Program.cs`. | ||
1. Update location of the location of the public document in `Program.cs` to be imported to the Kernel Memory. | ||
1. Add an example system prompt. | ||
1. Run with `dotnet run` or `F5`. |