pythonazureazure-cognitive-searchazure-python-sdkazure-ai-search

Error on Hybrid Search using Azure AI Search


I've been getting the following error using python sdk and front end although I believe I have my schema set up "Searchable" correctly. Please advice, thank you.

"The 'search' parameter requires at least 1 searchable text field in the index.\r\nParameter name: searchFields"

def simple_hybrid_search():
    # [START simple_hybrid_search]
    query = "classify earthworks"

    search_client = SearchClient(endpoint, index_name, AzureKeyCredential(key))
    vector_query = VectorizedQuery(vector=generate_embeddings(query), k_nearest_neighbors=3, fields="vector")

    results = search_client.search(
        search_text=query,
        vector_queries=[vector_query],
        select=["metadata"],
    )

    for result in results:
        print(result)

fields = [
    SimpleField(name="id", type=SearchFieldDataType.String, key=True, searchable=True),
    SearchField(name="vector",type=SearchFieldDataType.Collection(SearchFieldDataType.Single), searchable=True, vector_search_dimensions=1536, vector_search_profile_name="uniclass-rag-vector-config",),
    ComplexField(name="metadata", fields=[
        SearchableField(name="code", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="group", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="group_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="sub_group", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True), 
        SearchableField(name="sub_group_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="sub_object_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="object_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        SearchableField(name="classification_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
        

enter image description here


Solution

  • As per this documentation, you can see:

    Hybrid search is a combination of full text and vector queries that execute against a search index that contains both searchable plain text content and generated embeddings.

    You need a vector field for vector query and searchable text field in index for text query, and not in subfields. Both are processed parallelly and give you the output.

    Your schema contains no searchable text field for search_text, and this is the reason you are getting the error saying The 'search' parameter requires at least 1 searchable text field in the index.

    Also, if you observe, it runs successfully if you only give vector search because you have a vector field of type SingleCollection and you are passing it.

    enter image description here

    So, in your case, the solution is to create an index with a searchable field and, while doing search, give an extra parameter search_fields with a list of metadata subfields.

    Below is the code to create the index.

    Here, I made id as Searchable.

    def get_hotel_index(name: str):
        from azure.search.documents.indexes.models import (
            SearchIndex,
            SearchField,
            SearchFieldDataType,
            SimpleField,
            SearchableField,
            ComplexField,
            VectorSearch,
            VectorSearchProfile,
            HnswAlgorithmConfiguration,
        )
        fields = [
        SearchableField(name="id", type=SearchFieldDataType.String, key=True, searchable=True),
        SearchField(name="vector",type=SearchFieldDataType.Collection(SearchFieldDataType.Single), searchable=True, vector_search_dimensions=1536, vector_search_profile_name="uniclass-rag-vector-config",),
        ComplexField(name="metadata", fields=[
            SearchableField(name="code", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="group", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="group_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="sub_group", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True), 
            SearchableField(name="sub_group_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="sub_object_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="object_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),
            SearchableField(name="classification_title", type=SearchFieldDataType.String, nullable=True, searchable=True, filterable=True, sortable=True, facetable=True),])]
        vector_search = VectorSearch(
            profiles=[VectorSearchProfile(name="uniclass-rag-vector-config", algorithm_configuration_name="my-algorithms-config")],
            algorithms=[HnswAlgorithmConfiguration(name="my-algorithms-config")],
        )
        return SearchIndex(name=name, fields=fields, vector_search=vector_search)
    

    And code for searching.

    def simple_hybrid_search(query):
    
        search_client = SearchClient(service_endpoint, index_name, AzureKeyCredential(key))
        vector_query = VectorizedQuery(vector=get_embeddings(query), k_nearest_neighbors=3, fields="vector")
    
        results = search_client.search(
            search_text=query,
            search_fields=["metadata/code", "metadata/group", "metadata/group_title", "metadata/sub_group", "metadata/sub_group_title", "metadata/sub_object_title", "metadata/title", "metadata/object_title", "metadata/classification_title"],
            vector_queries=[vector_query],
            select=["metadata"],
        )
    
        for result in results:
            print(result)
    
    simple_hybrid_search("Give me description 3")
    

    Output:

    enter image description here