Milvus Model (the pymilvus.model package) is a Python library that gives embedding and reranking models one shared interface, so you can turn text into vectors and re-score search results without writing a separate adapter for each provider. You install it with pip install "pymilvus[model]". It runs in your application process, not inside the Milvus server: the model you pick here decides which vectors you insert and which vectors you search with. The latest release, 0.3.4, exports twelve dense embedding functions, two sparse, two hybrid (dense plus sparse), and seven rerankers.
Every embedding function follows the same pattern: encode_documents() for the corpus, encode_queries() for search input, and a dim property that tells you how large to make the vector field. Every reranker is a callable that takes a query, a list of documents, and top_k. Swapping OpenAI for a local Sentence Transformers model is therefore a one-line change, as long as you re-embed the collection.
Three places to generate a representation. A wrapper export is not proof of executed inference or universal compatibility.
How do you use a Milvus Model embedding function?
Install the extra and encode a few documents:
pip install "pymilvus[model]"
from pymilvus import model
ef = model.DefaultEmbeddingFunction() # alias for OnnxEmbeddingFunction
docs = [
"Artificial intelligence was founded as an academic discipline in 1956.",
"Alan Turing was the first person to conduct substantial research in AI.",
]
doc_vectors = ef.encode_documents(docs) # list of numpy arrays
query_vectors = ef.encode_queries(["Who started AI research?"])
print(ef.dim, doc_vectors[0].shape) # use ef.dim for the FLOAT_VECTOR field
Read ef.dim before you create the collection and set the vector field’s dim to that value. The output vectors are ready for MilvusClient.insert() and MilvusClient.search(). Some wrappers treat queries and documents differently (Cohere, Voyage, and Jina pass a task or input type to the provider; BM25 and SPLADE weight them differently), so always use encode_queries at search time instead of reusing the document method.
Sparse functions return SciPy csr_array rows that go into a SPARSE_FLOAT_VECTOR field. Client-side BM25 needs corpus statistics before it can encode anything:
from pymilvus.model.sparse import BM25EmbeddingFunction
from pymilvus.model.sparse.bm25 import build_default_analyzer
bm25 = BM25EmbeddingFunction(build_default_analyzer(language="en"))
bm25.fit(docs) # compute IDF over your corpus
bm25.save("bm25_params.json") # reload the same statistics at query time
sparse_docs = bm25.encode_documents(docs)
Hybrid functions such as BGEM3EmbeddingFunction return a dictionary with "dense" and "sparse" keys (and optional ColBERT vectors), and their dim is a dictionary too. Each output needs its own field in the schema, which pairs naturally with hybrid search.
Which embedding function should you use?
Start from where you want inference to run and what kind of retrieval you need:
| If you want… | Use | Notes |
|---|---|---|
| A hosted API you already pay for | OpenAIEmbeddingFunction, CohereEmbeddingFunction, VoyageEmbeddingFunction, JinaEmbeddingFunction, MistralAIEmbeddingFunction, GeminiEmbeddingFunction, NomicEmbeddingFunction | Fastest path; pass an explicit model_name and API key |
| Local inference with an open model | SentenceTransformerEmbeddingFunction | Covers most Hugging Face sentence-embedding checkpoints |
| A small CPU-friendly baseline | Model2VecEmbeddingFunction or DefaultEmbeddingFunction | Good for tests and prototypes, weaker on quality |
| Your own inference server | TEIEmbeddingFunction | Points at a Hugging Face Text Embeddings Inference endpoint |
| Keyword-style sparse retrieval | BM25EmbeddingFunction, SpladeEmbeddingFunction | BM25 needs fit(); SPLADE is a learned sparse model |
| Dense and sparse from one model | BGEM3EmbeddingFunction, MGTEEmbeddingFunction | One encode call, two vector fields |
| Better ordering of a shortlist | CohereRerankFunction, VoyageRerankFunction, JinaRerankFunction (hosted) or BGERerankFunction, CrossEncoderRerankFunction (local) | Run after the initial vector search |
Model quality matters more than the wrapper. Use MTEB and an evaluation set from your own data to pick the model, then pick the wrapper that runs it.
The full catalog in 0.3.4
The defaults below are what the wrapper uses if you pass no model_name. Several are older model generations, so pin the model you actually evaluated.
| Category | Export | Default model | What it does |
|---|---|---|---|
| dense | OpenAIEmbeddingFunction | text-embedding-ada-002 | Hosted OpenAI text embeddings |
| dense | SentenceTransformerEmbeddingFunction | all-MiniLM-L6-v2 | Local Sentence Transformers models |
| dense | VoyageEmbeddingFunction | voyage-3-large | Hosted Voyage embeddings; its dimension table predates Voyage 4 |
| dense | JinaEmbeddingFunction | jina-embeddings-v3 | Jina text API with task and dimension options |
| dense | TEIEmbeddingFunction | set by the endpoint | Calls a Text Embeddings Inference server |
| dense | OnnxEmbeddingFunction | GPTCache/paraphrase-albert-onnx | Bundled ONNX model; also exported as DefaultEmbeddingFunction. Not a general ONNX loader |
| dense | CohereEmbeddingFunction | embed-english-light-v3.0 | Hosted Cohere embeddings with query/document input types |
| dense | MistralAIEmbeddingFunction | mistral-embed | Hosted Mistral text embeddings |
| dense | NomicEmbeddingFunction | nomic-embed-text-v1.5 | Nomic SDK text embeddings |
| dense | InstructorEmbeddingFunction | hkunlp/instructor-xl | Instruction-conditioned embeddings |
| dense | Model2VecEmbeddingFunction | minishlab/potion-base-8M | Static, very fast Model2Vec embeddings |
| dense | GeminiEmbeddingFunction | gemini-embedding-exp-03-07 | Gemini text embeddings; predates Gemini Embedding 2 |
| sparse | SpladeEmbeddingFunction | naver/splade-cocondenser-ensembledistil | Learned sparse (lexical) vectors |
| sparse | BM25EmbeddingFunction | none; fit on your corpus | Client-side BM25 with an analyzer, k1=1.5, b=0.75 |
| hybrid | BGEM3EmbeddingFunction | BAAI/bge-m3 | Dense, sparse, and optional ColBERT output |
| hybrid | MGTEEmbeddingFunction | Alibaba-NLP/gte-multilingual-base | Multilingual dense and sparse output |
| reranker | CohereRerankFunction | rerank-english-v3.0 | Hosted Cohere reranking |
| reranker | BGERerankFunction | BAAI/bge-reranker-v2-m3 | Local BGE reranker via FlagEmbedding |
| reranker | VoyageRerankFunction | rerank-2 | Hosted Voyage reranking (older default) |
| reranker | CrossEncoderRerankFunction | none; pass model_name | Local Sentence Transformers CrossEncoder |
| reranker | JinaRerankFunction | jina-reranker-v2-base-multilingual | Hosted Jina reranking |
| reranker | JevRerankFunction | jev-latest | TypeSafe Jev evidence scoring with a scientific-claim template |
| reranker | TEIRerankFunction | set by the endpoint | Reranking through a TEI server |
What the library does not cover
The wrappers are text-first. They do not produce image, video, or audio embeddings, and they have no dedicated export for newer checkpoints such as WeMM, KaLM, or R3. For those, call the provider’s SDK or a multimodal model directly and insert the vectors yourself. A wrapper also does not guarantee that every model name you pass will work: Voyage 4 or Gemini Embedding 2 can be requested explicitly, but verify the returned dimension and normalization before encoding a full corpus.
The package name has history worth knowing. The current distribution is pymilvus.model on PyPI, which pymilvus[model] installs for you; the older milvus-model name has a separate release history, so don’t copy an import path from an old notebook without checking it.
Client-side model library or server-side Function?
Milvus can also generate embeddings itself. Since Milvus 2.6, you can declare a TEXTEMBEDDING Function in the collection schema (providers include OpenAI, Azure OpenAI, Cohere, Voyage AI, Gemini, AWS Bedrock, Vertex AI, and TEI), and a BM25 Function computes full-text sparse vectors on the server. Then you insert raw text and search with raw text.
Use pymilvus.model when you want to run open models locally, control batching and GPUs yourself, or reuse the same vectors outside Milvus. Use server-side Functions when you want the database to own the text-to-vector step so every client stays consistent. Note that client-side BM25EmbeddingFunction and the server BM25 Function keep different corpus statistics, so pick one per collection. The trade-offs are covered in client model wrappers vs. server Functions.
Related reading
- How do client model wrappers, server Functions, and rank fusion differ?
- Which dense, sparse, and compact embedding families should you compare?
- How should you serve and version embedding and reranking models for Milvus?
- Which reranking models fit a Milvus retrieval pipeline?
- How should you build a reproducible application workflow with PyMilvus?
To put an embedding function to work, follow the Milvus Quickstart and swap in the function you chose, or see the embedding overview for more examples.