Mixing Raw Text Queries and Precomputed Vectors in Milvus Text Embedding Functions
Milvus's Function module is a powerful feature that simplifies developer workflows by handling text-to-vector embeddings directly within the database. However, a common architectural question arises: Can you mix raw text search queries and precomputed vectors against the same Milvus collection?
The short answer is yes, absolutely. Milvus is designed to handle both search styles seamlessly. You can pass raw text in one query and a precomputed vector in another, as long as they target the same vector field and use matching embedding models.
How Milvus Handles Mixed Search Styles
When you define a TEXTEMBEDDING function in your schema, Milvus associates a VARCHAR field (the source) with a FLOAT_VECTOR field (the target). When executing a search via client.search(), Milvus inspects the data type of the input in the data parameter:
- If you pass raw text (a string): Milvus detects the string, automatically routes it through the defined embedding function (e.g., OpenAI, HuggingFace, etc.) to generate the query vector, and then performs the vector search.
- If you pass a precomputed vector (a list of floats): Milvus bypasses the embedding function entirely and directly executes the vector search using the provided vector.
Code Examples
Here is how both search methods look in practice when targeting the same collection:
1. Searching with Raw Text
In this approach, Milvus calls your embedding provider (e.g., OpenAI) under the hood to vectorize the query before searching:
text_results = client.search(
collection_name="demo",
data=["How does Milvus generate embeddings?"],
anns_field="dense",
limit=3,
output_fields=["document"]
)
2. Searching with Precomputed Vectors
If your application has already computed and cached the vector, you can bypass the external API call and search directly:
# Precomputed 1536-dimensional vector
query_vector = [0.012, -0.031, 0.044, ...]
vector_results = client.search(
collection_name="demo",
data=[query_vector],
anns_field="dense",
limit=3,
output_fields=["document"]
)
Best Practices & Crucial Considerations
While mixing these two approaches is supported out of the box, you must adhere to the following rules to prevent unexpected search results:
- Model Consistency is Critical: The precomputed vector must be generated using the exact same embedding model and configuration (e.g.,
text-embedding-3-smallwith the same dimension size) defined in your Milvus function. If you use a different model, the vector space will not align, and your search results will be inaccurate. - Dimension Matching: Ensure the dimension of your precomputed vector matches the
dimparameter of your target vector field (e.g., 1536 for OpenAI's standard models). - Optimizing API Costs: Using precomputed vectors is highly recommended for high-throughput production environments where you can cache embeddings at the application level, saving both latency and API token costs.
Conclusion
Milvus provides the ultimate flexibility by allowing you to mix raw text queries and precomputed vectors. This capability enables you to build a highly optimized system where ad-hoc user queries can use the convenient raw-text pipeline, while high-frequency or background tasks can leverage precomputed vector caches to maximize performance.