Repository: microsoft/semantic-kernel
File: dotnet/src/SemanticKernel.Abstractions/Data/TextSearch/ITextSearch.cs (C#)

Code before:
﻿// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.SemanticKernel.Data;

/// <summary>
/// Interface for text based search queries with type-safe LINQ filtering for use with Semantic Kernel prompts and automatic function calling.
/// </summary>
/// <typeparam name="TRecord">The type of record being searched.</typeparam>
[Experimental("SKEXP0001")]
public interface ITextSearch<TRecord>
{
    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="string"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    [RequiresDynamicCode("LINQ filtering over generic types requires dynamic code generation for expression trees.")]
    Task<KernelSearchResults<string>> SearchAsync(
        string query,
        TextSearchOptions<TRecord>? searchOptions = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="TextSearchResult"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    [RequiresDynamicCode("LINQ filtering over generic types requires dynamic code generation for expression trees.")]
    Task<KernelSearchResults<TextSearchResult>> GetTextSearchResultsAsync(
        string query,
        TextSearchOptions<TRecord>? searchOptions = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="object"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    [RequiresDynamicCode("LINQ filtering over generic types requires dynamic code generation for expression trees.")]
    Task<KernelSearchResults<object>> GetSearchResultsAsync(

Review comment (suggestion):
If we want to do proper NativeAOT annotating, then unless I'm mistaken, actual dynamic code is only needed if we need to generate LINQ Contains (i.e. because the user uses AnyTagEqualToFilterClause); in other words, if the user simply expresses equailty, no problematic APIs should be involved and everything should be possible with trimming/NativeAOT.

If that's the case (and we want to properly annotate for NativeAOT), then it seems like the annotation should go on AnyTagEqualToFilterClause only, and not on the entire SearchAsync API.

Code after:
﻿// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.SemanticKernel.Data;

/// <summary>
/// Interface for text based search queries with type-safe LINQ filtering for use with Semantic Kernel prompts and automatic function calling.
/// </summary>
/// <typeparam name="TRecord">The type of record being searched.</typeparam>
[Experimental("SKEXP0001")]
public interface ITextSearch<TRecord>
{
    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="string"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    Task<KernelSearchResults<string>> SearchAsync(
        string query,
        TextSearchOptions<TRecord>? searchOptions = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="TextSearchResult"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    Task<KernelSearchResults<TextSearchResult>> GetTextSearchResultsAsync(
        string query,
        TextSearchOptions<TRecord>? searchOptions = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Perform a search for content related to the specified query and return <see cref="object"/> values representing the search results.
    /// </summary>
    /// <param name="query">What to search for.</param>
    /// <param name="searchOptions">Options used when executing a text search.</param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    Task<KernelSearchResults<object>> GetSearchResultsAsync(
        string query,
        TextSearchOptions<TRecord>? searchOptions = null,
        CancellationToken cancellationToken = default);