Quickstart

The 1.x line targets CPython 3.11–3.15 and ClickHouse 26.3 and 26.8 LTS. Use an existing server or start an isolated local one.

export CLICKHOUSE_USER=chrag
export CLICKHOUSE_PASSWORD="$(python3 -c 'import secrets; print(secrets.token_urlsafe(24))')"
docker run --detach --rm --name chrag-demo \
  --publish 127.0.0.1:8123:8123 \
  --env CLICKHOUSE_USER --env CLICKHOUSE_PASSWORD \
  clickhouse/clickhouse-server:26.8.36.3

python -m pip install 'clickhouserag>=1,<2'

If the server is still starting, wait until curl -fsS http://127.0.0.1:8123/ping returns Ok. Run this example in the same shell.

import os

import clickhouse_connect

from clickhouserag import Chunk, ClickHouseStore, EmbeddedChunk

with clickhouse_connect.get_client(
    host="127.0.0.1",
    port=8123,
    username=os.environ["CLICKHOUSE_USER"],
    password=os.environ["CLICKHOUSE_PASSWORD"],
    autogenerate_session_id=False,
    form_encode_query_params=True,
) as client:
    store = ClickHouseStore(client, table="demo_passages", embedding_model="toy-v1", dimensions=2)
    store.initialize()
    store.insert(
        [
            EmbeddedChunk(
                Chunk(
                    chunk_id="retention-1",
                    document_id="runbook",
                    text="ERR531 indicates that retention exceeded the configured window.",
                    source="https://example.com/runbook#retention",
                    metadata={"product": "storage"},
                ),
                [1.0, 0.0],
            )
        ],
        namespace="runbooks",
    )
    for hit in store.search_hybrid(
        "ERR531 retention",
        [1.0, 0.0],
        namespace="runbooks",
        metadata={"product": "storage"},
    ):
        print(hit.chunk.text, hit.chunk.source)

Run docker stop chrag-demo to remove the temporary server.

For a model-backed application, implement the EmbeddingProvider protocol and pass it to Retriever. Include the model version and the relevant encoding configuration in model_id. Provide separate document and query encoders when the model expects different prompts or prefixes. The caller owns document chunking and generation. Store stable chunk IDs and resolvable source pointers.

Pass previously chunked data to store.insert or Retriever.index in batches. For local development from a clone, install uv, then run uv sync --locked and uv run --locked python examples/basic_usage.py.