in src/WebJobs.Extensions.OpenAI.AzureAISearch/AzureAISearchProvider.cs [105:186]
public async Task<SearchResponse> SearchAsync(SearchRequest request)
{
if (request.Query is null && request.Embeddings.IsEmpty)
{
throw new ArgumentException("Either query or embeddings must be provided");
}
if (request.ConnectionInfo is null)
{
throw new ArgumentNullException(nameof(request.ConnectionInfo));
}
this.searchConnectionNamePrefix = request.ConnectionInfo.ConnectionName;
this.SetConfigSectionProperties();
SearchClient searchClient = this.GetSearchClient(request.ConnectionInfo);
SearchOptions searchOptions = this.isSemanticSearchEnabled
? new SearchOptions
{
QueryType = SearchQueryType.Semantic,
SemanticSearch = new()
{
SemanticConfigurationName = "default",
QueryCaption = new(this.useSemanticCaptions
? QueryCaptionType.Extractive
: QueryCaptionType.None),
},
Size = request.MaxResults,
}
: new SearchOptions
{
Size = request.MaxResults,
};
// Use vector search if embeddings are provided.
if (!request.Embeddings.IsEmpty)
{
VectorizedQuery vectorQuery = new(request.Embeddings)
{
// Use a higher K value for semantic search to get better results.
KNearestNeighborsCount = this.isSemanticSearchEnabled ? Math.Max(50, request.MaxResults) : request.MaxResults,
};
vectorQuery.Fields.Add("embeddings");
searchOptions.VectorSearch = new();
searchOptions.VectorSearch.Queries.Add(vectorQuery);
}
Response<SearchResults<SearchDocument>> searchResultResponse = await searchClient.SearchAsync<SearchDocument>(
request.Query, searchOptions);
if (searchResultResponse.Value is null)
{
throw new InvalidOperationException($"Failed to get search result from Azure AI Search instance: {searchClient.ServiceName} and index: {searchClient.IndexName}");
}
SearchResults<SearchDocument> searchResult = searchResultResponse.Value;
List<SearchResult> results = new(capacity: request.MaxResults);
foreach (SearchResult<SearchDocument> doc in searchResult.GetResults())
{
doc.Document.TryGetValue("title", out object? titleValue);
string? contentValue;
if (this.useSemanticCaptions)
{
IEnumerable<string> docs = doc.SemanticSearch.Captions.Select(c => c.Text);
contentValue = string.Join(" . ", docs);
}
else
{
doc.Document.TryGetValue("text", out object? content);
contentValue = (string)content;
}
if (titleValue is string title && contentValue is string text)
{
results.Add(new SearchResult(title, text));
}
}
SearchResponse response = new(results);
return response;
}