├── img
├── 10DownloadOnnx.png
├── 20SampleConsole.gif
└── 30SampleVisionConsole.gif
├── src
├── LabsPhi303
│ ├── imgs
│ │ ├── foggyday.png
│ │ ├── petsmusic.png
│ │ └── ultrarunningmug.png
│ ├── LabsPhi303.csproj
│ └── Program.cs
├── LabsPhi304
│ ├── imgs
│ │ ├── foggyday.png
│ │ ├── petsmusic.png
│ │ ├── foggydaysmall.png
│ │ └── ultrarunningmug.png
│ ├── LabsPhi304.csproj
│ ├── SpectreConsoleOutput.cs
│ └── Program.cs
├── LabsPhi3_sk03
│ ├── imgs
│ │ ├── foggyday.png
│ │ ├── petsmusic.png
│ │ └── ultrarunningmug.png
│ ├── LabsPhi3_sk03.csproj
│ └── Program.cs
├── LabsPhi3_sk_azure02
│ ├── imgs
│ │ ├── foggyday.png
│ │ ├── petsmusic.png
│ │ ├── foggydaysmall.png
│ │ └── ultrarunningmug.png
│ ├── LabsPhi3_sk_azure02.csproj
│ └── Program.cs
├── LabsPhi3_sk02
│ ├── LabsPhi3_sk02.csproj
│ └── Program.cs
├── LabsPhi301
│ ├── LabsPhi301.csproj
│ └── Program.cs
├── LabsPhi401
│ ├── LabsPhi401.csproj
│ └── Program.cs
├── LabsPhi3_sk_azure01
│ ├── LabsPhi3_sk_azure01.csproj
│ └── Program.cs
├── LabsPhi3_sk_rag01
│ ├── LabsPhi3_sk_rag01.csproj
│ ├── SpectreConsoleOutput.cs
│ └── Program.cs
├── LabsPhi3_sk01
│ ├── LabsPhi3_sk01.csproj
│ └── Program.cs
├── LabsPhi3_sk_rag02
│ ├── LabsPhi3_sk_rag02.csproj
│ └── Program.cs
├── LabsPhi3_sk_rag03
│ ├── LabsPhi3_sk_rag03.csproj
│ ├── Program.cs
│ └── SpectreConsoleOutput.cs
├── SemanticKernel.Connectors.OnnxRuntimeGenAI
│ ├── OnnxRuntimeGenAIKernelBuilderExtensions.cs
│ ├── OnnxRuntimeGenAIServiceCollectionExtensions.cs
│ ├── Connectors.OnnxRuntimeGenAI.csproj
│ ├── Models
│ │ └── PromptBuilderResult.cs
│ ├── OnnxRuntimeGenAIPromptExecutionSettings.cs
│ └── Services
│ │ └── OnnxRuntimeGenAIChatCompletionService.cs
└── LabsPhi3.sln
├── LICENSE
├── README.md
└── .gitignore
/img/10DownloadOnnx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/img/10DownloadOnnx.png
--------------------------------------------------------------------------------
/img/20SampleConsole.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/img/20SampleConsole.gif
--------------------------------------------------------------------------------
/img/30SampleVisionConsole.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/img/30SampleVisionConsole.gif
--------------------------------------------------------------------------------
/src/LabsPhi303/imgs/foggyday.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi303/imgs/foggyday.png
--------------------------------------------------------------------------------
/src/LabsPhi304/imgs/foggyday.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi304/imgs/foggyday.png
--------------------------------------------------------------------------------
/src/LabsPhi303/imgs/petsmusic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi303/imgs/petsmusic.png
--------------------------------------------------------------------------------
/src/LabsPhi304/imgs/petsmusic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi304/imgs/petsmusic.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk03/imgs/foggyday.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk03/imgs/foggyday.png
--------------------------------------------------------------------------------
/src/LabsPhi304/imgs/foggydaysmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi304/imgs/foggydaysmall.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk03/imgs/petsmusic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk03/imgs/petsmusic.png
--------------------------------------------------------------------------------
/src/LabsPhi303/imgs/ultrarunningmug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi303/imgs/ultrarunningmug.png
--------------------------------------------------------------------------------
/src/LabsPhi304/imgs/ultrarunningmug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi304/imgs/ultrarunningmug.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk03/imgs/ultrarunningmug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk03/imgs/ultrarunningmug.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/imgs/foggyday.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk_azure02/imgs/foggyday.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/imgs/petsmusic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk_azure02/imgs/petsmusic.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/imgs/foggydaysmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk_azure02/imgs/foggydaysmall.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/imgs/ultrarunningmug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elbruno/phi3-labs/HEAD/src/LabsPhi3_sk_azure02/imgs/ultrarunningmug.png
--------------------------------------------------------------------------------
/src/LabsPhi3_sk02/LabsPhi3_sk02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/LabsPhi301/LabsPhi301.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/LabsPhi401/LabsPhi401.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk03/LabsPhi3_sk03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure01/LabsPhi3_sk_azure01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | b53b47a3-4029-4c27-86f8-c96adca5337f
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag01/LabsPhi3_sk_rag01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk01/LabsPhi3_sk01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag02/LabsPhi3_sk_rag02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/LabsPhi303/LabsPhi303.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 | PreserveNewest
22 |
23 |
24 | Always
25 |
26 |
27 | PreserveNewest
28 |
29 |
30 | PreserveNewest
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag03/LabsPhi3_sk_rag03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure01/Program.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable SKEXP0010
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.SemanticKernel;
4 | using Microsoft.SemanticKernel.ChatCompletion;
5 |
6 | var config = new ConfigurationBuilder().AddUserSecrets().Build();
7 | var modelId = config["AZURE_AI_PHI3_MODEL"];
8 | var endPoint = config["AZURE_AI_PHI3_ENDPOINT"];
9 | var apiKey = config["AZURE_AI_PHI3_APIKEY"];
10 |
11 | // create kernel
12 | var builder = Kernel.CreateBuilder();
13 | builder.AddOpenAIChatCompletion(modelId, new Uri(endPoint), apiKey);
14 | var kernel = builder.Build();
15 |
16 | // create chat
17 | var chat = kernel.GetRequiredService();
18 | var history = new ChatHistory();
19 |
20 | // run chat
21 | while (true)
22 | {
23 | Console.Write("Q: ");
24 | var userQ = Console.ReadLine();
25 | if (string.IsNullOrEmpty(userQ))
26 | {
27 | break;
28 | }
29 | history.AddUserMessage(userQ);
30 |
31 | Console.Write($"Phi3: ");
32 | var response = "";
33 | var result = chat.GetStreamingChatMessageContentsAsync(history);
34 | await foreach (var message in result)
35 | {
36 | Console.Write(message.Content);
37 | response += message.Content;
38 | }
39 | history.AddAssistantMessage(response);
40 | Console.WriteLine("");
41 | }
42 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/LabsPhi3_sk_azure02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | PreserveNewest
21 |
22 |
23 | PreserveNewest
24 |
25 |
26 | PreserveNewest
27 |
28 |
29 | PreserveNewest
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Logging;
3 | using Microsoft.SemanticKernel.ChatCompletion;
4 | using philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI;
5 |
6 | namespace Microsoft.SemanticKernel;
7 |
8 | ///
9 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder.
10 | ///
11 | public static class OnnxRuntimeGenAIKernelBuilderExtensions
12 | {
13 | ///
14 | /// Add OnnxRuntimeGenAI Chat Completion services to the kernel builder.
15 | ///
16 | /// The kernel builder.
17 | /// The generative AI ONNX model path.
18 | /// The optional service ID.
19 | /// The updated kernel builder.
20 | public static IKernelBuilder AddOnnxRuntimeGenAIChatCompletion(
21 | this IKernelBuilder builder,
22 | string modelPath,
23 | string? serviceId = null)
24 | {
25 | builder.Services.AddKeyedSingleton(serviceId, (serviceProvider, _) =>
26 | new OnnxRuntimeGenAIChatCompletionService(
27 | modelPath: modelPath,
28 | loggerFactory: serviceProvider.GetService()));
29 |
30 | return builder;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Logging;
3 | using Microsoft.SemanticKernel.ChatCompletion;
4 | using philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI;
5 |
6 | namespace Microsoft.SemanticKernel;
7 |
8 | ///
9 | /// Extension methods for adding OnnxRuntimeGenAI Text Generation service to the kernel builder.
10 | ///
11 | public static class OnnxRuntimeGenAIServiceCollectionExtensions
12 | {
13 | ///
14 | /// Add OnnxRuntimeGenAI Chat Completion services to the specified service collection.
15 | ///
16 | /// The service collection to add the OnnxRuntimeGenAI Text Generation service to.
17 | /// The generative AI ONNX model path.
18 | /// Optional service ID.
19 | /// The updated service collection.
20 | public static IServiceCollection AddOnnxRuntimeGenAIChatCompletion(
21 | this IServiceCollection services,
22 | string modelPath,
23 | string? serviceId = null)
24 | {
25 | services.AddKeyedSingleton(serviceId, (serviceProvider, _) =>
26 | new OnnxRuntimeGenAIChatCompletionService(
27 | modelPath,
28 | loggerFactory: serviceProvider.GetService()));
29 |
30 | return services;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/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 |
26 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_azure02/Program.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable SKEXP0010
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.SemanticKernel;
4 | using Microsoft.SemanticKernel.ChatCompletion;
5 |
6 | var config = new ConfigurationBuilder().AddUserSecrets().Build();
7 | var modelId = config["AZURE_AI_PHI3V_MODEL"];
8 | var endPoint = config["AZURE_AI_PHI3V_ENDPOINT"];
9 | var apiKey = config["AZURE_AI_PHI3V_APIKEY"];
10 |
11 | // create kernel
12 | var builder = Kernel.CreateBuilder();
13 | builder.AddOpenAIChatCompletion(modelId, new Uri(endPoint), apiKey);
14 | var kernel = builder.Build();
15 |
16 | // create chat
17 | var chat = kernel.GetRequiredService();
18 | var history = new ChatHistory();
19 |
20 | var petsMusicImagePath = Path.Combine(Directory.GetCurrentDirectory(), "imgs", "petsmusic.png");
21 |
22 | // get the mime type from the image
23 | var mimeType = "image/png";
24 |
25 | // create chat collection items
26 | var collectionItems = new ChatMessageContentItemCollection
27 | {
28 | new TextContent("What's in the image?"),
29 | //new ImageContent( new Uri(petsMusicImagePath))
30 | //new ImageContent( new Uri("https://github.com/elbruno/gpt4o-labs-csharp/tree/main/src/GPT4o_AOAI_lab02/imgs/foggyday.png?raw=true"))
31 | new ImageContent(File.ReadAllBytes(petsMusicImagePath), mimeType)
32 | };
33 | history.AddUserMessage(collectionItems);
34 |
35 | Console.Write($"Phi3: ");
36 | var result = await chat.GetChatMessageContentsAsync(history);
37 | Console.WriteLine(result[^1].Content);
38 |
39 | Console.WriteLine("");
40 |
--------------------------------------------------------------------------------
/src/LabsPhi304/LabsPhi304.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | PreserveNewest
26 |
27 |
28 | PreserveNewest
29 |
30 |
31 | PreserveNewest
32 |
33 |
34 | PreserveNewest
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 | PreserveNewest
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk01/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using Microsoft.SemanticKernel;
26 | using Microsoft.SemanticKernel.ChatCompletion;
27 |
28 | var modelPath = @"D:\phi3\models\Phi-3-mini-4k-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32";
29 |
30 | // create kernel
31 | var builder = Kernel.CreateBuilder();
32 | builder.AddOnnxRuntimeGenAIChatCompletion(modelPath: modelPath);
33 | var kernel = builder.Build();
34 |
35 | // create chat
36 | var chat = kernel.GetRequiredService();
37 | var history = new ChatHistory();
38 |
39 | // run chat
40 | while (true)
41 | {
42 | Console.Write("Q: ");
43 | var userQ = Console.ReadLine();
44 | if (string.IsNullOrEmpty(userQ))
45 | {
46 | break;
47 | }
48 | history.AddUserMessage(userQ);
49 |
50 | Console.Write($"Phi3: ");
51 | var response = "";
52 | var result = chat.GetStreamingChatMessageContentsAsync(history);
53 | await foreach (var message in result)
54 | {
55 | Console.Write(message.Content);
56 | response += message.Content;
57 | }
58 | history.AddAssistantMessage(response);
59 | Console.WriteLine("");
60 | }
61 |
--------------------------------------------------------------------------------
/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/LabsPhi3_sk02/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | #pragma warning disable SKEXP0010
26 |
27 | using Microsoft.SemanticKernel;
28 | using Microsoft.SemanticKernel.ChatCompletion;
29 |
30 | var modelPath = @"D:\phi3\models\Phi-3-mini-4k-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32";
31 |
32 | var model = "phi3";
33 | var endpoint = "https://localhost:14141";
34 | var apiKey = "apiKey";
35 |
36 |
37 | // create kernel
38 | var builder = Kernel.CreateBuilder();
39 | builder.AddOpenAIChatCompletion(model, new Uri(endpoint), apiKey);
40 | var kernel = builder.Build();
41 |
42 | // create chat
43 | var chat = kernel.GetRequiredService();
44 | var history = new ChatHistory();
45 | history.AddSystemMessage("You are a useful assistant. You always reply with a short and funny message using emojis. If you don't know an answer, you say 'I don't know that.' You only answers questions relates to math problems. For any other type of questions, explain the user that you only answer math problems questions.");
46 |
47 | // run chat
48 | while (true)
49 | {
50 | Console.Write("Q: ");
51 | var userQ = Console.ReadLine();
52 | if (string.IsNullOrEmpty(userQ))
53 | {
54 | break;
55 | }
56 | history.AddUserMessage(userQ);
57 |
58 | Console.Write($"Phi3: ");
59 | var response = "";
60 | var result = chat.GetStreamingChatMessageContentsAsync(history);
61 | await foreach (var message in result)
62 | {
63 | Console.Write(message.Content);
64 | response += message.Content;
65 | }
66 | history.AddAssistantMessage(response);
67 | Console.WriteLine("");
68 | }
69 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk03/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using Microsoft.ML.OnnxRuntimeGenAI;
26 | using Microsoft.SemanticKernel;
27 | using Microsoft.SemanticKernel.ChatCompletion;
28 |
29 | // path for model and images
30 | var modelPath = @"d:\phi3\models\Phi-3-vision-128k-instruct-onnx-cpu\cpu-int4-rtn-block-32-acc-level-4";
31 | //var modelPath = @"d:\phi3\models\Phi-3-vision-128k-instruct-onnx-cuda\cuda-fp16";
32 | //var modelPath = @"d:\phi3\models\Phi-3-vision-128k-instruct-onnx-cuda\cuda-int4-rtn-block-32-bruno";
33 |
34 | // create kernel
35 | var builder = Kernel.CreateBuilder();
36 | builder.AddOnnxRuntimeGenAIChatCompletion(modelPath: modelPath);
37 | var kernel = builder.Build();
38 |
39 | // create chat
40 | var chat = kernel.GetRequiredService();
41 | var history = new ChatHistory();
42 |
43 | var petsMusicImagePath = Path.Combine(Directory.GetCurrentDirectory(), "imgs", "petsmusic.png");
44 |
45 | // get the mime type from the image
46 | var mimeType = "image/png";
47 |
48 | // create chat collection items
49 | var collectionItems = new ChatMessageContentItemCollection
50 | {
51 | new TextContent("What's in the image?"),
52 | //new ImageContent( new Uri(petsMusicImagePath))
53 | //new ImageContent( new Uri("https://github.com/elbruno/gpt4o-labs-csharp/tree/main/src/GPT4o_AOAI_lab02/imgs/foggyday.png?raw=true"))
54 | new ImageContent(File.ReadAllBytes(petsMusicImagePath), mimeType)
55 | };
56 | history.AddUserMessage(collectionItems);
57 |
58 | Console.Write($"Phi3: ");
59 | var result = await chat.GetChatMessageContentsAsync(history);
60 | Console.WriteLine(result[^1].Content);
61 |
62 | Console.WriteLine("");
63 |
--------------------------------------------------------------------------------
/src/LabsPhi301/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using Microsoft.ML.OnnxRuntimeGenAI;
26 |
27 | var modelPath = @"C:\src\phi3\models\Phi-3-mini-4k-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32";
28 | var model = new Model(modelPath);
29 | var tokenizer = new Tokenizer(model);
30 |
31 | var systemPrompt = "You are an AI assistant that helps people find information. Answer questions using a direct style. Do not share more information that the requested by the users.";
32 |
33 | // chat start
34 | Console.WriteLine(@"Ask your question. Type an empty string to Exit.");
35 |
36 | // chat loop
37 | while (true)
38 | {
39 | // Get user question
40 | Console.WriteLine();
41 | Console.Write(@"Q: ");
42 | var userQ = Console.ReadLine();
43 | if (string.IsNullOrEmpty(userQ))
44 | {
45 | break;
46 | }
47 |
48 | // show phi3 response
49 | Console.Write("Phi3: ");
50 | var fullPrompt = $"<|system|>{systemPrompt}<|end|><|user|>{userQ}<|end|><|assistant|>";
51 | var tokens = tokenizer.Encode(fullPrompt);
52 |
53 | var generatorParams = new GeneratorParams(model);
54 | generatorParams.SetSearchOption("max_length", 2048);
55 | generatorParams.SetSearchOption("past_present_share_buffer", false);
56 | generatorParams.SetInputSequences(tokens);
57 |
58 | var generator = new Generator(model, generatorParams);
59 | while (!generator.IsDone())
60 | {
61 | generator.ComputeLogits();
62 | generator.GenerateNextToken();
63 | var outputTokens = generator.GetSequence(0);
64 | var newToken = outputTokens.Slice(outputTokens.Length - 1, 1);
65 | var output = tokenizer.Decode(newToken);
66 | Console.Write(output);
67 | }
68 | Console.WriteLine();
69 | }
70 |
--------------------------------------------------------------------------------
/src/LabsPhi303/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using Microsoft.ML.OnnxRuntime;
26 | using Microsoft.ML.OnnxRuntimeGenAI;
27 |
28 | // path for model and images
29 | var modelPath = @"d:\src\Phi3\models\Phi-3-vision-128k-instruct-onnx-cpu\cpu-int4-rtn-block-32-acc-level-4";
30 | //var modelPath = @"c:\src\Phi3\models\Phi-3-vision-128k-instruct-onnx-cuda\cuda-int4-rtn-block-32";
31 |
32 | var foggyDayImagePath = Path.Combine(Directory.GetCurrentDirectory(), "imgs", "foggyday.png");
33 | var petsMusicImagePath = Path.Combine(Directory.GetCurrentDirectory(), "imgs", "petsmusic.png");
34 | var img = Images.Load(petsMusicImagePath);
35 |
36 | // define prompts
37 | var systemPrompt = "You are an AI assistant that helps people find information. Answer questions using a direct style. Do not share more information that the requested by the users.";
38 | string userPrompt = "Describe the image, and return the string 'STOP' at the end.";
39 | var fullPrompt = $"<|system|>{systemPrompt}<|end|><|user|><|image_1|>{userPrompt}<|end|><|assistant|>";
40 |
41 | // load model and create processor
42 | using Model model = new Model(modelPath);
43 | using MultiModalProcessor processor = new MultiModalProcessor(model);
44 | using var tokenizerStream = processor.CreateStream();
45 |
46 | // create the input tensor with the prompt and image
47 | Console.WriteLine("Full Prompt: " + fullPrompt);
48 | Console.WriteLine("Start processing image and prompt ...");
49 | var inputTensors = processor.ProcessImages(fullPrompt, img);
50 | using GeneratorParams generatorParams = new GeneratorParams(model);
51 | generatorParams.SetSearchOption("max_length", 3072);
52 | generatorParams.SetInputs(inputTensors);
53 |
54 | // generate response
55 | Console.WriteLine("Generating response ...");
56 | using var generator = new Generator(model, generatorParams);
57 | while (!generator.IsDone())
58 | {
59 | generator.ComputeLogits();
60 | generator.GenerateNextToken();
61 | var seq = generator.GetSequence(0)[^1];
62 | Console.Write(tokenizerStream.Decode(seq));
63 | }
64 |
65 | Console.WriteLine("");
66 | Console.WriteLine("Done!");
--------------------------------------------------------------------------------
/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIPromptExecutionSettings.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 | using Microsoft.SemanticKernel;
3 |
4 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI;
5 |
6 | ///
7 | /// OnnxRuntimeGenAI Execution Settings.
8 | ///
9 | public sealed class OnnxRuntimeGenAIPromptExecutionSettings : PromptExecutionSettings
10 | {
11 | public static OnnxRuntimeGenAIPromptExecutionSettings FromExecutionSettings(PromptExecutionSettings? executionSettings)
12 | {
13 | switch (executionSettings)
14 | {
15 | case OnnxRuntimeGenAIPromptExecutionSettings settings:
16 | return settings;
17 | default:
18 | return new OnnxRuntimeGenAIPromptExecutionSettings();
19 | }
20 | }
21 |
22 | private int _topK = 50;
23 | private float _topP = 0.9f;
24 | private float _temperature = 1;
25 | private float _repetitionPenalty = 1;
26 | private bool _pastPresentShareBuffer = false;
27 | private int _numReturnSequences = 1;
28 | private int _numBeams = 1;
29 | private int _noRepeatNgramSize = 0;
30 | private int _minLength = 0;
31 | private int _maxLength = 200;
32 | private float _lengthPenalty = 1;
33 | private bool _earlyStopping = true;
34 | private bool _doSample = false;
35 | private float _diversityPenalty = 0;
36 |
37 | [JsonPropertyName("top_k")]
38 | public int TopK
39 | {
40 | get { return _topK; }
41 | set { _topK = value; }
42 | }
43 |
44 | [JsonPropertyName("top_p")]
45 | public float TopP
46 | {
47 | get { return _topP; }
48 | set { _topP = value; }
49 | }
50 |
51 | [JsonPropertyName("temperature")]
52 | public float Temperature
53 | {
54 | get { return _temperature; }
55 | set { _temperature = value; }
56 | }
57 |
58 | [JsonPropertyName("repetition_penalty")]
59 | public float RepetitionPenalty
60 | {
61 | get { return _repetitionPenalty; }
62 | set { _repetitionPenalty = value; }
63 | }
64 |
65 | [JsonPropertyName("past_present_share_buffer")]
66 | public bool PastPresentShareBuffer
67 | {
68 | get { return _pastPresentShareBuffer; }
69 | set { _pastPresentShareBuffer = value; }
70 | }
71 |
72 | [JsonPropertyName("num_return_sequences")]
73 | public int NumReturnSequences
74 | {
75 | get { return _numReturnSequences; }
76 | set { _numReturnSequences = value; }
77 | }
78 |
79 | [JsonPropertyName("num_beams")]
80 | public int NumBeams
81 | {
82 | get { return _numBeams; }
83 | set { _numBeams = value; }
84 | }
85 |
86 | [JsonPropertyName("no_repeat_ngram_size")]
87 | public int NoRepeatNgramSize
88 | {
89 | get { return _noRepeatNgramSize; }
90 | set { _noRepeatNgramSize = value; }
91 | }
92 |
93 | [JsonPropertyName("min_length")]
94 | public int MinLength
95 | {
96 | get { return _minLength; }
97 | set { _minLength = value; }
98 | }
99 |
100 | [JsonPropertyName("max_length")]
101 | public int MaxLength
102 | {
103 | get { return _maxLength; }
104 | set { _maxLength = value; }
105 | }
106 |
107 | [JsonPropertyName("length_penalty")]
108 | public float LengthPenalty
109 | {
110 | get { return _lengthPenalty; }
111 | set { _lengthPenalty = value; }
112 | }
113 |
114 | [JsonPropertyName("diversity_penalty")]
115 | public float DiversityPenalty
116 | {
117 | get { return _diversityPenalty; }
118 | set { _diversityPenalty = value; }
119 | }
120 |
121 | [JsonPropertyName("early_stopping")]
122 | public bool EarlyStopping
123 | {
124 | get { return _earlyStopping; }
125 | set { _earlyStopping = value; }
126 | }
127 |
128 | [JsonPropertyName("do_sample")]
129 | public bool DoSample
130 | {
131 | get { return _doSample; }
132 | set { _doSample = value; }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag03/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | // - Sample console application to use a local model hosted in ollama and semantic memory for search
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #pragma warning disable SKEXP0001, SKEXP0003, SKEXP0010, SKEXP0011, SKEXP0050, SKEXP0052, SKEXP0070
27 |
28 | using Microsoft.KernelMemory;
29 | using Microsoft.KernelMemory.AI.Ollama;
30 | using Microsoft.SemanticKernel;
31 |
32 | var ollamaEndpoint = "http://localhost:11434";
33 | var modelIdChat = "deepseek-r1";
34 | var modelIdEmbeddings = "all-minilm";
35 |
36 | // questions
37 | var questionEnglish = "What is Bruno's favourite super hero?";
38 | var questionSpanish = "Cual es el SuperHeroe favorito de Bruno?";
39 | var questionFrench = "Quel est le super-héros préféré de Bruno?";
40 | var question = questionEnglish;
41 |
42 | // intro
43 | SpectreConsoleOutput.DisplayTitle(modelIdChat);
44 | SpectreConsoleOutput.DisplayTitleH2($"This program will answer the following question:");
45 | SpectreConsoleOutput.DisplayTitleH2(question);
46 | SpectreConsoleOutput.DisplayTitleH3("1st approach will be to ask the question directly to the Phi-3 model.");
47 | SpectreConsoleOutput.DisplayTitleH3("2nd approach will be to add facts to a semantic memory and ask the question again");
48 | Console.WriteLine("");
49 |
50 | SpectreConsoleOutput.DisplayTitleH2($"{modelIdChat} response (no memory).");
51 |
52 | // Create a kernel with Azure OpenAI chat completion
53 | var builder = Kernel.CreateBuilder().AddOllamaChatCompletion(
54 | modelId: modelIdChat,
55 | endpoint: new Uri(ollamaEndpoint));
56 |
57 | Kernel kernel = builder.Build();
58 | var response = kernel.InvokePromptStreamingAsync(question);
59 | await foreach (var result in response)
60 | {
61 | SpectreConsoleOutput.WriteGreen(result.ToString());
62 | }
63 |
64 | // separator
65 | Console.WriteLine("");
66 | SpectreConsoleOutput.DisplaySeparator();
67 | Console.WriteLine("Press Enter to continue");
68 | Console.ReadLine();
69 | SpectreConsoleOutput.DisplayTitleH2($"{modelIdChat} response (using semantic memory).");
70 |
71 | var configOllamaKernelMemory = new OllamaConfig
72 | {
73 | Endpoint = ollamaEndpoint,
74 | TextModel = new OllamaModelConfig(modelIdChat),
75 | EmbeddingModel = new OllamaModelConfig(modelIdEmbeddings, 2048)
76 | };
77 |
78 | var memory = new KernelMemoryBuilder()
79 | .WithOllamaTextGeneration(configOllamaKernelMemory)
80 | .WithOllamaTextEmbeddingGeneration(configOllamaKernelMemory)
81 | .Build();
82 |
83 | await memory.ImportTextAsync("Gisela's favourite super hero is Batman");
84 | await memory.ImportTextAsync("The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3");
85 | await memory.ImportTextAsync("Bruno's favourite super hero is Invincible");
86 | await memory.ImportTextAsync("The last super hero movie watched by Bruno was Deadpool and Wolverine");
87 | await memory.ImportTextAsync("Bruno don't like the super hero movie: Eternals");
88 |
89 | var answer = memory.AskStreamingAsync(question);
90 | await foreach (var result in answer)
91 | {
92 | SpectreConsoleOutput.WriteGreen(result.ToString());
93 | }
94 |
95 | Console.WriteLine($"");
--------------------------------------------------------------------------------
/src/LabsPhi304/SpectreConsoleOutput.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | #pragma warning disable SKEXP0001, SKEXP0003, SKEXP0010, SKEXP0011, SKEXP0050, SKEXP0052
26 | using Spectre.Console;
27 |
28 | namespace LabsPhi304;
29 |
30 | public static class SpectreConsoleOutput
31 | {
32 | public static void DisplayTitle(string title = ".NET - Phi-3 Vision Sample")
33 | {
34 | AnsiConsole.Write(new FigletText(title).Centered().Color(Color.Purple));
35 | }
36 |
37 | public static void DisplayTitleH2(string subtitle)
38 | {
39 | AnsiConsole.MarkupLine($"[bold][blue]=== {subtitle} ===[/][/]");
40 | AnsiConsole.MarkupLine($"");
41 | }
42 |
43 | public static void DisplayTitleH3(string subtitle)
44 | {
45 | AnsiConsole.MarkupLine($"[bold]>> {subtitle}[/]");
46 | AnsiConsole.MarkupLine($"");
47 | }
48 |
49 | public static void DisplayQuestion(string question)
50 | {
51 | AnsiConsole.MarkupLine($"[bold][blue]>>Q: {question}[/][/]");
52 | AnsiConsole.MarkupLine($"");
53 | }
54 | public static void DisplayAnswerStart(string answerPrefix)
55 | {
56 | AnsiConsole.Markup($"[bold][blue]>> {answerPrefix}:[/][/]");
57 | }
58 |
59 | public static void DisplayFilePath(string prefix, string filePath)
60 | {
61 | var path = new TextPath(filePath);
62 |
63 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
64 | AnsiConsole.Write(path);
65 | AnsiConsole.MarkupLine($"");
66 | }
67 |
68 | public static void DisplaySubtitle(string prefix, string content)
69 | {
70 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
71 | AnsiConsole.WriteLine(content);
72 | AnsiConsole.MarkupLine($"");
73 | }
74 |
75 |
76 |
77 | public static int AskForNumber(string question)
78 | {
79 | var number = AnsiConsole.Ask(@$"[green]{question}[/]");
80 | return number;
81 | }
82 |
83 | public static string AskForString(string question)
84 | {
85 | var response = AnsiConsole.Ask(@$"[green]{question}[/]");
86 | return response;
87 | }
88 |
89 | public static List SelectScenarios()
90 | {
91 | // Ask for the user's favorite fruits
92 | var scenarios = AnsiConsole.Prompt(
93 | new MultiSelectionPrompt()
94 | .Title("Select the [green]Phi 3 Vision scenarios[/] to run?")
95 | .PageSize(10)
96 | .Required(true)
97 | .MoreChoicesText("[grey](Move up and down to reveal more scenarios)[/]")
98 | .InstructionsText(
99 | "[grey](Press [blue][/] to toggle a scenario, " +
100 | "[green][/] to accept)[/]")
101 | .AddChoiceGroup("Select an image to be analuyzed", new[]
102 | {"foggyday.png","foggydaysmall.png","petsmusic.png","ultrarunningmug.png",
103 | })
104 | .AddChoices( new[] {
105 | "Type the image path to be analyzed",
106 | "Type a question"
107 | })
108 | );
109 | return scenarios;
110 | }
111 | }
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag01/SpectreConsoleOutput.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | #pragma warning disable SKEXP0001, SKEXP0003, SKEXP0010, SKEXP0011, SKEXP0050, SKEXP0052
26 | using Spectre.Console;
27 |
28 | public static class SpectreConsoleOutput
29 | {
30 | public static void DisplayTitle(string modelId = "")
31 | {
32 | var title = $"{modelId} RAG";
33 |
34 | AnsiConsole.Write(new FigletText(title).Centered().Color(Color.Purple));
35 | }
36 |
37 | public static void DisplayTitleH2(string subtitle)
38 | {
39 | AnsiConsole.MarkupLine($"[bold][blue]=== {subtitle} ===[/][/]");
40 | AnsiConsole.MarkupLine($"");
41 | }
42 |
43 | public static void DisplayTitleH3(string subtitle)
44 | {
45 | AnsiConsole.MarkupLine($"[bold]>> {subtitle}[/]");
46 | AnsiConsole.MarkupLine($"");
47 | }
48 |
49 | public static void DisplaySeparator()
50 | {
51 | AnsiConsole.MarkupLine($"");
52 | AnsiConsole.MarkupLine($"[bold][blue]==============[/][/]");
53 | AnsiConsole.MarkupLine($"");
54 | }
55 |
56 | public static void WriteGreen(string message)
57 | {
58 | AnsiConsole.Markup($"[green]{message}[/]");
59 | }
60 |
61 | public static void DisplayQuestion(string question)
62 | {
63 | AnsiConsole.MarkupLine($"[bold][blue]>>Q: {question}[/][/]");
64 | AnsiConsole.MarkupLine($"");
65 | }
66 | public static void DisplayAnswerStart(string answerPrefix)
67 | {
68 | AnsiConsole.Markup($"[bold][blue]>> {answerPrefix}:[/][/]");
69 | }
70 |
71 | public static void DisplayFilePath(string prefix, string filePath)
72 | {
73 | var path = new TextPath(filePath);
74 |
75 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
76 | AnsiConsole.Write(path);
77 | AnsiConsole.MarkupLine($"");
78 | }
79 |
80 | public static void DisplaySubtitle(string prefix, string content)
81 | {
82 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
83 | AnsiConsole.WriteLine(content);
84 | AnsiConsole.MarkupLine($"");
85 | }
86 |
87 | public static int AskForNumber(string question)
88 | {
89 | var number = AnsiConsole.Ask(@$"[green]{question}[/]");
90 | return number;
91 | }
92 |
93 | public static string AskForString(string question)
94 | {
95 | var response = AnsiConsole.Ask(@$"[green]{question}[/]");
96 | return response;
97 | }
98 |
99 | public static List SelectScenarios()
100 | {
101 | // Ask for the user's favorite fruits
102 | var scenarios = AnsiConsole.Prompt(
103 | new MultiSelectionPrompt()
104 | .Title("Select the [green]Phi 3 Vision scenarios[/] to run?")
105 | .PageSize(10)
106 | .Required(true)
107 | .MoreChoicesText("[grey](Move up and down to reveal more scenarios)[/]")
108 | .InstructionsText(
109 | "[grey](Press [blue][/] to toggle a scenario, " +
110 | "[green][/] to accept)[/]")
111 | .AddChoiceGroup("Select an image to be analuyzed", new[]
112 | {"foggyday.png","foggydaysmall.png","petsmusic.png","ultrarunningmug.png",
113 | })
114 | .AddChoices( new[] {
115 | "Type the image path to be analyzed",
116 | "Type a question"
117 | })
118 | );
119 | return scenarios;
120 | }
121 | }
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag03/SpectreConsoleOutput.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | #pragma warning disable SKEXP0001, SKEXP0003, SKEXP0010, SKEXP0011, SKEXP0050, SKEXP0052
26 | using Spectre.Console;
27 |
28 | public static class SpectreConsoleOutput
29 | {
30 | public static void DisplayTitle(string modelId = "")
31 | {
32 | var title = $"{modelId} RAG";
33 |
34 | AnsiConsole.Write(new FigletText(title).Centered().Color(Color.Purple));
35 | }
36 |
37 | public static void DisplayTitleH2(string subtitle)
38 | {
39 | AnsiConsole.MarkupLine($"[bold][blue]=== {subtitle} ===[/][/]");
40 | AnsiConsole.MarkupLine($"");
41 | }
42 |
43 | public static void DisplayTitleH3(string subtitle)
44 | {
45 | AnsiConsole.MarkupLine($"[bold]>> {subtitle}[/]");
46 | AnsiConsole.MarkupLine($"");
47 | }
48 |
49 | public static void DisplaySeparator()
50 | {
51 | AnsiConsole.MarkupLine($"");
52 | AnsiConsole.MarkupLine($"[bold][blue]==============[/][/]");
53 | AnsiConsole.MarkupLine($"");
54 | }
55 |
56 | public static void WriteGreen(string message)
57 | {
58 | try
59 | {
60 | AnsiConsole.Markup($"[green]{message}[/]");
61 | }
62 | catch
63 | {
64 | AnsiConsole.Write($"{message}");
65 | }
66 | }
67 |
68 | public static void DisplayQuestion(string question)
69 | {
70 | AnsiConsole.MarkupLine($"[bold][blue]>>Q: {question}[/][/]");
71 | AnsiConsole.MarkupLine($"");
72 | }
73 | public static void DisplayAnswerStart(string answerPrefix)
74 | {
75 | AnsiConsole.Markup($"[bold][blue]>> {answerPrefix}:[/][/]");
76 | }
77 |
78 | public static void DisplayFilePath(string prefix, string filePath)
79 | {
80 | var path = new TextPath(filePath);
81 |
82 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
83 | AnsiConsole.Write(path);
84 | AnsiConsole.MarkupLine($"");
85 | }
86 |
87 | public static void DisplaySubtitle(string prefix, string content)
88 | {
89 | AnsiConsole.Markup($"[bold][blue]>> {prefix}: [/][/]");
90 | AnsiConsole.WriteLine(content);
91 | AnsiConsole.MarkupLine($"");
92 | }
93 |
94 | public static int AskForNumber(string question)
95 | {
96 | var number = AnsiConsole.Ask(@$"[green]{question}[/]");
97 | return number;
98 | }
99 |
100 | public static string AskForString(string question)
101 | {
102 | var response = AnsiConsole.Ask(@$"[green]{question}[/]");
103 | return response;
104 | }
105 |
106 | public static List SelectScenarios()
107 | {
108 | // Ask for the user's favorite fruits
109 | var scenarios = AnsiConsole.Prompt(
110 | new MultiSelectionPrompt()
111 | .Title("Select the [green]Phi 3 Vision scenarios[/] to run?")
112 | .PageSize(10)
113 | .Required(true)
114 | .MoreChoicesText("[grey](Move up and down to reveal more scenarios)[/]")
115 | .InstructionsText(
116 | "[grey](Press [blue][/] to toggle a scenario, " +
117 | "[green][/] to accept)[/]")
118 | .AddChoiceGroup("Select an image to be analuyzed", new[]
119 | {"foggyday.png","foggydaysmall.png","petsmusic.png","ultrarunningmug.png",
120 | })
121 | .AddChoices( new[] {
122 | "Type the image path to be analyzed",
123 | "Type a question"
124 | })
125 | );
126 | return scenarios;
127 | }
128 | }
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag01/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | // - Sample console application to use a local model hosted in ollama and semantic memory for search
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #pragma warning disable SKEXP0001
27 | #pragma warning disable SKEXP0003
28 | #pragma warning disable SKEXP0010
29 | #pragma warning disable SKEXP0011
30 | #pragma warning disable SKEXP0050
31 | #pragma warning disable SKEXP0052
32 |
33 | using Microsoft.Extensions.DependencyInjection;
34 | using Microsoft.SemanticKernel;
35 | using Microsoft.SemanticKernel.Connectors.OpenAI;
36 | using Microsoft.SemanticKernel.Embeddings;
37 | using Microsoft.SemanticKernel.Memory;
38 | using Microsoft.SemanticKernel.Plugins.Memory;
39 |
40 | var modelId = "phi4";
41 |
42 | // questions
43 | var questionEnglish = "What is Bruno's favourite super hero?";
44 | var questionSpanish = "Cual es el SuperHeroe favorito de Bruno?";
45 | var questionFrench = "Quel est le super-héros préféré de Bruno?";
46 | var questionEnglish1 = "Who likes Batman?";
47 | var questionSpanish2 = "A quien le gusta Batman?";
48 | var question = questionEnglish;
49 |
50 | // intro
51 |
52 | SpectreConsoleOutput.DisplayTitle(modelId);
53 | SpectreConsoleOutput.DisplayTitleH2($"This program will answer the following question:");
54 | SpectreConsoleOutput.DisplayTitleH2(question);
55 | SpectreConsoleOutput.DisplayTitleH3("1st approach will be to ask the question directly to the Phi-3 model.");
56 | SpectreConsoleOutput.DisplayTitleH3("2nd approach will be to add facts to a semantic memory and ask the question again");
57 | Console.WriteLine("");
58 |
59 | // Create a chat completion service
60 | var builder = Kernel.CreateBuilder();
61 | //builder.AddOnnxRuntimeGenAIChatCompletion(modelPath: modelPath);
62 | builder.AddOpenAIChatCompletion(
63 | modelId: modelId,
64 | endpoint: new Uri("http://localhost:11434"),
65 | apiKey: "");
66 | builder.AddLocalTextEmbeddingGeneration();
67 | Kernel kernel = builder.Build();
68 |
69 | SpectreConsoleOutput.DisplayTitleH2($"Phi-3 response (no memory).");
70 | var response = kernel.InvokePromptStreamingAsync(question);
71 | await foreach (var result in response)
72 | {
73 | SpectreConsoleOutput.WriteGreen(result.ToString());
74 | }
75 |
76 | // separator
77 | Console.WriteLine("");
78 | SpectreConsoleOutput.DisplaySeparator();
79 | Console.WriteLine("Press Enter to continue");
80 | Console.ReadLine();
81 | SpectreConsoleOutput.DisplayTitleH2($"Phi-4 response (using semantic memory).");
82 |
83 | // get the embeddings generator service
84 | var embeddingGenerator = kernel.Services.GetRequiredService();
85 | var memory = new SemanticTextMemory(new VolatileMemoryStore(), embeddingGenerator);
86 |
87 | // add facts to the collection
88 | const string MemoryCollectionName = "fanFacts";
89 |
90 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info1", text: "Gisela's favourite super hero is Batman");
91 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info2", text: "The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3");
92 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info3", text: "Bruno's favourite super hero is Invincible");
93 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info4", text: "The last super hero movie watched by Bruno was Deadpool and Wolverine");
94 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info5", text: "Bruno don't like the super hero movie: Eternals");
95 |
96 | TextMemoryPlugin memoryPlugin = new(memory);
97 |
98 | // Import the text memory plugin into the Kernel.
99 | kernel.ImportPluginFromObject(memoryPlugin);
100 |
101 | OpenAIPromptExecutionSettings settings = new()
102 | {
103 | ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
104 | };
105 |
106 | var prompt = @"Question: {{$input}}
107 | Answer the question using the memory content: {{Recall}}";
108 |
109 | var arguments = new KernelArguments(settings)
110 | {
111 | { "input", question },
112 | { "collection", MemoryCollectionName }
113 | };
114 |
115 | response = kernel.InvokePromptStreamingAsync(prompt, arguments);
116 | await foreach (var result in response)
117 | {
118 | SpectreConsoleOutput.WriteGreen(result.ToString());
119 | }
120 |
121 | Console.WriteLine($"");
--------------------------------------------------------------------------------
/src/LabsPhi401/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using Microsoft.ML.OnnxRuntimeGenAI;
26 | using System.Reflection.Emit;
27 | using System.Reflection;
28 | using Microsoft.ML.OnnxRuntime;
29 | using Microsoft.ML.OnnxRuntime.Tensors;
30 | using System.Diagnostics;
31 |
32 | //var modelPath = @"D:\phi3\models\Phi-3-mini-4k-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32";
33 | var modelPath = @"d:\phi3\models\Phi-3.5-mini-instruct-onnx\cpu_and_mobile\cpu-int4-awq-block-128-acc-level-4\phi-3.5-mini-instruct-cpu-int4-awq-block-128-acc-level-4.onnx";
34 | var session = new InferenceSession(modelPath);
35 |
36 | var systemPrompt = "You are an AI assistant that helps people find information. Answer questions using a direct style. Do not share more information that the requested by the users.";
37 |
38 | // chat start
39 | Console.WriteLine(@"Ask your question. Type an empty string to Exit.");
40 |
41 | // chat loop
42 | while (true)
43 | {
44 | // Get user question
45 | Console.WriteLine();
46 | Console.Write(@"Q: ");
47 | //var userQ = Console.ReadLine();
48 | var userQ = "2+2";
49 | if (string.IsNullOrEmpty(userQ))
50 | {
51 | break;
52 | }
53 |
54 | // show phi3 response
55 | Console.Write("Phi3: ");
56 |
57 |
58 | // create input tensor (nlp example)
59 | var inputOrtValue = OrtValue.CreateTensorWithEmptyStrings(OrtAllocator.DefaultInstance, new long[] { 1, 1 });
60 | inputOrtValue.StringTensorSetElementAt(userQ, 0);
61 |
62 | // Create input data for session. Request all outputs in this case.
63 | var inputs = new Dictionary
64 | {
65 | { "input", inputOrtValue }
66 | };
67 |
68 | var runOptions = new RunOptions();
69 |
70 | // We are getting a sequence of maps as output. We are interested in the first element (map) of the sequence.
71 | // That result is a Sequence of Maps, and we only need the first map from there.
72 | var outputs = session.Run(runOptions, inputs, session.OutputNames);
73 | Debug.Assert(outputs.Count > 0, "Expecting some output");
74 |
75 | // We want the last output, which is the sequence of maps
76 | var lastOutput = outputs[outputs.Count - 1];
77 |
78 | // Optional code to check the output type
79 | {
80 | var outputTypeInfo = lastOutput.GetTypeInfo();
81 | Debug.Assert(outputTypeInfo.OnnxType == OnnxValueType.ONNX_TYPE_SEQUENCE, "Expecting a sequence");
82 |
83 | var sequenceTypeInfo = outputTypeInfo.SequenceTypeInfo;
84 | Debug.Assert(sequenceTypeInfo.ElementType.OnnxType == OnnxValueType.ONNX_TYPE_MAP, "Expecting a sequence of maps");
85 | }
86 |
87 | var elementsNum = lastOutput.GetValueCount();
88 | Debug.Assert(elementsNum > 0, "Expecting a non empty sequence");
89 |
90 | // Get the first map in sequence
91 | var firstMap = lastOutput.GetValue(0, OrtAllocator.DefaultInstance);
92 |
93 | // Optional code just checking
94 | {
95 | // Maps always have two elements, keys and values
96 | // We are expecting this to be a map of strings to floats
97 | var mapTypeInfo = firstMap.GetTypeInfo().MapTypeInfo;
98 | Debug.Assert(mapTypeInfo.KeyType == TensorElementType.String, "Expecting keys to be strings");
99 | Debug.Assert(mapTypeInfo.ValueType.OnnxType == OnnxValueType.ONNX_TYPE_TENSOR, "Values are in the tensor");
100 | Debug.Assert(mapTypeInfo.ValueType.TensorTypeAndShapeInfo.ElementDataType == TensorElementType.Float, "Result map value is float");
101 | }
102 |
103 | var inferenceResult = new Dictionary();
104 | // Let use the visitor to read map keys and values
105 | // Here keys and values are represented with the same number of corresponding entries
106 | // string -> float
107 | firstMap.ProcessMap((keys, values) => {
108 | // Access native buffer directly
109 | var valuesSpan = values.GetTensorDataAsSpan();
110 |
111 | var entryCount = (int)keys.GetTensorTypeAndShape().ElementCount;
112 | inferenceResult.EnsureCapacity(entryCount);
113 | for (int i = 0; i < entryCount; ++i)
114 | {
115 | inferenceResult.Add(keys.GetStringElement(i), valuesSpan[i]);
116 | }
117 | }, OrtAllocator.DefaultInstance);
118 |
119 |
120 | Console.WriteLine(inferenceResult.Aggregate("", (current, next) => current + $"{next.Key} "));
121 |
122 | //// Return the inference result as json.
123 | //return new JsonResult(inferenceResult);
124 |
125 | Console.WriteLine();
126 | }
127 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Labs using Phi-3 and Phi-3-Vision
2 |
3 | [](/LICENSE)
4 | [](https://twitter.com/elbruno)
5 | 
6 |
7 | Welcome to the Phi-3 samples using C#. This repository contains a set of demo projects that showcases how to integrate the powerful different versions of Phi-3 models in a .NET environment.
8 |
9 | ## Prerequisites
10 |
11 | Before running the sample, ensure you have the following installed:
12 | - **.NET 8**: Make sure you have the latest version of .NET installed on your machine.
13 | - **(Optional) Visual Studio or Visual Studio Code**: You will need an IDE or code editor capable of running .NET projects. Visual Studio or Visual Studio Code are recommended.
14 | - Using git, clone locally one of the available Phi-3 versions from Hugging Face.
15 |
16 | - Download the **phi3-mini-4k-instruct-onnx** model to your local machine:
17 | ```bash
18 | # navigate to the folder to store the models
19 | cd c:\phi3\models
20 |
21 | # add support for lfs
22 | git lfs install
23 |
24 | # clone and download mini 4K instruct model
25 | git clone https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-onnx
26 |
27 | # clone and download vision 128K model
28 | git clone https://huggingface.co/microsoft/Phi-3-vision-128k-instruct-onnx-cpu
29 | ```
30 | ***Important:** The current demos are designed to use the ONNX versions of the model. The previous steps clone the following models.*
31 | 
32 |
33 | You can learn more about [Phi-3 in Hugging Face](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-onnx).
34 |
35 | ## About the Samples
36 |
37 | The main solution have several sample projects that demonstrates the capabilities of the Phi-3 models.
38 |
39 | ### Microsoft ML ONNX Runtime Samples
40 |
41 | | Project | Description | Location |
42 | | ------------ | ----------- | -------- |
43 | | LabsPhi301 | This is a sample project that uses a local phi3 model to ask a question. The project load a local ONNX Phi-3 model using the `Microsoft.ML.OnnxRuntime` libraries. | .\src\LabsPhi301\ |
44 | | LabsPhi303 | This is a sample project that uses a local phi3 vision model to analyze images.. The project load a local ONNX Phi-3 Vision model using the `Microsoft.ML.OnnxRuntime` libraries. | .\src\LabsPhi303\ |
45 | | LabsPhi304 | This is a sample project that uses a local phi3 vision model to analyze images.. The project load a local ONNX Phi-3 Vision model using the `Microsoft.ML.OnnxRuntime` libraries. The project also presents a menu with different options to interacti with the user. | .\src\LabsPhi304\ |
46 |
47 | ### Semantic Kernel Samples
48 |
49 | | Project | Description | Location |
50 | | ------------ | ----------- | -------- |
51 | | LabsPhi3_sk01 | This is a sample project that uses a local phi3 model to ask a question. The project uses Semantic Kernel and [SemanticKernel.Connectors.OnnxRuntimeGenAI](https://github.com/feiyun0112/SemanticKernel.Connectors.OnnxRuntimeGenAI) to load a local Phi-3 model and implement a console chat. | .\src\LabsPhi3_sk01\ |
52 | | LabsPhi3_sk02 | This is a sample project that uses a local phi3 model to ask a question. The project uses Semantic Kernel and a local copy of the source code and project [SemanticKernel.Connectors.OnnxRuntimeGenAI](/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs) to load a local Phi-3 model and implement a console chat. | .\src\LabsPhi3_sk02\ |
53 | | LabsPhi3_sk03 | The project uses Semantic Kernel and the local copy of the source code and project [SemanticKernel.Connectors.OnnxRuntimeGenAI](/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/OnnxRuntimeGenAIKernelBuilderExtensions.cs) to load a local Phi-3 Vision model and analyzes and describes an image. | .\src\LabsPhi3_sk03\ |
54 |
55 |
56 | ## How to Run the Projects
57 |
58 | To run the projects, follow these steps:
59 | 1. Clone the repository to your local machine.
60 |
61 | 1. Open a terminal and navigate to the desired project. In example, let's run `LabsPhi301`.
62 | ```bash
63 | cd .\src\LabsPhi301\
64 | ```
65 |
66 | 1. Run the project with the command
67 | ```bash
68 | dotnet run
69 | ```
70 |
71 | 1. The sample project ask for a user input and replies using the local mode.
72 |
73 | The running demo is similar to this one:
74 |
75 | 
76 |
77 | ***Note:** there is a typo in the 1st question, Phi-3 is cool enough to share the correct answer!*
78 |
79 | 1. The project `LabsPhi304` ask for the user to select different options, and then process the request. In example, analyzing a local image.
80 |
81 | The running demo is similar to this one:
82 |
83 | 
84 |
85 | ## References
86 |
87 | - [Semantic Kernel main repository](https://github.com/microsoft/semantic-kernel)
88 | - [SemanticKernel.Connectors.OnnxRuntimeGenAI repository by feiyun0112](https://github.com/feiyun0112/SemanticKernel.Connectors.OnnxRuntimeGenAI)
89 |
90 |
91 | ## Author
92 |
93 | 👤 **Bruno Capuano**
94 |
95 | * Website: https://elbruno.com
96 | * Twitter: [@elbruno](https://twitter.com/elbruno)
97 | * Github: [@elbruno](https://github.com/elbruno)
98 | * LinkedIn: [@elbruno](https://linkedin.com/in/elbruno)
99 |
100 | ## 🤝 Contributing
101 |
102 | Contributions, issues and feature requests are welcome!
103 |
104 | Feel free to check [issues page](https://github.com/elbruno/phi3-labs//issues).
105 |
106 | ## Show your support
107 |
108 | Give a ⭐️ if this project helped you!
109 |
110 |
111 | ## 📝 License
112 |
113 | Copyright © 2024 [Bruno Capuano](https://github.com/elbruno).
114 |
115 | This project is [MIT](/LICENSE) licensed.
116 |
117 | ***
118 |
--------------------------------------------------------------------------------
/src/LabsPhi3_sk_rag02/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | // - Sample console application to use a local model hosted in ollama and semantic memory for search
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #pragma warning disable SKEXP0001
27 | #pragma warning disable SKEXP0003
28 | #pragma warning disable SKEXP0010
29 | #pragma warning disable SKEXP0011
30 | #pragma warning disable SKEXP0050
31 | #pragma warning disable SKEXP0052
32 |
33 | using Microsoft.Extensions.DependencyInjection;
34 | using Microsoft.SemanticKernel;
35 | using Microsoft.SemanticKernel.ChatCompletion;
36 | using Microsoft.SemanticKernel.Connectors.OpenAI;
37 | using Microsoft.SemanticKernel.Embeddings;
38 | using Microsoft.SemanticKernel.Memory;
39 | using Microsoft.SemanticKernel.Plugins.Memory;
40 | using SmartComponents.StaticAssets.Inference;
41 |
42 | // system message
43 | var systemMessage = "You are a helpful assistant. You reply in short and precise answers, and you explain your responses. If you don't know an answer, you reply 'I don't know'";
44 |
45 | // questions
46 | var questionEnglish = "What is Bruno's favourite super hero?";
47 | var questionSpanish = "Cual es el SuperHeroe favorito de Bruno?";
48 | var questionFrench = "Quel est le super-héros préféré de Bruno?";
49 | var questionEnglish1 = "Who likes Batman?";
50 | var questionSpanish2 = "A quien le gusta Batman?";
51 | var question = questionSpanish2;
52 |
53 | // intro
54 | SpectreConsoleOutput.DisplayTitle();
55 | SpectreConsoleOutput.DisplayTitleH2($"This program will answer the following question:");
56 | SpectreConsoleOutput.DisplayTitleH2(question);
57 | SpectreConsoleOutput.DisplayTitleH3("1st approach will be to ask the question directly to the Phi-3 model.");
58 | SpectreConsoleOutput.DisplayTitleH3("2nd approach will be to add facts to a semantic memory and ask the question again");
59 | Console.WriteLine("");
60 |
61 | //var modelPath = @"D:\phi3\models\Phi-3-mini-4k-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32";
62 | var modelPath = @"d:\phi3\models\Phi-3.5-mini-instruct-onnx-web";
63 |
64 | // Create a chat completion service
65 | var builder = Kernel.CreateBuilder();
66 | //builder.AddOnnxRuntimeGenAIChatCompletion(modelPath: modelPath);
67 | builder.AddOpenAIChatCompletion(
68 | modelId: "phi3.5",
69 | endpoint: new Uri("http://localhost:11434"),
70 | apiKey: "apikey");
71 | builder.AddLocalTextEmbeddingGeneration();
72 | Kernel kernel = builder.Build();
73 | var chat = kernel.GetRequiredService();
74 |
75 | // no memory
76 | SpectreConsoleOutput.DisplayTitleH2($"Phi-3 response (no memory).");
77 | var history = new ChatHistory();
78 | history.AddSystemMessage(systemMessage);
79 |
80 | //history.AddUserMessage(question);
81 | //var response = chat.GetStreamingChatMessageContentsAsync(history);
82 | //await foreach (var result in response)
83 | //{
84 | // SpectreConsoleOutput.WriteGreen(result.ToString());
85 | //}
86 |
87 | // separator
88 | Console.WriteLine("");
89 | SpectreConsoleOutput.DisplaySeparator();
90 | Console.WriteLine("Press Enter to continue");
91 | Console.ReadLine();
92 | SpectreConsoleOutput.DisplayTitleH2($"Phi-3 response (using semantic memory).");
93 |
94 | // Using memory
95 | history = new ChatHistory();
96 | history.AddSystemMessage(systemMessage);
97 |
98 | // get the embeddings generator service
99 | var embeddingGenerator = kernel.Services.GetRequiredService();
100 | var memory = new SemanticTextMemory(new VolatileMemoryStore(), embeddingGenerator);
101 |
102 | // add facts to the collection
103 | const string MemoryCollectionName = "fanFacts";
104 |
105 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info1", text: "Gisela's favourite super hero is Batman");
106 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info2", text: "The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3");
107 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info3", text: "Bruno's favourite super hero is Invincible");
108 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info4", text: "The last super hero movie watched by Bruno was Deadpool and Wolverine");
109 | await memory.SaveInformationAsync(MemoryCollectionName, id: "info5", text: "Bruno don't like the super hero movie: Eternals");
110 |
111 | TextMemoryPlugin memoryPlugin = new(memory);
112 |
113 | // Import the text memory plugin into the Kernel.
114 | kernel.ImportPluginFromObject(memoryPlugin);
115 |
116 | OpenAIPromptExecutionSettings settings = new()
117 | {
118 | ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
119 | };
120 |
121 | var prompt = @"Question: {{$input}}
122 | Answer the question using the memory content: {{Recall}}";
123 |
124 | history.AddUserMessage(prompt);
125 |
126 | var arguments = new KernelArguments(settings)
127 | {
128 | { "input", question },
129 | { "collection", MemoryCollectionName },
130 | { "messages", history }
131 | };
132 |
133 | var newResponse = kernel.InvokePromptStreamingAsync(prompt, arguments);
134 | await foreach (var result in newResponse)
135 | {
136 | SpectreConsoleOutput.WriteGreen(result.ToString());
137 | }
138 |
139 | Console.WriteLine($"");
--------------------------------------------------------------------------------
/src/LabsPhi304/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024
2 | // Author : Bruno Capuano
3 | // Change Log :
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 | //
14 | // The above copyright notice and this permission notice shall be included in
15 | // all copies or substantial portions of the Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | // THE SOFTWARE.
24 |
25 | using LabsPhi304;
26 | using Microsoft.ML.OnnxRuntimeGenAI;
27 | using Spectre.Console;
28 | using System.Text;
29 |
30 | // path for model and images
31 | var modelPath = @"d:\phi3\models\Phi-3-vision-128k-instruct-onnx-cpu\cpu-int4-rtn-block-32-acc-level-4";
32 |
33 | // write title
34 | SpectreConsoleOutput.DisplayTitle($".NET - Phi3v");
35 |
36 | // load model and create processor
37 | using Model model = new Model(modelPath);
38 | using MultiModalProcessor processor = new MultiModalProcessor(model);
39 | using var tokenizerStream = processor.CreateStream();
40 | var tokenizer = new Tokenizer(model);
41 |
42 | // define prompts
43 | var systemPrompt = "You are an AI assistant that helps people find information. Answer questions using a direct style. Do not share more information that the requested by the users.";
44 |
45 | // user choice scenarios
46 | var scenarios = SpectreConsoleOutput.SelectScenarios();
47 | var scenario = scenarios[0];
48 |
49 | // switch between the options for the selected scenario
50 | // options can be file names with extension equal to ".png" or ".jpg"
51 | // or the values "Type the image path to be analyzed" or "Type a question"
52 | switch (scenario)
53 | {
54 | case "foggyday.png":
55 | case "foggydaysmall.png":
56 | case "petsmusic.png":
57 | case "ultrarunningmug.png":
58 | var imagePath = Path.Combine(Directory.GetCurrentDirectory(), "imgs", scenario);
59 | AnalizeImage(imagePath);
60 | break;
61 | case "Type the image path to be analyzed":
62 | scenario = SpectreConsoleOutput.AskForString("Type the image path to be analyzed");
63 | AnalizeImage(scenario);
64 | break;
65 | case "Type a question":
66 | AnswerQuestion();
67 | break;
68 | }
69 | SpectreConsoleOutput.DisplayTitleH3("Done !");
70 |
71 | void AnswerQuestion()
72 | {
73 | var question = SpectreConsoleOutput.AskForString("Type a question");
74 | SpectreConsoleOutput.DisplayQuestion(question);
75 | SpectreConsoleOutput.DisplayAnswerStart("Phi-3");
76 |
77 | var fullPrompt = $"<|system|>{systemPrompt}<|end|><|user|>{question}<|end|><|assistant|>";
78 | var tokens = tokenizer.Encode(fullPrompt);
79 |
80 | var generatorParams = new GeneratorParams(model);
81 | generatorParams.SetSearchOption("max_length", 2048);
82 | generatorParams.SetSearchOption("past_present_share_buffer", false);
83 | generatorParams.SetInputSequences(tokens);
84 |
85 | var generator = new Generator(model, generatorParams);
86 | while (!generator.IsDone())
87 | {
88 | generator.ComputeLogits();
89 | generator.GenerateNextToken();
90 | var outputTokens = generator.GetSequence(0);
91 | var newToken = outputTokens.Slice(outputTokens.Length - 1, 1);
92 | var output = tokenizer.Decode(newToken);
93 | Console.Write(output);
94 | }
95 | Console.WriteLine();
96 | }
97 |
98 | void AnalizeImage(string imagePath)
99 | {
100 | // display text with the image path
101 | SpectreConsoleOutput.DisplayFilePath("Analizing image", imagePath);
102 |
103 | // Display the image thumbnail
104 | var image = new CanvasImage(imagePath);
105 | image.MaxWidth(16);
106 | AnsiConsole.Write(image);
107 |
108 | StringBuilder phiResponse = new StringBuilder();
109 |
110 | AnsiConsole.Status()
111 | .Start("Analyzing image ...", ctx =>
112 | {
113 | var img = Images.Load(imagePath);
114 | string userPrompt = "Describe the image, and return the string 'STOP' at the end.";
115 | var fullPrompt = $"<|system|>{systemPrompt}<|end|><|user|><|image_1|>{userPrompt}<|end|><|assistant|>";
116 |
117 | // create the input tensor with the prompt and image
118 | SpectreConsoleOutput.DisplaySubtitle("Full Prompt", fullPrompt);
119 |
120 | // Update the status and spinner
121 | ctx.Status("ONNX image processing ...");
122 | ctx.Spinner(Spinner.Known.Star);
123 | ctx.SpinnerStyle(Style.Parse("green"));
124 |
125 |
126 | var inputTensors = processor.ProcessImages(fullPrompt, img);
127 | using GeneratorParams generatorParams = new GeneratorParams(model);
128 | generatorParams.SetSearchOption("max_length", 3072);
129 | generatorParams.SetInputs(inputTensors);
130 |
131 | var isProcessingTokenStarted = false;
132 |
133 | // generate response
134 | using var generator = new Generator(model, generatorParams);
135 | while (!generator.IsDone())
136 | {
137 | generator.ComputeLogits();
138 | generator.GenerateNextToken();
139 |
140 | if (!isProcessingTokenStarted)
141 | {
142 | ctx.Status("Processing response tokens ...");
143 | ctx.Spinner(Spinner.Known.Dots12);
144 | ctx.SpinnerStyle(Style.Parse("blue"));
145 | isProcessingTokenStarted = true;
146 | }
147 |
148 | var seq = generator.GetSequence(0)[^1];
149 | var tokenString = tokenizerStream.Decode(seq);
150 | AnsiConsole.Markup($"[bold][blue]>> Token:[/][/] {tokenString}");
151 | phiResponse.Append(tokenString);
152 | }
153 | });
154 |
155 | // display the response
156 | SpectreConsoleOutput.DisplaySubtitle("Phi-3 Response", phiResponse.ToString());
157 | }
--------------------------------------------------------------------------------
/src/SemanticKernel.Connectors.OnnxRuntimeGenAI/Services/OnnxRuntimeGenAIChatCompletionService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using Microsoft.Extensions.Logging;
6 | using Microsoft.ML.OnnxRuntimeGenAI;
7 | using Microsoft.SemanticKernel;
8 | using Microsoft.SemanticKernel.ChatCompletion;
9 | using Microsoft.SemanticKernel.Services;
10 | using philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI.Models;
11 |
12 | namespace philabs.SemanticKernel.Connectors.OnnxRuntimeGenAI;
13 |
14 | ///
15 | /// Represents a chat completion service using OnnxRuntimeGenAI.
16 | ///
17 | public sealed class OnnxRuntimeGenAIChatCompletionService : IChatCompletionService
18 | {
19 | private readonly Model _model;
20 | private readonly Tokenizer _tokenizer;
21 | private readonly MultiModalProcessor _processor;
22 | private readonly TokenizerStream _tokenizerStream;
23 | private Dictionary AttributesInternal { get; } = new();
24 |
25 | ///
26 | /// Initializes a new instance of the OnnxRuntimeGenAIChatCompletionService class.
27 | ///
28 | /// The generative AI ONNX model path for the chat completion service.
29 | /// Optional logger factory to be used for logging.
30 | public OnnxRuntimeGenAIChatCompletionService(
31 | string modelPath,
32 | ILoggerFactory? loggerFactory = null)
33 | {
34 | _model = new Model(modelPath);
35 | _tokenizer = new Tokenizer(_model);
36 |
37 | if (modelPath.Contains("vision"))
38 | {
39 | _processor = new MultiModalProcessor(_model);
40 | _tokenizerStream = _processor.CreateStream();
41 | }
42 |
43 | this.AttributesInternal.Add(AIServiceExtensions.ModelIdKey, _tokenizer);
44 | }
45 |
46 | ///
47 | public IReadOnlyDictionary Attributes => this.AttributesInternal;
48 |
49 | ///
50 | public async Task> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
51 | {
52 | var result = new StringBuilder();
53 |
54 | await foreach (var content in RunInferenceAsync(chatHistory, executionSettings, cancellationToken))
55 | {
56 | result.Append(content);
57 | }
58 |
59 | return new List
60 | {
61 | new(
62 | role: AuthorRole.Assistant,
63 | content: result.ToString())
64 | };
65 | }
66 |
67 | ///
68 | public async IAsyncEnumerable GetStreamingChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
69 | {
70 | await foreach (var content in RunInferenceAsync(chatHistory, executionSettings, cancellationToken))
71 | {
72 | yield return new StreamingChatMessageContent(AuthorRole.Assistant, content);
73 | }
74 | }
75 |
76 | private async IAsyncEnumerable RunInferenceAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings, CancellationToken cancellationToken)
77 | {
78 | OnnxRuntimeGenAIPromptExecutionSettings onnxRuntimeGenAIPromptExecutionSettings = OnnxRuntimeGenAIPromptExecutionSettings.FromExecutionSettings(executionSettings);
79 |
80 | var promptResult = GetPrompt(chatHistory, onnxRuntimeGenAIPromptExecutionSettings);
81 |
82 | Generator generator;
83 |
84 | var generatorParams = new GeneratorParams(_model);
85 | ApplyPromptExecutionSettings(generatorParams, onnxRuntimeGenAIPromptExecutionSettings);
86 |
87 | if (!promptResult.ImageFound)
88 | {
89 | var tokens = _tokenizer.Encode(promptResult.Prompt);
90 | generatorParams.SetInputSequences(tokens);
91 | }
92 | else
93 | {
94 | var img = Images.Load(promptResult.ImagePath);
95 | var inputTensors = _processor.ProcessImages(promptResult.Prompt, img);
96 | generatorParams.SetSearchOption("max_length", 3072);
97 | generatorParams.SetInputs(inputTensors);
98 | }
99 |
100 | generator = new Generator(_model, generatorParams);
101 |
102 |
103 | if (generator is not null)
104 | while (!generator.IsDone())
105 | {
106 | cancellationToken.ThrowIfCancellationRequested();
107 |
108 | yield return await Task.Run(() =>
109 | {
110 | generator.ComputeLogits();
111 | generator.GenerateNextToken();
112 |
113 | var outputTokens = generator.GetSequence(0);
114 | var newToken = outputTokens.Slice(outputTokens.Length - 1, 1);
115 | var output = _tokenizer.Decode(newToken);
116 | return output;
117 | }, cancellationToken);
118 | }
119 |
120 | }
121 |
122 | private PromptBuilderResult GetPrompt(ChatHistory chatHistory, OnnxRuntimeGenAIPromptExecutionSettings onnxRuntimeGenAIPromptExecutionSettings)
123 | {
124 | var result = new PromptBuilderResult();
125 | var promptBuilder = new StringBuilder();
126 | foreach (var message in chatHistory)
127 | {
128 | promptBuilder.Append($"<|{message.Role}|>\n{message.Content}");
129 |
130 | // process sub items
131 | foreach (var item in message.Items)
132 | {
133 | if (item is ImageContent imageContent)
134 | {
135 | result.ImageFound = true;
136 | promptBuilder.Append($"<|image_1|>");
137 |
138 | var imageItem = item as ImageContent;
139 |
140 | if (imageItem?.Data != null)
141 | {
142 | result.ImageBytes = imageItem.Data.Value.ToArray();
143 | }
144 | else if (imageItem?.Uri != null)
145 | {
146 | result.Uri = imageItem.Uri;
147 | }
148 | break;
149 | }
150 | }
151 |
152 | }
153 | promptBuilder.Append($"<|end|>\n<|assistant|>");
154 |
155 | result.Prompt = promptBuilder.ToString();
156 |
157 | return result;
158 | }
159 |
160 | private void ApplyPromptExecutionSettings(GeneratorParams generatorParams, OnnxRuntimeGenAIPromptExecutionSettings onnxRuntimeGenAIPromptExecutionSettings)
161 | {
162 | generatorParams.SetSearchOption("top_p", onnxRuntimeGenAIPromptExecutionSettings.TopP);
163 | generatorParams.SetSearchOption("top_k", onnxRuntimeGenAIPromptExecutionSettings.TopK);
164 | generatorParams.SetSearchOption("temperature", onnxRuntimeGenAIPromptExecutionSettings.Temperature);
165 | generatorParams.SetSearchOption("repetition_penalty", onnxRuntimeGenAIPromptExecutionSettings.RepetitionPenalty);
166 | generatorParams.SetSearchOption("past_present_share_buffer", onnxRuntimeGenAIPromptExecutionSettings.PastPresentShareBuffer);
167 | generatorParams.SetSearchOption("num_return_sequences", onnxRuntimeGenAIPromptExecutionSettings.NumReturnSequences);
168 | generatorParams.SetSearchOption("no_repeat_ngram_size", onnxRuntimeGenAIPromptExecutionSettings.NoRepeatNgramSize);
169 | generatorParams.SetSearchOption("min_length", onnxRuntimeGenAIPromptExecutionSettings.MinLength);
170 | generatorParams.SetSearchOption("max_length", onnxRuntimeGenAIPromptExecutionSettings.MaxLength);
171 | generatorParams.SetSearchOption("length_penalty", onnxRuntimeGenAIPromptExecutionSettings.LengthPenalty);
172 | generatorParams.SetSearchOption("early_stopping", onnxRuntimeGenAIPromptExecutionSettings.EarlyStopping);
173 | generatorParams.SetSearchOption("do_sample", onnxRuntimeGenAIPromptExecutionSettings.DoSample);
174 | generatorParams.SetSearchOption("diversity_penalty", onnxRuntimeGenAIPromptExecutionSettings.DiversityPenalty);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
399 |
--------------------------------------------------------------------------------
/src/LabsPhi3.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.10.34928.147
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi301", "LabsPhi301\LabsPhi301.csproj", "{22131B1B-1289-41DF-882F-A2E16A63BE9E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk01", "LabsPhi3_sk01\LabsPhi3_sk01.csproj", "{1254AB34-B99A-4E4C-BD95-18BB22BF478E}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi304", "LabsPhi304\LabsPhi304.csproj", "{4EB2FBF6-75D3-4B10-B5B5-675469C24780}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.OnnxRuntimeGenAI", "SemanticKernel.Connectors.OnnxRuntimeGenAI\Connectors.OnnxRuntimeGenAI.csproj", "{52D662CC-407B-42E6-8446-BEF969FFD30B}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ONNX", "ONNX", "{0BC576AC-FDE1-4DF8-BABD-668DBE6E7C9C}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SK", "SK", "{255AD044-4A87-4975-B8EF-016F87277741}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi303", "LabsPhi303\LabsPhi303.csproj", "{ED480C58-4355-4430-950B-1D85D3AE9891}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk02", "LabsPhi3_sk02\LabsPhi3_sk02.csproj", "{2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk03", "LabsPhi3_sk03\LabsPhi3_sk03.csproj", "{C88880FD-67E0-4A72-BD29-005A8291DF7B}"
23 | EndProject
24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure AI", "Azure AI", "{EA6E5514-23BD-4B8B-A804-88AD5BF03E06}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk_azure01", "LabsPhi3_sk_azure01\LabsPhi3_sk_azure01.csproj", "{F9835E50-8AB8-4307-A70E-6DD63142CF50}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk_azure02", "LabsPhi3_sk_azure02\LabsPhi3_sk_azure02.csproj", "{84B45833-3D23-4095-ACDD-2C769A0E078C}"
29 | EndProject
30 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RAG", "RAG", "{57EDA879-FEC3-484B-B5A2-CC60B9BADE47}"
31 | EndProject
32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LabsPhi3_sk_rag01", "LabsPhi3_sk_rag01\LabsPhi3_sk_rag01.csproj", "{046B5598-8DA6-4E49-BBC0-B88620E4CA48}"
33 | EndProject
34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabsPhi3_sk_rag02", "LabsPhi3_sk_rag02\LabsPhi3_sk_rag02.csproj", "{813A9EBB-F3CF-434B-AAC6-3058CCF75632}"
35 | EndProject
36 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabsPhi401", "LabsPhi401\LabsPhi401.csproj", "{0E93E13A-4AC6-48EB-A146-474639B0F7A6}"
37 | EndProject
38 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabsPhi3_sk_rag03", "LabsPhi3_sk_rag03\LabsPhi3_sk_rag03.csproj", "{BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}"
39 | EndProject
40 | Global
41 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
42 | Debug_Cuda|Any CPU = Debug_Cuda|Any CPU
43 | Debug_DirectML|Any CPU = Debug_DirectML|Any CPU
44 | Debug|Any CPU = Debug|Any CPU
45 | Release_Cuda|Any CPU = Release_Cuda|Any CPU
46 | Release_DirectML|Any CPU = Release_DirectML|Any CPU
47 | Release|Any CPU = Release|Any CPU
48 | EndGlobalSection
49 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
50 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
51 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
52 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
53 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
54 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
57 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
58 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
59 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
60 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {22131B1B-1289-41DF-882F-A2E16A63BE9E}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
63 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
64 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
65 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
66 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Debug|Any CPU.Build.0 = Debug|Any CPU
68 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
69 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
70 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
71 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
72 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release|Any CPU.ActiveCfg = Release|Any CPU
73 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E}.Release|Any CPU.Build.0 = Release|Any CPU
74 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
75 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
76 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
77 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
78 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
79 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Debug|Any CPU.Build.0 = Debug|Any CPU
80 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
81 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
82 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
83 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
84 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release|Any CPU.ActiveCfg = Release|Any CPU
85 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780}.Release|Any CPU.Build.0 = Release|Any CPU
86 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug_Cuda|Any CPU.ActiveCfg = Debug_Cuda|Any CPU
87 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug_Cuda|Any CPU.Build.0 = Debug_Cuda|Any CPU
88 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug_DirectML|Any CPU.ActiveCfg = Debug_DirectML|Any CPU
89 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug_DirectML|Any CPU.Build.0 = Debug_DirectML|Any CPU
90 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
91 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Debug|Any CPU.Build.0 = Debug|Any CPU
92 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release_Cuda|Any CPU.ActiveCfg = Release_Cuda|Any CPU
93 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release_Cuda|Any CPU.Build.0 = Release_Cuda|Any CPU
94 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release_DirectML|Any CPU.ActiveCfg = Release_DirectML|Any CPU
95 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release_DirectML|Any CPU.Build.0 = Release_DirectML|Any CPU
96 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release|Any CPU.ActiveCfg = Release|Any CPU
97 | {52D662CC-407B-42E6-8446-BEF969FFD30B}.Release|Any CPU.Build.0 = Release|Any CPU
98 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
99 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
100 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
101 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
102 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
103 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Debug|Any CPU.Build.0 = Debug|Any CPU
104 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
105 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
106 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
107 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
108 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release|Any CPU.ActiveCfg = Release|Any CPU
109 | {ED480C58-4355-4430-950B-1D85D3AE9891}.Release|Any CPU.Build.0 = Release|Any CPU
110 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
111 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
112 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
113 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
114 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
115 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Debug|Any CPU.Build.0 = Debug|Any CPU
116 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
117 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
118 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
119 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
120 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release|Any CPU.ActiveCfg = Release|Any CPU
121 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858}.Release|Any CPU.Build.0 = Release|Any CPU
122 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
123 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
124 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
125 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
126 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
127 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
128 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
129 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
130 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
131 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
132 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
133 | {C88880FD-67E0-4A72-BD29-005A8291DF7B}.Release|Any CPU.Build.0 = Release|Any CPU
134 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
135 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
136 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
137 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
138 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
139 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Debug|Any CPU.Build.0 = Debug|Any CPU
140 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
141 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
142 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
143 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
144 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release|Any CPU.ActiveCfg = Release|Any CPU
145 | {F9835E50-8AB8-4307-A70E-6DD63142CF50}.Release|Any CPU.Build.0 = Release|Any CPU
146 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
147 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
148 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
149 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
150 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
151 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Debug|Any CPU.Build.0 = Debug|Any CPU
152 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
153 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
154 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
155 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
156 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release|Any CPU.ActiveCfg = Release|Any CPU
157 | {84B45833-3D23-4095-ACDD-2C769A0E078C}.Release|Any CPU.Build.0 = Release|Any CPU
158 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
159 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
160 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
161 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
162 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
163 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Debug|Any CPU.Build.0 = Debug|Any CPU
164 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
165 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
166 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
167 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
168 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release|Any CPU.ActiveCfg = Release|Any CPU
169 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48}.Release|Any CPU.Build.0 = Release|Any CPU
170 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
171 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
172 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
173 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
174 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
175 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Debug|Any CPU.Build.0 = Debug|Any CPU
176 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
177 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
178 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
179 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
180 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release|Any CPU.ActiveCfg = Release|Any CPU
181 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632}.Release|Any CPU.Build.0 = Release|Any CPU
182 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
183 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
184 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
185 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
186 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
187 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
188 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
189 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
190 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
191 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
192 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
193 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6}.Release|Any CPU.Build.0 = Release|Any CPU
194 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug_Cuda|Any CPU.ActiveCfg = Debug|Any CPU
195 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug_Cuda|Any CPU.Build.0 = Debug|Any CPU
196 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug_DirectML|Any CPU.ActiveCfg = Debug|Any CPU
197 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug_DirectML|Any CPU.Build.0 = Debug|Any CPU
198 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
199 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Debug|Any CPU.Build.0 = Debug|Any CPU
200 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release_Cuda|Any CPU.ActiveCfg = Release|Any CPU
201 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release_Cuda|Any CPU.Build.0 = Release|Any CPU
202 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release_DirectML|Any CPU.ActiveCfg = Release|Any CPU
203 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release_DirectML|Any CPU.Build.0 = Release|Any CPU
204 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release|Any CPU.ActiveCfg = Release|Any CPU
205 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C}.Release|Any CPU.Build.0 = Release|Any CPU
206 | EndGlobalSection
207 | GlobalSection(SolutionProperties) = preSolution
208 | HideSolutionNode = FALSE
209 | EndGlobalSection
210 | GlobalSection(NestedProjects) = preSolution
211 | {22131B1B-1289-41DF-882F-A2E16A63BE9E} = {0BC576AC-FDE1-4DF8-BABD-668DBE6E7C9C}
212 | {1254AB34-B99A-4E4C-BD95-18BB22BF478E} = {255AD044-4A87-4975-B8EF-016F87277741}
213 | {4EB2FBF6-75D3-4B10-B5B5-675469C24780} = {0BC576AC-FDE1-4DF8-BABD-668DBE6E7C9C}
214 | {52D662CC-407B-42E6-8446-BEF969FFD30B} = {255AD044-4A87-4975-B8EF-016F87277741}
215 | {ED480C58-4355-4430-950B-1D85D3AE9891} = {0BC576AC-FDE1-4DF8-BABD-668DBE6E7C9C}
216 | {2C14C6E3-AF20-43CB-AECD-F6BBC2B2A858} = {255AD044-4A87-4975-B8EF-016F87277741}
217 | {C88880FD-67E0-4A72-BD29-005A8291DF7B} = {255AD044-4A87-4975-B8EF-016F87277741}
218 | {F9835E50-8AB8-4307-A70E-6DD63142CF50} = {EA6E5514-23BD-4B8B-A804-88AD5BF03E06}
219 | {84B45833-3D23-4095-ACDD-2C769A0E078C} = {EA6E5514-23BD-4B8B-A804-88AD5BF03E06}
220 | {046B5598-8DA6-4E49-BBC0-B88620E4CA48} = {57EDA879-FEC3-484B-B5A2-CC60B9BADE47}
221 | {813A9EBB-F3CF-434B-AAC6-3058CCF75632} = {57EDA879-FEC3-484B-B5A2-CC60B9BADE47}
222 | {0E93E13A-4AC6-48EB-A146-474639B0F7A6} = {0BC576AC-FDE1-4DF8-BABD-668DBE6E7C9C}
223 | {BFEF19DC-15C0-4ADD-A672-4337F9A7B95C} = {57EDA879-FEC3-484B-B5A2-CC60B9BADE47}
224 | EndGlobalSection
225 | GlobalSection(ExtensibilityGlobals) = postSolution
226 | SolutionGuid = {EAA25EC1-C5F2-40DC-8080-4DAF13311AEE}
227 | EndGlobalSection
228 | EndGlobal
229 |
--------------------------------------------------------------------------------