diff --git a/.github/_typos.toml b/.github/_typos.toml
index 8298df765..779f5a254 100644
--- a/.github/_typos.toml
+++ b/.github/_typos.toml
@@ -15,6 +15,7 @@ extend-exclude = [
"GPT3TokenizerTests.cs",
"CodeTokenizerTests.cs",
"test_code_tokenizer.py",
+ "CopilotChat.sln.DotSettings"
]
[default.extend-words]
diff --git a/CopilotChat.sln.DotSettings b/CopilotChat.sln.DotSettings
new file mode 100644
index 000000000..e0cd1b828
--- /dev/null
+++ b/CopilotChat.sln.DotSettings
@@ -0,0 +1,304 @@
+
+ False
+ False
+ True
+ True
+ FullFormat
+ True
+ True
+ True
+ True
+ True
+ SOLUTION
+ False
+ SUGGESTION
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ SUGGESTION
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ True
+ Field, Property, Event, Method
+ True
+ True
+ True
+ NEXT_LINE
+ True
+ True
+ True
+ True
+ True
+ True
+ 1
+ 1
+ True
+ True
+ True
+ ALWAYS
+ True
+ True
+ False
+ 512
+ True
+ Copyright (c) Microsoft. All rights reserved.
+ ACS
+ AI
+ AIGPT
+ AMQP
+ API
+ BOM
+ CORS
+ DB
+ DI
+ GPT
+ GRPC
+ HMAC
+ HTTP
+ IM
+ IO
+ IOS
+ JSON
+ JWT
+ MQ
+ MQTT
+ MS
+ MSAL
+ OCR
+ OID
+ OK
+ OS
+ PR
+ QA
+ SHA
+ SK
+ SKHTTP
+ SSL
+ TTL
+ UI
+ UID
+ URL
+ XML
+ YAML
+ False
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
+ <Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy>
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local variables"><ElementKinds><Kind Name="LOCAL_VARIABLE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local functions"><ElementKinds><Kind Name="LOCAL_FUNCTION" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Methods"><ElementKinds><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /></Policy>
+
+ 2
+ False
+ True
+ Console
+ PushToShowHints
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+ TRACE
+ 8201
+ Automatic
+ True
+ True
+ True
+ True
+ True
+ 2.0
+ InCSharpFile
+ pragma
+ True
+ #pragma warning disable CA0000 // reason
+
+#pragma warning restore CA0000
+ True
+ True
+ False
+ True
+ guid()
+ 0
+ True
+ True
+ False
+ False
+ True
+ 2.0
+ InCSharpFile
+ aaa
+ True
+ [Fact]
+public void It$SOMENAME$()
+{
+ // Arrange
+
+ // Act
+
+ // Assert
+
+}
+ True
+ True
+ MSFT copyright
+ True
+ 2.0
+ InCSharpFile
+ copy
+ // Copyright (c) Microsoft. All rights reserved.
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ DO_NOT_SHOW
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+
diff --git a/integration-tests/.editorconfig b/integration-tests/.editorconfig
new file mode 100644
index 000000000..96b5cd531
--- /dev/null
+++ b/integration-tests/.editorconfig
@@ -0,0 +1,3 @@
+[**/**.cs]
+resharper_inconsistent_naming_highlighting = none
+dotnet_diagnostic.IDE1006.severity = none # No need for Async suffix on test names
diff --git a/integration-tests/ChatCopilotIntegrationTest.cs b/integration-tests/ChatCopilotIntegrationTest.cs
index 84613fb95..44e1fff5a 100644
--- a/integration-tests/ChatCopilotIntegrationTest.cs
+++ b/integration-tests/ChatCopilotIntegrationTest.cs
@@ -24,25 +24,25 @@ public abstract class ChatCopilotIntegrationTest : IDisposable
protected const string PasswordSettingName = "TestPassword";
protected const string ScopesSettingName = "Scopes";
- protected readonly HttpClient _httpClient;
- protected readonly IConfigurationRoot configuration;
+ protected readonly HttpClient HTTPClient;
+ protected readonly IConfigurationRoot Configuration;
protected ChatCopilotIntegrationTest()
{
// Load configuration
- this.configuration = new ConfigurationBuilder()
+ this.Configuration = new ConfigurationBuilder()
.AddJsonFile(path: "testsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(path: "testsettings.development.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddUserSecrets()
.Build();
- string? baseUrl = this.configuration[BaseUrlSettingName];
+ string? baseUrl = this.Configuration[BaseUrlSettingName];
Assert.False(string.IsNullOrEmpty(baseUrl));
Assert.True(baseUrl.EndsWith('/'));
- this._httpClient = new HttpClient();
- this._httpClient.BaseAddress = new Uri(baseUrl);
+ this.HTTPClient = new HttpClient();
+ this.HTTPClient.BaseAddress = new Uri(baseUrl);
}
public void Dispose()
@@ -55,25 +55,25 @@ protected virtual void Dispose(bool disposing)
{
if (disposing)
{
- this._httpClient.Dispose();
+ this.HTTPClient.Dispose();
}
}
- protected async Task SetUpAuth()
+ protected async Task SetUpAuthAsync()
{
- string accesstoken = await this.GetUserTokenByPassword();
+ string accesstoken = await this.GetUserTokenByPasswordAsync();
Assert.True(!string.IsNullOrEmpty(accesstoken));
- this._httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken);
+ this.HTTPClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken);
}
- protected async Task GetUserTokenByPassword()
+ protected async Task GetUserTokenByPasswordAsync()
{
- IPublicClientApplication app = PublicClientApplicationBuilder.Create(this.configuration[ClientIdSettingName])
- .WithAuthority(this.configuration[AuthoritySettingName])
- .Build();
+ IPublicClientApplication app = PublicClientApplicationBuilder.Create(this.Configuration[ClientIdSettingName])
+ .WithAuthority(this.Configuration[AuthoritySettingName])
+ .Build();
- string? scopeString = this.configuration[ScopesSettingName];
+ string? scopeString = this.Configuration[ScopesSettingName];
Assert.NotNull(scopeString);
string[] scopes = scopeString.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
@@ -88,7 +88,7 @@ protected async Task GetUserTokenByPassword()
}
else
{
- result = await app.AcquireTokenByUsernamePassword(scopes, this.configuration[UsernameSettingName], this.configuration[PasswordSettingName]).ExecuteAsync();
+ result = await app.AcquireTokenByUsernamePassword(scopes, this.Configuration[UsernameSettingName], this.Configuration[PasswordSettingName]).ExecuteAsync();
}
return result?.AccessToken ?? string.Empty;
diff --git a/integration-tests/ChatCopilotIntegrationTests.csproj b/integration-tests/ChatCopilotIntegrationTests.csproj
index f9392fbf6..419e81b4f 100644
--- a/integration-tests/ChatCopilotIntegrationTests.csproj
+++ b/integration-tests/ChatCopilotIntegrationTests.csproj
@@ -15,6 +15,22 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/integration-tests/ChatTests.cs b/integration-tests/ChatTests.cs
index 6e05d5b7b..aac84f509 100644
--- a/integration-tests/ChatTests.cs
+++ b/integration-tests/ChatTests.cs
@@ -16,11 +16,11 @@ public class ChatTests : ChatCopilotIntegrationTest
[Fact]
public async void ChatMessagePostSucceedsWithValidInput()
{
- await this.SetUpAuth();
+ await this.SetUpAuthAsync();
// Create chat session
- var createChatParams = new CreateChatParameters() { Title = nameof(ChatMessagePostSucceedsWithValidInput) };
- HttpResponseMessage response = await this._httpClient.PostAsJsonAsync("chats", createChatParams);
+ var createChatParams = new CreateChatParameters() { Title = nameof(this.ChatMessagePostSucceedsWithValidInput) };
+ HttpResponseMessage response = await this.HTTPClient.PostAsJsonAsync("chats", createChatParams);
response.EnsureSuccessStatusCode();
var contentStream = await response.Content.ReadAsStreamAsync();
@@ -33,7 +33,7 @@ public async void ChatMessagePostSucceedsWithValidInput()
Input = "Who is Satya Nadella?",
Variables = new KeyValuePair[] { new("MessageType", ChatMessageType.Message.ToString()) }
};
- response = await this._httpClient.PostAsJsonAsync($"chats/{createChatResponse.ChatSession.Id}/messages", ask);
+ response = await this.HTTPClient.PostAsJsonAsync($"chats/{createChatResponse.ChatSession.Id}/messages", ask);
response.EnsureSuccessStatusCode();
contentStream = await response.Content.ReadAsStreamAsync();
@@ -41,10 +41,8 @@ public async void ChatMessagePostSucceedsWithValidInput()
Assert.NotNull(askResult);
Assert.False(string.IsNullOrEmpty(askResult.Value));
-
// Clean up
- response = await this._httpClient.DeleteAsync($"chats/{createChatResponse.ChatSession.Id}");
+ response = await this.HTTPClient.DeleteAsync($"chats/{createChatResponse.ChatSession.Id}");
response.EnsureSuccessStatusCode();
}
}
-
diff --git a/integration-tests/HealthzTests.cs b/integration-tests/HealthzTests.cs
index f14b0069e..d35a4cc9f 100644
--- a/integration-tests/HealthzTests.cs
+++ b/integration-tests/HealthzTests.cs
@@ -13,7 +13,7 @@ public class HealthzTests : ChatCopilotIntegrationTest
[Fact]
public async void HealthzSuccessfullyReturns()
{
- HttpResponseMessage response = await this._httpClient.GetAsync("healthz");
+ HttpResponseMessage response = await this.HTTPClient.GetAsync("healthz");
response.EnsureSuccessStatusCode();
}
diff --git a/integration-tests/ServiceInfoTests.cs b/integration-tests/ServiceInfoTests.cs
index 4cf8039a9..d71aac6a3 100644
--- a/integration-tests/ServiceInfoTests.cs
+++ b/integration-tests/ServiceInfoTests.cs
@@ -13,9 +13,9 @@ public class ServiceInfoTests : ChatCopilotIntegrationTest
[Fact]
public async void GetServiceInfo()
{
- await this.SetUpAuth();
+ await this.SetUpAuthAsync();
- HttpResponseMessage response = await this._httpClient.GetAsync("info/");
+ HttpResponseMessage response = await this.HTTPClient.GetAsync("info/");
response.EnsureSuccessStatusCode();
var contentStream = await response.Content.ReadAsStreamAsync();
@@ -29,7 +29,7 @@ public async void GetServiceInfo()
[Fact]
public async void GetAuthConfig()
{
- HttpResponseMessage response = await this._httpClient.GetAsync("authConfig/");
+ HttpResponseMessage response = await this.HTTPClient.GetAsync("authConfig/");
response.EnsureSuccessStatusCode();
var contentStream = await response.Content.ReadAsStreamAsync();
@@ -37,9 +37,8 @@ public async void GetAuthConfig()
Assert.NotNull(objectFromResponse);
Assert.Equal(ChatAuthenticationOptions.AuthenticationType.AzureAd.ToString(), objectFromResponse.AuthType);
- Assert.Equal(this.configuration[AuthoritySettingName], objectFromResponse.AadAuthority);
- Assert.Equal(this.configuration[ClientIdSettingName], objectFromResponse.AadClientId);
+ Assert.Equal(this.Configuration[AuthoritySettingName], objectFromResponse.AadAuthority);
+ Assert.Equal(this.Configuration[ClientIdSettingName], objectFromResponse.AadClientId);
Assert.False(string.IsNullOrEmpty(objectFromResponse.AadApiScope));
}
}
-
diff --git a/integration-tests/SpeechTokenTests.cs b/integration-tests/SpeechTokenTests.cs
index 7873aa000..337ddc234 100644
--- a/integration-tests/SpeechTokenTests.cs
+++ b/integration-tests/SpeechTokenTests.cs
@@ -12,9 +12,9 @@ public class SpeechTokenTests : ChatCopilotIntegrationTest
[Fact]
public async void GetSpeechToken()
{
- await this.SetUpAuth();
+ await this.SetUpAuthAsync();
- HttpResponseMessage response = await this._httpClient.GetAsync("speechToken/");
+ HttpResponseMessage response = await this.HTTPClient.GetAsync("speechToken/");
response.EnsureSuccessStatusCode();
var contentStream = await response.Content.ReadAsStreamAsync();
@@ -22,6 +22,6 @@ public async void GetSpeechToken()
Assert.NotNull(speechTokenResponse);
Assert.True((speechTokenResponse.IsSuccess == true && !string.IsNullOrEmpty(speechTokenResponse.Token)) ||
- speechTokenResponse.IsSuccess == false);
+ speechTokenResponse.IsSuccess == false);
}
}
diff --git a/integration-tests/StaticFiles.cs b/integration-tests/StaticFiles.cs
index 3926d2857..5c98348b1 100644
--- a/integration-tests/StaticFiles.cs
+++ b/integration-tests/StaticFiles.cs
@@ -10,11 +10,11 @@ public class StaticFiles : ChatCopilotIntegrationTest
[Fact]
public async void GetStaticFiles()
{
- HttpResponseMessage response = await this._httpClient.GetAsync("index.html");
+ HttpResponseMessage response = await this.HTTPClient.GetAsync("index.html");
response.EnsureSuccessStatusCode();
Assert.True(response.Content.Headers.ContentLength > 1);
- response = await this._httpClient.GetAsync("favicon.ico");
+ response = await this.HTTPClient.GetAsync("favicon.ico");
response.EnsureSuccessStatusCode();
Assert.True(response.Content.Headers.ContentLength > 1);
}
diff --git a/memorypipeline/CopilotChatMemoryPipeline.csproj b/memorypipeline/CopilotChatMemoryPipeline.csproj
index ebdcecd1e..3efbeb226 100644
--- a/memorypipeline/CopilotChatMemoryPipeline.csproj
+++ b/memorypipeline/CopilotChatMemoryPipeline.csproj
@@ -17,6 +17,22 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/memorypipeline/Program.cs b/memorypipeline/Program.cs
index 93157e315..8e69548b4 100644
--- a/memorypipeline/Program.cs
+++ b/memorypipeline/Program.cs
@@ -39,6 +39,7 @@
{
message += $" Environment: {environment}";
}
+
return Results.Ok(message);
});
diff --git a/memorypipeline/README.md b/memorypipeline/README.md
index 270047455..cdee60d52 100644
--- a/memorypipeline/README.md
+++ b/memorypipeline/README.md
@@ -33,7 +33,7 @@ Please refer to the [webapi README](../webapi/README.md).
#### Memorypipeline
-The memorypipeline is only needed when `SemanticMemory:DataIngestion:OrchestrationType` is set to `Distributed` in [../webapi/appsettings.json](./appsettings.json).
+The memorypipeline is only needed when `KernelMemory:DataIngestion:OrchestrationType` is set to `Distributed` in [../webapi/appsettings.json](./appsettings.json).
- Content Storage: storage solution to save the original contents. Available options:
- AzureBlobs
@@ -48,7 +48,7 @@ The memorypipeline is only needed when `SemanticMemory:DataIngestion:Orchestrati
- SimpleVectorDb
- TextFile: stores vectors on your local file system.
- Volatile: stores vectors in RAM.
- > Note that do not configure the memory pipeline to use Volatile. Use volatile in the webapi only when its `SemanticMemory:DataIngestion:OrchestrationType` is set to `InProcess`.
+ > Note that do not configure the memory pipeline to use Volatile. Use volatile in the webapi only when its `KernelMemory:DataIngestion:OrchestrationType` is set to `InProcess`.
##### AzureBlobs & AzureQueue
@@ -58,10 +58,10 @@ The memorypipeline is only needed when `SemanticMemory:DataIngestion:Orchestrati
2. Find the **connection string** under **Access keys** on the portal.
3. Run the following to set up the authentication to the resources:
```bash
- dotnet user-secrets set SemanticMemory:Services:AzureBlobs:Auth ConnectionString
- dotnet user-secrets set SemanticMemory:Services:AzureBlobs:ConnectionString [your secret]
- dotnet user-secrets set SemanticMemory:Services:AzureQueue:Auth ConnectionString
- dotnet user-secrets set SemanticMemory:Services:AzureQueue:ConnectionString [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureBlobs:Auth ConnectionString
+ dotnet user-secrets set KernelMemory:Services:AzureBlobs:ConnectionString [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureQueue:Auth ConnectionString
+ dotnet user-secrets set KernelMemory:Services:AzureQueue:ConnectionString [your secret]
```
##### [Azure Cognitive Search](https://learn.microsoft.com/en-us/azure/search/search-what-is-azure-search)
@@ -72,8 +72,8 @@ The memorypipeline is only needed when `SemanticMemory:DataIngestion:Orchestrati
2. Find the **Url** under **Overview** and the **key** under **Keys** on the portal.
3. Run the following to set up the authentication to the resources:
```bash
- dotnet user-secrets set SemanticMemory:Services:AzureAISearch:Endpoint [your secret]
- dotnet user-secrets set SemanticMemory:Services:AzureAISearch:APIKey [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureAISearch:Endpoint [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureAISearch:APIKey [your secret]
```
##### RabbitMQ
diff --git a/memorypipeline/appsettings.json b/memorypipeline/appsettings.json
index 8484c4434..6f1755a79 100644
--- a/memorypipeline/appsettings.json
+++ b/memorypipeline/appsettings.json
@@ -48,7 +48,7 @@
},
//
// Configuration for the various services used by kernel memory and semantic kernel.
- // Section names correspond to type specified in SemanticMemory section. All supported
+ // Section names correspond to type specified in KernelMemory section. All supported
// sections are listed below for reference. Only referenced sections are required.
//
"Services": {
@@ -85,7 +85,7 @@
//
"AzureBlobs": {
"Auth": "ConnectionString",
- //"ConnectionString": "", // dotnet user-secrets set "SemanticMemory:Services:AzureBlobs:ConnectionString" "MY_AZUREBLOB_CONNECTIONSTRING"
+ //"ConnectionString": "", // dotnet user-secrets set "KernelMemory:Services:AzureBlobs:ConnectionString" "MY_AZUREBLOB_CONNECTIONSTRING"
//"Account": "",
"Container": "chatmemory"
//"EndpointSuffix": "core.windows.net"
@@ -99,7 +99,7 @@
//
"AzureQueue": {
"Auth": "ConnectionString"
- //"ConnectionString": "", // dotnet user-secrets set "SemanticMemory:Services:AzureQueue:ConnectionString" "MY_AZUREQUEUE_CONNECTIONSTRING"
+ //"ConnectionString": "", // dotnet user-secrets set "KernelMemory:Services:AzureQueue:ConnectionString" "MY_AZUREQUEUE_CONNECTIONSTRING"
//"Account": "",
//"EndpointSuffix": "core.windows.net"
},
@@ -111,8 +111,8 @@
// - Port is the RabbitMq service port.
//
"RabbitMq": {
- //"Username": "user", // dotnet user-secrets set "SemanticMemory:Services:RabbitMq:Username" "MY_RABBITMQ_USER"
- //"Password": "", // dotnet user-secrets set "SemanticMemory:Services:RabbitMq:Password" "MY_RABBITMQ_KEY"
+ //"Username": "user", // dotnet user-secrets set "KernelMemory:Services:RabbitMq:Username" "MY_RABBITMQ_USER"
+ //"Password": "", // dotnet user-secrets set "KernelMemory:Services:RabbitMq:Password" "MY_RABBITMQ_KEY"
"Host": "127.0.0.1",
"Port": "5672"
},
@@ -124,7 +124,7 @@
//
"AzureAISearch": {
"Auth": "ApiKey",
- //"APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:AzureAISearch:APIKey" "MY_ACS_KEY"
+ //"APIKey": "", // dotnet user-secrets set "KernelMemory:Services:AzureAISearch:APIKey" "MY_ACS_KEY"
"Endpoint": ""
},
//
@@ -133,7 +133,7 @@
// - Endpoint is the service endpoint url.
//
"Qdrant": {
- //"APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:Qdrant:APIKey" "MY_QDRANT_KEY"
+ //"APIKey": "", // dotnet user-secrets set "KernelMemory:Services:Qdrant:APIKey" "MY_QDRANT_KEY"
"Endpoint": "http://127.0.0.1:6333"
},
//
@@ -147,7 +147,7 @@
//
"AzureOpenAIText": {
"Auth": "ApiKey",
- //"APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:AzureOpenAIText:APIKey" "MY_AZUREOPENAI_KEY"
+ //"APIKey": "", // dotnet user-secrets set "KernelMemory:Services:AzureOpenAIText:APIKey" "MY_AZUREOPENAI_KEY"
"Endpoint": "",
"Deployment": "gpt-4o",
"APIType": "ChatCompletion",
@@ -162,7 +162,7 @@
//
"AzureOpenAIEmbedding": {
"Auth": "ApiKey",
- // "APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:AzureOpenAIEmbedding:APIKey" "MY_AZUREOPENAI_KEY"
+ // "APIKey": "", // dotnet user-secrets set "KernelMemory:Services:AzureOpenAIEmbedding:APIKey" "MY_AZUREOPENAI_KEY"
"Endpoint": ".openai.azure.com/",
"Deployment": "text-embedding-ada-002"
},
@@ -177,7 +177,7 @@
"OpenAI": {
"TextModel": "gpt-3.5-turbo",
"EmbeddingModel": "text-embedding-ada-002",
- //"APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:OpenAI:APIKey" "MY_OPENAI_KEY"
+ //"APIKey": "", // dotnet user-secrets set "KernelMemory:Services:OpenAI:APIKey" "MY_OPENAI_KEY"
"OrgId": "",
"MaxRetries": 10
},
@@ -189,14 +189,14 @@
//
"AzureAIDocIntel": {
"Auth": "APIKey",
- //"APIKey": "", // dotnet user-secrets set "SemanticMemory:Services:AzureAIDocIntel:APIKey" "MY_AZURE_AI_DOC_INTEL_KEY"
+ //"APIKey": "", // dotnet user-secrets set "KernelMemory:Services:AzureAIDocIntel:APIKey" "MY_AZURE_AI_DOC_INTEL_KEY"
"Endpoint": ""
},
//
// Tesseract configuration for memory pipeline OCR.
// - Language is the language supported by the data file.
// - FilePath is the path to the data file.
- //
+ //
// Note: When using Tesseract OCR Support (In order to upload image file formats such as png, jpg and tiff):
// 1. Obtain language data files here: https://github.com/tesseract-ocr/tessdata .
// 2. Add these files to your `data` folder or the path specified in the "FilePath" property and set the "Copy to Output Directory" value to "Copy if newer".
diff --git a/plugins/shared/PluginShared.csproj b/plugins/shared/PluginShared.csproj
index cd1e84cb9..609406c1f 100644
--- a/plugins/shared/PluginShared.csproj
+++ b/plugins/shared/PluginShared.csproj
@@ -6,4 +6,23 @@
Plugins.PluginShared
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
\ No newline at end of file
diff --git a/plugins/web-searcher/Models/BingSearchResponse.cs b/plugins/web-searcher/Models/BingSearchResponse.cs
index d2310b8e2..02e2ebc95 100644
--- a/plugins/web-searcher/Models/BingSearchResponse.cs
+++ b/plugins/web-searcher/Models/BingSearchResponse.cs
@@ -22,7 +22,7 @@ internal sealed class WebPage
public string Url { get; set; } = string.Empty;
///
- /// A snippet of text from the webpage that describes its contents.
+ /// A snippet of text from the webpage that describes its contents.
///
[JsonPropertyName("snippet")]
public string Snippet { get; set; } = string.Empty;
diff --git a/plugins/web-searcher/PluginEndpoint.cs b/plugins/web-searcher/PluginEndpoint.cs
index 101efce0d..589ad59cd 100644
--- a/plugins/web-searcher/PluginEndpoint.cs
+++ b/plugins/web-searcher/PluginEndpoint.cs
@@ -7,7 +7,6 @@
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
@@ -44,8 +43,9 @@ public PluginEndpoint(PluginConfig config, ILogger logger)
/// The http request data.
/// The manifest in Json
[Function("WellKnownAIPluginManifest")]
- public async Task WellKnownAIPluginManifest(
- [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = ".well-known/ai-plugin.json")] HttpRequestData req)
+ public async Task WellKnownAIPluginManifestAsync(
+ [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = ".well-known/ai-plugin.json")]
+ HttpRequestData req)
{
var pluginManifest = new PluginManifest()
{
@@ -76,8 +76,9 @@ public async Task WellKnownAIPluginManifest(
/// The http request data.
/// The icon.
[Function("Icon")]
- public async Task Icon(
- [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = ".well-known/icon")] HttpRequestData req)
+ public async Task IconAsync(
+ [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = ".well-known/icon")]
+ HttpRequestData req)
{
if (!File.Exists("./Icons/bing.png"))
{
@@ -107,7 +108,7 @@ public async Task Icon(
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "Returns a collection of search results with the name, URL and snippet for each.")]
[OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Description = "Invalid query")]
[Function("WebSearch")]
- public async Task WebSearch([HttpTrigger(AuthorizationLevel.Function, "get", Route = "search")] HttpRequestData req)
+ public async Task WebSearchAsync([HttpTrigger(AuthorizationLevel.Function, "get", Route = "search")] HttpRequestData req)
{
var queries = QueryHelpers.ParseQuery(req.Url.Query);
var query = queries.ContainsKey("Query") ? queries["Query"].ToString() : string.Empty;
@@ -145,7 +146,6 @@ public async Task WebSearch([HttpTrigger(AuthorizationLevel.Fu
queryString += $"&count={numResults}";
queryString += $"&offset={offset}";
-
var uri = new Uri($"{this._config.BingApiBaseUrl}{queryString}");
this._logger.LogDebug("Sending request to {0}", uri);
diff --git a/plugins/web-searcher/WebSearcher.csproj b/plugins/web-searcher/WebSearcher.csproj
index 48c03d543..57c9321e2 100644
--- a/plugins/web-searcher/WebSearcher.csproj
+++ b/plugins/web-searcher/WebSearcher.csproj
@@ -13,6 +13,22 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/shared/CopilotChatShared.csproj b/shared/CopilotChatShared.csproj
index aadf642c7..32324f3dd 100644
--- a/shared/CopilotChatShared.csproj
+++ b/shared/CopilotChatShared.csproj
@@ -13,6 +13,22 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/shared/MemoryClientBuilderExtensions.cs b/shared/MemoryClientBuilderExtensions.cs
index e9d3f215a..3a54bd577 100644
--- a/shared/MemoryClientBuilderExtensions.cs
+++ b/shared/MemoryClientBuilderExtensions.cs
@@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
+
using CopilotChat.Shared.Ocr;
using Microsoft.Extensions.Configuration;
using Microsoft.KernelMemory;
diff --git a/shared/MemoryConfiguration.cs b/shared/MemoryConfiguration.cs
index 1af975096..285d12fce 100644
--- a/shared/MemoryConfiguration.cs
+++ b/shared/MemoryConfiguration.cs
@@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
+
namespace CopilotChat.Shared;
///
diff --git a/shared/ServiceConfiguration.cs b/shared/ServiceConfiguration.cs
index 5d189d40d..3507469cb 100644
--- a/shared/ServiceConfiguration.cs
+++ b/shared/ServiceConfiguration.cs
@@ -38,7 +38,7 @@ public ServiceConfiguration(string? settingsDirectory = null)
public ServiceConfiguration(IConfiguration rawAppSettings)
: this(rawAppSettings,
rawAppSettings.GetSection(ConfigRoot).Get()
- ?? throw new ConfigurationException($"Unable to load Kernel Memory settings from the given configuration. " +
+ ?? throw new ConfigurationException("Unable to load Kernel Memory settings from the given configuration. " +
$"There should be a '{ConfigRoot}' root node, " +
$"with data mapping to '{nameof(KernelMemoryConfig)}'"))
{
diff --git a/tools/importdocument/ImportDocument.csproj b/tools/importdocument/ImportDocument.csproj
index 80eb3c9f4..f8b6c5919 100644
--- a/tools/importdocument/ImportDocument.csproj
+++ b/tools/importdocument/ImportDocument.csproj
@@ -19,6 +19,22 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/tools/importdocument/Program.cs b/tools/importdocument/Program.cs
index 8b0570470..3d9c89c8a 100644
--- a/tools/importdocument/Program.cs
+++ b/tools/importdocument/Program.cs
@@ -113,7 +113,8 @@ private static async Task ImportFilesAsync(IEnumerable files, Config c
Console.WriteLine("Error: Failed to acquire access token.");
return;
}
- Console.WriteLine($"Successfully acquired access token. Continuing...");
+
+ Console.WriteLine("Successfully acquired access token. Continuing...");
}
using var formContent = new MultipartFormDataContent();
@@ -123,7 +124,6 @@ private static async Task ImportFilesAsync(IEnumerable files, Config c
formContent.Add(filesContent[i], "formFiles", files.ElementAt(i).Name);
}
-
if (chatCollectionId != Guid.Empty)
{
Console.WriteLine($"Uploading and parsing file to chat {chatCollectionId}...");
@@ -163,9 +163,7 @@ async Task UploadAsync(Guid? chatId = null)
}
string uriPath =
- chatId.HasValue ?
- $"chats/{chatId}/documents" :
- "documents";
+ chatId.HasValue ? $"chats/{chatId}/documents" : "documents";
try
{
diff --git a/webapi/Auth/AuthInfo.cs b/webapi/Auth/AuthInfo.cs
index b4b60e3a8..5a0e00ec0 100644
--- a/webapi/Auth/AuthInfo.cs
+++ b/webapi/Auth/AuthInfo.cs
@@ -27,21 +27,24 @@ public AuthInfo(IHttpContextAccessor httpContextAccessor)
{
throw new InvalidOperationException("HttpContext must be present to inspect auth info.");
}
+
var userIdClaim = user.FindFirst(ClaimConstants.Oid)
- ?? user.FindFirst(ClaimConstants.ObjectId)
- ?? user.FindFirst(ClaimConstants.Sub)
- ?? user.FindFirst(ClaimConstants.NameIdentifierId);
+ ?? user.FindFirst(ClaimConstants.ObjectId)
+ ?? user.FindFirst(ClaimConstants.Sub)
+ ?? user.FindFirst(ClaimConstants.NameIdentifierId);
if (userIdClaim is null)
{
throw new CredentialUnavailableException("User Id was not present in the request token.");
}
+
var tenantIdClaim = user.FindFirst(ClaimConstants.Tid)
- ?? user.FindFirst(ClaimConstants.TenantId);
+ ?? user.FindFirst(ClaimConstants.TenantId);
var userNameClaim = user.FindFirst(ClaimConstants.Name);
if (userNameClaim is null)
{
throw new CredentialUnavailableException("User name was not present in the request token.");
}
+
return new AuthData
{
UserId = (tenantIdClaim is null) ? userIdClaim.Value : string.Join(".", userIdClaim.Value, tenantIdClaim.Value),
diff --git a/webapi/Controllers/ChatController.cs b/webapi/Controllers/ChatController.cs
index 74d7e4297..f1340e215 100644
--- a/webapi/Controllers/ChatController.cs
+++ b/webapi/Controllers/ChatController.cs
@@ -203,27 +203,27 @@ private async Task RegisterFunctionsAsync(Kernel kernel, Dictionary();
// GitHub
- if (authHeaders.TryGetValue("GITHUB", out string? GithubAuthHeader))
+ if (authHeaders.TryGetValue("GITHUB", out string? githubAuthHeader))
{
- tasks.Add(this.RegisterGithubPlugin(kernel, GithubAuthHeader));
+ tasks.Add(this.RegisterGithubPluginAsync(kernel, githubAuthHeader));
}
// Jira
- if (authHeaders.TryGetValue("JIRA", out string? JiraAuthHeader))
+ if (authHeaders.TryGetValue("JIRA", out string? jiraAuthHeader))
{
- tasks.Add(this.RegisterJiraPlugin(kernel, JiraAuthHeader, variables));
+ tasks.Add(this.RegisterJiraPluginAsync(kernel, jiraAuthHeader, variables));
}
// Microsoft Graph
- if (authHeaders.TryGetValue("GRAPH", out string? GraphAuthHeader))
+ if (authHeaders.TryGetValue("GRAPH", out string? graphAuthHeader))
{
- tasks.Add(this.RegisterMicrosoftGraphPlugins(kernel, GraphAuthHeader));
+ tasks.Add(this.RegisterMicrosoftGraphPlugins(kernel, graphAuthHeader));
}
// Microsoft Graph OBO
- if (authHeaders.TryGetValue("MSGRAPHOBO", out string? GraphOboAuthHeader))
+ if (authHeaders.TryGetValue("MSGRAPHOBO", out string? graphOboAuthHeader))
{
- tasks.Add(this.RegisterMicrosoftGraphOBOPlugins(kernel, GraphOboAuthHeader));
+ tasks.Add(this.RegisterMicrosoftGraphOBOPlugins(kernel, graphOboAuthHeader));
}
if (variables.TryGetValue("customPlugins", out object? customPluginsString))
@@ -234,10 +234,10 @@ private async Task RegisterFunctionsAsync(Kernel kernel, Dictionary Task.FromResult(GithubAuthHeader));
+ BearerAuthenticationProvider authenticationProvider = new(() => Task.FromResult(githubAuthHeader));
await kernel.ImportPluginFromOpenApiAsync(
pluginName: "GitHubPlugin",
filePath: GetPluginFullPath("GitHubPlugin/openapi.json"),
@@ -247,10 +247,10 @@ await kernel.ImportPluginFromOpenApiAsync(
});
}
- private async Task RegisterJiraPlugin(Kernel kernel, string JiraAuthHeader, KernelArguments variables)
+ private async Task RegisterJiraPluginAsync(Kernel kernel, string jiraAuthHeader, KernelArguments variables)
{
this._logger.LogInformation("Registering Jira plugin");
- var authenticationProvider = new BasicAuthenticationProvider(() => { return Task.FromResult(JiraAuthHeader); });
+ var authenticationProvider = new BasicAuthenticationProvider(() => { return Task.FromResult(jiraAuthHeader); });
var hasServerUrlOverride = variables.TryGetValue("jira-server-url", out object? serverUrlOverride);
await kernel.ImportPluginFromOpenApiAsync(
@@ -260,13 +260,15 @@ await kernel.ImportPluginFromOpenApiAsync(
{
AuthCallback = authenticationProvider.AuthenticateRequestAsync,
ServerUrlOverride = hasServerUrlOverride ? new Uri(serverUrlOverride!.ToString()!) : null,
- }); ; ;
+ });
+ ;
+ ;
}
- private Task RegisterMicrosoftGraphPlugins(Kernel kernel, string GraphAuthHeader)
+ private Task RegisterMicrosoftGraphPlugins(Kernel kernel, string graphAuthHeader)
{
this._logger.LogInformation("Enabling Microsoft Graph plugin(s).");
- BearerAuthenticationProvider authenticationProvider = new(() => Task.FromResult(GraphAuthHeader));
+ BearerAuthenticationProvider authenticationProvider = new(() => Task.FromResult(graphAuthHeader));
GraphServiceClient graphServiceClient = this.CreateGraphServiceClient(authenticationProvider.GraphClientAuthenticateRequestAsync);
kernel.ImportPluginFromObject(new TaskListPlugin(new MicrosoftToDoConnector(graphServiceClient)), "todo");
@@ -275,11 +277,11 @@ private Task RegisterMicrosoftGraphPlugins(Kernel kernel, string GraphAuthHeader
return Task.CompletedTask;
}
- private Task RegisterMicrosoftGraphOBOPlugins(Kernel kernel, string GraphOboAuthHeader)
+ private Task RegisterMicrosoftGraphOBOPlugins(Kernel kernel, string graphOboAuthHeader)
{
this._logger.LogInformation("Enabling Microsoft Graph OBO plugin(s).");
kernel.ImportPluginFromObject(
- new MsGraphOboPlugin(GraphOboAuthHeader, this._httpClientFactory, this._msGraphOboPluginOptions, this._promptsOptions.FunctionCallingTokenLimit, this._logger),
+ new MsGraphOboPlugin(graphOboAuthHeader, this._httpClientFactory, this._msGraphOboPluginOptions, this._promptsOptions.FunctionCallingTokenLimit, this._logger),
"msGraphObo");
return Task.CompletedTask;
}
@@ -292,16 +294,17 @@ private IEnumerable RegisterCustomPlugins(Kernel kernel, object? customPlu
{
foreach (CustomPlugin plugin in customPlugins)
{
- if (authHeaders.TryGetValue(plugin.AuthHeaderTag.ToUpperInvariant(), out string? PluginAuthValue))
+ if (authHeaders.TryGetValue(plugin.AuthHeaderTag.ToUpperInvariant(), out string? pluginAuthValue))
{
// Register the ChatGPT plugin with the kernel.
this._logger.LogInformation("Enabling {0} plugin.", plugin.NameForHuman);
// TODO: [Issue #44] Support other forms of auth. Currently, we only support user PAT or no auth.
var requiresAuth = !plugin.AuthType.Equals("none", StringComparison.OrdinalIgnoreCase);
- Task authCallback(HttpRequestMessage request, string _, OpenAIAuthenticationConfig __, CancellationToken ___ = default)
+
+ Task AuthCallback(HttpRequestMessage request, string _, OpenAIAuthenticationConfig __, CancellationToken ___ = default)
{
- request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", PluginAuthValue);
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", pluginAuthValue);
return Task.CompletedTask;
}
@@ -313,7 +316,7 @@ Task authCallback(HttpRequestMessage request, string _, OpenAIAuthenticationConf
{
HttpClient = this._httpClientFactory.CreateClient(),
IgnoreNonCompliantErrors = true,
- AuthCallback = requiresAuth ? authCallback : null
+ AuthCallback = requiresAuth ? AuthCallback : null
});
}
}
@@ -352,7 +355,7 @@ private async Task RegisterHostedFunctionsAsync(Kernel kernel, HashSet e
{
this._logger.LogDebug("Enabling hosted plugin {0}.", plugin.Name);
- Task authCallback(HttpRequestMessage request, string _, OpenAIAuthenticationConfig __, CancellationToken ___ = default)
+ Task AuthCallback(HttpRequestMessage request, string _, OpenAIAuthenticationConfig __, CancellationToken ___ = default)
{
request.Headers.Add("X-Functions-Key", plugin.Key);
@@ -367,7 +370,7 @@ await kernel.ImportPluginFromOpenAIAsync(
{
HttpClient = this._httpClientFactory.CreateClient(),
IgnoreNonCompliantErrors = true,
- AuthCallback = authCallback
+ AuthCallback = AuthCallback
});
}
else
diff --git a/webapi/Controllers/ChatMemoryController.cs b/webapi/Controllers/ChatMemoryController.cs
index adc57ae74..be1f7b8f3 100644
--- a/webapi/Controllers/ChatMemoryController.cs
+++ b/webapi/Controllers/ChatMemoryController.cs
@@ -49,7 +49,7 @@ public ChatMemoryController(
///
/// Gets the kernel memory for the chat session.
///
- /// The semantic text memory instance.
+ /// The kernel memory client.
/// The chat id.
/// Type of memory. Must map to a member of .
[HttpGet]
diff --git a/webapi/Controllers/DocumentController.cs b/webapi/Controllers/DocumentController.cs
index d2279fbb0..48c9fe565 100644
--- a/webapi/Controllers/DocumentController.cs
+++ b/webapi/Controllers/DocumentController.cs
@@ -143,7 +143,7 @@ private async Task DocumentImportAsync(
var importResults = await this.ImportDocumentsAsync(memoryClient, chatId, documentImportForm, documentMessageContent);
- var chatMessage = await this.TryCreateDocumentUploadMessage(chatId, documentMessageContent);
+ var chatMessage = await this.TryCreateDocumentUploadMessageAsync(chatId, documentMessageContent);
if (chatMessage == null)
{
@@ -295,7 +295,7 @@ private async Task ValidateDocumentImportFormAsync(Guid chatId, DocumentScopes s
{
// Make sure the user has access to the chat session if the document is uploaded to a chat session.
if (scope == DocumentScopes.Chat
- && !(await this.UserHasAccessToChatAsync(this._authInfo.UserId, chatId)))
+ && !(await this.UserHasAccessToChatAsync(this._authInfo.UserId, chatId)))
{
throw new ArgumentException("User does not have access to the chat session.");
}
@@ -369,7 +369,7 @@ private async Task ValidateDocumentStatusFormAsync(DocumentStatusForm documentSt
{
// Make sure the user has access to the chat session if the document is uploaded to a chat session.
if (documentStatusForm.DocumentScope == DocumentScopes.Chat
- && !(await this.UserHasAccessToChatAsync(documentStatusForm.UserId, documentStatusForm.ChatId)))
+ && !(await this.UserHasAccessToChatAsync(documentStatusForm.UserId, documentStatusForm.ChatId)))
{
throw new ArgumentException("User does not have access to the chat session.");
}
@@ -455,7 +455,7 @@ private async Task TryStoreMemoryAsync(MemorySource memorySource)
/// The target chat-id
/// The document message content
/// A ChatMessage object if successful, null otherwise
- private async Task TryCreateDocumentUploadMessage(
+ private async Task TryCreateDocumentUploadMessageAsync(
Guid chatId,
DocumentMessageContent messageContent)
{
diff --git a/webapi/Controllers/PluginController.cs b/webapi/Controllers/PluginController.cs
index 6a795fc31..be2ad8feb 100644
--- a/webapi/Controllers/PluginController.cs
+++ b/webapi/Controllers/PluginController.cs
@@ -48,9 +48,9 @@ public PluginController(
/// The domain of the manifest.
/// The plugin's manifest JSON.
[HttpGet]
- [Route("pluginManifests")]
+ [Route("pluginManifests")] // TODO: Fix name and test - use singular?
[ProducesResponseType(StatusCodes.Status200OK)]
- public async Task GetPluginManifest([FromQuery] Uri manifestDomain)
+ public async Task GetPluginManifestAsync([FromQuery] Uri manifestDomain)
{
using var request = new HttpRequestMessage(HttpMethod.Get, PluginUtils.GetPluginManifestUri(manifestDomain));
// Need to set the user agent to avoid 403s from some sites.
diff --git a/webapi/Controllers/ServiceInfoController.cs b/webapi/Controllers/ServiceInfoController.cs
index 0f2ee8f5c..b7a2b961f 100644
--- a/webapi/Controllers/ServiceInfoController.cs
+++ b/webapi/Controllers/ServiceInfoController.cs
@@ -24,13 +24,11 @@ namespace CopilotChat.WebApi.Controllers;
public class ServiceInfoController : ControllerBase
{
private readonly ILogger _logger;
-
- private readonly IConfiguration Configuration;
-
- private readonly KernelMemoryConfig memoryOptions;
+ private readonly IConfiguration _configuration;
+ private readonly KernelMemoryConfig _memoryOptions;
private readonly ChatAuthenticationOptions _chatAuthenticationOptions;
private readonly FrontendOptions _frontendOptions;
- private readonly IEnumerable availablePlugins;
+ private readonly IEnumerable _availablePlugins;
private readonly ContentSafetyOptions _contentSafetyOptions;
public ServiceInfoController(
@@ -43,11 +41,11 @@ public ServiceInfoController(
IOptions contentSafetyOptions)
{
this._logger = logger;
- this.Configuration = configuration;
- this.memoryOptions = memoryOptions.Value;
+ this._configuration = configuration;
+ this._memoryOptions = memoryOptions.Value;
this._chatAuthenticationOptions = chatAuthenticationOptions.Value;
this._frontendOptions = frontendOptions.Value;
- this.availablePlugins = this.SanitizePlugins(availablePlugins);
+ this._availablePlugins = this.SanitizePlugins(availablePlugins);
this._contentSafetyOptions = contentSafetyOptions.Value;
}
@@ -64,9 +62,9 @@ public IActionResult GetServiceInfo()
MemoryStore = new MemoryStoreInfoResponse()
{
Types = Enum.GetNames(typeof(MemoryStoreType)),
- SelectedType = this.memoryOptions.GetMemoryStoreType(this.Configuration).ToString(),
+ SelectedType = this._memoryOptions.GetMemoryStoreType(this._configuration).ToString(),
},
- AvailablePlugins = this.availablePlugins,
+ AvailablePlugins = this._availablePlugins,
Version = GetAssemblyFileVersion(),
IsContentSafetyEnabled = this._contentSafetyOptions.Enabled
};
diff --git a/webapi/CopilotChatWebApi.csproj b/webapi/CopilotChatWebApi.csproj
index 29b8106e9..47da146b1 100644
--- a/webapi/CopilotChatWebApi.csproj
+++ b/webapi/CopilotChatWebApi.csproj
@@ -57,17 +57,17 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/webapi/Extensions/IAsyncEnumerableExtensions.cs b/webapi/Extensions/AsyncEnumerableExtensions.cs
similarity index 93%
rename from webapi/Extensions/IAsyncEnumerableExtensions.cs
rename to webapi/Extensions/AsyncEnumerableExtensions.cs
index af09b1904..f50a4b593 100644
--- a/webapi/Extensions/IAsyncEnumerableExtensions.cs
+++ b/webapi/Extensions/AsyncEnumerableExtensions.cs
@@ -8,7 +8,7 @@ namespace CopilotChat.WebApi.Extensions;
///
/// Extension methods for enabling async LINQ operations on IAsyncEnumerable sequence.
///
-public static class IAsyncEnumerableExtensions
+public static class AsyncEnumerableExtensions
{
///
/// Creates a List from an IAsyncEnumerable by enumerating it asynchronously.
diff --git a/webapi/Extensions/ISemanticMemoryClientExtensions.cs b/webapi/Extensions/KernelMemoryClientExtensions.cs
similarity index 94%
rename from webapi/Extensions/ISemanticMemoryClientExtensions.cs
rename to webapi/Extensions/KernelMemoryClientExtensions.cs
index 02b17d872..77e147bb7 100644
--- a/webapi/Extensions/ISemanticMemoryClientExtensions.cs
+++ b/webapi/Extensions/KernelMemoryClientExtensions.cs
@@ -19,14 +19,14 @@ namespace CopilotChat.WebApi.Extensions;
///
/// Extension methods for and service registration.
///
-internal static class ISemanticMemoryClientExtensions
+internal static class KernelMemoryClientExtensions
{
- private static readonly List pipelineSteps = new() { "extract", "partition", "gen_embeddings", "save_records" };
+ private static readonly List s_pipelineSteps = new() { "extract", "partition", "gen_embeddings", "save_records" };
///
/// Inject .
///
- public static void AddSemanticMemoryServices(this WebApplicationBuilder appBuilder)
+ public static void AddKernelMemoryServices(this WebApplicationBuilder appBuilder)
{
var serviceProvider = appBuilder.Services.BuildServiceProvider();
@@ -122,7 +122,7 @@ public static async Task StoreDocumentAsync(
DocumentId = documentId,
Files = new List { new(fileName, fileContent) },
Index = indexName,
- Steps = pipelineSteps,
+ Steps = s_pipelineSteps,
};
uploadRequest.Tags.Add(MemoryTags.TagChatId, chatId);
@@ -167,7 +167,7 @@ public static async Task StoreMemoryAsync(
// Document file name not relevant, but required.
new DocumentUploadRequest.UploadedFile("memory.txt", stream)
},
- Steps = pipelineSteps,
+ Steps = s_pipelineSteps,
};
uploadRequest.Tags.Add(MemoryTags.TagChatId, chatId);
diff --git a/webapi/Extensions/SemanticKernelExtensions.cs b/webapi/Extensions/SemanticKernelExtensions.cs
index 0bafb441b..219a42172 100644
--- a/webapi/Extensions/SemanticKernelExtensions.cs
+++ b/webapi/Extensions/SemanticKernelExtensions.cs
@@ -236,7 +236,7 @@ private static ChatArchiveEmbeddingConfig WithBotConfig(this IServiceProvider pr
};
default:
- throw new ArgumentException($"Invalid {nameof(memoryOptions.Retrieval.EmbeddingGeneratorType)} value in 'SemanticMemory' settings.");
+ throw new ArgumentException($"Invalid {nameof(memoryOptions.Retrieval.EmbeddingGeneratorType)} value in 'KernelMemory' settings.");
}
}
}
diff --git a/webapi/Extensions/ServiceExtensions.cs b/webapi/Extensions/ServiceExtensions.cs
index f5837a4f8..4b8d6e790 100644
--- a/webapi/Extensions/ServiceExtensions.cs
+++ b/webapi/Extensions/ServiceExtensions.cs
@@ -109,6 +109,7 @@ internal static IServiceCollection AddPlugins(this IServiceCollection services,
{
throw new InvalidOperationException($"Plugin '{plugin.Name}' at '{pluginManifestUrl}' returned status code '{response.StatusCode}'.");
}
+
validatedPlugins.Add(plugin.Name, plugin);
logger.LogInformation("Added plugin: {0}.", plugin.Name);
}
diff --git a/webapi/Models/Request/CreateChatParameters.cs b/webapi/Models/Request/CreateChatParameters.cs
index 0d8a32404..921e3508d 100644
--- a/webapi/Models/Request/CreateChatParameters.cs
+++ b/webapi/Models/Request/CreateChatParameters.cs
@@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
+
using System.Text.Json.Serialization;
namespace CopilotChat.WebApi.Models.Request;
diff --git a/webapi/Models/Request/CustomPlugin.cs b/webapi/Models/Request/CustomPlugin.cs
index b0872e4d0..027257ed5 100644
--- a/webapi/Models/Request/CustomPlugin.cs
+++ b/webapi/Models/Request/CustomPlugin.cs
@@ -1,4 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
+
using System.Text.Json.Serialization;
namespace CopilotChat.WebApi.Models.Request;
diff --git a/webapi/Models/Storage/CitationSource.cs b/webapi/Models/Storage/CitationSource.cs
index 466687bc2..626db6f28 100644
--- a/webapi/Models/Storage/CitationSource.cs
+++ b/webapi/Models/Storage/CitationSource.cs
@@ -39,7 +39,7 @@ public class CitationSource
///
/// Converts a to a .
///
- public static CitationSource FromSemanticMemoryCitation(Citation citation, string snippet, double relevanceScore)
+ public static CitationSource FromKernelMemoryCitation(Citation citation, string snippet, double relevanceScore)
{
var citationSource = new CitationSource
{
diff --git a/webapi/Models/Storage/CopilotChatMessage.cs b/webapi/Models/Storage/CopilotChatMessage.cs
index c0aa13a98..16eb1351c 100644
--- a/webapi/Models/Storage/CopilotChatMessage.cs
+++ b/webapi/Models/Storage/CopilotChatMessage.cs
@@ -15,7 +15,7 @@ namespace CopilotChat.WebApi.Models.Storage;
///
public class CopilotChatMessage : IStorageEntity
{
- private static readonly JsonSerializerOptions SerializerSettings = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
+ private static readonly JsonSerializerOptions s_serializerSettings = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
///
/// Role of the author of a chat message.
@@ -190,7 +190,7 @@ public string ToFormattedString()
return $"{messagePrefix} {this.UserName} uploaded: {documentMessageContent}";
- case ChatMessageType.Plan: // Fall through
+ case ChatMessageType.Plan: // Fall through
case ChatMessageType.Message:
return $"{messagePrefix} {this.UserName} said: {this.Content}";
@@ -206,7 +206,7 @@ public string ToFormattedString()
/// A serialized json string
public override string ToString()
{
- return JsonSerializer.Serialize(this, SerializerSettings);
+ return JsonSerializer.Serialize(this, s_serializerSettings);
}
///
@@ -216,6 +216,6 @@ public override string ToString()
/// A ChatMessage object
public static CopilotChatMessage? FromString(string json)
{
- return JsonSerializer.Deserialize(json, SerializerSettings);
+ return JsonSerializer.Deserialize(json, s_serializerSettings);
}
}
diff --git a/webapi/Options/ContentSafetyOptions.cs b/webapi/Options/ContentSafetyOptions.cs
index 8374367b3..57afe5438 100644
--- a/webapi/Options/ContentSafetyOptions.cs
+++ b/webapi/Options/ContentSafetyOptions.cs
@@ -1,6 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.
-using System;
using System.ComponentModel.DataAnnotations;
namespace CopilotChat.WebApi.Options;
diff --git a/webapi/Options/MsGraphOboPluginOptions.cs b/webapi/Options/MsGraphOboPluginOptions.cs
index c55fa6aaf..1352421eb 100644
--- a/webapi/Options/MsGraphOboPluginOptions.cs
+++ b/webapi/Options/MsGraphOboPluginOptions.cs
@@ -5,18 +5,22 @@ namespace CopilotChat.WebApi.Options;
public class MsGraphOboPluginOptions
{
public const string PropertyName = "OnBehalfOf";
+
///
/// The authority to use for OBO Auth.
///
public string? Authority { get; set; }
+
///
/// The Tenant Id to use for OBO Auth.
///
public string? TenantId { get; set; }
+
///
/// The Client Id to use for OBO Auth.
///
public string? ClientId { get; set; }
+
///
/// The Client Secret to use for OBO Auth.
///
diff --git a/webapi/Options/PromptsOptions.cs b/webapi/Options/PromptsOptions.cs
index 636bb1344..0f8c9cf29 100644
--- a/webapi/Options/PromptsOptions.cs
+++ b/webapi/Options/PromptsOptions.cs
@@ -40,13 +40,13 @@ public class PromptsOptions
/// Upper bound of relevance score of a kernel memory to be included in the final prompt.
/// The actual relevancy score is determined by the memory balance.
///
- internal float SemanticMemoryRelevanceUpper { get; } = 0.9F;
+ internal float KernelMemoryRelevanceUpper { get; } = 0.9F;
///
/// Lower bound of relevance score of a kernel memory to be included in the final prompt.
/// The actual relevancy score is determined by the memory balance.
///
- internal float SemanticMemoryRelevanceLower { get; } = 0.6F;
+ internal float KernelMemoryRelevanceLower { get; } = 0.6F;
///
/// Minimum relevance of a document memory to be included in the final prompt.
diff --git a/webapi/Plugins/Chat/ChatPlugin.cs b/webapi/Plugins/Chat/ChatPlugin.cs
index e5db7be92..6b29afcb0 100644
--- a/webapi/Plugins/Chat/ChatPlugin.cs
+++ b/webapi/Plugins/Chat/ChatPlugin.cs
@@ -72,7 +72,7 @@ public class ChatPlugin
///
/// A kernel memory retriever instance to query semantic memories.
///
- private readonly SemanticMemoryRetriever _semanticMemoryRetriever;
+ private readonly KernelMemoryRetriever _kernelMemoryRetriever;
///
/// Azure content safety moderator.
@@ -102,7 +102,7 @@ public ChatPlugin(
// Clone the prompt options to avoid modifying the original prompt options.
this._promptOptions = promptOptions.Value.Copy();
- this._semanticMemoryRetriever = new SemanticMemoryRetriever(promptOptions, chatSessionRepository, memoryClient, logger);
+ this._kernelMemoryRetriever = new KernelMemoryRetriever(promptOptions, chatSessionRepository, memoryClient, logger);
this._contentSafety = contentSafety;
}
@@ -115,8 +115,10 @@ public ChatPlugin(
/// The cancellation token.
[KernelFunction, Description("Extract chat history")]
public Task ExtractChatHistory(
- [Description("Chat ID to extract history from")] string chatId,
- [Description("Maximum number of tokens")] int tokenLimit,
+ [Description("Chat ID to extract history from")]
+ string chatId,
+ [Description("Maximum number of tokens")]
+ int tokenLimit,
CancellationToken cancellationToken = default)
{
return this.GetAllowedChatHistoryAsync(chatId, tokenLimit, cancellationToken: cancellationToken);
@@ -166,8 +168,8 @@ private async Task GetAllowedChatHistoryAsync(
{
// Omit user name if Auth is disabled.
var userMessage = PassThroughAuthenticationHandler.IsDefaultUser(chatMessage.UserId)
- ? $"[{chatMessage.Timestamp.ToString("G", CultureInfo.CurrentCulture)}] {chatMessage.Content}"
- : formattedMessage;
+ ? $"[{chatMessage.Timestamp.ToString("G", CultureInfo.CurrentCulture)}] {chatMessage.Content}"
+ : formattedMessage;
allottedChatHistory.AddUserMessage(userMessage.Trim());
}
@@ -193,9 +195,11 @@ private async Task GetAllowedChatHistoryAsync(
[KernelFunction, Description("Get chat response")]
public async Task ChatAsync(
[Description("The new message")] string message,
- [Description("Unique and persistent identifier for the user")] string userId,
+ [Description("Unique and persistent identifier for the user")]
+ string userId,
[Description("Name of the user")] string userName,
- [Description("Unique and persistent identifier for the chat")] string chatId,
+ [Description("Unique and persistent identifier for the chat")]
+ string chatId,
[Description("Type of the message")] string messageType,
KernelArguments context,
CancellationToken cancellationToken = default)
@@ -239,7 +243,7 @@ private async Task GetChatResponseAsync(string chatId, strin
{
// Render system instruction components and create the meta-prompt template
var systemInstructions = await AsyncUtils.SafeInvokeAsync(
- () => this.RenderSystemInstructions(chatId, chatContext, cancellationToken), nameof(RenderSystemInstructions));
+ () => this.RenderSystemInstructionsAsync(chatId, chatContext, cancellationToken), nameof(this.RenderSystemInstructionsAsync));
ChatHistory metaPrompt = new(systemInstructions);
// Bypass audience extraction if Auth is disabled
@@ -249,14 +253,14 @@ private async Task GetChatResponseAsync(string chatId, strin
// Get the audience
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Extracting audience", cancellationToken);
audience = await AsyncUtils.SafeInvokeAsync(
- () => this.GetAudienceAsync(chatContext, cancellationToken), nameof(GetAudienceAsync));
+ () => this.GetAudienceAsync(chatContext, cancellationToken), nameof(this.GetAudienceAsync));
metaPrompt.AddSystemMessage(audience);
}
// Extract user intent from the conversation history.
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Extracting user intent", cancellationToken);
var userIntent = await AsyncUtils.SafeInvokeAsync(
- () => this.GetUserIntentAsync(chatContext, cancellationToken), nameof(GetUserIntentAsync));
+ () => this.GetUserIntentAsync(chatContext, cancellationToken), nameof(this.GetUserIntentAsync));
metaPrompt.AddSystemMessage(userIntent);
// Calculate max amount of tokens to use for memories
@@ -264,13 +268,13 @@ private async Task GetChatResponseAsync(string chatId, strin
// Calculate tokens used so far: system instructions, audience extraction and user intent
int tokensUsed = TokenUtils.GetContextMessagesTokenCount(metaPrompt);
int chatMemoryTokenBudget = maxRequestTokenBudget
- - tokensUsed
- - TokenUtils.GetContextMessageTokenCount(AuthorRole.User, userMessage.ToFormattedString());
+ - tokensUsed
+ - TokenUtils.GetContextMessageTokenCount(AuthorRole.User, userMessage.ToFormattedString());
chatMemoryTokenBudget = (int)(chatMemoryTokenBudget * this._promptOptions.MemoriesResponseContextWeight);
// Query relevant semantic and document memories
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Extracting semantic and document memories", cancellationToken);
- (var memoryText, var citationMap) = await this._semanticMemoryRetriever.QueryMemoriesAsync(userIntent, chatId, chatMemoryTokenBudget);
+ (var memoryText, var citationMap) = await this._kernelMemoryRetriever.QueryMemoriesAsync(userIntent, chatId, chatMemoryTokenBudget);
if (!string.IsNullOrWhiteSpace(memoryText))
{
metaPrompt.AddSystemMessage(memoryText);
@@ -296,7 +300,7 @@ private async Task GetChatResponseAsync(string chatId, strin
/// The chat ID
/// The KernelArguments.
/// The cancellation token.
- private async Task RenderSystemInstructions(string chatId, KernelArguments context, CancellationToken cancellationToken)
+ private async Task RenderSystemInstructionsAsync(string chatId, KernelArguments context, CancellationToken cancellationToken)
{
// Render system instruction components
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Initializing prompt", cancellationToken);
@@ -327,7 +331,7 @@ private async Task HandleBotResponseAsync(
// Get bot response and stream to client
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Generating bot response", cancellationToken);
CopilotChatMessage chatMessage = await AsyncUtils.SafeInvokeAsync(
- () => this.StreamResponseToClientAsync(chatId, userId, promptView, cancellationToken, citations), nameof(StreamResponseToClientAsync));
+ () => this.StreamResponseToClientAsync(chatId, userId, promptView, cancellationToken, citations), nameof(this.StreamResponseToClientAsync));
// Save the message into chat history
await this.UpdateBotResponseStatusOnClientAsync(chatId, "Saving message to chat history", cancellationToken);
@@ -499,7 +503,7 @@ private async Task SaveNewResponseAsync(
CancellationToken cancellationToken,
Dictionary? tokenUsage = null,
IEnumerable? citations = null
- )
+ )
{
// Make sure the chat exists.
if (!await this._chatSessionRepository.TryFindByIdAsync(chatId))
@@ -583,11 +587,11 @@ private int GetMaxRequestTokenBudget()
// This burns just under 20 tokens which need to be accounted for.
const int ExtraOpenAiMessageTokens = 20;
return this._promptOptions.CompletionTokenLimit // Total token limit
- - ExtraOpenAiMessageTokens
- // Token count reserved for model to generate a response
- - this._promptOptions.ResponseTokenLimit
- // Buffer for Tool Calls
- - this._promptOptions.FunctionCallingTokenLimit;
+ - ExtraOpenAiMessageTokens
+ // Token count reserved for model to generate a response
+ - this._promptOptions.ResponseTokenLimit
+ // Buffer for Tool Calls
+ - this._promptOptions.FunctionCallingTokenLimit;
}
///
@@ -601,7 +605,7 @@ private Dictionary GetTokenUsages(KernelArguments kernelArguments,
var tokenUsageDict = new Dictionary(StringComparer.OrdinalIgnoreCase);
// Total token usage of each semantic function
- foreach (string function in TokenUtils.semanticFunctions.Values)
+ foreach (string function in TokenUtils.SemanticFunctions.Values)
{
if (kernelArguments.TryGetValue($"{function}TokenUsage", out object? tokenUsage))
{
@@ -614,7 +618,7 @@ private Dictionary GetTokenUsages(KernelArguments kernelArguments,
if (content != null)
{
- tokenUsageDict.Add(TokenUtils.semanticFunctions["SystemCompletion"]!, TokenUtils.TokenCount(content));
+ tokenUsageDict.Add(TokenUtils.SemanticFunctions["SystemCompletion"]!, TokenUtils.TokenCount(content));
}
return tokenUsageDict;
diff --git a/webapi/Plugins/Chat/SemanticMemoryRetriever.cs b/webapi/Plugins/Chat/KernelMemoryRetriever.cs
similarity index 95%
rename from webapi/Plugins/Chat/SemanticMemoryRetriever.cs
rename to webapi/Plugins/Chat/KernelMemoryRetriever.cs
index f237c97e7..bb087a8c5 100644
--- a/webapi/Plugins/Chat/SemanticMemoryRetriever.cs
+++ b/webapi/Plugins/Chat/KernelMemoryRetriever.cs
@@ -20,7 +20,7 @@ namespace CopilotChat.WebApi.Plugins.Chat;
///
/// This class provides the functions to query kernel memory.
///
-public class SemanticMemoryRetriever
+public class KernelMemoryRetriever
{
private readonly PromptsOptions _promptOptions;
@@ -36,9 +36,9 @@ public class SemanticMemoryRetriever
private readonly ILogger _logger;
///
- /// Create a new instance of SemanticMemoryRetriever.
+ /// Create a new instance of KernelMemoryRetriever.
///
- public SemanticMemoryRetriever(
+ public KernelMemoryRetriever(
IOptions promptOptions,
ChatSessionRepository chatSessionRepository,
IKernelMemory memoryClient,
@@ -49,7 +49,8 @@ public SemanticMemoryRetriever(
this._memoryClient = memoryClient;
this._logger = logger;
- this._memoryNames = new List {
+ this._memoryNames = new List
+ {
this._promptOptions.DocumentMemoryName,
this._promptOptions.LongTermMemoryName,
this._promptOptions.WorkingMemoryName
@@ -62,8 +63,10 @@ public SemanticMemoryRetriever(
/// A string containing the relevant memories.
public async Task<(string, IDictionary)> QueryMemoriesAsync(
[Description("Query to match.")] string query,
- [Description("Chat ID to query history from")] string chatId,
- [Description("Maximum number of tokens")] int tokenLimit)
+ [Description("Chat ID to query history from")]
+ string chatId,
+ [Description("Maximum number of tokens")]
+ int tokenLimit)
{
ChatSession? chatSession = null;
if (!await this._chatSessionRepository.TryFindByIdAsync(chatId, callback: v => chatSession = v))
@@ -80,6 +83,7 @@ public SemanticMemoryRetriever(
{
tasks.Add(SearchMemoryAsync(memoryName));
}
+
// Global document memory.
tasks.Add(SearchMemoryAsync(this._promptOptions.DocumentMemoryName, isGlobalMemory: true));
// Wait for all tasks to complete.
@@ -177,7 +181,7 @@ await this._memoryClient.SearchMemoryAsync(
if (result.Memory.Tags.TryGetValue(MemoryTags.TagMemory, out var tag) && tag.Count > 0)
{
var memoryName = tag.Single()!;
- var citationSource = CitationSource.FromSemanticMemoryCitation(
+ var citationSource = CitationSource.FromKernelMemoryCitation(
result.Citation,
result.Memory.Text,
result.Memory.Relevance
@@ -232,8 +236,8 @@ await this._memoryClient.SearchMemoryAsync(
/// Thrown when the memory name is invalid.
private float CalculateRelevanceThreshold(string memoryName, float memoryBalance)
{
- var upper = this._promptOptions.SemanticMemoryRelevanceUpper;
- var lower = this._promptOptions.SemanticMemoryRelevanceLower;
+ var upper = this._promptOptions.KernelMemoryRelevanceUpper;
+ var lower = this._promptOptions.KernelMemoryRelevanceLower;
if (memoryBalance < 0.0 || memoryBalance > 1.0)
{
diff --git a/webapi/Plugins/Chat/MsGraphOboPlugin.cs b/webapi/Plugins/Chat/MsGraphOboPlugin.cs
index 65fcf4911..4ce0592de 100644
--- a/webapi/Plugins/Chat/MsGraphOboPlugin.cs
+++ b/webapi/Plugins/Chat/MsGraphOboPlugin.cs
@@ -120,6 +120,7 @@ public async Task CallGraphApiTasksAsync([Description("The URI of the Gr
}
}
}
+
return graphResponseContent;
}
@@ -132,14 +133,14 @@ private async Task GetOboAccessTokenAsync(string graphScopes, Cancellati
using (var request = new HttpRequestMessage(HttpMethod.Post, this._authority + "/" + this._tenantId + "/oauth2/v2.0/token"))
{
var keyValues = new List>
- {
- new("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
- new("client_id", this._clientId),
- new("client_secret", this._clientSecret),
- new("assertion", this._bearerToken),
- new("scope", graphScopes),
- new("requested_token_use", "on_behalf_of")
- };
+ {
+ new("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
+ new("client_id", this._clientId),
+ new("client_secret", this._clientSecret),
+ new("assertion", this._bearerToken),
+ new("scope", graphScopes),
+ new("requested_token_use", "on_behalf_of")
+ };
request.Content = new FormUrlEncodedContent(keyValues);
var response = await client.SendAsync(request, cancellationToken);
diff --git a/webapi/Plugins/Chat/SemanticChatMemoryExtractor.cs b/webapi/Plugins/Chat/SemanticChatMemoryExtractor.cs
index ecf0eb26e..11cb1c579 100644
--- a/webapi/Plugins/Chat/SemanticChatMemoryExtractor.cs
+++ b/webapi/Plugins/Chat/SemanticChatMemoryExtractor.cs
@@ -48,6 +48,7 @@ public static async Task ExtractSemanticChatMemoryAsync(
logger.LogInformation("Unable to extract kernel memory for invalid memory type {0}. Continuing...", memoryType);
continue;
}
+
var semanticMemory = await ExtractCognitiveMemoryAsync(memoryType, memoryName, logger);
foreach (var item in semanticMemory.Items)
{
@@ -128,7 +129,7 @@ async Task CreateMemoryAsync(string memoryName, string memory)
await memoryClient.SearchMemoryAsync(
options.MemoryIndexName,
memory,
- options.SemanticMemoryRelevanceUpper,
+ options.KernelMemoryRelevanceUpper,
resultCount: 1,
chatId,
memoryName,
diff --git a/webapi/Plugins/Utils/TokenUtils.cs b/webapi/Plugins/Utils/TokenUtils.cs
index f3adad225..355af59fb 100644
--- a/webapi/Plugins/Utils/TokenUtils.cs
+++ b/webapi/Plugins/Utils/TokenUtils.cs
@@ -15,18 +15,18 @@ namespace CopilotChat.WebApi.Plugins.Utils;
///
public static class TokenUtils
{
- private static SharpToken.GptEncoding tokenizer = SharpToken.GptEncoding.GetEncoding("cl100k_base");
+ private static readonly SharpToken.GptEncoding s_tokenizer = SharpToken.GptEncoding.GetEncoding("cl100k_base");
///
/// Semantic dependencies of ChatPlugin.
/// If you add a new semantic dependency, please add it here.
///
- internal static readonly Dictionary semanticFunctions = new()
+ internal static readonly Dictionary SemanticFunctions = new()
{
{ "SystemAudienceExtraction", "audienceExtraction" },
{ "SystemIntentExtraction", "userIntentExtraction" },
{ "SystemMetaPrompt", "metaPromptTemplate" },
- { "SystemCompletion", "responseCompletion"},
+ { "SystemCompletion", "responseCompletion" },
{ "SystemCognitive_WorkingMemory", "workingMemoryExtraction" },
{ "SystemCognitive_LongTermMemory", "longTermMemoryExtraction" }
};
@@ -37,7 +37,7 @@ public static class TokenUtils
///
internal static Dictionary EmptyTokenUsages()
{
- return semanticFunctions.Values.ToDictionary(v => v, v => 0);
+ return SemanticFunctions.Values.ToDictionary(v => v, v => 0);
}
///
@@ -47,10 +47,12 @@ internal static Dictionary EmptyTokenUsages()
/// The key corresponding to the semantic function name, or null if the function name is unknown.
internal static string GetFunctionKey(string? functionName)
{
- if (functionName == null || !semanticFunctions.TryGetValue(functionName, out string? key))
+ if (functionName == null || !SemanticFunctions.TryGetValue(functionName, out string? key))
{
throw new KeyNotFoundException($"Unknown token dependency {functionName}. Please define function as semanticFunctions entry in TokenUtils.cs");
- };
+ }
+
+ ;
return $"{key}TokenUsage";
}
@@ -93,7 +95,7 @@ internal static string GetFunctionKey(string? functionName)
/// The string to calculate the number of tokens in.
internal static int TokenCount(string text)
{
- var tokens = tokenizer.Encode(text);
+ var tokens = s_tokenizer.Encode(text);
return tokens.Count;
}
diff --git a/webapi/Program.cs b/webapi/Program.cs
index bdbf10638..c4dd756eb 100644
--- a/webapi/Program.cs
+++ b/webapi/Program.cs
@@ -51,7 +51,7 @@ public static async Task Main(string[] args)
builder
.AddBotConfig()
.AddSemanticKernelServices()
- .AddSemanticMemoryServices();
+ .AddKernelMemoryServices();
// Add SignalR as the real time relay service
builder.Services.AddSignalR();
diff --git a/webapi/README.md b/webapi/README.md
index 89e553c8f..f24abf95c 100644
--- a/webapi/README.md
+++ b/webapi/README.md
@@ -22,12 +22,12 @@ The following material is under development and may not be complete or accurate.
2. In Solution Explorer, right-click on `CopilotChatWebApi` and select `Set as Startup Project`.
3. Start debugging by pressing `F5` or selecting the menu item `Debug`->`Start Debugging`.
-4. **(Optional)** To enable support for uploading image file formats such as png, jpg and tiff, there are two options for `SemanticMemory:ImageOcrType` section of `./appsettings.json`, the Tesseract open source library and Azure Form Recognizer.
+4. **(Optional)** To enable support for uploading image file formats such as png, jpg and tiff, there are two options for `KernelMemory:ImageOcrType` section of `./appsettings.json`, the Tesseract open source library and Azure Form Recognizer.
- **Tesseract** we have included the [Tesseract](https://www.nuget.org/packages/Tesseract) nuget package.
- - You will need to obtain one or more [tessdata language data files](https://github.com/tesseract-ocr/tessdata) such as `eng.traineddata` and add them to your `./data` directory or the location specified in the `SemanticMemory:Services:Tesseract:FilePath` location in `./appsettings.json`.
+ - You will need to obtain one or more [tessdata language data files](https://github.com/tesseract-ocr/tessdata) such as `eng.traineddata` and add them to your `./data` directory or the location specified in the `KernelMemory:Services:Tesseract:FilePath` location in `./appsettings.json`.
- Set the `Copy to Output Directory` value to `Copy if newer`.
- **Azure AI Doc Intel** we have included the [Azure.AI.FormRecognizer](https://www.nuget.org/packages/Azure.AI.FormRecognizer) nuget package.
- - You will need to obtain an [Azure AI Doc Intel](https://azure.microsoft.com/en-us/products/ai-services/ai-document-intelligence) resource and add the `SemanticMemory:Services:AzureAIDocIntel:Endpoint` and `SemanticMemory:Services:AzureAIDocIntel:Key` values to the `./appsettings.json` file.
+ - You will need to obtain an [Azure AI Doc Intel](https://azure.microsoft.com/en-us/products/ai-services/ai-document-intelligence) resource and add the `KernelMemory:Services:AzureAIDocIntel:Endpoint` and `KernelMemory:Services:AzureAIDocIntel:Key` values to the `./appsettings.json` file.
## Running [Memory Service](https://github.com/microsoft/kernel-memory)
@@ -45,30 +45,30 @@ No additional configuration is needed.
Running the memory creation pipeline steps in different processes. This means the memory creation is asynchronous. This allows better scalability if you have many chat sessions active at the same time or you have big documents that require minutes to process.
-1. In [./webapi/appsettings.json](./appsettings.json), set `SemanticMemory:DataIngestion:OrchestrationType` to `Distributed`.
-2. In [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `SemanticMemory:DataIngestion:OrchestrationType` to `Distributed`.
+1. In [./webapi/appsettings.json](./appsettings.json), set `KernelMemory:DataIngestion:OrchestrationType` to `Distributed`.
+2. In [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `KernelMemory:DataIngestion:OrchestrationType` to `Distributed`.
3. Make sure the following settings in the [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json) respectively point to the same locations on your machine so that both processes can access the data:
- - `SemanticMemory:Services:SimpleFileStorage:Directory`
- - `SemanticMemory:Services:SimpleQueues:Directory`
- - `SemanticMemory:Services:SimpleVectorDb:Directory`
+ - `KernelMemory:Services:SimpleFileStorage:Directory`
+ - `KernelMemory:Services:SimpleQueues:Directory`
+ - `KernelMemory:Services:SimpleVectorDb:Directory`
> Do not configure SimpleVectorDb to use Volatile. Volatile storage cannot be shared across processes.
4. You need to run both the [webapi](./README.md) and the [memorypipeline](../memorypipeline/README.md).
### (Optional) Use hosted resources: [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview), [Azure Cognitive Search](https://learn.microsoft.com/en-us/azure/search/search-what-is-azure-search)
-1. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `SemanticMemory:DocumentStorageType` to `AzureBlobs`.
-2. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `SemanticMemory:DataIngestion:DistributedOrchestration:QueueType` to `AzureQueue`.
-3. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `SemanticMemory:DataIngestion:MemoryDbTypes:0` to `AzureAISearch`.
-4. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `SemanticMemory:Retrieval:MemoryDbType` to `AzureAISearch`.
+1. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `KernelMemory:DocumentStorageType` to `AzureBlobs`.
+2. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `KernelMemory:DataIngestion:DistributedOrchestration:QueueType` to `AzureQueue`.
+3. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `KernelMemory:DataIngestion:MemoryDbTypes:0` to `AzureAISearch`.
+4. In [./webapi/appsettings.json](./appsettings.json) and [../memorypipeline/appsettings.json](../memorypipeline/appsettings.json), set `KernelMemory:Retrieval:MemoryDbType` to `AzureAISearch`.
5. Run the following to set up the authentication to the resources:
```bash
- dotnet user-secrets set SemanticMemory:Services:AzureBlobs:Auth ConnectionString
- dotnet user-secrets set SemanticMemory:Services:AzureBlobs:ConnectionString [your secret]
- dotnet user-secrets set SemanticMemory:Services:AzureQueue:Auth ConnectionString # Only needed when running distributed processing
- dotnet user-secrets set SemanticMemory:Services:AzureQueue:ConnectionString [your secret] # Only needed when running distributed processing
- dotnet user-secrets set SemanticMemory:Services:AzureAISearch:Endpoint [your secret]
- dotnet user-secrets set SemanticMemory:Services:AzureAISearch:APIKey [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureBlobs:Auth ConnectionString
+ dotnet user-secrets set KernelMemory:Services:AzureBlobs:ConnectionString [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureQueue:Auth ConnectionString # Only needed when running distributed processing
+ dotnet user-secrets set KernelMemory:Services:AzureQueue:ConnectionString [your secret] # Only needed when running distributed processing
+ dotnet user-secrets set KernelMemory:Services:AzureAISearch:Endpoint [your secret]
+ dotnet user-secrets set KernelMemory:Services:AzureAISearch:APIKey [your secret]
```
6. For more information and other options, please refer to the [memorypipeline](../memorypipeline/README.md).
diff --git a/webapi/Services/AzureContentSafety.cs b/webapi/Services/AzureContentSafety.cs
index e16094180..f1c98198d 100644
--- a/webapi/Services/AzureContentSafety.cs
+++ b/webapi/Services/AzureContentSafety.cs
@@ -13,6 +13,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.SemanticKernel;
+// ReSharper disable MissingLinebreak
namespace CopilotChat.WebApi.Services;
public record AnalysisResult(
@@ -117,6 +118,7 @@ public async Task ImageAnalysisAsync(IFormFile formFile,
{
throw new KernelException($"[Content Safety] Failed to analyze image. Details: {body}");
}
+
return result;
}
diff --git a/webapi/Services/DocumentTypeProvider.cs b/webapi/Services/DocumentTypeProvider.cs
index 28dcf1882..66d2e7c9c 100644
--- a/webapi/Services/DocumentTypeProvider.cs
+++ b/webapi/Services/DocumentTypeProvider.cs
@@ -11,7 +11,7 @@ namespace CopilotChat.WebApi.Services;
///
public class DocumentTypeProvider
{
- private readonly Dictionary supportedTypes;
+ private readonly Dictionary _supportedTypes;
///
/// Construct provider based on if images are supported, or not.
@@ -19,7 +19,7 @@ public class DocumentTypeProvider
/// Flag indicating if image ocr is supported
public DocumentTypeProvider(bool allowImageOcr)
{
- this.supportedTypes =
+ this._supportedTypes =
new(StringComparer.OrdinalIgnoreCase)
{
{ FileExtensions.MarkDown, false },
@@ -44,6 +44,6 @@ public DocumentTypeProvider(bool allowImageOcr)
///
public bool IsSupported(string extension, out bool isSafetyTarget)
{
- return this.supportedTypes.TryGetValue(extension, out isSafetyTarget);
+ return this._supportedTypes.TryGetValue(extension, out isSafetyTarget);
}
}
diff --git a/webapi/Services/MaintenanceMiddleware.cs b/webapi/Services/MaintenanceMiddleware.cs
index c0e5b5e02..0edd5165e 100644
--- a/webapi/Services/MaintenanceMiddleware.cs
+++ b/webapi/Services/MaintenanceMiddleware.cs
@@ -14,7 +14,7 @@
namespace CopilotChat.WebApi.Services;
///
-/// Middleware for determining is site is undergoing maintenance.
+/// Middleware for determining if site is undergoing maintenance.
///
public class MaintenanceMiddleware
{
@@ -41,7 +41,7 @@ public MaintenanceMiddleware(
this._logger = logger;
}
- public async Task Invoke(HttpContext ctx, Kernel kernel)
+ public async Task InvokeAsync(HttpContext ctx, Kernel kernel)
{
// Skip inspection if _isInMaintenance explicitly false.
if (this._isInMaintenance == null || this._isInMaintenance.Value)
diff --git a/webapi/Storage/CosmosDbContext.cs b/webapi/Storage/CosmosDbContext.cs
index 238b59930..dbbc45944 100644
--- a/webapi/Storage/CosmosDbContext.cs
+++ b/webapi/Storage/CosmosDbContext.cs
@@ -24,7 +24,7 @@ public class CosmosDbContext : IStorageContext, IDisposable where T : ISto
/// CosmosDB container.
///
#pragma warning disable CA1051 // Do not declare visible instance fields
- protected readonly Container _container;
+ protected readonly Container Container;
#pragma warning restore CA1051 // Do not declare visible instance fields
///
@@ -44,14 +44,14 @@ public CosmosDbContext(string connectionString, string database, string containe
},
};
this._client = new CosmosClient(connectionString, options);
- this._container = this._client.GetContainer(database, container);
+ this.Container = this._client.GetContainer(database, container);
}
///
public async Task> QueryEntitiesAsync(Func predicate)
{
return await Task.Run>(
- () => this._container.GetItemLinqQueryable(true).Where(predicate).AsEnumerable());
+ () => this.Container.GetItemLinqQueryable(true).Where(predicate).AsEnumerable());
}
///
@@ -62,7 +62,7 @@ public async Task CreateAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- await this._container.CreateItemAsync(entity, new PartitionKey(entity.Partition));
+ await this.Container.CreateItemAsync(entity, new PartitionKey(entity.Partition));
}
///
@@ -73,7 +73,7 @@ public async Task DeleteAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- await this._container.DeleteItemAsync(entity.Id, new PartitionKey(entity.Partition));
+ await this.Container.DeleteItemAsync(entity.Id, new PartitionKey(entity.Partition));
}
///
@@ -86,7 +86,7 @@ public async Task ReadAsync(string entityId, string partitionKey)
try
{
- var response = await this._container.ReadItemAsync(entityId, new PartitionKey(partitionKey));
+ var response = await this.Container.ReadItemAsync(entityId, new PartitionKey(partitionKey));
return response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
@@ -103,7 +103,7 @@ public async Task UpsertAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- await this._container.UpsertItemAsync(entity, new PartitionKey(entity.Partition));
+ await this.Container.UpsertItemAsync(entity, new PartitionKey(entity.Partition));
}
public void Dispose()
@@ -141,7 +141,7 @@ public CosmosDbCopilotChatMessageContext(string connectionString, string databas
public Task> QueryEntitiesAsync(Func predicate, int skip, int count)
{
return Task.Run>(
- () => this._container.GetItemLinqQueryable(true)
- .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count).AsEnumerable());
+ () => this.Container.GetItemLinqQueryable(true)
+ .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count).AsEnumerable());
}
}
diff --git a/webapi/Storage/FileSystemContext.cs b/webapi/Storage/FileSystemContext.cs
index e39716819..de6b21f6f 100644
--- a/webapi/Storage/FileSystemContext.cs
+++ b/webapi/Storage/FileSystemContext.cs
@@ -24,13 +24,13 @@ public FileSystemContext(FileInfo filePath)
{
this._fileStorage = filePath;
- this._entities = this.Load(this._fileStorage);
+ this.Entities = this.Load(this._fileStorage);
}
///
public Task> QueryEntitiesAsync(Func predicate)
{
- return Task.FromResult(this._entities.Values.Where(predicate));
+ return Task.FromResult(this.Entities.Values.Where(predicate));
}
///
@@ -41,9 +41,9 @@ public Task CreateAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- if (this._entities.TryAdd(entity.Id, entity))
+ if (this.Entities.TryAdd(entity.Id, entity))
{
- this.Save(this._entities, this._fileStorage);
+ this.Save(this.Entities, this._fileStorage);
}
return Task.CompletedTask;
@@ -57,9 +57,9 @@ public Task DeleteAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- if (this._entities.TryRemove(entity.Id, out _))
+ if (this.Entities.TryRemove(entity.Id, out _))
{
- this.Save(this._entities, this._fileStorage);
+ this.Save(this.Entities, this._fileStorage);
}
return Task.CompletedTask;
@@ -73,7 +73,7 @@ public Task ReadAsync(string entityId, string partitionKey)
throw new ArgumentOutOfRangeException(nameof(entityId), "Entity Id cannot be null or empty.");
}
- if (this._entities.TryGetValue(entityId, out T? entity))
+ if (this.Entities.TryGetValue(entityId, out T? entity))
{
return Task.FromResult(entity);
}
@@ -89,9 +89,9 @@ public Task UpsertAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- if (this._entities.AddOrUpdate(entity.Id, entity, (key, oldValue) => entity) != null)
+ if (this.Entities.AddOrUpdate(entity.Id, entity, (key, oldValue) => entity) != null)
{
- this.Save(this._entities, this._fileStorage);
+ this.Save(this.Entities, this._fileStorage);
}
return Task.CompletedTask;
@@ -108,7 +108,7 @@ protected sealed class EntityDictionary : ConcurrentDictionary
/// Using a concurrent dictionary to store entities in memory.
///
#pragma warning disable CA1051 // Do not declare visible instance fields
- protected readonly EntityDictionary _entities;
+ protected readonly EntityDictionary Entities;
#pragma warning restore CA1051 // Do not declare visible instance fields
///
@@ -188,7 +188,7 @@ public FileSystemCopilotChatMessageContext(FileInfo filePath) :
public Task> QueryEntitiesAsync(Func predicate, int skip, int count)
{
return Task.Run>(
- () => this._entities.Values
- .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count));
+ () => this.Entities.Values
+ .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count));
}
}
diff --git a/webapi/Storage/Repository.cs b/webapi/Storage/Repository.cs
index bfe2fcef3..f22fb6eb0 100644
--- a/webapi/Storage/Repository.cs
+++ b/webapi/Storage/Repository.cs
@@ -80,7 +80,7 @@ public class CopilotChatMessageRepository : Repository
private readonly ICopilotChatMessageStorageContext _messageStorageContext;
public CopilotChatMessageRepository(ICopilotChatMessageStorageContext storageContext)
- : base(storageContext)
+ : base(storageContext)
{
this._messageStorageContext = storageContext;
}
diff --git a/webapi/Storage/VolatileContext.cs b/webapi/Storage/VolatileContext.cs
index 91c104850..10d6c834b 100644
--- a/webapi/Storage/VolatileContext.cs
+++ b/webapi/Storage/VolatileContext.cs
@@ -20,7 +20,7 @@ public class VolatileContext : IStorageContext where T : IStorageEntity
/// Using a concurrent dictionary to store entities in memory.
///
#pragma warning disable CA1051 // Do not declare visible instance fields
- protected readonly ConcurrentDictionary _entities;
+ protected readonly ConcurrentDictionary Entities;
#pragma warning restore CA1051 // Do not declare visible instance fields
///
@@ -28,13 +28,13 @@ public class VolatileContext : IStorageContext where T : IStorageEntity
///
public VolatileContext()
{
- this._entities = new ConcurrentDictionary();
+ this.Entities = new ConcurrentDictionary();
}
///
public Task> QueryEntitiesAsync(Func predicate)
{
- return Task.FromResult(this._entities.Values.Where(predicate));
+ return Task.FromResult(this.Entities.Values.Where(predicate));
}
///
@@ -45,7 +45,7 @@ public Task CreateAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- this._entities.TryAdd(entity.Id, entity);
+ this.Entities.TryAdd(entity.Id, entity);
return Task.CompletedTask;
}
@@ -58,7 +58,7 @@ public Task DeleteAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- this._entities.TryRemove(entity.Id, out _);
+ this.Entities.TryRemove(entity.Id, out _);
return Task.CompletedTask;
}
@@ -71,7 +71,7 @@ public Task ReadAsync(string entityId, string partitionKey)
throw new ArgumentOutOfRangeException(nameof(entityId), "Entity Id cannot be null or empty.");
}
- if (this._entities.TryGetValue(entityId, out T? entity))
+ if (this.Entities.TryGetValue(entityId, out T? entity))
{
return Task.FromResult(entity);
}
@@ -87,7 +87,7 @@ public Task UpsertAsync(T entity)
throw new ArgumentOutOfRangeException(nameof(entity), "Entity Id cannot be null or empty.");
}
- this._entities.AddOrUpdate(entity.Id, entity, (key, oldValue) => entity);
+ this.Entities.AddOrUpdate(entity.Id, entity, (key, oldValue) => entity);
return Task.CompletedTask;
}
@@ -107,7 +107,7 @@ public class VolatileCopilotChatMessageContext : VolatileContext> QueryEntitiesAsync(Func predicate, int skip, int count)
{
return Task.Run>(
- () => this._entities.Values
- .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count));
+ () => this.Entities.Values
+ .Where(predicate).OrderByDescending(m => m.Timestamp).Skip(skip).Take(count));
}
}