Skip to content

Configuration

haiku.rag reads its configuration from a YAML file. Every setting has a default, so a file sets only what differs.

Note

The embedding model in the configuration must match the one a database was built with. See Operational constraints for what a mismatch does and how to reconcile it.

Getting started

Generate a configuration file with defaults:

haiku-rag init-config

This writes haiku.rag.yaml in the current directory with every setting and its default. haiku-rag settings prints the configuration in effect.

Configuration file locations

haiku.rag searches for configuration files in this order:

  1. Path specified via --config flag: haiku-rag --config /path/to/config.yaml <command>, or the HAIKU_RAG_CONFIG_PATH environment variable, which library use reads too. A path that does not exist is an error.
  2. ./haiku.rag.yaml (current directory)
  3. Platform-specific user directory:
    • Linux: ~/.local/share/haiku.rag/haiku.rag.yaml
    • macOS: ~/Library/Application Support/haiku.rag/haiku.rag.yaml
    • Windows: C:/Users/<USER>/AppData/Roaming/haiku.rag/haiku.rag.yaml

Environment variables

Any string value can reference an environment variable, so secrets stay out of the file and one config can serve multiple deployments:

ingester:
  queue:
    dburi: postgresql+asyncpg://haiku:${POSTGRES_PASSWORD}@db:5432/haiku_rag
    namespace: ${SOURCE}
  • ${VAR} is replaced with the value of VAR. If VAR is unset or empty, loading fails with an error naming the variable.
  • ${VAR:-default} uses default when VAR is unset or empty.
  • $$ produces a literal $.
  • ${HAIKU_RAG_CONFIG_DIR} is the absolute directory of the config file, so ${HAIKU_RAG_CONFIG_DIR}/papers.lancedb places a database next to it. The environment cannot override it.

Substitution happens after the YAML is parsed, so a value containing :, @, or # fills the string verbatim and never changes the document structure.

Database fragments

databases_include names a directory of files that each add databases, so a provisioner can own one file per database and leave the main file alone:

# haiku.rag.yaml
databases_include: databases.d
# databases.d/notes.yaml
lancedb:
  databases:
    notes: ${HAIKU_RAG_CONFIG_DIR}/notes.lancedb
ingester:
  databases:
    notes:
      sources:
        - type: fs
          root: /uploads/notes
  • A relative directory is relative to the main file's directory. A missing or empty directory adds nothing.
  • Every *.yaml file in it loads in name order. Dotfiles and other extensions are skipped.
  • A fragment may set only lancedb.databases and ingester.databases. Any other key fails loading with an error naming the file.
  • A database name defined twice, in two fragments or in a fragment and the main file, fails loading with an error naming both files.
  • Environment variables and ${file:path} expand in a fragment as in the main file, and ${HAIKU_RAG_CONFIG_DIR} is the main file's directory.
  • The ingester's reload reads the directory again, so adding or deleting a fragment adds or removes its database.

Only configuration loaded from a file reads fragments. A host that builds AppConfig itself places no fragment databases.

File-based secrets

Use ${file:path} in any string value to read a mounted secret:

ingester:
  queue:
    dburi: postgresql+asyncpg://haiku:${file:/run/secrets/db_password}@db:5432/haiku_rag
  api:
    auth_token: ${file:/run/secrets/ingester_token}

Paths may be absolute or relative to the YAML configuration file's directory. ${file:-x} is the environment variable file with default x, so write a relative path starting with - as ${file:./-x}. Files must contain UTF-8 text. Trailing \r and \n characters are removed. Spaces and internal line endings are preserved. Missing, unreadable, invalid UTF-8 and empty files fail configuration loading with an error naming the path.

File contents are substituted literally after YAML parsing, without expanding references inside them. $${file:path} produces the literal ${file:path}. Files are read on each configuration load and are not watched for changes. An ingester reload rereads them, but it refuses a changed value outside lancedb.databases and ingester.databases, so a rotated queue password or API token needs a restart.

Interpolation does not URL-encode values. A password embedded in a connection URL must already be percent-encoded where required. Alternatively, store the complete connection URL in a file and use dburi: ${file:/run/secrets/dburi}.

Environment

environment defaults to production. In the CLI, any value other than development silences Python warnings and Logfire console output.

Minimal configuration

A minimal configuration file with defaults. These qa.model values are the defaults only when the qa section is omitted. Once you write a qa.model block, each field you leave out takes the ModelConfig default: vision: false, and no thinking, temperature or max_tokens. The same holds for processing.title_model and processing.conversion_options.picture_description.model.

# haiku.rag.yaml
environment: production

embeddings:
  model:
    provider: ollama
    name: qwen3-embedding:4b
    vector_dim: 2560

qa:
  model:
    provider: ollama
    name: qwen3.8
    thinking: true

Programmatic configuration

When using haiku.rag as a Python library, you can pass configuration directly to the HaikuRAG client:

from haiku.rag.config import AppConfig
from haiku.rag.config.models import EmbeddingModelConfig, ModelConfig, QAConfig, EmbeddingsConfig
from haiku.rag.client import HaikuRAG

# Create custom configuration
custom_config = AppConfig(
    qa=QAConfig(
        model=ModelConfig(
            provider="openai",
            name="gpt-4o",
            temperature=0.3
        )
    ),
    embeddings=EmbeddingsConfig(
        model=EmbeddingModelConfig(
            provider="ollama",
            name="qwen3-embedding:4b",
            vector_dim=2560
        )
    ),
    processing={"chunk_size": 512}
)

# Pass configuration to the client
async with HaikuRAG(config=custom_config) as client:
    ...

Without config, the client uses the configuration loaded from the YAML file, or the defaults. Clients in one process can each take a different configuration.

Configuration topics