Skip to content

Latest commit

 

History

History
54 lines (41 loc) · 2.68 KB

File metadata and controls

54 lines (41 loc) · 2.68 KB

Design Decisions (ADR-style)

Short records of the non-obvious choices. Format: Context / Decision / Consequences.

1. pgvector over a dedicated vector database

  • Context: We need vector similarity search plus relational data (issues, classifications, analyses).
  • Decision: Use PostgreSQL + pgvector for both, rather than adding a dedicated vector store (Milvus/Qdrant/etc.).
  • Consequences: One datastore to run, back up, and reason about. Joins between vectors and relational rows are trivial. At very large scale a dedicated store may win, but for this workload a single Postgres is simpler and sufficient.

2. Local embeddings over a hosted embedding API

  • Context: The demo must be cheap and reproducible by anyone.
  • Decision: Embed locally with sentence-transformers (all-MiniLM-L6-v2).
  • Consequences: No API key, no cost, deterministic. First run downloads the model (cached in a volume). Quality is lower than large hosted embeddings but more than enough to demonstrate semantic retrieval.

3. LLM behind a Protocol, with a rule-based fallback

  • Context: Reviewers may not have an API key; LLM calls can fail.
  • Decision: Define LLMProvider as a Protocol; ship Claude and OpenAI adapters plus a RuleFallback. The factory returns the fallback when no key is configured, and the analyzer degrades to it if a live call errors.
  • Consequences: docker compose up works offline. The pipeline shape is identical across providers. Tests run without secrets.

4. Hybrid classification (KNN + keyword) instead of pure KNN

  • Context: Issues have no category; the case library may not cover every phrasing.
  • Decision: Vote with semantic KNN over the labeled case library, backed by a small keyword ruleset, and record the deciding source.
  • Consequences: Handles cold-start phrasings while staying mostly semantic. The source field makes decisions explainable.

5. No vector index at demo scale

  • Context: ~200 issues + ~40 cases.
  • Decision: Do not create an ivfflat/hnsw index. A sequential scan is fast here and gives perfect recall; an ivfflat index built on a tiny table hurts recall.
  • Consequences: Simpler setup, exact results. The index statement to add at scale is documented in migrations/001_init.sql.

6. ORM as schema source of truth; SQL migration only for the extension

  • Context: Avoid drift between an init SQL file and the ORM models.
  • Decision: Create tables from app/models.py on startup; 001_init.sql only runs CREATE EXTENSION vector.
  • Consequences: One place defines the schema. For a production system you would switch to versioned migrations (e.g. Alembic).