diff --git a/.editorconfig b/.editorconfig index 9003d88ed..773ef5247 100644 --- a/.editorconfig +++ b/.editorconfig @@ -446,12 +446,34 @@ dotnet_diagnostic.CA1032.severity = none # We're using RCS1194 which seems to co dotnet_diagnostic.CA1034.severity = none # Do not nest type. Alternatively, change its accessibility so that it is not externally visible dotnet_diagnostic.CA1054.severity = none # URI parameters should not be strings dotnet_diagnostic.CA1062.severity = none # Disable null check, C# already does it for us -dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member +dotnet_diagnostic.CA1515.severity = none # Because an application's API isn't typically referenced from outside the assembly, types can be made internal dotnet_diagnostic.CA1805.severity = none # Member is explicitly initialized to its default value dotnet_diagnostic.CA1822.severity = none # Member does not access instance data and can be marked as static dotnet_diagnostic.CA1848.severity = none # For improved performance, use the LoggerMessage delegates dotnet_diagnostic.CA2227.severity = none # Change to be read-only by removing the property setter dotnet_diagnostic.CA2253.severity = none # Named placeholders in the logging message template should not be comprised of only numeric characters +dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member +dotnet_diagnostic.IDE0001.severity = none # Simplify name +dotnet_diagnostic.IDE0002.severity = none # Simplify member access +dotnet_diagnostic.IDE0004.severity = none # Remove unnecessary cast +dotnet_diagnostic.IDE0010.severity = none # Populate switch +dotnet_diagnostic.IDE0032.severity = none # Use auto property +dotnet_diagnostic.IDE0035.severity = none # Remove unreachable code +dotnet_diagnostic.IDE0051.severity = none # Remove unused private member +dotnet_diagnostic.IDE0052.severity = none # Remove unread private member +dotnet_diagnostic.IDE0056.severity = none # Indexing can be simplified +dotnet_diagnostic.IDE0057.severity = none # Substring can be simplified +dotnet_diagnostic.IDE0058.severity = none # Remove unused expression value +dotnet_diagnostic.IDE0059.severity = none # Unnecessary assignment of a value +dotnet_diagnostic.IDE0060.severity = none # Remove unused parameter +dotnet_diagnostic.IDE0066.severity = none # Use 'switch' expression +dotnet_diagnostic.IDE0072.severity = none # Populate switch +dotnet_diagnostic.IDE0080.severity = none # Remove unnecessary suppression operator +dotnet_diagnostic.IDE0100.severity = none # Remove unnecessary equality operator +dotnet_diagnostic.IDE0110.severity = none # Remove unnecessary discards +dotnet_diagnostic.IDE0160.severity = none # Use block-scoped namespace +dotnet_diagnostic.IDE0290.severity = none # Use primary constructor +dotnet_diagnostic.IDE0305.severity = none # Collection initialization can be simplified dotnet_diagnostic.RCS1021.severity = none # Use expression-bodied lambda. dotnet_diagnostic.RCS1061.severity = none # Merge 'if' with nested 'if'. dotnet_diagnostic.RCS1069.severity = none # Remove unnecessary case label. @@ -480,26 +502,11 @@ dotnet_diagnostic.RCS1226.severity = none # Add paragraph to documentation comme dotnet_diagnostic.RCS1234.severity = none # Enum duplicate value dotnet_diagnostic.RCS1238.severity = none # Avoid nested ?: operators. dotnet_diagnostic.RCS1241.severity = none # Implement IComparable when implementing IComparable. -dotnet_diagnostic.IDE0001.severity = none # Simplify name -dotnet_diagnostic.IDE0002.severity = none # Simplify member access -dotnet_diagnostic.IDE0004.severity = none # Remove unnecessary cast -dotnet_diagnostic.IDE0035.severity = none # Remove unreachable code -dotnet_diagnostic.IDE0051.severity = none # Remove unused private member -dotnet_diagnostic.IDE0052.severity = none # Remove unread private member -dotnet_diagnostic.IDE0058.severity = none # Remove unused expression value -dotnet_diagnostic.IDE0059.severity = none # Unnecessary assignment of a value -dotnet_diagnostic.IDE0060.severity = none # Remove unused parameter -dotnet_diagnostic.IDE0080.severity = none # Remove unnecessary suppression operator -dotnet_diagnostic.IDE0100.severity = none # Remove unnecessary equality operator -dotnet_diagnostic.IDE0110.severity = none # Remove unnecessary discards -dotnet_diagnostic.IDE0032.severity = none # Use auto property -dotnet_diagnostic.IDE0160.severity = none # Use block-scoped namespace dotnet_diagnostic.VSTHRD111.severity = none # Use .ConfigureAwait(bool) is hidden by default, set to none to prevent IDE from changing on autosave dotnet_diagnostic.xUnit1004.severity = none # Test methods should not be skipped. Remove the Skip property to start running the test again. dotnet_diagnostic.SKEXP0003.severity = none # XYZ is for evaluation purposes only dotnet_diagnostic.SKEXP0010.severity = none -dotnet_diagnostic.SKEXP0010.severity = none dotnet_diagnostic.SKEXP0011.severity = none dotnet_diagnostic.SKEXP0052.severity = none dotnet_diagnostic.SKEXP0101.severity = none diff --git a/Directory.Packages.props b/Directory.Packages.props index 42ebd516b..9947848b6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -75,8 +75,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/applications/evaluation/Distribution.cs b/applications/evaluation/Distribution.cs index cd08644fc..3b18e15a9 100644 --- a/applications/evaluation/Distribution.cs +++ b/applications/evaluation/Distribution.cs @@ -17,13 +17,13 @@ public struct Distribution : IEquatable public Distribution() { } // TODO: use tolerance when comparing floating numbers for equality - public override bool Equals(object? obj) => obj is Distribution distribution && - this.Simple == distribution.Simple && - this.Reasoning == distribution.Reasoning && - this.MultiContext == distribution.MultiContext && - this.Conditioning == distribution.Conditioning; + public override readonly bool Equals(object? obj) => obj is Distribution distribution && + this.Simple == distribution.Simple && + this.Reasoning == distribution.Reasoning && + this.MultiContext == distribution.MultiContext && + this.Conditioning == distribution.Conditioning; - public override int GetHashCode() + public override readonly int GetHashCode() { return HashCode.Combine(this.Simple, this.Reasoning, this.MultiContext, this.Conditioning); } @@ -38,9 +38,8 @@ public override int GetHashCode() return !(left == right); } - public bool Equals(Distribution other) + public readonly bool Equals(Distribution other) { return this == other; } } - diff --git a/applications/evaluation/Evaluators/AnswerCorrectness/StatementExtraction.cs b/applications/evaluation/Evaluators/AnswerCorrectness/StatementExtraction.cs index 53bc5f247..0acbb2507 100644 --- a/applications/evaluation/Evaluators/AnswerCorrectness/StatementExtraction.cs +++ b/applications/evaluation/Evaluators/AnswerCorrectness/StatementExtraction.cs @@ -12,5 +12,5 @@ internal sealed class StatementExtraction #pragma warning restore CA1812 // 'StatementExtraction' is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static members, make it 'static' (Module in Visual Basic). (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1812) { [JsonPropertyName("statements")] - public List Statements { get; set; } = new List(); + public List Statements { get; set; } = []; } diff --git a/applications/evaluation/Evaluators/ContextRecall/GroundTruthClassifications.cs b/applications/evaluation/Evaluators/ContextRecall/GroundTruthClassifications.cs index ee1c0235b..e1e3f09b8 100644 --- a/applications/evaluation/Evaluators/ContextRecall/GroundTruthClassifications.cs +++ b/applications/evaluation/Evaluators/ContextRecall/GroundTruthClassifications.cs @@ -12,5 +12,5 @@ internal sealed class GroundTruthClassifications #pragma warning restore CA1812 // 'GroundTruthClassifications' is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static members, make it 'static' (Module in Visual Basic). (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1812) { [JsonPropertyName("evaluations")] - public List Evaluations { get; set; } = new(); + public List Evaluations { get; set; } = []; } diff --git a/applications/evaluation/Evaluators/Faithfulness/FaithfulnessEvaluations.cs b/applications/evaluation/Evaluators/Faithfulness/FaithfulnessEvaluations.cs index d6a5e5d03..8e75962c2 100644 --- a/applications/evaluation/Evaluators/Faithfulness/FaithfulnessEvaluations.cs +++ b/applications/evaluation/Evaluators/Faithfulness/FaithfulnessEvaluations.cs @@ -12,5 +12,5 @@ internal sealed class FaithfulnessEvaluations #pragma warning restore CA1812 // 'FaithfulnessEvaluations' is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static members, make it 'static' (Module in Visual Basic). (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1812) { [JsonPropertyName("evaluations")] - public List Evaluations { get; set; } = new(); + public List Evaluations { get; set; } = []; } diff --git a/applications/evaluation/TestSet/TestSetItem.cs b/applications/evaluation/TestSet/TestSetItem.cs index e534ac10a..82939075d 100644 --- a/applications/evaluation/TestSet/TestSetItem.cs +++ b/applications/evaluation/TestSet/TestSetItem.cs @@ -15,7 +15,7 @@ public sealed class TestSetItem public int GroundTruthVerdict { get; set; } - public IEnumerable Context { get; set; } = Array.Empty(); + public IEnumerable Context { get; set; } = []; public ICollection Filters { get; set; } = Array.Empty(); diff --git a/applications/evaluation/TestSetEvaluator.cs b/applications/evaluation/TestSetEvaluator.cs index 54da444c5..7bd4959be 100644 --- a/applications/evaluation/TestSetEvaluator.cs +++ b/applications/evaluation/TestSetEvaluator.cs @@ -129,7 +129,7 @@ public class QuestionEvaluation public MemoryAnswer MemoryAnswer { get; set; } = null!; - public EvaluationMetrics Metrics { get; set; } = new EvaluationMetrics(); + public EvaluationMetrics Metrics { get; set; } = new(); - public Dictionary Metadata { get; set; } = new(); + public Dictionary Metadata { get; set; } = []; } diff --git a/applications/evaluation/TestSetGenerator.cs b/applications/evaluation/TestSetGenerator.cs index 984e29b9c..ceacd1ef3 100644 --- a/applications/evaluation/TestSetGenerator.cs +++ b/applications/evaluation/TestSetGenerator.cs @@ -97,7 +97,7 @@ public async IAsyncEnumerable GenerateTestSetsAsync( var documentIds = new List(); - await foreach (var record in this._memory.GetListAsync(index, limit: int.MaxValue)) + await foreach (var record in this._memory.GetListAsync(index, limit: int.MaxValue).ConfigureAwait(false)) { if (documentIds.Contains(record.GetDocumentId())) { @@ -110,7 +110,7 @@ public async IAsyncEnumerable GenerateTestSetsAsync( foreach (var documentId in documentIds) { var partitionRecords = await this._memory.GetListAsync(index, - filters: new[] { new MemoryFilter().ByDocument(documentId) }, + filters: [new MemoryFilter().ByDocument(documentId)], limit: int.MaxValue) .ToArrayAsync() .ConfigureAwait(false); @@ -123,7 +123,7 @@ public async IAsyncEnumerable GenerateTestSetsAsync( .Concat(this.GetMultiContextTestSetsAsync(nodes.Skip(simpleCount + reasoningCount).Take(multiContextCount), language: language, retryCount: retryCount)) .Concat(this.GetConditioningTestSetsAsync(nodes.Skip(simpleCount + reasoningCount + multiContextCount).Take(conditioningCount), language: language, retryCount: retryCount)); - await foreach (var item in questions) + await foreach (var item in questions.ConfigureAwait(false)) { yield return item; } diff --git a/applications/tests/Evaluation.Tests/TestsetGenerationTests.cs b/applications/tests/Evaluation.Tests/TestsetGenerationTests.cs index e1ab4d654..83d1e8bcc 100644 --- a/applications/tests/Evaluation.Tests/TestsetGenerationTests.cs +++ b/applications/tests/Evaluation.Tests/TestsetGenerationTests.cs @@ -81,14 +81,13 @@ await this._memory documentId: "file1-NASA-news", steps: Constants.PipelineWithoutSummary); - var evaluation = await this._testSetEvaluator.EvaluateTestSetAsync("default4tests", new[] - { + var evaluation = await this._testSetEvaluator.EvaluateTestSetAsync("default4tests", [ new TestSetItem { Question = "What is the role of the Department of Defense in the recovery operations for the Artemis II mission?", GroundTruth = "The Department of Defense personnel are involved in practicing recovery operations for the Artemis II mission. They use a crew module test article to help verify the recovery team's readiness to recover the Artemis II crew and the Orion spacecraft.", } - }).ToArrayAsync(); + ]).ToArrayAsync(); Assert.NotEmpty(evaluation); } diff --git a/clients/dotnet/WebClient/MemoryWebClient.cs b/clients/dotnet/WebClient/MemoryWebClient.cs index 42f5fd73c..a89b25a55 100644 --- a/clients/dotnet/WebClient/MemoryWebClient.cs +++ b/clients/dotnet/WebClient/MemoryWebClient.cs @@ -312,7 +312,7 @@ public async Task SearchAsync( { if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } @@ -321,7 +321,7 @@ public async Task SearchAsync( { Index = index, Query = query, - Filters = (filters is { Count: > 0 }) ? filters.ToList() : new(), + Filters = (filters is { Count: > 0 }) ? filters.ToList() : [], MinRelevance = minRelevance, Limit = limit, ContextArguments = (context?.Arguments ?? new Dictionary()).ToDictionary(), @@ -348,7 +348,7 @@ public async Task AskAsync( { if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } @@ -357,7 +357,7 @@ public async Task AskAsync( { Index = index, Question = question, - Filters = (filters is { Count: > 0 }) ? filters.ToList() : new(), + Filters = (filters is { Count: > 0 }) ? filters.ToList() : [], MinRelevance = minRelevance, ContextArguments = (context?.Arguments ?? new Dictionary()).ToDictionary(), }; @@ -425,7 +425,7 @@ private async Task ImportInternalAsync( CancellationToken cancellationToken) { // Populate form with values and files from disk - using MultipartFormDataContent formData = new(); + using MultipartFormDataContent formData = []; using StringContent indexContent = new(index); using StringContent contextArgsContent = new(JsonSerializer.Serialize(context?.Arguments)); diff --git a/examples/001-dotnet-WebClient/Program.cs b/examples/001-dotnet-WebClient/Program.cs index d668ba801..0eec905c4 100644 --- a/examples/001-dotnet-WebClient/Program.cs +++ b/examples/001-dotnet-WebClient/Program.cs @@ -13,10 +13,10 @@ * handlers are running to get the pipeline to complete, * otherwise the web service might just upload the files * without extracting memories. */ -public static class Program +internal static class Program { private static MemoryWebClient? s_memory; - private static readonly List s_toDelete = new(); + private static readonly List s_toDelete = []; // Change this to True and configure Azure Document Intelligence to test OCR and support for images private const bool ImageSupportDemoEnabled = true; diff --git a/examples/002-dotnet-Serverless/Program.cs b/examples/002-dotnet-Serverless/Program.cs index f09770c06..14e92dcdc 100644 --- a/examples/002-dotnet-Serverless/Program.cs +++ b/examples/002-dotnet-Serverless/Program.cs @@ -13,7 +13,7 @@ public static class Program { private static MemoryServerless? s_memory; - private static readonly List s_toDelete = new(); + private static readonly List s_toDelete = []; // Remember to configure Azure Document Intelligence to test OCR and support for images private static bool s_imageSupportDemoEnabled = true; diff --git a/examples/204-dotnet-ASP.NET-MVC-integration/204-dotnet-ASP.NET-MVC-integration.csproj b/examples/204-dotnet-ASP.NET-MVC-integration/204-dotnet-ASP.NET-MVC-integration.csproj index c27671236..876a7af53 100644 --- a/examples/204-dotnet-ASP.NET-MVC-integration/204-dotnet-ASP.NET-MVC-integration.csproj +++ b/examples/204-dotnet-ASP.NET-MVC-integration/204-dotnet-ASP.NET-MVC-integration.csproj @@ -6,6 +6,7 @@ 12 enable enable + $(NoWarn);NU1900 diff --git a/examples/211-dotnet-WebClient-Intent-Detection/Program.cs b/examples/211-dotnet-WebClient-Intent-Detection/Program.cs index 9f64ec227..b2e9d1f7f 100644 --- a/examples/211-dotnet-WebClient-Intent-Detection/Program.cs +++ b/examples/211-dotnet-WebClient-Intent-Detection/Program.cs @@ -10,7 +10,7 @@ public static class Program { private static MemoryWebClient? s_memory; - private static readonly List s_toDelete = new(); + private static readonly List s_toDelete = []; public static async Task Main() { diff --git a/examples/301-discord-test-application/301-discord-test-application.csproj b/examples/301-discord-test-application/301-discord-test-application.csproj index 4871148be..1587e2656 100644 --- a/examples/301-discord-test-application/301-discord-test-application.csproj +++ b/examples/301-discord-test-application/301-discord-test-application.csproj @@ -7,6 +7,7 @@ 12 enable enable + $(NoWarn);NU1900 diff --git a/extensions/Anthropic/AnthropicTextGeneration.cs b/extensions/Anthropic/AnthropicTextGeneration.cs index 2aa60eb26..df0252ce4 100644 --- a/extensions/Anthropic/AnthropicTextGeneration.cs +++ b/extensions/Anthropic/AnthropicTextGeneration.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.KernelMemory.AI.Anthropic.Client; using Microsoft.KernelMemory.AI.OpenAI; @@ -113,7 +114,7 @@ public async IAsyncEnumerable GenerateTextAsync( IAsyncEnumerable streamedResponse = this._client.CallClaudeStreamingAsync(parameters, cancellationToken); - await foreach (StreamingResponseMessage response in streamedResponse) + await foreach (StreamingResponseMessage response in streamedResponse.ConfigureAwait(false)) { //now we simply yield the response switch (response) diff --git a/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyConfig.cs b/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyConfig.cs index 9634017dc..ad7837f69 100644 --- a/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyConfig.cs +++ b/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyConfig.cs @@ -24,7 +24,7 @@ public enum AuthTypes public string Endpoint { get; set; } = string.Empty; public string APIKey { get; set; } = string.Empty; public double GlobalSafetyThreshold { get; set; } = 0.0; - public List IgnoredWords { get; set; } = new(); + public List IgnoredWords { get; set; } = []; public void SetCredential(TokenCredential credential) { diff --git a/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyModeration.cs b/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyModeration.cs index 4bcc57949..f86d14ca9 100644 --- a/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyModeration.cs +++ b/extensions/AzureAIContentSafety/AzureAIContentSafety/AzureAIContentSafetyModeration.cs @@ -75,7 +75,7 @@ public async Task IsSafeAsync(string? text, double threshold, Cancellation if (!isSafe) { - IEnumerable report = result.HasValue ? result.Value.CategoriesAnalysis.Select(x => $"{x.Category}: {x.Severity}") : Array.Empty(); + IEnumerable report = result.HasValue ? result.Value.CategoriesAnalysis.Select(x => $"{x.Category}: {x.Severity}") : []; this._log.LogWarning("Unsafe content detected, report: {0}", string.Join("; ", report)); this._log.LogSensitive("Unsafe content: {0}", text); } diff --git a/extensions/AzureAISearch/AzureAISearch.TestApplication/Program.cs b/extensions/AzureAISearch/AzureAISearch.TestApplication/Program.cs index db95a2f0a..93618ad48 100644 --- a/extensions/AzureAISearch/AzureAISearch.TestApplication/Program.cs +++ b/extensions/AzureAISearch/AzureAISearch.TestApplication/Program.cs @@ -11,7 +11,7 @@ namespace Microsoft.AzureAISearch.TestApplication; -public static class Program +internal static class Program { // Azure Search Index name private const string Index = "test01"; @@ -124,7 +124,7 @@ private static async Task CreateIndexAsync(string name) var indexSchema = new SearchIndex(name) { - Fields = new List(), + Fields = [], VectorSearch = new VectorSearch { Profiles = @@ -285,7 +285,7 @@ private static async Task DeleteRecordAsync(string index, string recordId) Console.WriteLine($"DELETING {recordId}\n"); - Response? response = await client.DeleteDocumentsAsync("id", new List { recordId }); + Response? response = await client.DeleteDocumentsAsync("id", [recordId]); Console.WriteLine("Status: " + response.GetRawResponse().Status); Console.WriteLine("IsError: " + response.GetRawResponse().IsError); diff --git a/extensions/AzureAISearch/AzureAISearch.UnitTests/AzureAISearchFilteringTest.cs b/extensions/AzureAISearch/AzureAISearch.UnitTests/AzureAISearchFilteringTest.cs index 4e57b4e8e..c6b7789da 100644 --- a/extensions/AzureAISearch/AzureAISearch.UnitTests/AzureAISearchFilteringTest.cs +++ b/extensions/AzureAISearch/AzureAISearch.UnitTests/AzureAISearchFilteringTest.cs @@ -20,7 +20,7 @@ public void ItRendersEmptyFilters() { // Arrange List filters1 = null!; - List filters2 = new(); + List filters2 = []; // Act var result1 = AzureAISearchFiltering.BuildSearchFilter(filters1); @@ -39,7 +39,7 @@ public void ItRendersEmptyFilters() public void ItRendersSimpleFilter() { // Arrange - List filters = new() { MemoryFilters.ByTag("color", "blue") }; + List filters = [MemoryFilters.ByTag("color", "blue")]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -55,11 +55,11 @@ public void ItRendersSimpleFilter() public void ItRendersSimpleFilters() { // Arrange - List filters = new() - { + List filters = + [ MemoryFilters.ByTag("color", "blue"), - MemoryFilters.ByTag("size", "medium"), - }; + MemoryFilters.ByTag("size", "medium") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -75,11 +75,11 @@ public void ItRendersSimpleFilters() public void ItRendersUsingSearchIn() { // Arrange - List filters = new() - { + List filters = + [ MemoryFilters.ByTag("color", "blue"), - MemoryFilters.ByTag("color", "green"), - }; + MemoryFilters.ByTag("color", "green") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -95,16 +95,16 @@ public void ItRendersUsingSearchIn() public void ItUsesSearchInWithAlternativeSeparators() { // Arrange - List filters1 = new() - { + List filters1 = + [ MemoryFilters.ByTag("color", "blue"), - MemoryFilters.ByTag("color", "green"), - }; - List filters2 = new() - { + MemoryFilters.ByTag("color", "green") + ]; + List filters2 = + [ MemoryFilters.ByTag("color", "bl|ue"), - MemoryFilters.ByTag("color", "gr|e|en"), - }; + MemoryFilters.ByTag("color", "gr|e|en") + ]; // Act var result1 = AzureAISearchFiltering.BuildSearchFilter(filters1); @@ -123,12 +123,11 @@ public void ItUsesSearchInWithAlternativeSeparators() public void ItHandlesComplexFilters() { // Arrange - List filters = new() - { - // (color == blue AND size == medium) OR (color == blue) + List filters = + [ MemoryFilters.ByTag("color", "blue").ByTag("size", "medium"), MemoryFilters.ByTag("color", "blue") - }; + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -145,12 +144,11 @@ public void ItHandlesComplexFilters() public void ItHandlesEdgeCase0() { // Arrange - List filters = new() - { - // (col|or == blue) OR (si,ze == small) + List filters = + [ MemoryFilters.ByTag("col|or", "blue"), - MemoryFilters.ByTag("si,ze", "small"), - }; + MemoryFilters.ByTag("si,ze", "small") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -165,15 +163,14 @@ public void ItHandlesEdgeCase0() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase1() { - // Arrange - List filters = new() - { - // (col|or == blue) OR (col|or == white) OR (si,ze == small) OR (si,ze == medium) + // Arrange - (col|or == blue) OR (col|or == white) OR (si,ze == small) OR (si,ze == medium) + List filters = + [ MemoryFilters.ByTag("col|or", "blue"), MemoryFilters.ByTag("col|or", "white"), MemoryFilters.ByTag("si,ze", "small"), - MemoryFilters.ByTag("si,ze", "medium"), - }; + MemoryFilters.ByTag("si,ze", "medium") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -189,15 +186,14 @@ public void ItHandlesEdgeCase1() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase2() { - // Arrange - List filters = new() - { - // (col|or == blue) OR (col|or == white) OR (si,ze == small) OR (si,ze == medium) + // Arrange - (col|or == blue) OR (col|or == white) OR (si,ze == small) OR (si,ze == medium) + List filters = + [ MemoryFilters.ByTag("col|or", "blue"), MemoryFilters.ByTag("col|or", "white"), MemoryFilters.ByTag("si,ze", "sm|all"), - MemoryFilters.ByTag("si,ze", "med;ium"), - }; + MemoryFilters.ByTag("si,ze", "med;ium") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -213,12 +209,11 @@ public void ItHandlesEdgeCase2() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase3() { - // Arrange - List filters = new() - { - // color == blue AND color == blue - MemoryFilters.ByTag("color", "blue").ByTag("color", "blue"), - }; + // Arrange - color == blue AND color == blue + List filters = + [ + MemoryFilters.ByTag("color", "blue").ByTag("color", "blue") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -233,13 +228,12 @@ public void ItHandlesEdgeCase3() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase4() { - // Arrange - List filters = new() - { - // (color == blue) OR (color == blue) + // Arrange - (color == blue) OR (color == blue) + List filters = + [ MemoryFilters.ByTag("color", "blue"), - MemoryFilters.ByTag("color", "blue"), - }; + MemoryFilters.ByTag("color", "blue") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -254,12 +248,11 @@ public void ItHandlesEdgeCase4() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase5() { - // Arrange - List filters = new() - { - // color == blue AND color == green - MemoryFilters.ByTag("color", "blue").ByTag("color", "green"), - }; + // Arrange - color == blue AND color == green + List filters = + [ + MemoryFilters.ByTag("color", "blue").ByTag("color", "green") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); @@ -274,13 +267,12 @@ public void ItHandlesEdgeCase5() [Trait("Category", "AzAISearch")] public void ItHandlesEdgeCase6() { - // Arrange - List filters = new() - { - // (color == blue AND color == green) OR (color == green) + // Arrange - (color == blue AND color == green) OR (color == green) + List filters = + [ MemoryFilters.ByTag("color", "blue").ByTag("color", "green"), - MemoryFilters.ByTag("color", "green"), - }; + MemoryFilters.ByTag("color", "green") + ]; // Act var result = AzureAISearchFiltering.BuildSearchFilter(filters); diff --git a/extensions/AzureAISearch/AzureAISearch/AzureAISearchMemory.cs b/extensions/AzureAISearch/AzureAISearch/AzureAISearchMemory.cs index 10c97827d..72eed149d 100644 --- a/extensions/AzureAISearch/AzureAISearch/AzureAISearchMemory.cs +++ b/extensions/AzureAISearch/AzureAISearch/AzureAISearchMemory.cs @@ -93,6 +93,7 @@ public AzureAISearchMemory( break; default: + case AzureAISearchConfig.AuthTypes.Unknown: this._log.LogCritical("Azure AI Search authentication type '{0}' undefined or not supported", config.Auth); throw new DocumentStorageException($"Azure AI Search authentication type '{config.Auth}' undefined or not supported"); } @@ -129,7 +130,7 @@ public Task DeleteIndexAsync(string index, CancellationToken cancellationToken = /// public async Task UpsertAsync(string index, MemoryRecord record, CancellationToken cancellationToken = default) { - var result = this.UpsertBatchAsync(index, new[] { record }, cancellationToken); + var result = this.UpsertBatchAsync(index, [record], cancellationToken); var id = await result.SingleAsync(cancellationToken).ConfigureAwait(false); return id; } @@ -286,7 +287,7 @@ public async Task DeleteAsync(string index, MemoryRecord record, CancellationTok this._log.LogDebug("Deleting record {0} from index {1}", id, index); Response? result = await client.DeleteDocumentsAsync( AzureAISearchMemoryRecord.IdField, - new List { id }, + [id], cancellationToken: cancellationToken) .ConfigureAwait(false); this._log.LogTrace("Delete response status: {0}, content: {1}", result.GetRawResponse().Status, result.GetRawResponse().Content.ToString()); @@ -459,7 +460,7 @@ private SearchIndex PrepareIndexSchema(string index, MemoryDbSchema schema) var indexSchema = new SearchIndex(index) { - Fields = new List(), + Fields = [], VectorSearch = new VectorSearch { Profiles = diff --git a/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchFiltering.cs b/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchFiltering.cs index af2e1a679..0ae27eeb1 100644 --- a/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchFiltering.cs +++ b/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchFiltering.cs @@ -8,7 +8,7 @@ namespace Microsoft.KernelMemory.MemoryDb.AzureAISearch; internal static class AzureAISearchFiltering { - private static readonly char[] s_searchInDelimitersAvailable = { '|', ',', ';', '-', '_', '.', ' ', '^', '$', '*', '`', '#', '@', '&', '/', '~' }; + private static readonly char[] s_searchInDelimitersAvailable = ['|', ',', ';', '-', '_', '.', ' ', '^', '$', '*', '`', '#', '@', '&', '/', '~']; /// /// Build a search query optimized to scale for in case a key has several (hundreds+) values @@ -23,10 +23,10 @@ internal static class AzureAISearchFiltering /// Query string for Azure AI Search internal static string BuildSearchFilter(IEnumerable filters) { - List conditions = new(); - var filterList = filters?.ToList() ?? new List(); + List conditions = []; + var filterList = filters?.ToList() ?? []; - // Get all non empty filters with the same key and more than one value, and combine them using "search.in" + // Get all non-empty filters with the same key and more than one value, and combine them using "search.in" // - If the filter has more than one filter we will exclude it, it means that needs to be composed with an AND (f.i. memoryFilter.ByTag("tag1", "value1").ByTag("tag2", "value2")) // - If the filter has only one filter, it means that it can be grouped with other filters with the same key to be composed with an OR var filtersForSearchInQuery = filterList diff --git a/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchMemoryRecord.cs b/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchMemoryRecord.cs index 7252b4284..cf6ced1d1 100644 --- a/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchMemoryRecord.cs +++ b/extensions/AzureAISearch/AzureAISearch/Internals/AzureAISearchMemoryRecord.cs @@ -37,7 +37,7 @@ internal sealed class AzureAISearchMemoryRecord #pragma warning restore CA1819 [JsonPropertyName(TagsField)] - public List Tags { get; set; } = new(); + public List Tags { get; set; } = []; [JsonPropertyName(PayloadField)] public string Payload { get; set; } = string.Empty; @@ -46,13 +46,13 @@ public static MemoryDbSchema GetSchema(int vectorSize) { return new MemoryDbSchema { - Fields = new List - { + Fields = + [ new() { Name = IdField, Type = MemoryDbField.FieldType.Text, IsKey = true }, new() { Name = VectorField, Type = MemoryDbField.FieldType.Vector, VectorSize = vectorSize }, new() { Name = TagsField, Type = MemoryDbField.FieldType.ListOfStrings, IsFilterable = true }, - new() { Name = PayloadField, Type = MemoryDbField.FieldType.Text, IsFilterable = false }, - } + new() { Name = PayloadField, Type = MemoryDbField.FieldType.Text, IsFilterable = false } + ] }; } @@ -61,8 +61,7 @@ public MemoryRecord ToMemoryRecord(bool withEmbedding = true) MemoryRecord result = new() { Id = DecodeId(this.Id), - Payload = JsonSerializer.Deserialize>(this.Payload, s_jsonOptions) - ?? new Dictionary() + Payload = JsonSerializer.Deserialize>(this.Payload, s_jsonOptions) ?? [] }; if (withEmbedding) diff --git a/extensions/AzureAISearch/AzureAISearch/Internals/MemoryDbSchema.cs b/extensions/AzureAISearch/AzureAISearch/Internals/MemoryDbSchema.cs index f06245dfe..bd8696a6f 100644 --- a/extensions/AzureAISearch/AzureAISearch/Internals/MemoryDbSchema.cs +++ b/extensions/AzureAISearch/AzureAISearch/Internals/MemoryDbSchema.cs @@ -7,7 +7,7 @@ namespace Microsoft.KernelMemory.MemoryDb.AzureAISearch; internal sealed class MemoryDbSchema { - public List Fields { get; set; } = new(); + public List Fields { get; set; } = []; public void Validate(bool vectorSizeRequired = false) { diff --git a/extensions/AzureBlobs/AzureBlobsStorage.cs b/extensions/AzureBlobs/AzureBlobsStorage.cs index 993bc2a80..b6d403e60 100644 --- a/extensions/AzureBlobs/AzureBlobsStorage.cs +++ b/extensions/AzureBlobs/AzureBlobsStorage.cs @@ -90,6 +90,7 @@ public AzureBlobsStorage( } default: + case AzureBlobsConfig.AuthTypes.Unknown: this._log.LogCritical("Azure Blob authentication type '{0}' undefined or not supported", config.Auth); throw new DocumentStorageException($"Azure Blob authentication type '{config.Auth}' undefined or not supported"); } diff --git a/extensions/AzureOpenAI/AzureOpenAI/AzureOpenAITextGenerator.cs b/extensions/AzureOpenAI/AzureOpenAI/AzureOpenAITextGenerator.cs index 0661bed3e..a95e48c45 100644 --- a/extensions/AzureOpenAI/AzureOpenAI/AzureOpenAITextGenerator.cs +++ b/extensions/AzureOpenAI/AzureOpenAI/AzureOpenAITextGenerator.cs @@ -130,7 +130,7 @@ public async IAsyncEnumerable GenerateTextAsync( if (options.StopSequences is { Count: > 0 }) { - skOptions.StopSequences = new List(); + skOptions.StopSequences = []; foreach (var s in options.StopSequences) { skOptions.StopSequences.Add(s); } } diff --git a/extensions/AzureOpenAI/AzureOpenAI/Internals/ClientSequentialRetryPolicy.cs b/extensions/AzureOpenAI/AzureOpenAI/Internals/ClientSequentialRetryPolicy.cs index 4b6d561b3..bf76d01ce 100644 --- a/extensions/AzureOpenAI/AzureOpenAI/Internals/ClientSequentialRetryPolicy.cs +++ b/extensions/AzureOpenAI/AzureOpenAI/Internals/ClientSequentialRetryPolicy.cs @@ -10,7 +10,7 @@ namespace Microsoft.KernelMemory.AI.AzureOpenAI.Internals; internal sealed class ClientSequentialRetryPolicy : ClientRetryPolicy { private static readonly TimeSpan[] s_retryDelaySequence = - { + [ TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), @@ -19,7 +19,7 @@ internal sealed class ClientSequentialRetryPolicy : ClientRetryPolicy TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(8) - }; + ]; private static readonly TimeSpan s_maxDelay = s_retryDelaySequence[^1]; diff --git a/extensions/AzureQueues/AzureQueuesPipeline.cs b/extensions/AzureQueues/AzureQueuesPipeline.cs index 2ce06ebd8..a35c85591 100644 --- a/extensions/AzureQueues/AzureQueuesPipeline.cs +++ b/extensions/AzureQueues/AzureQueuesPipeline.cs @@ -124,6 +124,7 @@ public AzureQueuesPipeline( } default: + case AzureQueuesConfig.AuthTypes.Unknown: this._log.LogCritical("Azure Queue authentication type '{0}' undefined or not supported", config.Auth); throw new DocumentStorageException($"Azure Queue authentication type '{config.Auth}' undefined or not supported"); } diff --git a/extensions/AzureQueues/DependencyInjection.cs b/extensions/AzureQueues/DependencyInjection.cs index 1415b0ace..a42683cc3 100644 --- a/extensions/AzureQueues/DependencyInjection.cs +++ b/extensions/AzureQueues/DependencyInjection.cs @@ -30,7 +30,7 @@ public static IServiceCollection AddAzureQueuesOrchestration(this IServiceCollec { config.Validate(); - IQueue QueueFactory(IServiceProvider serviceProvider) + static IQueue QueueFactory(IServiceProvider serviceProvider) { return serviceProvider.GetService() ?? throw new KernelMemoryException("Unable to instantiate " + typeof(AzureQueuesPipeline)); diff --git a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/DataStorageTests.cs b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/DataStorageTests.cs index 1d30d6e45..55417a239 100644 --- a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/DataStorageTests.cs +++ b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/DataStorageTests.cs @@ -30,10 +30,7 @@ public async Task CanUpsertOneTextDocumentAndDeleteAsync() textEmbeddingGenerator: this.TextEmbeddingGenerator, output: this.Output, indexName: nameof(this.CanUpsertOneTextDocumentAndDeleteAsync), - fileNames: new[] - { - TestsHelper.WikipediaCarbonFileName - }).ConfigureAwait(false); + fileNames: [TestsHelper.WikipediaCarbonFileName]).ConfigureAwait(false); // Deletes the document var deletes = docIds.Select(id => new MemoryRecord() @@ -63,11 +60,11 @@ await UpsertTextFilesAsync( textEmbeddingGenerator: this.TextEmbeddingGenerator, output: this.Output, indexName: nameof(this.CanUpsertTwoTextFilesAndGetSimilarListAsync), - fileNames: new[] - { + fileNames: + [ TestsHelper.WikipediaCarbonFileName, TestsHelper.WikipediaMoonFilename - }).ConfigureAwait(false); + ]).ConfigureAwait(false); // Gets documents that are similar to the word "carbon" . var foundSomething = false; diff --git a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/KernelMemoryTests.cs b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/KernelMemoryTests.cs index 20b9bee1f..f77793350 100644 --- a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/KernelMemoryTests.cs +++ b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/KernelMemoryTests.cs @@ -55,47 +55,47 @@ await this.KernelMemory.ImportDocumentAsync( } // Multiple filters: unknown users cannot see the memory - var answer = await this.KernelMemory.AskAsync("What is Orion?", filters: new List - { + var answer = await this.KernelMemory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1"), MemoryFilters.ByTag("user", "someone2"), - }, index: indexName); + ], index: indexName); this.Output.WriteLine(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: unknown users cannot see the memory even if the type is correct (testing AND logic) - answer = await this.KernelMemory.AskAsync("What is Orion?", filters: new List - { + answer = await this.KernelMemory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "someone2").ByTag("type", "news"), - }, index: indexName); + ], index: indexName); this.Output.WriteLine(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: AND + OR logic works - answer = await this.KernelMemory.AskAsync("What is Orion?", filters: new List - { + answer = await this.KernelMemory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "admin").ByTag("type", "fact"), - }, index: indexName); + ], index: indexName); this.Output.WriteLine(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: OR logic works - answer = await this.KernelMemory.AskAsync("What is Orion?", filters: new List - { + answer = await this.KernelMemory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1"), MemoryFilters.ByTag("user", "admin"), - }, index: indexName); + ], index: indexName); this.Output.WriteLine(answer.Result); Assert.Contains(Found, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: OR logic works - answer = await this.KernelMemory.AskAsync("What is Orion?", filters: new List - { + answer = await this.KernelMemory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "admin").ByTag("type", "news"), - }, index: indexName); + ], index: indexName); this.Output.WriteLine(answer.Result); Assert.Contains(Found, answer.Result, StringComparison.OrdinalIgnoreCase); @@ -286,12 +286,11 @@ public async Task CanImportTwoDocumentsAndAskAsync() docId = await this.KernelMemory.ImportDocumentAsync( new Document("doc002") - .AddFiles(new[] - { + .AddFiles([ TestsHelper.WikipediaMoonFilename, TestsHelper.LoremIpsumFileName, TestsHelper.SKReadmeFileName - }) + ]) .AddTag("user", "Blake"), index: indexName) .ConfigureAwait(false); diff --git a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/SearchTests.cs b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/SearchTests.cs index e8958ac2c..2be5df621 100644 --- a/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/SearchTests.cs +++ b/extensions/Elasticsearch/Elasticsearch.FunctionalTests/Additional/SearchTests.cs @@ -36,11 +36,11 @@ public async Task CanGetListWithTagsAsync() textEmbeddingGenerator: this.TextEmbeddingGenerator, output: this.Output, indexName: nameof(this.CanGetListWithTagsAsync), - fileNames: new[] - { + fileNames: + [ TestsHelper.WikipediaCarbonFileName, - TestsHelper.WikipediaMoonFilename, - }) + TestsHelper.WikipediaMoonFilename + ]) .ConfigureAwait(false); // docsIds is a list of values like "d=3ed7b0787d484496ab25d50b2a887f8cf63193954fc844689116766434c11887//p=b84ee5e4841c4ab2877e30293752f7cc" @@ -52,16 +52,18 @@ public async Task CanGetListWithTagsAsync() var expectedDocs = docIds.Count(); // Gets documents that are similar to the word "carbon" . - var filter = new MemoryFilter(); - filter.Add("__file_type", "text/plain"); - filter.Add("__document_id", docIds.Select(x => (string?)x).ToList()); + var filter = new MemoryFilter + { + { "__file_type", "text/plain" }, + { "__document_id", docIds.Select(x => (string?)x).ToList() } + }; var idx = 0; this.Output.WriteLine($"Filter: {filter.ToDebugString()}.\n"); await foreach (var result in this.MemoryDb.GetListAsync( index: nameof(this.CanGetListWithTagsAsync), - filters: new[] { filter }, + filters: [filter], limit: 100, withEmbeddings: false)) { @@ -69,8 +71,6 @@ public async Task CanGetListWithTagsAsync() this.Output.WriteLine($"Match #{idx++}: {fileName}"); } - ; - Assert.Equal(expected: ExpectedTotalParagraphs, actual: idx); } @@ -80,7 +80,7 @@ public async Task CanGetListWithEmptyFiltersAsync() { await foreach (var result in this.MemoryDb.GetListAsync( index: nameof(this.CanGetListWithTagsAsync), - filters: new[] { new MemoryFilter() }, // <-- KM has a test to make sure this works. + filters: [[]], // <-- KM has a test to make sure this works. limit: 100, withEmbeddings: false)) { diff --git a/extensions/Elasticsearch/Elasticsearch/ElasticsearchMemory.cs b/extensions/Elasticsearch/Elasticsearch/ElasticsearchMemory.cs index c1056949f..b98877360 100644 --- a/extensions/Elasticsearch/Elasticsearch/ElasticsearchMemory.cs +++ b/extensions/Elasticsearch/Elasticsearch/ElasticsearchMemory.cs @@ -321,11 +321,11 @@ private QueryDescriptor ConvertTagFilters( return qd; } - List super = new(); + List super = []; foreach (MemoryFilter filter in filters) { - List thisMust = new(); + List thisMust = []; // Each filter is a list of key/value pairs. foreach (var pair in filter.Pairs) diff --git a/extensions/Elasticsearch/Elasticsearch/Internals/ElasticsearchMemoryRecord.cs b/extensions/Elasticsearch/Elasticsearch/Internals/ElasticsearchMemoryRecord.cs index 3e88bedb5..97a594e60 100644 --- a/extensions/Elasticsearch/Elasticsearch/Internals/ElasticsearchMemoryRecord.cs +++ b/extensions/Elasticsearch/Elasticsearch/Internals/ElasticsearchMemoryRecord.cs @@ -45,7 +45,7 @@ public sealed class ElasticsearchMemoryRecord /// TBC /// [JsonPropertyName(TagsField)] - public List Tags { get; set; } = new(); + public List Tags { get; set; } = []; /// /// TBC @@ -74,8 +74,7 @@ public MemoryRecord ToMemoryRecord(bool withEmbedding = true) MemoryRecord result = new() { Id = this.Id, - Payload = JsonSerializer.Deserialize>(this.Payload, s_jsonOptions) - ?? new Dictionary() + Payload = JsonSerializer.Deserialize>(this.Payload, s_jsonOptions) ?? [] }; // TODO: remove magic string result.Payload["text"] = this.Content; diff --git a/extensions/LlamaSharp/LlamaSharp.FunctionalTests/LlamaSharpTextGeneratorTest.cs b/extensions/LlamaSharp/LlamaSharp.FunctionalTests/LlamaSharpTextGeneratorTest.cs index 50016dd0a..3bca592e4 100644 --- a/extensions/LlamaSharp/LlamaSharp.FunctionalTests/LlamaSharpTextGeneratorTest.cs +++ b/extensions/LlamaSharp/LlamaSharp.FunctionalTests/LlamaSharpTextGeneratorTest.cs @@ -83,7 +83,7 @@ public async Task ItGeneratesText() { MaxTokens = 60, Temperature = 0, - StopSequences = new List { "Question" } + StopSequences = ["Question"] }; // Act diff --git a/extensions/LlamaSharp/LlamaSharp/LlamaSharpTextGenerator.cs b/extensions/LlamaSharp/LlamaSharp/LlamaSharpTextGenerator.cs index a0026b3c4..0290de95f 100644 --- a/extensions/LlamaSharp/LlamaSharp/LlamaSharpTextGenerator.cs +++ b/extensions/LlamaSharp/LlamaSharp/LlamaSharpTextGenerator.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using LLama; -using LLama.Abstractions; using LLama.Common; using LLama.Native; using LLama.Sampling; @@ -84,7 +83,7 @@ public IAsyncEnumerable GenerateTextAsync( var logitBias = options.TokenSelectionBiases.Count > 0 ? options.TokenSelectionBiases.ToDictionary(pair => (LLamaToken)pair.Key, pair => pair.Value) - : new Dictionary(); + : []; var samplingPipeline = new DefaultSamplingPipeline() { @@ -95,11 +94,11 @@ public IAsyncEnumerable GenerateTextAsync( LogitBias = logitBias, }; - IInferenceParams settings = new InferenceParams + var settings = new InferenceParams { TokensKeep = this.MaxTokenTotal, MaxTokens = options.MaxTokens ?? -1, - AntiPrompts = options.StopSequences?.ToList() ?? new(), + AntiPrompts = options.StopSequences?.ToList() ?? [], SamplingPipeline = samplingPipeline }; diff --git a/extensions/MongoDbAtlas/MongoDbAtlas/Internals/MongoDbAtlasMemoryRecord.cs b/extensions/MongoDbAtlas/MongoDbAtlas/Internals/MongoDbAtlasMemoryRecord.cs index 92425d851..7f4ae34d3 100644 --- a/extensions/MongoDbAtlas/MongoDbAtlas/Internals/MongoDbAtlasMemoryRecord.cs +++ b/extensions/MongoDbAtlas/MongoDbAtlas/Internals/MongoDbAtlasMemoryRecord.cs @@ -12,9 +12,9 @@ internal sealed class MongoDbAtlasMemoryRecord public float[] Embedding { get; set; } = null!; - public List Tags { get; set; } = new(); + public List Tags { get; set; } = []; - public List Payloads { get; set; } = new(); + public List Payloads { get; set; } = []; internal sealed class Payload { diff --git a/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasBaseStorage.cs b/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasBaseStorage.cs index ccd39e804..2b12ad82b 100644 --- a/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasBaseStorage.cs +++ b/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasBaseStorage.cs @@ -28,7 +28,7 @@ public abstract class MongoDbAtlasBaseStorage /// Keys are mongo collection of T but since we do not know T we cache them /// as simple object then cast to the correct value. /// - private Dictionary Collections { get; set; } = new(); + private Dictionary Collections { get; set; } = []; /// /// Create an instance of the storage based on configuration diff --git a/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasMemory.cs b/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasMemory.cs index 1183188d6..0681927fd 100644 --- a/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasMemory.cs +++ b/extensions/MongoDbAtlas/MongoDbAtlas/MongoDbAtlasMemory.cs @@ -215,11 +215,11 @@ public async Task UpsertAsync(string index, MemoryRecord record, Cancell private FilterDefinition? TranslateFilters(ICollection? filters, string index) { - List> outerFiltersArray = new(); + List> outerFiltersArray = []; foreach (var filter in filters ?? Array.Empty()) { var thisFilter = filter.GetFilters().ToArray(); - List> filtersArray = new(); + List> filtersArray = []; foreach (var singleFilter in thisFilter) { var condition = Builders.Filter.And( @@ -327,7 +327,7 @@ private static MemoryRecord FromMongodbMemoryRecord(MongoDbAtlasMemoryRecord doc var record = new MemoryRecord { Id = doc.Id, - Vector = withEmbeddings ? doc.Embedding : Array.Empty(), + Vector = withEmbeddings ? doc.Embedding : [], }; foreach (var tag in doc.Tags) diff --git a/extensions/ONNX/Onnx/OnnxTextGenerator.cs b/extensions/ONNX/Onnx/OnnxTextGenerator.cs index 1a51a5108..adfa0c8cc 100644 --- a/extensions/ONNX/Onnx/OnnxTextGenerator.cs +++ b/extensions/ONNX/Onnx/OnnxTextGenerator.cs @@ -149,7 +149,7 @@ public async IAsyncEnumerable GenerateTextAsync( using (var generator = new Generator(this._model, generatorParams)) { - List outputTokens = new(); + List outputTokens = []; while (!generator.IsDone() && cancellationToken.IsCancellationRequested == false) { @@ -161,7 +161,7 @@ public async IAsyncEnumerable GenerateTextAsync( if (outputTokens.Count > 0 && this._tokenizer != null) { var newToken = outputTokens[^1]; - yield return this._tokenizer.Decode(new int[] { newToken }); + yield return this._tokenizer.Decode([newToken]); } } } diff --git a/extensions/Ollama/Ollama/OllamaTextGenerator.cs b/extensions/Ollama/Ollama/OllamaTextGenerator.cs index 2bf0cd445..5f15d7428 100644 --- a/extensions/Ollama/Ollama/OllamaTextGenerator.cs +++ b/extensions/Ollama/Ollama/OllamaTextGenerator.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.KernelMemory.AI.OpenAI; using Microsoft.KernelMemory.Context; @@ -143,7 +144,7 @@ public async IAsyncEnumerable GenerateTextAsync( var chat = new Chat(this._client); IAsyncEnumerable stream = chat.SendAsync(prompt, cancellationToken); - await foreach (string? token in stream) + await foreach (string? token in stream.ConfigureAwait(false)) { if (token != null) { yield return token; } } diff --git a/extensions/OpenAI/OpenAI/Internals/ClientSequentialRetryPolicy.cs b/extensions/OpenAI/OpenAI/Internals/ClientSequentialRetryPolicy.cs index aa2bf6335..56214d7ca 100644 --- a/extensions/OpenAI/OpenAI/Internals/ClientSequentialRetryPolicy.cs +++ b/extensions/OpenAI/OpenAI/Internals/ClientSequentialRetryPolicy.cs @@ -10,7 +10,7 @@ namespace Microsoft.KernelMemory.AI.OpenAI.Internals; internal sealed class ClientSequentialRetryPolicy : ClientRetryPolicy { private static readonly TimeSpan[] s_retryDelaySequence = - { + [ TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), @@ -19,7 +19,7 @@ internal sealed class ClientSequentialRetryPolicy : ClientRetryPolicy TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(8) - }; + ]; private static readonly TimeSpan s_maxDelay = s_retryDelaySequence[^1]; diff --git a/extensions/OpenAI/OpenAI/OpenAITextGenerator.cs b/extensions/OpenAI/OpenAI/OpenAITextGenerator.cs index 8faa3e947..c0cd6b0b7 100644 --- a/extensions/OpenAI/OpenAI/OpenAITextGenerator.cs +++ b/extensions/OpenAI/OpenAI/OpenAITextGenerator.cs @@ -129,7 +129,7 @@ public async IAsyncEnumerable GenerateTextAsync( if (options.StopSequences is { Count: > 0 }) { - skOptions.StopSequences = new List(); + skOptions.StopSequences = []; foreach (var s in options.StopSequences) { skOptions.StopSequences.Add(s); } } diff --git a/extensions/Postgres/Postgres.FunctionalTests/AdditionalFilteringTests.cs b/extensions/Postgres/Postgres.FunctionalTests/AdditionalFilteringTests.cs index 028802057..97c9b6c10 100644 --- a/extensions/Postgres/Postgres.FunctionalTests/AdditionalFilteringTests.cs +++ b/extensions/Postgres/Postgres.FunctionalTests/AdditionalFilteringTests.cs @@ -42,7 +42,7 @@ public async Task ItFiltersSourcesCorrectly() Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("red", answer.Result, StringComparison.OrdinalIgnoreCase); - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "hulk") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "hulk")]); Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("red", answer.Result, StringComparison.OrdinalIgnoreCase); @@ -59,12 +59,12 @@ public async Task ItFiltersSourcesCorrectly() Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("green", answer.Result, StringComparison.OrdinalIgnoreCase); - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "flash") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "flash")]); Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("green", answer.Result, StringComparison.OrdinalIgnoreCase); // Act + Assert - See both memories - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "hulk"), MemoryFilters.ByTag("user", "flash") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "hulk"), MemoryFilters.ByTag("user", "flash")]); Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); diff --git a/extensions/Postgres/Postgres.FunctionalTests/ConcurrencyTests.cs b/extensions/Postgres/Postgres.FunctionalTests/ConcurrencyTests.cs index 2fc2a68fa..328b3ec0b 100644 --- a/extensions/Postgres/Postgres.FunctionalTests/ConcurrencyTests.cs +++ b/extensions/Postgres/Postgres.FunctionalTests/ConcurrencyTests.cs @@ -79,7 +79,7 @@ last_update TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL await Task.WhenAll(tasks); - tasks = new List(); + tasks = []; for (int i = 0; i < concurrency; i++) { tasks.Add(target.DeleteIndexAsync(indexName)); @@ -103,7 +103,7 @@ public async Task UpsertConcurrencyTest() var record = new MemoryRecord { Id = "one", - Vector = new Embedding(new float[] { 0, 1, 2, 3 }) + Vector = new Embedding([0, 1, 2, 3]) }; var tasks = new List(); @@ -114,7 +114,7 @@ public async Task UpsertConcurrencyTest() await Task.WhenAll(tasks); - tasks = new List(); + tasks = []; for (int i = 0; i < concurrency; i++) { tasks.Add(target.DeleteAsync(indexName, record)); diff --git a/extensions/Postgres/Postgres/Internals/PostgresDbClient.cs b/extensions/Postgres/Postgres/Internals/PostgresDbClient.cs index 7d05b4b92..5ec4ddbe7 100644 --- a/extensions/Postgres/Postgres/Internals/PostgresDbClient.cs +++ b/extensions/Postgres/Postgres/Internals/PostgresDbClient.cs @@ -424,7 +424,7 @@ DO UPDATE SET var maxDistance = 1 - minSimilarity; filterSql += $" AND {this._colEmbedding} <=> @embedding < @maxDistance"; - if (sqlUserValues == null) { sqlUserValues = new(); } + if (sqlUserValues == null) { sqlUserValues = []; } this._log.LogTrace("Searching by similarity. Table: {0}. Threshold: {1}. Limit: {2}. Offset: {3}. Using SQL filter: {4}", tableName, minSimilarity, limit, offset, string.IsNullOrWhiteSpace(filterSql) ? "false" : "true"); diff --git a/extensions/Postgres/Postgres/Internals/PostgresMemoryRecord.cs b/extensions/Postgres/Postgres/Internals/PostgresMemoryRecord.cs index 4da86d85e..13879a379 100644 --- a/extensions/Postgres/Postgres/Internals/PostgresMemoryRecord.cs +++ b/extensions/Postgres/Postgres/Internals/PostgresMemoryRecord.cs @@ -36,7 +36,7 @@ internal sealed class PostgresMemoryRecord /// /// List of tags /// - public List Tags { get; set; } = new(); + public List Tags { get; set; } = []; /// /// Memory content @@ -59,8 +59,7 @@ public static MemoryRecord ToMemoryRecord(PostgresMemoryRecord pgRecord) { Id = pgRecord.Id, Vector = new Embedding(pgRecord.Embedding.ToArray()), - Payload = JsonSerializer.Deserialize>(pgRecord.Payload, s_jsonOptions) - ?? new Dictionary() + Payload = JsonSerializer.Deserialize>(pgRecord.Payload, s_jsonOptions) ?? [] }; result.Payload[Constants.ReservedPayloadTextField] = pgRecord.Content; diff --git a/extensions/Postgres/Postgres/PostgresConfig.cs b/extensions/Postgres/Postgres/PostgresConfig.cs index 77c0a39b6..f34be9637 100644 --- a/extensions/Postgres/Postgres/PostgresConfig.cs +++ b/extensions/Postgres/Postgres/PostgresConfig.cs @@ -105,7 +105,7 @@ public class PostgresConfig /// CREATE INDEX IF NOT EXISTS idx_tags ON %%table_name%% USING GIN(tags); /// COMMIT; /// - public List CreateTableSql { get; set; } = new(); + public List CreateTableSql { get; set; } = []; /// /// Create a new instance of the configuration diff --git a/extensions/Postgres/Postgres/PostgresMemory.cs b/extensions/Postgres/Postgres/PostgresMemory.cs index bd7854c9c..27a92745c 100644 --- a/extensions/Postgres/Postgres/PostgresMemory.cs +++ b/extensions/Postgres/Postgres/PostgresMemory.cs @@ -259,7 +259,7 @@ private static string NormalizeTableNamePrefix(string? name) ICollection? filters = null) { var sql = ""; - Dictionary unsafeSqlUserValues = new(); + Dictionary unsafeSqlUserValues = []; if (filters is not { Count: > 0 }) { @@ -281,7 +281,7 @@ private static string NormalizeTableNamePrefix(string? name) } List requiredTags = filter.GetFilters().Select(x => $"{x.Key}{Constants.ReservedEqualsChar}{x.Value}").ToList(); - List safeSqlPlaceholders = new(); + List safeSqlPlaceholders = []; if (requiredTags.Count > 0) { var safeSqlPlaceholder = $"@placeholder{tagCounter++}"; diff --git a/extensions/Qdrant/Qdrant.TestApplication/Program.cs b/extensions/Qdrant/Qdrant.TestApplication/Program.cs index d053d7fed..a358c45a5 100644 --- a/extensions/Qdrant/Qdrant.TestApplication/Program.cs +++ b/extensions/Qdrant/Qdrant.TestApplication/Program.cs @@ -43,7 +43,7 @@ public static async Task Main() Id = "memory 1", Vector = embedding, Tags = new TagCollection { { "updated", "no" }, { "type", "email" } }, - Payload = new Dictionary() + Payload = [] }; var id1 = await memory.UpsertAsync("test", memoryRecord1); @@ -56,7 +56,7 @@ public static async Task Main() Id = "memory two", Vector = new[] { 0f, 0, 1, 0, 1 }, Tags = new TagCollection { { "type", "news" } }, - Payload = new Dictionary() + Payload = [] }; var id2 = await memory.UpsertAsync("test", memoryRecord2); @@ -81,7 +81,7 @@ public static async Task Main() Console.WriteLine("===== SEARCH 2 ====="); similarList = memory.GetSimilarListAsync("test", text: Text, - limit: 10, withEmbeddings: true, filters: new List { MemoryFilters.ByTag("type", "email") }); + limit: 10, withEmbeddings: true, filters: [MemoryFilters.ByTag("type", "email")]); await foreach ((MemoryRecord, double) record in similarList) { Console.WriteLine(record.Item1.Id); diff --git a/extensions/Qdrant/Qdrant.UnitTests/ScrollVectorsRequestTest.cs b/extensions/Qdrant/Qdrant.UnitTests/ScrollVectorsRequestTest.cs index 3550e6027..9b3dccfc5 100644 --- a/extensions/Qdrant/Qdrant.UnitTests/ScrollVectorsRequestTest.cs +++ b/extensions/Qdrant/Qdrant.UnitTests/ScrollVectorsRequestTest.cs @@ -93,11 +93,10 @@ public void FiltersAreRenderedToJson() var request = ScrollVectorsRequest .Create("coll") .HavingAllTags(["user:devis", "type:blog"]) - .HavingSomeTags(new[] - { - new[] { "month:january", "year:2000" }, - new[] { "month:july", "year:2003" }, - }); + .HavingSomeTags([ + ["month:january", "year:2000"], + ["month:july", "year:2003"] + ]); // Act var actual = JsonSerializer.Serialize(request); @@ -158,7 +157,7 @@ public void ItRendersOptimizedConditions() var request = ScrollVectorsRequest .Create("coll") .HavingAllTags(["user:devis", "type:blog"]) - .HavingSomeTags([new[] { "month:january", "year:2000" }]); + .HavingSomeTags([["month:january", "year:2000"]]); // Act var actual = JsonSerializer.Serialize(request); diff --git a/extensions/Qdrant/Qdrant/Internals/DefaultQdrantPayload.cs b/extensions/Qdrant/Qdrant/Internals/DefaultQdrantPayload.cs index 3ef7d9ed6..ac2200ea8 100644 --- a/extensions/Qdrant/Qdrant/Internals/DefaultQdrantPayload.cs +++ b/extensions/Qdrant/Qdrant/Internals/DefaultQdrantPayload.cs @@ -13,7 +13,7 @@ internal class DefaultQdrantPayload public string Id { get; set; } = string.Empty; [JsonPropertyName(QdrantConstants.PayloadTagsField)] - public List Tags { get; set; } = new(); + public List Tags { get; set; } = []; [JsonPropertyName(QdrantConstants.PayloadPayloadField)] public string Payload { get; set; } = string.Empty; diff --git a/extensions/Qdrant/Qdrant/Internals/Http/CreateCollectionRequest.cs b/extensions/Qdrant/Qdrant/Internals/Http/CreateCollectionRequest.cs index f8e2d6db5..33f8ca6c1 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/CreateCollectionRequest.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/CreateCollectionRequest.cs @@ -26,7 +26,7 @@ public string DistanceAsString QdrantDistanceType.DotProduct => "DotProduct", QdrantDistanceType.Euclidean => "Euclidean", QdrantDistanceType.Manhattan => "Manhattan", - _ => throw new NotSupportedException($"Distance type {Enum.GetName(typeof(QdrantDistanceType), this._distanceType)} not supported") + _ => throw new NotSupportedException($"Distance type {Enum.GetName(this._distanceType)} not supported") }; } } diff --git a/extensions/Qdrant/Qdrant/Internals/Http/DeleteVectorsRequest.cs b/extensions/Qdrant/Qdrant/Internals/Http/DeleteVectorsRequest.cs index 49d3f36e2..e454cd96c 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/DeleteVectorsRequest.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/DeleteVectorsRequest.cs @@ -43,7 +43,7 @@ public HttpRequestMessage Build() private DeleteVectorsRequest(string collectionName) { - this.Ids = new List(); + this.Ids = []; this._collectionName = collectionName; } diff --git a/extensions/Qdrant/Qdrant/Internals/Http/Filter.cs b/extensions/Qdrant/Qdrant/Internals/Http/Filter.cs index d7df0ab82..dd2a76a8d 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/Filter.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/Filter.cs @@ -14,7 +14,7 @@ internal sealed class OrClause internal OrClause() { - this.Clauses = new(); + this.Clauses = []; } internal OrClause Or(object condition) @@ -59,7 +59,7 @@ internal sealed class AndClause internal AndClause() { - this.Clauses = new(); + this.Clauses = []; } internal AndClause And(object condition) diff --git a/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsRequest.cs b/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsRequest.cs index 1294f51f8..3ee4df3e3 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsRequest.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsRequest.cs @@ -21,7 +21,7 @@ internal sealed class GetVectorsRequest /// Array of vector IDs to retrieve /// [JsonPropertyName("ids")] - public IEnumerable PointIds { get; set; } = new List(); + public IEnumerable PointIds { get; set; } = []; /// /// Select which payload to return with the response. Default: All diff --git a/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsResponse.cs b/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsResponse.cs index 3dc72a770..887d88016 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsResponse.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/GetVectorsResponse.cs @@ -11,5 +11,5 @@ namespace Microsoft.KernelMemory.MemoryDb.Qdrant.Client.Http; /// Array of vectors and their associated metadata /// [JsonPropertyName("result")] - public IEnumerable> Results { get; set; } = new List>(); + public IEnumerable> Results { get; set; } = []; } diff --git a/extensions/Qdrant/Qdrant/Internals/Http/ListCollectionsResponse.cs b/extensions/Qdrant/Qdrant/Internals/Http/ListCollectionsResponse.cs index d4b18ca44..43d85dcde 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/ListCollectionsResponse.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/ListCollectionsResponse.cs @@ -22,7 +22,7 @@ internal sealed class CollectionDescription /// List of the collection names that the qdrant database contains. /// [JsonPropertyName("collections")] - public IList Collections { get; set; } = new List(); + public IList Collections { get; set; } = []; } /// diff --git a/extensions/Qdrant/Qdrant/Internals/Http/ScrollVectorsResponse.cs b/extensions/Qdrant/Qdrant/Internals/Http/ScrollVectorsResponse.cs index 2c942c043..d0c8f0d51 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/ScrollVectorsResponse.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/ScrollVectorsResponse.cs @@ -19,7 +19,7 @@ internal sealed class ScoredPoint : QdrantPoint internal sealed class ScrollResult { [JsonPropertyName("points")] - public IEnumerable> Points { get; set; } = new List>(); + public IEnumerable> Points { get; set; } = []; } [JsonPropertyName("result")] diff --git a/extensions/Qdrant/Qdrant/Internals/Http/SearchVectorsResponse.cs b/extensions/Qdrant/Qdrant/Internals/Http/SearchVectorsResponse.cs index a98c7542e..0657ba428 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/SearchVectorsResponse.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/SearchVectorsResponse.cs @@ -17,5 +17,5 @@ internal sealed class ScoredPoint : QdrantPoint } [JsonPropertyName("result")] - public IEnumerable Results { get; set; } = new List(); + public IEnumerable Results { get; set; } = []; } diff --git a/extensions/Qdrant/Qdrant/Internals/Http/UpsertVectorRequest.cs b/extensions/Qdrant/Qdrant/Internals/Http/UpsertVectorRequest.cs index f48ffe387..e7930794e 100644 --- a/extensions/Qdrant/Qdrant/Internals/Http/UpsertVectorRequest.cs +++ b/extensions/Qdrant/Qdrant/Internals/Http/UpsertVectorRequest.cs @@ -12,13 +12,13 @@ namespace Microsoft.KernelMemory.MemoryDb.Qdrant.Client.Http; internal sealed class BatchRequest { [JsonPropertyName("ids")] - public List Ids { get; set; } = new(); + public List Ids { get; set; } = []; [JsonPropertyName("vectors")] - public List Vectors { get; set; } = new(); + public List Vectors { get; set; } = []; [JsonPropertyName("payloads")] - public List Payloads { get; set; } = new(); + public List Payloads { get; set; } = []; } private readonly string _collectionName; diff --git a/extensions/Qdrant/Qdrant/Internals/QdrantClient.cs b/extensions/Qdrant/Qdrant/Internals/QdrantClient.cs index 8abf979ad..7b4706cfb 100644 --- a/extensions/Qdrant/Qdrant/Internals/QdrantClient.cs +++ b/extensions/Qdrant/Qdrant/Internals/QdrantClient.cs @@ -300,7 +300,7 @@ public async Task>> GetListAsync( if (response.StatusCode == HttpStatusCode.NotFound) { this._log.LogDebug("HTTP 404: {0}", content); - return new List>(); + return []; } this.ValidateResponse(response, content, nameof(this.GetListAsync)); @@ -315,7 +315,7 @@ public async Task>> GetListAsync( if (!data.Results.Points.Any()) { this._log.LogDebug("No vectors found"); - return new List>(); + return []; } return data.Results.Points.ToList(); diff --git a/extensions/Qdrant/Qdrant/Internals/QdrantPoint.cs b/extensions/Qdrant/Qdrant/Internals/QdrantPoint.cs index 9c2dcbbd2..600ee1e10 100644 --- a/extensions/Qdrant/Qdrant/Internals/QdrantPoint.cs +++ b/extensions/Qdrant/Qdrant/Internals/QdrantPoint.cs @@ -29,8 +29,7 @@ public MemoryRecord ToMemoryRecord(bool withEmbedding = true) MemoryRecord result = new() { Id = this.Payload.Id, - Payload = JsonSerializer.Deserialize>(this.Payload.Payload, QdrantConfig.JSONOptions) - ?? new Dictionary() + Payload = JsonSerializer.Deserialize>(this.Payload.Payload, QdrantConfig.JSONOptions) ?? [] }; if (withEmbedding) diff --git a/extensions/Qdrant/Qdrant/QdrantMemory.cs b/extensions/Qdrant/Qdrant/QdrantMemory.cs index 820b20b92..64607f690 100644 --- a/extensions/Qdrant/Qdrant/QdrantMemory.cs +++ b/extensions/Qdrant/Qdrant/QdrantMemory.cs @@ -260,7 +260,7 @@ public async Task DeleteAsync( } this._log.LogTrace("Point ID {0} found, deleting...", existingPoint.Id); - await this._qdrantClient.DeleteVectorsAsync(index, new List { existingPoint.Id }, cancellationToken).ConfigureAwait(false); + await this._qdrantClient.DeleteVectorsAsync(index, [existingPoint.Id], cancellationToken).ConfigureAwait(false); } catch (IndexNotFoundException e) { diff --git a/extensions/RabbitMQ/RabbitMQ/DependencyInjection.cs b/extensions/RabbitMQ/RabbitMQ/DependencyInjection.cs index 2508cad14..0a954dbbe 100644 --- a/extensions/RabbitMQ/RabbitMQ/DependencyInjection.cs +++ b/extensions/RabbitMQ/RabbitMQ/DependencyInjection.cs @@ -30,7 +30,7 @@ public static IServiceCollection AddRabbitMQOrchestration(this IServiceCollectio { config.Validate(); - IQueue QueueFactory(IServiceProvider serviceProvider) + static IQueue QueueFactory(IServiceProvider serviceProvider) { return serviceProvider.GetService() ?? throw new KernelMemoryException("Unable to instantiate " + typeof(RabbitMQPipeline)); diff --git a/extensions/Redis/Redis.FunctionalTests/AdditionalFilteringTests.cs b/extensions/Redis/Redis.FunctionalTests/AdditionalFilteringTests.cs index 4c5396d81..3418928a7 100644 --- a/extensions/Redis/Redis.FunctionalTests/AdditionalFilteringTests.cs +++ b/extensions/Redis/Redis.FunctionalTests/AdditionalFilteringTests.cs @@ -44,7 +44,7 @@ public async Task ItFiltersSourcesCorrectly() Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("red", answer.Result, StringComparison.OrdinalIgnoreCase); - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "hulk") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "hulk")]); Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("red", answer.Result, StringComparison.OrdinalIgnoreCase); @@ -61,12 +61,12 @@ public async Task ItFiltersSourcesCorrectly() Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("green", answer.Result, StringComparison.OrdinalIgnoreCase); - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "flash") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "x"), MemoryFilters.ByTag("user", "flash")]); Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("green", answer.Result, StringComparison.OrdinalIgnoreCase); // Act + Assert - See both memories - answer = await this._memory.AskAsync(Q, filters: new[] { MemoryFilters.ByTag("user", "hulk"), MemoryFilters.ByTag("user", "flash") }); + answer = await this._memory.AskAsync(Q, filters: [MemoryFilters.ByTag("user", "hulk"), MemoryFilters.ByTag("user", "flash")]); Assert.Contains("green", answer.Result, StringComparison.OrdinalIgnoreCase); Assert.Contains("red", answer.Result, StringComparison.OrdinalIgnoreCase); diff --git a/extensions/Redis/Redis.TestApplication/MockEmbeddingGenerator.cs b/extensions/Redis/Redis.TestApplication/MockEmbeddingGenerator.cs index 6019b83a8..42086da97 100644 --- a/extensions/Redis/Redis.TestApplication/MockEmbeddingGenerator.cs +++ b/extensions/Redis/Redis.TestApplication/MockEmbeddingGenerator.cs @@ -7,7 +7,7 @@ namespace Microsoft.Redis.TestApplication; internal sealed class MockEmbeddingGenerator : ITextEmbeddingGenerator { - private readonly Dictionary _embeddings = new(); + private readonly Dictionary _embeddings = []; internal void AddFakeEmbedding(string str, Embedding vector) { @@ -18,7 +18,7 @@ internal void AddFakeEmbedding(string str, Embedding vector) public int CountTokens(string text) => 0; /// - public IReadOnlyList GetTokens(string text) => Array.Empty(); + public IReadOnlyList GetTokens(string text) => []; /// public int MaxTokens => 0; diff --git a/extensions/Redis/Redis.TestApplication/Program.cs b/extensions/Redis/Redis.TestApplication/Program.cs index fc326f367..73c440787 100644 --- a/extensions/Redis/Redis.TestApplication/Program.cs +++ b/extensions/Redis/Redis.TestApplication/Program.cs @@ -44,7 +44,7 @@ public static async Task Main() Id = "memory 1", Vector = embeddings[0], Tags = new TagCollection { { "updated", "no" }, { "type", "email" } }, - Payload = new Dictionary() + Payload = [] }; var memoryRecord2 = new MemoryRecord @@ -52,7 +52,7 @@ public static async Task Main() Id = "memory 2", Vector = embeddings[0], Tags = new TagCollection { { "updated", "no" }, { "type", "email" } }, - Payload = new Dictionary() + Payload = [] }; var id1 = await memory.UpsertAsync("test", memoryRecord1); @@ -76,7 +76,7 @@ public static async Task Main() Id = "memory three", Vector = embeddings[1], Tags = new TagCollection { { "type", "news" } }, - Payload = new Dictionary() + Payload = [] }; var id3 = await memory.UpsertAsync("test", memoryRecord3); @@ -103,7 +103,7 @@ public static async Task Main() similarList = memory.GetSimilarListAsync( "test", text: Text1, limit: 10, withEmbeddings: true, - filters: new List { MemoryFilters.ByTag("type", "email") }); + filters: [MemoryFilters.ByTag("type", "email")]); await foreach ((MemoryRecord, double) record in similarList) { Console.WriteLine(record.Item1.Id); diff --git a/extensions/Redis/Redis/RedisMemory.cs b/extensions/Redis/Redis/RedisMemory.cs index 60bd72ccd..8d674e54f 100644 --- a/extensions/Redis/Redis/RedisMemory.cs +++ b/extensions/Redis/Redis/RedisMemory.cs @@ -149,11 +149,11 @@ public async Task UpsertAsync(string index, MemoryRecord record, Cancell args.Add(JsonSerializer.Serialize(record.Payload)); } - var scriptResult = (await this._db.ScriptEvaluateAsync(Scripts.CheckIndexAndUpsert, new RedisKey[] { key }, args.ToArray()).ConfigureAwait(false)).ToString()!; + var scriptResult = (await this._db.ScriptEvaluateAsync(Scripts.CheckIndexAndUpsert, [key], args.ToArray()).ConfigureAwait(false)).ToString()!; if (scriptResult == "false") { await this.CreateIndexAsync(index, record.Vector.Length, cancellationToken).ConfigureAwait(false); - await this._db.ScriptEvaluateAsync(Scripts.CheckIndexAndUpsert, new RedisKey[] { key }, args.ToArray()).ConfigureAwait(false); + await this._db.ScriptEvaluateAsync(Scripts.CheckIndexAndUpsert, [key], args.ToArray()).ConfigureAwait(false); } else if (scriptResult.StartsWith("(error)", StringComparison.Ordinal)) { @@ -272,7 +272,7 @@ public async IAsyncEnumerable GetListAsync(string index, ICollecti query.ReturnFields(this._fieldNamesNoEmbeddings); } - List documents = new(); + List documents = []; try { // handle the case of negative indexes (-1 = end, -2 = 1 from end, etc. . .) @@ -342,10 +342,10 @@ public Task DeleteAsync(string index, MemoryRecord record, CancellationToken can /// Characters to escape when serializing a tag expression. /// private static readonly char[] s_tagEscapeChars = - { + [ ',', '.', '<', '>', '{', '}', '[', ']', '"', '\'', ':', ';', - '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', '~', '|', ' ', '/', - }; + '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', '~', '|', ' ', '/' + ]; /// /// Special chars to specifically replace within index names to keep @@ -376,7 +376,7 @@ public Task DeleteAsync(string index, MemoryRecord record, CancellationToken can else if (field.Key == PayloadFieldName) { var payload = JsonSerializer.Deserialize>(field.Value.ToString()); - memoryRecord.Payload = payload ?? new Dictionary(); + memoryRecord.Payload = payload ?? []; } else if (field.Key == DistanceFieldName) { diff --git a/extensions/SQLServer/SQLServer/SqlServerMemory.cs b/extensions/SQLServer/SQLServer/SqlServerMemory.cs index f00a60c97..5adb98866 100644 --- a/extensions/SQLServer/SQLServer/SqlServerMemory.cs +++ b/extensions/SQLServer/SQLServer/SqlServerMemory.cs @@ -179,7 +179,7 @@ public async Task> GetIndexesAsync(CancellationToken cancell { if (!this._isReady) { await this.InitAsync(cancellationToken).ConfigureAwait(false); } - List indexes = new(); + List indexes = []; var sql = this._queryProvider.PrepareGetIndexesQuery(); diff --git a/service/Abstractions/AI/Embedding.cs b/service/Abstractions/AI/Embedding.cs index aa2566868..3fddff0fd 100644 --- a/service/Abstractions/AI/Embedding.cs +++ b/service/Abstractions/AI/Embedding.cs @@ -31,7 +31,7 @@ public struct Embedding : IEquatable /// Note: use Embedding.JsonConverter to serialize objects using this type. /// [JsonIgnore] - public int Length => this.Data.Length; + public readonly int Length => this.Data.Length; public Embedding(float[] vector) { @@ -60,7 +60,7 @@ public Embedding(int size) this.Data = new ReadOnlyMemory(new float[size]); } - public double CosineSimilarity(Embedding embedding) + public readonly double CosineSimilarity(Embedding embedding) { var size1 = this.Data.Span.Length; var size2 = embedding.Data.Span.Length; @@ -84,15 +84,15 @@ public double CosineSimilarity(Embedding embedding) /// public static implicit operator Embedding(float[] data) => new(data); - public bool Equals(Embedding other) => this.Data.Equals(other.Data); + public readonly bool Equals(Embedding other) => this.Data.Equals(other.Data); - public override bool Equals(object? obj) => (obj is Embedding other && this.Equals(other)); + public override readonly bool Equals(object? obj) => (obj is Embedding other && this.Equals(other)); public static bool operator ==(Embedding v1, Embedding v2) => v1.Equals(v2); public static bool operator !=(Embedding v1, Embedding v2) => !(v1 == v2); - public override int GetHashCode() => this.Data.GetHashCode(); + public override readonly int GetHashCode() => this.Data.GetHashCode(); /// /// Note: use Embedding.JsonConverter to serialize objects using @@ -109,7 +109,7 @@ public sealed class JsonConverter : JsonConverter public override Embedding Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new Embedding(s_converter.Read(ref reader, typeof(float[]), options) ?? Array.Empty()); + return new Embedding(s_converter.Read(ref reader, typeof(float[]), options) ?? []); } public override void Write(Utf8JsonWriter writer, Embedding value, JsonSerializerOptions options) diff --git a/service/Abstractions/AI/TextGenerationOptions.cs b/service/Abstractions/AI/TextGenerationOptions.cs index f72dfe280..3e7db7347 100644 --- a/service/Abstractions/AI/TextGenerationOptions.cs +++ b/service/Abstractions/AI/TextGenerationOptions.cs @@ -57,5 +57,5 @@ public class TextGenerationOptions /// /// Modify the likelihood of specified tokens appearing in the completion. /// - public Dictionary TokenSelectionBiases { get; set; } = new(); + public Dictionary TokenSelectionBiases { get; set; } = []; } diff --git a/service/Abstractions/AppBuilders/ServiceCollectionPool.cs b/service/Abstractions/AppBuilders/ServiceCollectionPool.cs index 23679e6d2..e156882a4 100644 --- a/service/Abstractions/AppBuilders/ServiceCollectionPool.cs +++ b/service/Abstractions/AppBuilders/ServiceCollectionPool.cs @@ -55,7 +55,7 @@ public ServiceCollectionPool(IServiceCollection primaryCollection) ArgumentNullExceptionEx.ThrowIfNull(primaryCollection, nameof(primaryCollection), "The primary service collection cannot be NULL"); this._poolSizeLocked = false; this._primaryCollection = primaryCollection; - this._pool = new List { primaryCollection }; + this._pool = [primaryCollection]; } /// diff --git a/service/Abstractions/Constants.cs b/service/Abstractions/Constants.cs index 05d441725..408c1b8dc 100644 --- a/service/Abstractions/Constants.cs +++ b/service/Abstractions/Constants.cs @@ -155,25 +155,25 @@ public static class Summary // Pipeline steps public static readonly string[] DefaultPipeline = - { + [ PipelineStepsExtract, PipelineStepsPartition, PipelineStepsGenEmbeddings, PipelineStepsSaveRecords - }; + ]; public static readonly string[] PipelineWithoutSummary = - { + [ PipelineStepsExtract, PipelineStepsPartition, PipelineStepsGenEmbeddings, PipelineStepsSaveRecords - }; + ]; public static readonly string[] PipelineWithSummary = - { + [ PipelineStepsExtract, PipelineStepsPartition, PipelineStepsGenEmbeddings, PipelineStepsSaveRecords, PipelineStepsSummarize, PipelineStepsGenEmbeddings, PipelineStepsSaveRecords - }; + ]; public static readonly string[] PipelineOnlySummary = - { + [ PipelineStepsExtract, PipelineStepsSummarize, PipelineStepsGenEmbeddings, PipelineStepsSaveRecords - }; + ]; // Standard prompt names public const string PromptNamesSummarize = "summarize"; diff --git a/service/Abstractions/DataFormats/FileContent.cs b/service/Abstractions/DataFormats/FileContent.cs index b20ebdd13..d6591f5d0 100644 --- a/service/Abstractions/DataFormats/FileContent.cs +++ b/service/Abstractions/DataFormats/FileContent.cs @@ -9,7 +9,7 @@ public class FileContent { [JsonPropertyOrder(0)] [JsonPropertyName("sections")] - public List Sections { get; set; } = new(); + public List Sections { get; set; } = []; [JsonPropertyOrder(1)] [JsonPropertyName("mimeType")] diff --git a/service/Abstractions/KernelMemoryExtensions.cs b/service/Abstractions/KernelMemoryExtensions.cs index 346b8d8f7..62443a890 100644 --- a/service/Abstractions/KernelMemoryExtensions.cs +++ b/service/Abstractions/KernelMemoryExtensions.cs @@ -31,8 +31,8 @@ public static async Task> SearchSyntheticsAsync( { if (filters == null) { - filters = new List(); - if (filter == null) { filters.Add(new MemoryFilter()); } + filters = []; + if (filter == null) { filters.Add([]); } } if (filter != null) diff --git a/service/Abstractions/MemoryStorage/MemoryRecord.cs b/service/Abstractions/MemoryStorage/MemoryRecord.cs index 11e462610..1c0538e75 100644 --- a/service/Abstractions/MemoryStorage/MemoryRecord.cs +++ b/service/Abstractions/MemoryStorage/MemoryRecord.cs @@ -13,8 +13,8 @@ public class MemoryRecord private const string CurrentSchemaVersion = SchemaVersion20231218A; // Internal data - private TagCollection _tags = new(); - private Dictionary _payload = new(); + private TagCollection _tags = []; + private Dictionary _payload = []; /// /// Unique record ID @@ -110,9 +110,9 @@ private bool UpgradeRequired() /// private void Upgrade() { - if (this._payload == null) { this._payload = new(); } + if (this._payload == null) { this._payload = []; } - if (this._tags == null) { this._tags = new(); } + if (this._tags == null) { this._tags = []; } string version = SchemaVersionZero; if (this._payload.TryGetValue(Constants.ReservedPayloadSchemaVersionField, out object? versionValue)) diff --git a/service/Abstractions/Models/Citation.cs b/service/Abstractions/Models/Citation.cs index f77390e70..3a8c5b82e 100644 --- a/service/Abstractions/Models/Citation.cs +++ b/service/Abstractions/Models/Citation.cs @@ -65,11 +65,11 @@ public class Citation /// [JsonPropertyName("partitions")] [JsonPropertyOrder(8)] - public List Partitions { get; set; } = new(); + public List Partitions { get; set; } = []; public class Partition { - private TagCollection _tags = new(); + private TagCollection _tags = []; /// /// Content of the document partition, aka chunk/block of text. @@ -117,7 +117,7 @@ public TagCollection Tags get { return this._tags; } set { - this._tags = new(); + this._tags = []; foreach (KeyValuePair> tag in value) { // Exclude internal tags diff --git a/service/Abstractions/Models/DataPipelineStatus.cs b/service/Abstractions/Models/DataPipelineStatus.cs index 195f4b16e..adada1f9c 100644 --- a/service/Abstractions/Models/DataPipelineStatus.cs +++ b/service/Abstractions/Models/DataPipelineStatus.cs @@ -32,7 +32,7 @@ public class DataPipelineStatus [JsonPropertyOrder(12)] [JsonPropertyName("tags")] - public TagCollection Tags { get; set; } = new(); + public TagCollection Tags { get; set; } = []; [JsonPropertyOrder(13)] [JsonPropertyName("creation")] @@ -47,19 +47,19 @@ public class DataPipelineStatus /// [JsonPropertyOrder(15)] [JsonPropertyName("steps")] - public List Steps { get; set; } = new(); + public List Steps { get; set; } = []; /// /// List of the steps remaining. /// [JsonPropertyOrder(16)] [JsonPropertyName("remaining_steps")] - public List RemainingSteps { get; set; } = new(); + public List RemainingSteps { get; set; } = []; /// /// List of steps already completed. /// [JsonPropertyOrder(17)] [JsonPropertyName("completed_steps")] - public List CompletedSteps { get; set; } = new(); + public List CompletedSteps { get; set; } = []; } diff --git a/service/Abstractions/Models/Document.cs b/service/Abstractions/Models/Document.cs index 764d80bd6..f65bfca2c 100644 --- a/service/Abstractions/Models/Document.cs +++ b/service/Abstractions/Models/Document.cs @@ -37,7 +37,7 @@ public string Id /// /// Tags to apply to the memories extracted from the files uploaded. /// - public TagCollection Tags { get; } = new(); + public TagCollection Tags { get; } = []; public Document(string? id = null, TagCollection? tags = null, IEnumerable? filePaths = null) { diff --git a/service/Abstractions/Models/DocumentUploadRequest.cs b/service/Abstractions/Models/DocumentUploadRequest.cs index cc534c752..193bd7f39 100644 --- a/service/Abstractions/Models/DocumentUploadRequest.cs +++ b/service/Abstractions/Models/DocumentUploadRequest.cs @@ -48,17 +48,17 @@ public UploadedFile(string fileName, Stream fileContent) /// /// Tags to apply to the memories extracted from the files uploaded. /// - public TagCollection Tags { get; set; } = new(); + public TagCollection Tags { get; set; } = []; /// /// Files to process /// - public List Files { get; set; } = new(); + public List Files { get; set; } = []; /// /// How to process the files, e.g. how to extract/chunk etc. /// - public List Steps { get; set; } = new(); + public List Steps { get; set; } = []; /// /// Normal ctor @@ -76,7 +76,7 @@ public DocumentUploadRequest() public DocumentUploadRequest(Document document, string? index = null, IEnumerable? steps = null) { this.Index = index ?? string.Empty; - this.Steps = steps?.ToList() ?? new List(); + this.Steps = steps?.ToList() ?? []; this.DocumentId = document.Id; this.Tags = document.Tags; diff --git a/service/Abstractions/Models/IndexCollection.cs b/service/Abstractions/Models/IndexCollection.cs index f2ad57862..f45fbfda6 100644 --- a/service/Abstractions/Models/IndexCollection.cs +++ b/service/Abstractions/Models/IndexCollection.cs @@ -9,5 +9,5 @@ public class IndexCollection { [JsonPropertyName("results")] [JsonPropertyOrder(1)] - public List Results { get; set; } = new(); + public List Results { get; set; } = []; } diff --git a/service/Abstractions/Models/MemoryAnswer.cs b/service/Abstractions/Models/MemoryAnswer.cs index 67e6df64b..eeb9d4d03 100644 --- a/service/Abstractions/Models/MemoryAnswer.cs +++ b/service/Abstractions/Models/MemoryAnswer.cs @@ -48,7 +48,7 @@ public class MemoryAnswer /// [JsonPropertyName("relevantSources")] [JsonPropertyOrder(20)] - public List RelevantSources { get; set; } = new(); + public List RelevantSources { get; set; } = []; /// /// Serialize using .NET JSON serializer, e.g. to avoid ambiguity diff --git a/service/Abstractions/Models/MemoryQuery.cs b/service/Abstractions/Models/MemoryQuery.cs index 2a436b3dc..f6e8dfae4 100644 --- a/service/Abstractions/Models/MemoryQuery.cs +++ b/service/Abstractions/Models/MemoryQuery.cs @@ -17,7 +17,7 @@ public class MemoryQuery [JsonPropertyName("filters")] [JsonPropertyOrder(10)] - public List Filters { get; set; } = new(); + public List Filters { get; set; } = []; [JsonPropertyName("minRelevance")] [JsonPropertyOrder(2)] @@ -25,5 +25,5 @@ public class MemoryQuery [JsonPropertyName("args")] [JsonPropertyOrder(100)] - public Dictionary ContextArguments { get; set; } = new(); + public Dictionary ContextArguments { get; set; } = []; } diff --git a/service/Abstractions/Models/SearchQuery.cs b/service/Abstractions/Models/SearchQuery.cs index 77701ffd0..dda92f37a 100644 --- a/service/Abstractions/Models/SearchQuery.cs +++ b/service/Abstractions/Models/SearchQuery.cs @@ -17,7 +17,7 @@ public class SearchQuery [JsonPropertyName("filters")] [JsonPropertyOrder(10)] - public List Filters { get; set; } = new(); + public List Filters { get; set; } = []; [JsonPropertyName("minRelevance")] [JsonPropertyOrder(2)] @@ -29,5 +29,5 @@ public class SearchQuery [JsonPropertyName("args")] [JsonPropertyOrder(100)] - public Dictionary ContextArguments { get; set; } = new(); + public Dictionary ContextArguments { get; set; } = []; } diff --git a/service/Abstractions/Models/SearchResult.cs b/service/Abstractions/Models/SearchResult.cs index a2e14d225..019720c22 100644 --- a/service/Abstractions/Models/SearchResult.cs +++ b/service/Abstractions/Models/SearchResult.cs @@ -40,7 +40,7 @@ private set { } /// [JsonPropertyName("results")] [JsonPropertyOrder(3)] - public List Results { get; set; } = new(); + public List Results { get; set; } = []; /// /// Serialize using .NET JSON serializer, e.g. to avoid ambiguity diff --git a/service/Abstractions/Models/TagCollection.cs b/service/Abstractions/Models/TagCollection.cs index 230541dcb..784ada81a 100644 --- a/service/Abstractions/Models/TagCollection.cs +++ b/service/Abstractions/Models/TagCollection.cs @@ -61,7 +61,7 @@ public void Add(string key) { if (!this._data.ContainsKey(key)) { - this._data[key] = new List(); + this._data[key] = []; } } @@ -76,7 +76,7 @@ public void Add(string key, string? value) else { // Add the key, but the value only if not null - this._data[key] = value == null ? new List() : new List { value }; + this._data[key] = value == null ? [] : [value]; } } @@ -89,7 +89,7 @@ public void Add(string key, List value) public bool TryGetValue(string key, out List value) { bool result = this._data.TryGetValue(key, out var valueOut); - value = valueOut ?? new List(); + value = valueOut ?? []; return result; } diff --git a/service/Abstractions/Pipeline/DataPipeline.cs b/service/Abstractions/Pipeline/DataPipeline.cs index 9e99c7351..7b6f1a6a1 100644 --- a/service/Abstractions/Pipeline/DataPipeline.cs +++ b/service/Abstractions/Pipeline/DataPipeline.cs @@ -104,14 +104,14 @@ public abstract class FileDetailsBase /// [JsonPropertyOrder(7)] [JsonPropertyName("tags")] - public TagCollection Tags { get; set; } = new(); + public TagCollection Tags { get; set; } = []; /// /// List of handlers who have already processed this file /// [JsonPropertyOrder(17)] [JsonPropertyName("processed_by")] - public List ProcessedBy { get; set; } = new(); + public List ProcessedBy { get; set; } = []; /// /// Optional log describing how the file has been processed. @@ -191,7 +191,7 @@ public class FileDetails : FileDetailsBase /// [JsonPropertyOrder(24)] [JsonPropertyName("generated_files")] - public Dictionary GeneratedFiles { get; set; } = new(); + public Dictionary GeneratedFiles { get; set; } = []; public string GetPartitionFileName(int partitionNumber) { @@ -234,28 +234,28 @@ public string GetHandlerOutputFileName(IPipelineStepHandler handler, int index = /// [JsonPropertyOrder(3)] [JsonPropertyName("steps")] - public List Steps { get; set; } = new(); + public List Steps { get; set; } = []; /// /// List of the steps remaining. /// [JsonPropertyOrder(4)] [JsonPropertyName("remaining_steps")] - public List RemainingSteps { get; set; } = new(); + public List RemainingSteps { get; set; } = []; /// /// List of steps already completed. /// [JsonPropertyOrder(5)] [JsonPropertyName("completed_steps")] - public List CompletedSteps { get; set; } = new(); + public List CompletedSteps { get; set; } = []; /// /// Document tags /// [JsonPropertyOrder(7)] [JsonPropertyName("tags")] - public TagCollection Tags { get; set; } = new(); + public TagCollection Tags { get; set; } = []; [JsonPropertyOrder(8)] [JsonPropertyName("creation")] @@ -267,7 +267,7 @@ public string GetHandlerOutputFileName(IPipelineStepHandler handler, int index = [JsonPropertyOrder(10)] [JsonPropertyName("files")] - public List Files { get; set; } = new(); + public List Files { get; set; } = []; /// /// Unstructured dictionary available to support custom tasks and business logic. @@ -285,13 +285,13 @@ public string GetHandlerOutputFileName(IPipelineStepHandler handler, int index = /// [JsonPropertyOrder(21)] [JsonPropertyName("previous_executions_to_purge")] - public List PreviousExecutionsToPurge { get; set; } = new(); + public List PreviousExecutionsToPurge { get; set; } = []; [JsonIgnore] public bool Complete => this.RemainingSteps.Count == 0; [JsonIgnore] - public List FilesToUpload { get; set; } = new(); + public List FilesToUpload { get; set; } = []; [JsonIgnore] public bool UploadComplete { get; set; } diff --git a/service/Abstractions/Pipeline/DataPipelinePointer.cs b/service/Abstractions/Pipeline/DataPipelinePointer.cs index 331af968a..6df19f271 100644 --- a/service/Abstractions/Pipeline/DataPipelinePointer.cs +++ b/service/Abstractions/Pipeline/DataPipelinePointer.cs @@ -35,7 +35,7 @@ public sealed class DataPipelinePointer /// [JsonPropertyOrder(3)] [JsonPropertyName("steps")] - public List Steps { get; set; } = new(); + public List Steps { get; set; } = []; public DataPipelinePointer() { diff --git a/service/Abstractions/Pipeline/Queue/QueueOptions.cs b/service/Abstractions/Pipeline/Queue/QueueOptions.cs index 8fd1d0e45..147b944f1 100644 --- a/service/Abstractions/Pipeline/Queue/QueueOptions.cs +++ b/service/Abstractions/Pipeline/Queue/QueueOptions.cs @@ -15,17 +15,17 @@ public QueueOptions() { } - public override bool Equals(object? obj) + public override readonly bool Equals(object? obj) { return obj is QueueOptions options && this.Equals(options); } - public bool Equals(QueueOptions other) + public readonly bool Equals(QueueOptions other) { return this.DequeueEnabled == other.DequeueEnabled; } - public override int GetHashCode() + public override readonly int GetHashCode() { return this.DequeueEnabled ? 1 : 2; } diff --git a/service/Abstractions/Search/SearchClientConfig.cs b/service/Abstractions/Search/SearchClientConfig.cs index 8871bf198..a92498e9e 100644 --- a/service/Abstractions/Search/SearchClientConfig.cs +++ b/service/Abstractions/Search/SearchClientConfig.cs @@ -82,12 +82,12 @@ public class SearchClientConfig /// /// Up to 4 sequences where the completion will stop generating further tokens. /// - public IList StopSequences { get; set; } = new List(); + public IList StopSequences { get; set; } = []; /// /// Modify the likelihood of specified tokens appearing in the completion. /// - public Dictionary TokenSelectionBiases { get; set; } = new(); + public Dictionary TokenSelectionBiases { get; set; } = []; /// /// Whether to check is the generated answers are safe. diff --git a/service/Abstractions/SemanticKernel/TextEmbeddingGenerationExtensions.cs b/service/Abstractions/SemanticKernel/TextEmbeddingGenerationExtensions.cs index e7ae1f859..7e744d1d6 100644 --- a/service/Abstractions/SemanticKernel/TextEmbeddingGenerationExtensions.cs +++ b/service/Abstractions/SemanticKernel/TextEmbeddingGenerationExtensions.cs @@ -26,7 +26,7 @@ public static async Task GenerateEmbeddingAsync( this ITextEmbeddingGenerationService generator, string text, CancellationToken cancellationToken = default) { IList>? embeddings = await generator - .GenerateEmbeddingsAsync(new List { text }, null, cancellationToken) + .GenerateEmbeddingsAsync([text], null, cancellationToken) .ConfigureAwait(false); if (embeddings.Count == 0) { diff --git a/service/Core/Configuration/KernelMemoryConfig.cs b/service/Core/Configuration/KernelMemoryConfig.cs index e2b29d108..68509f562 100644 --- a/service/Core/Configuration/KernelMemoryConfig.cs +++ b/service/Core/Configuration/KernelMemoryConfig.cs @@ -47,13 +47,13 @@ public class DistributedOrchestrationConfig /// List of embedding types to generate during document ingestion. /// Using multiple types can help with migration from two different models, or for comparing models performance. /// - public List EmbeddingGeneratorTypes { get; set; } = new(); + public List EmbeddingGeneratorTypes { get; set; } = []; /// /// List of vector storages where embeddings will be saved during ingestion. /// Multiple storages can help with data migrations and testing purposes. /// - public List MemoryDbTypes { get; set; } = new(); + public List MemoryDbTypes { get; set; } = []; /// /// How many memory DB records to insert at once when extracting memories @@ -83,7 +83,7 @@ public class DistributedOrchestrationConfig /// * gen_embeddings: generate embeddings for new chunks (e.g. the summary) /// * save_records: save new records generated from the summary /// - public List DefaultSteps { get; set; } = new(); + public List DefaultSteps { get; set; } = []; /// /// Note: do not store these values in DefaultSteps, to avoid @@ -185,7 +185,7 @@ public string ContentStorageType /// /// Dependencies settings, e.g. credentials, endpoints, etc. /// - public Dictionary> Services { get; set; } = new(); + public Dictionary> Services { get; set; } = []; /// /// Fetch a service configuration from the "Services" node diff --git a/service/Core/Configuration/ServiceAuthorizationConfig.cs b/service/Core/Configuration/ServiceAuthorizationConfig.cs index 3886c0bc4..357faf8a3 100644 --- a/service/Core/Configuration/ServiceAuthorizationConfig.cs +++ b/service/Core/Configuration/ServiceAuthorizationConfig.cs @@ -10,11 +10,11 @@ public class ServiceAuthorizationConfig public const int AccessKeyMinLength = 32; public static readonly char[] ValidChars = - { + [ ',', '.', ';', ':', '_', '-', '!', '@', '#', '$', '^', '*', '~', '=', '|', '[', ']', '{', '}', '(', ')' - }; + ]; /// /// Whether clients must provide some credentials to interact with the HTTP API. diff --git a/service/Core/Configuration/ServiceConfig.cs b/service/Core/Configuration/ServiceConfig.cs index 05082c8e1..4b89ff129 100644 --- a/service/Core/Configuration/ServiceConfig.cs +++ b/service/Core/Configuration/ServiceConfig.cs @@ -27,7 +27,7 @@ public class ServiceConfig /// /// List of handlers to enable /// - public Dictionary Handlers { get; set; } = new(); + public Dictionary Handlers { get; set; } = []; /// /// The maximum allowed size in megabytes for an HTTP request body posted to the upload endpoint. diff --git a/service/Core/DataFormats/Text/TextChunker.cs b/service/Core/DataFormats/Text/TextChunker.cs index b80a3dcfe..374a4eb5f 100644 --- a/service/Core/DataFormats/Text/TextChunker.cs +++ b/service/Core/DataFormats/Text/TextChunker.cs @@ -25,9 +25,9 @@ public static class TextChunker /// The number of tokens in the input string. public delegate int TokenCounter(string input); - private static readonly char[] s_spaceChar = { ' ' }; - private static readonly string?[] s_plaintextSplitOptions = { "\n\r", ".", "?!", ";", ":", ",", ")]}", " ", "-", null }; - private static readonly string?[] s_markdownSplitOptions = { ".", "?!", ";", ":", ",", ")]}", " ", "-", "\n\r", null }; + private static readonly char[] s_spaceChar = [' ']; + private static readonly string?[] s_plaintextSplitOptions = ["\n\r", ".", "?!", ";", ":", ",", ")]}", " ", "-", null]; + private static readonly string?[] s_markdownSplitOptions = [".", "?!", ";", ":", ",", ")]}", " ", "-", "\n\r", null]; /// /// Split plain text into lines. @@ -140,7 +140,7 @@ private static List InternalSplitTextParagraphs( if (lines.Count == 0) { - return new List(); + return []; } var chunkHeaderTokens = chunkHeader is { Length: > 0 } ? GetTokenCount(chunkHeader, tokenCounter) : 0; @@ -166,7 +166,7 @@ private static List BuildParagraph( TokenCounter? tokenCounter) { StringBuilder paragraphBuilder = new(); - List paragraphs = new(); + List paragraphs = []; foreach (string line in truncatedLines) { @@ -305,7 +305,7 @@ private static (List, bool) Split( TokenCounter? tokenCounter) { bool inputWasSplit = false; - List result = new(); + List result = []; int count = input.Count; for (int i = 0; i < count; i++) { @@ -326,7 +326,7 @@ private static (List, bool) Split( TokenCounter? tokenCounter) { Debug.Assert(inputString is null || input.SequenceEqual(inputString.AsSpan())); - List result = new(); + List result = []; var inputWasSplit = false; int inputTokenCount = GetTokenCount(inputString ??= input.ToString(), tokenCounter); diff --git a/service/Core/DataFormats/WebPages/WebScraper.cs b/service/Core/DataFormats/WebPages/WebScraper.cs index 578740932..7c0a2e557 100644 --- a/service/Core/DataFormats/WebPages/WebScraper.cs +++ b/service/Core/DataFormats/WebPages/WebScraper.cs @@ -47,7 +47,7 @@ public void Dispose() private async Task GetAsync(Uri url, CancellationToken cancellationToken = default) { var scheme = url.Scheme.ToUpperInvariant(); - if ((scheme != "HTTP") && (scheme != "HTTPS")) + if (scheme is not "HTTP" and not "HTTPS") { return new WebScraperResult { Success = false, Error = $"Unknown URL protocol: {url.Scheme}" }; } diff --git a/service/Core/DocumentStorage/DevTools/SimpleFileStorage.cs b/service/Core/DocumentStorage/DevTools/SimpleFileStorage.cs index 8c8791a61..b8a577636 100644 --- a/service/Core/DocumentStorage/DevTools/SimpleFileStorage.cs +++ b/service/Core/DocumentStorage/DevTools/SimpleFileStorage.cs @@ -113,7 +113,7 @@ public async Task ReadFileAsync( { return await this._fileSystem.ReadFileInfoAsync(volume: index, relPath: documentId, fileName: fileName, cancellationToken).ConfigureAwait(false); } - catch (Exception e) when (e is DirectoryNotFoundException || e is FileNotFoundException) + catch (Exception e) when (e is DirectoryNotFoundException or FileNotFoundException) { if (logErrIfNotFound) { diff --git a/service/Core/Handlers/DeleteDocumentHandler.cs b/service/Core/Handlers/DeleteDocumentHandler.cs index d869ef981..8aa8370ab 100644 --- a/service/Core/Handlers/DeleteDocumentHandler.cs +++ b/service/Core/Handlers/DeleteDocumentHandler.cs @@ -45,7 +45,7 @@ public DeleteDocumentHandler( IAsyncEnumerable records = db.GetListAsync( index: pipeline.Index, limit: -1, - filters: new List { MemoryFilters.ByDocument(pipeline.DocumentId) }, + filters: [MemoryFilters.ByDocument(pipeline.DocumentId)], cancellationToken: cancellationToken); await foreach (var record in records.WithCancellation(cancellationToken).ConfigureAwait(false)) diff --git a/service/Core/Handlers/GenerateEmbeddingsHandlerBase.cs b/service/Core/Handlers/GenerateEmbeddingsHandlerBase.cs index d4adc2d8f..ecfecfae7 100644 --- a/service/Core/Handlers/GenerateEmbeddingsHandlerBase.cs +++ b/service/Core/Handlers/GenerateEmbeddingsHandlerBase.cs @@ -41,8 +41,8 @@ protected async Task> GetListOfPartitionsToProcessAsync( DataPipeline.GeneratedFileDetails partitionFile = generatedFile.Value; // Calc embeddings only for partitions (text chunks) and synthetic data - if (partitionFile.ArtifactType != DataPipeline.ArtifactTypes.TextPartition - && partitionFile.ArtifactType != DataPipeline.ArtifactTypes.SyntheticData) + if (partitionFile.ArtifactType is not DataPipeline.ArtifactTypes.TextPartition + and not DataPipeline.ArtifactTypes.SyntheticData) { this._log.LogTrace("Skipping file {0} (not a partition, not synthetic data)", partitionFile.Name); continue; diff --git a/service/Core/Handlers/SaveRecordsHandler.cs b/service/Core/Handlers/SaveRecordsHandler.cs index cceeee66d..939e379d9 100644 --- a/service/Core/Handlers/SaveRecordsHandler.cs +++ b/service/Core/Handlers/SaveRecordsHandler.cs @@ -93,7 +93,7 @@ public SaveRecordsHandler( // Here we split the list of DBs in two lists, those supporting batching and those not, prioritizing // the single upsert if possible, to have the best retry strategy when possible. this._memoryDbsWithSingleUpsert = this._memoryDbs; - this._memoryDbsWithBatchUpsert = new List(); + this._memoryDbsWithBatchUpsert = []; if (this._upsertBatchSize > 1) { this._memoryDbsWithSingleUpsert = this._memoryDbs.Where(x => x is not IMemoryDbUpsertBatch).ToList(); @@ -109,7 +109,7 @@ public SaveRecordsHandler( this._log.LogDebug("Saving memory records, pipeline '{0}/{1}'", pipeline.Index, pipeline.DocumentId); await this.DeletePreviousRecordsAsync(pipeline, cancellationToken).ConfigureAwait(false); - pipeline.PreviousExecutionsToPurge = new List(); + pipeline.PreviousExecutionsToPurge = []; var recordsFound = false; diff --git a/service/Core/Handlers/SummarizationHandler.cs b/service/Core/Handlers/SummarizationHandler.cs index a4ee36f9e..1620108dd 100644 --- a/service/Core/Handlers/SummarizationHandler.cs +++ b/service/Core/Handlers/SummarizationHandler.cs @@ -62,7 +62,7 @@ public SummarizationHandler( foreach (DataPipeline.FileDetails uploadedFile in pipeline.Files) { // Track new files being generated (cannot edit originalFile.GeneratedFiles while looping it) - Dictionary summaryFiles = new(); + Dictionary summaryFiles = []; foreach (KeyValuePair generatedFile in uploadedFile.GeneratedFiles) { diff --git a/service/Core/Handlers/SummarizationParallelHandler.cs b/service/Core/Handlers/SummarizationParallelHandler.cs index 44e309270..118e4f962 100644 --- a/service/Core/Handlers/SummarizationParallelHandler.cs +++ b/service/Core/Handlers/SummarizationParallelHandler.cs @@ -61,7 +61,7 @@ public SummarizationParallelHandler( foreach (DataPipeline.FileDetails uploadedFile in pipeline.Files) { // Track new files being generated (cannot edit originalFile.GeneratedFiles while looping it) - Dictionary summaryFiles = new(); + Dictionary summaryFiles = []; var options = new ParallelOptions() { diff --git a/service/Core/Handlers/TextPartitioningHandler.cs b/service/Core/Handlers/TextPartitioningHandler.cs index 960c4b47b..489ffbfb0 100644 --- a/service/Core/Handlers/TextPartitioningHandler.cs +++ b/service/Core/Handlers/TextPartitioningHandler.cs @@ -95,7 +95,7 @@ public TextPartitioningHandler( foreach (DataPipeline.FileDetails uploadedFile in pipeline.Files) { // Track new files being generated (cannot edit originalFile.GeneratedFiles while looping it) - Dictionary newFiles = new(); + Dictionary newFiles = []; foreach (KeyValuePair generatedFile in uploadedFile.GeneratedFiles) { diff --git a/service/Core/KernelMemoryBuilder.cs b/service/Core/KernelMemoryBuilder.cs index 418d56992..305d67663 100644 --- a/service/Core/KernelMemoryBuilder.cs +++ b/service/Core/KernelMemoryBuilder.cs @@ -40,10 +40,10 @@ private enum ClientTypes private readonly IServiceCollection? _hostServiceCollection; // List of all the embedding generators to use during ingestion - private readonly List _embeddingGenerators = new(); + private readonly List _embeddingGenerators = []; // List of all the memory DBs to use during ingestion - private readonly List _memoryDbs = new(); + private readonly List _memoryDbs = []; // Normalized configuration private readonly KernelMemoryConfig? _memoryConfiguration = null; diff --git a/service/Core/MemoryServerless.cs b/service/Core/MemoryServerless.cs index 91a6b741b..2aba4cf0d 100644 --- a/service/Core/MemoryServerless.cs +++ b/service/Core/MemoryServerless.cs @@ -245,7 +245,7 @@ public Task SearchAsync( this._contextProvider.InitContext(context); if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } @@ -274,7 +274,7 @@ public Task AskAsync( this._contextProvider.InitContext(context); if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } diff --git a/service/Core/MemoryService.cs b/service/Core/MemoryService.cs index 169cb45b6..2ee34b163 100644 --- a/service/Core/MemoryService.cs +++ b/service/Core/MemoryService.cs @@ -211,7 +211,7 @@ public Task SearchAsync( { if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } @@ -239,7 +239,7 @@ public Task AskAsync( { if (filter != null) { - if (filters == null) { filters = new List(); } + if (filters == null) { filters = []; } filters.Add(filter); } diff --git a/service/Core/Pipeline/BaseOrchestrator.cs b/service/Core/Pipeline/BaseOrchestrator.cs index c613139b6..72aba2dee 100644 --- a/service/Core/Pipeline/BaseOrchestrator.cs +++ b/service/Core/Pipeline/BaseOrchestrator.cs @@ -138,7 +138,7 @@ public DataPipeline PrepareNewDocumentUpload( { index = IndexName.CleanName(index, this._defaultIndexName); - filesToUpload ??= new List(); + filesToUpload ??= []; var pipeline = new DataPipeline { @@ -406,14 +406,14 @@ protected async Task UploadFilesAsync(DataPipeline currentPipeline, Cancellation if (dedupe.Contains(oldExecution.ExecutionId)) { continue; } // Reset the list to avoid wasting space with nested trees - oldExecution.PreviousExecutionsToPurge = new List(); + oldExecution.PreviousExecutionsToPurge = []; currentPipeline.PreviousExecutionsToPurge.Add(oldExecution); dedupe.Add(oldExecution.ExecutionId); } // Reset the list to avoid wasting space with nested trees - previousPipeline.PreviousExecutionsToPurge = new List(); + previousPipeline.PreviousExecutionsToPurge = []; currentPipeline.PreviousExecutionsToPurge.Add(previousPipeline); } diff --git a/service/Core/Search/SearchClient.cs b/service/Core/Search/SearchClient.cs index ae37144db..a3bebaa51 100644 --- a/service/Core/Search/SearchClient.cs +++ b/service/Core/Search/SearchClient.cs @@ -79,7 +79,7 @@ public async Task SearchAsync( var result = new SearchResult { Query = query, - Results = new List() + Results = [] }; if (string.IsNullOrWhiteSpace(query) && (filters == null || filters.Count == 0)) diff --git a/service/Service.AspNetCore/Models/HttpDocumentUploadRequest.cs b/service/Service.AspNetCore/Models/HttpDocumentUploadRequest.cs index b55288ca5..2f86e5fc3 100644 --- a/service/Service.AspNetCore/Models/HttpDocumentUploadRequest.cs +++ b/service/Service.AspNetCore/Models/HttpDocumentUploadRequest.cs @@ -30,7 +30,7 @@ public class HttpDocumentUploadRequest /// Optional tags to apply to the memories extracted from the document. /// Tags allow to filter memory records when searching and asking questions. /// - public TagCollection Tags { get; set; } = new(); + public TagCollection Tags { get; set; } = []; /// /// Pipeline steps to execute, aka handlers uses to process the data uploaded. @@ -46,12 +46,12 @@ public class HttpDocumentUploadRequest /// These steps can be changed and customized, using custom handlers, implementing bespoke flows. /// For example, you can create handlers to zip files, send emails, write to DBs, etc. /// - public List Steps { get; set; } = new(); + public List Steps { get; set; } = []; /// /// Files uploaded /// - public IEnumerable Files { get; set; } = new List(); + public IEnumerable Files { get; set; } = []; /// /// Optional custom arguments passed to handlers and other internal components. diff --git a/service/tests/Abstractions.UnitTests/AI/EmbeddingTest.cs b/service/tests/Abstractions.UnitTests/AI/EmbeddingTest.cs index 0c928ddab..f7da04099 100644 --- a/service/tests/Abstractions.UnitTests/AI/EmbeddingTest.cs +++ b/service/tests/Abstractions.UnitTests/AI/EmbeddingTest.cs @@ -11,8 +11,8 @@ public class EmbeddingTest public void ItShowsEmbeddingSizeWhenThrowing() { // Arrange - var vec1 = new Embedding(new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }); - var vec2 = new Embedding(new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0 }); + var vec1 = new Embedding([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]); + var vec2 = new Embedding([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0]); // Act - Assert var e = Assert.Throws(() => vec1.CosineSimilarity(vec2)); diff --git a/service/tests/Abstractions.UnitTests/MemoryStorage/MemoryRecordTest.cs b/service/tests/Abstractions.UnitTests/MemoryStorage/MemoryRecordTest.cs index b168420d3..94f6c346f 100644 --- a/service/tests/Abstractions.UnitTests/MemoryStorage/MemoryRecordTest.cs +++ b/service/tests/Abstractions.UnitTests/MemoryStorage/MemoryRecordTest.cs @@ -26,7 +26,7 @@ public void ItCanBeSerialized() // Arrange record.Id = "123"; - record.Tags["foo"] = new List { "bar" }; + record.Tags["foo"] = ["bar"]; record.Payload["bar"] = "foo"; // Act diff --git a/service/tests/Core.FunctionalTests/DefaultTestCases/FilteringTest.cs b/service/tests/Core.FunctionalTests/DefaultTestCases/FilteringTest.cs index df24307ca..d1e31b1fe 100644 --- a/service/tests/Core.FunctionalTests/DefaultTestCases/FilteringTest.cs +++ b/service/tests/Core.FunctionalTests/DefaultTestCases/FilteringTest.cs @@ -92,47 +92,47 @@ await memory.ImportDocumentAsync( } // Multiple filters: unknown users cannot see the memory - var answer = await memory.AskAsync("What is Orion?", filters: new List - { + var answer = await memory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1"), MemoryFilters.ByTag("user", "someone2"), - }, index: indexName); + ], index: indexName); log(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: unknown users cannot see the memory even if the type is correct (testing AND logic) - answer = await memory.AskAsync("What is Orion?", filters: new List - { + answer = await memory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "someone2").ByTag("type", "news"), - }, index: indexName); + ], index: indexName); log(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: AND + OR logic works - answer = await memory.AskAsync("What is Orion?", filters: new List - { + answer = await memory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "admin").ByTag("type", "fact"), - }, index: indexName); + ], index: indexName); log(answer.Result); Assert.Contains(NotFound, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: OR logic works - answer = await memory.AskAsync("What is Orion?", filters: new List - { + answer = await memory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1"), MemoryFilters.ByTag("user", "admin"), - }, index: indexName); + ], index: indexName); log(answer.Result); Assert.Contains(Found, answer.Result, StringComparison.OrdinalIgnoreCase); // Multiple filters: OR logic works - answer = await memory.AskAsync("What is Orion?", filters: new List - { + answer = await memory.AskAsync("What is Orion?", filters: + [ MemoryFilters.ByTag("user", "someone1").ByTag("type", "news"), MemoryFilters.ByTag("user", "admin").ByTag("type", "news"), - }, index: indexName); + ], index: indexName); log(answer.Result); Assert.Contains(Found, answer.Result, StringComparison.OrdinalIgnoreCase); @@ -170,7 +170,7 @@ await memory.ImportDocumentAsync( // Act // Simple filter: empty filters have no impact - var answer = await memory.AskAsync(Question, filter: new(), index: indexName); + var answer = await memory.AskAsync(Question, filter: [], index: indexName); // Retry, e.g. let the index populate if (withRetries) @@ -183,7 +183,7 @@ await memory.ImportDocumentAsync( } await Task.Delay(TimeSpan.FromSeconds(2)); - answer = await memory.AskAsync(Question, filter: new(), index: indexName); + answer = await memory.AskAsync(Question, filter: [], index: indexName); } } @@ -193,8 +193,7 @@ await memory.ImportDocumentAsync( // Act // Multiple filters: empty filters have no impact - answer = await memory.AskAsync(Question, - filters: new List { new() }, index: indexName); + answer = await memory.AskAsync(Question, filters: [[]], index: indexName); log(answer.Result); // Assert diff --git a/service/tests/Core.FunctionalTests/DefaultTestCases/RecordDeletionTest.cs b/service/tests/Core.FunctionalTests/DefaultTestCases/RecordDeletionTest.cs index ee5b94924..637acbf58 100644 --- a/service/tests/Core.FunctionalTests/DefaultTestCases/RecordDeletionTest.cs +++ b/service/tests/Core.FunctionalTests/DefaultTestCases/RecordDeletionTest.cs @@ -56,12 +56,12 @@ await memory.ImportDocumentAsync( IAsyncEnumerable records = db.GetListAsync( index: IndexName, limit: -1, - filters: new List - { + filters: + [ MemoryFilters.ByDocument(DocId3), MemoryFilters.ByDocument(DocId2), MemoryFilters.ByDocument(DocId1), - }); + ]); log("Deleting records"); var count = 0; diff --git a/service/tests/Core.FunctionalTests/ParallelHandlersTest.cs b/service/tests/Core.FunctionalTests/ParallelHandlersTest.cs index 92cb68ae7..f4f193539 100644 --- a/service/tests/Core.FunctionalTests/ParallelHandlersTest.cs +++ b/service/tests/Core.FunctionalTests/ParallelHandlersTest.cs @@ -37,13 +37,13 @@ public async Task ItUsesParallelEmbeddingGeneration() await this._memory.ImportDocumentAsync( "file2-largePDF.pdf", documentId: Id, - steps: new[] - { + steps: + [ Constants.PipelineStepsExtract, Constants.PipelineStepsPartition, "gen_embeddings_parallel", // alternative to default "gen_embeddings", 3 secs vs 12 secs Constants.PipelineStepsSaveRecords - }); + ]); var count = 0; while (!await this._memory.IsDocumentReadyAsync(documentId: Id)) @@ -80,13 +80,13 @@ public async Task ItUsesParallelSummarization() await this._memory.ImportDocumentAsync( "file2-largePDF.pdf", documentId: Id, - steps: new[] - { + steps: + [ Constants.PipelineStepsExtract, "summarize", // alternative to default "summarize", 55secs vs 50secs Constants.PipelineStepsGenEmbeddings, - Constants.PipelineStepsSaveRecords, - }); + Constants.PipelineStepsSaveRecords + ]); var count = 0; while (!await this._memory.IsDocumentReadyAsync(documentId: Id)) diff --git a/service/tests/Core.FunctionalTests/VectorDbComparison/TestCosineSimilarity.cs b/service/tests/Core.FunctionalTests/VectorDbComparison/TestCosineSimilarity.cs index 838347a73..86d6be415 100644 --- a/service/tests/Core.FunctionalTests/VectorDbComparison/TestCosineSimilarity.cs +++ b/service/tests/Core.FunctionalTests/VectorDbComparison/TestCosineSimilarity.cs @@ -27,7 +27,7 @@ public class TestCosineSimilarity : BaseFunctionalTestCase private readonly bool _qdrantEnabled = false; private readonly bool _redisEnabled = false; - private readonly Dictionary _memoryDbs = new(); + private readonly Dictionary _memoryDbs = []; private readonly FakeEmbeddingGenerator _embeddingGenerator; public TestCosineSimilarity(IConfiguration cfg, ITestOutputHelper log) : base(cfg, log) diff --git a/service/tests/Core.FunctionalTests/VectorDbComparison/TestMemoryFilters.cs b/service/tests/Core.FunctionalTests/VectorDbComparison/TestMemoryFilters.cs index e1a1eb4ea..e432ab8b7 100644 --- a/service/tests/Core.FunctionalTests/VectorDbComparison/TestMemoryFilters.cs +++ b/service/tests/Core.FunctionalTests/VectorDbComparison/TestMemoryFilters.cs @@ -27,7 +27,7 @@ public class TestMemoryFilters : BaseFunctionalTestCase private readonly bool _qdrantEnabled = false; private readonly bool _redisEnabled = false; - private readonly Dictionary _memoryDbs = new(); + private readonly Dictionary _memoryDbs = []; public TestMemoryFilters(IConfiguration cfg, ITestOutputHelper log) : base(cfg, log) { diff --git a/service/tests/Core.UnitTests/DataFormats/Text/TextChunkerTests.cs b/service/tests/Core.UnitTests/DataFormats/Text/TextChunkerTests.cs index f086b4e99..1d451e708 100644 --- a/service/tests/Core.UnitTests/DataFormats/Text/TextChunkerTests.cs +++ b/service/tests/Core.UnitTests/DataFormats/Text/TextChunkerTests.cs @@ -15,11 +15,11 @@ public sealed class TextChunkerTests public void CanSplitPlainTextLines() { const string Input = "This is a test of the emergency broadcast system. This is only a test."; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test." - }; + ]; var result = TextChunker.SplitPlainTextLines(Input, 15, tokenCounter: s_tokenCounter); @@ -30,17 +30,17 @@ public void CanSplitPlainTextLines() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphs() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; - var expected = new[] - { + ]; + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 13, tokenCounter: s_tokenCounter); @@ -51,20 +51,20 @@ public void CanSplitMarkdownParagraphs() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphsWithOverlap() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "emergency broadcast system. This is only a test.", "This is only a test. We repeat, this is only a test.", "We repeat, this is only a test. A unit test.", "A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 15, 8, tokenCounter: s_tokenCounter); @@ -75,18 +75,18 @@ public void CanSplitMarkdownParagraphsWithOverlap() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphs() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 13, tokenCounter: s_tokenCounter); @@ -97,20 +97,20 @@ public void CanSplitTextParagraphs() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsWithOverlap() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "emergency broadcast system. This is only a test.", "This is only a test. We repeat, this is only a test.", "We repeat, this is only a test. A unit test.", "A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, 8, tokenCounter: s_tokenCounter); @@ -122,11 +122,11 @@ public void CanSplitTextParagraphsWithOverlap() public void CanSplitMarkDownLines() { const string Input = "This is a test of the emergency broadcast system. This is only a test."; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test." - }; + ]; var result = TextChunker.SplitMarkDownLines(Input, 15, tokenCounter: s_tokenCounter); @@ -137,7 +137,7 @@ public void CanSplitMarkDownLines() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsWithEmptyInput() { - List input = new(); + List input = []; var expected = new List(); @@ -150,7 +150,7 @@ public void CanSplitTextParagraphsWithEmptyInput() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphsWithEmptyInput() { - List input = new(); + List input = []; var expected = new List(); @@ -163,22 +163,22 @@ public void CanSplitMarkdownParagraphsWithEmptyInput() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsEvenly() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test.", "A small note. And another. And once again. Seriously, this is the end. We're finished. All set. Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test.", "We repeat, this is only a test. A unit test.", "A small note. And another. And once again.", "Seriously, this is the end. We're finished. All set. Bye. Done." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -190,22 +190,22 @@ public void CanSplitTextParagraphsEvenly() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnNewlines() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system\r\nThis is only a test", "We repeat this is only a test\nA unit test", "A small note\nAnd another\r\nAnd once again\rSeriously this is the end\nWe're finished\nAll set\nBye\n", "Done" - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system", "This is only a test", "We repeat this is only a test\nA unit test", "A small note\nAnd another\nAnd once again", - "Seriously this is the end\nWe're finished\nAll set\nBye Done", - }; + "Seriously this is the end\nWe're finished\nAll set\nBye Done" + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -217,23 +217,23 @@ public void CanSplitTextParagraphsOnNewlines() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnPunctuation() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test", "We repeat, this is only a test? A unit test", "A small note! And another? And once again! Seriously, this is the end. We're finished. All set. Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test", "We repeat, this is only a test? A unit test", "A small note! And another? And once again!", "Seriously, this is the end.", - $"We're finished. All set. Bye.{Environment.NewLine}Done.", - }; + $"We're finished. All set. Bye.{Environment.NewLine}Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -245,22 +245,22 @@ public void CanSplitTextParagraphsOnPunctuation() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnSemicolons() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system; This is only a test", "We repeat; this is only a test; A unit test", "A small note; And another; And once again; Seriously, this is the end; We're finished; All set; Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system;", "This is only a test", "We repeat; this is only a test; A unit test", "A small note; And another; And once again;", - "Seriously, this is the end; We're finished; All set; Bye. Done.", - }; + "Seriously, this is the end; We're finished; All set; Bye. Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -272,22 +272,22 @@ public void CanSplitTextParagraphsOnSemicolons() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnColons() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system: This is only a test", "We repeat: this is only a test: A unit test", "A small note: And another: And once again: Seriously, this is the end: We're finished: All set: Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system:", "This is only a test", "We repeat: this is only a test: A unit test", "A small note: And another: And once again:", - "Seriously, this is the end: We're finished: All set: Bye. Done.", - }; + "Seriously, this is the end: We're finished: All set: Bye. Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -299,22 +299,22 @@ public void CanSplitTextParagraphsOnColons() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnCommas() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system, This is only a test", "We repeat, this is only a test, A unit test", "A small note, And another, And once again, Seriously, this is the end, We're finished, All set, Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system,", "This is only a test", "We repeat, this is only a test, A unit test", "A small note, And another, And once again, Seriously,", - $"this is the end, We're finished, All set, Bye.{Environment.NewLine}Done.", - }; + $"this is the end, We're finished, All set, Bye.{Environment.NewLine}Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -326,22 +326,22 @@ public void CanSplitTextParagraphsOnCommas() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnClosingBrackets() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system) This is only a test", "We repeat) this is only a test) A unit test", "A small note] And another) And once again] Seriously this is the end} We're finished} All set} Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system)", "This is only a test", "We repeat) this is only a test) A unit test", "A small note] And another) And once again]", - "Seriously this is the end} We're finished} All set} Bye. Done.", - }; + "Seriously this is the end} We're finished} All set} Bye. Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -353,22 +353,22 @@ public void CanSplitTextParagraphsOnClosingBrackets() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnSpaces() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system This is only a test", "We repeat this is only a test A unit test", "A small note And another And once again Seriously this is the end We're finished All set Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency", "broadcast system This is only a test", "We repeat this is only a test A unit test", "A small note And another And once again Seriously", - $"this is the end We're finished All set Bye.{Environment.NewLine}Done.", - }; + $"this is the end We're finished All set Bye.{Environment.NewLine}Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -380,22 +380,22 @@ public void CanSplitTextParagraphsOnSpaces() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsOnHyphens() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system-This is only a test", "We repeat-this is only a test-A unit test", "A small note-And another-And once again-Seriously, this is the end-We're finished-All set-Bye.", "Done." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency", "broadcast system-This is only a test", "We repeat-this is only a test-A unit test", "A small note-And another-And once again-Seriously,", - $"this is the end-We're finished-All set-Bye.{Environment.NewLine}Done.", - }; + $"this is the end-We're finished-All set-Bye.{Environment.NewLine}Done." + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -407,23 +407,23 @@ public void CanSplitTextParagraphsOnHyphens() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsWithNoDelimiters() { - List input = new() - { + List input = + [ "Thisisatestoftheemergencybroadcastsystem", "Thisisonlyatest", "WerepeatthisisonlyatestAunittest", "AsmallnoteAndanotherAndonceagain", - "SeriouslythisistheendWe'refinishedAllsetByeDoneThisOneWillBeSplitToMeetTheLimit", - }; + "SeriouslythisistheendWe'refinishedAllsetByeDoneThisOneWillBeSplitToMeetTheLimit" + ]; - var expected = new[] - { + string[] expected = + [ $"Thisisatestoftheemergencybroadcastsystem{Environment.NewLine}Thisisonlyatest", "WerepeatthisisonlyatestAunittest", "AsmallnoteAndanotherAndonceagain", "SeriouslythisistheendWe'refinishedAllse", - "tByeDoneThisOneWillBeSplitToMeetTheLimit", - }; + "tByeDoneThisOneWillBeSplitToMeetTheLimit" + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -451,22 +451,22 @@ public void CanSplitTextParagraphsWithNoDelimiters() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphsOnNewlines() { - List input = new() - { + List input = + [ "This_is_a_test_of_the_emergency_broadcast_system\r\nThis_is_only_a_test", "We_repeat_this_is_only_a_test\nA_unit_test", "A_small_note\nAnd_another\r\nAnd_once_again\rSeriously_this_is_the_end\nWe're_finished\nAll_set\nBye\n", "Done" - }; + ]; - var expected = new[] - { + string[] expected = + [ "This_is_a_test_of_the_emergency_broadcast_system", "This_is_only_a_test", "We_repeat_this_is_only_a_test\nA_unit_test", "A_small_note\nAnd_another\nAnd_once_again", - "Seriously_this_is_the_end\nWe're_finished\nAll_set\nBye Done", - }; + "Seriously_this_is_the_end\nWe're_finished\nAll_set\nBye Done" + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 15, tokenCounter: s_tokenCounter); @@ -504,11 +504,11 @@ public void CanSplitVeryLargeDocumentsWithoutStackOverflowing() public void CanSplitPlainTextLinesWithCustomTokenCounter() { const string Input = "This is a test of the emergency broadcast system. This is only a test."; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test." - }; + ]; var result = TextChunker.SplitPlainTextLines(Input, 60, s => s.Length); @@ -519,17 +519,17 @@ public void CanSplitPlainTextLinesWithCustomTokenCounter() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphsWithCustomTokenCounter() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; - var expected = new[] - { + ]; + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 52, tokenCounter: s => s.Length); @@ -540,20 +540,20 @@ public void CanSplitMarkdownParagraphsWithCustomTokenCounter() [Trait("Category", "UnitTest")] public void CanSplitMarkdownParagraphsWithOverlapAndCustomTokenCounter() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "emergency broadcast system. This is only a test.", "This is only a test. We repeat, this is only a test.", "We repeat, this is only a test. A unit test.", "A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 75, 40, tokenCounter: s => s.Length); @@ -564,18 +564,18 @@ public void CanSplitMarkdownParagraphsWithOverlapAndCustomTokenCounter() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsWithCustomTokenCounter() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 52, tokenCounter: s => s.Length); @@ -586,20 +586,20 @@ public void CanSplitTextParagraphsWithCustomTokenCounter() [Trait("Category", "UnitTest")] public void CanSplitTextParagraphsWithOverlapAndCustomTokenCounter() { - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "emergency broadcast system. This is only a test.", "This is only a test. We repeat, this is only a test.", "We repeat, this is only a test. A unit test.", "A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 75, 40, tokenCounter: s => s.Length); @@ -611,11 +611,11 @@ public void CanSplitTextParagraphsWithOverlapAndCustomTokenCounter() public void CanSplitMarkDownLinesWithCustomTokenCounter() { const string Input = "This is a test of the emergency broadcast system. This is only a test."; - var expected = new[] - { + string[] expected = + [ "This is a test of the emergency broadcast system.", "This is only a test." - }; + ]; var result = TextChunker.SplitMarkDownLines(Input, 60, tokenCounter: s => s.Length); @@ -627,17 +627,17 @@ public void CanSplitMarkDownLinesWithCustomTokenCounter() public void CanSplitMarkdownParagraphsWithHeader() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; - var expected = new[] - { + ]; + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}This is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 20, chunkHeader: ChunkHeader, tokenCounter: s_tokenCounter); @@ -649,20 +649,20 @@ public void CanSplitMarkdownParagraphsWithHeader() public void CanSplitMarkdownParagraphsWithOverlapAndHeader() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}emergency broadcast system. This is only a test.", $"{ChunkHeader}This is only a test. We repeat, this is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test.", $"{ChunkHeader}A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 22, 8, chunkHeader: ChunkHeader, tokenCounter: s_tokenCounter); @@ -674,18 +674,18 @@ public void CanSplitMarkdownParagraphsWithOverlapAndHeader() public void CanSplitTextParagraphsWithHeader() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}This is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 20, chunkHeader: ChunkHeader, tokenCounter: s_tokenCounter); @@ -697,20 +697,20 @@ public void CanSplitTextParagraphsWithHeader() public void CanSplitTextParagraphsWithOverlapAndHeader() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}emergency broadcast system. This is only a test.", $"{ChunkHeader}This is only a test. We repeat, this is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test.", $"{ChunkHeader}A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 22, 8, chunkHeader: ChunkHeader, tokenCounter: s_tokenCounter); @@ -722,17 +722,17 @@ public void CanSplitTextParagraphsWithOverlapAndHeader() public void CanSplitMarkdownParagraphsWithHeaderAndCustomTokenCounter() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; - var expected = new[] - { + ]; + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}This is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 77, chunkHeader: ChunkHeader, tokenCounter: s => s.Length); @@ -744,20 +744,20 @@ public void CanSplitMarkdownParagraphsWithHeaderAndCustomTokenCounter() public void CanSplitMarkdownParagraphsWithOverlapAndHeaderAndCustomTokenCounter() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}emergency broadcast system. This is only a test.", $"{ChunkHeader}This is only a test. We repeat, this is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test.", $"{ChunkHeader}A unit test." - }; + ]; var result = TextChunker.SplitMarkdownParagraphs(input, 100, 40, chunkHeader: ChunkHeader, tokenCounter: s => s.Length); @@ -769,18 +769,18 @@ public void CanSplitMarkdownParagraphsWithOverlapAndHeaderAndCustomTokenCounter( public void CanSplitTextParagraphsWithHeaderAndCustomTokenCounter() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}This is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 77, chunkHeader: ChunkHeader, tokenCounter: s => s.Length); @@ -792,20 +792,20 @@ public void CanSplitTextParagraphsWithHeaderAndCustomTokenCounter() public void CanSplitTextParagraphsWithOverlapAndHeaderAndCustomTokenCounter() { const string ChunkHeader = "DOCUMENT NAME: test.txt\n\n"; - List input = new() - { + List input = + [ "This is a test of the emergency broadcast system. This is only a test.", "We repeat, this is only a test. A unit test." - }; + ]; - var expected = new[] - { + string[] expected = + [ $"{ChunkHeader}This is a test of the emergency broadcast system.", $"{ChunkHeader}emergency broadcast system. This is only a test.", $"{ChunkHeader}This is only a test. We repeat, this is only a test.", $"{ChunkHeader}We repeat, this is only a test. A unit test.", $"{ChunkHeader}A unit test." - }; + ]; var result = TextChunker.SplitPlainTextParagraphs(input, 100, 40, chunkHeader: ChunkHeader, tokenCounter: s => s.Length); diff --git a/service/tests/Core.UnitTests/Prompts/PromptUtilsTest.cs b/service/tests/Core.UnitTests/Prompts/PromptUtilsTest.cs index 2ad1f1092..edf67af24 100644 --- a/service/tests/Core.UnitTests/Prompts/PromptUtilsTest.cs +++ b/service/tests/Core.UnitTests/Prompts/PromptUtilsTest.cs @@ -49,7 +49,7 @@ public void ItRendersFactTemplatesWithTags() public void ItRendersFactTemplatesWithMetadata() { Assert.Equal("text; Foo:-", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}", factContent: "text")); - Assert.Equal("text; Foo:-", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}", factContent: "text", metadata: new Dictionary())); + Assert.Equal("text; Foo:-", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}", factContent: "text", metadata: [])); Assert.Equal("text; Foo:bar", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}", factContent: "text", metadata: new Dictionary { { "foo", "bar" } })); Assert.Equal("text; Foo:bar", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}", factContent: "text", metadata: new Dictionary { { "foo", "bar" }, { "car", "red" } })); Assert.Equal("text; Foo:bar; Car:red", PromptUtils.RenderFactTemplate(template: "{{$content}}; Foo:{{$meta[foo]}}; Car:{{$meta[car]}}", factContent: "text", metadata: new Dictionary { { "foo", "bar" }, { "car", "red" } })); diff --git a/service/tests/Service.FunctionalTests/ImageOCRTest.cs b/service/tests/Service.FunctionalTests/ImageOCRTest.cs index 772cb7f49..15affd34a 100644 --- a/service/tests/Service.FunctionalTests/ImageOCRTest.cs +++ b/service/tests/Service.FunctionalTests/ImageOCRTest.cs @@ -29,7 +29,7 @@ public async Task ItUsesTextFoundInsideImages() // Arrange const string DocId = nameof(this.ItUsesTextFoundInsideImages); await this._memory.ImportDocumentAsync(new Document(DocId) - .AddFiles(new[] { Path.Join(this._fixturesPath, "ANWC-image-for-OCR.jpg") })); + .AddFiles([Path.Join(this._fixturesPath, "ANWC-image-for-OCR.jpg")])); // Wait while (!await this._memory.IsDocumentReadyAsync(documentId: DocId)) diff --git a/service/tests/Service.FunctionalTests/SKPluginTest.cs b/service/tests/Service.FunctionalTests/SKPluginTest.cs index ebbafe7d1..fc80788da 100644 --- a/service/tests/Service.FunctionalTests/SKPluginTest.cs +++ b/service/tests/Service.FunctionalTests/SKPluginTest.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.Identity; using Microsoft.KernelMemory; using Microsoft.KM.TestHelpers; using Microsoft.SemanticKernel; @@ -18,12 +19,27 @@ public SKPluginTest(IConfiguration cfg, ITestOutputHelper output) : base(cfg, ou public async Task ItSupportsQuestionsOnUploadedFiles() { // Arrange - var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion( - deploymentName: this.AzureOpenAITextConfiguration.Deployment, - modelId: this.AzureOpenAITextConfiguration.Deployment, - endpoint: this.AzureOpenAITextConfiguration.Endpoint, - apiKey: this.AzureOpenAITextConfiguration.APIKey) - .Build(); + Kernel kernel; + if (string.IsNullOrEmpty(this.AzureOpenAITextConfiguration.APIKey)) + { + // MS Entra auth + kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion( + deploymentName: this.AzureOpenAITextConfiguration.Deployment, + modelId: this.AzureOpenAITextConfiguration.Deployment, + endpoint: this.AzureOpenAITextConfiguration.Endpoint, + credentials: new DefaultAzureCredential()) + .Build(); + } + else + { + // API key auth + kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion( + deploymentName: this.AzureOpenAITextConfiguration.Deployment, + modelId: this.AzureOpenAITextConfiguration.Deployment, + endpoint: this.AzureOpenAITextConfiguration.Endpoint, + apiKey: this.AzureOpenAITextConfiguration.APIKey) + .Build(); + } var skPrompt = """ Question to Kernel Memory: {{$input}} diff --git a/service/tests/TestHelpers/FakeEmbeddingGenerator.cs b/service/tests/TestHelpers/FakeEmbeddingGenerator.cs index 58e8c7118..b26188cdc 100644 --- a/service/tests/TestHelpers/FakeEmbeddingGenerator.cs +++ b/service/tests/TestHelpers/FakeEmbeddingGenerator.cs @@ -7,7 +7,7 @@ namespace Microsoft.KM.TestHelpers; public sealed class FakeEmbeddingGenerator : ITextEmbeddingGenerator { - private readonly Dictionary _mocks = new(); + private readonly Dictionary _mocks = []; public IReadOnlyDictionary Attributes { get; } = new Dictionary(); @@ -18,7 +18,7 @@ public void Mock(string input, float[] embedding) public int CountTokens(string text) => 0; - public IReadOnlyList GetTokens(string text) => Array.Empty(); + public IReadOnlyList GetTokens(string text) => []; public int MaxTokens { get; } = 0; diff --git a/tools/InteractiveSetup/Main.cs b/tools/InteractiveSetup/Main.cs index 9cbfcbffc..0819dbbbe 100644 --- a/tools/InteractiveSetup/Main.cs +++ b/tools/InteractiveSetup/Main.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using System; -using System.Collections.Generic; using Microsoft.KernelMemory.InteractiveSetup.Service; using Microsoft.KernelMemory.InteractiveSetup.Services; using Microsoft.KernelMemory.InteractiveSetup.UI; @@ -181,8 +180,8 @@ private static void EmbeddingGeneratorSetup(Context ctx) { x.Retrieval.EmbeddingGeneratorType = "AzureOpenAIEmbedding"; x.DataIngestion.EmbeddingGeneratorTypes = ctx.CfgEmbeddingGenerationEnabled.Value - ? new List { x.Retrieval.EmbeddingGeneratorType } - : new List(); + ? [x.Retrieval.EmbeddingGeneratorType] + : []; }); ctx.CfgAzureOpenAIEmbedding.Value = true; }), @@ -193,8 +192,8 @@ private static void EmbeddingGeneratorSetup(Context ctx) { x.Retrieval.EmbeddingGeneratorType = "OpenAI"; x.DataIngestion.EmbeddingGeneratorTypes = ctx.CfgEmbeddingGenerationEnabled.Value - ? new List { x.Retrieval.EmbeddingGeneratorType } - : new List { }; + ? [x.Retrieval.EmbeddingGeneratorType] + : []; }); ctx.CfgOpenAI.Value = true; }), @@ -205,8 +204,8 @@ private static void EmbeddingGeneratorSetup(Context ctx) { x.Retrieval.EmbeddingGeneratorType = "Ollama"; x.DataIngestion.EmbeddingGeneratorTypes = ctx.CfgEmbeddingGenerationEnabled.Value - ? new List { x.Retrieval.EmbeddingGeneratorType } - : new List { }; + ? [x.Retrieval.EmbeddingGeneratorType] + : []; }); ctx.CfgOllama.Value = true; }), @@ -216,7 +215,7 @@ private static void EmbeddingGeneratorSetup(Context ctx) AppSettings.Change(x => { x.Retrieval.EmbeddingGeneratorType = ""; - x.DataIngestion.EmbeddingGeneratorTypes = new List(); + x.DataIngestion.EmbeddingGeneratorTypes = []; }); }), diff --git a/tools/InteractiveSetup/Service/KMService.cs b/tools/InteractiveSetup/Service/KMService.cs index 473803ca3..05687b92c 100644 --- a/tools/InteractiveSetup/Service/KMService.cs +++ b/tools/InteractiveSetup/Service/KMService.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using System.Collections.Generic; using Microsoft.KernelMemory.InteractiveSetup.UI; namespace Microsoft.KernelMemory.InteractiveSetup.Service; @@ -19,8 +18,8 @@ public static void Setup(Context ctx) "When running asynchronously, handlers run in the background and use distributed queues to enable " + "long running tasks, to retry in case of errors, and to allow scaling the service horizontally. " + "The web service can also be disabled in case the queued jobs are populated differently.", - Options = new List - { + Options = + [ new("Web Service with Asynchronous Ingestion Handlers (better for retry logic and long operations)", config.Service.RunWebService && config.Service.RunHandlers, () => @@ -34,6 +33,7 @@ public static void Setup(Context ctx) x.DataIngestion.OrchestrationType = "Distributed"; }); }), + new("Web Service with Synchronous Ingestion Handlers", config.Service.RunWebService && !config.Service.RunHandlers, () => @@ -48,6 +48,7 @@ public static void Setup(Context ctx) x.DataIngestion.DistributedOrchestration.QueueType = ""; }); }), + new("No web Service, run only asynchronous Ingestion Handlers in the background", !config.Service.RunWebService && config.Service.RunHandlers, () => @@ -61,8 +62,9 @@ public static void Setup(Context ctx) x.DataIngestion.OrchestrationType = "Distributed"; }); }), - new("-exit-", false, SetupUI.Exit), - } + + new("-exit-", false, SetupUI.Exit) + ] }); } } diff --git a/tools/InteractiveSetup/Service/Logger.cs b/tools/InteractiveSetup/Service/Logger.cs index ec7f02727..1d1f3e2a1 100644 --- a/tools/InteractiveSetup/Service/Logger.cs +++ b/tools/InteractiveSetup/Service/Logger.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using System.Collections.Generic; using Microsoft.KernelMemory.InteractiveSetup.UI; using Newtonsoft.Json.Linq; @@ -14,16 +13,16 @@ public static void Setup() SetupUI.AskQuestionWithOptions(new QuestionWithOptions { Title = "Log level?", - Options = new List - { + Options = + [ new("Trace", false, () => { logLevel = "Trace"; }), new("Debug", false, () => { logLevel = "Debug"; }), new("Information", false, () => { logLevel = "Information"; }), new("Warning", true, () => { logLevel = "Warning"; }), new("Error", false, () => { logLevel = "Error"; }), new("Critical", false, () => { logLevel = "Critical"; }), - new("-exit-", false, SetupUI.Exit), - } + new("-exit-", false, SetupUI.Exit) + ] }); AppSettings.GlobalChange(data => diff --git a/tools/InteractiveSetup/Service/Webservice.cs b/tools/InteractiveSetup/Service/Webservice.cs index 26b6277f1..41eb7f1d7 100644 --- a/tools/InteractiveSetup/Service/Webservice.cs +++ b/tools/InteractiveSetup/Service/Webservice.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using System.Collections.Generic; using Microsoft.KernelMemory.InteractiveSetup.UI; namespace Microsoft.KernelMemory.InteractiveSetup.Service; @@ -17,8 +16,8 @@ public static void Setup(Context ctx, bool force = false) { Title = "Protect the web service with API Keys?", Description = "If the web service runs on a public network it should protected requiring clients to pass one of two secret API keys on each request. The API Key is passed using the `Authorization` HTTP header.", - Options = new List - { + Options = + [ new("Yes", config.ServiceAuthorization.Enabled, () => { AppSettings.Change(x => @@ -29,6 +28,7 @@ public static void Setup(Context ctx, bool force = false) x.ServiceAuthorization.AccessKey2 = SetupUI.AskPassword("API Key 2 (min 32 chars, alphanumeric ('- . _' allowed))", x.ServiceAuthorization.AccessKey2); }); }), + new("No", !config.ServiceAuthorization.Enabled, () => { AppSettings.Change(x => @@ -39,19 +39,20 @@ public static void Setup(Context ctx, bool force = false) x.ServiceAuthorization.AccessKey2 = ""; }); }), - new("-exit-", false, SetupUI.Exit), - } + + new("-exit-", false, SetupUI.Exit) + ] }); SetupUI.AskQuestionWithOptions(new QuestionWithOptions { Title = "Enable OpenAPI swagger doc at /swagger/index.html?", - Options = new List - { + Options = + [ new("Yes", config.Service.OpenApiEnabled, () => { AppSettings.Change(x => { x.Service.OpenApiEnabled = true; }); }), new("No", !config.Service.OpenApiEnabled, () => { AppSettings.Change(x => { x.Service.OpenApiEnabled = false; }); }), - new("-exit-", false, SetupUI.Exit), - } + new("-exit-", false, SetupUI.Exit) + ] }); } } diff --git a/tools/InteractiveSetup/Services/Ollama.cs b/tools/InteractiveSetup/Services/Ollama.cs index 59b656540..5470f4318 100644 --- a/tools/InteractiveSetup/Services/Ollama.cs +++ b/tools/InteractiveSetup/Services/Ollama.cs @@ -15,8 +15,8 @@ public static void Setup(Context ctx, bool force = false) ctx.CfgOllama.Value = false; const string ServiceName = "Ollama"; - Dictionary textModel = new(); - Dictionary embeddingModel = new(); + Dictionary textModel = []; + Dictionary embeddingModel = []; if (!AppSettings.GetCurrentConfig().Services.TryGetValue(ServiceName, out var config)) { diff --git a/tools/InteractiveSetup/Services/Redis.cs b/tools/InteractiveSetup/Services/Redis.cs index a7d2488db..ccd016986 100644 --- a/tools/InteractiveSetup/Services/Redis.cs +++ b/tools/InteractiveSetup/Services/Redis.cs @@ -31,17 +31,17 @@ bool AskMoreTags(string additionalMessage) SetupUI.AskQuestionWithOptions(new QuestionWithOptions { Title = $"{additionalMessage}[Redis] Do you want to add a tag (or another tag) to filter memory records?", - Options = new List - { + Options = + [ new("Yes", false, () => { answer = "Yes"; }), - new("No", true, () => { answer = "No"; }), - } + new("No", true, () => { answer = "No"; }) + ] }); return answer.Equals("Yes", StringComparison.OrdinalIgnoreCase); } - Dictionary tagFields = new(); + Dictionary tagFields = []; string additionalMessage = string.Empty; while (AskMoreTags(additionalMessage)) diff --git a/tools/InteractiveSetup/UI/QuestionWithOptions.cs b/tools/InteractiveSetup/UI/QuestionWithOptions.cs index 2c86dc3b5..5c6bc623b 100644 --- a/tools/InteractiveSetup/UI/QuestionWithOptions.cs +++ b/tools/InteractiveSetup/UI/QuestionWithOptions.cs @@ -8,5 +8,5 @@ public sealed class QuestionWithOptions { public string Title { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; - public List Options { get; set; } = new(); + public List Options { get; set; } = []; } diff --git a/tools/InteractiveSetup/UI/SetupUI.cs b/tools/InteractiveSetup/UI/SetupUI.cs index b2113261e..80107bd33 100644 --- a/tools/InteractiveSetup/UI/SetupUI.cs +++ b/tools/InteractiveSetup/UI/SetupUI.cs @@ -15,8 +15,8 @@ public static string AskPassword(string question, string? defaultValue, bool tri public static bool AskBoolean(string question, bool defaultValue) { - string[] yes = { "YES", "Y" }; - string[] no = { "NO", "N" }; + string[] yes = ["YES", "Y"]; + string[] no = ["NO", "N"]; while (true) { var answer = AskOpenQuestion(question: question, defaultValue: defaultValue ? "Yes" : "No", optional: false).ToUpperInvariant();