-
Notifications
You must be signed in to change notification settings - Fork 3k
/
DocumentPlugin.cs
101 lines (92 loc) · 4.56 KB
/
DocumentPlugin.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.SemanticKernel.Plugins.Document.FileSystem;
namespace Microsoft.SemanticKernel.Plugins.Document;
//**********************************************************************************************************************
// EXAMPLE USAGE
// Option #1: as a standalone C# function
//
// DocumentPlugin documentPlugin = new(new WordDocumentConnector(), new LocalDriveConnector());
// string filePath = "PATH_TO_DOCX_FILE.docx";
// string text = await documentPlugin.ReadTextAsync(filePath);
// Console.WriteLine(text);
//
//
// Option #2: with the Semantic Kernel
//
// DocumentPlugin documentPlugin = new(new WordDocumentConnector(), new LocalDriveConnector());
// string filePath = "PATH_TO_DOCX_FILE.docx";
// ISemanticKernel kernel = SemanticKernel.Build();
// var result = await kernel.RunAsync(
// filePath,
// documentPlugin.ReadTextAsync);
// Console.WriteLine(result);
//**********************************************************************************************************************
/// <summary>
/// Plugin for interacting with documents (e.g. Microsoft Word)
/// </summary>
public sealed class DocumentPlugin
{
private readonly IDocumentConnector _documentConnector;
private readonly IFileSystemConnector _fileSystemConnector;
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DocumentPlugin"/> class.
/// </summary>
/// <param name="documentConnector">Document connector</param>
/// <param name="fileSystemConnector">File system connector</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use for logging. If null, no logging will be performed.</param>
public DocumentPlugin(IDocumentConnector documentConnector, IFileSystemConnector fileSystemConnector, ILoggerFactory? loggerFactory = null)
{
this._documentConnector = documentConnector ?? throw new ArgumentNullException(nameof(documentConnector));
this._fileSystemConnector = fileSystemConnector ?? throw new ArgumentNullException(nameof(fileSystemConnector));
this._logger = loggerFactory?.CreateLogger(typeof(DocumentPlugin)) ?? NullLogger.Instance;
}
/// <summary>
/// Read all text from a document, using the filePath argument as the file path.
/// </summary>
[KernelFunction, Description("Read all text from a document")]
public async Task<string> ReadTextAsync(
[Description("Path to the file to read")] string filePath,
CancellationToken cancellationToken = default)
{
this._logger.LogDebug("Reading text from {0}", filePath);
using var stream = await this._fileSystemConnector.GetFileContentStreamAsync(filePath, cancellationToken).ConfigureAwait(false);
return this._documentConnector.ReadText(stream);
}
/// <summary>
/// Append the text specified by the text argument to a document. If the document doesn't exist, it will be created.
/// </summary>
[KernelFunction, Description("Append text to a document. If the document doesn't exist, it will be created.")]
public async Task AppendTextAsync(
[Description("Text to append")] string text,
[Description("Destination file path")] string filePath,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentException("Variable was null or whitespace", nameof(filePath));
}
// If the document already exists, open it. If not, create it.
if (await this._fileSystemConnector.FileExistsAsync(filePath, cancellationToken).ConfigureAwait(false))
{
this._logger.LogDebug("Writing text to file {0}", filePath);
using Stream stream = await this._fileSystemConnector.GetWriteableFileStreamAsync(filePath, cancellationToken).ConfigureAwait(false);
this._documentConnector.AppendText(stream, text);
}
else
{
this._logger.LogDebug("File does not exist. Creating file at {0}", filePath);
using Stream stream = await this._fileSystemConnector.CreateFileAsync(filePath, cancellationToken).ConfigureAwait(false);
this._documentConnector.Initialize(stream);
this._logger.LogDebug("Writing text to {0}", filePath);
this._documentConnector.AppendText(stream, text);
}
}
}