Skip to main content

A lightweight, open-source vector-database migration & infrastructure CLI (Alembic for vector databases).

Project description

vecbee

Alembic for vector databases.

Migrate, sync, and re-embed vector data across stores with blue-green zero-downtime cutovers — all driven by one declarative vector.config.yaml.

PyPI version Python versions License: Apache-2.0 CI mypy strict


Why vecbee?

Relational databases have had migration tooling for decades — Alembic, Flyway, Rails migrations. Vector databases have had almost nothing. When your embedding model changes, your chunking strategy improves, or you outgrow your vector store, you're left writing one-off scripts, praying nothing breaks, and taking downtime while you rebuild an index.

vecbee treats vector migrations like the versioned, reviewable, reversible operations they should be. It re-embeds and re-chunks into a shadow collection, verifies it, then does an atomic alias swap — your application never queries a half-built index, and if something's wrong you roll back with one command.

pip install vecbee
vecbee init      # scaffolds a runnable project — zero API keys, zero infra
vecbee up        # runs the full pipeline for $0 (mock embeddings + local store)

That first up runs end-to-end with no paid API calls and no external services, so you can see exactly what vecbee does before pointing it at anything real.


Features

  • 🐝 Blue-green zero-downtime cutovers — migrations build a shadow collection and flip a stable alias atomically. Readers never see a partial index.
  • Reversiblevecbee down reverts the most recently applied migration.
  • 🔀 Three migration modessql_chunk_embed (chunk + embed rows from any SQL source), re_embed (re-embed existing content with a new model), and pure_copy (move vectors verbatim, zero embedding calls).
  • 📈 Incremental sync — an updated_at watermark means re-runs only process changed rows, not the whole table.
  • 🔎 Drift detectionvecbee status reconciles applied migration history against your local migration files and reports drift before you touch production.
  • 🧾 Dead-letter queue — every failed record is written to dlq/ as self-describing JSONL. Nothing is ever silently dropped.
  • 🔁 Resumable & rate-limit aware — upsert-by-source-id makes runs idempotent; exponential backoff handles 429s from embedding APIs.
  • 🧩 Pluggable — sources, targets, and embedding providers are swappable drivers; third-party plugins register via a standard entry-point group.
  • 💸 Zero-cost default pathmock provider + local SQLite store means CI and first-run cost nothing and need no network.
  • 🎛️ Declarative — one vector.config.yaml is the whole contract. No imperative glue code.

Quickstart

1. Install

pip install vecbee
# optional extras for real targets/providers:
pip install "vecbee[qdrant]"      # Qdrant vector target
pip install "vecbee[postgres]"    # Postgres/asyncpg source

2. Scaffold a project

vecbee init

This writes a runnable vector.config.yaml (wired to the mock provider + local store), a sample SQL source fixture, and a migrations/ directory.

3. Run the pipeline — for $0

vecbee up

up chunks and embeds the sample data into a shadow collection, then atomically swaps the docs alias to it. No API keys, no Docker, no cost.

4. Point it at your own data

Edit the source block in vector.config.yaml to your real database, swap provider.driver to a real embedding API, and re-run vecbee up.


