diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step18_TextSearchRag/Program.cs b/dotnet/samples/GettingStarted/Agents/Agent_Step18_TextSearchRag/Program.cs index f06ba68298..931ce50014 100644 --- a/dotnet/samples/GettingStarted/Agents/Agent_Step18_TextSearchRag/Program.cs +++ b/dotnet/samples/GettingStarted/Agents/Agent_Step18_TextSearchRag/Program.cs @@ -42,11 +42,11 @@ Console.WriteLine(await agent.RunAsync("How long does standard shipping usually Console.WriteLine("\n>> Asking about product care\n"); Console.WriteLine(await agent.RunAsync("What is the best way to maintain the TrailRunner tent fabric?", thread)); -static Task> MockSearchAsync(string query, CancellationToken cancellationToken) +static Task> MockSearchAsync(string query, CancellationToken cancellationToken) { // The mock search inspects the user's question and returns pre-defined snippets // that resemble documents stored in an external knowledge source. - List results = new(); + List results = new(); if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase)) { @@ -78,5 +78,5 @@ static Task> MockSearchAs }); } - return Task.FromResult>(results); + return Task.FromResult>(results); } diff --git a/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProvider.cs b/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProvider.cs index b3b62318f6..7c6e05828f 100644 --- a/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProvider.cs +++ b/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProvider.cs @@ -40,7 +40,7 @@ public sealed class TextSearchProvider : AIContextProvider private const string DefaultContextPrompt = "## Additional Context\nConsider the following information from source documents when responding to the user:"; private const string DefaultCitationsPrompt = "Include citations to the source document with document name and link if document name and link is available."; - private readonly Func>> _searchAsync; + private readonly Func>> _searchAsync; private readonly ILogger? _logger; private readonly AITool[] _tools; private readonly Queue _recentMessagesText; @@ -53,7 +53,7 @@ public sealed class TextSearchProvider : AIContextProvider /// Optional configuration options. /// Optional logger factory. /// Thrown when is . - public TextSearchProvider(Func>> searchAsync, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null) + public TextSearchProvider(Func>> searchAsync, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null) { this._searchAsync = searchAsync ?? throw new ArgumentNullException(nameof(searchAsync)); this._options = options ?? new(); @@ -85,7 +85,7 @@ public sealed class TextSearchProvider : AIContextProvider /// If a value was not persisted or matches the defaults it will fall back to the built-in defaults. /// Custom delegates are not serialized. /// - public TextSearchProvider(Func>> searchAsync, JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null) + public TextSearchProvider(Func>> searchAsync, JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null) { this._searchAsync = searchAsync ?? throw new ArgumentNullException(nameof(searchAsync)); this._options = options ?? new(); @@ -148,7 +148,7 @@ public sealed class TextSearchProvider : AIContextProvider // Search var results = await this._searchAsync(input, cancellationToken).ConfigureAwait(false); - IList materialized = results as IList ?? results.ToList(); + IList materialized = results as IList ?? results.ToList(); if (materialized.Count == 0) { this._logger?.LogWarning("TextSearchProvider: No search results found."); @@ -226,7 +226,7 @@ public sealed class TextSearchProvider : AIContextProvider internal async Task SearchAsync(string userQuestion, CancellationToken cancellationToken = default) { var results = await this._searchAsync(userQuestion, cancellationToken).ConfigureAwait(false); - IList materialized = results as IList ?? results.ToList(); + IList materialized = results as IList ?? results.ToList(); string formatted = this.FormatResults(materialized); this._logger?.LogInformation("TextSearchProvider: Retrieved {Count} search results.", materialized.Count); @@ -240,7 +240,7 @@ public sealed class TextSearchProvider : AIContextProvider /// /// The results. /// Formatted string (may be empty). - private string FormatResults(IList results) + private string FormatResults(IList results) { if (this._options.ContextFormatter is not null) { @@ -276,7 +276,7 @@ public sealed class TextSearchProvider : AIContextProvider /// /// Represents a single retrieved text search result. /// - public sealed class TextSearchSearchResult + public sealed class TextSearchResult { /// /// Gets or sets the display name of the source document (optional). @@ -297,7 +297,7 @@ public sealed class TextSearchProvider : AIContextProvider /// Gets or sets the raw representation of the search result from the data source. /// /// - /// If a is created to represent some underlying object from another object + /// If a is created to represent some underlying object from another object /// model, this property can be used to store that original object. This can be useful for debugging or /// for enabling the to access the underlying object model if needed. /// diff --git a/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProviderOptions.cs b/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProviderOptions.cs index 7709df435e..e6b20ed6b2 100644 --- a/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProviderOptions.cs +++ b/dotnet/src/Microsoft.Agents.AI/Data/TextSearchProviderOptions.cs @@ -45,7 +45,7 @@ public sealed class TextSearchProviderOptions /// /// If provided, and are ignored. /// - public Func, string>? ContextFormatter { get; set; } + public Func, string>? ContextFormatter { get; set; } /// /// Gets or sets the number of recent conversation messages (both user and assistant) to keep in memory diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Data/TextSearchProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Data/TextSearchProviderTests.cs index fa5f33ac95..8b019ab8c6 100644 --- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/Data/TextSearchProviderTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/Data/TextSearchProviderTests.cs @@ -39,17 +39,17 @@ public sealed class TextSearchProviderTests public async Task InvokingAsync_ShouldInjectFormattedResultsAsync(string? overrideContextPrompt, string? overrideCitationsPrompt, bool withLogging) { // Arrange - List results = + List results = [ new() { Name = "Doc1", Link = "http://example.com/doc1", Value = "Content of Doc1" }, new() { Name = "Doc2", Link = "http://example.com/doc2", Value = "Content of Doc2" } ]; string? capturedInput = null; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>(results); + return Task.FromResult>(results); } var options = new TextSearchProviderOptions @@ -156,15 +156,15 @@ public sealed class TextSearchProviderTests public async Task SearchAsync_ShouldReturnFormattedResultsAsync(string? overrideContextPrompt, string? overrideCitationsPrompt) { // Arrange - List results = + List results = [ new() { Name = "Doc1", Link = "http://example.com/doc1", Value = "Content of Doc1" }, new() { Name = "Doc2", Link = "http://example.com/doc2", Value = "Content of Doc2" } ]; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { - return Task.FromResult>(results); + return Task.FromResult>(results); } var options = new TextSearchProviderOptions @@ -208,15 +208,15 @@ public sealed class TextSearchProviderTests public async Task InvokingAsync_ShouldUseContextFormatterWhenProvidedAsync() { // Arrange - List results = + List results = [ new() { Name = "Doc1", Link = "http://example.com/doc1", Value = "Content of Doc1" }, new() { Name = "Doc2", Link = "http://example.com/doc2", Value = "Content of Doc2" } ]; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { - return Task.FromResult>(results); + return Task.FromResult>(results); } var options = new TextSearchProviderOptions @@ -242,15 +242,15 @@ public sealed class TextSearchProviderTests // Arrange var payload1 = new RawPayload { Id = "R1" }; var payload2 = new RawPayload { Id = "R2" }; - List results = + List results = [ new() { Name = "Doc1", Value = "Content 1", RawRepresentation = payload1 }, new() { Name = "Doc2", Value = "Content 2", RawRepresentation = payload2 } ]; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { - return Task.FromResult>(results); + return Task.FromResult>(results); } var options = new TextSearchProviderOptions @@ -299,10 +299,10 @@ public sealed class TextSearchProviderTests RecentMessageMemoryLimit = 3 }; string? capturedInput = null; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>([]); // No results needed. + return Task.FromResult>([]); // No results needed. } var provider = new TextSearchProvider(SearchDelegateAsync, options); @@ -338,10 +338,10 @@ public sealed class TextSearchProviderTests RecentMessageMemoryLimit = 5 }; string? capturedInput = null; - Task> SearchDelegateAsync(string input, CancellationToken ct) + Task> SearchDelegateAsync(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>([]); + return Task.FromResult>([]); } var provider = new TextSearchProvider(SearchDelegateAsync, options); @@ -443,10 +443,10 @@ public sealed class TextSearchProviderTests // Act var state = provider.Serialize(); string? capturedInput = null; - Task> SearchDelegate2Async(string input, CancellationToken ct) + Task> SearchDelegate2Async(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>([]); + return Task.FromResult>([]); } var roundTrippedProvider = new TextSearchProvider(SearchDelegate2Async, state, options: new TextSearchProviderOptions { @@ -482,10 +482,10 @@ public sealed class TextSearchProviderTests var state = initialProvider.Serialize(); string? capturedInput = null; - Task> SearchDelegate2Async(string input, CancellationToken ct) + Task> SearchDelegate2Async(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>([]); + return Task.FromResult>([]); } // Act @@ -508,10 +508,10 @@ public sealed class TextSearchProviderTests var emptyState = JsonSerializer.Deserialize("{}", TestJsonSerializerContext.Default.JsonElement); string? capturedInput = null; - Task> SearchDelegate2Async(string input, CancellationToken ct) + Task> SearchDelegate2Async(string input, CancellationToken ct) { capturedInput = input; - return Task.FromResult>([]); + return Task.FromResult>([]); } // Act @@ -530,9 +530,9 @@ public sealed class TextSearchProviderTests #endregion - private Task> NoResultSearchAsync(string input, CancellationToken ct) + private Task> NoResultSearchAsync(string input, CancellationToken ct) { - return Task.FromResult>([]); + return Task.FromResult>([]); } private sealed class RawPayload