Skip to content

selfhost(ai): Qdrant vector database profile — dedicated embeddings store for RAG #1217

Description

@JSONbored

Part of #1029.

Context

The current RAG vector store is split: sqlite-vec on the SQLite path, pgvector on the Postgres path. Both are embedded in the DB layer and are outgrown quickly — neither supports filtering, quantization, or high-cardinality search efficiently. Qdrant is a purpose-built vector database that runs as a standalone container, handles millions of embeddings, and exposes a clean REST + gRPC API. It becomes the RAG store when QDRANT_URL is set; both sqlite-vec and pgvector remain untouched as the zero-config fallbacks.

Easy on/off

# Enable:
docker compose --profile qdrant up -d
# Add to .env: QDRANT_URL=http://qdrant:6333

# Disable:
# Remove QDRANT_URL from .env — falls back to sqlite-vec or pgvector automatically

No other service depends on Qdrant. Removing the profile stops the container; unsetting the env var makes the app ignore it.

Implementation plan

docker-compose.yml

qdrant:
  image: qdrant/qdrant:latest
  profiles: ["qdrant"]
  restart: unless-stopped
  ports:
    - "6333:6333"    # REST API
    - "6334:6334"    # gRPC
  volumes:
    - qdrant-data:/qdrant/storage
  environment:
    QDRANT__SERVICE__GRPC_PORT: "6334"

src/selfhost/qdrant-vectorize.ts

New Vectorize-compatible adapter using the Qdrant REST API:

  • createQdrantVectorize(url: string): Vectorize
  • upsert(vectors)PUT /collections/{name}/points
  • query(vector, topK)POST /collections/{name}/points/search
  • Collection per-repo (namespace via collection name)
  • Falls back gracefully if Qdrant is unreachable (logs warning, returns empty results)

server.ts wiring

// After existing vectorize setup:
if (process.env.QDRANT_URL) {
  vectorize = createQdrantVectorize(process.env.QDRANT_URL);
  console.log(JSON.stringify({ event: "selfhost_vectorize", backend: "qdrant" }));
}

.env.example

# Qdrant vector database (--profile qdrant)
# QDRANT_URL=http://qdrant:6333   # enables Qdrant; omit to use sqlite-vec/pgvector
# QDRANT_COLLECTION=gittensory    # collection name (default: gittensory)

Acceptance criteria

  • docker compose --profile qdrant up starts Qdrant at ports 6333/6334
  • QDRANT_URL set → app uses Qdrant for all vector operations; logs selfhost_vectorize: qdrant
  • QDRANT_URL unset → falls back to sqlite-vec/pgvector silently
  • qdrant-vectorize.ts adapter unit tested: upsert, query, unreachable-host fallback
  • Both arms covered: QDRANT_URL set/unset in server.ts branch
  • qdrant-data volume added to docker-compose.yml volumes block
  • npm run test:ci green, Codecov ≥ 97% patch

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions