lectio / README.md
adesh01's picture
feat: Lectio β€” HF Space deployment
14fda63
|
Raw
History Blame Contribute Delete
6.21 kB
---
title: Lectio
emoji: πŸ“–
colorFrom: yellow
colorTo: gray
sdk: docker
app_port: 7860
pinned: false
license: mit
short_description: Denomination-aware Christian AI assistant
---
# Lectio β€” Scripture Companion
Grounded, denomination-aware Christianity AI assistant built for the SoluLab technical assessment.
## Live Demo
| Service | URL |
| :-- | :-- |
| Frontend | [lectio-neon.vercel.app](https://lectio-neon.vercel.app) |
| Backend API | [adesh01-lectio.hf.space](https://adesh01-lectio.hf.space) |
| API Docs | [adesh01-lectio.hf.space/docs](https://adesh01-lectio.hf.space/docs) |
| Source | [github.com/adeshboudh/lectio](https://github.com/adeshboudh/lectio) |
## Architecture at a Glance
```
User β†’ FastAPI β†’ LangGraph Agent β†’ pgvector RAG β†’ Gemini Pro (grounded)
↓
Safety Router (regex + Gemini Flash)
↓
Citation Validator + Semantic Drift Check
↓
Image Generator (FLUX.1-dev via NVIDIA) β€” if image intent
↓
Conversation Memory (window/semantic)
```
Full design: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | HLD: [`docs/HLD.md`](docs/HLD.md)
## Features
| Feature | Implementation |
| :-- | :-- |
| Scripture RAG | pgvector HNSW cosine, bge-base-en-v1.5 embeddings, KJV corpus |
| Denomination awareness | Protestant / Catholic / Orthodox canon filtering via `@>` SQL |
| Hallucination prevention | Citation validator (regex β†’ `verse_exists()`) + semantic drift check |
| Safety moderation | Two-stage: regex (0ms) + Gemini Flash classifier |
| Image generation | FLUX.1-dev (NVIDIA) with prompt rewrite to Renaissance art style |
| Conversation memory | Window (≀10 turns) or semantic (>20 turns), denomination-switch guard |
| Evaluation harness | 20-case PASS/PARTIAL/FAIL suite with category grouping |
## Stack
| Concern | Choice |
| :-- | :-- |
| Backend | Python 3.12, FastAPI, uvicorn |
| Agent | LangGraph StateGraph |
| LLM | `gemini-3.1-flash-lite` (grounded gen) + `gemma-4-31b-it` (safety/router) |
| Embeddings | `BAAI/bge-base-en-v1.5` (local, sentence-transformers) |
| Data | PostgreSQL 16 + pgvector (NeonDB cloud) |
| Images | FLUX.1-dev via NVIDIA AI API |
| Frontend | Next.js 16, pure CSS (Lectio design system) |
| Logging | structlog |
| Package mgr | uv |
## Deployment
| Layer | Platform | Notes |
| :-- | :-- | :-- |
| Frontend | Vercel | Auto-deploy from `master`, `NEXT_PUBLIC_API_URL` points to HF Space |
| Backend | HuggingFace Spaces (Docker) | Port 7860, env secrets set in Space settings |
| Database | NeonDB (ap-southeast-1) | pgvector enabled, 31,102 KJV verses + 1,406 history chunks ingested |
## Quick Start
### Prerequisites
- Docker + Docker Compose
- Python 3.12 (via `uv`)
- Node 20+
- API keys in `backend/.env` (see `.env.example`)
### 1. Start the database
```bash
make db-up
```
### 2. Backend setup
```bash
make backend-install # uv sync β€” creates .venv, installs all deps
make backend-init # DB schema migration
make backend-ingest # embed KJV verses + church history (~30 min first run)
make dev # start API on :8000
```
### 3. Frontend
```bash
make frontend-install # npm install
make frontend-dev # Next.js on :3000
```
Open `http://localhost:3000`.
### 4. Run evaluation
```bash
make eval
```
Expected: β‰₯18/20 PASS/PARTIAL.
### Environment variables
```bash
# backend/.env
GEMINI_API_KEY=...
NVIDIA_API_KEY=... # FLUX.1-dev image generation
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/christianity_ai
```
## Project Structure
```
.
β”œβ”€β”€ backend/
β”‚ β”œβ”€β”€ app/
β”‚ β”‚ β”œβ”€β”€ agent/ # LangGraph graph, nodes, state
β”‚ β”‚ β”œβ”€β”€ api/ # FastAPI routes
β”‚ β”‚ └── core/ # db, embeddings, llm, retrieval, safety, memory, image
β”‚ └── scripts/
β”‚ β”œβ”€β”€ init_db.py # schema init
β”‚ β”œβ”€β”€ ingest_bible.py # KJV verse embeddings
β”‚ └── ingest_history.py # creed/council document embeddings
β”œβ”€β”€ eval/
β”‚ β”œβ”€β”€ dataset.json # 20 eval cases
β”‚ └── run_eval.py # harness with PASS/PARTIAL/FAIL scoring
β”œβ”€β”€ frontend/
β”‚ β”œβ”€β”€ app/ # Next.js app router (page.tsx, layout.tsx, globals.css)
β”‚ └── components/ # Composer, DenominationSelector, MessageBubble,
β”‚ # VerseBlock, EmptyState, Icons, Loading
β”œβ”€β”€ docs/
β”‚ β”œβ”€β”€ ARCHITECTURE.md
β”‚ β”œβ”€β”€ HLD.md
β”‚ β”œβ”€β”€ PHASES.md
β”‚ └── SYSTEM_DESIGN.md
β”œβ”€β”€ Makefile
└── docker-compose.yml
```
## Evaluation Categories
| Category | Cases | What it tests |
| :-- | :-- | :-- |
| adversarial | 5 | Jailbreak, rewrite, extremism β€” must be flagged + blocked |
| fake_verse | 2 | Non-existent references β€” must detect, not hallucinate |
| hallucination | 2 | Common misquotes + topics not in scripture |
| image_safety | 3 | Safety pre/post rewrite + policy block |
| historical | 3 | Council dates, creed attribution |
| denomination | 2 | Catholic vs Protestant framing (purgatory, papal infallibility) |
| theology | 2 | Predestination paradox, resurrection significance |
| scripture | 1 | Normal retrieval with citation verification |
## Key Design Decisions
**Retrieval-first grounding** β€” System prompt forbids citing anything outside the injected context block. Hallucinated refs are detected post-generation and flagged in the UI with strikethrough.
**Two-stage safety** β€” Regex catches obvious violations in <1ms. Gemini Flash handles nuanced manipulation attempts. Either stage can block.
**Public-domain corpus only** β€” KJV translation avoids copyright. NIV/ESV are not used.
**Denomination filtering** β€” Each denomination has an associated canon list. Queries filter `denomination_canon @> ARRAY[denomination]` so Orthodox/Catholic users see deuterocanon results.
**Image prompt rewriting** β€” User requests are rewritten by the LLM into safe Renaissance fine-art style before hitting FLUX.1-dev. Post-generation safety check runs on the rewritten prompt too.