-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathDocuRAGPlugin.cs
164 lines (140 loc) · 7.93 KB
/
DocuRAGPlugin.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.KernelMemory;
using Microsoft.KernelMemory.FileSystem.DevTools;
using Microsoft.KernelMemory.MemoryStorage.DevTools;
using Microsoft.Extensions.Logging;
using Spectre.Console;
/*
DocuRAGPlugin: can be used to retrieve content for question answering and task guidance from documentation via RAG
Exposed functions:
- RetrieveRagContent: Retrieve content for question answering, e.g about an AI related topic. The question can be about about scientific or technology topics, e.g. AI or to get a summary of a topic for a synopsis.
- GetProcessGuidance: Get guidance on how a certain process or task can be done.
*/
namespace SemanticKernelConsoleCopilotDemo
{
public sealed class DocuRAGPlugin
{
private IKernelMemory? kernelMemory;
private bool reimportDocuments = false;
private string assistantLanguage = "English";
private ConfigurationSettings configSettings = new ConfigurationSettings();
// ----------------- Plugin functions -----------------
[KernelFunction, Description("Retrieve content for question answering, e.g about an AI related topic. The question can be about about scientific or technology topics, e.g. AI or to get a summary of a topic for a synopsis.")]
public async Task<string> RetrieveRagContent(
[Description("The question about the topic. Rephrase the question which keeps the original meaning and can be used to retrieve content for question answering. If the question is not in English, translate it first.")] string question)
{
if (kernelMemory == null)
throw new InvalidOperationException("Kernel memory is not initialized.");
var askResult = await AnsiConsole.Status()
.Spinner(Spinner.Known.Dots)
.StartAsync("Getting info from external sources...", async (context) =>
{
return (await kernelMemory.AskAsync(question, filter: new MemoryFilter().ByTag("topic", "documentation")).ConfigureAwait(continueOnCapturedContext: false)).Result;
});
return askResult;
}
[KernelFunction, Description("Get guidance on how a certain process or task can be done.")]
public async Task<string> GetProcessGuidance(
[Description("What is process or task on which the guidance is needed")] string question)
{
if (kernelMemory == null)
throw new InvalidOperationException("Kernel memory is not initialized.");
var askResult = await AnsiConsole.Status()
.Spinner(Spinner.Known.Dots)
.StartAsync("Getting plan guidance from cookbook...", async (context) =>
{
var ragSearchResult = (await kernelMemory.AskAsync(question, filter: new MemoryFilter().ByTag("topic", "cookbook")).ConfigureAwait(continueOnCapturedContext: false)).Result;
return $"Anwser based on the following content, don't add your own take on it: {ragSearchResult}. ";
});
return askResult;
}
// ----------------- Initialization -----------------
public static Task<DocuRAGPlugin> Create(bool reimportDocuments = false, string assistantLanguage = "English")
{
var ret = new DocuRAGPlugin();
ret.reimportDocuments = reimportDocuments;
ret.assistantLanguage = assistantLanguage;
return ret.InitializeAsync();
}
private async Task<DocuRAGPlugin> InitializeAsync()
{
await InitKernelMemoryForRAG();
return this;
}
private AzureOpenAIConfig GetAzureOpenAIConfig(bool isEmbedding = false)
{
return new AzureOpenAIConfig
{
APIKey = ConfigurationSettings.ApiKey,
Deployment = isEmbedding ? ConfigurationSettings.EmbeddingDeploymentId : ConfigurationSettings.DeploymentId,
Endpoint = ConfigurationSettings.Endpoint,
APIType = AzureOpenAIConfig.APITypes.ChatCompletion,
Auth = AzureOpenAIConfig.AuthTypes.APIKey
};
}
private OpenAIConfig GetOpenAIConfig(bool isEmbedding = false)
{
return new OpenAIConfig
{
APIKey = ConfigurationSettings.ApiKey,
EmbeddingModel = ConfigurationSettings.EmbeddingModelId,
TextModel = ConfigurationSettings.ModelId,
};
}
private async Task InitKernelMemoryForRAG()
{
var useAzureAiSearch = true;
#pragma warning disable 0162 // disable unreachable code warning
var indexName = "sk_copilot_demo";
if (ConfigurationSettings.ServiceType == "OpenAI")
{
var kernelMemoryBuilderOpenAI = new KernelMemoryBuilder()
.WithOpenAITextEmbeddingGeneration(GetOpenAIConfig(isEmbedding: true))
.WithOpenAITextGeneration(GetOpenAIConfig())
.WithSimpleVectorDb(new SimpleVectorDbConfig { StorageType = FileSystemTypes.Disk, Directory = "vector_storage" });
kernelMemoryBuilderOpenAI.Services
.AddLogging(c => { c.AddConsole().SetMinimumLevel(LogLevel.Warning); });
kernelMemory = kernelMemoryBuilderOpenAI.Build();
} else {
if (useAzureAiSearch) {
var kernelMemoryBuilderAzure = new KernelMemoryBuilder()
.With(new KernelMemoryConfig{ DefaultIndexName = indexName,})
.WithAzureOpenAITextEmbeddingGeneration(GetAzureOpenAIConfig(isEmbedding: true))
.WithAzureOpenAITextGeneration(GetAzureOpenAIConfig())
.WithAzureAISearchMemoryDb(ConfigurationSettings.AiSearchEndpoint, ConfigurationSettings.AiSearchApiKey);
kernelMemoryBuilderAzure.Services
.AddLogging(c => { c.AddConsole().SetMinimumLevel(LogLevel.Warning); });
kernelMemory = kernelMemoryBuilderAzure.Build();
} else {
var kernelMemoryBuilderAzure = new KernelMemoryBuilder()
.With(new KernelMemoryConfig{ DefaultIndexName = indexName,})
.WithAzureOpenAITextEmbeddingGeneration(GetAzureOpenAIConfig(isEmbedding: true))
.WithAzureOpenAITextGeneration(GetAzureOpenAIConfig())
.WithSimpleVectorDb(new SimpleVectorDbConfig { StorageType = FileSystemTypes.Disk, Directory = "vector_storage"});
kernelMemoryBuilderAzure.Services
.AddLogging(c => { c.AddConsole().SetMinimumLevel(LogLevel.Warning); });
kernelMemory = kernelMemoryBuilderAzure.Build();
}
}
#pragma warning restore 0162
// Import documents to the kernel memory / vector store if does not exist yet or reimportDocuments is set to true
if (reimportDocuments || IsDirectoryEmpty("vector_storage") && useAzureAiSearch == false)
{
await kernelMemory.DeleteIndexAsync(indexName);
await kernelMemory.ImportDocumentAsync(new Document().AddFile("rag_docs/rag_doc.txt").AddTag("topic", "documentation"));
await kernelMemory.ImportDocumentAsync(new Document().AddFile("rag_docs/process_cookbook.txt").AddTag("topic", "cookbook"));
}
}
public bool IsDirectoryEmpty(string path)
{
// check if directory exists
if (!Directory.Exists(path))
{
return true;
}
return !Directory.EnumerateFileSystemEntries(path).Any();
}
}
}