├── .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 |
--------------------------------------------------------------------------------