How it works

                    ┌─────────────────────────────────────────────┐
   vector.config    │  vecbee up                                   │
   .yaml  ────────► │                                              │
                    │  source ──► chunk ──► embed ──► shadow write  │
                    │   (SQL)     (recursive)  (provider)   │       │
                    │                                       ▼       │
   migrations/  ──► │                              ┌── reconcile ──┐│
   0001_*.yaml      │                              │  verify count ││
                    │                              └──────┬────────┘│
                    │        readers query  ◄── alias ────┘         │
                    │        "docs"          atomic swap (cutover)  │
                    └─────────────────────────────────────────────┘
                    failed records ──► dlq/*.jsonl   (never dropped)

The alias (collection: in your config) is the stable name your application queries. A migration never mutates the live collection in place — it builds a new shadow collection and, only once written and reconciled, repoints the alias. That repoint is the cutover.


Commands

Command What it does
vecbee init Scaffold a runnable project (vector.config.yaml + sample fixtures + migrations/).
vecbee status Reconcile applied migration history vs. local migration files; report drift.
vecbee up Blue-green migration into a shadow collection + atomic cutover.
vecbee down Revert the most recently applied migration.
vecbee run-ext <name> Load and run one extension standalone (no args → list discoverable extensions).
vecbee --version Print the installed version.

Configuration

vecbee init generates this annotated starter. Every block below already works end-to-end against the zero-cost defaults; edit source to migrate your own data.

source:
  driver: sql                       # read rows from any SQLAlchemy-supported database
  dsn: "sqlite+aiosqlite:///./.vecbee/sample_data/sample_sql_source.db"
  table: documents
  updated_at_column: updated_at     # enables incremental sync

target:
  driver: local                     # zero-infra SQLite store with real atomic alias-swap
  collection: docs                  # the stable alias your application queries
  path: "./.vecbee/local_target.db"

provider:
  driver: mock                      # deterministic, zero-cost, offline embeddings
  dimensions: 8

chunker:
  driver: recursive                 # langchain-text-splitters RecursiveCharacterTextSplitter
  chunk_size: 1000
  chunk_overlap: 200

state_store:
  dsn: "sqlite+aiosqlite:///./.vecbee/state.db"   # tracks migration history

migrations:
  dir: "./migrations"               # your NNNN_<slug>.yaml migration files

dlq:
  path: "./dlq"                     # failed records land here as JSONL

concurrency: 8                      # in-flight records
batch_size: 64                      # records per batch

Values support ${ENV_VAR} interpolation for secrets (see .env.example).

Drivers & providers

Kind Driver Notes
Source sql Any SQLAlchemy dialect (SQLite, Postgres via [postgres], …).
Source vector_local Read vectors back out of a local store (e.g. for pure_copy).
Target local Zero-infra SQLite store with WAL-backed atomic alias swap.
Target qdrant Real Qdrant target (pip install "vecbee[qdrant]").
Provider mock Deterministic offline embeddings — $0, CI-safe.
Provider openai_compat Any OpenAI-compatible embeddings endpoint (key-gated).
Chunker recursive RecursiveCharacterTextSplitter with configurable size/overlap.

Architecture

vecbee enforces one hard rule: engine/ is pure domain logic and must never import display/ or Rich. The engine emits plain dataclasses; display/ is the only place Rich is used to render them. This boundary is enforced in CI by import-linter, so the core stays testable, scriptable, and free of presentation concerns.

src/vecbee/
├── abc/         # provider / source / target / hooks interfaces (the contracts)
├── engine/      # pure orchestration: pipeline, reconciler, drift, dlq, backoff, modes
├── drivers/     # concrete sources, targets, providers, chunker
├── config/      # vector.config.yaml loading, validation, secrets
├── cli/         # Typer commands (init / status / up / down / run-ext)
├── display/     # Rich rendering — the ONLY place Rich is imported
├── plugins/     # entry-point discovery for third-party drivers
└── state/       # migration-history persistence

Extending vecbee

Third-party drivers register under the vecbee.plugins entry-point group. In your plugin package's pyproject.toml:

[project.entry-points."vecbee.plugins"]
my_target = "my_pkg.my_module:MyTargetDriver"

Then vecbee run-ext will discover it, and it becomes usable as a driver: in config.


Development

git clone https://github.com/Caoquyen1913/vecbee.git
cd vecbee
pip install -e ".[dev,qdrant]"

ruff check .        # lint
mypy                # strict type-check on engine/abc/config
lint-imports        # enforce the engine ↛ display boundary
pytest              # full test suite

The optional Qdrant integration check runs against a real dockerized Qdrant:

docker compose up -d qdrant
QDRANT_URL=http://localhost:6333 python scripts/qdrant_integration_check.py
docker compose down

Project status

Alpha (0.1.0). The interface is exercised by a large passing test suite and every acceptance criterion, but has no real-world usage history yet. Expect the API to stabilize toward 0.2.0. Feedback and issues are very welcome.

Contributing

Contributions are welcome! Please open an issue to discuss substantial changes first. Before submitting a PR, make sure ruff, mypy, lint-imports, and pytest all pass locally (they're gated in CI). See PUBLISHING.md for the release process.

License

Apache-2.0 © Kawin Tran (@Caoquyen1913) and AI Outsourcing Studio.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vecbee-0.1.0.tar.gz (353.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vecbee-0.1.0-py3-none-any.whl (145.9 kB view details)

Uploaded Python 3

File details

Details for the file vecbee-0.1.0.tar.gz.

File metadata

  • Download URL: vecbee-0.1.0.tar.gz
  • Upload date:
  • Size: 353.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vecbee-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5717d578fd3e33b37a065035f24ebe49e320408441c9d34b1d21956ce98783ef
MD5 653621e393743b53ab65e7521215f05a
BLAKE2b-256 01e7533448bb24e5345f25e124a3f59e821d28cc606f307526c7e3ba90804d6a

See more details on using hashes here.

Provenance

The following attestation bundles were made for vecbee-0.1.0.tar.gz:

Publisher: release.yml on Caoquyen1913/vecbee

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vecbee-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: vecbee-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 145.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vecbee-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 93ba76c016118a12af6a0b68689965a246a032529c7a95d341f72d04d1935928
MD5 ce94bf5e1627f56b774b1d021b293d01
BLAKE2b-256 57f031359f7523d235769b4bde9f015b8abfabf981568ec4a0dabba46f8907b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for vecbee-0.1.0-py3-none-any.whl:

Publisher: release.yml on Caoquyen1913/vecbee

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page