Skip to content

Commit e63bbac

Browse files
committed
Memory Plugin for .NET
* New MemoryPlugin class / nuget * Example showing how to use the memory plugin * Add future API Key param to web client
1 parent 49edc93 commit e63bbac

File tree

8 files changed

+514
-3
lines changed

8 files changed

+514
-3
lines changed

KernelMemory.sln

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "009-dotnet-custom-LLM", "ex
162162
EndProject
163163
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "010-dotnet-custom-EmbeddingGenerator", "examples\010-dotnet-custom-EmbeddingGenerator\010-dotnet-custom-EmbeddingGenerator.csproj", "{70ACEB4A-6820-4E67-BB15-98DC19CC7DB1}"
164164
EndProject
165+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{06F36495-16F8-458A-A455-3F85C8C9B24F}"
166+
EndProject
167+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.KernelMemory.Plugin", "plugins\dotnet\Microsoft.KernelMemory.Plugin\Microsoft.KernelMemory.Plugin.csproj", "{F7609330-E97E-422C-8983-EC501B2DDC52}"
168+
EndProject
169+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "011-using-MemoryPlugin", "examples\011-using-MemoryPlugin\011-using-MemoryPlugin.csproj", "{89F72748-E8A4-4FDF-A02C-8B141E8EA433}"
170+
EndProject
165171
Global
166172
GlobalSection(SolutionConfigurationPlatforms) = preSolution
167173
Debug|Any CPU = Debug|Any CPU
@@ -198,6 +204,8 @@ Global
198204
{8A90555B-C28B-401B-960A-619DE9A87C4C} = {5E7DD43D-B5E7-4827-B57D-447E5B428589}
199205
{89D6F024-C4E1-4779-A7C6-117F32433E90} = {0A43C65C-6007-4BB4-B3FE-8D439FC91841}
200206
{70ACEB4A-6820-4E67-BB15-98DC19CC7DB1} = {0A43C65C-6007-4BB4-B3FE-8D439FC91841}
207+
{F7609330-E97E-422C-8983-EC501B2DDC52} = {06F36495-16F8-458A-A455-3F85C8C9B24F}
208+
{89F72748-E8A4-4FDF-A02C-8B141E8EA433} = {0A43C65C-6007-4BB4-B3FE-8D439FC91841}
201209
EndGlobalSection
202210
GlobalSection(ProjectConfigurationPlatforms) = postSolution
203211
{8A9FA587-7EBA-4D43-BE47-38D798B1C74C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -288,5 +296,13 @@ Global
288296
{70ACEB4A-6820-4E67-BB15-98DC19CC7DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
289297
{70ACEB4A-6820-4E67-BB15-98DC19CC7DB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
290298
{70ACEB4A-6820-4E67-BB15-98DC19CC7DB1}.Release|Any CPU.Build.0 = Release|Any CPU
299+
{F7609330-E97E-422C-8983-EC501B2DDC52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
300+
{F7609330-E97E-422C-8983-EC501B2DDC52}.Debug|Any CPU.Build.0 = Debug|Any CPU
301+
{F7609330-E97E-422C-8983-EC501B2DDC52}.Release|Any CPU.ActiveCfg = Release|Any CPU
302+
{F7609330-E97E-422C-8983-EC501B2DDC52}.Release|Any CPU.Build.0 = Release|Any CPU
303+
{89F72748-E8A4-4FDF-A02C-8B141E8EA433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
304+
{89F72748-E8A4-4FDF-A02C-8B141E8EA433}.Debug|Any CPU.Build.0 = Debug|Any CPU
305+
{89F72748-E8A4-4FDF-A02C-8B141E8EA433}.Release|Any CPU.ActiveCfg = Release|Any CPU
306+
{89F72748-E8A4-4FDF-A02C-8B141E8EA433}.Release|Any CPU.Build.0 = Release|Any CPU
291307
EndGlobalSection
292308
EndGlobal

dotnet/ClientLib/MemoryWebClient.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ namespace Microsoft.KernelMemory;
1818
public class MemoryWebClient : IKernelMemory
1919
{
2020
private readonly HttpClient _client;
21+
private readonly string _apiKey;
2122

22-
public MemoryWebClient(string endpoint) : this(endpoint, new HttpClient())
23+
public MemoryWebClient(string endpoint, string apiKey = "") : this(endpoint, new HttpClient())
2324
{
2425
}
2526

26-
public MemoryWebClient(string endpoint, HttpClient client)
27+
public MemoryWebClient(string endpoint, HttpClient client, string apiKey = "")
2728
{
2829
this._client = client;
2930
this._client.BaseAddress = new Uri(endpoint);
31+
this._apiKey = apiKey;
3032
}
3133

3234
/// <inheritdoc />
@@ -300,7 +302,11 @@ public async Task<MemoryAnswer> AskAsync(
300302

301303
#region private
302304

303-
private async Task<string> ImportInternalAsync(string index, DocumentUploadRequest uploadRequest, CancellationToken cancellationToken)
305+
/// <returns>Document ID</returns>
306+
private async Task<string> ImportInternalAsync(
307+
string index,
308+
DocumentUploadRequest uploadRequest,
309+
CancellationToken cancellationToken)
304310
{
305311
// Populate form with values and files from disk
306312
using MultipartFormDataContent formData = new();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<AssemblyName/>
8+
<RootNamespace/>
9+
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.SemanticKernel" VersionOverride="1.0.0-beta5"/>
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\..\plugins\dotnet\Microsoft.KernelMemory.Plugin\Microsoft.KernelMemory.Plugin.csproj" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<None Remove="mydocs-NASA-news.pdf" />
22+
<Content Include="mydocs-NASA-news.pdf">
23+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
24+
</Content>
25+
</ItemGroup>
26+
27+
</Project>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Microsoft.KernelMemory;
4+
using Microsoft.SemanticKernel;
5+
using Microsoft.SemanticKernel.Orchestration;
6+
7+
public static class Program
8+
{
9+
// ReSharper disable InconsistentNaming
10+
public static async Task Main()
11+
{
12+
const string Document = "mydocs-NASA-news.pdf";
13+
const string Question1 = "any news about Orion?";
14+
const string Question2 = "any news about Hubble telescope?";
15+
const string Question3 = "what is a solar eclipse?";
16+
17+
// === PREPARE KERNEL ===
18+
// Usual code to create an instance of SK, using Azure OpenAI.
19+
// You can use any LLM, replacing `WithAzureChatCompletionService` with other LLM options.
20+
21+
var builder = new KernelBuilder();
22+
builder.WithAzureChatCompletionService(
23+
deploymentName: Environment.GetEnvironmentVariable("AOAI_DEPLOYMENT"),
24+
endpoint: Environment.GetEnvironmentVariable("AOAI_ENDPOINT"),
25+
apiKey: Environment.GetEnvironmentVariable("AOAI_API_KEY"));
26+
27+
var kernel = builder.Build();
28+
29+
// === PREPARE A SIMPLE SEMANTIC FUNCTION
30+
// A simple prompt showing how you can leverage the memory inside prompts and semantic functions.
31+
// See how "memory.ask" is used to pass the user question. At runtime the block is replaced with the
32+
// answer provided by the memory service.
33+
34+
var skPrompt = """
35+
Question to Kernel Memory: {{$input}}
36+
37+
Kernel Memory Answer: {{memory.ask $input}}
38+
39+
If the answer is empty say 'I don't know' otherwise reply with a preview of the answer, truncated to 15 words.
40+
""";
41+
42+
var doesItKnowFunction = kernel.CreateSemanticFunction(skPrompt);
43+
44+
// === PREPARE MEMORY PLUGIN ===
45+
// Load the Kernel Memory plugin into Semantic Kernel.
46+
// We're using a local instance here, so remember to start the service locally first,
47+
// otherwise change the URL pointing to your KM endpoint.
48+
49+
var memory = new MemoryWebClient("http://127.0.0.1:9001/");
50+
kernel.ImportFunctions(new MemoryPlugin(memory), "memory");
51+
52+
// === LOAD DOCUMENT INTO MEMORY ===
53+
// Load some data in memory, in this case use a PDF file, though
54+
// you can also load web pages, Word docs, raw text, etc.
55+
56+
await memory.ImportDocumentAsync(Document, documentId: "NASA001");
57+
58+
// === RUN SEMANTIC FUNCTION ===
59+
// Run some example questions, showing how the answer is grounded on the document uploaded.
60+
// Only the first question can be answered, because the document uploaded doesn't contain any
61+
// information about Question2 and Question3.
62+
63+
Console.WriteLine("---------");
64+
KernelResult answer = await kernel.RunAsync(Question1, doesItKnowFunction);
65+
Console.WriteLine(Question1 + "\n");
66+
Console.WriteLine("Answer: " + answer);
67+
68+
Console.WriteLine("---------");
69+
answer = await kernel.RunAsync(Question2, doesItKnowFunction);
70+
Console.WriteLine(Question2 + "\n");
71+
Console.WriteLine("Answer: " + answer);
72+
73+
Console.WriteLine("---------");
74+
answer = await kernel.RunAsync(Question3, doesItKnowFunction);
75+
Console.WriteLine(Question3 + "\n");
76+
Console.WriteLine("Answer: " + answer);
77+
}
78+
}
79+
80+
/* ===== OUTPUT =====
81+
82+
---------
83+
any news about Orion?
84+
85+
Answer: Yes, NASA has invited media to see the new test version of the Orion spacecraft...
86+
---------
87+
any news about Hubble telescope?
88+
89+
Answer: I don't know.
90+
---------
91+
what is a solar eclipse?
92+
93+
Answer: I don't know.
94+
95+
*/
213 KB
Binary file not shown.

0 commit comments

Comments
 (0)