def test_hybrid_search_calls_correct_vespa_query(self):
        """
        Test all hybrid search calls the correct vespa queries.
        """

        for index in [self.structured_text_index_score_modifiers, self.semi_structured_default_text_index,
                      self.unstructured_default_text_index]:
            with self.subTest(index=index.name):
                original_query = self.config.vespa_client.query
                def pass_through_query(*arg, **kwargs):
                    return original_query(*arg, **kwargs)

                mock_vespa_client_query = unittest.mock.MagicMock()
                mock_vespa_client_query.side_effect = pass_through_query

                if isinstance(index, UnstructuredMarqoIndex):
                    # this is required to create the tensor fields in the semi-structured index
                    self.add_documents(
                        config=self.config,
                        add_docs_params=AddDocsParams(
                            index_name=index.name,
                            docs=[{"_id": "1", "text_field_1": "dogs", "text_field_2": "cats", "text_field_3": "cows"},],
                            tensor_fields=["text_field_1", "text_field_2", "text_field_3"]
                        ),
                    )

                @unittest.mock.patch("marqo.vespa.vespa_client.VespaClient.query", mock_vespa_client_query)
                def run():
                    res = tensor_search.search(
                        config=self.config,
                        index_name=index.name,
                        text="dogs",
                        search_method="HYBRID",
                        rerank_depth=None if index == self.unstructured_default_text_index else 3,
                        result_count=3,
                        hybrid_parameters=HybridParameters(
                            retrievalMethod="disjunction",
                            rankingMethod="rrf",
                            alpha=0.6,
                            rrfK=61,
                            searchableAttributesLexical=["text_field_1", "text_field_2"] \
                                if isinstance(index, (StructuredMarqoIndex, SemiStructuredMarqoIndex)) else None,
                            searchableAttributesTensor=["text_field_2", "text_field_3"] \
                                if isinstance(index, (StructuredMarqoIndex, SemiStructuredMarqoIndex)) else None,
                            scoreModifiersLexical={
                                "multiply_score_by": [
                                    {"field_name": "mult_field_1", "weight": 1.0},
                                    {"field_name": "mult_field_2", "weight": 1.0}
                                ]
                            },
                            scoreModifiersTensor={
                                "multiply_score_by": [
                                    {"field_name": "mult_field_1", "weight": 1.0}
                                ],
                                "add_to_score": [
                                    {"field_name": "add_field_1", "weight": 1.0}
                                ]
                            }

                        )
                    )
                    return res

                res = run()

                call_args = mock_vespa_client_query.call_args_list
                self.assertEqual(len(call_args), 1)

                vespa_query_kwargs = call_args[0][1]
                self.assertIn("PLACEHOLDER. WILL NOT BE USED IN HYBRID SEARCH.", vespa_query_kwargs["yql"])
                self.assertEqual(vespa_query_kwargs["marqo__hybrid.retrievalMethod"], RetrievalMethod.Disjunction)
                self.assertEqual(vespa_query_kwargs["marqo__hybrid.rankingMethod"], RankingMethod.RRF)
                self.assertEqual(vespa_query_kwargs["marqo__hybrid.alpha"], 0.6)
                self.assertEqual(vespa_query_kwargs["marqo__hybrid.rrf_k"], 61)
                self.assertEqual(vespa_query_kwargs["hits"], 3)

                self.assertEqual(vespa_query_kwargs["ranking"], "hybrid_custom_searcher")
                self.assertEqual(vespa_query_kwargs["marqo__ranking.lexical.lexical"], "bm25")
                self.assertEqual(vespa_query_kwargs["marqo__ranking.tensor.tensor"], "embedding_similarity")
                self.assertEqual(vespa_query_kwargs["marqo__ranking.lexical.tensor"], "hybrid_bm25_then_embedding_similarity")
                self.assertEqual(vespa_query_kwargs["marqo__ranking.tensor.lexical"], "hybrid_embedding_similarity_then_bm25")

                self.assertEqual(vespa_query_kwargs["query_features"]["marqo__mult_weights_lexical"],
                                 {'mult_field_1': 1.0, 'mult_field_2': 1.0})
                self.assertEqual(vespa_query_kwargs["query_features"]["marqo__add_weights_lexical"], {})
                self.assertEqual(vespa_query_kwargs["query_features"]["marqo__mult_weights_tensor"],
                                 {'mult_field_1': 1.0})
                self.assertEqual(vespa_query_kwargs["query_features"]["marqo__add_weights_tensor"],
                                 {'add_field_1': 1.0})

                if isinstance(index, (StructuredMarqoIndex, SemiStructuredMarqoIndex)):
                    self.assertIn("(({targetHits:3, approximate:True, hnsw.exploreAdditionalHits:1997}"
                                  "nearestNeighbor(marqo__embeddings_text_field_2, marqo__query_embedding)) OR "
                                  "({targetHits:3, approximate:True, hnsw.exploreAdditionalHits:1997}"
                                  "nearestNeighbor(marqo__embeddings_text_field_3, marqo__query_embedding)))",
                                  vespa_query_kwargs["marqo__yql.tensor"])
                    self.assertIn(
                        "marqo__lexical_text_field_1 contains \"dogs\" OR marqo__lexical_text_field_2 contains \"dogs\"",
                        vespa_query_kwargs["marqo__yql.lexical"])
                    self.assertEqual(vespa_query_kwargs["query_features"]["marqo__fields_to_rank_lexical"],
                                     {'marqo__lexical_text_field_1': 1, 'marqo__lexical_text_field_2': 1})
                    self.assertEqual(vespa_query_kwargs["query_features"]["marqo__fields_to_rank_tensor"],
                                     {'marqo__embeddings_text_field_2': 1, 'marqo__embeddings_text_field_3': 1})
                    # global rerankDepth & score modifiers are not available for legacy unstructured
                    self.assertEqual(vespa_query_kwargs["marqo__hybrid.rerankDepthGlobal"], 3)

                elif isinstance(index, UnstructuredMarqoIndex):
                    self.assertIn("({targetHits:3, approximate:True, hnsw.exploreAdditionalHits:1997}"
                                  "nearestNeighbor(marqo__embeddings, marqo__query_embedding))",
                                  vespa_query_kwargs["marqo__yql.tensor"])
                    self.assertIn(
                        "default contains \"dogs\"",
                        vespa_query_kwargs["marqo__yql.lexical"])
                    self.assertEqual(vespa_query_kwargs["query_features"]["marqo__fields_to_rank_lexical"], {})
                    self.assertEqual(vespa_query_kwargs["query_features"]["marqo__fields_to_rank_tensor"], {})

                # TODO: For lexical/tensor and tensor/lexical. Check fields to rank specifically.
                # TODO: with and without score modifiers
                # Make sure results are retrieved
                self.assertIn("hits", res)

        Test all hybrid search calls the correct vespa queries.
        
tests/integ_tests/tensor_search/integ_tests/test_hybrid_search.py