Skip to content

P1: pgvector migration + chat/Librarian similarity cutover #977

Description

@northdpole

Summary

Migrate existing embeddings to pgvector, keep the CSV/embeddings_content columns, and cut over chatbot + similarity matching (and Librarian C.1) to use embedding_vec on Postgres.

This is a follow-on to the Heroku slug work (#975): drop app-side numpy/scipy/sklearn for prod chat matching by doing cosine in Postgres.

Related: Librarian C.1 already expects embedding_vec + <=> (PR #937 by @PRAteek-singHWY); the W8 Alembic migration was never written. Prod DB is Heroku Postgres essential-1 (pgvector extension supported; $0 for the extension itself).

Local plan: .cursor/plans/pgvector-migration.md

Goals

  1. Add embeddings.embedding_vec (pgvector), backfill from existing CSV embeddings where dim matches.
  2. Keep embeddings (CSV string) + embeddings_content (raw text) on the same row (link by PK).
  3. Dual-write on add_embedding (CSV + vector + content).
  4. Cut over chatbot and existing similarity paths to pgvector on Postgres.
  5. Enable Librarian CRE_LIBRARIAN_RETRIEVER_BACKEND=pgvector once migrated.

Locked decisions

Decision Choice
Dim policy Single project-wide dim; migration hard-fails if multiple dims detected (alert clearly)
Migration backfill Idempotent CSV → embedding_vec only (WHERE embedding_vec IS NULL + dim match)
Re-run Safe/expected after failure or partial fill — re-run migration/backfill, not LLM re-embed
Re-embed on Heroku/prod Forbidden — likely OOM-killed; re-embed only on a high-memory machine, then sync/backfill
Multi-dim Exit fail migration; do not silently pick a majority dim

Contributor warning (must land in code)

Near migration / embedding write / regenerate CLI:

Do not re-embed the full corpus on Heroku/production dynos — likely OOM-killed.
Re-embedding (fix missing / wrong-dim via LLM) must run only where there is enough RAM (local or high-resource worker), then sync/backfill vectors.
Alembic on prod only: enable extension, add column, copy CSV→vector for matching dims.

Implementation outline

  1. Alembic (Postgres-only)

    • CREATE EXTENSION IF NOT EXISTS vector
    • Detect dims; if ≠ 1 distinct → raise and abort
    • ADD COLUMN embedding_vec vector(N) with that N
    • Idempotent backfill from CSV embeddings
    • Optional HNSW index (may defer on Essential-1)
    • SQLite/CI: skip vector (CSV + in-memory fallback)
  2. db.Embeddings + add_embedding — dual-write CSV + embedding_vec

  3. Chat + existing match paths — prefer pgvector on Postgres; avoid pulling sklearn/numpy on Heroku for chat

  4. Librarian — already queries embedding_vec; flip backend env after migrate

  5. Verification

    • make alembic-guardrail before prod upgrade
    • Backup: scripts/db/backup-opencreorg.sh before prod migrate
    • Tests: dual-write, multi-dim fail, idempotent backfill
    • No re-embed in release/Procfile

Success criteria

  • Single-dim assert fails migration loudly on mixed dims
  • Matching rows backfilled; CSV + embeddings_content preserved
  • Chat uses pgvector on Postgres
  • Contributor OOM/Heroku re-embed warning present in code
  • make lint / make test / alembic guardrail green
  • Prod migrate only after backup

Out of scope

  • Dropping the CSV embeddings column
  • Automatic LLM re-embed on deploy/Heroku
  • Librarian W8 graph-write path (separate)

Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High PriorityenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions