diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 1b363636db590..4dab0986ea5b6 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -114,6 +114,9 @@ "unhold", "uninstrumented", "vcpus", + "Vectorizable", + "Vectorizer", + "Vectorizers", "vmss", "vnet", "westcentralus", diff --git a/sdk/search/Azure.Search.Documents/api/Azure.Search.Documents.netstandard2.0.cs b/sdk/search/Azure.Search.Documents/api/Azure.Search.Documents.netstandard2.0.cs index f0e7721fce614..b28d8460bbf19 100644 --- a/sdk/search/Azure.Search.Documents/api/Azure.Search.Documents.netstandard2.0.cs +++ b/sdk/search/Azure.Search.Documents/api/Azure.Search.Documents.netstandard2.0.cs @@ -76,7 +76,7 @@ public SearchClient(System.Uri endpoint, string indexName, Azure.Core.TokenCrede } public partial class SearchClientOptions : Azure.Core.ClientOptions { - public SearchClientOptions(Azure.Search.Documents.SearchClientOptions.ServiceVersion version = Azure.Search.Documents.SearchClientOptions.ServiceVersion.V2023_07_01_Preview) { } + public SearchClientOptions(Azure.Search.Documents.SearchClientOptions.ServiceVersion version = Azure.Search.Documents.SearchClientOptions.ServiceVersion.V2023_10_01_Preview) { } public Azure.Search.Documents.SearchAudience? Audience { get { throw null; } set { } } public Azure.Core.Serialization.ObjectSerializer Serializer { get { throw null; } set { } } public Azure.Search.Documents.SearchClientOptions.ServiceVersion Version { get { throw null; } } @@ -84,7 +84,7 @@ public enum ServiceVersion { V2020_06_30 = 1, V2021_04_30_Preview = 2, - V2023_07_01_Preview = 3, + V2023_10_01_Preview = 3, } } public static partial class SearchFilter @@ -170,10 +170,12 @@ public SearchOptions() { } public Azure.Search.Documents.Models.SemanticErrorHandling? SemanticErrorHandling { get { throw null; } set { } } public System.Collections.Generic.IList SemanticFields { get { throw null; } } public int? SemanticMaxWaitInMilliseconds { get { throw null; } set { } } + public string SemanticQuery { get { throw null; } set { } } public string SessionId { get { throw null; } set { } } public int? Size { get { throw null; } set { } } public int? Skip { get { throw null; } set { } } - public System.Collections.Generic.IList Vectors { get { throw null; } } + public Azure.Search.Documents.Models.VectorFilterMode? VectorFilterMode { get { throw null; } set { } } + public System.Collections.Generic.IList VectorQueries { get { throw null; } } } public partial class SuggestOptions { @@ -210,8 +212,8 @@ public SearchableFieldAttribute() { } public string IndexAnalyzerName { get { throw null; } set { } } public string SearchAnalyzerName { get { throw null; } set { } } public string[] SynonymMapNames { get { throw null; } set { } } - public string VectorSearchConfiguration { get { throw null; } set { } } public string VectorSearchDimensions { get { throw null; } set { } } + public string VectorSearchProfile { get { throw null; } set { } } } public partial class SearchIndexClient { @@ -401,6 +403,27 @@ public AzureMachineLearningSkill(System.Collections.Generic.IEnumerable inputs, System.Collections.Generic.IEnumerable outputs) { } + public string ApiKey { get { throw null; } set { } } + public Azure.Search.Documents.Indexes.Models.SearchIndexerDataIdentity AuthIdentity { get { throw null; } set { } } + public string DeploymentId { get { throw null; } set { } } + public System.Uri ResourceUri { get { throw null; } set { } } + } + public partial class AzureOpenAIParameters + { + public AzureOpenAIParameters() { } + public string ApiKey { get { throw null; } set { } } + public Azure.Search.Documents.Indexes.Models.SearchIndexerDataIdentity AuthIdentity { get { throw null; } set { } } + public string DeploymentId { get { throw null; } set { } } + public System.Uri ResourceUri { get { throw null; } set { } } + } + public partial class AzureOpenAIVectorizer : Azure.Search.Documents.Indexes.Models.VectorSearchVectorizer + { + public AzureOpenAIVectorizer(string name) : base (default(string)) { } + public Azure.Search.Documents.Indexes.Models.AzureOpenAIParameters AzureOpenAIParameters { get { throw null; } set { } } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct BlobIndexerDataToExtract : System.IEquatable { @@ -633,6 +656,21 @@ public CustomNormalizer(string name) : base (default(string)) { } public System.Collections.Generic.IList CharFilters { get { throw null; } } public System.Collections.Generic.IList TokenFilters { get { throw null; } } } + public partial class CustomVectorizer : Azure.Search.Documents.Indexes.Models.VectorSearchVectorizer + { + public CustomVectorizer(string name) : base (default(string)) { } + public Azure.Search.Documents.Indexes.Models.CustomVectorizerParameters CustomVectorizerParameters { get { throw null; } set { } } + } + public partial class CustomVectorizerParameters + { + public CustomVectorizerParameters() { } + public Azure.Search.Documents.Indexes.Models.SearchIndexerDataIdentity AuthIdentity { get { throw null; } set { } } + public string AuthResourceId { get { throw null; } set { } } + public System.Collections.Generic.IDictionary HttpHeaders { get { throw null; } } + public string HttpMethod { get { throw null; } set { } } + public System.TimeSpan? Timeout { get { throw null; } set { } } + public System.Uri Uri { get { throw null; } set { } } + } public partial class DataChangeDetectionPolicy { internal DataChangeDetectionPolicy() { } @@ -796,6 +834,16 @@ public EntityRecognitionSkill(System.Collections.Generic.IEnumerable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public IndexProjectionMode(string value) { throw null; } + public static Azure.Search.Documents.Indexes.Models.IndexProjectionMode IncludeIndexingParentDocuments { get { throw null; } } + public static Azure.Search.Documents.Indexes.Models.IndexProjectionMode SkipIndexingParentDocuments { get { throw null; } } + public bool Equals(Azure.Search.Documents.Indexes.Models.IndexProjectionMode other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Search.Documents.Indexes.Models.IndexProjectionMode left, Azure.Search.Documents.Indexes.Models.IndexProjectionMode right) { throw null; } + public static implicit operator Azure.Search.Documents.Indexes.Models.IndexProjectionMode (string value) { throw null; } + public static bool operator !=(Azure.Search.Documents.Indexes.Models.IndexProjectionMode left, Azure.Search.Documents.Indexes.Models.IndexProjectionMode right) { throw null; } + public override string ToString() { throw null; } + } public partial class InputFieldMappingEntry { public InputFieldMappingEntry(string name) { } @@ -1148,6 +1214,7 @@ public partial class KnowledgeStore { public KnowledgeStore(string storageConnectionString, System.Collections.Generic.IEnumerable projections) { } public Azure.Search.Documents.Indexes.Models.SearchIndexerDataIdentity Identity { get { throw null; } set { } } + public Azure.Search.Documents.Indexes.Models.SearchIndexerKnowledgeStoreParameters Parameters { get { throw null; } set { } } public System.Collections.Generic.IList Projections { get { throw null; } } public string StorageConnectionString { get { throw null; } set { } } } @@ -1641,6 +1708,10 @@ public enum MicrosoftTokenizerLanguage Urdu = 40, Vietnamese = 41, } + public partial class NativeBlobSoftDeleteDeletionDetectionPolicy : Azure.Search.Documents.Indexes.Models.DataDeletionDetectionPolicy + { + public NativeBlobSoftDeleteDeletionDetectionPolicy() { } + } public partial class NGramTokenFilter : Azure.Search.Documents.Indexes.Models.TokenFilter { public NGramTokenFilter(string name) { } @@ -2038,8 +2109,8 @@ public SearchField(string name, Azure.Search.Documents.Indexes.Models.SearchFiel public Azure.Search.Documents.Indexes.Models.LexicalAnalyzerName? SearchAnalyzerName { get { throw null; } set { } } public System.Collections.Generic.IList SynonymMapNames { get { throw null; } } public Azure.Search.Documents.Indexes.Models.SearchFieldDataType Type { get { throw null; } } - public string VectorSearchConfiguration { get { throw null; } set { } } public int? VectorSearchDimensions { get { throw null; } set { } } + public string VectorSearchProfile { get { throw null; } set { } } public override string ToString() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] @@ -2186,6 +2257,32 @@ internal SearchIndexerError() { } public string Name { get { throw null; } } public int StatusCode { get { throw null; } } } + public partial class SearchIndexerIndexProjections + { + public SearchIndexerIndexProjections(System.Collections.Generic.IEnumerable selectors) { } + public Azure.Search.Documents.Indexes.Models.SearchIndexerIndexProjectionsParameters Parameters { get { throw null; } set { } } + public System.Collections.Generic.IList Selectors { get { throw null; } } + } + public partial class SearchIndexerIndexProjectionSelector + { + public SearchIndexerIndexProjectionSelector(string targetIndexName, string parentKeyFieldName, string sourceContext, System.Collections.Generic.IEnumerable mappings) { } + public System.Collections.Generic.IList Mappings { get { throw null; } } + public string ParentKeyFieldName { get { throw null; } set { } } + public string SourceContext { get { throw null; } set { } } + public string TargetIndexName { get { throw null; } set { } } + } + public partial class SearchIndexerIndexProjectionsParameters + { + public SearchIndexerIndexProjectionsParameters() { } + public System.Collections.Generic.IDictionary AdditionalProperties { get { throw null; } } + public Azure.Search.Documents.Indexes.Models.IndexProjectionMode? ProjectionMode { get { throw null; } set { } } + } + public partial class SearchIndexerKnowledgeStoreParameters + { + public SearchIndexerKnowledgeStoreParameters() { } + public System.Collections.Generic.IDictionary AdditionalProperties { get { throw null; } } + public bool? SynthesizeGeneratedKeyName { get { throw null; } set { } } + } public partial class SearchIndexerLimits { internal SearchIndexerLimits() { } @@ -2209,6 +2306,7 @@ public SearchIndexerSkillset(string name, System.Collections.Generic.IEnumerable public string Description { get { throw null; } set { } } public Azure.Search.Documents.Indexes.Models.SearchResourceEncryptionKey EncryptionKey { get { throw null; } set { } } public Azure.ETag? ETag { get { throw null; } set { } } + public Azure.Search.Documents.Indexes.Models.SearchIndexerIndexProjections IndexProjections { get { throw null; } set { } } public Azure.Search.Documents.Indexes.Models.KnowledgeStore KnowledgeStore { get { throw null; } set { } } public string Name { get { throw null; } set { } } public System.Collections.Generic.IList Skills { get { throw null; } } @@ -2235,7 +2333,7 @@ public partial class SearchIndexStatistics internal SearchIndexStatistics() { } public long DocumentCount { get { throw null; } } public long StorageSize { get { throw null; } } - public long? VectorIndexSize { get { throw null; } } + public long VectorIndexSize { get { throw null; } } } public partial class SearchResourceCounter { @@ -2433,6 +2531,8 @@ public partial class SplitSkill : Azure.Search.Documents.Indexes.Models.SearchIn public SplitSkill(System.Collections.Generic.IEnumerable inputs, System.Collections.Generic.IEnumerable outputs) { } public Azure.Search.Documents.Indexes.Models.SplitSkillLanguage? DefaultLanguageCode { get { throw null; } set { } } public int? MaximumPageLength { get { throw null; } set { } } + public int? MaximumPagesToTake { get { throw null; } set { } } + public int? PageOverlapLength { get { throw null; } set { } } public Azure.Search.Documents.Indexes.Models.TextSplitMode? TextSplitMode { get { throw null; } set { } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] @@ -2803,7 +2903,9 @@ public UniqueTokenFilter(string name) { } public partial class VectorSearch { public VectorSearch() { } - public System.Collections.Generic.IList AlgorithmConfigurations { get { throw null; } } + public System.Collections.Generic.IList Algorithms { get { throw null; } } + public System.Collections.Generic.IList Profiles { get { throw null; } } + public System.Collections.Generic.IList Vectorizers { get { throw null; } } } public abstract partial class VectorSearchAlgorithmConfiguration { @@ -2811,6 +2913,24 @@ protected VectorSearchAlgorithmConfiguration(string name) { } public string Name { get { throw null; } set { } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct VectorSearchAlgorithmKind : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public VectorSearchAlgorithmKind(string value) { throw null; } + public static Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind ExhaustiveKnn { get { throw null; } } + public static Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind Hnsw { get { throw null; } } + public bool Equals(Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind left, Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind right) { throw null; } + public static implicit operator Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind (string value) { throw null; } + public static bool operator !=(Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind left, Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmKind right) { throw null; } + public override string ToString() { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct VectorSearchAlgorithmMetric : System.IEquatable { private readonly object _dummy; @@ -2829,6 +2949,36 @@ protected VectorSearchAlgorithmConfiguration(string name) { } public static bool operator !=(Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmMetric left, Azure.Search.Documents.Indexes.Models.VectorSearchAlgorithmMetric right) { throw null; } public override string ToString() { throw null; } } + public partial class VectorSearchProfile + { + public VectorSearchProfile(string name, string algorithm) { } + public string Algorithm { get { throw null; } set { } } + public string Name { get { throw null; } set { } } + public string Vectorizer { get { throw null; } set { } } + } + public abstract partial class VectorSearchVectorizer + { + protected VectorSearchVectorizer(string name) { } + public string Name { get { throw null; } set { } } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct VectorSearchVectorizerKind : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public VectorSearchVectorizerKind(string value) { throw null; } + public static Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind AzureOpenAI { get { throw null; } } + public static Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind CustomWebApi { get { throw null; } } + public bool Equals(Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind left, Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind right) { throw null; } + public static implicit operator Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind (string value) { throw null; } + public static bool operator !=(Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind left, Azure.Search.Documents.Indexes.Models.VectorSearchVectorizerKind right) { throw null; } + public override string ToString() { throw null; } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct VisualFeature : System.IEquatable { @@ -3189,6 +3339,11 @@ public RangeFacetResult(long count, T? from, T? to) { } public T? From { get { throw null; } } public T? To { get { throw null; } } } + public partial class RawVectorQuery : Azure.Search.Documents.Models.VectorQuery + { + public RawVectorQuery() { } + public System.Collections.Generic.IReadOnlyList Vector { get { throw null; } set { } } + } public partial class ResetDocumentOptions { public ResetDocumentOptions() { } @@ -3282,8 +3437,9 @@ public static partial class SearchModelFactory [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static Azure.Search.Documents.Indexes.Models.SearchIndexerStatus SearchIndexerStatus(Azure.Search.Documents.Indexes.Models.IndexerStatus status, Azure.Search.Documents.Indexes.Models.IndexerExecutionResult lastResult, System.Collections.Generic.IReadOnlyList executionHistory, Azure.Search.Documents.Indexes.Models.SearchIndexerLimits limits) { throw null; } public static Azure.Search.Documents.Indexes.Models.SearchIndexerWarning SearchIndexerWarning(string key, string message, string name, string details, string documentationLink) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public static Azure.Search.Documents.Indexes.Models.SearchIndexStatistics SearchIndexStatistics(long documentCount, long storageSize) { throw null; } - public static Azure.Search.Documents.Indexes.Models.SearchIndexStatistics SearchIndexStatistics(long documentCount = (long)0, long storageSize = (long)0, long? vectorIndexSize = default(long?)) { throw null; } + public static Azure.Search.Documents.Indexes.Models.SearchIndexStatistics SearchIndexStatistics(long documentCount = (long)0, long storageSize = (long)0, long vectorIndexSize = (long)0) { throw null; } public static Azure.Search.Documents.Indexes.Models.SearchResourceCounter SearchResourceCounter(long usage, long? quota) { throw null; } public static Azure.Search.Documents.Models.SearchResultsPage SearchResultsPage(Azure.Search.Documents.Models.SearchResults results) { throw null; } public static Azure.Search.Documents.Models.SearchResults SearchResults(System.Collections.Generic.IEnumerable> values, long? totalCount, System.Collections.Generic.IDictionary> facets, double? coverage, Azure.Response rawResponse) { throw null; } @@ -3309,13 +3465,6 @@ public enum SearchQueryType Full = 1, Semantic = 2, } - public partial class SearchQueryVector - { - public SearchQueryVector() { } - public System.Collections.Generic.IList Fields { get { throw null; } } - public int? KNearestNeighborsCount { get { throw null; } set { } } - public System.Collections.Generic.IReadOnlyList Value { get { throw null; } set { } } - } public partial class SearchResultsPage : Azure.Page> { internal SearchResultsPage() { } @@ -3451,6 +3600,54 @@ public ValueFacetResult(long count, T value) { } public long Count { get { throw null; } } public T Value { get { throw null; } } } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct VectorFilterMode : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public VectorFilterMode(string value) { throw null; } + public static Azure.Search.Documents.Models.VectorFilterMode PostFilter { get { throw null; } } + public static Azure.Search.Documents.Models.VectorFilterMode PreFilter { get { throw null; } } + public bool Equals(Azure.Search.Documents.Models.VectorFilterMode other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Search.Documents.Models.VectorFilterMode left, Azure.Search.Documents.Models.VectorFilterMode right) { throw null; } + public static implicit operator Azure.Search.Documents.Models.VectorFilterMode (string value) { throw null; } + public static bool operator !=(Azure.Search.Documents.Models.VectorFilterMode left, Azure.Search.Documents.Models.VectorFilterMode right) { throw null; } + public override string ToString() { throw null; } + } + public partial class VectorizableTextQuery : Azure.Search.Documents.Models.VectorQuery + { + public VectorizableTextQuery() { } + public string Text { get { throw null; } set { } } + } + public abstract partial class VectorQuery + { + protected VectorQuery() { } + public bool? Exhaustive { get { throw null; } set { } } + public System.Collections.Generic.IList Fields { get { throw null; } } + public int? KNearestNeighborsCount { get { throw null; } set { } } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct VectorQueryKind : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public VectorQueryKind(string value) { throw null; } + public static Azure.Search.Documents.Models.VectorQueryKind Text { get { throw null; } } + public static Azure.Search.Documents.Models.VectorQueryKind Vector { get { throw null; } } + public bool Equals(Azure.Search.Documents.Models.VectorQueryKind other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Search.Documents.Models.VectorQueryKind left, Azure.Search.Documents.Models.VectorQueryKind right) { throw null; } + public static implicit operator Azure.Search.Documents.Models.VectorQueryKind (string value) { throw null; } + public static bool operator !=(Azure.Search.Documents.Models.VectorQueryKind left, Azure.Search.Documents.Models.VectorQueryKind right) { throw null; } + public override string ToString() { throw null; } + } } namespace Microsoft.Extensions.Azure { diff --git a/sdk/search/Azure.Search.Documents/assets.json b/sdk/search/Azure.Search.Documents/assets.json index 11be40fa860bf..57becb523891c 100644 --- a/sdk/search/Azure.Search.Documents/assets.json +++ b/sdk/search/Azure.Search.Documents/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/search/Azure.Search.Documents", - "Tag": "net/search/Azure.Search.Documents_38f84358e8" + "Tag": "net/search/Azure.Search.Documents_53888408bf" } diff --git a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch.md b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch.md index 7b1aaeb58b1a3..a272b3a40ec5b 100644 --- a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch.md +++ b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch.md @@ -6,347 +6,19 @@ Cognitive Search doesn't host vectorization models. This presents a challenge in Please refer the [documentation](https://learn.microsoft.com/azure/search/vector-search-overview) to learn more about Vector Search. -This sample will show you how to index a vector field and perform vector search using .NET SDK. - -## Create a Vector Index - -Let's consider the example of a `Hotel`. First, we need to create an index for storing hotel information. In this index, we will define vector fields called `DescriptionVector` and `CategoryVector`. To configure the vector field, you need to provide the model dimensions, which indicate the size of the embeddings generated for this field, and the name of the vector search algorithm configuration that specifies the algorithm and any optional parameters for searching the vector field. You can find detailed instructions on how to create a vector index in the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-create-index). - -We will create an instace of `SearchIndex` and define `Hotel` fields. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index -string vectorSearchConfigName = "my-vector-config"; -int modelDimensions = 1536; - -string indexName = "Hotel"; -SearchIndex searchIndex = new(indexName) -{ - Fields = - { - new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, - new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, - new SearchableField("Description") { IsFilterable = true }, - new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) - { - IsSearchable = true, - VectorSearchDimensions = modelDimensions, - VectorSearchConfiguration = vectorSearchConfigName - }, - new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, - new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) - { - IsSearchable = true, - VectorSearchDimensions = modelDimensions, - VectorSearchConfiguration = vectorSearchConfigName - }, - }, - VectorSearch = new() - { - AlgorithmConfigurations = - { - new HnswVectorSearchAlgorithmConfiguration(vectorSearchConfigName) - } - } -}; -``` - -After creating an instance of the `SearchIndex`, we need to instantiate the `SearchIndexClient` and call the `CreateIndex` method to create the search index. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index -Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); -string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); -AzureKeyCredential credential = new(key); - -SearchIndexClient indexClient = new(endpoint, credential); -await indexClient.CreateIndexAsync(searchIndex); -``` - -## Add documents to your index - -Let's create a simple model type for `Hotel`: - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model -public class Hotel -{ - public string HotelId { get; set; } - public string HotelName { get; set; } - public string Description { get; set; } - public IReadOnlyList DescriptionVector { get; set; } - public string Category { get; set; } - public IReadOnlyList CategoryVector { get; set; } -} -``` - -Next, we will create sample hotel documents. The vector field requires submitting text input to an embedding model that converts human-readable text into a vector representation. To convert a text query string provided by a user into a vector representation, your application should utilize an embedding library that offers this functionality. For more details about how to generate embeddings, refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). Here's an example of how you can get embeddings using [Azure.AI.OpenAI](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/README.md) library. - -#### Get Embeddings using `Azure.AI.OpenAI` - -```C# Snippet:Azure_Search_Tests_Samples_Readme_GetEmbeddings -Uri endpoint = new Uri(Environment.GetEnvironmentVariable("OpenAI_ENDPOINT")); -string key = Environment.GetEnvironmentVariable("OpenAI_API_KEY"); -AzureKeyCredential credential = new AzureKeyCredential(key); - -OpenAIClient openAIClient = new OpenAIClient(endpoint, credential); -string description = "Very popular hotel in town."; -EmbeddingsOptions embeddingsOptions = new(description); - -Embeddings embeddings = await openAIClient.GetEmbeddingsAsync("EmbeddingsModelName", embeddingsOptions); -IReadOnlyList descriptionVector = embeddings.Data[0].Embedding; -``` - -In the sample code below, we are using hardcoded embeddings for the vector fields named `DescriptionVector` and `CategoryVector`: - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document -public static Hotel[] GetHotelDocuments() -{ - return new[] - { - new Hotel() - { - HotelId = "1", - HotelName = "Fancy Stay", - Description = - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + - "and a really helpful concierge. The location is perfect -- right downtown, close to all " + - "the tourist attractions. We highly recommend this hotel.", - DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, - Category = "Luxury", - CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory - }, - new Hotel() - { - HotelId = "2", - HotelName = "Roach Motel", - Description = "Cheapest hotel in town. Infact, a motel.", - DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, - Category = "Budget", - CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory - }, - // Add more hotel documents here... - }; -} -``` - -Now, we can instantiate the `SearchClient` and upload the documents to the `Hotel` index we created earlier: - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents -SearchClient searchClient = new(endpoint, indexName, credential); -Hotel[] hotelDocuments = GetHotelDocuments(); -await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); -``` - -## Query Vector Data - -To query a vector field, the query itself must be a vector. To convert a text query string provided by a user into a vector representation, your application must call an embedding library that provides this capability. Use the same embedding library that you used to generate embeddings in the source documents. For more details on how to generate embeddings, please refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). In the sample codes below, we are using hardcoded embeddings to query vector field. - -Let's query the index and make sure everything works as implemented. You can also refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-query) for more information on querying vector data. - -### Single Vector Search - -In this vector query, the `Value` contains the vectorized text of the query input. The `Fields` property specifies which vector fields are searched. The "KNearestNeighborsCount" property specifies the number of nearest neighbors to return as top hits. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search -IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" - -SearchResults response = await searchClient.SearchAsync(null, - new SearchOptions - { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, - }); - -int count = 0; -Console.WriteLine($"Single Vector Search Results:"); -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); -} -Console.WriteLine($"Total number of search results:{count}"); -``` - -### Single Vector Search With Filter - -In addition to the vector query mentioned above, we can also apply a filter to narrow down the search results. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter -IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" - -SearchResults response = await searchClient.SearchAsync(null, - new SearchOptions - { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, - Filter = "Category eq 'Luxury'" - }); - -int count = 0; -Console.WriteLine($"Single Vector Search With Filter Results:"); -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); -} -Console.WriteLine($"Total number of search results:{count}"); -``` - -### Hybrid Search - -A hybrid query combines full text search, semantic search (reranking), and vector search. The search engine runs full text and vector queries in parallel. Semantic ranking is applied to the results from the text search. A single result set is returned in the response. - -#### Simple Hybrid Search - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search -IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" - -SearchResults response = await searchClient.SearchAsync( - "Top hotels in town", - new SearchOptions - { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, - }); - -int count = 0; -Console.WriteLine($"Simple Hybrid Search Results:"); -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); -} -Console.WriteLine($"Total number of search results:{count}"); -``` - -#### Semantic Hybrid Search - -To use semantic search, we need to add a `SemanticConfiguration` to the index. In this example, we will update the previously created index and add the `SemanticConfiguration` to it. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Semantic_Index -string indexName = "Hotel"; -SearchIndex createdIndex = await indexClient.GetIndexAsync(indexName); - -createdIndex.SemanticSettings = new() -{ - Configurations = - { - new SemanticConfiguration("my-semantic-config", new() - { - TitleField = new(){ FieldName = "HotelName" }, - ContentFields = - { - new() { FieldName = "Description" } - }, - KeywordFields = - { - new() { FieldName = "Category" } - } - }) - } -}; - -// Update index -await indexClient.CreateOrUpdateIndexAsync(createdIndex); -``` -With the semantic configuration added, we can now execute a semantic hybrid query. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Semantic_Hybrid_Search -IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" - -SearchResults response = await searchClient.SearchAsync( - "Is there any hotel located on the main commercial artery of the city in the heart of New York?", - new SearchOptions - { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, - QueryType = SearchQueryType.Semantic, - QueryLanguage = QueryLanguage.EnUs, - SemanticConfigurationName = "my-semantic-config", - QueryCaption = QueryCaptionType.Extractive, - QueryAnswer = QueryAnswerType.Extractive, - }); - -int count = 0; -Console.WriteLine($"Semantic Hybrid Search Results:"); - -Console.WriteLine($"\nQuery Answer:"); -foreach (AnswerResult result in response.Answers) -{ - Console.WriteLine($"Answer Highlights: {result.Highlights}"); - Console.WriteLine($"Answer Text: {result.Text}"); -} - -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); - - if (result.Captions != null) - { - var caption = result.Captions.FirstOrDefault(); - if (caption.Highlights != null && caption.Highlights != "") - { - Console.WriteLine($"Caption Highlights: {caption.Highlights}"); - } - else - { - Console.WriteLine($"Caption Text: {caption.Text}"); - } - } -} -Console.WriteLine($"Total number of search results:{count}"); -``` - -### Multi-vector Search - -You can search containing multiple query vectors using the `SearchOptions.Vectors` property. These queries will be executed concurrently in the search index, with each one searching for similarities in the target vector fields. The result set will be a combination of documents that matched both vector queries. One common use case for this query request is when using models like CLIP for a multi-modal vector search, where the same model can vectorize both image and non-image content. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search -IReadOnlyList vectorizedDescriptionQuery = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" -IReadOnlyList vectorizedCategoryQuery = VectorSearchEmbeddings.SearchVectorizeCategory; // "Luxury hotels in town" - -SearchResults response = await searchClient.SearchAsync(null, - new SearchOptions - { - Vectors = { - new() { Value = vectorizedDescriptionQuery, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } }, - new() { Value = vectorizedCategoryQuery, KNearestNeighborsCount = 3, Fields = { "CategoryVector" } } - }, - }); - -int count = 0; -Console.WriteLine($"Multi Vector Search Results:"); -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); -} -Console.WriteLine($"Total number of search results:{count}"); -``` - -### Multi-field Vector Search - -You can set the `SearchOptions.Vectors.Fields` property to multiple vector fields. For example, we have vector fields named `DescriptionVector` and `CategoryVector`. Your vector query executes over both the `DescriptionVector` and `CategoryVector` fields, which must have the same embedding space since they share the same query vector. - -```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search -IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" - -SearchResults response = await searchClient.SearchAsync(null, - new SearchOptions - { - Vectors = { new() { - Value = vectorizedResult, - KNearestNeighborsCount = 3, - Fields = { "DescriptionVector", "CategoryVector" } } } - }); - -int count = 0; -Console.WriteLine($"Multi Fields Vector Search Results:"); -await foreach (SearchResult result in response.GetResultsAsync()) -{ - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); -} -Console.WriteLine($"Total number of search results:{count}"); -``` +Here's the list of samples that will show you how to index the vector fields and perform vector search using .NET SDK. + +* [Vector Search Using RAW Vector Query](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#vector-search-using-raw-vector-query) + * [Single Vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#single-vector-search) + * [Single Vector Search With Filter](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#single-vector-search-with-filter) + * [Hybrid Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#hybrid-search) + * [Multi-vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#multi-vector-search) + * [Multi-field Vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md#multi-field-vector-search) +* [Vector Search Using Vectorizable Text Query](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#vector-search-using-vectorizable-text-query) + * [Single Vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#single-vector-search) + * [Single Vector Search With Filter](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#single-vector-search-with-filter) + * [Hybrid Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#hybrid-search) + * [Multi-vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#multi-vector-search) + * [Multi-field Vector Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md#multi-field-vector-search) +* [Vector Semantic Hybrid Search](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingSemanticHybridQuery.md) +* [Vector Search Using Field Builder](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingFieldBuilder.md) diff --git a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingFieldBuilder.md b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingFieldBuilder.md new file mode 100644 index 0000000000000..b06aa2fe5788a --- /dev/null +++ b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingFieldBuilder.md @@ -0,0 +1,64 @@ +# Vector Search Using Field Builder + +The `FieldBuilder` class allows you to define a Search index from a model type. This sample demonstrates how to create a vector fields index using the field builder. + +## Model Creation + +Consider the following model, which includes a property named `DescriptionVector` that represents a vector field. To configure a vector field, you must provide the model dimensions, indicating the size of the embeddings generated for this field, as well as the name of the vector search profile that specifies the algorithm configuration and any optional parameters for searching the vector field. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_FieldBuilder_Model +public class MyDocument +{ + [SimpleField(IsKey = true, IsFilterable = true, IsSortable = true)] + public string Id { get; set; } + + [SearchableField(IsFilterable = true, IsSortable = true)] + public string Name { get; set; } + + [SearchableField(AnalyzerName = "en.microsoft")] + public string Description { get; set; } + + [SearchableField(VectorSearchDimensions = "1536", VectorSearchProfile = "my-vector-profile")] + public IReadOnlyList DescriptionVector { get; set; } +} +``` + +## Create an Index using `FieldBuilder` + +We will create an instace of `SearchIndex` and use `FieldBuilder` to define fields based on the `MyDocument` model class. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingFieldBuilder +string vectorSearchProfile = "my-vector-profile"; +string vectorSearchHnswConfig = "my-hsnw-vector-config"; + +string indexName = "MyDocument"; +// Create Index +SearchIndex searchIndex = new SearchIndex(indexName) +{ + Fields = new FieldBuilder().Build(typeof(MyDocument)), + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + } + }, +}; +``` + +After creating an instance of the `SearchIndex`, we need to instantiate the `SearchIndexClient` and call the `CreateIndex` method to create the search index. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_FieldBuilder +Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); +AzureKeyCredential credential = new(key); + +SearchIndexClient indexClient = new(endpoint, credential); +await indexClient.CreateIndexAsync(searchIndex); +``` + +To perform vector search please refer to the [Vector Search Using RAW Vector Query](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md) or [Vector Search Using Vectorizable Text Query](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md) samples. diff --git a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md new file mode 100644 index 0000000000000..ae806d897333f --- /dev/null +++ b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingRawVectorQuery.md @@ -0,0 +1,272 @@ +# Vector Search Using RAW Vector Query + +This sample demonstrates how to create a vector fields index, upload data into the index, and perform various types of vector searches using raw vector queries. + +## Create a Vector Index + +Let's consider the example of a `Hotel`. First, we need to create an index for storing hotel information. In this index, we will define vector fields called `DescriptionVector` and `CategoryVector`. To configure the vector field, you need to provide the model dimensions, which indicate the size of the embeddings generated for this field, and the name of the vector search profile that specifies the algorithm configuration and any optional parameters for searching the vector field. You can find detailed instructions on how to create a vector index in the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-create-index). + +We will create an instace of `SearchIndex` and define `Hotel` fields. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingRawVectors +string vectorSearchProfile = "my-vector-profile"; +string vectorSearchHnswConfig = "my-hsnw-vector-config"; +int modelDimensions = 1536; + +string indexName = "Hotel"; +SearchIndex searchIndex = new(indexName) +{ + Fields = + { + new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, + new SearchableField("Description") { IsFilterable = true }, + new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + }, + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + } + }, +}; +``` + +After creating an instance of the `SearchIndex`, we need to instantiate the `SearchIndexClient` and call the `CreateIndex` method to create the search index. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_UsingRawVectors +Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); +AzureKeyCredential credential = new(key); + +SearchIndexClient indexClient = new(endpoint, credential); +await indexClient.CreateIndexAsync(searchIndex); +``` + +## Add documents to your index + +Let's create a simple model type for `Hotel`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model +public class Hotel +{ + public string HotelId { get; set; } + public string HotelName { get; set; } + public string Description { get; set; } + public IReadOnlyList DescriptionVector { get; set; } + public string Category { get; set; } + public IReadOnlyList CategoryVector { get; set; } +} +``` + +Next, we will create sample hotel documents. The vector field requires submitting text input to an embedding model that converts human-readable text into a vector representation. To convert a text query string provided by a user into a vector representation, your application should utilize an embedding library that offers this functionality. For more details about how to generate embeddings, refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). Here's an example of how you can get embeddings using [Azure.AI.OpenAI](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/README.md) library. + +### Get Embeddings using `Azure.AI.OpenAI` + +```C# Snippet:Azure_Search_Tests_Samples_Readme_GetEmbeddings +Uri endpoint = new Uri(Environment.GetEnvironmentVariable("OpenAI_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("OpenAI_API_KEY"); +AzureKeyCredential credential = new AzureKeyCredential(key); + +OpenAIClient openAIClient = new OpenAIClient(endpoint, credential); +string description = "Very popular hotel in town."; +EmbeddingsOptions embeddingsOptions = new(description); + +Embeddings embeddings = await openAIClient.GetEmbeddingsAsync("EmbeddingsModelName", embeddingsOptions); +IReadOnlyList descriptionVector = embeddings.Data[0].Embedding; +``` + +In the sample code below, we are using hardcoded embeddings for the vector fields named `DescriptionVector` and `CategoryVector`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document +public static Hotel[] GetHotelDocuments() +{ + return new[] + { + new Hotel() + { + HotelId = "1", + HotelName = "Fancy Stay", + Description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + + "and a really helpful concierge. The location is perfect -- right downtown, close to all " + + "the tourist attractions. We highly recommend this hotel.", + DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, + Category = "Luxury", + CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory + }, + new Hotel() + { + HotelId = "2", + HotelName = "Roach Motel", + Description = "Cheapest hotel in town. Infact, a motel.", + DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, + Category = "Budget", + CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory + }, + // Add more hotel documents here... + }; +} +``` + +Now, we can instantiate the `SearchClient` and upload the documents to the `Hotel` index we created earlier: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents_UsingRawVectors +SearchClient searchClient = new(endpoint, indexName, credential); +Hotel[] hotelDocuments = GetHotelDocuments(); +await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); +``` + +## Query Vector Data + +When using `RawVectorQuery`, the query for a vector field must also be a vector. To convert a text query string provided by a user into a vector representation, your application must call an embedding library that provides this capability. Use the same embedding library that you used to generate embeddings in the source documents. For more details on how to generate embeddings, please refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). In the sample codes below, we are using hardcoded embeddings to query vector field. + +Let's query the index and make sure everything works as implemented. You can also refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-query) for more information on querying vector data. + +### Single Vector Search + +In this vector query, the `VectorQueries` collection contains the vectors representing the query input. The `Fields` property specifies which vector fields are searched. The `KNearestNeighborsCount` property specifies the number of nearest neighbors to return as top hits. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search_UsingRawVectors +IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" + +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + }); + +int count = 0; +Console.WriteLine($"Single Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Single Vector Search With Filter + +In addition to the vector query mentioned above, we can also apply a filter to narrow down the search results. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter_UsingRawVectors +IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" + +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + Filter = "Category eq 'Luxury'" + }); + +int count = 0; +Console.WriteLine($"Single Vector Search With Filter Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Hybrid Search + +A hybrid query combines full text search, semantic search (reranking), and vector search. The search engine runs full text and vector queries in parallel. Semantic ranking is applied to the results from the text search. A single result set is returned in the response. + +#### Simple Hybrid Search + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search_UsingRawVectors +IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" + +SearchResults response = await searchClient.SearchAsync( + "Top hotels in town", + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + }); + +int count = 0; +Console.WriteLine($"Simple Hybrid Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Multi-vector Search + +You can search containing multiple query vectors using the `SearchOptions.VectorQueries` property. These queries will be executed concurrently in the search index, with each one searching for similarities in the target vector fields. The result set will be a combination of documents that matched both vector queries. One common use case for this query request is when using models like CLIP for a multi-modal vector search, where the same model can vectorize both image and non-image content. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search_UsingRawVectors +IReadOnlyList vectorizedDescriptionQuery = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" +IReadOnlyList vectorizedCategoryQuery = VectorSearchEmbeddings.SearchVectorizeCategory; // "Luxury hotels in town" + +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { + new RawVectorQuery() { Vector = vectorizedDescriptionQuery, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } }, + new RawVectorQuery() { Vector = vectorizedCategoryQuery, KNearestNeighborsCount = 3, Fields = { "CategoryVector" } } + }, + }); + +int count = 0; +Console.WriteLine($"Multi Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Multi-field Vector Search + +You can set the `SearchOptions.VectorQueries.Fields` property to multiple vector fields. For example, we have vector fields named `DescriptionVector` and `CategoryVector`. Your vector query executes over both the `DescriptionVector` and `CategoryVector` fields, which must have the same embedding space since they share the same query vector. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search_UsingRawVectors +IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" + +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { + Vector = vectorizedResult, + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector", "CategoryVector" } } } + }); + +int count = 0; +Console.WriteLine($"Multi Fields Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` diff --git a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingSemanticHybridQuery.md b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingSemanticHybridQuery.md new file mode 100644 index 0000000000000..fe4a427345edd --- /dev/null +++ b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingSemanticHybridQuery.md @@ -0,0 +1,210 @@ +# Vector Semantic Hybrid Search + +This sample will show you how to perform vector semantic hybrid search. + +## Create a Vector Index + +Let's consider the example of a `Hotel`. First, we need to create an index for storing hotel information. In this index, we will define vector fields called `DescriptionVector` and `CategoryVector`. To configure these vector fields, you need to specify the model dimensions, indicating the size of the embeddings generated for each field and the name of the vector search profile, which specifies the algorithm configuration and any optional search parameters for these vector fields. In addition to that, you also need to configure semantic settings for the index. You can find detailed instructions on how to create a vector index in the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-create-index). + +We will create an instace of `SearchIndex` and define `Hotel` fields. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Index +string vectorSearchProfile = "my-vector-profile"; +string vectorSearchHnswConfig = "my-hsnw-vector-config"; +int modelDimensions = 1536; + +string indexName = "Hotel"; +SearchIndex searchIndex = new(indexName) +{ + Fields = + { + new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, + new SearchableField("Description") { IsFilterable = true }, + new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + }, + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + } + }, + SemanticSettings = new() + { + Configurations = + { + new SemanticConfiguration("my-semantic-config", new() + { + TitleField = new(){ FieldName = "HotelName" }, + ContentFields = + { + new() { FieldName = "Description" } + }, + KeywordFields = + { + new() { FieldName = "Category" } + } + }) + } + } +}; +``` + +After creating an instance of the `SearchIndex`, we need to instantiate the `SearchIndexClient` and call the `CreateIndex` method to create the search index. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Create_Index +Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); +AzureKeyCredential credential = new(key); + +SearchIndexClient indexClient = new(endpoint, credential); +await indexClient.CreateIndexAsync(searchIndex); +``` + +## Add documents to your index + +Let's create a simple model type for `Hotel`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model +public class Hotel +{ + public string HotelId { get; set; } + public string HotelName { get; set; } + public string Description { get; set; } + public IReadOnlyList DescriptionVector { get; set; } + public string Category { get; set; } + public IReadOnlyList CategoryVector { get; set; } +} +``` + +Next, we will create sample hotel documents. The vector field requires submitting text input to an embedding model that converts human-readable text into a vector representation. To convert a text query string provided by a user into a vector representation, your application should utilize an embedding library that offers this functionality. For more details about how to generate embeddings, refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). Here's an example of how you can get embeddings using [Azure.AI.OpenAI](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/README.md) library. + +### Get Embeddings using `Azure.AI.OpenAI` + +```C# Snippet:Azure_Search_Tests_Samples_Readme_GetEmbeddings +Uri endpoint = new Uri(Environment.GetEnvironmentVariable("OpenAI_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("OpenAI_API_KEY"); +AzureKeyCredential credential = new AzureKeyCredential(key); + +OpenAIClient openAIClient = new OpenAIClient(endpoint, credential); +string description = "Very popular hotel in town."; +EmbeddingsOptions embeddingsOptions = new(description); + +Embeddings embeddings = await openAIClient.GetEmbeddingsAsync("EmbeddingsModelName", embeddingsOptions); +IReadOnlyList descriptionVector = embeddings.Data[0].Embedding; +``` + +In the sample code below, we are using hardcoded embeddings for the vector fields named `DescriptionVector` and `CategoryVector`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document +public static Hotel[] GetHotelDocuments() +{ + return new[] + { + new Hotel() + { + HotelId = "1", + HotelName = "Fancy Stay", + Description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + + "and a really helpful concierge. The location is perfect -- right downtown, close to all " + + "the tourist attractions. We highly recommend this hotel.", + DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, + Category = "Luxury", + CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory + }, + new Hotel() + { + HotelId = "2", + HotelName = "Roach Motel", + Description = "Cheapest hotel in town. Infact, a motel.", + DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, + Category = "Budget", + CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory + }, + // Add more hotel documents here... + }; +} +``` + +Now, we can instantiate the `SearchClient` and upload the documents to the `Hotel` index we created earlier: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Upload_Documents +SearchClient searchClient = new(endpoint, indexName, credential); +Hotel[] hotelDocuments = GetHotelDocuments(); +await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); +``` + +## Query Vector Data + +When using `RawVectorQuery`, the query for a vector field must also be a vector. To convert a text query string provided by a user into a vector representation, your application must call an embedding library that provides this capability. Use the same embedding library that you used to generate embeddings in the source documents. For more details on how to generate embeddings, please refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). In the sample codes below, we are using hardcoded embeddings to query vector field. + +Let's query the index and make sure everything works as implemented. You can also refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-query?tabs=portal-vector-query#query-syntax-for-hybrid-search) for more information on querying vector data. + +### Vector Semantic Hybrid Query + +In a vector semantic hybrid query, the `VectorQueries` collection contains the vectors representing the query input. The `Fields` property specifies which vector fields to search within. The `KNearestNeighborsCount` property dictates the number of nearest neighbors to return as top hits. With the semantic configuration added, we can proceed to execute a semantic hybrid query. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search +IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" + +SearchResults response = await searchClient.SearchAsync( + "Is there any hotel located on the main commercial artery of the city in the heart of New York?", + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + QueryType = SearchQueryType.Semantic, + QueryLanguage = QueryLanguage.EnUs, + SemanticConfigurationName = "my-semantic-config", + QueryCaption = QueryCaptionType.Extractive, + QueryAnswer = QueryAnswerType.Extractive, + }); + +int count = 0; +Console.WriteLine($"Semantic Hybrid Search Results:"); + +Console.WriteLine($"\nQuery Answer:"); +foreach (AnswerResult result in response.Answers) +{ + Console.WriteLine($"Answer Highlights: {result.Highlights}"); + Console.WriteLine($"Answer Text: {result.Text}"); +} + +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + + if (result.Captions != null) + { + var caption = result.Captions.FirstOrDefault(); + if (caption.Highlights != null && caption.Highlights != "") + { + Console.WriteLine($"Caption Highlights: {caption.Highlights}"); + } + else + { + Console.WriteLine($"Caption Text: {caption.Text}"); + } + } +} +Console.WriteLine($"Total number of search results:{count}"); +``` diff --git a/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md new file mode 100644 index 0000000000000..cb6fea295d425 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/samples/Sample07_VectorSearch_UsingVectorizableTextQuery.md @@ -0,0 +1,290 @@ +# Vector Search Using Vectorizable Text Query + +This sample demonstrates how to create a vector fields index, upload data into the index, and perform various types of vector searches using vectorizable text queries. + +## Create a Vector Index + +Let's consider the example of a `Hotel`. First, we need to create an index for storing hotel information. In this index, we will define vector fields called `DescriptionVector` and `CategoryVector`. To configure the vector field, you need to provide the model dimensions, which indicate the size of the embeddings generated for this field, and the name of the vector search profile that specifies the algorithm configuration and `Vectorizer` which contains configuration options on how to vectorize text vector queries. You can find detailed instructions on how to create a vector index in the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-create-index). + +We will create an instace of `SearchIndex` and define `Hotel` fields. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingTextVectors +string vectorSearchProfile = "my-vector-profile"; +string vectorSearchHnswConfig = "my-hsnw-vector-config"; +string modelName = "text-embedding-ada-002"; +int modelDimensions = 1536; + +string indexName = "Hotel"; +SearchIndex searchIndex = new(indexName) +{ + Fields = + { + new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, + new SearchableField("Description") { IsFilterable = true }, + new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + }, + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + { + Vectorizer = "openai" + } + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + }, + Vectorizers = + { + new AzureOpenAIVectorizer("openai") + { + AzureOpenAIParameters = new AzureOpenAIParameters() + { + ResourceUri = new Uri(Environment.GetEnvironmentVariable("OPENAI_ENDPOINT")), + ApiKey = Environment.GetEnvironmentVariable("OPENAI_KEY"), + DeploymentId = modelName, + } + } + } + }, +}; +``` + +After creating an instance of the `SearchIndex`, we need to instantiate the `SearchIndexClient` and call the `CreateIndex` method to create the search index. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_UsingTextVectors +Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); +AzureKeyCredential credential = new(key); + +SearchIndexClient indexClient = new(endpoint, credential); +await indexClient.CreateIndexAsync(searchIndex); +``` + +## Add documents to your index + +Let's create a simple model type for `Hotel`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model +public class Hotel +{ + public string HotelId { get; set; } + public string HotelName { get; set; } + public string Description { get; set; } + public IReadOnlyList DescriptionVector { get; set; } + public string Category { get; set; } + public IReadOnlyList CategoryVector { get; set; } +} +``` + +Next, we will create sample hotel documents. The vector field requires submitting text input to an embedding model that converts human-readable text into a vector representation. To convert a text query string provided by a user into a vector representation, your application should utilize an embedding library that offers this functionality. For more details about how to generate embeddings, refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-generate-embeddings). Here's an example of how you can get embeddings using [Azure.AI.OpenAI](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/README.md) library. + +### Get Embeddings using `Azure.AI.OpenAI` + +```C# Snippet:Azure_Search_Tests_Samples_Readme_GetEmbeddings +Uri endpoint = new Uri(Environment.GetEnvironmentVariable("OpenAI_ENDPOINT")); +string key = Environment.GetEnvironmentVariable("OpenAI_API_KEY"); +AzureKeyCredential credential = new AzureKeyCredential(key); + +OpenAIClient openAIClient = new OpenAIClient(endpoint, credential); +string description = "Very popular hotel in town."; +EmbeddingsOptions embeddingsOptions = new(description); + +Embeddings embeddings = await openAIClient.GetEmbeddingsAsync("EmbeddingsModelName", embeddingsOptions); +IReadOnlyList descriptionVector = embeddings.Data[0].Embedding; +``` + +In the sample code below, we are using hardcoded embeddings for the vector fields named `DescriptionVector` and `CategoryVector`: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document +public static Hotel[] GetHotelDocuments() +{ + return new[] + { + new Hotel() + { + HotelId = "1", + HotelName = "Fancy Stay", + Description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + + "and a really helpful concierge. The location is perfect -- right downtown, close to all " + + "the tourist attractions. We highly recommend this hotel.", + DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, + Category = "Luxury", + CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory + }, + new Hotel() + { + HotelId = "2", + HotelName = "Roach Motel", + Description = "Cheapest hotel in town. Infact, a motel.", + DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, + Category = "Budget", + CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory + }, + // Add more hotel documents here... + }; +} +``` + +Now, we can instantiate the `SearchClient` and upload the documents to the `Hotel` index we created earlier: + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents_UsingTextVectors +SearchClient searchClient = new(endpoint, indexName, credential); +Hotel[] hotelDocuments = GetHotelDocuments(); +await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); +``` + +## Query Vector Data + +When using `VectorizableTextQuery`, the query for a vector field should be the text that will be vectorized based on the `Vectorizer` configuration in order to perform a vector search. + +Let's query the index and make sure everything works as implemented. You can also refer to the [documentation](https://learn.microsoft.com/azure/search/vector-search-how-to-query) for more information on querying vector data. + +### Single Vector Search + +In this vector query, the `VectorQueries` contains the vectorizable text of the query input. The `Fields` property specifies which vector fields are searched. The `KNearestNeighborsCount` property specifies the number of nearest neighbors to return as top hits. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search_UsingTextVectors +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + }); + +int count = 0; +Console.WriteLine($"Single Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Single Vector Search With Filter + +In addition to the vector query mentioned above, we can also apply a filter to narrow down the search results. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter_UsingTextVectors +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + Filter = "Category eq 'Luxury'" + }); + +int count = 0; +Console.WriteLine($"Single Vector Search With Filter Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Hybrid Search + +A hybrid query combines full text search, semantic search (reranking), and vector search. The search engine runs full text and vector queries in parallel. Semantic ranking is applied to the results from the text search. A single result set is returned in the response. + +#### Simple Hybrid Search + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search_UsingTextVectors +SearchResults response = await searchClient.SearchAsync( + "Luxury hotels in town", + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + }); + +int count = 0; +Console.WriteLine($"Simple Hybrid Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Multi-vector Search + +You can search containing multiple queries using the `SearchOptions.VectorQueries` property. These queries will be executed concurrently in the search index, with each one searching for similarities in the target vector fields. The result set will be a combination of documents that matched both vector queries. One common use case for this query request is when using models like CLIP for a multi-modal vector search, where the same model can vectorize both image and non-image content. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search_UsingTextVectors +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { + new VectorizableTextQuery() { + Text = "Top hotels in town", KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } + }, + new VectorizableTextQuery() { + Text = "Luxury hotels in town", KNearestNeighborsCount = 3, Fields = { "CategoryVector" } + } + }, + }); + +int count = 0; +Console.WriteLine($"Multi Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` + +### Multi-field Vector Search + +You can set the `SearchOptions.VectorQueries.Fields` property to multiple vector fields. For example, we have vector fields named `DescriptionVector` and `CategoryVector`. Your vector query executes over both the `DescriptionVector` and `CategoryVector` fields. + +```C# Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search_UsingTextVectors +SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector", "CategoryVector" } } } + }); + +int count = 0; +Console.WriteLine($"Multi Fields Vector Search Results:"); +await foreach (SearchResult result in response.GetResultsAsync()) +{ + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); +} +Console.WriteLine($"Total number of search results:{count}"); +``` diff --git a/sdk/search/Azure.Search.Documents/src/Generated/AliasesRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/AliasesRestClient.cs index 9ad3176a28b13..36ce277a15f6c 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/AliasesRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/AliasesRestClient.cs @@ -33,7 +33,7 @@ internal partial class AliasesRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public AliasesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public AliasesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/DataSourcesRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/DataSourcesRestClient.cs index b9563b3b0606d..9c6c0cf0753a8 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/DataSourcesRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/DataSourcesRestClient.cs @@ -33,7 +33,7 @@ internal partial class DataSourcesRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public DataSourcesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public DataSourcesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/DocumentsRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/DocumentsRestClient.cs index 2319e790f4c7e..74c7f24430f6a 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/DocumentsRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/DocumentsRestClient.cs @@ -37,7 +37,7 @@ internal partial class DocumentsRestClient /// Api Version. /// , , , or is null. /// is an empty string, and was expected to be non-empty. - public DocumentsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string indexName, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public DocumentsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string indexName, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/IndexersRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/IndexersRestClient.cs index b79f8dc264918..febb1b9e2bf50 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/IndexersRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/IndexersRestClient.cs @@ -34,7 +34,7 @@ internal partial class IndexersRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public IndexersRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public IndexersRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/IndexesRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/IndexesRestClient.cs index 7bc689a0070d8..62760b53cab2c 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/IndexesRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/IndexesRestClient.cs @@ -33,7 +33,7 @@ internal partial class IndexesRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public IndexesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public IndexesRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.Serialization.cs new file mode 100644 index 0000000000000..bde3ed60afa10 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.Serialization.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class AzureOpenAIEmbeddingSkill : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(ResourceUri)) + { + writer.WritePropertyName("resourceUri"u8); + writer.WriteStringValue(ResourceUri.AbsoluteUri); + } + if (Optional.IsDefined(DeploymentId)) + { + writer.WritePropertyName("deploymentId"u8); + writer.WriteStringValue(DeploymentId); + } + if (Optional.IsDefined(ApiKey)) + { + writer.WritePropertyName("apiKey"u8); + writer.WriteStringValue(ApiKey); + } + if (Optional.IsDefined(AuthIdentity)) + { + if (AuthIdentity != null) + { + writer.WritePropertyName("authIdentity"u8); + writer.WriteObjectValue(AuthIdentity); + } + else + { + writer.WriteNull("authIdentity"); + } + } + writer.WritePropertyName("@odata.type"u8); + writer.WriteStringValue(ODataType); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsDefined(Description)) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + if (Optional.IsDefined(Context)) + { + writer.WritePropertyName("context"u8); + writer.WriteStringValue(Context); + } + writer.WritePropertyName("inputs"u8); + writer.WriteStartArray(); + foreach (var item in Inputs) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("outputs"u8); + writer.WriteStartArray(); + foreach (var item in Outputs) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WriteEndObject(); + } + + internal static AzureOpenAIEmbeddingSkill DeserializeAzureOpenAIEmbeddingSkill(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional resourceUri = default; + Optional deploymentId = default; + Optional apiKey = default; + Optional authIdentity = default; + string odataType = default; + Optional name = default; + Optional description = default; + Optional context = default; + IList inputs = default; + IList outputs = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("resourceUri"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + resourceUri = new Uri(property.Value.GetString()); + continue; + } + if (property.NameEquals("deploymentId"u8)) + { + deploymentId = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiKey"u8)) + { + apiKey = property.Value.GetString(); + continue; + } + if (property.NameEquals("authIdentity"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + authIdentity = null; + continue; + } + authIdentity = SearchIndexerDataIdentity.DeserializeSearchIndexerDataIdentity(property.Value); + continue; + } + if (property.NameEquals("@odata.type"u8)) + { + odataType = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("description"u8)) + { + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("context"u8)) + { + context = property.Value.GetString(); + continue; + } + if (property.NameEquals("inputs"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(InputFieldMappingEntry.DeserializeInputFieldMappingEntry(item)); + } + inputs = array; + continue; + } + if (property.NameEquals("outputs"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OutputFieldMappingEntry.DeserializeOutputFieldMappingEntry(item)); + } + outputs = array; + continue; + } + } + return new AzureOpenAIEmbeddingSkill(odataType, name.Value, description.Value, context.Value, inputs, outputs, resourceUri.Value, deploymentId.Value, apiKey.Value, authIdentity.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.cs new file mode 100644 index 0000000000000..f2048307c3bc3 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIEmbeddingSkill.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Allows you to generate a vector embedding for a given text input using the Azure Open AI service. + public partial class AzureOpenAIEmbeddingSkill : SearchIndexerSkill + { + /// Initializes a new instance of AzureOpenAIEmbeddingSkill. + /// Inputs of the skills could be a column in the source data set, or the output of an upstream skill. + /// The output of a skill is either a field in a search index, or a value that can be consumed as an input by another skill. + /// or is null. + public AzureOpenAIEmbeddingSkill(IEnumerable inputs, IEnumerable outputs) : base(inputs, outputs) + { + Argument.AssertNotNull(inputs, nameof(inputs)); + Argument.AssertNotNull(outputs, nameof(outputs)); + + ODataType = "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill"; + } + + /// Initializes a new instance of AzureOpenAIEmbeddingSkill. + /// Identifies the concrete type of the skill. + /// The name of the skill which uniquely identifies it within the skillset. A skill with no name defined will be given a default name of its 1-based index in the skills array, prefixed with the character '#'. + /// The description of the skill which describes the inputs, outputs, and usage of the skill. + /// Represents the level at which operations take place, such as the document root or document content (for example, /document or /document/content). The default is /document. + /// Inputs of the skills could be a column in the source data set, or the output of an upstream skill. + /// The output of a skill is either a field in a search index, or a value that can be consumed as an input by another skill. + /// The resource uri for your Azure Open AI resource. + /// ID of your Azure Open AI model deployment on the designated resource. + /// API key for the designated Azure Open AI resource. + /// + /// The user-assigned managed identity used for outbound connections. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + internal AzureOpenAIEmbeddingSkill(string oDataType, string name, string description, string context, IList inputs, IList outputs, Uri resourceUri, string deploymentId, string apiKey, SearchIndexerDataIdentity authIdentity) : base(oDataType, name, description, context, inputs, outputs) + { + ResourceUri = resourceUri; + DeploymentId = deploymentId; + ApiKey = apiKey; + AuthIdentity = authIdentity; + ODataType = oDataType ?? "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill"; + } + + /// The resource uri for your Azure Open AI resource. + public Uri ResourceUri { get; set; } + /// ID of your Azure Open AI model deployment on the designated resource. + public string DeploymentId { get; set; } + /// API key for the designated Azure Open AI resource. + public string ApiKey { get; set; } + /// + /// The user-assigned managed identity used for outbound connections. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public SearchIndexerDataIdentity AuthIdentity { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.Serialization.cs new file mode 100644 index 0000000000000..7ed3c7cc7b436 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.Serialization.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class AzureOpenAIParameters : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(ResourceUri)) + { + writer.WritePropertyName("resourceUri"u8); + writer.WriteStringValue(ResourceUri.AbsoluteUri); + } + if (Optional.IsDefined(DeploymentId)) + { + writer.WritePropertyName("deploymentId"u8); + writer.WriteStringValue(DeploymentId); + } + if (Optional.IsDefined(ApiKey)) + { + writer.WritePropertyName("apiKey"u8); + writer.WriteStringValue(ApiKey); + } + if (Optional.IsDefined(AuthIdentity)) + { + if (AuthIdentity != null) + { + writer.WritePropertyName("authIdentity"u8); + writer.WriteObjectValue(AuthIdentity); + } + else + { + writer.WriteNull("authIdentity"); + } + } + writer.WriteEndObject(); + } + + internal static AzureOpenAIParameters DeserializeAzureOpenAIParameters(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional resourceUri = default; + Optional deploymentId = default; + Optional apiKey = default; + Optional authIdentity = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("resourceUri"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + resourceUri = new Uri(property.Value.GetString()); + continue; + } + if (property.NameEquals("deploymentId"u8)) + { + deploymentId = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiKey"u8)) + { + apiKey = property.Value.GetString(); + continue; + } + if (property.NameEquals("authIdentity"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + authIdentity = null; + continue; + } + authIdentity = SearchIndexerDataIdentity.DeserializeSearchIndexerDataIdentity(property.Value); + continue; + } + } + return new AzureOpenAIParameters(resourceUri.Value, deploymentId.Value, apiKey.Value, authIdentity.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.cs new file mode 100644 index 0000000000000..7ff21b588a6c7 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIParameters.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains the parameters specific to using an Azure Open AI service for vectorization at query time. + public partial class AzureOpenAIParameters + { + /// Initializes a new instance of AzureOpenAIParameters. + public AzureOpenAIParameters() + { + } + + /// Initializes a new instance of AzureOpenAIParameters. + /// The resource uri for your Azure Open AI resource. + /// ID of your Azure Open AI model deployment on the designated resource. + /// API key for the designated Azure Open AI resource. + /// + /// The user-assigned managed identity used for outbound connections. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + internal AzureOpenAIParameters(Uri resourceUri, string deploymentId, string apiKey, SearchIndexerDataIdentity authIdentity) + { + ResourceUri = resourceUri; + DeploymentId = deploymentId; + ApiKey = apiKey; + AuthIdentity = authIdentity; + } + + /// The resource uri for your Azure Open AI resource. + public Uri ResourceUri { get; set; } + /// ID of your Azure Open AI model deployment on the designated resource. + public string DeploymentId { get; set; } + /// API key for the designated Azure Open AI resource. + public string ApiKey { get; set; } + /// + /// The user-assigned managed identity used for outbound connections. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public SearchIndexerDataIdentity AuthIdentity { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.Serialization.cs new file mode 100644 index 0000000000000..1a76e26d61710 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.Serialization.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class AzureOpenAIVectorizer : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(AzureOpenAIParameters)) + { + writer.WritePropertyName("azureOpenAIParameters"u8); + writer.WriteObjectValue(AzureOpenAIParameters); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + writer.WriteEndObject(); + } + + internal static AzureOpenAIVectorizer DeserializeAzureOpenAIVectorizer(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional azureOpenAIParameters = default; + string name = default; + VectorSearchVectorizerKind kind = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("azureOpenAIParameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + azureOpenAIParameters = AzureOpenAIParameters.DeserializeAzureOpenAIParameters(property.Value); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorSearchVectorizerKind(property.Value.GetString()); + continue; + } + } + return new AzureOpenAIVectorizer(name, kind, azureOpenAIParameters.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.cs new file mode 100644 index 0000000000000..e88117361ebcf --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/AzureOpenAIVectorizer.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains the parameters specific to using an Azure Open AI service for vectorization at query time. + public partial class AzureOpenAIVectorizer : VectorSearchVectorizer + { + /// Initializes a new instance of AzureOpenAIVectorizer. + /// The name to associate with this particular vectorization method. + /// is null. + public AzureOpenAIVectorizer(string name) : base(name) + { + Argument.AssertNotNull(name, nameof(name)); + + Kind = VectorSearchVectorizerKind.AzureOpenAI; + } + + /// Initializes a new instance of AzureOpenAIVectorizer. + /// The name to associate with this particular vectorization method. + /// The name of the kind of vectorization method being configured for use with vector search. + /// Contains the parameters specific to Azure Open AI embedding vectorization. + internal AzureOpenAIVectorizer(string name, VectorSearchVectorizerKind kind, AzureOpenAIParameters azureOpenAIParameters) : base(name, kind) + { + AzureOpenAIParameters = azureOpenAIParameters; + Kind = kind; + } + + /// Contains the parameters specific to Azure Open AI embedding vectorization. + public AzureOpenAIParameters AzureOpenAIParameters { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.Serialization.cs new file mode 100644 index 0000000000000..12d050b4a1995 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.Serialization.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class CustomVectorizer : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(CustomVectorizerParameters)) + { + writer.WritePropertyName("customVectorizerParameters"u8); + writer.WriteObjectValue(CustomVectorizerParameters); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + writer.WriteEndObject(); + } + + internal static CustomVectorizer DeserializeCustomVectorizer(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional customVectorizerParameters = default; + string name = default; + VectorSearchVectorizerKind kind = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("customVectorizerParameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + customVectorizerParameters = CustomVectorizerParameters.DeserializeCustomVectorizerParameters(property.Value); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorSearchVectorizerKind(property.Value.GetString()); + continue; + } + } + return new CustomVectorizer(name, kind, customVectorizerParameters.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.cs new file mode 100644 index 0000000000000..4ab08910b84e2 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizer.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains the parameters specific to generating vector embeddings via a custom endpoint. + public partial class CustomVectorizer : VectorSearchVectorizer + { + /// Initializes a new instance of CustomVectorizer. + /// The name to associate with this particular vectorization method. + /// is null. + public CustomVectorizer(string name) : base(name) + { + Argument.AssertNotNull(name, nameof(name)); + + Kind = VectorSearchVectorizerKind.CustomWebApi; + } + + /// Initializes a new instance of CustomVectorizer. + /// The name to associate with this particular vectorization method. + /// The name of the kind of vectorization method being configured for use with vector search. + /// Contains the parameters specific to generating vector embeddings via a custom endpoint. + internal CustomVectorizer(string name, VectorSearchVectorizerKind kind, CustomVectorizerParameters customVectorizerParameters) : base(name, kind) + { + CustomVectorizerParameters = customVectorizerParameters; + Kind = kind; + } + + /// Contains the parameters specific to generating vector embeddings via a custom endpoint. + public CustomVectorizerParameters CustomVectorizerParameters { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.Serialization.cs new file mode 100644 index 0000000000000..4df9665a3946f --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.Serialization.cs @@ -0,0 +1,148 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class CustomVectorizerParameters : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Uri)) + { + writer.WritePropertyName("uri"u8); + writer.WriteStringValue(Uri.AbsoluteUri); + } + if (Optional.IsCollectionDefined(HttpHeaders)) + { + writer.WritePropertyName("httpHeaders"u8); + writer.WriteStartObject(); + foreach (var item in HttpHeaders) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + if (Optional.IsDefined(HttpMethod)) + { + writer.WritePropertyName("httpMethod"u8); + writer.WriteStringValue(HttpMethod); + } + if (Optional.IsDefined(Timeout)) + { + writer.WritePropertyName("timeout"u8); + writer.WriteStringValue(Timeout.Value, "P"); + } + if (Optional.IsDefined(AuthResourceId)) + { + if (AuthResourceId != null) + { + writer.WritePropertyName("authResourceId"u8); + writer.WriteStringValue(AuthResourceId); + } + else + { + writer.WriteNull("authResourceId"); + } + } + if (Optional.IsDefined(AuthIdentity)) + { + if (AuthIdentity != null) + { + writer.WritePropertyName("authIdentity"u8); + writer.WriteObjectValue(AuthIdentity); + } + else + { + writer.WriteNull("authIdentity"); + } + } + writer.WriteEndObject(); + } + + internal static CustomVectorizerParameters DeserializeCustomVectorizerParameters(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional uri = default; + Optional> httpHeaders = default; + Optional httpMethod = default; + Optional timeout = default; + Optional authResourceId = default; + Optional authIdentity = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("uri"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + uri = new Uri(property.Value.GetString()); + continue; + } + if (property.NameEquals("httpHeaders"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + httpHeaders = dictionary; + continue; + } + if (property.NameEquals("httpMethod"u8)) + { + httpMethod = property.Value.GetString(); + continue; + } + if (property.NameEquals("timeout"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + timeout = property.Value.GetTimeSpan("P"); + continue; + } + if (property.NameEquals("authResourceId"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + authResourceId = null; + continue; + } + authResourceId = property.Value.GetString(); + continue; + } + if (property.NameEquals("authIdentity"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + authIdentity = null; + continue; + } + authIdentity = SearchIndexerDataIdentity.DeserializeSearchIndexerDataIdentity(property.Value); + continue; + } + } + return new CustomVectorizerParameters(uri.Value, Optional.ToDictionary(httpHeaders), httpMethod.Value, Optional.ToNullable(timeout), authResourceId.Value, authIdentity.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.cs new file mode 100644 index 0000000000000..9629ecae08edf --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/CustomVectorizerParameters.cs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains the parameters specific to generating vector embeddings via a custom endpoint. + public partial class CustomVectorizerParameters + { + /// Initializes a new instance of CustomVectorizerParameters. + public CustomVectorizerParameters() + { + HttpHeaders = new ChangeTrackingDictionary(); + } + + /// Initializes a new instance of CustomVectorizerParameters. + /// The uri for the Web API. + /// The headers required to make the http request. + /// The method for the http request. + /// The desired timeout for the request. Default is 30 seconds. + /// Applies to custom endpoints that connect to external code in an Azure function or some other application that provides the transformations. This value should be the application ID created for the function or app when it was registered with Azure Active Directory. When specified, the vectorization connects to the function or app using a managed ID (either system or user-assigned) of the search service and the access token of the function or app, using this value as the resource id for creating the scope of the access token. + /// + /// The user-assigned managed identity used for outbound connections. If an authResourceId is provided and it's not specified, the system-assigned managed identity is used. On updates to the indexer, if the identity is unspecified, the value remains unchanged. If set to "none", the value of this property is cleared. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + internal CustomVectorizerParameters(Uri uri, IDictionary httpHeaders, string httpMethod, TimeSpan? timeout, string authResourceId, SearchIndexerDataIdentity authIdentity) + { + Uri = uri; + HttpHeaders = httpHeaders; + HttpMethod = httpMethod; + Timeout = timeout; + AuthResourceId = authResourceId; + AuthIdentity = authIdentity; + } + + /// The uri for the Web API. + public Uri Uri { get; set; } + /// The headers required to make the http request. + public IDictionary HttpHeaders { get; } + /// The method for the http request. + public string HttpMethod { get; set; } + /// The desired timeout for the request. Default is 30 seconds. + public TimeSpan? Timeout { get; set; } + /// Applies to custom endpoints that connect to external code in an Azure function or some other application that provides the transformations. This value should be the application ID created for the function or app when it was registered with Azure Active Directory. When specified, the vectorization connects to the function or app using a managed ID (either system or user-assigned) of the search service and the access token of the function or app, using this value as the resource id for creating the scope of the access token. + public string AuthResourceId { get; set; } + /// + /// The user-assigned managed identity used for outbound connections. If an authResourceId is provided and it's not specified, the system-assigned managed identity is used. On updates to the indexer, if the identity is unspecified, the value remains unchanged. If set to "none", the value of this property is cleared. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public SearchIndexerDataIdentity AuthIdentity { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.Serialization.cs index 2d4d605eae856..30529ab847706 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.Serialization.cs @@ -31,6 +31,7 @@ internal static DataDeletionDetectionPolicy DeserializeDataDeletionDetectionPoli { switch (discriminator.GetString()) { + case "#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy": return NativeBlobSoftDeleteDeletionDetectionPolicy.DeserializeNativeBlobSoftDeleteDeletionDetectionPolicy(element); case "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy": return SoftDeleteColumnDeletionDetectionPolicy.DeserializeSoftDeleteColumnDeletionDetectionPolicy(element); } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.cs index f4d41827dcad1..86d3b97132708 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/DataDeletionDetectionPolicy.cs @@ -10,7 +10,7 @@ namespace Azure.Search.Documents.Indexes.Models /// /// Base type for data deletion detection policies. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . /// public partial class DataDeletionDetectionPolicy { diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.Serialization.cs new file mode 100644 index 0000000000000..61acbb2c86611 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.Serialization.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class ExhaustiveKnnParameters : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Metric)) + { + if (Metric != null) + { + writer.WritePropertyName("metric"u8); + writer.WriteStringValue(Metric.Value.ToString()); + } + else + { + writer.WriteNull("metric"); + } + } + writer.WriteEndObject(); + } + + internal static ExhaustiveKnnParameters DeserializeExhaustiveKnnParameters(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional metric = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("metric"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metric = null; + continue; + } + metric = new VectorSearchAlgorithmMetric(property.Value.GetString()); + continue; + } + } + return new ExhaustiveKnnParameters(Optional.ToNullable(metric)); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.cs new file mode 100644 index 0000000000000..4e1900bce3618 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnParameters.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains the parameters specific to exhaustive KNN algorithm. + public partial class ExhaustiveKnnParameters + { + /// Initializes a new instance of ExhaustiveKnnParameters. + public ExhaustiveKnnParameters() + { + } + + /// Initializes a new instance of ExhaustiveKnnParameters. + /// The similarity metric to use for vector comparisons. + internal ExhaustiveKnnParameters(VectorSearchAlgorithmMetric? metric) + { + Metric = metric; + } + + /// The similarity metric to use for vector comparisons. + public VectorSearchAlgorithmMetric? Metric { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.Serialization.cs new file mode 100644 index 0000000000000..e25b3e2504142 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.Serialization.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class ExhaustiveKnnVectorSearchAlgorithmConfiguration : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Parameters)) + { + writer.WritePropertyName("exhaustiveKnnParameters"u8); + writer.WriteObjectValue(Parameters); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + writer.WriteEndObject(); + } + + internal static ExhaustiveKnnVectorSearchAlgorithmConfiguration DeserializeExhaustiveKnnVectorSearchAlgorithmConfiguration(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional exhaustiveKnnParameters = default; + string name = default; + VectorSearchAlgorithmKind kind = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("exhaustiveKnnParameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + exhaustiveKnnParameters = ExhaustiveKnnParameters.DeserializeExhaustiveKnnParameters(property.Value); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorSearchAlgorithmKind(property.Value.GetString()); + continue; + } + } + return new ExhaustiveKnnVectorSearchAlgorithmConfiguration(name, kind, exhaustiveKnnParameters.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.cs new file mode 100644 index 0000000000000..c7c50150af7d2 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/ExhaustiveKnnVectorSearchAlgorithmConfiguration.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Contains configuration options specific to the exhaustive KNN algorithm used during querying, which will perform brute-force search across the entire vector index. + public partial class ExhaustiveKnnVectorSearchAlgorithmConfiguration : VectorSearchAlgorithmConfiguration + { + /// Initializes a new instance of ExhaustiveKnnVectorSearchAlgorithmConfiguration. + /// The name to associate with this particular configuration. + /// is null. + public ExhaustiveKnnVectorSearchAlgorithmConfiguration(string name) : base(name) + { + Argument.AssertNotNull(name, nameof(name)); + + Kind = VectorSearchAlgorithmKind.ExhaustiveKnn; + } + + /// Initializes a new instance of ExhaustiveKnnVectorSearchAlgorithmConfiguration. + /// The name to associate with this particular configuration. + /// The name of the kind of algorithm being configured for use with vector search. + /// Contains the parameters specific to exhaustive KNN algorithm. + internal ExhaustiveKnnVectorSearchAlgorithmConfiguration(string name, VectorSearchAlgorithmKind kind, ExhaustiveKnnParameters parameters) : base(name, kind) + { + Parameters = parameters; + Kind = kind; + } + + /// Contains the parameters specific to exhaustive KNN algorithm. + public ExhaustiveKnnParameters Parameters { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswParameters.cs index 702904af54a58..19c5e59c5b399 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswParameters.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswParameters.cs @@ -18,7 +18,7 @@ public HnswParameters() /// Initializes a new instance of HnswParameters. /// The number of bi-directional links created for every new element during construction. Increasing this parameter value may improve recall and reduce retrieval times for datasets with high intrinsic dimensionality at the expense of increased memory consumption and longer indexing time. /// The size of the dynamic list containing the nearest neighbors, which is used during index time. Increasing this parameter may improve index quality, at the expense of increased indexing time. At a certain point, increasing this parameter leads to diminishing returns. - /// The size of the dynamic list containing the nearest neighbors, which is used during search time. Increasing this parameter may improve search results, at the expense of slower search. Increasing this parameter leads to diminishing returns.. + /// The size of the dynamic list containing the nearest neighbors, which is used during search time. Increasing this parameter may improve search results, at the expense of slower search. At a certain point, increasing this parameter leads to diminishing returns. /// The similarity metric to use for vector comparisons. internal HnswParameters(int? m, int? efConstruction, int? efSearch, VectorSearchAlgorithmMetric? metric) { @@ -32,7 +32,7 @@ internal HnswParameters(int? m, int? efConstruction, int? efSearch, VectorSearch public int? M { get; set; } /// The size of the dynamic list containing the nearest neighbors, which is used during index time. Increasing this parameter may improve index quality, at the expense of increased indexing time. At a certain point, increasing this parameter leads to diminishing returns. public int? EfConstruction { get; set; } - /// The size of the dynamic list containing the nearest neighbors, which is used during search time. Increasing this parameter may improve search results, at the expense of slower search. Increasing this parameter leads to diminishing returns.. + /// The size of the dynamic list containing the nearest neighbors, which is used during search time. Increasing this parameter may improve search results, at the expense of slower search. At a certain point, increasing this parameter leads to diminishing returns. public int? EfSearch { get; set; } /// The similarity metric to use for vector comparisons. public VectorSearchAlgorithmMetric? Metric { get; set; } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.Serialization.cs index e589d5d7ef8a5..dcfbe42db9d52 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.Serialization.cs @@ -23,7 +23,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("name"u8); writer.WriteStringValue(Name); writer.WritePropertyName("kind"u8); - writer.WriteStringValue(Kind); + writer.WriteStringValue(Kind.ToString()); writer.WriteEndObject(); } @@ -35,7 +35,7 @@ internal static HnswVectorSearchAlgorithmConfiguration DeserializeHnswVectorSear } Optional hnswParameters = default; string name = default; - string kind = default; + VectorSearchAlgorithmKind kind = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("hnswParameters"u8)) @@ -54,7 +54,7 @@ internal static HnswVectorSearchAlgorithmConfiguration DeserializeHnswVectorSear } if (property.NameEquals("kind"u8)) { - kind = property.Value.GetString(); + kind = new VectorSearchAlgorithmKind(property.Value.GetString()); continue; } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.cs index 303e3792f15e5..ca23a8d58736a 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/HnswVectorSearchAlgorithmConfiguration.cs @@ -10,7 +10,7 @@ namespace Azure.Search.Documents.Indexes.Models { - /// Contains configuration options specific to the hnsw approximate nearest neighbors algorithm used during indexing time. + /// Contains configuration options specific to the hnsw approximate nearest neighbors algorithm used during indexing and querying. The hnsw algorithm offers a tunable trade-off between search speed and accuracy. public partial class HnswVectorSearchAlgorithmConfiguration : VectorSearchAlgorithmConfiguration { /// Initializes a new instance of HnswVectorSearchAlgorithmConfiguration. @@ -20,17 +20,17 @@ public HnswVectorSearchAlgorithmConfiguration(string name) : base(name) { Argument.AssertNotNull(name, nameof(name)); - Kind = "hnsw"; + Kind = VectorSearchAlgorithmKind.Hnsw; } /// Initializes a new instance of HnswVectorSearchAlgorithmConfiguration. /// The name to associate with this particular configuration. - /// The name of the kind of algorithm being configured for use with vector search. Only `hnsw` is supported in the current preview. + /// The name of the kind of algorithm being configured for use with vector search. /// Contains the parameters specific to hnsw algorithm. - internal HnswVectorSearchAlgorithmConfiguration(string name, string kind, HnswParameters parameters) : base(name, kind) + internal HnswVectorSearchAlgorithmConfiguration(string name, VectorSearchAlgorithmKind kind, HnswParameters parameters) : base(name, kind) { Parameters = parameters; - Kind = kind ?? "hnsw"; + Kind = kind; } /// Contains the parameters specific to hnsw algorithm. diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/IndexProjectionMode.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/IndexProjectionMode.cs new file mode 100644 index 0000000000000..0d629e30d902c --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/IndexProjectionMode.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Defines behavior of the index projections in relation to the rest of the indexer. + public readonly partial struct IndexProjectionMode : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public IndexProjectionMode(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string SkipIndexingParentDocumentsValue = "skipIndexingParentDocuments"; + private const string IncludeIndexingParentDocumentsValue = "includeIndexingParentDocuments"; + + /// The source document will be skipped from writing into the indexer's target index. + public static IndexProjectionMode SkipIndexingParentDocuments { get; } = new IndexProjectionMode(SkipIndexingParentDocumentsValue); + /// The source document will be written into the indexer's target index. This is the default pattern. + public static IndexProjectionMode IncludeIndexingParentDocuments { get; } = new IndexProjectionMode(IncludeIndexingParentDocumentsValue); + /// Determines if two values are the same. + public static bool operator ==(IndexProjectionMode left, IndexProjectionMode right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(IndexProjectionMode left, IndexProjectionMode right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator IndexProjectionMode(string value) => new IndexProjectionMode(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is IndexProjectionMode other && Equals(other); + /// + public bool Equals(IndexProjectionMode other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.Serialization.cs index de33627ca2301..156f09ccef9f3 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.Serialization.cs @@ -37,6 +37,11 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WriteNull("identity"); } } + if (Optional.IsDefined(Parameters)) + { + writer.WritePropertyName("parameters"u8); + writer.WriteObjectValue(Parameters); + } writer.WriteEndObject(); } @@ -49,6 +54,7 @@ internal static KnowledgeStore DeserializeKnowledgeStore(JsonElement element) string storageConnectionString = default; IList projections = default; Optional identity = default; + Optional parameters = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("storageConnectionString"u8)) @@ -76,8 +82,17 @@ internal static KnowledgeStore DeserializeKnowledgeStore(JsonElement element) identity = SearchIndexerDataIdentity.DeserializeSearchIndexerDataIdentity(property.Value); continue; } + if (property.NameEquals("parameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + parameters = SearchIndexerKnowledgeStoreParameters.DeserializeSearchIndexerKnowledgeStoreParameters(property.Value); + continue; + } } - return new KnowledgeStore(storageConnectionString, projections, identity.Value); + return new KnowledgeStore(storageConnectionString, projections, identity.Value, parameters.Value); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.cs index 56784f3e80f36..80cbfc974122f 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/KnowledgeStore.cs @@ -36,11 +36,13 @@ public KnowledgeStore(string storageConnectionString, IEnumerable is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. /// The available derived classes include and . /// - internal KnowledgeStore(string storageConnectionString, IList projections, SearchIndexerDataIdentity identity) + /// A dictionary of knowledge store-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + internal KnowledgeStore(string storageConnectionString, IList projections, SearchIndexerDataIdentity identity, SearchIndexerKnowledgeStoreParameters parameters) { StorageConnectionString = storageConnectionString; Projections = projections; Identity = identity; + Parameters = parameters; } /// The connection string to the storage account projections will be stored in. @@ -53,5 +55,7 @@ internal KnowledgeStore(string storageConnectionString, IList and . /// public SearchIndexerDataIdentity Identity { get; set; } + /// A dictionary of knowledge store-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + public SearchIndexerKnowledgeStoreParameters Parameters { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.Serialization.cs new file mode 100644 index 0000000000000..3768cd2ef9a2f --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.Serialization.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class NativeBlobSoftDeleteDeletionDetectionPolicy : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("@odata.type"u8); + writer.WriteStringValue(ODataType); + writer.WriteEndObject(); + } + + internal static NativeBlobSoftDeleteDeletionDetectionPolicy DeserializeNativeBlobSoftDeleteDeletionDetectionPolicy(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string odataType = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("@odata.type"u8)) + { + odataType = property.Value.GetString(); + continue; + } + } + return new NativeBlobSoftDeleteDeletionDetectionPolicy(odataType); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.cs new file mode 100644 index 0000000000000..d55005cb69074 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/NativeBlobSoftDeleteDeletionDetectionPolicy.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Defines a data deletion detection policy utilizing Azure Blob Storage's native soft delete feature for deletion detection. + public partial class NativeBlobSoftDeleteDeletionDetectionPolicy : DataDeletionDetectionPolicy + { + /// Initializes a new instance of NativeBlobSoftDeleteDeletionDetectionPolicy. + public NativeBlobSoftDeleteDeletionDetectionPolicy() + { + ODataType = "#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy"; + } + + /// Initializes a new instance of NativeBlobSoftDeleteDeletionDetectionPolicy. + /// Identifies the concrete type of the data deletion detection policy. + internal NativeBlobSoftDeleteDeletionDetectionPolicy(string oDataType) : base(oDataType) + { + ODataType = oDataType ?? "#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy"; + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.Serialization.cs new file mode 100644 index 0000000000000..b4928d04d965f --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.Serialization.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + public partial class RawVectorQuery : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsCollectionDefined(Vector)) + { + writer.WritePropertyName("vector"u8); + writer.WriteStartArray(); + foreach (var item in Vector) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + } + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + if (Optional.IsDefined(KNearestNeighborsCount)) + { + writer.WritePropertyName("k"u8); + writer.WriteNumberValue(KNearestNeighborsCount.Value); + } + if (Optional.IsDefined(FieldsRaw)) + { + writer.WritePropertyName("fields"u8); + writer.WriteStringValue(FieldsRaw); + } + if (Optional.IsDefined(Exhaustive)) + { + writer.WritePropertyName("exhaustive"u8); + writer.WriteBooleanValue(Exhaustive.Value); + } + writer.WriteEndObject(); + } + + internal static RawVectorQuery DeserializeRawVectorQuery(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional> vector = default; + VectorQueryKind kind = default; + Optional k = default; + Optional fields = default; + Optional exhaustive = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("vector"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetSingle()); + } + vector = array; + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorQueryKind(property.Value.GetString()); + continue; + } + if (property.NameEquals("k"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + k = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("fields"u8)) + { + fields = property.Value.GetString(); + continue; + } + if (property.NameEquals("exhaustive"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + exhaustive = property.Value.GetBoolean(); + continue; + } + } + return new RawVectorQuery(kind, Optional.ToNullable(k), fields.Value, Optional.ToNullable(exhaustive), Optional.ToList(vector)); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.cs new file mode 100644 index 0000000000000..5d1d81f3bfbb6 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/RawVectorQuery.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + /// The query parameters to use for vector search when a raw vector value is provided. + public partial class RawVectorQuery : VectorQuery + { + /// Initializes a new instance of RawVectorQuery. + public RawVectorQuery() + { + Vector = new ChangeTrackingList(); + Kind = VectorQueryKind.Vector; + } + + /// Initializes a new instance of RawVectorQuery. + /// The kind of vector query being performed. + /// Number of nearest neighbors to return as top hits. + /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. + /// When true, triggers an exhaustive k-nearest neighbor search across all vectors within the vector index. Useful for scenarios where exact matches are critical, such as determining ground truth values. + /// The vector representation of a search query. + internal RawVectorQuery(VectorQueryKind kind, int? kNearestNeighborsCount, string fieldsRaw, bool? exhaustive, IReadOnlyList vector) : base(kind, kNearestNeighborsCount, fieldsRaw, exhaustive) + { + Vector = vector; + Kind = kind; + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.Serialization.cs index 7ef9362205de5..5b15c274d92f1 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.Serialization.cs @@ -110,16 +110,16 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WriteNull("dimensions"); } } - if (Optional.IsDefined(VectorSearchConfiguration)) + if (Optional.IsDefined(VectorSearchProfile)) { - if (VectorSearchConfiguration != null) + if (VectorSearchProfile != null) { - writer.WritePropertyName("vectorSearchConfiguration"u8); - writer.WriteStringValue(VectorSearchConfiguration); + writer.WritePropertyName("vectorSearchProfile"u8); + writer.WriteStringValue(VectorSearchProfile); } else { - writer.WriteNull("vectorSearchConfiguration"); + writer.WriteNull("vectorSearchProfile"); } } if (Optional.IsCollectionDefined(SynonymMapNames)) @@ -164,7 +164,7 @@ internal static SearchField DeserializeSearchField(JsonElement element) Optional indexAnalyzer = default; Optional normalizer = default; Optional dimensions = default; - Optional vectorSearchConfiguration = default; + Optional vectorSearchProfile = default; Optional> synonymMaps = default; Optional> fields = default; foreach (var property in element.EnumerateObject()) @@ -283,14 +283,14 @@ internal static SearchField DeserializeSearchField(JsonElement element) dimensions = property.Value.GetInt32(); continue; } - if (property.NameEquals("vectorSearchConfiguration"u8)) + if (property.NameEquals("vectorSearchProfile"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { - vectorSearchConfiguration = null; + vectorSearchProfile = null; continue; } - vectorSearchConfiguration = property.Value.GetString(); + vectorSearchProfile = property.Value.GetString(); continue; } if (property.NameEquals("synonymMaps"u8)) @@ -322,7 +322,7 @@ internal static SearchField DeserializeSearchField(JsonElement element) continue; } } - return new SearchField(name, type, Optional.ToNullable(key), Optional.ToNullable(retrievable), Optional.ToNullable(searchable), Optional.ToNullable(filterable), Optional.ToNullable(sortable), Optional.ToNullable(facetable), Optional.ToNullable(analyzer), Optional.ToNullable(searchAnalyzer), Optional.ToNullable(indexAnalyzer), Optional.ToNullable(normalizer), Optional.ToNullable(dimensions), vectorSearchConfiguration.Value, Optional.ToList(synonymMaps), Optional.ToList(fields)); + return new SearchField(name, type, Optional.ToNullable(key), Optional.ToNullable(retrievable), Optional.ToNullable(searchable), Optional.ToNullable(filterable), Optional.ToNullable(sortable), Optional.ToNullable(facetable), Optional.ToNullable(analyzer), Optional.ToNullable(searchAnalyzer), Optional.ToNullable(indexAnalyzer), Optional.ToNullable(normalizer), Optional.ToNullable(dimensions), vectorSearchProfile.Value, Optional.ToList(synonymMaps), Optional.ToList(fields)); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.cs index 4e06f03edbc36..ca0d379fad7b9 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchField.cs @@ -28,10 +28,10 @@ public partial class SearchField /// The name of the analyzer used at indexing time for the field. This option can be used only with searchable fields. It must be set together with searchAnalyzer and it cannot be set together with the analyzer option. This property cannot be set to the name of a language analyzer; use the analyzer property instead if you need a language analyzer. Once the analyzer is chosen, it cannot be changed for the field. Must be null for complex fields. /// The name of the normalizer to use for the field. This option can be used only with fields with filterable, sortable, or facetable enabled. Once the normalizer is chosen, it cannot be changed for the field. Must be null for complex fields. /// The dimensionality of the vector field. - /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters for searching the vector field. + /// The name of the vector search profile that specifies the algorithm and vectorizer to use when searching the vector field. /// A list of the names of synonym maps to associate with this field. This option can be used only with searchable fields. Currently only one synonym map per field is supported. Assigning a synonym map to a field ensures that query terms targeting that field are expanded at query-time using the rules in the synonym map. This attribute can be changed on existing fields. Must be null or an empty collection for complex fields. /// A list of sub-fields if this is a field of type Edm.ComplexType or Collection(Edm.ComplexType). Must be null or empty for simple fields. - internal SearchField(string name, SearchFieldDataType type, bool? isKey, bool? isRetrievable, bool? isSearchable, bool? isFilterable, bool? isSortable, bool? isFacetable, LexicalAnalyzerName? analyzerName, LexicalAnalyzerName? searchAnalyzerName, LexicalAnalyzerName? indexAnalyzerName, LexicalNormalizerName? normalizerName, int? vectorSearchDimensions, string vectorSearchConfiguration, IList synonymMapNames, IList fields) + internal SearchField(string name, SearchFieldDataType type, bool? isKey, bool? isRetrievable, bool? isSearchable, bool? isFilterable, bool? isSortable, bool? isFacetable, LexicalAnalyzerName? analyzerName, LexicalAnalyzerName? searchAnalyzerName, LexicalAnalyzerName? indexAnalyzerName, LexicalNormalizerName? normalizerName, int? vectorSearchDimensions, string vectorSearchProfile, IList synonymMapNames, IList fields) { Name = name; Type = type; @@ -46,13 +46,13 @@ internal SearchField(string name, SearchFieldDataType type, bool? isKey, bool? i IndexAnalyzerName = indexAnalyzerName; NormalizerName = normalizerName; VectorSearchDimensions = vectorSearchDimensions; - VectorSearchConfiguration = vectorSearchConfiguration; + VectorSearchProfile = vectorSearchProfile; SynonymMapNames = synonymMapNames; Fields = fields; } /// The dimensionality of the vector field. public int? VectorSearchDimensions { get; set; } - /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters for searching the vector field. - public string VectorSearchConfiguration { get; set; } + /// The name of the vector search profile that specifies the algorithm and vectorizer to use when searching the vector field. + public string VectorSearchProfile { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.Serialization.cs index 50e32ab9228a4..56e3d1ebc78e5 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.Serialization.cs @@ -6,7 +6,6 @@ #nullable disable using System.Text.Json; -using Azure.Core; namespace Azure.Search.Documents.Indexes.Models { @@ -20,7 +19,7 @@ internal static SearchIndexStatistics DeserializeSearchIndexStatistics(JsonEleme } long documentCount = default; long storageSize = default; - Optional vectorIndexSize = default; + long vectorIndexSize = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("documentCount"u8)) @@ -35,15 +34,11 @@ internal static SearchIndexStatistics DeserializeSearchIndexStatistics(JsonEleme } if (property.NameEquals("vectorIndexSize"u8)) { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } vectorIndexSize = property.Value.GetInt64(); continue; } } - return new SearchIndexStatistics(documentCount, storageSize, Optional.ToNullable(vectorIndexSize)); + return new SearchIndexStatistics(documentCount, storageSize, vectorIndexSize); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.cs index 2510eac167360..778f35b17e601 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexStatistics.cs @@ -10,20 +10,11 @@ namespace Azure.Search.Documents.Indexes.Models /// Statistics for a given index. Statistics are collected periodically and are not guaranteed to always be up-to-date. public partial class SearchIndexStatistics { - /// Initializes a new instance of SearchIndexStatistics. - /// The number of documents in the index. - /// The amount of storage in bytes consumed by the index. - internal SearchIndexStatistics(long documentCount, long storageSize) - { - DocumentCount = documentCount; - StorageSize = storageSize; - } - /// Initializes a new instance of SearchIndexStatistics. /// The number of documents in the index. /// The amount of storage in bytes consumed by the index. /// The amount of memory in bytes consumed by vectors in the index. - internal SearchIndexStatistics(long documentCount, long storageSize, long? vectorIndexSize) + internal SearchIndexStatistics(long documentCount, long storageSize, long vectorIndexSize) { DocumentCount = documentCount; StorageSize = storageSize; @@ -35,6 +26,6 @@ internal SearchIndexStatistics(long documentCount, long storageSize, long? vecto /// The amount of storage in bytes consumed by the index. public long StorageSize { get; } /// The amount of memory in bytes consumed by vectors in the index. - public long? VectorIndexSize { get; } + public long VectorIndexSize { get; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerDataSourceConnection.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerDataSourceConnection.cs index df6b9a9c01e9c..54975b0e4593a 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerDataSourceConnection.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerDataSourceConnection.cs @@ -32,7 +32,7 @@ public partial class SearchIndexerDataSourceConnection /// /// The data deletion detection policy for the datasource. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . /// /// The ETag of the data source. /// A description of an encryption key that you create in Azure Key Vault. This key is used to provide an additional level of encryption-at-rest for your datasource definition when you want full assurance that no one, not even Microsoft, can decrypt your data source definition in Azure Cognitive Search. Once you have encrypted your data source definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you want to rotate your encryption key; Your datasource definition will be unaffected. Encryption with customer-managed keys is not available for free search services, and is only available for paid services created on or after January 1, 2019. @@ -73,7 +73,7 @@ internal SearchIndexerDataSourceConnection(string name, string description, Sear /// /// The data deletion detection policy for the datasource. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . /// public DataDeletionDetectionPolicy DataDeletionDetectionPolicy { get; set; } /// A description of an encryption key that you create in Azure Key Vault. This key is used to provide an additional level of encryption-at-rest for your datasource definition when you want full assurance that no one, not even Microsoft, can decrypt your data source definition in Azure Cognitive Search. Once you have encrypted your data source definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you want to rotate your encryption key; Your datasource definition will be unaffected. Encryption with customer-managed keys is not available for free search services, and is only available for paid services created on or after January 1, 2019. diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.Serialization.cs new file mode 100644 index 0000000000000..138f03cbdd157 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.Serialization.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class SearchIndexerIndexProjectionSelector : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("targetIndexName"u8); + writer.WriteStringValue(TargetIndexName); + writer.WritePropertyName("parentKeyFieldName"u8); + writer.WriteStringValue(ParentKeyFieldName); + writer.WritePropertyName("sourceContext"u8); + writer.WriteStringValue(SourceContext); + writer.WritePropertyName("mappings"u8); + writer.WriteStartArray(); + foreach (var item in Mappings) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WriteEndObject(); + } + + internal static SearchIndexerIndexProjectionSelector DeserializeSearchIndexerIndexProjectionSelector(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string targetIndexName = default; + string parentKeyFieldName = default; + string sourceContext = default; + IList mappings = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("targetIndexName"u8)) + { + targetIndexName = property.Value.GetString(); + continue; + } + if (property.NameEquals("parentKeyFieldName"u8)) + { + parentKeyFieldName = property.Value.GetString(); + continue; + } + if (property.NameEquals("sourceContext"u8)) + { + sourceContext = property.Value.GetString(); + continue; + } + if (property.NameEquals("mappings"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(InputFieldMappingEntry.DeserializeInputFieldMappingEntry(item)); + } + mappings = array; + continue; + } + } + return new SearchIndexerIndexProjectionSelector(targetIndexName, parentKeyFieldName, sourceContext, mappings); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.cs new file mode 100644 index 0000000000000..7b1cb29d08238 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionSelector.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Description for what data to store in the designated search index. + public partial class SearchIndexerIndexProjectionSelector + { + /// Initializes a new instance of SearchIndexerIndexProjectionSelector. + /// Name of the search index to project to. Must have a key field with the 'keyword' analyzer set. + /// Name of the field in the search index to map the parent document's key value to. Must be a string field that is filterable and not the key field. + /// Source context for the projections. Represents the cardinality at which the document will be split into multiple sub documents. + /// Mappings for the projection, or which source should be mapped to which field in the target index. + /// , , or is null. + public SearchIndexerIndexProjectionSelector(string targetIndexName, string parentKeyFieldName, string sourceContext, IEnumerable mappings) + { + Argument.AssertNotNull(targetIndexName, nameof(targetIndexName)); + Argument.AssertNotNull(parentKeyFieldName, nameof(parentKeyFieldName)); + Argument.AssertNotNull(sourceContext, nameof(sourceContext)); + Argument.AssertNotNull(mappings, nameof(mappings)); + + TargetIndexName = targetIndexName; + ParentKeyFieldName = parentKeyFieldName; + SourceContext = sourceContext; + Mappings = mappings.ToList(); + } + + /// Initializes a new instance of SearchIndexerIndexProjectionSelector. + /// Name of the search index to project to. Must have a key field with the 'keyword' analyzer set. + /// Name of the field in the search index to map the parent document's key value to. Must be a string field that is filterable and not the key field. + /// Source context for the projections. Represents the cardinality at which the document will be split into multiple sub documents. + /// Mappings for the projection, or which source should be mapped to which field in the target index. + internal SearchIndexerIndexProjectionSelector(string targetIndexName, string parentKeyFieldName, string sourceContext, IList mappings) + { + TargetIndexName = targetIndexName; + ParentKeyFieldName = parentKeyFieldName; + SourceContext = sourceContext; + Mappings = mappings; + } + + /// Name of the search index to project to. Must have a key field with the 'keyword' analyzer set. + public string TargetIndexName { get; set; } + /// Name of the field in the search index to map the parent document's key value to. Must be a string field that is filterable and not the key field. + public string ParentKeyFieldName { get; set; } + /// Source context for the projections. Represents the cardinality at which the document will be split into multiple sub documents. + public string SourceContext { get; set; } + /// Mappings for the projection, or which source should be mapped to which field in the target index. + public IList Mappings { get; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.Serialization.cs new file mode 100644 index 0000000000000..400e324069d52 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.Serialization.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class SearchIndexerIndexProjections : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("selectors"u8); + writer.WriteStartArray(); + foreach (var item in Selectors) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (Optional.IsDefined(Parameters)) + { + writer.WritePropertyName("parameters"u8); + writer.WriteObjectValue(Parameters); + } + writer.WriteEndObject(); + } + + internal static SearchIndexerIndexProjections DeserializeSearchIndexerIndexProjections(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IList selectors = default; + Optional parameters = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("selectors"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(SearchIndexerIndexProjectionSelector.DeserializeSearchIndexerIndexProjectionSelector(item)); + } + selectors = array; + continue; + } + if (property.NameEquals("parameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + parameters = SearchIndexerIndexProjectionsParameters.DeserializeSearchIndexerIndexProjectionsParameters(property.Value); + continue; + } + } + return new SearchIndexerIndexProjections(selectors, parameters.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.cs new file mode 100644 index 0000000000000..ef20ea9ffb7bc --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjections.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Definition of additional projections to secondary search indexes. + public partial class SearchIndexerIndexProjections + { + /// Initializes a new instance of SearchIndexerIndexProjections. + /// A list of projections to be performed to secondary search indexes. + /// is null. + public SearchIndexerIndexProjections(IEnumerable selectors) + { + Argument.AssertNotNull(selectors, nameof(selectors)); + + Selectors = selectors.ToList(); + } + + /// Initializes a new instance of SearchIndexerIndexProjections. + /// A list of projections to be performed to secondary search indexes. + /// A dictionary of index projection-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + internal SearchIndexerIndexProjections(IList selectors, SearchIndexerIndexProjectionsParameters parameters) + { + Selectors = selectors; + Parameters = parameters; + } + + /// A list of projections to be performed to secondary search indexes. + public IList Selectors { get; } + /// A dictionary of index projection-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + public SearchIndexerIndexProjectionsParameters Parameters { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.Serialization.cs new file mode 100644 index 0000000000000..5f2b84cd69a33 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.Serialization.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class SearchIndexerIndexProjectionsParameters : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(ProjectionMode)) + { + writer.WritePropertyName("projectionMode"u8); + writer.WriteStringValue(ProjectionMode.Value.ToString()); + } + foreach (var item in AdditionalProperties) + { + writer.WritePropertyName(item.Key); + writer.WriteObjectValue(item.Value); + } + writer.WriteEndObject(); + } + + internal static SearchIndexerIndexProjectionsParameters DeserializeSearchIndexerIndexProjectionsParameters(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional projectionMode = default; + IDictionary additionalProperties = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("projectionMode"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + projectionMode = new IndexProjectionMode(property.Value.GetString()); + continue; + } + additionalPropertiesDictionary.Add(property.Name, property.Value.GetObject()); + } + additionalProperties = additionalPropertiesDictionary; + return new SearchIndexerIndexProjectionsParameters(Optional.ToNullable(projectionMode), additionalProperties); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.cs new file mode 100644 index 0000000000000..f2cbd9d81dc86 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerIndexProjectionsParameters.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// A dictionary of index projection-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + public partial class SearchIndexerIndexProjectionsParameters + { + /// Initializes a new instance of SearchIndexerIndexProjectionsParameters. + public SearchIndexerIndexProjectionsParameters() + { + AdditionalProperties = new ChangeTrackingDictionary(); + } + + /// Initializes a new instance of SearchIndexerIndexProjectionsParameters. + /// Defines behavior of the index projections in relation to the rest of the indexer. + /// Additional Properties. + internal SearchIndexerIndexProjectionsParameters(IndexProjectionMode? projectionMode, IDictionary additionalProperties) + { + ProjectionMode = projectionMode; + AdditionalProperties = additionalProperties; + } + + /// Defines behavior of the index projections in relation to the rest of the indexer. + public IndexProjectionMode? ProjectionMode { get; set; } + /// Additional Properties. + public IDictionary AdditionalProperties { get; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.Serialization.cs new file mode 100644 index 0000000000000..0cca32358fc36 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.Serialization.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class SearchIndexerKnowledgeStoreParameters : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(SynthesizeGeneratedKeyName)) + { + writer.WritePropertyName("synthesizeGeneratedKeyName"u8); + writer.WriteBooleanValue(SynthesizeGeneratedKeyName.Value); + } + foreach (var item in AdditionalProperties) + { + writer.WritePropertyName(item.Key); + writer.WriteObjectValue(item.Value); + } + writer.WriteEndObject(); + } + + internal static SearchIndexerKnowledgeStoreParameters DeserializeSearchIndexerKnowledgeStoreParameters(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional synthesizeGeneratedKeyName = default; + IDictionary additionalProperties = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("synthesizeGeneratedKeyName"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + synthesizeGeneratedKeyName = property.Value.GetBoolean(); + continue; + } + additionalPropertiesDictionary.Add(property.Name, property.Value.GetObject()); + } + additionalProperties = additionalPropertiesDictionary; + return new SearchIndexerKnowledgeStoreParameters(Optional.ToNullable(synthesizeGeneratedKeyName), additionalProperties); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.cs new file mode 100644 index 0000000000000..f78a793a000f9 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerKnowledgeStoreParameters.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// A dictionary of knowledge store-specific configuration properties. Each name is the name of a specific property. Each value must be of a primitive type. + public partial class SearchIndexerKnowledgeStoreParameters + { + /// Initializes a new instance of SearchIndexerKnowledgeStoreParameters. + public SearchIndexerKnowledgeStoreParameters() + { + AdditionalProperties = new ChangeTrackingDictionary(); + } + + /// Initializes a new instance of SearchIndexerKnowledgeStoreParameters. + /// Whether or not projections should synthesize a generated key name if one isn't already present. + /// Additional Properties. + internal SearchIndexerKnowledgeStoreParameters(bool? synthesizeGeneratedKeyName, IDictionary additionalProperties) + { + SynthesizeGeneratedKeyName = synthesizeGeneratedKeyName; + AdditionalProperties = additionalProperties; + } + + /// Whether or not projections should synthesize a generated key name if one isn't already present. + public bool? SynthesizeGeneratedKeyName { get; set; } + /// Additional Properties. + public IDictionary AdditionalProperties { get; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.Serialization.cs index 1409c4a1d122b..fc06d8f858a0c 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.Serialization.cs @@ -62,6 +62,7 @@ internal static SearchIndexerSkill DeserializeSearchIndexerSkill(JsonElement ele { case "#Microsoft.Skills.Custom.AmlSkill": return AzureMachineLearningSkill.DeserializeAzureMachineLearningSkill(element); case "#Microsoft.Skills.Custom.WebApiSkill": return WebApiSkill.DeserializeWebApiSkill(element); + case "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill": return AzureOpenAIEmbeddingSkill.DeserializeAzureOpenAIEmbeddingSkill(element); case "#Microsoft.Skills.Text.CustomEntityLookupSkill": return CustomEntityLookupSkill.DeserializeCustomEntityLookupSkill(element); case "#Microsoft.Skills.Text.EntityRecognitionSkill": return EntityRecognitionSkill.DeserializeEntityRecognitionSkill(element); case "#Microsoft.Skills.Text.KeyPhraseExtractionSkill": return KeyPhraseExtractionSkill.DeserializeKeyPhraseExtractionSkill(element); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.cs index 74a4d6df0e7de..fda5442057a19 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkill.cs @@ -15,7 +15,7 @@ namespace Azure.Search.Documents.Indexes.Models /// /// Base type for skills. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include , , , , , , , , , , , , , , , , , and . + /// The available derived classes include , , , , , , , , , , , , , , , , , , and . /// public partial class SearchIndexerSkill { diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.Serialization.cs index 4f7049bb9a3b9..0fab9b6b4b48a 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.Serialization.cs @@ -40,6 +40,11 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("knowledgeStore"u8); writer.WriteObjectValue(KnowledgeStore); } + if (Optional.IsDefined(IndexProjections)) + { + writer.WritePropertyName("indexProjections"u8); + writer.WriteObjectValue(IndexProjections); + } if (Optional.IsDefined(_etag)) { writer.WritePropertyName("@odata.etag"u8); @@ -71,6 +76,7 @@ internal static SearchIndexerSkillset DeserializeSearchIndexerSkillset(JsonEleme IList skills = default; Optional cognitiveServices = default; Optional knowledgeStore = default; + Optional indexProjections = default; Optional odataEtag = default; Optional encryptionKey = default; foreach (var property in element.EnumerateObject()) @@ -113,6 +119,15 @@ internal static SearchIndexerSkillset DeserializeSearchIndexerSkillset(JsonEleme knowledgeStore = KnowledgeStore.DeserializeKnowledgeStore(property.Value); continue; } + if (property.NameEquals("indexProjections"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + indexProjections = SearchIndexerIndexProjections.DeserializeSearchIndexerIndexProjections(property.Value); + continue; + } if (property.NameEquals("@odata.etag"u8)) { odataEtag = property.Value.GetString(); @@ -129,7 +144,7 @@ internal static SearchIndexerSkillset DeserializeSearchIndexerSkillset(JsonEleme continue; } } - return new SearchIndexerSkillset(name, description.Value, skills, cognitiveServices.Value, knowledgeStore.Value, odataEtag.Value, encryptionKey.Value); + return new SearchIndexerSkillset(name, description.Value, skills, cognitiveServices.Value, knowledgeStore.Value, indexProjections.Value, odataEtag.Value, encryptionKey.Value); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.cs index 8c480b1945452..18f36c4d9153b 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchIndexerSkillset.cs @@ -20,7 +20,7 @@ public partial class SearchIndexerSkillset /// /// A list of skills in the skillset. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include , , , , , , , , , , , , , , , , , and . + /// The available derived classes include , , , , , , , , , , , , , , , , , , and . /// /// or is null. public SearchIndexerSkillset(string name, IEnumerable skills) @@ -38,7 +38,7 @@ public SearchIndexerSkillset(string name, IEnumerable skills /// /// A list of skills in the skillset. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include , , , , , , , , , , , , , , , , , and . + /// The available derived classes include , , , , , , , , , , , , , , , , , , and . /// /// /// Details about cognitive services to be used when running skills. @@ -46,15 +46,17 @@ public SearchIndexerSkillset(string name, IEnumerable skills /// The available derived classes include and . /// /// Definition of additional projections to azure blob, table, or files, of enriched data. + /// Definition of additional projections to secondary search index(es). /// The ETag of the skillset. /// A description of an encryption key that you create in Azure Key Vault. This key is used to provide an additional level of encryption-at-rest for your skillset definition when you want full assurance that no one, not even Microsoft, can decrypt your skillset definition in Azure Cognitive Search. Once you have encrypted your skillset definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you want to rotate your encryption key; Your skillset definition will be unaffected. Encryption with customer-managed keys is not available for free search services, and is only available for paid services created on or after January 1, 2019. - internal SearchIndexerSkillset(string name, string description, IList skills, CognitiveServicesAccount cognitiveServicesAccount, KnowledgeStore knowledgeStore, string etag, SearchResourceEncryptionKey encryptionKey) + internal SearchIndexerSkillset(string name, string description, IList skills, CognitiveServicesAccount cognitiveServicesAccount, KnowledgeStore knowledgeStore, SearchIndexerIndexProjections indexProjections, string etag, SearchResourceEncryptionKey encryptionKey) { Name = name; Description = description; Skills = skills; CognitiveServicesAccount = cognitiveServicesAccount; KnowledgeStore = knowledgeStore; + IndexProjections = indexProjections; _etag = etag; EncryptionKey = encryptionKey; } @@ -71,6 +73,8 @@ internal SearchIndexerSkillset(string name, string description, IList Definition of additional projections to azure blob, table, or files, of enriched data. public KnowledgeStore KnowledgeStore { get; set; } + /// Definition of additional projections to secondary search index(es). + public SearchIndexerIndexProjections IndexProjections { get; set; } /// A description of an encryption key that you create in Azure Key Vault. This key is used to provide an additional level of encryption-at-rest for your skillset definition when you want full assurance that no one, not even Microsoft, can decrypt your skillset definition in Azure Cognitive Search. Once you have encrypted your skillset definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set this property to null. You can change this property as needed if you want to rotate your encryption key; Your skillset definition will be unaffected. Encryption with customer-managed keys is not available for free search services, and is only available for paid services created on or after January 1, 2019. public SearchResourceEncryptionKey EncryptionKey { get; set; } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.Serialization.cs index 055b4ae7ef19d..9be2c0d887fbb 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.Serialization.cs @@ -92,6 +92,11 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("scoringProfile"u8); writer.WriteStringValue(ScoringProfile); } + if (Optional.IsDefined(SemanticQuery)) + { + writer.WritePropertyName("semanticQuery"u8); + writer.WriteStringValue(SemanticQuery); + } if (Optional.IsDefined(SemanticConfigurationName)) { writer.WritePropertyName("semanticConfiguration"u8); @@ -174,16 +179,21 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("semanticFields"u8); writer.WriteStringValue(SemanticFieldsRaw); } - if (Optional.IsCollectionDefined(Vectors)) + if (Optional.IsCollectionDefined(VectorQueries)) { - writer.WritePropertyName("vectors"u8); + writer.WritePropertyName("vectorQueries"u8); writer.WriteStartArray(); - foreach (var item in Vectors) + foreach (var item in VectorQueries) { writer.WriteObjectValue(item); } writer.WriteEndArray(); } + if (Optional.IsDefined(VectorFilterMode)) + { + writer.WritePropertyName("vectorFilterMode"u8); + writer.WriteStringValue(VectorFilterMode.Value.ToString()); + } writer.WriteEndObject(); } @@ -206,6 +216,7 @@ internal static SearchOptions DeserializeSearchOptions(JsonElement element) Optional sessionId = default; Optional> scoringParameters = default; Optional scoringProfile = default; + Optional semanticQuery = default; Optional semanticConfiguration = default; Optional semanticErrorHandling = default; Optional semanticMaxWaitInMilliseconds = default; @@ -221,7 +232,8 @@ internal static SearchOptions DeserializeSearchOptions(JsonElement element) Optional top = default; Optional captions = default; Optional semanticFields = default; - Optional> vectors = default; + Optional> vectorQueries = default; + Optional vectorFilterMode = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("count"u8)) @@ -323,6 +335,11 @@ internal static SearchOptions DeserializeSearchOptions(JsonElement element) scoringProfile = property.Value.GetString(); continue; } + if (property.NameEquals("semanticQuery"u8)) + { + semanticQuery = property.Value.GetString(); + continue; + } if (property.NameEquals("semanticConfiguration"u8)) { semanticConfiguration = property.Value.GetString(); @@ -431,22 +448,31 @@ internal static SearchOptions DeserializeSearchOptions(JsonElement element) semanticFields = property.Value.GetString(); continue; } - if (property.NameEquals("vectors"u8)) + if (property.NameEquals("vectorQueries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { continue; } - List array = new List(); + List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(SearchQueryVector.DeserializeSearchQueryVector(item)); + array.Add(VectorQuery.DeserializeVectorQuery(item)); + } + vectorQueries = array; + continue; + } + if (property.NameEquals("vectorFilterMode"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; } - vectors = array; + vectorFilterMode = new VectorFilterMode(property.Value.GetString()); continue; } } - return new SearchOptions(Optional.ToNullable(count), Optional.ToList(facets), filter.Value, highlight.Value, highlightPostTag.Value, highlightPreTag.Value, Optional.ToNullable(minimumCoverage), orderby.Value, Optional.ToNullable(queryType), Optional.ToNullable(scoringStatistics), sessionId.Value, Optional.ToList(scoringParameters), scoringProfile.Value, semanticConfiguration.Value, Optional.ToNullable(semanticErrorHandling), Optional.ToNullable(semanticMaxWaitInMilliseconds), Optional.ToNullable(debug), search.Value, searchFields.Value, Optional.ToNullable(searchMode), Optional.ToNullable(queryLanguage), Optional.ToNullable(speller), answers.Value, select.Value, Optional.ToNullable(skip), Optional.ToNullable(top), captions.Value, semanticFields.Value, Optional.ToList(vectors)); + return new SearchOptions(Optional.ToNullable(count), Optional.ToList(facets), filter.Value, highlight.Value, highlightPostTag.Value, highlightPreTag.Value, Optional.ToNullable(minimumCoverage), orderby.Value, Optional.ToNullable(queryType), Optional.ToNullable(scoringStatistics), sessionId.Value, Optional.ToList(scoringParameters), scoringProfile.Value, semanticQuery.Value, semanticConfiguration.Value, Optional.ToNullable(semanticErrorHandling), Optional.ToNullable(semanticMaxWaitInMilliseconds), Optional.ToNullable(debug), search.Value, searchFields.Value, Optional.ToNullable(searchMode), Optional.ToNullable(queryLanguage), Optional.ToNullable(speller), answers.Value, select.Value, Optional.ToNullable(skip), Optional.ToNullable(top), captions.Value, semanticFields.Value, Optional.ToList(vectorQueries), Optional.ToNullable(vectorFilterMode)); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.cs index ea220cb371eb5..8dcaef2dc8153 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchOptions.cs @@ -19,7 +19,7 @@ public SearchOptions() { Facets = new ChangeTrackingList(); ScoringParameters = new ChangeTrackingList(); - Vectors = new ChangeTrackingList(); + VectorQueries = new ChangeTrackingList(); } /// Initializes a new instance of SearchOptions. @@ -36,8 +36,9 @@ public SearchOptions() /// A value to be used to create a sticky session, which can help getting more consistent results. As long as the same sessionId is used, a best-effort attempt will be made to target the same replica set. Be wary that reusing the same sessionID values repeatedly can interfere with the load balancing of the requests across replicas and adversely affect the performance of the search service. The value used as sessionId cannot start with a '_' character. /// The list of parameter values to be used in scoring functions (for example, referencePointParameter) using the format name-values. For example, if the scoring profile defines a function with a parameter called 'mylocation' the parameter string would be "mylocation--122.2,44.8" (without the quotes). /// The name of a scoring profile to evaluate match scores for matching documents in order to sort the results. + /// Allows setting a separate search query that will be solely used for semantic reranking, semantic captions and semantic answers. Is useful for scenarios where there is a need to use different queries between the base retrieval and ranking phase, and the L2 semantic phase. /// The name of a semantic configuration that will be used when processing documents for queries of type semantic. - /// Allows the user to choose whether a semantic call should fail completely (default / current behavior), or to return partial results. + /// Allows the user to choose whether a semantic call should fail completely, or to return partial results (default). /// Allows the user to set an upper bound on the amount of time it takes for semantic enrichment to finish processing before the request fails. /// Enables a debugging tool that can be used to further explore your Semantic search results. /// A full-text search query expression; Use "*" or omit this parameter to match all documents. @@ -51,8 +52,13 @@ public SearchOptions() /// The number of search results to retrieve. This can be used in conjunction with $skip to implement client-side paging of search results. If results are truncated due to server-side paging, the response will include a continuation token that can be used to issue another Search request for the next page of results. /// A value that specifies whether captions should be returned as part of the search response. /// The comma-separated list of field names used for semantic search. - /// The query parameters for multi-vector search queries. - internal SearchOptions(bool? includeTotalCount, IList facets, string filter, string highlightFieldsRaw, string highlightPostTag, string highlightPreTag, double? minimumCoverage, string orderByRaw, SearchQueryType? queryType, ScoringStatistics? scoringStatistics, string sessionId, IList scoringParameters, string scoringProfile, string semanticConfigurationName, SemanticErrorHandling? semanticErrorHandling, int? semanticMaxWaitInMilliseconds, QueryDebugMode? debug, string searchText, string searchFieldsRaw, SearchMode? searchMode, QueryLanguage? queryLanguage, QuerySpellerType? querySpeller, string queryAnswerRaw, string selectRaw, int? skip, int? size, string queryCaptionRaw, string semanticFieldsRaw, IList vectors) + /// + /// The query parameters for vector and hybrid search queries. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + /// Determines whether or not filters are applied before or after the vector search is performed. Default is 'preFilter'. + internal SearchOptions(bool? includeTotalCount, IList facets, string filter, string highlightFieldsRaw, string highlightPostTag, string highlightPreTag, double? minimumCoverage, string orderByRaw, SearchQueryType? queryType, ScoringStatistics? scoringStatistics, string sessionId, IList scoringParameters, string scoringProfile, string semanticQuery, string semanticConfigurationName, SemanticErrorHandling? semanticErrorHandling, int? semanticMaxWaitInMilliseconds, QueryDebugMode? debug, string searchText, string searchFieldsRaw, SearchMode? searchMode, QueryLanguage? queryLanguage, QuerySpellerType? querySpeller, string queryAnswerRaw, string selectRaw, int? skip, int? size, string queryCaptionRaw, string semanticFieldsRaw, IList vectorQueries, VectorFilterMode? vectorFilterMode) { IncludeTotalCount = includeTotalCount; Facets = facets; @@ -67,6 +73,7 @@ internal SearchOptions(bool? includeTotalCount, IList facets, string fil SessionId = sessionId; ScoringParameters = scoringParameters; ScoringProfile = scoringProfile; + SemanticQuery = semanticQuery; SemanticConfigurationName = semanticConfigurationName; SemanticErrorHandling = semanticErrorHandling; SemanticMaxWaitInMilliseconds = semanticMaxWaitInMilliseconds; @@ -82,7 +89,8 @@ internal SearchOptions(bool? includeTotalCount, IList facets, string fil Size = size; QueryCaptionRaw = queryCaptionRaw; SemanticFieldsRaw = semanticFieldsRaw; - Vectors = vectors; + VectorQueries = vectorQueries; + VectorFilterMode = vectorFilterMode; } /// A string tag that is appended to hit highlights. Must be set with highlightPreTag. Default is </em>. public string HighlightPostTag { get; set; } @@ -98,7 +106,9 @@ internal SearchOptions(bool? includeTotalCount, IList facets, string fil public string SessionId { get; set; } /// The name of a scoring profile to evaluate match scores for matching documents in order to sort the results. public string ScoringProfile { get; set; } - /// Allows the user to choose whether a semantic call should fail completely (default / current behavior), or to return partial results. + /// Allows setting a separate search query that will be solely used for semantic reranking, semantic captions and semantic answers. Is useful for scenarios where there is a need to use different queries between the base retrieval and ranking phase, and the L2 semantic phase. + public string SemanticQuery { get; set; } + /// Allows the user to choose whether a semantic call should fail completely, or to return partial results (default). public SemanticErrorHandling? SemanticErrorHandling { get; set; } /// Allows the user to set an upper bound on the amount of time it takes for semantic enrichment to finish processing before the request fails. public int? SemanticMaxWaitInMilliseconds { get; set; } @@ -108,5 +118,7 @@ internal SearchOptions(bool? includeTotalCount, IList facets, string fil public SearchMode? SearchMode { get; set; } /// The number of search results to skip. This value cannot be greater than 100,000. If you need to scan documents in sequence, but cannot use skip due to this limitation, consider using orderby on a totally-ordered key and filter with a range query instead. public int? Skip { get; set; } + /// Determines whether or not filters are applied before or after the vector search is performed. Default is 'preFilter'. + public VectorFilterMode? VectorFilterMode { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.cs deleted file mode 100644 index 5ddd81d55716d..0000000000000 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// - -#nullable disable - -using System.Collections.Generic; -using Azure.Core; - -namespace Azure.Search.Documents.Models -{ - /// The query parameters for vector and hybrid search queries. - public partial class SearchQueryVector - { - /// Initializes a new instance of SearchQueryVector. - public SearchQueryVector() - { - Value = new ChangeTrackingList(); - } - - /// Initializes a new instance of SearchQueryVector. - /// The vector representation of a search query. - /// Number of nearest neighbors to return as top hits. - /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. - internal SearchQueryVector(IReadOnlyList value, int? kNearestNeighborsCount, string fieldsRaw) - { - Value = value; - KNearestNeighborsCount = kNearestNeighborsCount; - FieldsRaw = fieldsRaw; - } - /// Number of nearest neighbors to return as top hits. - public int? KNearestNeighborsCount { get; set; } - } -} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.Serialization.cs index 7a4a37b2e6743..c041927958fb2 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.Serialization.cs @@ -45,6 +45,30 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WriteNull("maximumPageLength"); } } + if (Optional.IsDefined(PageOverlapLength)) + { + if (PageOverlapLength != null) + { + writer.WritePropertyName("pageOverlapLength"u8); + writer.WriteNumberValue(PageOverlapLength.Value); + } + else + { + writer.WriteNull("pageOverlapLength"); + } + } + if (Optional.IsDefined(MaximumPagesToTake)) + { + if (MaximumPagesToTake != null) + { + writer.WritePropertyName("maximumPagesToTake"u8); + writer.WriteNumberValue(MaximumPagesToTake.Value); + } + else + { + writer.WriteNull("maximumPagesToTake"); + } + } writer.WritePropertyName("@odata.type"u8); writer.WriteStringValue(ODataType); if (Optional.IsDefined(Name)) @@ -88,6 +112,8 @@ internal static SplitSkill DeserializeSplitSkill(JsonElement element) Optional defaultLanguageCode = default; Optional textSplitMode = default; Optional maximumPageLength = default; + Optional pageOverlapLength = default; + Optional maximumPagesToTake = default; string odataType = default; Optional name = default; Optional description = default; @@ -125,6 +151,26 @@ internal static SplitSkill DeserializeSplitSkill(JsonElement element) maximumPageLength = property.Value.GetInt32(); continue; } + if (property.NameEquals("pageOverlapLength"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + pageOverlapLength = null; + continue; + } + pageOverlapLength = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("maximumPagesToTake"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + maximumPagesToTake = null; + continue; + } + maximumPagesToTake = property.Value.GetInt32(); + continue; + } if (property.NameEquals("@odata.type"u8)) { odataType = property.Value.GetString(); @@ -166,7 +212,7 @@ internal static SplitSkill DeserializeSplitSkill(JsonElement element) continue; } } - return new SplitSkill(odataType, name.Value, description.Value, context.Value, inputs, outputs, Optional.ToNullable(defaultLanguageCode), Optional.ToNullable(textSplitMode), Optional.ToNullable(maximumPageLength)); + return new SplitSkill(odataType, name.Value, description.Value, context.Value, inputs, outputs, Optional.ToNullable(defaultLanguageCode), Optional.ToNullable(textSplitMode), Optional.ToNullable(maximumPageLength), Optional.ToNullable(pageOverlapLength), Optional.ToNullable(maximumPagesToTake)); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.cs index a745d6fb34b7a..d45130ff5768e 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/SplitSkill.cs @@ -36,11 +36,15 @@ public SplitSkill(IEnumerable inputs, IEnumerable A value indicating which language code to use. Default is en. /// A value indicating which split mode to perform. /// The desired maximum page length. Default is 10000. - internal SplitSkill(string oDataType, string name, string description, string context, IList inputs, IList outputs, SplitSkillLanguage? defaultLanguageCode, TextSplitMode? textSplitMode, int? maximumPageLength) : base(oDataType, name, description, context, inputs, outputs) + /// Only applicable when textSplitMode is set to 'pages'. If specified, n+1th chunk will start with this number of characters/tokens from the end of the nth chunk. + /// Only applicable when textSplitMode is set to 'pages'. If specified, the SplitSkill will discontinue splitting after processing the first 'maximumPagesToTake' pages, in order to improve performance when only a few initial pages are needed from each document. + internal SplitSkill(string oDataType, string name, string description, string context, IList inputs, IList outputs, SplitSkillLanguage? defaultLanguageCode, TextSplitMode? textSplitMode, int? maximumPageLength, int? pageOverlapLength, int? maximumPagesToTake) : base(oDataType, name, description, context, inputs, outputs) { DefaultLanguageCode = defaultLanguageCode; TextSplitMode = textSplitMode; MaximumPageLength = maximumPageLength; + PageOverlapLength = pageOverlapLength; + MaximumPagesToTake = maximumPagesToTake; ODataType = oDataType ?? "#Microsoft.Skills.Text.SplitSkill"; } @@ -50,5 +54,9 @@ internal SplitSkill(string oDataType, string name, string description, string co public TextSplitMode? TextSplitMode { get; set; } /// The desired maximum page length. Default is 10000. public int? MaximumPageLength { get; set; } + /// Only applicable when textSplitMode is set to 'pages'. If specified, n+1th chunk will start with this number of characters/tokens from the end of the nth chunk. + public int? PageOverlapLength { get; set; } + /// Only applicable when textSplitMode is set to 'pages'. If specified, the SplitSkill will discontinue splitting after processing the first 'maximumPagesToTake' pages, in order to improve performance when only a few initial pages are needed from each document. + public int? MaximumPagesToTake { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.Serialization.cs similarity index 66% rename from sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.Serialization.cs rename to sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.Serialization.cs index 1391bb06b0a3e..e9d768008b03f 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/SearchQueryVector.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.Serialization.cs @@ -5,27 +5,18 @@ #nullable disable -using System.Collections.Generic; using System.Text.Json; using Azure.Core; namespace Azure.Search.Documents.Models { - public partial class SearchQueryVector : IUtf8JsonSerializable + internal partial class UnknownVectorQuery : IUtf8JsonSerializable { void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) { writer.WriteStartObject(); - if (Optional.IsCollectionDefined(Value)) - { - writer.WritePropertyName("value"u8); - writer.WriteStartArray(); - foreach (var item in Value) - { - writer.WriteNumberValue(item); - } - writer.WriteEndArray(); - } + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); if (Optional.IsDefined(KNearestNeighborsCount)) { writer.WritePropertyName("k"u8); @@ -36,32 +27,29 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("fields"u8); writer.WriteStringValue(FieldsRaw); } + if (Optional.IsDefined(Exhaustive)) + { + writer.WritePropertyName("exhaustive"u8); + writer.WriteBooleanValue(Exhaustive.Value); + } writer.WriteEndObject(); } - internal static SearchQueryVector DeserializeSearchQueryVector(JsonElement element) + internal static UnknownVectorQuery DeserializeUnknownVectorQuery(JsonElement element) { if (element.ValueKind == JsonValueKind.Null) { return null; } - Optional> value = default; + VectorQueryKind kind = "Unknown"; Optional k = default; Optional fields = default; + Optional exhaustive = default; foreach (var property in element.EnumerateObject()) { - if (property.NameEquals("value"u8)) + if (property.NameEquals("kind"u8)) { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(item.GetSingle()); - } - value = array; + kind = new VectorQueryKind(property.Value.GetString()); continue; } if (property.NameEquals("k"u8)) @@ -78,8 +66,17 @@ internal static SearchQueryVector DeserializeSearchQueryVector(JsonElement eleme fields = property.Value.GetString(); continue; } + if (property.NameEquals("exhaustive"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + exhaustive = property.Value.GetBoolean(); + continue; + } } - return new SearchQueryVector(Optional.ToList(value), Optional.ToNullable(k), fields.Value); + return new UnknownVectorQuery(kind, Optional.ToNullable(k), fields.Value, Optional.ToNullable(exhaustive)); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.cs new file mode 100644 index 0000000000000..4c9c12547715c --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorQuery.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Search.Documents.Models +{ + /// The UnknownVectorQuery. + internal partial class UnknownVectorQuery : VectorQuery + { + /// Initializes a new instance of UnknownVectorQuery. + /// The kind of vector query being performed. + /// Number of nearest neighbors to return as top hits. + /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. + /// When true, triggers an exhaustive k-nearest neighbor search across all vectors within the vector index. Useful for scenarios where exact matches are critical, such as determining ground truth values. + internal UnknownVectorQuery(VectorQueryKind kind, int? kNearestNeighborsCount, string fieldsRaw, bool? exhaustive) : base(kind, kNearestNeighborsCount, fieldsRaw, exhaustive) + { + Kind = kind; + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.Serialization.cs index fe8756a47ad1f..13be5e6a0c432 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.Serialization.cs @@ -7,6 +7,7 @@ using System.Text.Json; using Azure.Core; +using Azure.Search.Documents.Indexes.Models; namespace Azure.Search.Documents.Models { @@ -18,7 +19,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("name"u8); writer.WriteStringValue(Name); writer.WritePropertyName("kind"u8); - writer.WriteStringValue(Kind); + writer.WriteStringValue(Kind.ToString()); writer.WriteEndObject(); } @@ -29,7 +30,7 @@ internal static UnknownVectorSearchAlgorithmConfiguration DeserializeUnknownVect return null; } string name = default; - string kind = "Unknown"; + VectorSearchAlgorithmKind kind = "Unknown"; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("name"u8)) @@ -39,7 +40,7 @@ internal static UnknownVectorSearchAlgorithmConfiguration DeserializeUnknownVect } if (property.NameEquals("kind"u8)) { - kind = property.Value.GetString(); + kind = new VectorSearchAlgorithmKind(property.Value.GetString()); continue; } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.cs index 0d8eb91895adc..913875bc6e237 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchAlgorithmConfiguration.cs @@ -14,10 +14,10 @@ internal partial class UnknownVectorSearchAlgorithmConfiguration : VectorSearchA { /// Initializes a new instance of UnknownVectorSearchAlgorithmConfiguration. /// The name to associate with this particular configuration. - /// The name of the kind of algorithm being configured for use with vector search. Only `hnsw` is supported in the current preview. - internal UnknownVectorSearchAlgorithmConfiguration(string name, string kind) : base(name, kind) + /// The name of the kind of algorithm being configured for use with vector search. + internal UnknownVectorSearchAlgorithmConfiguration(string name, VectorSearchAlgorithmKind kind) : base(name, kind) { - Kind = kind ?? "Unknown"; + Kind = kind; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.Serialization.cs new file mode 100644 index 0000000000000..5baccdc4a5fc0 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.Serialization.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; +using Azure.Search.Documents.Indexes.Models; + +namespace Azure.Search.Documents.Models +{ + internal partial class UnknownVectorSearchVectorizer : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + writer.WriteEndObject(); + } + + internal static UnknownVectorSearchVectorizer DeserializeUnknownVectorSearchVectorizer(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + VectorSearchVectorizerKind kind = "Unknown"; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorSearchVectorizerKind(property.Value.GetString()); + continue; + } + } + return new UnknownVectorSearchVectorizer(name, kind); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.cs new file mode 100644 index 0000000000000..d1af52532439e --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/UnknownVectorSearchVectorizer.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using Azure.Search.Documents.Indexes.Models; + +namespace Azure.Search.Documents.Models +{ + /// The UnknownVectorSearchVectorizer. + internal partial class UnknownVectorSearchVectorizer : VectorSearchVectorizer + { + /// Initializes a new instance of UnknownVectorSearchVectorizer. + /// The name to associate with this particular vectorization method. + /// The name of the kind of vectorization method being configured for use with vector search. + internal UnknownVectorSearchVectorizer(string name, VectorSearchVectorizerKind kind) : base(name, kind) + { + Kind = kind; + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorFilterMode.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorFilterMode.cs new file mode 100644 index 0000000000000..4f2b90efbe888 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorFilterMode.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Search.Documents.Models +{ + /// Determines whether or not filters are applied before or after the vector search is performed. + public readonly partial struct VectorFilterMode : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public VectorFilterMode(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string PostFilterValue = "postFilter"; + private const string PreFilterValue = "preFilter"; + + /// The filter will be applied after the candidate set of vector results is returned. Depending on the filter selectivity, this can result in fewer results than requested by the parameter 'k'. + public static VectorFilterMode PostFilter { get; } = new VectorFilterMode(PostFilterValue); + /// The filter will be applied before the search query. + public static VectorFilterMode PreFilter { get; } = new VectorFilterMode(PreFilterValue); + /// Determines if two values are the same. + public static bool operator ==(VectorFilterMode left, VectorFilterMode right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(VectorFilterMode left, VectorFilterMode right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator VectorFilterMode(string value) => new VectorFilterMode(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is VectorFilterMode other && Equals(other); + /// + public bool Equals(VectorFilterMode other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.Serialization.cs new file mode 100644 index 0000000000000..ec7e8120fe452 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.Serialization.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + public partial class VectorQuery : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + if (Optional.IsDefined(KNearestNeighborsCount)) + { + writer.WritePropertyName("k"u8); + writer.WriteNumberValue(KNearestNeighborsCount.Value); + } + if (Optional.IsDefined(FieldsRaw)) + { + writer.WritePropertyName("fields"u8); + writer.WriteStringValue(FieldsRaw); + } + if (Optional.IsDefined(Exhaustive)) + { + writer.WritePropertyName("exhaustive"u8); + writer.WriteBooleanValue(Exhaustive.Value); + } + writer.WriteEndObject(); + } + + internal static VectorQuery DeserializeVectorQuery(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + if (element.TryGetProperty("kind", out JsonElement discriminator)) + { + switch (discriminator.GetString()) + { + case "text": return VectorizableTextQuery.DeserializeVectorizableTextQuery(element); + case "vector": return RawVectorQuery.DeserializeRawVectorQuery(element); + } + } + return UnknownVectorQuery.DeserializeUnknownVectorQuery(element); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.cs new file mode 100644 index 0000000000000..292f670b6ef75 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQuery.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Search.Documents.Models +{ + /// + /// The query parameters for vector and hybrid search queries. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public abstract partial class VectorQuery + { + /// Initializes a new instance of VectorQuery. + protected VectorQuery() + { + } + + /// Initializes a new instance of VectorQuery. + /// The kind of vector query being performed. + /// Number of nearest neighbors to return as top hits. + /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. + /// When true, triggers an exhaustive k-nearest neighbor search across all vectors within the vector index. Useful for scenarios where exact matches are critical, such as determining ground truth values. + internal VectorQuery(VectorQueryKind kind, int? kNearestNeighborsCount, string fieldsRaw, bool? exhaustive) + { + Kind = kind; + KNearestNeighborsCount = kNearestNeighborsCount; + FieldsRaw = fieldsRaw; + Exhaustive = exhaustive; + } + + /// The kind of vector query being performed. + internal VectorQueryKind Kind { get; set; } + /// Number of nearest neighbors to return as top hits. + public int? KNearestNeighborsCount { get; set; } + /// When true, triggers an exhaustive k-nearest neighbor search across all vectors within the vector index. Useful for scenarios where exact matches are critical, such as determining ground truth values. + public bool? Exhaustive { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQueryKind.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQueryKind.cs new file mode 100644 index 0000000000000..8eb67f2cd6e01 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorQueryKind.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Search.Documents.Models +{ + /// The kind of vector query being performed. + public readonly partial struct VectorQueryKind : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public VectorQueryKind(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string VectorValue = "vector"; + private const string TextValue = "text"; + + /// Vector query where a raw vector value is provided. + public static VectorQueryKind Vector { get; } = new VectorQueryKind(VectorValue); + /// Vector query where a text value that needs to be vectorized is provided. + public static VectorQueryKind Text { get; } = new VectorQueryKind(TextValue); + /// Determines if two values are the same. + public static bool operator ==(VectorQueryKind left, VectorQueryKind right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(VectorQueryKind left, VectorQueryKind right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator VectorQueryKind(string value) => new VectorQueryKind(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is VectorQueryKind other && Equals(other); + /// + public bool Equals(VectorQueryKind other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.Serialization.cs index 12cb1ad0ffd08..e44ece97a0e5d 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.Serialization.cs @@ -16,11 +16,31 @@ public partial class VectorSearch : IUtf8JsonSerializable void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) { writer.WriteStartObject(); - if (Optional.IsCollectionDefined(AlgorithmConfigurations)) + if (Optional.IsCollectionDefined(Profiles)) { - writer.WritePropertyName("algorithmConfigurations"u8); + writer.WritePropertyName("profiles"u8); writer.WriteStartArray(); - foreach (var item in AlgorithmConfigurations) + foreach (var item in Profiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(Algorithms)) + { + writer.WritePropertyName("algorithms"u8); + writer.WriteStartArray(); + foreach (var item in Algorithms) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(Vectorizers)) + { + writer.WritePropertyName("vectorizers"u8); + writer.WriteStartArray(); + foreach (var item in Vectorizers) { writer.WriteObjectValue(item); } @@ -35,10 +55,26 @@ internal static VectorSearch DeserializeVectorSearch(JsonElement element) { return null; } - Optional> algorithmConfigurations = default; + Optional> profiles = default; + Optional> algorithms = default; + Optional> vectorizers = default; foreach (var property in element.EnumerateObject()) { - if (property.NameEquals("algorithmConfigurations"u8)) + if (property.NameEquals("profiles"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(VectorSearchProfile.DeserializeVectorSearchProfile(item)); + } + profiles = array; + continue; + } + if (property.NameEquals("algorithms"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { @@ -49,11 +85,25 @@ internal static VectorSearch DeserializeVectorSearch(JsonElement element) { array.Add(VectorSearchAlgorithmConfiguration.DeserializeVectorSearchAlgorithmConfiguration(item)); } - algorithmConfigurations = array; + algorithms = array; + continue; + } + if (property.NameEquals("vectorizers"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(VectorSearchVectorizer.DeserializeVectorSearchVectorizer(item)); + } + vectorizers = array; continue; } } - return new VectorSearch(Optional.ToList(algorithmConfigurations)); + return new VectorSearch(Optional.ToList(profiles), Optional.ToList(algorithms), Optional.ToList(vectorizers)); } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.cs index 9b51c1b97a8bf..40f70e4024f38 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearch.cs @@ -16,25 +16,43 @@ public partial class VectorSearch /// Initializes a new instance of VectorSearch. public VectorSearch() { - AlgorithmConfigurations = new ChangeTrackingList(); + Profiles = new ChangeTrackingList(); + Algorithms = new ChangeTrackingList(); + Vectorizers = new ChangeTrackingList(); } /// Initializes a new instance of VectorSearch. - /// - /// Contains configuration options specific to the algorithm used during indexing time. + /// Defines combinations of configurations to use with vector search. + /// + /// Contains configuration options specific to the algorithm used during indexing and/or querying. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . /// - internal VectorSearch(IList algorithmConfigurations) + /// + /// Contains configuration options on how to vectorize text vector queries. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + internal VectorSearch(IList profiles, IList algorithms, IList vectorizers) { - AlgorithmConfigurations = algorithmConfigurations; + Profiles = profiles; + Algorithms = algorithms; + Vectorizers = vectorizers; } + /// Defines combinations of configurations to use with vector search. + public IList Profiles { get; } /// - /// Contains configuration options specific to the algorithm used during indexing time. + /// Contains configuration options specific to the algorithm used during indexing and/or querying. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . + /// + public IList Algorithms { get; } + /// + /// Contains configuration options on how to vectorize text vector queries. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . /// - public IList AlgorithmConfigurations { get; } + public IList Vectorizers { get; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.Serialization.cs index 66111f010beb3..5c26ebac06bae 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.Serialization.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.Serialization.cs @@ -19,7 +19,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) writer.WritePropertyName("name"u8); writer.WriteStringValue(Name); writer.WritePropertyName("kind"u8); - writer.WriteStringValue(Kind); + writer.WriteStringValue(Kind.ToString()); writer.WriteEndObject(); } @@ -33,6 +33,7 @@ internal static VectorSearchAlgorithmConfiguration DeserializeVectorSearchAlgori { switch (discriminator.GetString()) { + case "exhaustiveKnn": return ExhaustiveKnnVectorSearchAlgorithmConfiguration.DeserializeExhaustiveKnnVectorSearchAlgorithmConfiguration(element); case "hnsw": return HnswVectorSearchAlgorithmConfiguration.DeserializeHnswVectorSearchAlgorithmConfiguration(element); } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.cs index 053b3b97912df..cb8de30164da0 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmConfiguration.cs @@ -11,9 +11,9 @@ namespace Azure.Search.Documents.Indexes.Models { /// - /// Contains configuration options specific to the algorithm used during indexing time. + /// Contains configuration options specific to the algorithm used during indexing and/or querying. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include . + /// The available derived classes include and . /// public abstract partial class VectorSearchAlgorithmConfiguration { @@ -29,8 +29,8 @@ protected VectorSearchAlgorithmConfiguration(string name) /// Initializes a new instance of VectorSearchAlgorithmConfiguration. /// The name to associate with this particular configuration. - /// The name of the kind of algorithm being configured for use with vector search. Only `hnsw` is supported in the current preview. - internal VectorSearchAlgorithmConfiguration(string name, string kind) + /// The name of the kind of algorithm being configured for use with vector search. + internal VectorSearchAlgorithmConfiguration(string name, VectorSearchAlgorithmKind kind) { Name = name; Kind = kind; @@ -38,7 +38,7 @@ internal VectorSearchAlgorithmConfiguration(string name, string kind) /// The name to associate with this particular configuration. public string Name { get; set; } - /// The name of the kind of algorithm being configured for use with vector search. Only `hnsw` is supported in the current preview. - internal string Kind { get; set; } + /// The name of the kind of algorithm being configured for use with vector search. + internal VectorSearchAlgorithmKind Kind { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmKind.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmKind.cs new file mode 100644 index 0000000000000..c12d23f8499f7 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchAlgorithmKind.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// The algorithm used for indexing and querying. + public readonly partial struct VectorSearchAlgorithmKind : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public VectorSearchAlgorithmKind(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string HnswValue = "hnsw"; + private const string ExhaustiveKnnValue = "exhaustiveKnn"; + + /// Hnsw (Hierarchical Navigable Small World), a type of approximate nearest neighbors algorithm. + public static VectorSearchAlgorithmKind Hnsw { get; } = new VectorSearchAlgorithmKind(HnswValue); + /// Exhaustive KNN algorithm which will perform brute-force search. + public static VectorSearchAlgorithmKind ExhaustiveKnn { get; } = new VectorSearchAlgorithmKind(ExhaustiveKnnValue); + /// Determines if two values are the same. + public static bool operator ==(VectorSearchAlgorithmKind left, VectorSearchAlgorithmKind right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(VectorSearchAlgorithmKind left, VectorSearchAlgorithmKind right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator VectorSearchAlgorithmKind(string value) => new VectorSearchAlgorithmKind(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is VectorSearchAlgorithmKind other && Equals(other); + /// + public bool Equals(VectorSearchAlgorithmKind other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.Serialization.cs new file mode 100644 index 0000000000000..6ed4865781569 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.Serialization.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class VectorSearchProfile : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("algorithm"u8); + writer.WriteStringValue(Algorithm); + if (Optional.IsDefined(Vectorizer)) + { + writer.WritePropertyName("vectorizer"u8); + writer.WriteStringValue(Vectorizer); + } + writer.WriteEndObject(); + } + + internal static VectorSearchProfile DeserializeVectorSearchProfile(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + string algorithm = default; + Optional vectorizer = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("algorithm"u8)) + { + algorithm = property.Value.GetString(); + continue; + } + if (property.NameEquals("vectorizer"u8)) + { + vectorizer = property.Value.GetString(); + continue; + } + } + return new VectorSearchProfile(name, algorithm, vectorizer.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.cs new file mode 100644 index 0000000000000..501d16e36e5d7 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchProfile.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// Defines a combination of configurations to use with vector search. + public partial class VectorSearchProfile + { + /// Initializes a new instance of VectorSearchProfile. + /// The name to associate with this particular vector search profile. + /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters. + /// or is null. + public VectorSearchProfile(string name, string algorithm) + { + Argument.AssertNotNull(name, nameof(name)); + Argument.AssertNotNull(algorithm, nameof(algorithm)); + + Name = name; + Algorithm = algorithm; + } + + /// Initializes a new instance of VectorSearchProfile. + /// The name to associate with this particular vector search profile. + /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters. + /// The name of the kind of vectorization method being configured for use with vector search. + internal VectorSearchProfile(string name, string algorithm, string vectorizer) + { + Name = name; + Algorithm = algorithm; + Vectorizer = vectorizer; + } + + /// The name to associate with this particular vector search profile. + public string Name { get; set; } + /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters. + public string Algorithm { get; set; } + /// The name of the kind of vectorization method being configured for use with vector search. + public string Vectorizer { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.Serialization.cs new file mode 100644 index 0000000000000..594d2d492028a --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.Serialization.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; +using Azure.Search.Documents.Models; + +namespace Azure.Search.Documents.Indexes.Models +{ + public partial class VectorSearchVectorizer : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + writer.WriteEndObject(); + } + + internal static VectorSearchVectorizer DeserializeVectorSearchVectorizer(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + if (element.TryGetProperty("kind", out JsonElement discriminator)) + { + switch (discriminator.GetString()) + { + case "azureOpenAI": return AzureOpenAIVectorizer.DeserializeAzureOpenAIVectorizer(element); + case "customWebApi": return CustomVectorizer.DeserializeCustomVectorizer(element); + } + } + return UnknownVectorSearchVectorizer.DeserializeUnknownVectorSearchVectorizer(element); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.cs new file mode 100644 index 0000000000000..2905d0d2ae7a5 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizer.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// + /// Contains specific details for a vectorization method to be used during query time. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public abstract partial class VectorSearchVectorizer + { + /// Initializes a new instance of VectorSearchVectorizer. + /// The name to associate with this particular vectorization method. + /// is null. + protected VectorSearchVectorizer(string name) + { + Argument.AssertNotNull(name, nameof(name)); + + Name = name; + } + + /// Initializes a new instance of VectorSearchVectorizer. + /// The name to associate with this particular vectorization method. + /// The name of the kind of vectorization method being configured for use with vector search. + internal VectorSearchVectorizer(string name, VectorSearchVectorizerKind kind) + { + Name = name; + Kind = kind; + } + + /// The name to associate with this particular vectorization method. + public string Name { get; set; } + /// The name of the kind of vectorization method being configured for use with vector search. + internal VectorSearchVectorizerKind Kind { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizerKind.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizerKind.cs new file mode 100644 index 0000000000000..32873ccfea0e4 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorSearchVectorizerKind.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Search.Documents.Indexes.Models +{ + /// The vectorization method to be used during query time. + public readonly partial struct VectorSearchVectorizerKind : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public VectorSearchVectorizerKind(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AzureOpenAIValue = "azureOpenAI"; + private const string CustomWebApiValue = "customWebApi"; + + /// Generate embeddings using an Azure Open AI service at query time. + public static VectorSearchVectorizerKind AzureOpenAI { get; } = new VectorSearchVectorizerKind(AzureOpenAIValue); + /// Generate embeddings using a custom web endpoint at query time. + public static VectorSearchVectorizerKind CustomWebApi { get; } = new VectorSearchVectorizerKind(CustomWebApiValue); + /// Determines if two values are the same. + public static bool operator ==(VectorSearchVectorizerKind left, VectorSearchVectorizerKind right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(VectorSearchVectorizerKind left, VectorSearchVectorizerKind right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator VectorSearchVectorizerKind(string value) => new VectorSearchVectorizerKind(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is VectorSearchVectorizerKind other && Equals(other); + /// + public bool Equals(VectorSearchVectorizerKind other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.Serialization.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.Serialization.cs new file mode 100644 index 0000000000000..2065b71b19104 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.Serialization.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + public partial class VectorizableTextQuery : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Text)) + { + writer.WritePropertyName("text"u8); + writer.WriteStringValue(Text); + } + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind.ToString()); + if (Optional.IsDefined(KNearestNeighborsCount)) + { + writer.WritePropertyName("k"u8); + writer.WriteNumberValue(KNearestNeighborsCount.Value); + } + if (Optional.IsDefined(FieldsRaw)) + { + writer.WritePropertyName("fields"u8); + writer.WriteStringValue(FieldsRaw); + } + if (Optional.IsDefined(Exhaustive)) + { + writer.WritePropertyName("exhaustive"u8); + writer.WriteBooleanValue(Exhaustive.Value); + } + writer.WriteEndObject(); + } + + internal static VectorizableTextQuery DeserializeVectorizableTextQuery(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional text = default; + VectorQueryKind kind = default; + Optional k = default; + Optional fields = default; + Optional exhaustive = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + if (property.NameEquals("kind"u8)) + { + kind = new VectorQueryKind(property.Value.GetString()); + continue; + } + if (property.NameEquals("k"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + k = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("fields"u8)) + { + fields = property.Value.GetString(); + continue; + } + if (property.NameEquals("exhaustive"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + exhaustive = property.Value.GetBoolean(); + continue; + } + } + return new VectorizableTextQuery(kind, Optional.ToNullable(k), fields.Value, Optional.ToNullable(exhaustive), text.Value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.cs b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.cs new file mode 100644 index 0000000000000..535515c95c4f0 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Generated/Models/VectorizableTextQuery.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Search.Documents.Models +{ + /// The query parameters to use for vector search when a text value that needs to be vectorized is provided. + public partial class VectorizableTextQuery : VectorQuery + { + /// Initializes a new instance of VectorizableTextQuery. + public VectorizableTextQuery() + { + Kind = VectorQueryKind.Text; + } + + /// Initializes a new instance of VectorizableTextQuery. + /// The kind of vector query being performed. + /// Number of nearest neighbors to return as top hits. + /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. + /// When true, triggers an exhaustive k-nearest neighbor search across all vectors within the vector index. Useful for scenarios where exact matches are critical, such as determining ground truth values. + /// The text to be vectorized to perform a vector search query. + internal VectorizableTextQuery(VectorQueryKind kind, int? kNearestNeighborsCount, string fieldsRaw, bool? exhaustive, string text) : base(kind, kNearestNeighborsCount, fieldsRaw, exhaustive) + { + Text = text; + Kind = kind; + } + + /// The text to be vectorized to perform a vector search query. + public string Text { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Generated/SearchModelFactory.cs b/sdk/search/Azure.Search.Documents/src/Generated/SearchModelFactory.cs index e30d69e6a7783..02f2798fe1d16 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/SearchModelFactory.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/SearchModelFactory.cs @@ -133,7 +133,7 @@ public static IndexerExecutionResult IndexerExecutionResult(IndexerExecutionStat /// The amount of storage in bytes consumed by the index. /// The amount of memory in bytes consumed by vectors in the index. /// A new instance for mocking. - public static SearchIndexStatistics SearchIndexStatistics(long documentCount = default, long storageSize = default, long? vectorIndexSize = null) + public static SearchIndexStatistics SearchIndexStatistics(long documentCount = default, long storageSize = default, long vectorIndexSize = default) { return new SearchIndexStatistics(documentCount, storageSize, vectorIndexSize); } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/SearchServiceRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/SearchServiceRestClient.cs index 4972be8a4cb34..c1fbdae9670e3 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/SearchServiceRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/SearchServiceRestClient.cs @@ -33,7 +33,7 @@ internal partial class SearchServiceRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public SearchServiceRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public SearchServiceRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/SkillsetsRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/SkillsetsRestClient.cs index f80eaa7b51347..230d1a12ae341 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/SkillsetsRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/SkillsetsRestClient.cs @@ -34,7 +34,7 @@ internal partial class SkillsetsRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public SkillsetsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public SkillsetsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Generated/SynonymMapsRestClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/SynonymMapsRestClient.cs index 0a70149d99810..6792974e47733 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/SynonymMapsRestClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/SynonymMapsRestClient.cs @@ -33,7 +33,7 @@ internal partial class SynonymMapsRestClient /// The tracking ID sent with the request to help with debugging. /// Api Version. /// , , or is null. - public SynonymMapsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-07-01-Preview") + public SynonymMapsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, Guid? xMsClientRequestId = null, string apiVersion = "2023-10-01-Preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/search/Azure.Search.Documents/src/Indexes/SearchableFieldAttribute.cs b/sdk/search/Azure.Search.Documents/src/Indexes/SearchableFieldAttribute.cs index 3115c0043198d..634273afd9ece 100644 --- a/sdk/search/Azure.Search.Documents/src/Indexes/SearchableFieldAttribute.cs +++ b/sdk/search/Azure.Search.Documents/src/Indexes/SearchableFieldAttribute.cs @@ -43,7 +43,7 @@ public class SearchableFieldAttribute : SimpleFieldAttribute, ISearchFieldAttrib /// /// The name of the vector search algorithm configuration that specifies the algorithm and optional parameters for searching the vector field. /// - public string VectorSearchConfiguration { get; set; } + public string VectorSearchProfile { get; set; } /// /// Gets or sets a list of names of synonym maps to associate with this field. @@ -91,9 +91,9 @@ void ISearchFieldAttribute.SetField(SearchField field) field.VectorSearchDimensions = dimensions; } - if (VectorSearchConfiguration != null) + if (VectorSearchProfile != null) { - field.VectorSearchConfiguration = VectorSearchConfiguration; + field.VectorSearchProfile = VectorSearchProfile; } } } diff --git a/sdk/search/Azure.Search.Documents/src/Models/RawVectorQuery.cs b/sdk/search/Azure.Search.Documents/src/Models/RawVectorQuery.cs new file mode 100644 index 0000000000000..f7ba339a6a582 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Models/RawVectorQuery.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + /// The query parameters for vector and hybrid search queries. + public partial class RawVectorQuery : VectorQuery + { + /// The vector representation of a search query. + public IReadOnlyList Vector { get; set; } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Models/SearchModelFactory.cs b/sdk/search/Azure.Search.Documents/src/Models/SearchModelFactory.cs index 9d473276413c0..f89bad416db25 100644 --- a/sdk/search/Azure.Search.Documents/src/Models/SearchModelFactory.cs +++ b/sdk/search/Azure.Search.Documents/src/Models/SearchModelFactory.cs @@ -189,10 +189,11 @@ public static SearchIndexerWarning SearchIndexerWarning( /// The number of documents in the index. /// The amount of storage in bytes consumed by the index. /// A new SearchIndexStatistics instance for mocking. + [EditorBrowsable(EditorBrowsableState.Never)] public static SearchIndexStatistics SearchIndexStatistics( long documentCount, long storageSize) => - new SearchIndexStatistics(documentCount, storageSize); + new SearchIndexStatistics(documentCount, storageSize, vectorIndexSize: default); /// Initializes a new instance of SearchResourceCounter. /// The resource usage amount. diff --git a/sdk/search/Azure.Search.Documents/src/Models/SearchQueryVector.cs b/sdk/search/Azure.Search.Documents/src/Models/SearchQueryVector.cs deleted file mode 100644 index c76d382441a82..0000000000000 --- a/sdk/search/Azure.Search.Documents/src/Models/SearchQueryVector.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using Azure.Core; - -namespace Azure.Search.Documents.Models -{ - /// The query parameters for vector and hybrid search queries. - public partial class SearchQueryVector - { - /// The vector representation of a search query. - public IReadOnlyList Value { get; set; } - - /// - /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. - /// - public IList Fields { get; internal set; } = new List(); - - /// - /// Join Fields so it can be sent as a comma separated string. - /// - [CodeGenMember("Fields")] - internal string FieldsRaw - { - get => Fields.CommaJoin(); - set => Fields = SearchExtensions.CommaSplit(value); - } - } -} diff --git a/sdk/search/Azure.Search.Documents/src/Models/VectorQuery.cs b/sdk/search/Azure.Search.Documents/src/Models/VectorQuery.cs new file mode 100644 index 0000000000000..95307c1f5e7e7 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/src/Models/VectorQuery.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Search.Documents.Models +{ + /// + /// The query parameters for vector and hybrid search queries. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. + /// The available derived classes include and . + /// + public abstract partial class VectorQuery + { + /// Vector Fields of type Collection(Edm.Single) to be included in the vector searched. + public IList Fields { get; internal set; } = new List(); + + /// + /// Join Fields so it can be sent as a comma separated string. + /// + [CodeGenMember("Fields")] + internal string FieldsRaw + { + get => Fields.CommaJoin(); + set => Fields = SearchExtensions.CommaSplit(value); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/src/Options/SearchOptions.cs b/sdk/search/Azure.Search.Documents/src/Options/SearchOptions.cs index 6deebbe9ae7c4..36269f05f8171 100644 --- a/sdk/search/Azure.Search.Documents/src/Options/SearchOptions.cs +++ b/sdk/search/Azure.Search.Documents/src/Options/SearchOptions.cs @@ -328,7 +328,7 @@ internal string QueryCaptionRaw } /// The query parameters for multi-vector search queries. - public IList Vectors { get; internal set; } = new List(); + public IList VectorQueries { get; internal set; } = new List(); /// /// Shallow copy one SearchOptions instance to another. @@ -368,7 +368,7 @@ private static void Copy(SearchOptions source, SearchOptions destination) destination.SessionId = source.SessionId; destination.Size = source.Size; destination.Skip = source.Skip; - destination.Vectors = source.Vectors; + destination.VectorQueries = source.VectorQueries; } /// diff --git a/sdk/search/Azure.Search.Documents/src/SearchClientOptions.cs b/sdk/search/Azure.Search.Documents/src/SearchClientOptions.cs index 850f95cd93524..eedf2dcfd1b52 100644 --- a/sdk/search/Azure.Search.Documents/src/SearchClientOptions.cs +++ b/sdk/search/Azure.Search.Documents/src/SearchClientOptions.cs @@ -37,16 +37,16 @@ public enum ServiceVersion V2021_04_30_Preview = 2, /// - /// The 2023_07_01_Preview version of the Azure Cognitive Search service. + /// The 2023_10_01_Preview version of the Azure Cognitive Search service. /// - V2023_07_01_Preview = 3, + V2023_10_01_Preview = 3, #pragma warning restore CA1707 } /// /// The Latest service version supported by this client library. /// - internal const ServiceVersion LatestVersion = ServiceVersion.V2023_07_01_Preview; + internal const ServiceVersion LatestVersion = ServiceVersion.V2023_10_01_Preview; /// /// The service version to use when creating continuation tokens that @@ -200,7 +200,7 @@ public static SearchClientOptions.ServiceVersion Validate(this SearchClientOptio { SearchClientOptions.ServiceVersion.V2020_06_30 => version, SearchClientOptions.ServiceVersion.V2021_04_30_Preview => version, - SearchClientOptions.ServiceVersion.V2023_07_01_Preview => version, + SearchClientOptions.ServiceVersion.V2023_10_01_Preview => version, _ => throw CreateInvalidVersionException(version) }; @@ -224,7 +224,7 @@ public static string ToVersionString(this SearchClientOptions.ServiceVersion ver { SearchClientOptions.ServiceVersion.V2020_06_30 => "2020-06-30", SearchClientOptions.ServiceVersion.V2021_04_30_Preview => "2021-04-30-Preview", - SearchClientOptions.ServiceVersion.V2023_07_01_Preview => "2023-07-01-Preview", + SearchClientOptions.ServiceVersion.V2023_10_01_Preview => "2023-10-01-Preview", _ => throw CreateInvalidVersionException(version) }; diff --git a/sdk/search/Azure.Search.Documents/src/autorest.md b/sdk/search/Azure.Search.Documents/src/autorest.md index 63f9a78e9c231..871708384c3d9 100644 --- a/sdk/search/Azure.Search.Documents/src/autorest.md +++ b/sdk/search/Azure.Search.Documents/src/autorest.md @@ -11,8 +11,8 @@ See the [Contributing guidelines](https://github.com/Azure/azure-sdk-for-net/blo ```yaml title: SearchServiceClient input-file: - - https://github.com/Azure/azure-rest-api-specs/blob/9383e81389c2b1c64da07cc70c66f8c54b9ad4f5/specification/search/data-plane/Azure.Search/preview/2023-07-01-Preview/searchindex.json - - https://github.com/Azure/azure-rest-api-specs/blob/9383e81389c2b1c64da07cc70c66f8c54b9ad4f5/specification/search/data-plane/Azure.Search/preview/2023-07-01-Preview/searchservice.json + - https://github.com/Azure/azure-rest-api-specs/blob/b62ddd0ffb844fbfb688a04546800d60645a18ef/specification/search/data-plane/Azure.Search/preview/2023-10-01-Preview/searchindex.json + - https://github.com/Azure/azure-rest-api-specs/blob/b62ddd0ffb844fbfb688a04546800d60645a18ef/specification/search/data-plane/Azure.Search/preview/2023-10-01-Preview/searchservice.json generation1-convenience-client: true deserialize-null-collection-as-null-value: true ``` @@ -92,17 +92,6 @@ directive: transform: $["x-ms-client-name"] = "SearchServiceError" ``` -### Rename Vector definition - - It conflicts with https://learn.microsoft.com/dotnet/api/system.numerics.vector?view=net-7.0 which is likely to be used by customers integrating with other .NET AI libraries. - -``` yaml -directive: -- from: searchindex.json - where: $.definitions.Vector - transform: $["x-ms-client-name"] = "SearchQueryVector"; -``` - ### Rename Dimensions To ensure alignment with `VectorSearchConfiguration` in intellisense and documentation, rename the `Dimensions` to `VectorSearchDimensions`. @@ -125,14 +114,14 @@ directive: transform: $["x-ms-format"] = "arm-id"; ``` -### Rename Vector property `K` +### Rename VectorQuery property `K` - Rename Vector property `K` to `KNearestNeighborsCount` + Rename VectorQuery property `K` to `KNearestNeighborsCount` ```yaml directive: - from: searchindex.json - where: $.definitions.Vector.properties.k + where: $.definitions.VectorQuery.properties.k transform: $["x-ms-client-name"] = "KNearestNeighborsCount"; ``` @@ -147,17 +136,6 @@ directive: transform: $["x-ms-enum"].name = "SemanticFieldState"; ``` -### Remove `Vector` Property - - Remove the `Vector` Property from `SearchRequest` in favor of the `Vectors` Array - -```yaml -directive: -- from: searchindex.json - where: $.definitions.SearchRequest - transform: delete $.properties.vector; -``` - ### Rename one of SearchMode definitions SearchMode is duplicated across swaggers. Rename one of them, even though it will be internalized. diff --git a/sdk/search/Azure.Search.Documents/tests/DocumentOperations/VectorSearchTests.cs b/sdk/search/Azure.Search.Documents/tests/DocumentOperations/VectorSearchTests.cs index 5755332c0eda2..a691955a7c891 100644 --- a/sdk/search/Azure.Search.Documents/tests/DocumentOperations/VectorSearchTests.cs +++ b/sdk/search/Azure.Search.Documents/tests/DocumentOperations/VectorSearchTests.cs @@ -13,7 +13,7 @@ namespace Azure.Search.Documents.Tests { - [ClientTestFixture(SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ClientTestFixture(SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public partial class VectorSearchTests : SearchTestBase { public VectorSearchTests(bool async, SearchClientOptions.ServiceVersion serviceVersion) @@ -42,7 +42,7 @@ public async Task SingleVectorSearch() null, new SearchOptions { - Vectors = { new SearchQueryVector { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, + VectorQueries = { new RawVectorQuery { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, Select = { "hotelId", "hotelName" } }); @@ -63,7 +63,7 @@ public async Task SingleVectorSearchWithFilter() null, new SearchOptions { - Vectors = { new SearchQueryVector { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, + VectorQueries = { new RawVectorQuery { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, Filter = "category eq 'Budget'", Select = { "hotelId", "hotelName", "category" } }); @@ -85,7 +85,7 @@ public async Task SimpleHybridSearch() "Top hotels in town", new SearchOptions { - Vectors = { new SearchQueryVector { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, + VectorQueries = { new RawVectorQuery { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, Select = { "hotelId", "hotelName" }, }); @@ -107,7 +107,7 @@ public async Task SemanticHybridSearch() "Is there any hotel located on the main commercial artery of the city in the heart of New York?", new SearchOptions { - Vectors = { new SearchQueryVector { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, + VectorQueries = { new RawVectorQuery { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, Select = { "hotelId", "hotelName", "description", "category" }, QueryType = SearchQueryType.Semantic, QueryLanguage = QueryLanguage.EnUs, @@ -186,15 +186,19 @@ public async Task UpdateExistingIndexToAddVectorFields() { IsSearchable = true, VectorSearchDimensions = 1536, - VectorSearchConfiguration = "my-vector-config" + VectorSearchProfile = "my-vector-profile" }; createdIndex.Fields.Add(vectorField); createdIndex.VectorSearch = new() { - AlgorithmConfigurations = + Profiles = { - new HnswVectorSearchAlgorithmConfiguration( "my-vector-config") + new VectorSearchProfile("my-vector-profile", "my-hsnw-vector-config") + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration("my-hsnw-vector-config") } }; @@ -223,6 +227,11 @@ public async Task UpdateExistingIndexToAddVectorFields() Assert.AreEqual(updatedIndex.Name, createdIndex.Name); } + // TODO: Add tests for updating an index to modify the vectorizer within a profile. + // TODO: Add a test for duplicate profile names, which should throw an error. + // TODO: Add a test for updating the profile name of a vector field, which should throw an error. + // TODO: Add tests for VectorizableTextQuery + [Test] public async Task CreateIndexUsingFieldBuilder() { @@ -237,11 +246,15 @@ public async Task CreateIndexUsingFieldBuilder() Fields = new FieldBuilder().Build(typeof(Model)), VectorSearch = new() { - AlgorithmConfigurations = + Profiles = { - new HnswVectorSearchAlgorithmConfiguration( "my-vector-config") + new VectorSearchProfile("my-vector-profile", "my-hsnw-vector-config") + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration("my-hsnw-vector-config") } - } + }, }; SearchIndexClient indexClient = resources.GetIndexClient(); @@ -263,7 +276,7 @@ private class Model [SearchableField(AnalyzerName = "en.microsoft")] public string Description { get; set; } - [SearchableField(VectorSearchDimensions = "1536", VectorSearchConfiguration = "my-vector-config")] + [SearchableField(VectorSearchDimensions = "1536", VectorSearchProfile = "my-vector-profile")] public IReadOnlyList DescriptionVector { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/tests/FieldBuilderTests.cs b/sdk/search/Azure.Search.Documents/tests/FieldBuilderTests.cs index b995614aa3976..9ed0a81d95a6b 100644 --- a/sdk/search/Azure.Search.Documents/tests/FieldBuilderTests.cs +++ b/sdk/search/Azure.Search.Documents/tests/FieldBuilderTests.cs @@ -674,7 +674,7 @@ private class ModelWithVectorProperty [SimpleField(IsKey = true)] public string ID { get; set; } - [SearchableField(VectorSearchDimensions = "1536", VectorSearchConfiguration = "test-config")] + [SearchableField(VectorSearchDimensions = "1536", VectorSearchProfile = "test-config")] public IReadOnlyList TitleVector { get; set; } } } diff --git a/sdk/search/Azure.Search.Documents/tests/Models/SkillsetTests.cs b/sdk/search/Azure.Search.Documents/tests/Models/SkillsetTests.cs index ab4054a4b1148..a6e64f5997c36 100644 --- a/sdk/search/Azure.Search.Documents/tests/Models/SkillsetTests.cs +++ b/sdk/search/Azure.Search.Documents/tests/Models/SkillsetTests.cs @@ -13,7 +13,7 @@ public class SkillsetTests [TestCase("\"0123abcd\"", "\"0123abcd\"")] public void ParsesETag(string value, string expected) { - SearchIndexerSkillset sut = new(name: null, description: null, skills: null, cognitiveServicesAccount: null, knowledgeStore: null, etag: value, encryptionKey: null); + SearchIndexerSkillset sut = new(name: null, description: null, skills: null, cognitiveServicesAccount: null, knowledgeStore: null, indexProjections: null, etag: value, encryptionKey: null); Assert.AreEqual(expected, sut.ETag?.ToString()); } diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample01_HelloWorld.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample01_HelloWorld.cs index be7d3512edb52..437949bec5fe1 100644 --- a/sdk/search/Azure.Search.Documents/tests/Samples/Sample01_HelloWorld.cs +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample01_HelloWorld.cs @@ -18,7 +18,7 @@ namespace Azure.Search.Documents.Tests.Samples { - [ClientTestFixture(SearchClientOptions.ServiceVersion.V2023_07_01_Preview), ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ClientTestFixture(SearchClientOptions.ServiceVersion.V2023_10_01_Preview), ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public partial class HelloWorld : SearchTestBase { public HelloWorld(bool async, SearchClientOptions.ServiceVersion serviceVersion) diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearchCommons.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearchCommons.cs new file mode 100644 index 0000000000000..bb719aa0ffac9 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearchCommons.cs @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Search.Documents.Indexes.Models; +using Azure.Search.Documents.Indexes; +using System.Threading.Tasks; +#pragma warning disable SA1402 // File may only contain a single type + +namespace Azure.Search.Documents.Tests.samples.VectorSearch +{ + public static partial class VectorSearchCommons + { + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document + public static Hotel[] GetHotelDocuments() + { + return new[] + { + new Hotel() + { + HotelId = "1", + HotelName = "Fancy Stay", + Description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + + "and a really helpful concierge. The location is perfect -- right downtown, close to all " + + "the tourist attractions. We highly recommend this hotel.", + DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, + Category = "Luxury", + CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory + }, + new Hotel() + { + HotelId = "2", + HotelName = "Roach Motel", + Description = "Cheapest hotel in town. Infact, a motel.", + DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, + Category = "Budget", + CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory + }, + #if !SNIPPET + new Hotel() + { + HotelId = "3", + HotelName = "EconoStay", + Description = "Very popular hotel in town.", + DescriptionVector = VectorSearchEmbeddings.Hotel3VectorizeDescription, + Category = "Budget", + CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory + }, + new Hotel() + { + HotelId = "4", + HotelName = "Modern Stay", + Description = "Modern architecture, very polite staff and very clean. Also very affordable.", + DescriptionVector = VectorSearchEmbeddings.Hotel7VectorizeDescription, + Category = "Luxury", + CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory + }, + new Hotel() + { + HotelId = "5", + HotelName = "Secret Point", + Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. " + + "A few minutes away is Time's Square and the historic centre of the city, " + + "as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", + DescriptionVector = VectorSearchEmbeddings.Hotel9VectorizeDescription, + Category = "Boutique", + CategoryVector = VectorSearchEmbeddings.BoutiqueVectorizeCategory + } +#endif + // Add more hotel documents here... + }; + } + #endregion + } + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model + public class Hotel + { + public string HotelId { get; set; } + public string HotelName { get; set; } + public string Description { get; set; } + public IReadOnlyList DescriptionVector { get; set; } + public string Category { get; set; } + public IReadOnlyList CategoryVector { get; set; } + } + #endregion +} diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_SemanticHybridSearch.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_SemanticHybridSearch.cs new file mode 100644 index 0000000000000..143198ede9e95 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_SemanticHybridSearch.cs @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Core.TestFramework; +using Azure.Search.Documents.Indexes.Models; +using Azure.Search.Documents.Indexes; +using Azure.Search.Documents.Models; +using NUnit.Framework; +using System.Linq; + +namespace Azure.Search.Documents.Tests.samples.VectorSearch +{ + public partial class VectorSemanticHybridSearch : SearchTestBase + { + public VectorSemanticHybridSearch(bool async, SearchClientOptions.ServiceVersion serviceVersion) + : base(async, SearchClientOptions.ServiceVersion.V2023_10_01_Preview, null /* RecordedTestMode.Record /* to re-record */) + { + } + + [Test] + [PlaybackOnly("The availability of Semantic Search is limited to specific regions, as indicated in the list provided here: https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=search. Due to this limitation, the deployment of resources for weekly test pipeline for setting the \"semanticSearch\": \"free\" fails in the UsGov and China cloud regions.")] + public async Task SemanticHybridSearch() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search + IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + + SearchResults response = await searchClient.SearchAsync( + "Is there any hotel located on the main commercial artery of the city in the heart of New York?", + new SearchOptions + { + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + QueryType = SearchQueryType.Semantic, + QueryLanguage = QueryLanguage.EnUs, + SemanticConfigurationName = "my-semantic-config", + QueryCaption = QueryCaptionType.Extractive, + QueryAnswer = QueryAnswerType.Extractive, + }); + + int count = 0; + Console.WriteLine($"Semantic Hybrid Search Results:"); + + Console.WriteLine($"\nQuery Answer:"); + foreach (AnswerResult result in response.Answers) + { + Console.WriteLine($"Answer Highlights: {result.Highlights}"); + Console.WriteLine($"Answer Text: {result.Text}"); + } + + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + + if (result.Captions != null) + { + var caption = result.Captions.FirstOrDefault(); + if (caption.Highlights != null && caption.Highlights != "") + { + Console.WriteLine($"Caption Highlights: {caption.Highlights}"); + } + else + { + Console.WriteLine($"Caption Text: {caption.Text}"); + } + } + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + private async Task CreateIndex(SearchResources resources, string name) + { + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Index + string vectorSearchProfile = "my-vector-profile"; + string vectorSearchHnswConfig = "my-hsnw-vector-config"; + int modelDimensions = 1536; + + string indexName = "Hotel"; +#if !SNIPPET + indexName = name; +#endif + SearchIndex searchIndex = new(indexName) + { + Fields = + { + new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, + new SearchableField("Description") { IsFilterable = true }, + new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + }, + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + } + }, + SemanticSettings = new() + { + Configurations = + { + new SemanticConfiguration("my-semantic-config", new() + { + TitleField = new(){ FieldName = "HotelName" }, + ContentFields = + { + new() { FieldName = "Description" } + }, + KeywordFields = + { + new() { FieldName = "Category" } + } + }) + } + } + }; + #endregion + + Environment.SetEnvironmentVariable("SEARCH_ENDPOINT", resources.Endpoint.ToString()); + Environment.SetEnvironmentVariable("SEARCH_API_KEY", resources.PrimaryApiKey); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Create_Index + Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); + string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); + AzureKeyCredential credential = new(key); + + SearchIndexClient indexClient = new(endpoint, credential); +#if !SNIPPET + indexClient = InstrumentClient(new SearchIndexClient(endpoint, credential, GetSearchClientOptions())); +#endif + await indexClient.CreateIndexAsync(searchIndex); + #endregion + + return indexClient; + } + + private async Task UploadDocuments(SearchResources resources, string indexName) + { + Uri endpoint = resources.Endpoint; + string key = resources.PrimaryApiKey; + AzureKeyCredential credential = new AzureKeyCredential(key); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Semantic_Hybrid_Search_Upload_Documents + SearchClient searchClient = new(endpoint, indexName, credential); +#if !SNIPPET + searchClient = InstrumentClient(new SearchClient(endpoint, indexName, credential, GetSearchClientOptions())); +#endif + Hotel[] hotelDocuments = GetHotelDocuments(); + await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); + #endregion + + return searchClient; + } + + public static Hotel[] GetHotelDocuments() + { + return VectorSearchCommons.GetHotelDocuments(); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingFieldBuilder.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingFieldBuilder.cs new file mode 100644 index 0000000000000..9961224134d02 --- /dev/null +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingFieldBuilder.cs @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Search.Documents.Indexes.Models; +using Azure.Search.Documents.Indexes; +using NUnit.Framework; + +namespace Azure.Search.Documents.Tests.samples.VectorSearch +{ + public partial class VectorSearchUsingFieldBuilder : SearchTestBase + { + public VectorSearchUsingFieldBuilder(bool async, SearchClientOptions.ServiceVersion serviceVersion) + : base(async, SearchClientOptions.ServiceVersion.V2023_10_01_Preview, null /* RecordedTestMode.Record /* to re-record */) + { + } + + [Test] + public async Task CreateVectorIndexUsingFieldBuilder() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + try + { + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingFieldBuilder + string vectorSearchProfile = "my-vector-profile"; + string vectorSearchHnswConfig = "my-hsnw-vector-config"; + + string indexName = "MyDocument"; +#if !SNIPPET + indexName = Recording.Random.GetName(); + resources.IndexName = indexName; +#endif + // Create Index + SearchIndex searchIndex = new SearchIndex(indexName) + { + Fields = new FieldBuilder().Build(typeof(MyDocument)), + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + } + }, + }; + #endregion + + Environment.SetEnvironmentVariable("SEARCH_ENDPOINT", resources.Endpoint.ToString()); + Environment.SetEnvironmentVariable("SEARCH_API_KEY", resources.PrimaryApiKey); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_FieldBuilder + Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); + string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); + AzureKeyCredential credential = new(key); + + SearchIndexClient indexClient = new(endpoint, credential); +#if !SNIPPET + indexClient = InstrumentClient(new SearchIndexClient(endpoint, credential, GetSearchClientOptions())); +#endif + await indexClient.CreateIndexAsync(searchIndex); + #endregion + + SearchIndex createdIndex = await indexClient.GetIndexAsync(indexName); + Assert.AreEqual(indexName, createdIndex.Name); + Assert.AreEqual(searchIndex.Fields.Count, createdIndex.Fields.Count); + } + finally + { + await resources.GetIndexClient().DeleteIndexAsync(resources.IndexName); + } + } + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_FieldBuilder_Model + public class MyDocument + { + [SimpleField(IsKey = true, IsFilterable = true, IsSortable = true)] + public string Id { get; set; } + + [SearchableField(IsFilterable = true, IsSortable = true)] + public string Name { get; set; } + + [SearchableField(AnalyzerName = "en.microsoft")] + public string Description { get; set; } + + [SearchableField(VectorSearchDimensions = "1536", VectorSearchProfile = "my-vector-profile")] + public IReadOnlyList DescriptionVector { get; set; } + } + #endregion + } +} diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingRawVectors.cs similarity index 54% rename from sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch.cs rename to sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingRawVectors.cs index e30eda8a22561..038177c2b3b9c 100644 --- a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch.cs +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingRawVectors.cs @@ -4,19 +4,17 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Azure.Core.TestFramework; using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Models; using NUnit.Framework; -using System.Linq; -namespace Azure.Search.Documents.Tests.Samples +namespace Azure.Search.Documents.Tests.samples.VectorSearch { - public partial class VectorSearch : SearchTestBase + public partial class VectorSearchUsingRawVectors : SearchTestBase { - public VectorSearch(bool async, SearchClientOptions.ServiceVersion serviceVersion) - : base(async, SearchClientOptions.ServiceVersion.V2023_07_01_Preview, null /* RecordedTestMode.Record /* to re-record */) + public VectorSearchUsingRawVectors(bool async, SearchClientOptions.ServiceVersion serviceVersion) + : base(async, SearchClientOptions.ServiceVersion.V2023_10_01_Preview, null /* RecordedTestMode.Record /* to re-record */) { } @@ -32,7 +30,7 @@ public async Task SingleVectorSearch() SearchClient searchClient = await UploadDocuments(resources, indexName); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search_UsingRawVectors IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" #if !SNIPPET await Task.Delay(TimeSpan.FromSeconds(1)); @@ -41,7 +39,7 @@ public async Task SingleVectorSearch() SearchResults response = await searchClient.SearchAsync(null, new SearchOptions { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, }); int count = 0; @@ -74,7 +72,7 @@ public async Task SingleVectorSearchWithFilter() SearchClient searchClient = await UploadDocuments(resources, indexName); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter_UsingRawVectors IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" #if !SNIPPET await Task.Delay(TimeSpan.FromSeconds(1)); @@ -83,7 +81,7 @@ public async Task SingleVectorSearchWithFilter() SearchResults response = await searchClient.SearchAsync(null, new SearchOptions { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, Filter = "Category eq 'Luxury'" }); @@ -117,7 +115,7 @@ public async Task SimpleHybridSearch() SearchClient searchClient = await UploadDocuments(resources, indexName); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search_UsingRawVectors IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" #if !SNIPPET await Task.Delay(TimeSpan.FromSeconds(1)); @@ -127,7 +125,7 @@ public async Task SimpleHybridSearch() "Top hotels in town", new SearchOptions { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, + VectorQueries = { new RawVectorQuery() { Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } } }, }); int count = 0; @@ -148,78 +146,6 @@ public async Task SimpleHybridSearch() } } - [Test] - [PlaybackOnly("The availability of Semantic Search is limited to specific regions, as indicated in the list provided here: https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=search. Due to this limitation, the deployment of resources for weekly test pipeline for setting the \"semanticSearch\": \"free\" fails in the UsGov and China cloud regions.")] - public async Task SemanticHybridSearch() - { - await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); - SearchIndexClient indexClient = null; - string indexName = Recording.Random.GetName(); - try - { - indexClient = await CreateIndex(resources, indexName); - - SearchClient searchClient = await UploadDocuments(resources, indexName); - - await AddSemanticSettingsToIndex(resources, indexName); - - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Semantic_Hybrid_Search - IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" -#if !SNIPPET - await Task.Delay(TimeSpan.FromSeconds(1)); -#endif - - SearchResults response = await searchClient.SearchAsync( - "Is there any hotel located on the main commercial artery of the city in the heart of New York?", - new SearchOptions - { - Vectors = { new() { Value = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "descriptionVector" } } }, - QueryType = SearchQueryType.Semantic, - QueryLanguage = QueryLanguage.EnUs, - SemanticConfigurationName = "my-semantic-config", - QueryCaption = QueryCaptionType.Extractive, - QueryAnswer = QueryAnswerType.Extractive, - }); - - int count = 0; - Console.WriteLine($"Semantic Hybrid Search Results:"); - - Console.WriteLine($"\nQuery Answer:"); - foreach (AnswerResult result in response.Answers) - { - Console.WriteLine($"Answer Highlights: {result.Highlights}"); - Console.WriteLine($"Answer Text: {result.Text}"); - } - - await foreach (SearchResult result in response.GetResultsAsync()) - { - count++; - Hotel doc = result.Document; - Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); - - if (result.Captions != null) - { - var caption = result.Captions.FirstOrDefault(); - if (caption.Highlights != null && caption.Highlights != "") - { - Console.WriteLine($"Caption Highlights: {caption.Highlights}"); - } - else - { - Console.WriteLine($"Caption Text: {caption.Text}"); - } - } - } - Console.WriteLine($"Total number of search results:{count}"); - #endregion - Assert.GreaterOrEqual(count, 1); - } - finally - { - await indexClient.DeleteIndexAsync(indexName); - } - } - [Test] public async Task MultiVectorQuerySearch() { @@ -232,7 +158,7 @@ public async Task MultiVectorQuerySearch() SearchClient searchClient = await UploadDocuments(resources, indexName); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search_UsingRawVectors IReadOnlyList vectorizedDescriptionQuery = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" IReadOnlyList vectorizedCategoryQuery = VectorSearchEmbeddings.SearchVectorizeCategory; // "Luxury hotels in town" #if !SNIPPET @@ -242,9 +168,9 @@ public async Task MultiVectorQuerySearch() SearchResults response = await searchClient.SearchAsync(null, new SearchOptions { - Vectors = { - new() { Value = vectorizedDescriptionQuery, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } }, - new() { Value = vectorizedCategoryQuery, KNearestNeighborsCount = 3, Fields = { "CategoryVector" } } + VectorQueries = { + new RawVectorQuery() { Vector = vectorizedDescriptionQuery, KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } }, + new RawVectorQuery() { Vector = vectorizedCategoryQuery, KNearestNeighborsCount = 3, Fields = { "CategoryVector" } } }, }); @@ -278,7 +204,7 @@ public async Task MultiFieldVectorQuerySearch() SearchClient searchClient = await UploadDocuments(resources, indexName); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search_UsingRawVectors IReadOnlyList vectorizedResult = VectorSearchEmbeddings.SearchVectorizeDescription; // "Top hotels in town" #if !SNIPPET await Task.Delay(TimeSpan.FromSeconds(1)); @@ -287,8 +213,8 @@ public async Task MultiFieldVectorQuerySearch() SearchResults response = await searchClient.SearchAsync(null, new SearchOptions { - Vectors = { new() { - Value = vectorizedResult, + VectorQueries = { new RawVectorQuery() { + Vector = vectorizedResult, KNearestNeighborsCount = 3, Fields = { "DescriptionVector", "CategoryVector" } } } }); @@ -313,8 +239,9 @@ public async Task MultiFieldVectorQuerySearch() private async Task CreateIndex(SearchResources resources, string name) { - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index - string vectorSearchConfigName = "my-vector-config"; + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingRawVectors + string vectorSearchProfile = "my-vector-profile"; + string vectorSearchHnswConfig = "my-hsnw-vector-config"; int modelDimensions = 1536; string indexName = "Hotel"; @@ -332,30 +259,34 @@ private async Task CreateIndex(SearchResources resources, str { IsSearchable = true, VectorSearchDimensions = modelDimensions, - VectorSearchConfiguration = vectorSearchConfigName + VectorSearchProfile = vectorSearchProfile }, new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) { IsSearchable = true, VectorSearchDimensions = modelDimensions, - VectorSearchConfiguration = vectorSearchConfigName + VectorSearchProfile = vectorSearchProfile }, }, VectorSearch = new() { - AlgorithmConfigurations = + Profiles = { - new HnswVectorSearchAlgorithmConfiguration(vectorSearchConfigName) + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) } - } + }, }; #endregion Environment.SetEnvironmentVariable("SEARCH_ENDPOINT", resources.Endpoint.ToString()); Environment.SetEnvironmentVariable("SEARCH_API_KEY", resources.PrimaryApiKey); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_UsingRawVectors Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); AzureKeyCredential credential = new(key); @@ -370,48 +301,13 @@ private async Task CreateIndex(SearchResources resources, str return indexClient; } - private static async Task AddSemanticSettingsToIndex(SearchResources resources, string name) - { - SearchIndexClient indexClient = resources.GetIndexClient(); - - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Semantic_Index - string indexName = "Hotel"; -#if !SNIPPET - indexName = name; -#endif - SearchIndex createdIndex = await indexClient.GetIndexAsync(indexName); - - createdIndex.SemanticSettings = new() - { - Configurations = - { - new SemanticConfiguration("my-semantic-config", new() - { - TitleField = new(){ FieldName = "HotelName" }, - ContentFields = - { - new() { FieldName = "Description" } - }, - KeywordFields = - { - new() { FieldName = "Category" } - } - }) - } - }; - - // Update index - await indexClient.CreateOrUpdateIndexAsync(createdIndex); - #endregion - } - private async Task UploadDocuments(SearchResources resources, string indexName) { Uri endpoint = resources.Endpoint; string key = resources.PrimaryApiKey; AzureKeyCredential credential = new AzureKeyCredential(key); - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents_UsingRawVectors SearchClient searchClient = new(endpoint, indexName, credential); #if !SNIPPET searchClient = InstrumentClient(new SearchClient(endpoint, indexName, credential, GetSearchClientOptions())); @@ -423,78 +319,9 @@ private async Task UploadDocuments(SearchResources resources, stri return searchClient; } - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Model - public class Hotel - { - public string HotelId { get; set; } - public string HotelName { get; set; } - public string Description { get; set; } - public IReadOnlyList DescriptionVector { get; set; } - public string Category { get; set; } - public IReadOnlyList CategoryVector { get; set; } - } - #endregion - - #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Hotel_Document public static Hotel[] GetHotelDocuments() { - return new[] - { - new Hotel() - { - HotelId = "1", - HotelName = "Fancy Stay", - Description = - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa, " + - "and a really helpful concierge. The location is perfect -- right downtown, close to all " + - "the tourist attractions. We highly recommend this hotel.", - DescriptionVector = VectorSearchEmbeddings.Hotel1VectorizeDescription, - Category = "Luxury", - CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory - }, - new Hotel() - { - HotelId = "2", - HotelName = "Roach Motel", - Description = "Cheapest hotel in town. Infact, a motel.", - DescriptionVector = VectorSearchEmbeddings.Hotel2VectorizeDescription, - Category = "Budget", - CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory - }, - #if !SNIPPET - new Hotel() - { - HotelId = "3", - HotelName = "EconoStay", - Description = "Very popular hotel in town.", - DescriptionVector = VectorSearchEmbeddings.Hotel3VectorizeDescription, - Category = "Budget", - CategoryVector = VectorSearchEmbeddings.BudgetVectorizeCategory - }, - new Hotel() - { - HotelId = "4", - HotelName = "Modern Stay", - Description = "Modern architecture, very polite staff and very clean. Also very affordable.", - DescriptionVector = VectorSearchEmbeddings.Hotel7VectorizeDescription, - Category = "Luxury", - CategoryVector = VectorSearchEmbeddings.LuxuryVectorizeCategory - }, - new Hotel() - { - HotelId = "5", - HotelName = "Secret Point", - Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. " + - "A few minutes away is Time's Square and the historic centre of the city, " + - "as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", - DescriptionVector = VectorSearchEmbeddings.Hotel9VectorizeDescription, - Category = "Boutique", - CategoryVector = VectorSearchEmbeddings.BoutiqueVectorizeCategory - } -#endif - // Add more hotel documents here... - }; + return VectorSearchCommons.GetHotelDocuments(); } - #endregion } } diff --git a/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingTextVectors.cs b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingTextVectors.cs new file mode 100644 index 0000000000000..cbf98bb141c8e --- /dev/null +++ b/sdk/search/Azure.Search.Documents/tests/Samples/Sample07_VectorSearch_UsingTextVectors.cs @@ -0,0 +1,360 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Threading.Tasks; +using Azure.Search.Documents.Indexes.Models; +using Azure.Search.Documents.Indexes; +using Azure.Search.Documents.Models; +using NUnit.Framework; +using Azure.Core.TestFramework; + +namespace Azure.Search.Documents.Tests.samples.VectorSearch +{ + public partial class VectorSearchUsingTextVectors : SearchTestBase + { + public VectorSearchUsingTextVectors(bool async, SearchClientOptions.ServiceVersion serviceVersion) + : base(async, SearchClientOptions.ServiceVersion.V2023_10_01_Preview, null /* RecordedTestMode.Record /* to re-record */) + { + } + + [Test] + [PlaybackOnly("Running it in the playback mode, eliminating the need for pipelines to create OpenAI resources.")] + public async Task SingleVectorSearch() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Single_Vector_Search_UsingTextVectors +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + }); + + int count = 0; + Console.WriteLine($"Single Vector Search Results:"); + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + [Test] + [PlaybackOnly("Running it in the playback mode, eliminating the need for pipelines to create OpenAI resources.")] + public async Task SingleVectorSearchWithFilter() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Filter_UsingTextVectors +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + Filter = "Category eq 'Luxury'" + }); + + int count = 0; + Console.WriteLine($"Single Vector Search With Filter Results:"); + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + [Test] + [PlaybackOnly("Running it in the playback mode, eliminating the need for pipelines to create OpenAI resources.")] + public async Task SimpleHybridSearch() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Simple_Hybrid_Search_UsingTextVectors +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + SearchResults response = await searchClient.SearchAsync( + "Luxury hotels in town", + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector" } } }, + }); + + int count = 0; + Console.WriteLine($"Simple Hybrid Search Results:"); + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + [Test] + [PlaybackOnly("Running it in the playback mode, eliminating the need for pipelines to create OpenAI resources.")] + public async Task MultiVectorQuerySearch() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Vector_Search_UsingTextVectors +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { + new VectorizableTextQuery() { + Text = "Top hotels in town", KNearestNeighborsCount = 3, Fields = { "DescriptionVector" } + }, + new VectorizableTextQuery() { + Text = "Luxury hotels in town", KNearestNeighborsCount = 3, Fields = { "CategoryVector" } + } + }, + }); + + int count = 0; + Console.WriteLine($"Multi Vector Search Results:"); + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + [Test] + [PlaybackOnly("Running it in the playback mode, eliminating the need for pipelines to create OpenAI resources.")] + public async Task MultiFieldVectorQuerySearch() + { + await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); + SearchIndexClient indexClient = null; + string indexName = Recording.Random.GetName(); + try + { + indexClient = await CreateIndex(resources, indexName); + + SearchClient searchClient = await UploadDocuments(resources, indexName); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Multi_Fields_Vector_Search_UsingTextVectors +#if !SNIPPET + await Task.Delay(TimeSpan.FromSeconds(1)); +#endif + SearchResults response = await searchClient.SearchAsync(null, + new SearchOptions + { + VectorQueries = { new VectorizableTextQuery() { + Text = "Top hotels in town", + KNearestNeighborsCount = 3, + Fields = { "DescriptionVector", "CategoryVector" } } } + }); + + int count = 0; + Console.WriteLine($"Multi Fields Vector Search Results:"); + await foreach (SearchResult result in response.GetResultsAsync()) + { + count++; + Hotel doc = result.Document; + Console.WriteLine($"{doc.HotelId}: {doc.HotelName}"); + } + Console.WriteLine($"Total number of search results:{count}"); + #endregion + Assert.GreaterOrEqual(count, 1); + } + finally + { + await indexClient.DeleteIndexAsync(indexName); + } + } + + private async Task CreateIndex(SearchResources resources, string name) + { + string openAIEndpoint = TestEnvironment.OpenAIEndpoint; + string openAIKey = TestEnvironment.OpenAIKey; + if (string.IsNullOrEmpty(openAIEndpoint) || string.IsNullOrEmpty(openAIKey)) + { + Assert.Ignore("OpenAI was not deployed"); + } + + Environment.SetEnvironmentVariable("OPENAI_ENDPOINT", openAIEndpoint); + Environment.SetEnvironmentVariable("OPENAI_KEY", openAIKey); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Index_UsingTextVectors + string vectorSearchProfile = "my-vector-profile"; + string vectorSearchHnswConfig = "my-hsnw-vector-config"; + string modelName = "text-embedding-ada-002"; + int modelDimensions = 1536; + + string indexName = "Hotel"; +#if !SNIPPET + indexName = name; +#endif + SearchIndex searchIndex = new(indexName) + { + Fields = + { + new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchableField("HotelName") { IsFilterable = true, IsSortable = true }, + new SearchableField("Description") { IsFilterable = true }, + new SearchField("DescriptionVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + new SearchableField("Category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, + new SearchField("CategoryVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) + { + IsSearchable = true, + VectorSearchDimensions = modelDimensions, + VectorSearchProfile = vectorSearchProfile + }, + }, + VectorSearch = new() + { + Profiles = + { + new VectorSearchProfile(vectorSearchProfile, vectorSearchHnswConfig) + { + Vectorizer = "openai" + } + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration(vectorSearchHnswConfig) + }, + Vectorizers = + { + new AzureOpenAIVectorizer("openai") + { + AzureOpenAIParameters = new AzureOpenAIParameters() + { + ResourceUri = new Uri(Environment.GetEnvironmentVariable("OPENAI_ENDPOINT")), + ApiKey = Environment.GetEnvironmentVariable("OPENAI_KEY"), + DeploymentId = modelName, + } + } + } + }, + }; + #endregion + + Environment.SetEnvironmentVariable("SEARCH_ENDPOINT", resources.Endpoint.ToString()); + Environment.SetEnvironmentVariable("SEARCH_API_KEY", resources.PrimaryApiKey); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Create_Index_UsingTextVectors + Uri endpoint = new(Environment.GetEnvironmentVariable("SEARCH_ENDPOINT")); + string key = Environment.GetEnvironmentVariable("SEARCH_API_KEY"); + AzureKeyCredential credential = new(key); + + SearchIndexClient indexClient = new(endpoint, credential); +#if !SNIPPET + indexClient = InstrumentClient(new SearchIndexClient(endpoint, credential, GetSearchClientOptions())); +#endif + await indexClient.CreateIndexAsync(searchIndex); + #endregion + + return indexClient; + } + + private async Task UploadDocuments(SearchResources resources, string indexName) + { + Uri endpoint = resources.Endpoint; + string key = resources.PrimaryApiKey; + AzureKeyCredential credential = new AzureKeyCredential(key); + + #region Snippet:Azure_Search_Documents_Tests_Samples_Sample07_Vector_Search_Upload_Documents_UsingTextVectors + SearchClient searchClient = new(endpoint, indexName, credential); +#if !SNIPPET + searchClient = InstrumentClient(new SearchClient(endpoint, indexName, credential, GetSearchClientOptions())); +#endif + Hotel[] hotelDocuments = GetHotelDocuments(); + await searchClient.IndexDocumentsAsync(IndexDocumentsBatch.Upload(hotelDocuments)); + #endregion + + return searchClient; + } + + public static Hotel[] GetHotelDocuments() + { + return VectorSearchCommons.GetHotelDocuments(); + } + } +} diff --git a/sdk/search/Azure.Search.Documents/tests/SearchIndexClientTests.cs b/sdk/search/Azure.Search.Documents/tests/SearchIndexClientTests.cs index 728b84abb26ad..fef4ea8fc2412 100644 --- a/sdk/search/Azure.Search.Documents/tests/SearchIndexClientTests.cs +++ b/sdk/search/Azure.Search.Documents/tests/SearchIndexClientTests.cs @@ -15,7 +15,7 @@ namespace Azure.Search.Documents.Tests { - [ClientTestFixture(SearchClientOptions.ServiceVersion.V2020_06_30, SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ClientTestFixture(SearchClientOptions.ServiceVersion.V2020_06_30, SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public class SearchIndexClientTests : SearchTestBase { public SearchIndexClientTests(bool async, SearchClientOptions.ServiceVersion serviceVersion) @@ -108,7 +108,7 @@ static string GetDuplicates(IEnumerable values) } [Test] - [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task GetServiceStatistics() { await using SearchResources resources = await SearchResources.GetSharedHotelsIndexAsync(this); @@ -145,7 +145,7 @@ public void CreateIndexParameterValidation() } [Test] - [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task CreateIndex() { await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); @@ -180,7 +180,7 @@ public void UpdateIndexParameterValidation() } [Test] - [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task UpdateIndex() { await using SearchResources resources = SearchResources.CreateWithNoIndexes(this); @@ -248,7 +248,7 @@ public void GetIndexParameterValidation() } [Test] - [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task GetIndex() { await using SearchResources resources = await SearchResources.CreateWithHotelsIndexAsync(this); @@ -262,7 +262,7 @@ public async Task GetIndex() } [Test] - [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_07_01_Preview)] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task GetIndexes() { await using SearchResources resources = await SearchResources.GetSharedHotelsIndexAsync(this); diff --git a/sdk/search/Azure.Search.Documents/tests/SearchIndexerClientTests.cs b/sdk/search/Azure.Search.Documents/tests/SearchIndexerClientTests.cs index 73d3ca4cb840e..cff26097da9f7 100644 --- a/sdk/search/Azure.Search.Documents/tests/SearchIndexerClientTests.cs +++ b/sdk/search/Azure.Search.Documents/tests/SearchIndexerClientTests.cs @@ -13,7 +13,7 @@ namespace Azure.Search.Documents.Tests { - [ClientTestFixture(SearchClientOptions.ServiceVersion.V2020_06_30, SearchClientOptions.ServiceVersion.V2021_04_30_Preview)] + [ClientTestFixture(SearchClientOptions.ServiceVersion.V2020_06_30, SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public class SearchIndexerClientTests : SearchTestBase { public SearchIndexerClientTests(bool async, SearchClientOptions.ServiceVersion serviceVersion) @@ -422,8 +422,9 @@ private SearchIndexerSkillset CreateSkillsetModel(string skillsetName, SearchRes }, new[] { - new OutputFieldMappingEntry("score") { TargetName = "Sentiment" }, - }) + new OutputFieldMappingEntry("confidenceScores") { TargetName = "Sentiment" }, + }, + SentimentSkill.SkillVersion.V3) { Context = "/document/reviews_text/pages/*", DefaultLanguageCode = SentimentSkillLanguage.En, @@ -624,6 +625,7 @@ private async Task TestSkillsetAsync(SearchIndexerClient client, SearchIndexerSk } [Test] + [ServiceVersion(Min = SearchClientOptions.ServiceVersion.V2023_10_01_Preview)] public async Task RoundtripAllSkills() { // BUGBUG: https://github.com/Azure/azure-sdk-for-net/issues/15108 @@ -649,6 +651,7 @@ SearchIndexerSkill CreateSkill(Type t, string[] inputNames, string[] outputNames Type _ when t == typeof(TextTranslationSkill) => new TextTranslationSkill(inputs, outputs, TextTranslationSkillLanguage.En), Type _ when t == typeof(WebApiSkill) => new WebApiSkill(inputs, outputs, "https://microsoft.com"), Type _ when t == typeof(AzureMachineLearningSkill) => new AzureMachineLearningSkill(inputs, outputs, new Uri("https://microsoft.com")), + Type _ when t == typeof(AzureOpenAIEmbeddingSkill) => new AzureOpenAIEmbeddingSkill(inputs, outputs) { ResourceUri = new Uri("https://test-sample.openai.azure.com"), ApiKey = "api-key", DeploymentId = "model" }, _ => (SearchIndexerSkill)Activator.CreateInstance(t, new object[] { inputs, outputs }), }; } @@ -698,19 +701,20 @@ SentimentSkill CreateSentimentSkill(SentimentSkill.SkillVersion skillVersion) Type _ when t == typeof(CustomEntityLookupSkill) => CreateSkill(t, new[] { "text", "languageCode" }, new[] { "entities" }), Type _ when t == typeof(DocumentExtractionSkill) => CreateSkill(t, new[] { "file_data" }, new[] { "content", "normalized_images" }), Type _ when t == typeof(EntityLinkingSkill) => CreateSkill(t, new[] { "languageCode", "text" }, new[] { "entities" }), - Type _ when t == typeof(EntityRecognitionSkill) => CreateEntityRecognitionSkill(EntityRecognitionSkill.SkillVersion.V1), + Type _ when t == typeof(EntityRecognitionSkill) => CreateEntityRecognitionSkill(EntityRecognitionSkill.SkillVersion.V3), Type _ when t == typeof(ImageAnalysisSkill) => CreateSkill(t, new[] { "image" }, new[] { "categories" }), Type _ when t == typeof(KeyPhraseExtractionSkill) => CreateSkill(t, new[] { "text", "languageCode" }, new[] { "keyPhrases" }), Type _ when t == typeof(LanguageDetectionSkill) => CreateSkill(t, new[] { "text" }, new[] { "languageCode", "languageName", "score" }), Type _ when t == typeof(MergeSkill) => CreateSkill(t, new[] { "text", "itemsToInsert", "offsets" }, new[] { "mergedText" }), Type _ when t == typeof(OcrSkill) => CreateSkill(t, new[] { "image" }, new[] { "text", "layoutText" }), Type _ when t == typeof(PiiDetectionSkill) => CreateSkill(t, new[] { "languageCode", "text" }, new[] { "piiEntities", "maskedText" }), - Type _ when t == typeof(SentimentSkill) => CreateSentimentSkill(SentimentSkill.SkillVersion.V1), + Type _ when t == typeof(SentimentSkill) => CreateSentimentSkill(SentimentSkill.SkillVersion.V3), Type _ when t == typeof(ShaperSkill) => CreateSkill(t, new[] { "text" }, new[] { "output" }), Type _ when t == typeof(SplitSkill) => CreateSkill(t, new[] { "text", "languageCode" }, new[] { "textItems" }), Type _ when t == typeof(TextTranslationSkill) => CreateSkill(t, new[] { "text", "toLanguageCode", "fromLanguageCode" }, new[] { "translatedText", "translatedToLanguageCode", "translatedFromLanguageCode" }), Type _ when t == typeof(WebApiSkill) => CreateSkill(t, new[] { "input" }, new[] { "output" }), Type _ when t == typeof(AzureMachineLearningSkill) => CreateSkill(t, new[] { "input" }, new[] { "output" }), + Type _ when t == typeof(AzureOpenAIEmbeddingSkill) => CreateSkill(t, new[] { "text" }, new[] { "embedding" }), _ => throw new NotSupportedException($"{t.FullName}"), }) .ToList(); diff --git a/sdk/search/Azure.Search.Documents/tests/Utilities/SearchResources.Data.cs b/sdk/search/Azure.Search.Documents/tests/Utilities/SearchResources.Data.cs index 315ac44876d43..cf75c70760352 100644 --- a/sdk/search/Azure.Search.Documents/tests/Utilities/SearchResources.Data.cs +++ b/sdk/search/Azure.Search.Documents/tests/Utilities/SearchResources.Data.cs @@ -43,7 +43,7 @@ internal static SearchIndex GetHotelIndex(string name) => { IsSearchable = true, VectorSearchDimensions = 1536, - VectorSearchConfiguration = "my-vector-config" + VectorSearchProfile = "my-vector-profile" }, new SearchableField("category") { IsFilterable = true, IsSortable = true, IsFacetable = true }, new SearchableField("tags", collection: true) { IsFilterable = true, IsFacetable = true }, @@ -81,9 +81,13 @@ internal static SearchIndex GetHotelIndex(string name) => }, VectorSearch = new() { - AlgorithmConfigurations = + Profiles = { - new HnswVectorSearchAlgorithmConfiguration( "my-vector-config") + new VectorSearchProfile("my-vector-profile", "my-hsnw-vector-config") + }, + Algorithms = + { + new HnswVectorSearchAlgorithmConfiguration( "my-hsnw-vector-config") } }, SemanticSettings = new() diff --git a/sdk/search/Azure.Search.Documents/tests/Utilities/SearchTestEnvironment.cs b/sdk/search/Azure.Search.Documents/tests/Utilities/SearchTestEnvironment.cs index 398b0afa3d855..4a344ede3abc1 100644 --- a/sdk/search/Azure.Search.Documents/tests/Utilities/SearchTestEnvironment.cs +++ b/sdk/search/Azure.Search.Documents/tests/Utilities/SearchTestEnvironment.cs @@ -45,6 +45,11 @@ public class SearchTestEnvironment: TestEnvironment /// public const string CognitiveKeyVariableName = "SEARCH_COGNITIVE_KEY"; + /// + /// The name of the variable for . + /// + public const string OpenAIKeyVariableName = "OPENAI_KEY"; + /// /// Gets the service name. /// @@ -89,5 +94,15 @@ public class SearchTestEnvironment: TestEnvironment /// Gets the recorded value for the CLIENT_ID, which gets sanitized as part of the payload. /// public string RecordedClientSecret => GetRecordedVariable(ClientSecretVariableName, options => options.IsSecret()); + + /// + /// Gets the optional OpenAI key + /// + public string OpenAIKey => GetRecordedOptionalVariable(OpenAIKeyVariableName, options => options.IsSecret()); + + /// + /// Gets the optional OpenAI URL used used for Vector Search. + /// + public string OpenAIEndpoint => GetRecordedOptionalVariable("OPENAI_ENDPOINT"); } } diff --git a/sdk/search/tests.yml b/sdk/search/tests.yml index e7edfcaaee06c..e955b7cdb9426 100644 --- a/sdk/search/tests.yml +++ b/sdk/search/tests.yml @@ -11,5 +11,13 @@ extends: # https://github.com/Azure/azure-sdk-tools/issues/2216 Clouds: 'Preview' SupportedClouds: 'Preview,UsGov,China' + CloudConfig: + Preview: + SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources-preview) + Location: 'eastus2euap' + UsGov: + SubscriptionConfiguration: $(sub-config-gov-test-resources) + China: + SubscriptionConfiguration: $(sub-config-cn-test-resources) EnvVars: AZURE_SEARCH_TEST_MODE: Live