Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions dotnet/src/SemanticKernel/CoreSkills/TextMemorySkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Microsoft.SemanticKernel.CoreSkills;

/// <summary>
/// TextMemorySkill provides a skill to recall information from the long or short term memory.
/// TextMemorySkill provides a skill to save or recall information from the long or short term memory.
/// </summary>
/// <example>
/// Usage: kernel.ImportSkill("memory", new TextMemorySkill());
Expand All @@ -23,15 +23,20 @@ namespace Microsoft.SemanticKernel.CoreSkills;
public class TextMemorySkill
{
/// <summary>
/// Name of the context parameter used to specify which memory collection to use.
/// Name of the context variable used to specify which memory collection to use.
/// </summary>
public const string CollectionParam = "collection";

/// <summary>
/// Name of the context parameter used to specify memory search relevance score.
/// Name of the context variable used to specify memory search relevance score.
/// </summary>
public const string RelevanceParam = "relevance";

/// <summary>
/// Name of the context variable used to specify a unique key associated with stored information.
/// </summary>
public const string KeyParam = "key";

private const string DefaultCollection = "generic";
private const string DefaultRelevance = "0.75";

Expand All @@ -42,8 +47,8 @@ public class TextMemorySkill
/// SKContext["input"] = "what is the capital of France?"
/// {{memory.recall $input }} => "Paris"
/// </example>
/// <param name="ask"> The information to retrieve </param>
/// <param name="context"> Contains the 'collection' to search for information and 'relevance' score </param>
/// <param name="ask">The information to retrieve</param>
/// <param name="context">Contains the 'collection' to search for information and 'relevance' score</param>
[SKFunction("Recall a fact from the long term memory")]
[SKFunctionName("Recall")]
[SKFunctionInput(Description = "The information to retrieve")]
Expand Down Expand Up @@ -76,4 +81,32 @@ public async Task<string> RecallAsync(string ask, SKContext context)

return memory != null ? memory.Text : string.Empty;
}

/// <summary>
/// Save information to semantic memory
/// </summary>
/// <example>
/// SKContext["input"] = "the capital of France is Paris"
Comment thread
awharrison-28 marked this conversation as resolved.
Outdated
/// SKContext[TextMemorySkill.KeyParam] = "countryInfo1"
/// {{memory.save $input }}
/// </example>
/// <param name="text">The information to save</param>
/// <param name="context">Contains the 'collection' to save the information and unique 'key' to associate it with.</param>
[SKFunction("Save information to semantic memory")]
[SKFunctionName("Save")]
[SKFunctionInput(Description = "The information to save")]
[SKFunctionContextParameter(Name = CollectionParam, Description = "Memories collection where to save the information", DefaultValue = DefaultCollection)]
[SKFunctionContextParameter(Name = KeyParam, Description = "The key to save the information")]
public async Task SaveAsync(string text, SKContext context)
{
var collection = context.Variables.ContainsKey(CollectionParam) ? context[CollectionParam] : DefaultCollection;
Verify.NotEmpty(collection, "Memory collection not defined");

var key = context.Variables.ContainsKey(KeyParam) ? context[KeyParam] : string.Empty;
Verify.NotEmpty(key, "Memory key not defined");

context.Log.LogTrace("Saving memory to collection '{0}'", collection);

await context.Memory.SaveInformationAsync(collection, text: text, id: key);
}
}
27 changes: 18 additions & 9 deletions samples/dotnet/kernel-syntax-examples/Example15_MemorySkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,27 @@ public static async Task RunAsync()
.WithMemoryStorage(new VolatileMemoryStore())
.Build();

// ========= Store memories =========
// ========= 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");
await kernel.Memory.SaveInformationAsync(MemoryCollectionName, id: "info5", text: "My family is from New York");

// ========= Store memories using semantic function =========

// Add Memory as a skill for other functions
kernel.ImportSkill(new TextMemorySkill());

// Build a semantic function that saves info to memory
const string SAVE_FUNCTION_DEFINITION = @"{{save $info}}";
Comment thread
awharrison-28 marked this conversation as resolved.
Outdated
var memorySaver = kernel.CreateSemanticFunction(SAVE_FUNCTION_DEFINITION);

var context = kernel.CreateNewContext();
context[TextMemorySkill.CollectionParam] = MemoryCollectionName;
context[TextMemorySkill.KeyParam] = "info5";
Comment thread
awharrison-28 marked this conversation as resolved.
Outdated
context["info"] = "My family is from New York";
await memorySaver.InvokeAsync(context);

// ========= Test memory =========

Expand All @@ -52,11 +66,8 @@ public static async Task RunAsync()

// ========= Use memory in a semantic function =========

// Add Memory as a skill for other functions
kernel.ImportSkill(new TextMemorySkill());

// Build a semantic function that uses memory to find facts
const string FUNCTION_DEFINITION = @"
const string RECALL_FUNCTION_DEFINITION = @"
Consider only the facts below when answering questions.

About me: {{recall $fact1}}
Expand All @@ -67,13 +78,11 @@ Consider only the facts below when answering questions.
Answer:
";

var aboutMeOracle = kernel.CreateSemanticFunction(FUNCTION_DEFINITION, maxTokens: 100);
var aboutMeOracle = kernel.CreateSemanticFunction(RECALL_FUNCTION_DEFINITION, maxTokens: 100);

var context = kernel.CreateNewContext();
context["fact1"] = "where did I grow up?";
context["fact2"] = "where do I live?";
context["query"] = "Do I live in the same town where I grew up?";
context[TextMemorySkill.CollectionParam] = MemoryCollectionName;
context[TextMemorySkill.RelevanceParam] = "0.8";

var result = await aboutMeOracle.InvokeAsync(context);
Expand Down