diff --git a/LLama.Examples/LLama.Examples.csproj b/LLama.Examples/LLama.Examples.csproj
index a8abe3ae..865a6321 100644
--- a/LLama.Examples/LLama.Examples.csproj
+++ b/LLama.Examples/LLama.Examples.csproj
@@ -27,6 +27,7 @@
+
diff --git a/LLama.Examples/NewVersion/SemanticKernelMemory.cs b/LLama.Examples/NewVersion/SemanticKernelMemory.cs
new file mode 100644
index 00000000..24e6f1fb
--- /dev/null
+++ b/LLama.Examples/NewVersion/SemanticKernelMemory.cs
@@ -0,0 +1,167 @@
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using LLama.Common;
+using LLamaSharp.SemanticKernel.TextEmbedding;
+using Microsoft.SemanticKernel.AI.Embeddings;
+
+namespace LLama.Examples.NewVersion
+{
+ public class SemanticKernelMemory
+ {
+ private const string MemoryCollectionName = "SKGitHub";
+
+ public static async Task Run()
+ {
+ var loggerFactory = ConsoleLogger.LoggerFactory;
+ Console.WriteLine("Example from: https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/KernelSyntaxExamples/Example14_SemanticMemory.cs");
+ Console.Write("Please input your model path: ");
+ var modelPath = Console.ReadLine();
+
+ var seed = 1337;
+ // Load weights into memory
+ var parameters = new ModelParams(modelPath)
+ {
+ Seed = seed,
+ EmbeddingMode = true,
+ GpuLayerCount = 50,
+ };
+
+ using var model = LLamaWeights.LoadFromFile(parameters);
+ var embedding = new LLamaEmbedder(model, parameters);
+
+ Console.WriteLine("====================================================");
+ Console.WriteLine("======== Semantic Memory (volatile, in RAM) ========");
+ Console.WriteLine("====================================================");
+
+ /* You can build your own semantic memory combining an Embedding Generator
+ * with a Memory storage that supports search by similarity (ie semantic search).
+ *
+ * In this example we use a volatile memory, a local simulation of a vector DB.
+ *
+ * You can replace VolatileMemoryStore with Qdrant (see QdrantMemoryStore connector)
+ * or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc.
+ */
+
+ var kernelWithCustomDb = Kernel.Builder
+ .WithLoggerFactory(ConsoleLogger.LoggerFactory)
+ .WithAIService("local-llama-embed", new LLamaSharpEmbeddingGeneration(embedding), true)
+ .WithMemoryStorage(new VolatileMemoryStore())
+ .Build();
+
+ await RunExampleAsync(kernelWithCustomDb);
+ }
+
+ private static async Task RunExampleAsync(IKernel kernel)
+ {
+ await StoreMemoryAsync(kernel);
+
+ await SearchMemoryAsync(kernel, "How do I get started?");
+
+ /*
+ Output:
+
+ Query: How do I get started?
+
+ Result 1:
+ URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md
+ Title : README: Installation, getting started, and how to contribute
+
+ Result 2:
+ URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet-jupyter-notebooks/00-getting-started.ipynb
+ Title : Jupyter notebook describing how to get started with the Semantic Kernel
+
+ */
+
+ await SearchMemoryAsync(kernel, "Can I build a chat with SK?");
+
+ /*
+ Output:
+
+ Query: Can I build a chat with SK?
+
+ Result 1:
+ URL: : https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT
+ Title : Sample demonstrating how to create a chat skill interfacing with ChatGPT
+
+ Result 2:
+ URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md
+ Title : README: README associated with a sample chat summary react-based webapp
+
+ */
+ }
+
+ private static async Task SearchMemoryAsync(IKernel kernel, string query)
+ {
+ Console.WriteLine("\nQuery: " + query + "\n");
+
+ var memories = kernel.Memory.SearchAsync(MemoryCollectionName, query, limit: 2, minRelevanceScore: 0.5);
+
+ int i = 0;
+ await foreach (MemoryQueryResult memory in memories)
+ {
+ Console.WriteLine($"Result {++i}:");
+ Console.WriteLine(" URL: : " + memory.Metadata.Id);
+ Console.WriteLine(" Title : " + memory.Metadata.Description);
+ Console.WriteLine(" Relevance: " + memory.Relevance);
+ Console.WriteLine();
+ }
+
+ Console.WriteLine("----------------------");
+ }
+
+ private static async Task StoreMemoryAsync(IKernel kernel)
+ {
+ /* Store some data in the semantic memory.
+ *
+ * When using Azure Cognitive Search the data is automatically indexed on write.
+ *
+ * When using the combination of VolatileStore and Embedding generation, SK takes
+ * care of creating and storing the index
+ */
+
+ Console.WriteLine("\nAdding some GitHub file URLs and their descriptions to the semantic memory.");
+ var githubFiles = SampleData();
+ var i = 0;
+ foreach (var entry in githubFiles)
+ {
+ var result = await kernel.Memory.SaveReferenceAsync(
+ collection: MemoryCollectionName,
+ externalSourceName: "GitHub",
+ externalId: entry.Key,
+ description: entry.Value,
+ text: entry.Value);
+
+ Console.WriteLine($"#{++i} saved.");
+ Console.WriteLine(result);
+ }
+
+ Console.WriteLine("\n----------------------");
+ }
+
+ private static Dictionary SampleData()
+ {
+ return new Dictionary
+ {
+ ["https://github.com/microsoft/semantic-kernel/blob/main/README.md"]
+ = "README: Installation, getting started, and how to contribute",
+ ["https://github.com/microsoft/semantic-kernel/blob/main/dotnet/notebooks/02-running-prompts-from-file.ipynb"]
+ = "Jupyter notebook describing how to pass prompts from a file to a semantic skill or function",
+ ["https://github.com/microsoft/semantic-kernel/blob/main/dotnet/notebooks//00-getting-started.ipynb"]
+ = "Jupyter notebook describing how to get started with the Semantic Kernel",
+ ["https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT"]
+ = "Sample demonstrating how to create a chat skill interfacing with ChatGPT",
+ ["https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs"]
+ = "C# class that defines a volatile embedding store",
+ ["https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md"]
+ = "README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4",
+ ["https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md"]
+ = "README: README associated with a sample chat summary react-based webapp",
+ };
+ }
+ }
+}
diff --git a/LLama.Examples/NewVersion/SemanticKernelMemorySkill.cs b/LLama.Examples/NewVersion/SemanticKernelMemorySkill.cs
new file mode 100644
index 00000000..c1c9bd48
--- /dev/null
+++ b/LLama.Examples/NewVersion/SemanticKernelMemorySkill.cs
@@ -0,0 +1,184 @@
+using System.Reflection.Metadata;
+using System.Security.Cryptography;
+using System.Text;
+using LLama.Abstractions;
+using LLama.Common;
+using LLamaSharp.SemanticKernel.TextCompletion;
+using LLamaSharp.SemanticKernel.TextEmbedding;
+using Microsoft.Extensions.Logging;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.AI.ChatCompletion;
+using Microsoft.SemanticKernel.AI.Embeddings;
+using Microsoft.SemanticKernel.AI.TextCompletion;
+using Microsoft.SemanticKernel.Memory;
+using Microsoft.SemanticKernel.Skills.Core;
+
+namespace LLama.Examples.NewVersion
+{
+ public class SemanticKernelMemorySkill
+ {
+ private const string MemoryCollectionName = "aboutMe";
+
+ public static async Task Run()
+ {
+ var loggerFactory = ConsoleLogger.LoggerFactory;
+ Console.WriteLine("Example from: https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/KernelSyntaxExamples/Example15_MemorySkill.cs");
+ Console.Write("Please input your model path: ");
+ var modelPath = Console.ReadLine();
+
+ var seed = 1337;
+ // Load weights into memory
+ var parameters = new ModelParams(modelPath)
+ {
+ Seed = seed,
+ EmbeddingMode = true,
+ GpuLayerCount = 50,
+ };
+
+ using var model = LLamaWeights.LoadFromFile(parameters);
+ var embedding = new LLamaEmbedder(model, parameters);
+ using var context = model.CreateContext(parameters);
+ // TODO: This executor is most likely incorrect.
+ var ex = new InteractiveExecutor(context);
+ var builder = new KernelBuilder();
+ builder.WithLoggerFactory(loggerFactory);
+
+ builder.WithAIService("local-llama-text", new LLamaSharpTextCompletion(ex), true);
+ builder.WithAIService("local-llama-embed", new LLamaSharpEmbeddingGeneration(embedding), true);
+ builder.WithMemoryStorage(new VolatileMemoryStore());
+ var kernel = builder.Build();
+ // ========= Store memories using the kernel =========
+
+ await kernel.Memory.SaveInformationAsync(MemoryCollectionName, id: "info1", text: "My name is Andrea");
+ await kernel.Memory.SaveInformationAsync(MemoryCollectionName, id: "info2", text: "I work as a tourist operator");
+ await kernel.Memory.SaveInformationAsync(MemoryCollectionName, id: "info3", text: "I've been living in Seattle since 2005");
+ await kernel.Memory.SaveInformationAsync(MemoryCollectionName, id: "info4", text: "I visited France and Italy five times since 2015");
+
+ // ========= Store memories using semantic function =========
+
+ // Add Memory as a skill for other functions
+ var memorySkill = new TextMemorySkill(kernel.Memory);
+ kernel.ImportSkill(memorySkill);
+
+ // Build a semantic function that saves info to memory
+ const string SaveFunctionDefinition = "{{save $info}}";
+ var memorySaver = kernel.CreateSemanticFunction(SaveFunctionDefinition);
+
+ //await kernel.RunAsync(memorySaver, new()
+ //{
+ // [TextMemorySkill.CollectionParam] = MemoryCollectionName,
+ // [TextMemorySkill.KeyParam] = "info5",
+ // ["info"] = "My family is from New York"
+ //});
+
+ // ========= Test memory remember =========
+ Console.WriteLine("========= Example: Recalling a Memory =========");
+
+ var answer = await memorySkill.RetrieveAsync(MemoryCollectionName, "info1", loggerFactory);
+ Console.WriteLine("Memory associated with 'info1': {0}", answer);
+
+ answer = await memorySkill.RetrieveAsync(MemoryCollectionName, "info2", loggerFactory);
+ Console.WriteLine("Memory associated with 'info2': {0}", answer);
+
+ answer = await memorySkill.RetrieveAsync(MemoryCollectionName, "info3", loggerFactory);
+ Console.WriteLine("Memory associated with 'info3': {0}", answer);
+
+ answer = await memorySkill.RetrieveAsync(MemoryCollectionName, "info4", loggerFactory);
+ Console.WriteLine("Memory associated with 'info4': {0}", answer);
+
+ //answer = await memorySkill.RetrieveAsync(MemoryCollectionName, "info5", loggerFactory);
+ //Console.WriteLine("Memory associated with 'info5': {0}", answer);
+
+ // ========= Test memory recall =========
+ Console.WriteLine("========= Example: Recalling an Idea =========");
+
+ answer = await memorySkill.RecallAsync("where did I grow up?", MemoryCollectionName, relevance: null, limit: 2, null);
+ Console.WriteLine("Ask: where did I grow up?");
+ Console.WriteLine("Answer:\n{0}", answer);
+
+ answer = await memorySkill.RecallAsync("where do I live?", MemoryCollectionName, relevance: null, limit: 2, null);
+ Console.WriteLine("Ask: where do I live?");
+ Console.WriteLine("Answer:\n{0}", answer);
+
+ /*
+ Output:
+
+ Ask: where did I grow up?
+ Answer:
+ ["My family is from New York","I\u0027ve been living in Seattle since 2005"]
+
+ Ask: where do I live?
+ Answer:
+ ["I\u0027ve been living in Seattle since 2005","My family is from New York"]
+ */
+
+ // ========= Use memory in a semantic function =========
+ Console.WriteLine("========= Example: Using Recall in a Semantic Function =========");
+
+ // Build a semantic function that uses memory to find facts
+ const string RecallFunctionDefinition = @"
+Consider only the facts below when answering questions.
+
+About me: {{recall 'where did I grow up?'}}
+About me: {{recall 'where do I live?'}}
+
+Question: {{$input}}
+
+Answer:
+";
+
+ var aboutMeOracle = kernel.CreateSemanticFunction(RecallFunctionDefinition, maxTokens: 100);
+
+ var result = await kernel.RunAsync(aboutMeOracle, new("Do I live in the same town where I grew up?")
+ {
+ [TextMemorySkill.CollectionParam] = MemoryCollectionName,
+ [TextMemorySkill.RelevanceParam] = "0.8"
+ });
+
+ Console.WriteLine("Do I live in the same town where I grew up?\n");
+ Console.WriteLine(result);
+
+ /*
+ Output:
+
+ Do I live in the same town where I grew up?
+
+ No, I do not live in the same town where I grew up since my family is from New York and I have been living in Seattle since 2005.
+ */
+
+ // ========= Remove a memory =========
+ Console.WriteLine("========= Example: Forgetting a Memory =========");
+
+ result = await kernel.RunAsync(aboutMeOracle, new("Tell me a bit about myself")
+ {
+ ["fact1"] = "What is my name?",
+ ["fact2"] = "What do I do for a living?",
+ [TextMemorySkill.RelevanceParam] = ".75"
+ });
+
+ Console.WriteLine("Tell me a bit about myself\n");
+ Console.WriteLine(result);
+
+ /*
+ Approximate Output:
+ Tell me a bit about myself
+
+ My name is Andrea and my family is from New York. I work as a tourist operator.
+ */
+
+ await memorySkill.RemoveAsync(MemoryCollectionName, "info1", loggerFactory);
+
+ result = await kernel.RunAsync(aboutMeOracle, new("Tell me a bit about myself"));
+
+ Console.WriteLine("Tell me a bit about myself\n");
+ Console.WriteLine(result);
+
+ /*
+ Approximate Output:
+ Tell me a bit about myself
+
+ I'm from a family originally from New York and I work as a tourist operator. I've been living in Seattle since 2005.
+ */
+ }
+ }
+}
diff --git a/LLama.Examples/NewVersion/TestRunner.cs b/LLama.Examples/NewVersion/TestRunner.cs
index 83316510..7d27f931 100644
--- a/LLama.Examples/NewVersion/TestRunner.cs
+++ b/LLama.Examples/NewVersion/TestRunner.cs
@@ -20,6 +20,8 @@
Console.WriteLine("10: Constrain response to json format using grammar.");
Console.WriteLine("11: Semantic Kernel Prompt.");
Console.WriteLine("12: Semantic Kernel Chat.");
+ Console.WriteLine("13: Semantic Kernel Memory.");
+ Console.WriteLine("14: Semantic Kernel Memory Skill.");
while (true)
{
@@ -78,6 +80,14 @@
{
await SemanticKernelChat.Run();
}
+ else if (choice == 13)
+ {
+ await SemanticKernelMemory.Run();
+ }
+ else if (choice == 14)
+ {
+ await SemanticKernelMemorySkill.Run();
+ }
else
{
Console.WriteLine("Cannot parse your choice. Please select again.");
diff --git a/LLama.Examples/RepoUtils.cs b/LLama.Examples/RepoUtils.cs
new file mode 100644
index 00000000..8e728339
--- /dev/null
+++ b/LLama.Examples/RepoUtils.cs
@@ -0,0 +1,40 @@
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LLama.Examples
+{
+ ///
+ /// Basic logger printing to console
+ ///
+ internal static class ConsoleLogger
+ {
+ internal static ILogger Logger => LoggerFactory.CreateLogger