Shorten TextSearchSearchResult to TextSearchResult (#1780)

This commit is contained in:
westey
2025-10-29 21:16:28 +00:00
committed by GitHub
Unverified
parent a2ee840eef
commit f6eadd412e
4 changed files with 36 additions and 36 deletions
@@ -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<IEnumerable<TextSearchProvider.TextSearchSearchResult>> MockSearchAsync(string query, CancellationToken cancellationToken)
static Task<IEnumerable<TextSearchProvider.TextSearchResult>> 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<TextSearchProvider.TextSearchSearchResult> results = new();
List<TextSearchProvider.TextSearchResult> results = new();
if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase))
{
@@ -78,5 +78,5 @@ static Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> MockSearchAs
});
}
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>(results);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}
@@ -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<string, CancellationToken, Task<IEnumerable<TextSearchSearchResult>>> _searchAsync;
private readonly Func<string, CancellationToken, Task<IEnumerable<TextSearchResult>>> _searchAsync;
private readonly ILogger<TextSearchProvider>? _logger;
private readonly AITool[] _tools;
private readonly Queue<string> _recentMessagesText;
@@ -53,7 +53,7 @@ public sealed class TextSearchProvider : AIContextProvider
/// <param name="options">Optional configuration options.</param>
/// <param name="loggerFactory">Optional logger factory.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="searchAsync"/> is <see langword="null"/>.</exception>
public TextSearchProvider(Func<string, CancellationToken, Task<IEnumerable<TextSearchSearchResult>>> searchAsync, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null)
public TextSearchProvider(Func<string, CancellationToken, Task<IEnumerable<TextSearchResult>>> 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 <see cref="TextSearchProviderOptions.ContextFormatter"/> delegates are not serialized.
/// </remarks>
public TextSearchProvider(Func<string, CancellationToken, Task<IEnumerable<TextSearchSearchResult>>> searchAsync, JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, TextSearchProviderOptions? options = null, ILoggerFactory? loggerFactory = null)
public TextSearchProvider(Func<string, CancellationToken, Task<IEnumerable<TextSearchResult>>> 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<TextSearchSearchResult> materialized = results as IList<TextSearchSearchResult> ?? results.ToList();
IList<TextSearchResult> materialized = results as IList<TextSearchResult> ?? 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<string> SearchAsync(string userQuestion, CancellationToken cancellationToken = default)
{
var results = await this._searchAsync(userQuestion, cancellationToken).ConfigureAwait(false);
IList<TextSearchSearchResult> materialized = results as IList<TextSearchSearchResult> ?? results.ToList();
IList<TextSearchResult> materialized = results as IList<TextSearchResult> ?? 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
/// </summary>
/// <param name="results">The results.</param>
/// <returns>Formatted string (may be empty).</returns>
private string FormatResults(IList<TextSearchSearchResult> results)
private string FormatResults(IList<TextSearchResult> results)
{
if (this._options.ContextFormatter is not null)
{
@@ -276,7 +276,7 @@ public sealed class TextSearchProvider : AIContextProvider
/// <summary>
/// Represents a single retrieved text search result.
/// </summary>
public sealed class TextSearchSearchResult
public sealed class TextSearchResult
{
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// If a <see cref="TextSearchSearchResult"/> is created to represent some underlying object from another object
/// If a <see cref="TextSearchResult"/> 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 <see cref="TextSearchProviderOptions.ContextFormatter"/> to access the underlying object model if needed.
/// </remarks>
@@ -45,7 +45,7 @@ public sealed class TextSearchProviderOptions
/// <remarks>
/// If provided, <see cref="ContextPrompt"/> and <see cref="CitationsPrompt"/> are ignored.
/// </remarks>
public Func<IList<TextSearchProvider.TextSearchSearchResult>, string>? ContextFormatter { get; set; }
public Func<IList<TextSearchProvider.TextSearchResult>, string>? ContextFormatter { get; set; }
/// <summary>
/// Gets or sets the number of recent conversation messages (both user and assistant) to keep in memory
@@ -39,17 +39,17 @@ public sealed class TextSearchProviderTests
public async Task InvokingAsync_ShouldInjectFormattedResultsAsync(string? overrideContextPrompt, string? overrideCitationsPrompt, bool withLogging)
{
// Arrange
List<TextSearchProvider.TextSearchSearchResult> results =
List<TextSearchProvider.TextSearchResult> 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<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>(results);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}
var options = new TextSearchProviderOptions
@@ -156,15 +156,15 @@ public sealed class TextSearchProviderTests
public async Task SearchAsync_ShouldReturnFormattedResultsAsync(string? overrideContextPrompt, string? overrideCitationsPrompt)
{
// Arrange
List<TextSearchProvider.TextSearchSearchResult> results =
List<TextSearchProvider.TextSearchResult> 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<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>(results);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}
var options = new TextSearchProviderOptions
@@ -208,15 +208,15 @@ public sealed class TextSearchProviderTests
public async Task InvokingAsync_ShouldUseContextFormatterWhenProvidedAsync()
{
// Arrange
List<TextSearchProvider.TextSearchSearchResult> results =
List<TextSearchProvider.TextSearchResult> 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<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>(results);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(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<TextSearchProvider.TextSearchSearchResult> results =
List<TextSearchProvider.TextSearchResult> results =
[
new() { Name = "Doc1", Value = "Content 1", RawRepresentation = payload1 },
new() { Name = "Doc2", Value = "Content 2", RawRepresentation = payload2 }
];
Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>(results);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}
var options = new TextSearchProviderOptions
@@ -299,10 +299,10 @@ public sealed class TextSearchProviderTests
RecentMessageMemoryLimit = 3
};
string? capturedInput = null;
Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]); // No results needed.
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]); // No results needed.
}
var provider = new TextSearchProvider(SearchDelegateAsync, options);
@@ -338,10 +338,10 @@ public sealed class TextSearchProviderTests
RecentMessageMemoryLimit = 5
};
string? capturedInput = null;
Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegateAsync(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]);
}
var provider = new TextSearchProvider(SearchDelegateAsync, options);
@@ -443,10 +443,10 @@ public sealed class TextSearchProviderTests
// Act
var state = provider.Serialize();
string? capturedInput = null;
Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]);
}
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<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]);
}
// Act
@@ -508,10 +508,10 @@ public sealed class TextSearchProviderTests
var emptyState = JsonSerializer.Deserialize("{}", TestJsonSerializerContext.Default.JsonElement);
string? capturedInput = null;
Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchDelegate2Async(string input, CancellationToken ct)
{
capturedInput = input;
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]);
}
// Act
@@ -530,9 +530,9 @@ public sealed class TextSearchProviderTests
#endregion
private Task<IEnumerable<TextSearchProvider.TextSearchSearchResult>> NoResultSearchAsync(string input, CancellationToken ct)
private Task<IEnumerable<TextSearchProvider.TextSearchResult>> NoResultSearchAsync(string input, CancellationToken ct)
{
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchSearchResult>>([]);
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>([]);
}
private sealed class RawPayload