Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Recall

RAG-as-a-service. A tenant signs up, creates a knowledge base, uploads docs (PDF / Markdown / txt), and a background worker chunks + embeds them into pgvector. The tenant gets a public API key and an embeddable chat widget to drop on their own site — end-users ask questions and get answers grounded in that tenant's docs, with citations. Queries are metered and billed through Stripe.

Multi-tenant SaaS built to show real full-stack range: own JWT auth, row-level tenancy, a real RAG pipeline, background jobs, Stripe metered billing, an embeddable widget, Docker, and CI — not tutorial CRUD.

Architecture

Browser ─┬─ dashboard ──────────► web (Next.js, App Router)  ← only host port (WEB_PORT)
         └─ widget (any site) ──►  │
                                   │ /api/backend/*  (proxy)
                                   ▼
                                  api (FastAPI, async SQLAlchemy)
                                   │           │
                          ┌────────┘           └────────┐
                          ▼                              ▼
                    postgres 17 + pgvector          redis ──► worker (arq)
                    tenants · users · kbs ·                    ingest: extract →
                    documents · chunks(vector) ·               chunk → embed → store
                    api_keys · subscriptions · usage_ledger
  • Ingestion is async (worker): upload → extract → chunk → embed → ready.
  • Query is inline (api): embed question → cosine-NN over the KB's chunks → grounded generation → citations → usage row.
  • Row-level multi-tenancy: every row carries tenant_id; requests scope through a current_tenant dependency.
  • Provider seam: OpenAI in prod, a deterministic offline fake provider for tests/CI — so the suite runs with no network and no keys.

Tech stack

Layer Choice
Backend Python 3.12 · FastAPI · SQLAlchemy 2 (async, psycopg3) · Alembic
Vector store Postgres 17 + pgvector (IVFFlat cosine index)
Jobs Redis + arq worker
Auth Own JWT access/refresh · argon2 password hashing
LLM OpenAI (embeddings + generation) behind a Provider interface
Billing Stripe metered (test mode) — Checkout + signature-verified webhook
Frontend Next.js (App Router) + Tailwind
Widget Vanilla JS, self-contained bundle
Infra Docker Compose · Makefile · GitHub Actions CI

Quick start

cp .env.example .env
# set JWT_SECRET (openssl rand -hex 32); add OPENAI_API_KEY for the live demo
make up            # build + start + migrate
# dashboard: http://localhost:3000   (or point portless at the web container)

External keys you must supply (not stubbed — called out honestly)

  • OPENAI_API_KEY — required for the live demo (real embeddings + generation). Without it, set LLM_PROVIDER=fake for a deterministic offline run.
  • Stripe test keys (STRIPE_ENABLED=true + STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_ID) — required only for the live billing demo. Billing code is real; the test suite mocks the Stripe client, so CI needs no keys.

Golden path

Signup → create KB → upload a doc → worker embeds it → dashboard shows the embed snippet + API key → open demo/index.html with the widget → ask a question → get a grounded answer with a citation. Full walkthrough: docs/runbooks/local-dev.md.

Develop

make test    # backend suite (LLM + Stripe mocked)
make lint    # ruff + mypy
make seed    # demo tenant + KB + API key
make         # list all commands

Docs: docs/CLAUDE.md · Architecture decisions: docs/decisions/0001-architecture.md.

About

RAG-as-a-service — upload docs, get an embeddable chat widget that answers grounded questions with citations. FastAPI · pgvector · Next.js · Docker

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages