Skip to content

Commit

Permalink
Add API allowing to store text/string, without the need to upload files
Browse files Browse the repository at this point in the history
  • Loading branch information
dluc committed Aug 23, 2023
1 parent acbbdcf commit 4aa6660
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 11 deletions.
45 changes: 42 additions & 3 deletions dotnet/ClientLib/ISemanticMemoryClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -24,17 +25,17 @@ public Task<string> ImportDocumentAsync(
CancellationToken cancellationToken = default);

/// <summary>
/// Import a files from disk into memory, with details such as tags and user ID.
/// Import a file from disk into memory, with details such as tags and user ID.
/// </summary>
/// <param name="fileName">Path and name of the files to import</param>
/// <param name="filePath">Path and name of the file to import</param>
/// <param name="documentId">Document ID</param>
/// <param name="tags">Optional tags to apply to the memories generated by the document</param>
/// <param name="index">Optional index name</param>
/// <param name="steps">Ingestion pipeline steps, optional override to the system default</param>
/// <param name="cancellationToken">Async task cancellation token</param>
/// <returns>Document ID</returns>
public Task<string> ImportDocumentAsync(
string fileName,
string filePath,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
Expand Down Expand Up @@ -65,6 +66,44 @@ public Task<bool> IsDocumentReadyAsync(
string? index = null,
CancellationToken cancellationToken = default);

/// <summary>
/// Import any stream from memory, e.g. text or binary data, with details such as tags and user ID.
/// </summary>
/// <param name="content">Content stream to import</param>
/// <param name="fileName">File name to assign to the stream, used to detect the file type</param>
/// <param name="documentId">Document ID</param>
/// <param name="tags">Optional tags to apply to the memories generated by the document</param>
/// <param name="index">Optional index name</param>
/// <param name="steps">Ingestion pipeline steps, optional override to the system default</param>
/// <param name="cancellationToken">Async task cancellation token</param>
/// <returns>Document ID</returns>
public Task<string> ImportDocumentAsync(
Stream content,
string? fileName = null,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default);

/// <summary>
/// Import any stream from memory, e.g. text or binary data, with details such as tags and user ID.
/// </summary>
/// <param name="text">Text content to import</param>
/// <param name="documentId">Document ID</param>
/// <param name="tags">Optional tags to apply to the memories generated by the document</param>
/// <param name="index">Optional index name</param>
/// <param name="steps">Ingestion pipeline steps, optional override to the system default</param>
/// <param name="cancellationToken">Async task cancellation token</param>
/// <returns>Document ID</returns>
public Task<string> ImportTextAsync(
string text,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default);

/// <summary>
/// Get information about an uploaded document
/// </summary>
Expand Down
33 changes: 31 additions & 2 deletions dotnet/ClientLib/MemoryWebClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public Task<string> ImportDocumentAsync(

/// <inheritdoc />
public Task<string> ImportDocumentAsync(
string fileName,
string filePath,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddFile(fileName);
var document = new Document(documentId, tags: tags).AddFile(filePath);
var uploadRequest = document.ToDocumentUploadRequest(index, steps);
return this.ImportDocumentAsync(uploadRequest, cancellationToken);
}
Expand All @@ -61,6 +61,35 @@ public Task<string> ImportDocumentAsync(
return this.ImportInternalAsync(index, uploadRequest, cancellationToken);
}

/// <inheritdoc />
public Task<string> ImportDocumentAsync(
Stream content,
string? fileName = null,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddStream(fileName, content);
var uploadRequest = document.ToDocumentUploadRequest(index, steps);
return this.ImportDocumentAsync(uploadRequest, cancellationToken);
}

/// <inheritdoc />
public async Task<string> ImportTextAsync(
string text,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
using Stream content = new MemoryStream(Encoding.UTF8.GetBytes(text));
return await this.ImportDocumentAsync(content, fileName: "content.txt", documentId: documentId, tags: tags, index: index, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<bool> IsDocumentReadyAsync(
string documentId,
Expand Down
34 changes: 34 additions & 0 deletions dotnet/ClientLib/Models/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public string Id

public List<string> FileNames { get; set; } = new();

public Dictionary<string, Stream> Streams { get; set; } = new();

public Document(string? id = null, TagCollection? tags = null, IEnumerable<string>? fileNames = null)
{
if (id == null || string.IsNullOrWhiteSpace(id)) { id = RandomId(); }
Expand All @@ -49,6 +51,32 @@ public Document AddFile(string fileName)
return this;
}

public Document AddStream(string? filename, Stream content)
{
if (content == null)
{
throw new SemanticMemoryException("The content stream is NULL");
}

if (string.IsNullOrWhiteSpace(filename))
{
var i = 0;
filename = "content.txt";
while (this.HasStream(filename))
{
filename = $"content{i++}.txt";
}
}

this.Streams.Add(filename!, content);
return this;
}

public bool HasStream(string name)
{
return this.Streams.ContainsKey(name);
}

public Document AddFiles(IEnumerable<string>? fileNames)
{
if (fileNames != null) { this.FileNames.AddRange(fileNames); }
Expand Down Expand Up @@ -106,6 +134,12 @@ public static DocumentUploadRequest ToDocumentUploadRequest(
files.Add(formFile);
}

foreach (KeyValuePair<string, Stream> stream in doc.Streams)
{
var formFile = new DocumentUploadRequest.UploadedFile(stream.Key, stream.Value);
files.Add(formFile);
}

uploadRequest.Files = files;

return uploadRequest;
Expand Down
38 changes: 36 additions & 2 deletions dotnet/CoreLib/Memory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SemanticMemory.Configuration;
Expand Down Expand Up @@ -62,14 +64,14 @@ public async Task<string> ImportDocumentAsync(

/// <inheritdoc />
public async Task<string> ImportDocumentAsync(
string fileName,
string filePath,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddFile(fileName);
var document = new Document(documentId, tags: tags).AddFile(filePath);
var uploadRequest = await document.ToDocumentUploadRequestAsync(index, steps, cancellationToken).ConfigureAwait(false);
return await this.ImportDocumentAsync(uploadRequest, cancellationToken).ConfigureAwait(false);
}
Expand All @@ -83,6 +85,38 @@ public async Task<string> ImportDocumentAsync(
return await this._orchestrator.ImportDocumentAsync(index, uploadRequest, cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<string> ImportDocumentAsync(
Stream content,
string? fileName = null,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddStream(fileName, content);
var uploadRequest = await document.ToDocumentUploadRequestAsync(index, steps, cancellationToken).ConfigureAwait(false);
return await this.ImportDocumentAsync(uploadRequest, cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<string> ImportTextAsync(
string text,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var content = new MemoryStream(Encoding.UTF8.GetBytes(text));
await using (content.ConfigureAwait(false))
{
return await this.ImportDocumentAsync(content, fileName: "content.txt", documentId: documentId, tags: tags, index: index, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
}

/// <inheritdoc />
public async Task<bool> IsDocumentReadyAsync(
string documentId,
Expand Down
38 changes: 36 additions & 2 deletions dotnet/CoreLib/MemoryService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SemanticMemory.Configuration;
Expand Down Expand Up @@ -37,14 +39,14 @@ public async Task<string> ImportDocumentAsync(

/// <inheritdoc />
public async Task<string> ImportDocumentAsync(
string fileName,
string filePath,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddFile(fileName);
var document = new Document(documentId, tags: tags).AddFile(filePath);
var uploadRequest = await document.ToDocumentUploadRequestAsync(index, steps, cancellationToken).ConfigureAwait(false);
return await this.ImportDocumentAsync(uploadRequest, cancellationToken).ConfigureAwait(false);
}
Expand All @@ -58,6 +60,38 @@ public Task<string> ImportDocumentAsync(
return this._orchestrator.ImportDocumentAsync(index, uploadRequest, cancellationToken);
}

/// <inheritdoc />
public async Task<string> ImportDocumentAsync(
Stream content,
string? fileName = null,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var document = new Document(documentId, tags: tags).AddStream(fileName, content);
var uploadRequest = await document.ToDocumentUploadRequestAsync(index, steps, cancellationToken).ConfigureAwait(false);
return await this.ImportDocumentAsync(uploadRequest, cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<string> ImportTextAsync(
string text,
string? documentId = null,
TagCollection? tags = null,
string? index = null,
IEnumerable<string>? steps = null,
CancellationToken cancellationToken = default)
{
var content = new MemoryStream(Encoding.UTF8.GetBytes(text));
await using (content.ConfigureAwait(false))
{
return await this.ImportDocumentAsync(content, fileName: "content.txt", documentId: documentId, tags: tags, index: index, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
}

/// <inheritdoc />
public Task<bool> IsDocumentReadyAsync(
string documentId,
Expand Down
34 changes: 33 additions & 1 deletion examples/001-dotnet-Serverless/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@
// === UPLOAD ============
// =======================

// Uploading some text, without using files
if (!await memory.IsDocumentReadyAsync(documentId: "doc000"))
{
Console.WriteLine("Uploading doc000");
await memory.ImportTextAsync("In physics, mass–energy equivalence is the relationship between mass and energy " +
"in a system's rest frame, where the two quantities differ only by a multiplicative " +
"constant and the units of measurement. The principle is described by the physicist " +
"Albert Einstein's formula: E = m*c^2", documentId: "doc000");
}
else
{
Console.WriteLine("doc000 already uploaded.");
}

// Simple file upload (checking if the file exists)
if (!await memory.IsDocumentReadyAsync(documentId: "doc001"))
{
Expand Down Expand Up @@ -67,10 +81,17 @@ await memory.ImportDocumentAsync(new Document("doc003")
// =======================

// Question without filters
var question = "What's Semantic Kernel?";
var question = "What's mc^2?";
Console.WriteLine($"\n\nQuestion: {question}");

var answer = await memory.AskAsync(question);
Console.WriteLine($"\nAnswer: {answer.Result}\n\n");

// Another question without filters
question = "What's Semantic Kernel?";
Console.WriteLine($"\n\nQuestion: {question}");

answer = await memory.AskAsync(question);
Console.WriteLine($"\nAnswer: {answer.Result}\n\n Sources:\n");

foreach (var x in answer.RelevantSources)
Expand Down Expand Up @@ -106,11 +127,22 @@ await memory.ImportDocumentAsync(new Document("doc003")
// ReSharper disable CommentTypo
/* ==== OUTPUT ====
Uploading doc000
doc001 already uploaded.
doc002 already uploaded.
doc003 already uploaded.
Question: What's mc^2?
Answer: mc^2 refers to the equation E=mc^2, which is the famous mass-energy equivalence equation proposed by
Albert Einstein in his theory of relativity. In this equation, E represents energy, m represents mass, and
c represents the speed of light in a vacuum. The equation states that energy is equal to mass multiplied by
the square of the speed of light. This equation shows the relationship between mass and energy, suggesting
that mass can be converted into energy and vice versa. It is a fundamental equation in physics and has
significant implications in various fields, including nuclear energy and particle physics.
Question: What's Semantic Kernel?
warn: Microsoft.SemanticMemory.Search.SearchClient[0]
No memories available
Expand Down
Loading

0 comments on commit 4aa6660

Please sign in to comment.