Skip to main content

Usage

The #[model] macro specifies which embedding model to use for Embed() calls within a query. This allows you to optimize embeddings for different use cases—such as storing documents versus searching them.
#[model("provider:model-name:task-type")]
QUERY QueryName(param: Type) =>
    result <- AddV<Type>(Embed(param), {properties})
    RETURN result
The #[model] macro overrides the default embedding model configured in your helix.toml file for that specific query.

Syntax Reference

The model string follows the format "provider:model-name:task-type":
  • provider The embedding service provider
  • model-name The specific model identifier
  • task-type Task optimization hint

Supported models

ProviderModelTask TypeNotes
geminigemini-embedding-001RETRIEVAL_DOCUMENT OR RETRIEVAL_QUERYRETRIEVAL_DOCUMENT is the default if no task type is included
openaitext-embedding-ada-002Not SupportedNot recommended
openaitext-embedding-smallNot Supported
openaitext-embedding-largeNot Supported

Many embedding providers offer task-specific optimizations. For example, Gemini’s embedding models support task types that hint whether the text being embedded is a document (to be stored and searched) or a query (used to search documents).
  • RETRIEVAL_DOCUMENT - Optimized for embedding documents that will be stored and retrieved later
  • RETRIEVAL_QUERY - Optimized for embedding search queries that find relevant documents
Using the appropriate task type can improve search relevance and retrieval quality.
All vectors in a vector type must have the same dimensions. When using different task types, ensure both use the same model (e.g., gemini-embedding-001) so the dimensions match.

This example shows how to use different task types for storing clinical notes versus searching them.
#[model("gemini:gemini-embedding-001:RETRIEVAL_DOCUMENT")]
QUERY addClinicalNote (text: String) =>
    note <- AddV<ClinicalNote>(Embed(text), {text: text})
    RETURN note

#[model("gemini:gemini-embedding-001:RETRIEVAL_QUERY")]
QUERY searchClinicalNotes (query: String, k: I64) =>
    notes <- SearchV<ClinicalNote>(Embed(query), k)
    RETURN notes
Here’s how to run the queries using the SDKs or curl:
from helix.client import Client

client = Client(local=True, port=6969)

# Store clinical notes with RETRIEVAL_DOCUMENT optimization
notes = [
    "Patient presents with acute lower back pain radiating to left leg.",
    "Follow-up visit: Blood pressure 120/80, heart rate normal.",
    "MRI results show mild disc herniation at L4-L5 level."
]

for note in notes:
    client.query("addClinicalNote", {"text": note})

# Search with RETRIEVAL_QUERY optimization
results = client.query("searchClinicalNotes", {
    "query": "back pain symptoms",
    "k": 5
})

print(results)
Make sure to set your GEMINI_API_KEY environment variable (or OPENAI_API_KEY for OpenAI models) in the same location as your queries.hx, schema.hx, and config.hx.json files.

Best Practices

Always use the same embedding model for all queries that operate on the same vector type. Different models produce vectors with different dimensions, which will cause errors.
// Good - same model, different task types
#[model("gemini:gemini-embedding-001:RETRIEVAL_DOCUMENT")]
QUERY storeDoc (text: String) => ...

#[model("gemini:gemini-embedding-001:RETRIEVAL_QUERY")]
QUERY searchDocs (query: String, k: I64) => ...

// Bad - different models for same vector type
#[model("gemini:gemini-embedding-001:RETRIEVAL_DOCUMENT")]
QUERY storeDoc (text: String) => ...

#[model("openai:text-embedding-3-small")]
QUERY searchDocs (query: String, k: I64) => ...
Use RETRIEVAL_DOCUMENT for operations that store data and RETRIEVAL_QUERY for operations that search data.
// Storing documents
#[model("gemini:gemini-embedding-001:RETRIEVAL_DOCUMENT")]
QUERY addDocument (content: String) =>
    doc <- AddV<Document>(Embed(content), {content: content})
    RETURN doc

// Searching documents
#[model("gemini:gemini-embedding-001:RETRIEVAL_QUERY")]
QUERY findDocuments (query: String, limit: I64) =>
    docs <- SearchV<Document>(Embed(query), limit)
    RETURN docs
If you don’t need task-specific optimization, you can skip the #[model] macro and use the default model from your config.hx.json.
// Uses default model from config.hx.json
QUERY simpleSearch (text: String, k: I64) =>
    results <- SearchV<Document>(Embed(text), k)
    RETURN results