├── .devcontainer └── devcontainer.json ├── .gitignore ├── .vscode └── vscode.code-snippets ├── LICENSE ├── README.md ├── img ├── 05ChatSample.png ├── 06ChatSampleWithAspire.png ├── 10scenarios.png ├── dotnet-icon-256x256-ozvjws7o.ico └── dotnet-icon-256x256-ozvjws7o.png ├── src ├── AppHost │ ├── AppHost.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ └── appsettings.json ├── ClientAppsIntegration.AppDefaults │ ├── AppDefatultsExtensions.cs │ └── ClientAppsIntegration.AppDefaults.csproj ├── SemanticKernel.Connectors.OnnxRuntimeGenAI │ ├── Connectors.OnnxRuntimeGenAI.csproj │ ├── Models │ │ └── PromptBuilderResult.cs │ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs │ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs │ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs │ └── Services │ │ └── OnnxRuntimeGenAIChatCompletionService.cs ├── ServiceDefaults │ ├── Extensions.cs │ └── ServiceDefaults.csproj ├── chat-models │ ├── Citation.cs │ ├── Question.cs │ ├── Response.cs │ └── chat-models.csproj ├── chat-server │ ├── Controllers │ │ └── ChatController.cs │ ├── NativeFunctions │ │ └── HeroInfo.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── chat-server.csproj │ └── chat-server.http ├── chat-winform │ ├── Azure │ │ └── AzureBlobContainer.cs │ ├── ChatAPI │ │ └── ChatApiClient.cs │ ├── ChatControls │ │ ├── ChatItem.Designer.cs │ │ ├── ChatItem.cs │ │ ├── ChatItem.resx │ │ ├── ChatModels.cs │ │ ├── ChatPanel.Functions.cs │ │ ├── Chatbox.Designer.cs │ │ ├── Chatbox.cs │ │ ├── Chatbox.resx │ │ ├── ChatboxInfo.cs │ │ └── fileattach.png │ ├── Program.cs │ ├── Properties │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Resources │ │ └── Large_SK_Logo-300x300.png │ ├── appsettings.json │ ├── chat-winform.csproj │ ├── dotnet-icon-256x256-ozvjws7o.ico │ ├── frmChat.Designer.cs │ ├── frmChat.cs │ └── frmChat.resx ├── sk-chat-demo-aspire.sln └── sk-chat-demo.sln ├── srcBU ├── 00 chat-server init │ ├── AppHost │ │ ├── AppHost.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── ClientAppsIntegration.AppDefaults │ │ ├── AppDefatultsExtensions.cs │ │ └── ClientAppsIntegration.AppDefaults.csproj │ ├── SemanticKernel.Connectors.OnnxRuntimeGenAI │ │ ├── Connectors.OnnxRuntimeGenAI.csproj │ │ ├── Models │ │ │ └── PromptBuilderResult.cs │ │ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs │ │ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs │ │ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs │ │ └── Services │ │ │ └── OnnxRuntimeGenAIChatCompletionService.cs │ ├── ServiceDefaults │ │ ├── Extensions.cs │ │ └── ServiceDefaults.csproj │ ├── chat-models │ │ ├── Citation.cs │ │ ├── Question.cs │ │ ├── Response.cs │ │ └── chat-models.csproj │ ├── chat-server │ │ ├── Controllers │ │ │ └── ChatController.cs │ │ ├── NativeFunctions │ │ │ └── HeroInfo.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── chat-server.csproj │ │ └── chat-server.http │ ├── chat-winform │ │ ├── Azure │ │ │ └── AzureBlobContainer.cs │ │ ├── ChatAPI │ │ │ └── ChatApiClient.cs │ │ ├── ChatControls │ │ │ ├── ChatItem.Designer.cs │ │ │ ├── ChatItem.cs │ │ │ ├── ChatItem.resx │ │ │ ├── ChatModels.cs │ │ │ ├── ChatPanel.Functions.cs │ │ │ ├── Chatbox.Designer.cs │ │ │ ├── Chatbox.cs │ │ │ ├── Chatbox.resx │ │ │ ├── ChatboxInfo.cs │ │ │ └── fileattach.png │ │ ├── Program.cs │ │ ├── Properties │ │ │ ├── Resources.Designer.cs │ │ │ └── Resources.resx │ │ ├── Resources │ │ │ └── Large_SK_Logo-300x300.png │ │ ├── appsettings.json │ │ ├── chat-winform.csproj │ │ ├── dotnet-icon-256x256-ozvjws7o.ico │ │ ├── frmChat.Designer.cs │ │ ├── frmChat.cs │ │ └── frmChat.resx │ ├── sk-chat-demo-aspire.sln │ └── sk-chat-demo.sln ├── 10 chat-server AOAI │ ├── AppHost │ │ ├── AppHost.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── ClientAppsIntegration.AppDefaults │ │ ├── AppDefatultsExtensions.cs │ │ └── ClientAppsIntegration.AppDefaults.csproj │ ├── SemanticKernel.Connectors.OnnxRuntimeGenAI │ │ ├── Connectors.OnnxRuntimeGenAI.csproj │ │ ├── Models │ │ │ └── PromptBuilderResult.cs │ │ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs │ │ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs │ │ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs │ │ └── Services │ │ │ └── OnnxRuntimeGenAIChatCompletionService.cs │ ├── ServiceDefaults │ │ ├── Extensions.cs │ │ └── ServiceDefaults.csproj │ ├── chat-models │ │ ├── Citation.cs │ │ ├── Question.cs │ │ ├── Response.cs │ │ └── chat-models.csproj │ ├── chat-server │ │ ├── Controllers │ │ │ └── ChatController.cs │ │ ├── NativeFunctions │ │ │ └── HeroInfo.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── chat-server.csproj │ │ └── chat-server.http │ ├── chat-winform │ │ ├── Azure │ │ │ └── AzureBlobContainer.cs │ │ ├── ChatAPI │ │ │ └── ChatApiClient.cs │ │ ├── ChatControls │ │ │ ├── ChatItem.Designer.cs │ │ │ ├── ChatItem.cs │ │ │ ├── ChatItem.resx │ │ │ ├── ChatModels.cs │ │ │ ├── ChatPanel.Functions.cs │ │ │ ├── Chatbox.Designer.cs │ │ │ ├── Chatbox.cs │ │ │ ├── Chatbox.resx │ │ │ ├── ChatboxInfo.cs │ │ │ └── fileattach.png │ │ ├── Program.cs │ │ ├── Properties │ │ │ ├── Resources.Designer.cs │ │ │ └── Resources.resx │ │ ├── Resources │ │ │ └── Large_SK_Logo-300x300.png │ │ ├── appsettings.json │ │ ├── chat-winform.csproj │ │ ├── dotnet-icon-256x256-ozvjws7o.ico │ │ ├── frmChat.Designer.cs │ │ ├── frmChat.cs │ │ └── frmChat.resx │ ├── sk-chat-demo-aspire.sln │ └── sk-chat-demo.sln ├── 20 chat-server phi-3 │ ├── Controllers │ │ └── ChatController.cs │ └── Program.cs ├── 30 chat-server memory │ ├── Controllers │ │ └── ChatController.cs │ └── Program.cs ├── 35 RAG with Azure AI Search │ ├── AppHost │ │ ├── AppHost.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── ClientAppsIntegration.AppDefaults │ │ ├── AppDefatultsExtensions.cs │ │ └── ClientAppsIntegration.AppDefaults.csproj │ ├── SemanticKernel.Connectors.OnnxRuntimeGenAI │ │ ├── Connectors.OnnxRuntimeGenAI.csproj │ │ ├── Models │ │ │ └── PromptBuilderResult.cs │ │ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs │ │ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs │ │ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs │ │ └── Services │ │ │ └── OnnxRuntimeGenAIChatCompletionService.cs │ ├── ServiceDefaults │ │ ├── Extensions.cs │ │ └── ServiceDefaults.csproj │ ├── chat-models │ │ ├── Citation.cs │ │ ├── Question.cs │ │ ├── Response.cs │ │ └── chat-models.csproj │ ├── chat-server │ │ ├── Controllers │ │ │ └── ChatController.cs │ │ ├── NativeFunctions │ │ │ └── HeroInfo.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── chat-server.csproj │ │ └── chat-server.http │ ├── chat-winform │ │ ├── Azure │ │ │ └── AzureBlobContainer.cs │ │ ├── ChatAPI │ │ │ └── ChatApiClient.cs │ │ ├── ChatControls │ │ │ ├── ChatItem.Designer.cs │ │ │ ├── ChatItem.cs │ │ │ ├── ChatItem.resx │ │ │ ├── ChatModels.cs │ │ │ ├── ChatPanel.Functions.cs │ │ │ ├── Chatbox.Designer.cs │ │ │ ├── Chatbox.cs │ │ │ ├── Chatbox.resx │ │ │ ├── ChatboxInfo.cs │ │ │ └── fileattach.png │ │ ├── Program.cs │ │ ├── Properties │ │ │ ├── Resources.Designer.cs │ │ │ └── Resources.resx │ │ ├── Resources │ │ │ └── Large_SK_Logo-300x300.png │ │ ├── appsettings.json │ │ ├── chat-winform.csproj │ │ ├── dotnet-icon-256x256-ozvjws7o.ico │ │ ├── frmChat.Designer.cs │ │ ├── frmChat.cs │ │ └── frmChat.resx │ ├── sk-chat-demo-aspire.sln │ └── sk-chat-demo.sln ├── 50 chat-server otlp │ ├── Controllers │ │ └── ChatController.cs │ └── Program.cs ├── 60 chat-server superhero api │ ├── Controllers │ │ └── ChatController.cs │ └── Program.cs ├── 70 Aspire │ └── chat-winform │ │ ├── Program.cs │ │ └── appsettings.json └── 80 Video Accident │ ├── AppHost │ ├── AppHost.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ └── appsettings.json │ ├── ClientAppsIntegration.AppDefaults │ ├── AppDefatultsExtensions.cs │ └── ClientAppsIntegration.AppDefaults.csproj │ ├── SemanticKernel.Connectors.OnnxRuntimeGenAI │ ├── Connectors.OnnxRuntimeGenAI.csproj │ ├── Models │ │ └── PromptBuilderResult.cs │ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs │ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs │ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs │ └── Services │ │ └── OnnxRuntimeGenAIChatCompletionService.cs │ ├── ServiceDefaults │ ├── Extensions.cs │ └── ServiceDefaults.csproj │ ├── chat-models │ ├── Citation.cs │ ├── Question.cs │ ├── Response.cs │ └── chat-models.csproj │ ├── chat-server │ ├── Controllers │ │ └── ChatController.cs │ ├── NativeFunctions │ │ └── HeroInfo.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── chat-server.csproj │ └── chat-server.http │ ├── chat-winform │ ├── Azure │ │ └── AzureBlobContainer.cs │ ├── ChatAPI │ │ └── ChatApiClient.cs │ ├── ChatControls │ │ ├── ChatItem.Designer.cs │ │ ├── ChatItem.cs │ │ ├── ChatItem.resx │ │ ├── ChatModels.cs │ │ ├── ChatPanel.Functions.cs │ │ ├── Chatbox.Designer.cs │ │ ├── Chatbox.cs │ │ ├── Chatbox.resx │ │ ├── ChatboxInfo.cs │ │ └── fileattach.png │ ├── Program.cs │ ├── Properties │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Resources │ │ └── Large_SK_Logo-300x300.png │ ├── appsettings.json │ ├── chat-winform.csproj │ ├── dotnet-icon-256x256-ozvjws7o.ico │ ├── frmChat.Designer.cs │ ├── frmChat.cs │ └── frmChat.resx │ ├── sk-chat-demo-aspire.sln │ └── sk-chat-demo.sln └── srcCompleted └── 60 chat-server superhero api ├── ClientAppsIntegration.AppDefaults ├── AppDefatultsExtensions.cs └── ClientAppsIntegration.AppDefaults.csproj ├── SemanticKernel.Connectors.OnnxRuntimeGenAI ├── Connectors.OnnxRuntimeGenAI.csproj ├── Models │ └── PromptBuilderResult.cs ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs ├── OnnxRuntimeGenAIPromptExecutionSettings.cs ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs └── Services │ └── OnnxRuntimeGenAIChatCompletionService.cs ├── chat-models ├── Citation.cs ├── Question.cs ├── Response.cs └── chat-models.csproj ├── chat-server ├── Controllers │ └── ChatController.cs ├── NativeFunctions │ └── HeroInfo.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── appsettings.Development.json ├── appsettings.json ├── chat-server.csproj └── chat-server.http ├── chat-winform ├── Azure │ └── AzureBlobContainer.cs ├── ChatControls │ ├── ChatItem.Designer.cs │ ├── ChatItem.cs │ ├── ChatItem.resx │ ├── ChatModels.cs │ ├── ChatPanel.Functions.cs │ ├── Chatbox.Designer.cs │ ├── Chatbox.cs │ ├── Chatbox.resx │ ├── ChatboxInfo.cs │ └── fileattach.png ├── Program.cs ├── Properties │ ├── Resources.Designer.cs │ └── Resources.resx ├── Resources │ └── Large_SK_Logo-300x300.png ├── appsettings.json ├── chat-winform.csproj ├── dotnet-icon-256x256-ozvjws7o.ico ├── frmChat.Designer.cs ├── frmChat.cs └── frmChat.resx └── sk-chat-demo.sln /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NET 8 + Ollama + Phi-3 + Aspire Dashboard", 3 | "image": "mcr.microsoft.com/devcontainers/dotnet", 4 | "features": { 5 | "ghcr.io/devcontainers/features/dotnet:2": { "version": "8.0"}, 6 | "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}, 7 | "ghcr.io/devcontainers/features/azure-cli:1": {}, 8 | "ghcr.io/devcontainers/features/docker-from-docker:1.5.0": {}, 9 | "ghcr.io/devcontainers/features/github-cli:1": { "version": "2" }, 10 | "ghcr.io/prulloac/devcontainer-features/ollama:1": {}, 11 | "sshd": "latest" 12 | }, 13 | "customizations": { 14 | "vscode": { 15 | "extensions": [ 16 | "ms-vscode.vscode-node-azure-pack", 17 | "github.vscode-github-actions", 18 | "ms-dotnettools.csdevkit", 19 | "ms-dotnettools.vscode-dotnet-runtime", 20 | "github.copilot" 21 | ] 22 | } 23 | }, 24 | "forwardPorts": [ 25 | 32000, 26 | 32001 27 | ], 28 | "postCreateCommand": "sudo dotnet workload update & sudo dotnet workload install aspire & sudo dotnet workload list", 29 | "postStartCommand": "ollama pull phi3 & docker run --rm -it -p 18888:18888 -p 4317:18889 -d --name aspire-dashboard mcr.microsoft.com/dotnet/aspire-dashboard:8.0.0", 30 | "remoteUser": "vscode", 31 | "hostRequirements": { 32 | "memory": "8gb", 33 | "cpus": 4 34 | }, 35 | "portsAttributes": { 36 | "11434": { 37 | "label": "Ollama" 38 | }, 39 | "4317": { 40 | "label": "Aspire Dashboard Endpoint" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 El Bruno 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /img/05ChatSample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/img/05ChatSample.png -------------------------------------------------------------------------------- /img/06ChatSampleWithAspire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/img/06ChatSampleWithAspire.png -------------------------------------------------------------------------------- /img/10scenarios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/img/10scenarios.png -------------------------------------------------------------------------------- /img/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/img/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /img/dotnet-icon-256x256-ozvjws7o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/img/dotnet-icon-256x256-ozvjws7o.png -------------------------------------------------------------------------------- /src/AppHost/AppHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 2c6c8cc9-d757-49ad-a150-d8dc54fba6ba 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/AppHost/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = DistributedApplication.CreateBuilder(args); 2 | 3 | var chatapi = builder.AddProject("chatapi"); 4 | 5 | if (OperatingSystem.IsWindows()) 6 | { 7 | var chatform = builder.AddProject("chatform") 8 | .WithReference(chatapi) 9 | .ExcludeFromManifest(); ; 10 | } 11 | builder.Build().Run(); 12 | -------------------------------------------------------------------------------- /src/AppHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "https://localhost:17095;http://localhost:15115", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development", 11 | "DOTNET_ENVIRONMENT": "Development", 12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21138", 13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22235" 14 | } 15 | }, 16 | "http": { 17 | "commandName": "Project", 18 | "dotnetRunMessages": true, 19 | "launchBrowser": true, 20 | "applicationUrl": "http://localhost:15115", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development", 23 | "DOTNET_ENVIRONMENT": "Development", 24 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19082", 25 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20033" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/AppHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/AppHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning", 6 | "Aspire.Hosting.Dcp": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ServiceDefaults/ServiceDefaults.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public string ImageMimeType { get; set; } 16 | public byte[]? FileBytes { get; set; } 17 | public string UserName { get; set; } 18 | public string UserQuestion { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero. Get the real name of a super hero.")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/chat-server/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | 15 | var builder = WebApplication.CreateBuilder(args); 16 | 17 | builder.AddServiceDefaults(); 18 | 19 | // Add services to the container. 20 | builder.Services.AddControllers(); 21 | builder.Services.AddEndpointsApiExplorer(); 22 | builder.Services.AddSwaggerGen(); 23 | 24 | builder.Services.AddLogging( 25 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 26 | ); 27 | 28 | builder.Services.AddSingleton(sp => 29 | { 30 | return builder.Configuration; 31 | }); 32 | 33 | builder.Services.AddSingleton(sp => 34 | { 35 | // add Azure OpenAI Chat Completion service 36 | var config = builder.Configuration; 37 | var chatDeploymentName = config["AZURE_OPENAI_MODEL"]; 38 | var endpoint = config["AZURE_OPENAI_ENDPOINT"]; 39 | var apiKey = config["AZURE_OPENAI_APIKEY"]; 40 | // set author 41 | config["author"]= "Azure OpenAI - GPT-4o"; 42 | 43 | return new AzureOpenAIChatCompletionService(chatDeploymentName, endpoint, apiKey); 44 | }); 45 | 46 | builder.Services.AddSingleton(sp => 47 | { 48 | var chatHistory = new ChatHistory(); 49 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 50 | return chatHistory; 51 | }); 52 | 53 | var app = builder.Build(); 54 | 55 | app.MapDefaultEndpoints(); 56 | 57 | // Configure the HTTP request pipeline. 58 | if (app.Environment.IsDevelopment()) 59 | { 60 | app.UseSwagger(); 61 | app.UseSwaggerUI(); 62 | } 63 | 64 | app.UseHttpsRedirection(); 65 | 66 | app.UseAuthorization(); 67 | 68 | app.MapControllers(); 69 | 70 | app.Run(); 71 | -------------------------------------------------------------------------------- /src/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /src/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /src/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/chat-winform/ChatAPI/ChatApiClient.cs: -------------------------------------------------------------------------------- 1 | using chat_models; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | 5 | namespace chat_winform; 6 | 7 | public class ChatApiClient(HttpClient httpClient) 8 | { 9 | public async Task CallApiChat(Question question, CancellationToken cancellationToken = default) 10 | { 11 | 12 | var responseLocal = new Response(); 13 | var httpResponse = await httpClient.PostAsJsonAsync("api/chat", question, cancellationToken: cancellationToken); 14 | if (httpResponse.IsSuccessStatusCode) 15 | { 16 | responseLocal = await httpResponse.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); 17 | } 18 | return responseLocal; 19 | } 20 | 21 | public string BaseAddress => httpClient.BaseAddress.ToString(); 22 | 23 | public HttpClient HttpClient => httpClient; 24 | } -------------------------------------------------------------------------------- /src/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class AttachmentChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "attachment"; 51 | public byte[] Attachment { get; set; } 52 | public string DocUri { get; set; } 53 | public string Filename { get; set; } 54 | public TimeSpan? ElapsedTime { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/src/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /src/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | //builder.AddAppDefaults(); 24 | builder.AddServiceDefaults(); 25 | 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{builder.Configuration["CHAT_SERVER"]}")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/src/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /src/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /src/chat-winform/chat-winform.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows8.0 6 | chat_winform 7 | true 8 | true 9 | f0ce84b4-bdc5-4452-8ea0-44a0f69ea165 10 | True 11 | enable 12 | dotnet-icon-256x256-ozvjws7o.ico 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Always 23 | true 24 | PreserveNewest 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | True 51 | True 52 | Resources.resx 53 | 54 | 55 | 56 | 57 | 58 | 59 | ResXFileCodeGenerator 60 | Resources.Designer.cs 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/src/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /src/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chat_winform 4 | { 5 | public partial class frmChat : Form 6 | { 7 | ChatApiClient _chatApiClient; 8 | private readonly ILogger _logger; 9 | 10 | string userName = @"Bruno"; 11 | ChatForm.ChatboxInfo cbi; 12 | 13 | public frmChat(ILogger logger, ChatApiClient chatApiClient) 14 | { 15 | _logger = logger; 16 | _chatApiClient = chatApiClient; 17 | InitializeComponent(); 18 | } 19 | 20 | private async void Form1_LoadAsync(object sender, EventArgs e) 21 | { 22 | // chat control 23 | cbi = new ChatForm.ChatboxInfo 24 | { 25 | MainTitlePlaceholder = "Adding AI to a Winforms Chat", 26 | SubtitlePlaceholder = "No LLM", 27 | User = userName 28 | }; 29 | toolStripTextBoxUserName.Text = userName; 30 | 31 | chatboxControl._chatApiClient = _chatApiClient; 32 | chatboxControl._logger = _logger; 33 | chatboxControl.SetChatBotInfo(cbi); 34 | 35 | // display chat server 36 | toolStripMenuItemShowServer.Text = $"Chat Server: {_chatApiClient.BaseAddress}"; 37 | } 38 | 39 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 40 | { 41 | userName = toolStripTextBoxUserName.Text; 42 | cbi.User = userName; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/AppHost/AppHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 2c6c8cc9-d757-49ad-a150-d8dc54fba6ba 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/AppHost/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = DistributedApplication.CreateBuilder(args); 2 | 3 | var chatapi = builder.AddProject("chatapi"); 4 | 5 | if (OperatingSystem.IsWindows()) 6 | { 7 | var chatform = builder.AddProject("chatform") 8 | .WithReference(chatapi) 9 | .ExcludeFromManifest(); ; 10 | } 11 | builder.Build().Run(); 12 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/AppHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "https://localhost:17095;http://localhost:15115", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development", 11 | "DOTNET_ENVIRONMENT": "Development", 12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21138", 13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22235" 14 | } 15 | }, 16 | "http": { 17 | "commandName": "Project", 18 | "dotnetRunMessages": true, 19 | "launchBrowser": true, 20 | "applicationUrl": "http://localhost:15115", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development", 23 | "DOTNET_ENVIRONMENT": "Development", 24 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19082", 25 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20033" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/AppHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/AppHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning", 6 | "Aspire.Hosting.Dcp": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/ServiceDefaults/ServiceDefaults.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public string ImageMimeType { get; set; } 16 | public byte[]? FileBytes { get; set; } 17 | public string UserName { get; set; } 18 | public string UserQuestion { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/Controllers/ChatController.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using chat_models; 8 | using System.Diagnostics; 9 | using Azure.AI.OpenAI; 10 | using Microsoft.AspNetCore.Mvc; 11 | using Microsoft.AspNetCore.OutputCaching; 12 | using Microsoft.SemanticKernel; 13 | using Microsoft.SemanticKernel.ChatCompletion; 14 | using Microsoft.SemanticKernel.Memory; 15 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 16 | using Microsoft.SemanticKernel.Connectors.OpenAI; 17 | namespace chat_server.Controllers; 18 | 19 | [Route("api/[controller]")] 20 | [ApiController] 21 | public class ChatController : ControllerBase 22 | { 23 | private bool _useCache = false; 24 | 25 | private readonly ILogger _logger; 26 | 27 | private IConfiguration _config; 28 | 29 | private ChatHistory _chatHistory; 30 | 31 | public ChatController(ILogger logger, IConfiguration config, ChatHistory chatHistory) 32 | { 33 | _logger = logger; 34 | _chatHistory = chatHistory; 35 | _config = config; 36 | } 37 | 38 | // POST api/ 39 | [HttpPost] 40 | public async Task Post(Question question) 41 | { 42 | _logger.LogInformation($"Input question: {question}"); 43 | 44 | var response = new Response 45 | { 46 | Author = string.IsNullOrEmpty(_config["Author"]) ? "chatbot" : _config["Author"] 47 | }; 48 | // complete chat history 49 | _chatHistory.AddUserMessage(question.UserQuestion); 50 | 51 | // get response 52 | var stopwatch = new Stopwatch(); 53 | stopwatch.Start(); 54 | var chatResponse = $" Your question [{question.UserQuestion}] is {question.UserQuestion.Length} chars long."; 55 | stopwatch.Stop(); 56 | response.QuestionResponse = chatResponse; 57 | response.ElapsedTime = stopwatch.Elapsed; 58 | 59 | // return response 60 | _logger.LogInformation($"Response: {response}"); 61 | return response; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero. Get the real name of a super hero.")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | 15 | var builder = WebApplication.CreateBuilder(args); 16 | 17 | builder.AddServiceDefaults(); 18 | 19 | // Add services to the container. 20 | builder.Services.AddControllers(); 21 | builder.Services.AddEndpointsApiExplorer(); 22 | builder.Services.AddSwaggerGen(); 23 | 24 | builder.Services.AddLogging( 25 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 26 | ); 27 | 28 | builder.Services.AddSingleton(sp => 29 | { 30 | return builder.Configuration; 31 | }); 32 | 33 | builder.Services.AddSingleton(sp => 34 | { 35 | var chatHistory = new ChatHistory(); 36 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 37 | return chatHistory; 38 | }); 39 | 40 | var app = builder.Build(); 41 | 42 | app.MapDefaultEndpoints(); 43 | 44 | // Configure the HTTP request pipeline. 45 | if (app.Environment.IsDevelopment()) 46 | { 47 | app.UseSwagger(); 48 | app.UseSwaggerUI(); 49 | } 50 | 51 | app.UseHttpsRedirection(); 52 | 53 | app.UseAuthorization(); 54 | 55 | app.MapControllers(); 56 | 57 | app.Run(); 58 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/ChatAPI/ChatApiClient.cs: -------------------------------------------------------------------------------- 1 | using chat_models; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | 5 | namespace chat_winform; 6 | 7 | public class ChatApiClient(HttpClient httpClient) 8 | { 9 | public async Task CallApiChat(Question question, CancellationToken cancellationToken = default) 10 | { 11 | 12 | var responseLocal = new Response(); 13 | var httpResponse = await httpClient.PostAsJsonAsync("api/chat", question, cancellationToken: cancellationToken); 14 | if (httpResponse.IsSuccessStatusCode) 15 | { 16 | responseLocal = await httpResponse.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); 17 | } 18 | return responseLocal; 19 | } 20 | 21 | public string BaseAddress => httpClient.BaseAddress.ToString(); 22 | 23 | public HttpClient HttpClient => httpClient; 24 | } -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class AttachmentChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "attachment"; 51 | public byte[] Attachment { get; set; } 52 | public string DocUri { get; set; } 53 | public string Filename { get; set; } 54 | public TimeSpan? ElapsedTime { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/00 chat-server init/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | //builder.AddAppDefaults(); 24 | builder.AddServiceDefaults(); 25 | 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{builder.Configuration["CHAT_SERVER"]}")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/00 chat-server init/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/00 chat-server init/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /srcBU/00 chat-server init/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chat_winform 4 | { 5 | public partial class frmChat : Form 6 | { 7 | ChatApiClient _chatApiClient; 8 | private readonly ILogger _logger; 9 | 10 | string userName = @"Bruno"; 11 | ChatForm.ChatboxInfo cbi; 12 | 13 | public frmChat(ILogger logger, ChatApiClient chatApiClient) 14 | { 15 | _logger = logger; 16 | _chatApiClient = chatApiClient; 17 | InitializeComponent(); 18 | } 19 | 20 | private async void Form1_LoadAsync(object sender, EventArgs e) 21 | { 22 | // chat control 23 | cbi = new ChatForm.ChatboxInfo 24 | { 25 | MainTitlePlaceholder = "Adding AI to a Winforms Chat", 26 | SubtitlePlaceholder = "No LLM", 27 | User = userName 28 | }; 29 | toolStripTextBoxUserName.Text = userName; 30 | 31 | chatboxControl._chatApiClient = _chatApiClient; 32 | chatboxControl._logger = _logger; 33 | chatboxControl.SetChatBotInfo(cbi); 34 | 35 | // display chat server 36 | toolStripMenuItemShowServer.Text = $"Chat Server: {_chatApiClient.BaseAddress}"; 37 | } 38 | 39 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 40 | { 41 | userName = toolStripTextBoxUserName.Text; 42 | cbi.User = userName; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/AppHost/AppHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 2c6c8cc9-d757-49ad-a150-d8dc54fba6ba 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/AppHost/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = DistributedApplication.CreateBuilder(args); 2 | 3 | var chatapi = builder.AddProject("chatapi"); 4 | 5 | if (OperatingSystem.IsWindows()) 6 | { 7 | var chatform = builder.AddProject("chatform") 8 | .WithReference(chatapi) 9 | .ExcludeFromManifest(); ; 10 | } 11 | builder.Build().Run(); 12 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/AppHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "https://localhost:17095;http://localhost:15115", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development", 11 | "DOTNET_ENVIRONMENT": "Development", 12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21138", 13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22235" 14 | } 15 | }, 16 | "http": { 17 | "commandName": "Project", 18 | "dotnetRunMessages": true, 19 | "launchBrowser": true, 20 | "applicationUrl": "http://localhost:15115", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development", 23 | "DOTNET_ENVIRONMENT": "Development", 24 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19082", 25 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20033" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/AppHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/AppHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning", 6 | "Aspire.Hosting.Dcp": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/ServiceDefaults/ServiceDefaults.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public string ImageMimeType { get; set; } 16 | public byte[]? FileBytes { get; set; } 17 | public string UserName { get; set; } 18 | public string UserQuestion { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero. Get the real name of a super hero.")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | using Microsoft.SemanticKernel.Connectors.AzureOpenAI; 15 | 16 | var builder = WebApplication.CreateBuilder(args); 17 | 18 | builder.AddServiceDefaults(); 19 | 20 | // Add services to the container. 21 | builder.Services.AddControllers(); 22 | builder.Services.AddEndpointsApiExplorer(); 23 | builder.Services.AddSwaggerGen(); 24 | 25 | builder.Services.AddLogging( 26 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 27 | ); 28 | 29 | builder.Services.AddSingleton(sp => 30 | { 31 | return builder.Configuration; 32 | }); 33 | 34 | builder.Services.AddSingleton(sp => 35 | { 36 | // add Azure OpenAI Chat Completion service 37 | var config = builder.Configuration; 38 | var chatDeploymentName = config["AZURE_OPENAI_MODEL"]; 39 | var endpoint = config["AZURE_OPENAI_ENDPOINT"]; 40 | var apiKey = config["AZURE_OPENAI_APIKEY"]; 41 | // set author 42 | config["author"]= "Azure OpenAI - GPT-4o"; 43 | 44 | return new AzureOpenAIChatCompletionService(chatDeploymentName, endpoint, apiKey); 45 | }); 46 | 47 | builder.Services.AddSingleton(sp => 48 | { 49 | var chatHistory = new ChatHistory(); 50 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 51 | return chatHistory; 52 | }); 53 | 54 | var app = builder.Build(); 55 | 56 | app.MapDefaultEndpoints(); 57 | 58 | // Configure the HTTP request pipeline. 59 | if (app.Environment.IsDevelopment()) 60 | { 61 | app.UseSwagger(); 62 | app.UseSwaggerUI(); 63 | } 64 | 65 | app.UseHttpsRedirection(); 66 | 67 | app.UseAuthorization(); 68 | 69 | app.MapControllers(); 70 | 71 | app.Run(); 72 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/ChatAPI/ChatApiClient.cs: -------------------------------------------------------------------------------- 1 | using chat_models; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | 5 | namespace chat_winform; 6 | 7 | public class ChatApiClient(HttpClient httpClient) 8 | { 9 | public async Task CallApiChat(Question question, CancellationToken cancellationToken = default) 10 | { 11 | 12 | var responseLocal = new Response(); 13 | var httpResponse = await httpClient.PostAsJsonAsync("api/chat", question, cancellationToken: cancellationToken); 14 | if (httpResponse.IsSuccessStatusCode) 15 | { 16 | responseLocal = await httpResponse.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); 17 | } 18 | return responseLocal; 19 | } 20 | 21 | public string BaseAddress => httpClient.BaseAddress.ToString(); 22 | 23 | public HttpClient HttpClient => httpClient; 24 | } -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class AttachmentChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "attachment"; 51 | public byte[] Attachment { get; set; } 52 | public string DocUri { get; set; } 53 | public string Filename { get; set; } 54 | public TimeSpan? ElapsedTime { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/10 chat-server AOAI/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | //builder.AddAppDefaults(); 24 | builder.AddServiceDefaults(); 25 | 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{builder.Configuration["CHAT_SERVER"]}")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/10 chat-server AOAI/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/chat-winform.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows8.0 6 | chat_winform 7 | true 8 | true 9 | f0ce84b4-bdc5-4452-8ea0-44a0f69ea165 10 | True 11 | enable 12 | dotnet-icon-256x256-ozvjws7o.ico 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Always 23 | true 24 | PreserveNewest 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | True 51 | True 52 | Resources.resx 53 | 54 | 55 | 56 | 57 | 58 | 59 | ResXFileCodeGenerator 60 | Resources.Designer.cs 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/10 chat-server AOAI/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /srcBU/10 chat-server AOAI/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chat_winform 4 | { 5 | public partial class frmChat : Form 6 | { 7 | ChatApiClient _chatApiClient; 8 | private readonly ILogger _logger; 9 | 10 | string userName = @"Bruno"; 11 | ChatForm.ChatboxInfo cbi; 12 | 13 | public frmChat(ILogger logger, ChatApiClient chatApiClient) 14 | { 15 | _logger = logger; 16 | _chatApiClient = chatApiClient; 17 | InitializeComponent(); 18 | } 19 | 20 | private async void Form1_LoadAsync(object sender, EventArgs e) 21 | { 22 | // chat control 23 | cbi = new ChatForm.ChatboxInfo 24 | { 25 | MainTitlePlaceholder = "Adding AI to a Winforms Chat", 26 | SubtitlePlaceholder = "No LLM", 27 | User = userName 28 | }; 29 | toolStripTextBoxUserName.Text = userName; 30 | 31 | chatboxControl._chatApiClient = _chatApiClient; 32 | chatboxControl._logger = _logger; 33 | chatboxControl.SetChatBotInfo(cbi); 34 | 35 | // display chat server 36 | toolStripMenuItemShowServer.Text = $"Chat Server: {_chatApiClient.BaseAddress}"; 37 | } 38 | 39 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 40 | { 41 | userName = toolStripTextBoxUserName.Text; 42 | cbi.User = userName; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /srcBU/20 chat-server phi-3/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | 15 | var builder = WebApplication.CreateBuilder(args); 16 | 17 | // Add services to the container. 18 | builder.Services.AddControllers(); 19 | builder.Services.AddEndpointsApiExplorer(); 20 | builder.Services.AddSwaggerGen(); 21 | 22 | builder.Services.AddLogging( 23 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 24 | ); 25 | 26 | builder.Services.AddSingleton(sp => 27 | { 28 | return builder.Configuration; 29 | }); 30 | 31 | builder.Services.AddSingleton(sp => 32 | { 33 | var chatHistory = new ChatHistory(); 34 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 35 | return chatHistory; 36 | }); 37 | 38 | builder.Services.AddSingleton(sp => 39 | { 40 | // add Phi-3 model from a ollama server 41 | var model = "phi3"; 42 | var endpoint = "http://localhost:11434"; 43 | var apiKey = "apiKey"; 44 | builder.Configuration["author"]= "Phi-3 Ollama Docker"; 45 | 46 | return new OpenAIChatCompletionService(model, new Uri(endpoint), apiKey); 47 | }); 48 | 49 | 50 | var app = builder.Build(); 51 | 52 | // Configure the HTTP request pipeline. 53 | if (app.Environment.IsDevelopment()) 54 | { 55 | app.UseSwagger(); 56 | app.UseSwaggerUI(); 57 | } 58 | 59 | app.UseHttpsRedirection(); 60 | 61 | app.UseAuthorization(); 62 | 63 | app.MapControllers(); 64 | 65 | app.Run(); 66 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/AppHost/AppHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 2c6c8cc9-d757-49ad-a150-d8dc54fba6ba 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/AppHost/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = DistributedApplication.CreateBuilder(args); 2 | 3 | var chatapi = builder.AddProject("chatapi"); 4 | 5 | if (OperatingSystem.IsWindows()) 6 | { 7 | var chatform = builder.AddProject("chatform") 8 | .WithReference(chatapi) 9 | .ExcludeFromManifest(); ; 10 | } 11 | builder.Build().Run(); 12 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/AppHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "https://localhost:17095;http://localhost:15115", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development", 11 | "DOTNET_ENVIRONMENT": "Development", 12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21138", 13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22235" 14 | } 15 | }, 16 | "http": { 17 | "commandName": "Project", 18 | "dotnetRunMessages": true, 19 | "launchBrowser": true, 20 | "applicationUrl": "http://localhost:15115", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development", 23 | "DOTNET_ENVIRONMENT": "Development", 24 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19082", 25 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20033" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/AppHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/AppHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning", 6 | "Aspire.Hosting.Dcp": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/ServiceDefaults/ServiceDefaults.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public string ImageMimeType { get; set; } 16 | public byte[]? FileBytes { get; set; } 17 | public string UserName { get; set; } 18 | public string UserQuestion { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero. Get the real name of a super hero.")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/ChatAPI/ChatApiClient.cs: -------------------------------------------------------------------------------- 1 | using chat_models; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | 5 | namespace chat_winform; 6 | 7 | public class ChatApiClient(HttpClient httpClient) 8 | { 9 | public async Task CallApiChat(Question question, CancellationToken cancellationToken = default) 10 | { 11 | 12 | var responseLocal = new Response(); 13 | var httpResponse = await httpClient.PostAsJsonAsync("api/chat", question, cancellationToken: cancellationToken); 14 | if (httpResponse.IsSuccessStatusCode) 15 | { 16 | responseLocal = await httpResponse.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); 17 | } 18 | return responseLocal; 19 | } 20 | 21 | public string BaseAddress => httpClient.BaseAddress.ToString(); 22 | 23 | public HttpClient HttpClient => httpClient; 24 | } -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class AttachmentChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "attachment"; 51 | public byte[] Attachment { get; set; } 52 | public string DocUri { get; set; } 53 | public string Filename { get; set; } 54 | public TimeSpan? ElapsedTime { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/35 RAG with Azure AI Search/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | //builder.AddAppDefaults(); 24 | builder.AddServiceDefaults(); 25 | 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{builder.Configuration["CHAT_SERVER"]}")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/35 RAG with Azure AI Search/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/35 RAG with Azure AI Search/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /srcBU/35 RAG with Azure AI Search/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chat_winform 4 | { 5 | public partial class frmChat : Form 6 | { 7 | ChatApiClient _chatApiClient; 8 | private readonly ILogger _logger; 9 | 10 | string userName = @"Bruno"; 11 | ChatForm.ChatboxInfo cbi; 12 | 13 | public frmChat(ILogger logger, ChatApiClient chatApiClient) 14 | { 15 | _logger = logger; 16 | _chatApiClient = chatApiClient; 17 | InitializeComponent(); 18 | } 19 | 20 | private async void Form1_LoadAsync(object sender, EventArgs e) 21 | { 22 | // chat control 23 | cbi = new ChatForm.ChatboxInfo 24 | { 25 | MainTitlePlaceholder = "Adding AI to a Winforms Chat", 26 | SubtitlePlaceholder = "No LLM", 27 | User = userName 28 | }; 29 | toolStripTextBoxUserName.Text = userName; 30 | 31 | chatboxControl._chatApiClient = _chatApiClient; 32 | chatboxControl._logger = _logger; 33 | chatboxControl.SetChatBotInfo(cbi); 34 | 35 | // display chat server 36 | toolStripMenuItemShowServer.Text = $"Chat Server: {_chatApiClient.BaseAddress}"; 37 | } 38 | 39 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 40 | { 41 | userName = toolStripTextBoxUserName.Text; 42 | cbi.User = userName; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /srcBU/60 chat-server superhero api/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | 15 | var builder = WebApplication.CreateBuilder(args); 16 | 17 | // add telemetry 18 | builder.AddAppDefaults(); 19 | 20 | // Add services to the container. 21 | builder.Services.AddControllers(); 22 | builder.Services.AddEndpointsApiExplorer(); 23 | builder.Services.AddSwaggerGen(); 24 | 25 | builder.Services.AddLogging( 26 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 27 | ); 28 | 29 | builder.Services.AddSingleton(sp => 30 | { 31 | return builder.Configuration; 32 | }); 33 | 34 | builder.Services.AddSingleton(sp => 35 | { 36 | var chatHistory = new ChatHistory(); 37 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 38 | return chatHistory; 39 | }); 40 | 41 | builder.Services.AddSingleton(sp => 42 | { 43 | // add Azure OpenAI Chat Completion service 44 | var config = builder.Configuration; 45 | var chatDeploymentName = config["AZURE_OPENAI_MODEL"]; 46 | var endpoint = config["AZURE_OPENAI_ENDPOINT"]; 47 | var apiKey = config["AZURE_OPENAI_APIKEY"]; 48 | 49 | return new AzureOpenAIChatCompletionService(chatDeploymentName, endpoint, apiKey); 50 | }); 51 | 52 | builder.Services.AddSingleton(sp => 53 | { 54 | // new hero info 55 | var config = builder.Configuration; 56 | var heroInfo = new HeroInfo(config["SUPERHERO_APIKEY"]); 57 | 58 | // return a Semantic Kernel instance 59 | var builderSK = Kernel.CreateBuilder(); 60 | builderSK.Plugins.AddFromObject(heroInfo, "HeroInfo"); 61 | return builderSK.Build(); 62 | }); 63 | 64 | var app = builder.Build(); 65 | 66 | // Configure the HTTP request pipeline. 67 | if (app.Environment.IsDevelopment()) 68 | { 69 | app.UseSwagger(); 70 | app.UseSwaggerUI(); 71 | } 72 | 73 | app.UseHttpsRedirection(); 74 | 75 | app.UseAuthorization(); 76 | 77 | app.MapControllers(); 78 | 79 | app.Run(); 80 | -------------------------------------------------------------------------------- /srcBU/70 Aspire/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | builder.AddServiceDefaults(); 24 | 25 | var scheme = builder.Environment.IsDevelopment() ? "http" : "https"; 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{scheme}://chatapi")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /srcBU/70 Aspire/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CHAT_SERVER": "https+http://chatapi" 3 | } -------------------------------------------------------------------------------- /srcBU/80 Video Accident/AppHost/AppHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 2c6c8cc9-d757-49ad-a150-d8dc54fba6ba 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/AppHost/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = DistributedApplication.CreateBuilder(args); 2 | 3 | var chatapi = builder.AddProject("chatapi"); 4 | 5 | if (OperatingSystem.IsWindows()) 6 | { 7 | var chatform = builder.AddProject("chatform") 8 | .WithReference(chatapi) 9 | .ExcludeFromManifest(); ; 10 | } 11 | builder.Build().Run(); 12 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/AppHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "applicationUrl": "https://localhost:17095;http://localhost:15115", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development", 11 | "DOTNET_ENVIRONMENT": "Development", 12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21138", 13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22235" 14 | } 15 | }, 16 | "http": { 17 | "commandName": "Project", 18 | "dotnetRunMessages": true, 19 | "launchBrowser": true, 20 | "applicationUrl": "http://localhost:15115", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development", 23 | "DOTNET_ENVIRONMENT": "Development", 24 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19082", 25 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20033" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/AppHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/AppHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning", 6 | "Aspire.Hosting.Dcp": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/ServiceDefaults/ServiceDefaults.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public bool IsVideo { get; set; } 16 | public string ImageMimeType { get; set; } 17 | public byte[]? FileBytes { get; set; } 18 | public string UserName { get; set; } 19 | public string UserQuestion { get; set; } 20 | 21 | public override string ToString() 22 | { 23 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero. Get the real name of a super hero.")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | using Microsoft.SemanticKernel.Connectors.AzureOpenAI; 15 | 16 | var builder = WebApplication.CreateBuilder(args); 17 | 18 | builder.AddServiceDefaults(); 19 | 20 | // Add services to the container. 21 | builder.Services.AddControllers(); 22 | builder.Services.AddEndpointsApiExplorer(); 23 | builder.Services.AddSwaggerGen(); 24 | 25 | builder.Services.AddLogging( 26 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 27 | ); 28 | 29 | builder.Services.AddSingleton(sp => 30 | { 31 | return builder.Configuration; 32 | }); 33 | 34 | builder.Services.AddSingleton(sp => 35 | { 36 | // add Azure OpenAI Chat Completion service 37 | var config = builder.Configuration; 38 | var chatDeploymentName = config["AZURE_OPENAI_MODEL"]; 39 | var endpoint = config["AZURE_OPENAI_ENDPOINT"]; 40 | var apiKey = config["AZURE_OPENAI_APIKEY"]; 41 | // set author 42 | config["author"]= "Azure OpenAI - GPT-4o"; 43 | 44 | return new AzureOpenAIChatCompletionService(chatDeploymentName, endpoint, apiKey); 45 | }); 46 | 47 | builder.Services.AddSingleton(sp => 48 | { 49 | var chatHistory = new ChatHistory(); 50 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 51 | return chatHistory; 52 | }); 53 | 54 | var app = builder.Build(); 55 | 56 | app.MapDefaultEndpoints(); 57 | 58 | // Configure the HTTP request pipeline. 59 | if (app.Environment.IsDevelopment()) 60 | { 61 | app.UseSwagger(); 62 | app.UseSwaggerUI(); 63 | } 64 | 65 | app.UseHttpsRedirection(); 66 | 67 | app.UseAuthorization(); 68 | 69 | app.MapControllers(); 70 | 71 | app.Run(); 72 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/ChatAPI/ChatApiClient.cs: -------------------------------------------------------------------------------- 1 | using chat_models; 2 | using System.Net.Http; 3 | using System.Net.Http.Json; 4 | 5 | namespace chat_winform; 6 | 7 | public class ChatApiClient(HttpClient httpClient) 8 | { 9 | public async Task CallApiChat(Question question, CancellationToken cancellationToken = default) 10 | { 11 | 12 | var responseLocal = new Response(); 13 | var httpResponse = await httpClient.PostAsJsonAsync("api/chat", question, cancellationToken: cancellationToken); 14 | if (httpResponse.IsSuccessStatusCode) 15 | { 16 | responseLocal = await httpResponse.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); 17 | } 18 | return responseLocal; 19 | } 20 | 21 | public string BaseAddress => httpClient.BaseAddress.ToString(); 22 | 23 | public HttpClient HttpClient => httpClient; 24 | } -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class VideoChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "video"; 51 | public byte[] Video { get; set; } 52 | public Image FirstFrame { get; set; } 53 | public string VideoName { get; set; } 54 | public string VideoUri { get; set; } 55 | public TimeSpan? ElapsedTime { get; set; } 56 | } 57 | 58 | public class AttachmentChatModel : IChatModel 59 | { 60 | public bool Inbound { get; set; } 61 | public bool Read { get; set; } 62 | public DateTime Time { get; set; } 63 | public string Author { get; set; } 64 | public string Type { get; } = "attachment"; 65 | public byte[] Attachment { get; set; } 66 | public string DocUri { get; set; } 67 | public string Filename { get; set; } 68 | public TimeSpan? ElapsedTime { get; set; } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/80 Video Accident/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | //builder.AddAppDefaults(); 24 | builder.AddServiceDefaults(); 25 | 26 | builder.Services.AddHttpClient( 27 | client => client.BaseAddress = new($"{builder.Configuration["CHAT_SERVER"]}")); 28 | var app = builder.Build(); 29 | 30 | Services = app.Services; 31 | app.Start(); 32 | 33 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 34 | Application.EnableVisualStyles(); 35 | Application.SetCompatibleTextRenderingDefault(false); 36 | ApplicationConfiguration.Initialize(); 37 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 38 | //Application.Run(new frmChat()); 39 | } 40 | 41 | public static IServiceProvider Services { get; private set; } = default!; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/80 Video Accident/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcBU/80 Video Accident/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /srcBU/80 Video Accident/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chat_winform 4 | { 5 | public partial class frmChat : Form 6 | { 7 | ChatApiClient _chatApiClient; 8 | private readonly ILogger _logger; 9 | 10 | string userName = @"Bruno"; 11 | ChatForm.ChatboxInfo cbi; 12 | 13 | public frmChat(ILogger logger, ChatApiClient chatApiClient) 14 | { 15 | _logger = logger; 16 | _chatApiClient = chatApiClient; 17 | InitializeComponent(); 18 | } 19 | 20 | private async void Form1_LoadAsync(object sender, EventArgs e) 21 | { 22 | // chat control 23 | cbi = new ChatForm.ChatboxInfo 24 | { 25 | MainTitlePlaceholder = "Adding AI to a Winforms Chat", 26 | SubtitlePlaceholder = "No LLM", 27 | User = userName 28 | }; 29 | toolStripTextBoxUserName.Text = userName; 30 | 31 | chatboxControl._chatApiClient = _chatApiClient; 32 | chatboxControl._logger = _logger; 33 | chatboxControl.SetChatBotInfo(cbi); 34 | 35 | // display chat server 36 | toolStripMenuItemShowServer.Text = $"Chat Server: {_chatApiClient.BaseAddress}"; 37 | } 38 | 39 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 40 | { 41 | userName = toolStripTextBoxUserName.Text; 42 | cbi.User = userName; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/ClientAppsIntegration.AppDefaults/AppDefatultsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using OpenTelemetry; 5 | using OpenTelemetry.Logs; 6 | using OpenTelemetry.Metrics; 7 | using OpenTelemetry.Trace; 8 | 9 | namespace Microsoft.Extensions.Hosting; 10 | 11 | public static class AppDefaultsExtensions 12 | { 13 | public static IHostApplicationBuilder AddAppDefaults(this IHostApplicationBuilder builder) 14 | { 15 | builder.ConfigureAppOpenTelemetry(); 16 | 17 | builder.Services.AddServiceDiscovery(); 18 | 19 | builder.Services.ConfigureHttpClientDefaults(http => 20 | { 21 | // Turn on resilience by default 22 | http.AddStandardResilienceHandler(); 23 | 24 | // Turn on service discovery by default 25 | http.AddServiceDiscovery(); 26 | }); 27 | 28 | return builder; 29 | } 30 | 31 | public static IHostApplicationBuilder ConfigureAppOpenTelemetry(this IHostApplicationBuilder builder) 32 | { 33 | builder.Logging.AddOpenTelemetry(logging => 34 | { 35 | logging.IncludeFormattedMessage = true; 36 | logging.IncludeScopes = true; 37 | }); 38 | 39 | builder.Services.AddOpenTelemetry() 40 | .WithMetrics(metrics => 41 | { 42 | metrics.AddHttpClientInstrumentation() 43 | .AddRuntimeInstrumentation(); 44 | }) 45 | .WithTracing(tracing => 46 | { 47 | tracing.AddHttpClientInstrumentation(); 48 | }); 49 | 50 | builder.AddOpenTelemetryExporters(); 51 | 52 | return builder; 53 | } 54 | 55 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) 56 | { 57 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); 58 | 59 | if (useOtlpExporter) 60 | { 61 | builder.Services.AddOpenTelemetry().UseOtlpExporter(); 62 | } 63 | 64 | return builder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/ClientAppsIntegration.AppDefaults/ClientAppsIntegration.AppDefaults.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net8.0 6 | enable 7 | enable 8 | a89c6d5f-24a4-4f2b-aa20-1b8c6b460e50 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/SemanticKernel.Connectors.OnnxRuntimeGenAI/Connectors.OnnxRuntimeGenAI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI 5 | $(AssemblyName) 6 | netstandard2.1 7 | enable 8 | 10 9 | Debug;Release;Debug_Cuda;Release_Cuda;Debug_DirectML;Release_DirectML; 10 | 11 | 12 | 13 | 14 | Semantic Kernel-Microsoft.ML.OnnxRuntimeGenAI connectors 15 | Semantic Kernel connector for Microsoft.ML.OnnxRuntimeGenAI. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/SemanticKernel.Connectors.OnnxRuntimeGenAI/Models/PromptBuilderResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models 6 | { 7 | internal class PromptBuilderResult 8 | { 9 | string _imagePath = ""; 10 | 11 | public string Prompt { get; set; } 12 | public bool ImageFound { get; set; } 13 | public string? ImagePath 14 | { 15 | get 16 | { 17 | 18 | if (Uri != null && Uri.IsFile) 19 | { 20 | _imagePath = Uri.LocalPath; 21 | } 22 | else if (Uri != null && Uri.IsWellFormedUriString(Uri.AbsoluteUri, UriKind.Absolute)) 23 | { 24 | // Check if the URI scheme is HTTP or HTTPS 25 | if (Uri.Scheme == Uri.UriSchemeHttp || Uri.Scheme == Uri.UriSchemeHttps) 26 | { 27 | // Additional validation for image file extensions 28 | string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; 29 | string fileExtension = Path.GetExtension(Uri.AbsoluteUri); 30 | 31 | if (imageExtensions.Any(ext => fileExtension.StartsWith(ext))) 32 | { 33 | string tempFilePath = Path.GetTempFileName(); 34 | using (var client = new System.Net.WebClient()) 35 | { 36 | client.DownloadFile(Uri.AbsoluteUri, tempFilePath); 37 | } 38 | _imagePath = tempFilePath; 39 | } 40 | } 41 | } 42 | else if (string.IsNullOrEmpty(_imagePath) && ImageBytes != null && ImageBytes.Length > 0) 43 | { 44 | _imagePath = Path.GetTempFileName(); 45 | if (File.Exists(_imagePath)) 46 | { 47 | File.Delete(_imagePath); 48 | } 49 | File.WriteAllBytes(_imagePath, ImageBytes ?? new byte[0]); 50 | } 51 | return _imagePath; 52 | } 53 | set 54 | { 55 | _imagePath = value; 56 | } 57 | } 58 | public byte[]? ImageBytes { get; internal set; } 59 | public Uri? Uri { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using System.Net.Http; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.SemanticKernel.ChatCompletion; 8 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 9 | using Microsoft.SemanticKernel.Embeddings; 10 | using Microsoft.SemanticKernel.Http; 11 | using Microsoft.SemanticKernel.TextGeneration; 12 | 13 | namespace Microsoft.SemanticKernel; 14 | 15 | /// 16 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 17 | /// 18 | public static class OnnxRuntimeGenAIKernelBuilderExtensions 19 | { 20 | /// 21 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder. 22 | /// 23 | /// The kernel builder. 24 | /// The generative AI ONNX model path. 25 | /// The optional service ID. 26 | /// The updated kernel builder. 27 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion( 28 | this IKernelBuilder builder, 29 | string modelPath, 30 | string? serviceId = null) 31 | { 32 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 33 | new OnnxRuntimeGenAIChatCompletionService( 34 | modelPath: modelPath, 35 | loggerFactory: serviceProvider.GetService())); 36 | 37 | return builder; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | using System; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.SemanticKernel.ChatCompletion; 7 | using feiyun0112.SemanticKernel.Connectors.OnnxRuntimeGenAI; 8 | using Microsoft.SemanticKernel.Embeddings; 9 | using Microsoft.SemanticKernel.Http; 10 | using Microsoft.SemanticKernel.TextGeneration; 11 | 12 | namespace Microsoft.SemanticKernel; 13 | 14 | /// 15 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder. 16 | /// 17 | public static class OnnxRuntimeGenAIServiceCollectionExtensions 18 | { 19 | /// 20 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection. 21 | /// 22 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to. 23 | /// The generative AI ONNX model path. 24 | /// Optional service ID. 25 | /// The updated service collection. 26 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion( 27 | this IServiceCollection services, 28 | string modelPath, 29 | string? serviceId = null) 30 | { 31 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) => 32 | new OnnxRuntimeGenAIChatCompletionService( 33 | modelPath, 34 | loggerFactory: serviceProvider.GetService())); 35 | 36 | return services; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-models/Citation.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Citation 4 | { 5 | public string Title { get; set; } 6 | public string URL { get; set; } 7 | public string FilePath { get; set; } 8 | public string Content { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-models/Question.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Question 4 | { 5 | public Question() 6 | { 7 | IsImage= false; 8 | UserName = "not defined"; 9 | UserQuestion = "not defined"; 10 | ImageMimeType = "not defined"; 11 | FileBytes = null; 12 | } 13 | 14 | public bool IsImage { get; set; } 15 | public string ImageMimeType { get; set; } 16 | public byte[]? FileBytes { get; set; } 17 | public string UserName { get; set; } 18 | public string UserQuestion { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"User: {UserName}, Question: {UserQuestion}, HasImage: {IsImage}, Mime Type: {ImageMimeType}"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-models/Response.cs: -------------------------------------------------------------------------------- 1 | namespace chat_models; 2 | 3 | public class Response 4 | { 5 | // contructor that initialize the properties with default values 6 | public Response() 7 | { 8 | Author = "not defined"; 9 | QuestionResponse = "not defined"; 10 | } 11 | 12 | public string Author { get; set; } 13 | public string QuestionResponse { get; set; } 14 | public TimeSpan ElapsedTime { get; set; } 15 | public bool FromCache { get; set; } 16 | 17 | public List? Citations { get; set; } 18 | 19 | public override string ToString() 20 | { 21 | return $"Author: {Author}, QuestionResponse: {QuestionResponse}, ElapsedTime: {ElapsedTime}, FromCache: {FromCache}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-models/chat-models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | chat_models 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/NativeFunctions/HeroInfo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.SemanticKernel; 3 | using Newtonsoft.Json.Linq; 4 | 5 | public class HeroInfo 6 | { 7 | static string apiKey; 8 | public HeroInfo(string superHeroApiKey) 9 | { 10 | apiKey = superHeroApiKey; 11 | } 12 | 13 | [KernelFunction, Description("Get the alter ego of a superhero")] 14 | public static string GetAlterEgo(string input) 15 | { 16 | // Call the API 17 | var httpClient = new HttpClient(); 18 | var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; 19 | 20 | // Get the response 21 | var responseContent = response.Content.ReadAsStringAsync().Result; 22 | 23 | // Parse the response 24 | var json = JObject.Parse(responseContent); 25 | 26 | // Get the hero info 27 | var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; 28 | 29 | // Return the hero info 30 | return heroInfo; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SKEXP0001 2 | #pragma warning disable SKEXP0010 3 | #pragma warning disable SKEXP0020 4 | #pragma warning disable SKEXP0027 5 | #pragma warning disable SKEXP0050 6 | 7 | using Microsoft.Build.Framework; 8 | using Microsoft.SemanticKernel; 9 | using Microsoft.SemanticKernel.ChatCompletion; 10 | using Microsoft.SemanticKernel.Connectors.OpenAI; 11 | using Microsoft.SemanticKernel.Memory; 12 | using Microsoft.SemanticKernel.Connectors.AzureAISearch; 13 | using OpenTelemetry.Logs; 14 | 15 | var builder = WebApplication.CreateBuilder(args); 16 | 17 | // add telemetry 18 | builder.AddAppDefaults(); 19 | 20 | // Add services to the container. 21 | builder.Services.AddControllers(); 22 | builder.Services.AddEndpointsApiExplorer(); 23 | builder.Services.AddSwaggerGen(); 24 | 25 | builder.Services.AddLogging( 26 | b => b.AddConsole().SetMinimumLevel(LogLevel.Trace) 27 | ); 28 | 29 | builder.Services.AddSingleton(sp => 30 | { 31 | return builder.Configuration; 32 | }); 33 | 34 | builder.Services.AddSingleton(sp => 35 | { 36 | var chatHistory = new ChatHistory(); 37 | chatHistory.AddSystemMessage("You are a usefull assistant. You always reply with a short and funny message. If you don't know an answer, you say 'I don't know that.'"); 38 | return chatHistory; 39 | }); 40 | 41 | builder.Services.AddSingleton(sp => 42 | { 43 | // add Azure OpenAI Chat Completion service 44 | var config = builder.Configuration; 45 | var chatDeploymentName = config["AZURE_OPENAI_MODEL"]; 46 | var endpoint = config["AZURE_OPENAI_ENDPOINT"]; 47 | var apiKey = config["AZURE_OPENAI_APIKEY"]; 48 | 49 | return new AzureOpenAIChatCompletionService(chatDeploymentName, endpoint, apiKey); 50 | }); 51 | 52 | builder.Services.AddSingleton(sp => 53 | { 54 | // new hero info 55 | var config = builder.Configuration; 56 | var heroInfo = new HeroInfo(config["SUPERHERO_APIKEY"]); 57 | 58 | // return a Semantic Kernel instance 59 | var builderSK = Kernel.CreateBuilder(); 60 | builderSK.Plugins.AddFromObject(heroInfo, "HeroInfo"); 61 | return builderSK.Build(); 62 | }); 63 | 64 | var app = builder.Build(); 65 | 66 | // Configure the HTTP request pipeline. 67 | if (app.Environment.IsDevelopment()) 68 | { 69 | app.UseSwagger(); 70 | app.UseSwaggerUI(); 71 | } 72 | 73 | app.UseHttpsRedirection(); 74 | 75 | app.UseAuthorization(); 76 | 77 | app.MapControllers(); 78 | 79 | app.Run(); 80 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:18796", 8 | "sslPort": 44369 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5259", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7075;http://localhost:5259", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-server/chat-server.http: -------------------------------------------------------------------------------- 1 | @chat_server_HostAddress = http://localhost:5259 2 | 3 | POST {{chat_server_HostAddress}}/chat/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/Azure/AzureBlobContainer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Identity; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Configuration; 4 | using System.IO; 5 | 6 | namespace chat_winform.Azure; 7 | 8 | internal class AzureBlobContainer 9 | { 10 | public static async Task UploadFileToAzureBlobWinformDocs(string docFileName, string docFullPath) 11 | { 12 | string uri = ""; 13 | var validExtensions = new[] { ".txt", ".pdf" }; 14 | var extension = Path.GetExtension(docFileName); 15 | if (validExtensions.Contains(extension)) 16 | { 17 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 18 | var containerName = config["AZURE_BLOB_CONTAINERNAME_DOCS"]; 19 | uri = await UploadFileToAzureBlob(containerName, docFileName, docFullPath); 20 | } 21 | return uri; 22 | } 23 | 24 | public static async Task UploadFileToAzureBlobWinformImages(string imageFileName, string imageFullPath) 25 | { 26 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 27 | var containerName = config["AZURE_BLOB_CONTAINERNAME_IMAGES"]; 28 | return await UploadFileToAzureBlob(containerName, imageFileName, imageFullPath); 29 | } 30 | 31 | public static async Task UploadFileToAzureBlob(string containerName, string fileName, string fileFullPath) 32 | { 33 | var config = new ConfigurationBuilder().AddUserSecrets().Build(); 34 | var azureBlobUri = config["AZURE_BLOB_URI"]; 35 | 36 | var blobServiceClient = new BlobServiceClient(new Uri(azureBlobUri), new DefaultAzureCredential()); 37 | var containerClient = blobServiceClient.GetBlobContainerClient(containerName); 38 | var blobClient = containerClient.GetBlobClient(fileName); 39 | Console.WriteLine($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); 40 | await blobClient.UploadAsync(fileFullPath, true); 41 | Console.WriteLine($"Uploading complete ...\n"); 42 | return blobClient.Uri.ToString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/ChatControls/ChatModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chat_winform.ChatForm 9 | { 10 | public interface IChatModel 11 | { 12 | bool Inbound { get; set; } 13 | bool Read { get; set; } 14 | DateTime Time { get; set; } 15 | string Author { get; set; } 16 | string Type { get; } 17 | TimeSpan? ElapsedTime { get; set; } 18 | } 19 | 20 | public class TextChatModel : IChatModel 21 | { 22 | public bool Inbound { get; set; } 23 | public bool Read { get; set; } 24 | public DateTime Time { get; set; } 25 | public string Author { get; set; } 26 | public string Type { get; } = "text"; 27 | public string Body { get; set; } 28 | public TimeSpan? ElapsedTime { get; set; } 29 | } 30 | 31 | public class ImageChatModel : IChatModel 32 | { 33 | public bool Inbound { get; set; } 34 | public bool Read { get; set; } 35 | public DateTime Time { get; set; } 36 | public string Author { get; set; } 37 | public string Type { get; } = "image"; 38 | public Image Image { get; set; } 39 | public string ImageName { get; set; } 40 | public string ImageUri { get; set; } 41 | public TimeSpan? ElapsedTime { get; set; } 42 | } 43 | 44 | public class AttachmentChatModel : IChatModel 45 | { 46 | public bool Inbound { get; set; } 47 | public bool Read { get; set; } 48 | public DateTime Time { get; set; } 49 | public string Author { get; set; } 50 | public string Type { get; } = "attachment"; 51 | public byte[] Attachment { get; set; } 52 | public string DocUri { get; set; } 53 | public string Filename { get; set; } 54 | public TimeSpan? ElapsedTime { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/ChatControls/ChatboxInfo.cs: -------------------------------------------------------------------------------- 1 | namespace chat_winform.ChatForm 2 | { 3 | public class ChatboxInfo 4 | { 5 | public string User { get; set; } 6 | public string MainTitlePlaceholder { get; set; } 7 | public string SubtitlePlaceholder { get; set; } 8 | public string ChatPlaceholder = "Please enter a message..."; 9 | public byte[] Attachment { get; set; } 10 | public string AttachmentName { get; set; } 11 | public string AttachmentFileName { get; set; } 12 | public string AttachmentType { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/ChatControls/fileattach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcCompleted/60 chat-server superhero api/chat-winform/ChatControls/fileattach.png -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net.Http; 8 | using System.Net.Http.Headers; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace chat_winform 13 | { 14 | static class Program 15 | { 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | static void Main() 21 | { 22 | var builder = Host.CreateApplicationBuilder(); 23 | builder.AddAppDefaults(); 24 | 25 | builder.Services.AddSingleton(sp => 26 | { 27 | var client = new HttpClient(); 28 | client.BaseAddress = new Uri(builder.Configuration["CHAT_SERVER"]); 29 | client.DefaultRequestHeaders.Accept.Clear(); 30 | client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 31 | return client; 32 | }); 33 | 34 | var app = builder.Build(); 35 | Services = app.Services; 36 | app.Start(); 37 | 38 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 39 | Application.EnableVisualStyles(); 40 | Application.SetCompatibleTextRenderingDefault(false); 41 | ApplicationConfiguration.Initialize(); 42 | Application.Run(ActivatorUtilities.CreateInstance(app.Services)); 43 | //Application.Run(new frmChat()); 44 | } 45 | 46 | public static IServiceProvider Services { get; private set; } = default!; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/Resources/Large_SK_Logo-300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcCompleted/60 chat-server superhero api/chat-winform/Resources/Large_SK_Logo-300x300.png -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", 3 | "CHAT_SERVER": "https://localhost:7075" 4 | } 5 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/chat-winform.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows8.0 6 | chat_winform 7 | true 8 | true 9 | f0ce84b4-bdc5-4452-8ea0-44a0f69ea165 10 | True 11 | enable 12 | dotnet-icon-256x256-ozvjws7o.ico 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | PreserveNewest 23 | true 24 | PreserveNewest 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | True 50 | True 51 | Resources.resx 52 | 53 | 54 | 55 | 56 | 57 | 58 | ResXFileCodeGenerator 59 | Resources.Designer.cs 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/dotnet-icon-256x256-ozvjws7o.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elbruno/ws-add-ai-to-net-apps/5fd03a598d08513c48c907e9be9a56139318ee6d/srcCompleted/60 chat-server superhero api/chat-winform/dotnet-icon-256x256-ozvjws7o.ico -------------------------------------------------------------------------------- /srcCompleted/60 chat-server superhero api/chat-winform/frmChat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace chat_winform 8 | { 9 | public partial class frmChat : Form 10 | { 11 | HttpClient _client; 12 | private readonly ILogger _logger; 13 | 14 | string userName = @"Bruno"; 15 | ChatForm.ChatboxInfo cbi; 16 | 17 | public frmChat(ILogger logger, HttpClient client) 18 | { 19 | _logger = logger; 20 | _client = client; 21 | InitializeComponent(); 22 | } 23 | 24 | private async void Form1_LoadAsync(object sender, EventArgs e) 25 | { 26 | // chat control 27 | cbi = new ChatForm.ChatboxInfo(); 28 | cbi.MainTitlePlaceholder = "Adding AI to a Winforms Chat"; 29 | cbi.SubtitlePlaceholder = "No LLM"; 30 | cbi.User = userName; 31 | toolStripTextBoxUserName.Text = userName; 32 | 33 | chatboxControl._client = _client; 34 | chatboxControl._logger = _logger; 35 | chatboxControl.SetChatBotInfo(cbi); 36 | 37 | // display chat server 38 | toolStripMenuItemShowServer.Text = $"Chat Server: {_client.BaseAddress.ToString()}"; 39 | } 40 | 41 | private void toolStripMenuItemSetUserName_Click(object sender, EventArgs e) 42 | { 43 | userName = toolStripTextBoxUserName.Text; 44 | cbi.User = userName; 45 | } 46 | } 47 | } 48 | --------------------------------------------------------------------------------