AI project

Backstory

RAG memory layer for legacy systems

Eval gate: ≥80% recall@5, ≥90% citation correctness

Backstory landing page: "Code tells you what. Backstory remembers why." with a cited answer receipt
  • Next.js
  • FastAPI
  • pgvector
  • Groq
  • Celery
  • Redis
  • PostgreSQL
  • Whisper
  • Clerk
  • pytest
  • Playwright
  • Docker

The story

Ask why a piece of old code works the way it does. Backstory answers from the project's own history, shows where each answer came from, and says so when it doesn't know.

The hard part
Making refusal honest: retrieval that is mostly right is easy, but guaranteeing every sentence traces to a real citation needed a gate before generation, a citation check after it, and an eval suite (recall@5, citation correctness) to prove the rule held.

How it’s built

Inside Backstory

System architecture

  1. STAGE 01

    • Next.js app · Client
      • → Clerk multi-tenant auth (sign-in)
      • → FastAPI (question)
  2. STAGE 02

    • Clerk multi-tenant auth · External
    • FastAPI · Service
      • → Redis queue (ingest jobs)
      • → Hybrid retrieval
  3. STAGE 03

    • Redis queue · Data
      • → Celery ingestion workers
    • Hybrid retrieval · AI
      • → Postgres + pgvector (search)
      • → Evidence gate
  4. STAGE 04

    • Celery ingestion workers · Service
      • → Whisper interview transcription (interviews)
      • → Postgres + pgvector (chunks + embeddings)
    • Evidence gate · AI
      • → Groq LLM generation (enough evidence)
  5. STAGE 05

    • Whisper interview transcription · AI
    • Postgres + pgvector · Data
    • Groq LLM generation · External
      • → Citation check or honest refusal (draft answer)
  6. STAGE 06

    • Citation check or honest refusal · AI

Engineering decisions

  1. Decision 01

    Two gates, not one prompt

    Evidence is checked before the LLM is called (is there enough to answer at all?) and every sentence is checked after (does it trace to a real citation?). Hallucinations are stopped by the pipeline, not by asking the model nicely.

  2. Decision 02

    Refusal is a feature

    When the evidence isn't there, the answer is "I don't have this", shown as a real answer with a next step. A confident wrong answer about legacy code costs more than an honest gap.

  3. Decision 03

    Hybrid retrieval

    Vector search on pgvector finds meaning; keyword search catches exact function names and ticket IDs that embeddings blur. Code needs both.

  4. Decision 04

    Slow work off the request path

    Ingestion and Whisper transcription run as Celery workers on a Redis queue, so the chat stays fast while large repos and interviews are processed in the background.

  5. Decision 05

    Quality is a release gate

    A pytest eval suite measures retrieval recall and citation correctness on every release. If recall@5 drops below 80% or citations below 90%, it doesn't ship.