@@ -18,9 +18,13 @@ An open-source, local-first platform for structured Bitcoin education. Transform
1818
1919### Prerequisites
2020
21- - Node.js 18+
22- - Python 3.10+
23- - PostgreSQL (running and accessible)
21+ | Requirement | Version | Notes |
22+ | ---| ---| ---|
23+ | Node.js | ** ≥ 22.17** | Required by ` @qvac/sdk ` (bare runtime shims). |
24+ | Python | 3.11 | For the FastAPI backend and ingestion pipeline. |
25+ | PostgreSQL | any recent | Running and accessible. |
26+ | Disk space | ~ 2 GB | For the QVAC embedding model (~ 670 MB) downloaded on first run. |
27+ | RAM | ≥ 8 GB | For the default LLM when one is configured (see QVAC docs). |
2428
2529### Recommended
2630
@@ -31,21 +35,22 @@ chmod +x start-dev.sh
3135
3236This script creates a Python virtualenv under ` services/ai/venv/ ` , installs dependencies for both services, seeds the database with test users, and starts both servers.
3337
34- | Service | URL |
35- | ---------------| ----------------------------------------------|
36- | Frontend | < http://localhost:3000 > |
37- | Backend API | < http://localhost:8000 > |
38- | Swagger UI | < http://localhost:8000/docs > |
39- | ReDoc | < http://localhost:8000/redoc > |
38+ | Service | URL |
39+ | ----------------| ----------------------------|
40+ | Frontend | < http://localhost:3000 > |
41+ | Backend API | < http://localhost:8000 > |
42+ | QVAC service | < http://localhost:3001 > |
43+ | Swagger UI | < http://localhost:8000/docs > |
44+ | ReDoc | < http://localhost:8000/redoc > |
4045
4146> Swagger UI and ReDoc are only available in ` development ` environment.
4247
4348** Dev credentials (seeded automatically):**
4449
45- | Role | Email | Password |
46- | ---------| ---------------------------- | -----------------------|
47- | Admin | admin@bitpolito.it | DevAdmin@2024!Secure |
48- | Student | student@bitpolito.it | DevStudent@2024!Learn |
50+ | Role | Email | Password |
51+ | ---------| ----------------------| -----------------------|
52+ | Admin | admin@bitpolito.it | DevAdmin@2024!Secure |
53+ | Student | student@bitpolito.it | DevStudent@2024!Learn |
4954
5055### Manual setup
5156
@@ -66,6 +71,15 @@ pip install -r requirements.txt
6671python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
6772```
6873
74+ ** QVAC service** (Node.js — embedding + retrieval + optional LLM generation):
75+
76+ ``` bash
77+ cd workers/qvac-service
78+ npm install
79+ node src/server.js
80+ # Downloads the embedding model (~670 MB) on first run, then listens on :3001
81+ ```
82+
6983---
7084
7185## Project Structure
@@ -80,30 +94,43 @@ bitcoin-academy/
8094│ ├── components/ # React components
8195│ └── lib/ # API client, auth helpers, services
8296├── services/
83- │ └── ai/ # FastAPI backend (primary service)
97+ │ └── ai/ # FastAPI backend
8498│ ├── Dockerfile
8599│ └── app/
86- │ ├── api/ # Route handlers (auth, courses, documents, progress)
87- │ ├── workers/ # Document processing pipeline
88- │ │ └── pipeline.py # parse → chunk → embed → index (runs as BackgroundTask)
89- │ ├── services/ # Business logic
100+ │ ├── api/ # Route handlers (auth, chat, courses, documents, progress, quizzes, certificates)
101+ │ ├── workers/
102+ │ │ └── pipeline.py # parse → chunk → ChromaDB + QVAC ingest (BackgroundTask)
103+ │ ├── services/
104+ │ │ └── chat_service.py # Forwards /chat queries to the QVAC service via httpx
90105│ ├── repositories/ # Data access layer
91106│ ├── db/ # SQLAlchemy models and session
92- │ ├── rag/ # LangChain RAG pipeline (chains, retrievers, prompts)
93107│ ├── schemas/ # Pydantic request/response models
94108│ ├── core/ # Config, DI container, error handling, token blacklist
95109│ └── middleware/ # Request ID, security headers
96- ├── workers/ # Standalone pipeline script (reference / CLI testing)
97- │ └── main.py
110+ ├── workers/
111+ │ ├── python-ingester/ # Standalone Python ingestion pipeline (PDF/PPTX → JSONL)
112+ │ │ └── src/
113+ │ │ ├── module_1_ingestor.py # RamSafeIngestor — RAM-safe PDF/PPTX batch reader
114+ │ │ ├── module_2_parser.py # StructuralParser — hybrid pdfplumber + Docling ML
115+ │ │ ├── module_3_micro_chunker.py # VerilocalChunker — 3-level chunking (section/paragraph/micro)
116+ │ │ ├── module_4_exporter.py # JsonlExporter — writes *_contingency.jsonl
117+ │ │ ├── retrieval_*.py # ChromaDB embedder + searcher + benchmark
118+ │ │ └── main_ingester_pipeline.py # CLI entry point
119+ │ └── qvac-service/ # Node.js service — QVAC SDK (embedding + HyperDB + LLM)
120+ │ └── src/
121+ │ ├── models.js # loadModel lifecycle (GTE_LARGE_FP16 embedding; LLM placeholder)
122+ │ ├── ingest.js # ragIngest — reads *_contingency.jsonl, indexes paragraph chunks
123+ │ ├── query.js # ragSearch + optional completion
124+ │ └── server.js # HTTP server on :3001 — POST /ingest, POST /query, GET /health
98125├── docs/
99- │ └ ── examples/
100- │ └── prototype / # Original in-memory API prototype (reference only)
126+ │ ├ ── qvac-integration.md # Step-by-step guide for the QVAC SDK integration
127+ │ └── src / # Source PDFs and PPTX used in tests
101128├── .github/
102129│ └── workflows/
103130│ └── ci.yml # CI: pytest + mypy + tsc + jest on every PR
104- ├── docker-compose.yml # Full stack: postgres + api + web
105- ├── start-dev.sh # Dev startup script (no Docker required)
106- └── package.json # Root workspace (npm workspaces: apps/*, services/* )
131+ ├── docker-compose.yml
132+ ├── start-dev.sh
133+ └── package.json # Root workspace (npm workspaces: apps/*, workers/qvac-service )
107134```
108135
109136---
@@ -112,26 +139,46 @@ bitcoin-academy/
112139
113140### Frontend (` apps/web ` )
114141
115- | Technology | Role |
116- | ---------------- | - ------------------------------|
117- | Next.js 14 | React framework, App Router |
118- | TypeScript | Type safety |
119- | Tailwind CSS | Styling |
120- | NextAuth.js 4 | Session-based authentication |
121- | Jest + RTL | Unit and integration tests |
142+ | Technology | Role |
143+ | ---------------| ------------------------------|
144+ | Next.js 14 | React framework, App Router |
145+ | TypeScript | Type safety |
146+ | Tailwind CSS | Styling |
147+ | NextAuth.js 4 | Session-based authentication |
148+ | Jest + RTL | Unit and integration tests |
122149
123150### Backend (` services/ai ` )
124151
125- | Technology | Role |
126- | ---------------------| -----------------------------------------|
127- | FastAPI | Async HTTP framework |
128- | SQLAlchemy 2 | ORM |
129- | Pydantic v2 | Data validation and serialization |
130- | python-jose + bcrypt| JWT authentication |
131- | LangChain + OpenAI | RAG pipeline for AI tutoring |
132- | PostgreSQL | Primary database |
133- | slowapi | Rate limiting |
134- | pytest | Test suite |
152+ | Technology | Role |
153+ | ----------------------| -----------------------------------------------|
154+ | FastAPI | HTTP framework |
155+ | SQLAlchemy 2 | ORM |
156+ | Pydantic v2 | Data validation and serialization |
157+ | python-jose + bcrypt | JWT authentication |
158+ | httpx | HTTP client — calls the QVAC service for chat |
159+ | ChromaDB | Vector store used during document ingestion |
160+ | fastembed | Embedding during ingestion (all-MiniLM-L6-v2) |
161+ | PostgreSQL | Primary database |
162+ | slowapi | Rate limiting |
163+ | pytest | Test suite |
164+
165+ ### QVAC service (` workers/qvac-service ` )
166+
167+ | Technology | Role |
168+ | ---------------| -------------------------------------------------------------------|
169+ | Node.js 22.17+| Runtime |
170+ | ` @qvac/sdk ` | Local-first AI — embedding, HyperDB vector store, LLM generation |
171+ | ` node:test ` | Built-in test runner |
172+
173+ ### Document ingestion pipeline (` workers/python-ingester ` )
174+
175+ | Technology | Role |
176+ | --------------------| ---------------------------------------------------|
177+ | pdfplumber | Primary PDF parser |
178+ | Docling | ML-based parser — flag ` --docling ` |
179+ | python-pptx | PPTX parser |
180+ | fastembed | Paragraph-level embedding (all-MiniLM-L6-v2 ONNX) |
181+ | ChromaDB | Persistent vector store |
135182
136183---
137184
@@ -146,9 +193,34 @@ DATABASE_URL=postgresql://user:password@localhost:5432/bitcoin_academy
146193SECRET_KEY=your-secret-key
147194ENVIRONMENT=development
148195CORS_ORIGINS=http://localhost:3000
196+
197+ # QVAC service (default: http://localhost:3001)
198+ QVAC_SERVICE_URL=http://localhost:3001
199+
200+ # Directory where the pipeline writes JSONL files for QVAC ingestion
201+ # (default: services/ai/qvac_ingest/)
202+ QVAC_INGEST_DIR=/absolute/path/to/qvac_ingest
203+
204+ # ChromaDB path (default: services/ai/chroma_db/)
205+ CHROMA_DB_PATH=/absolute/path/to/chroma_db
149206```
150207
151- ` DATABASE_URL ` and ` SECRET_KEY ` are required at startup — the app will crash without them.
208+ ` DATABASE_URL ` and ` SECRET_KEY ` are required at startup.
209+
210+ ** QVAC service** — environment variables (optional):
211+
212+ ``` env
213+ # Override the LLM model — any of the four modelSrc options in qvac-integration.md
214+ # Default: QWEN3_4B_INST_Q4_K_M from the QVAC registry (~2.4 GB, requires ≥ 8 GB RAM)
215+ # Leave unset to run without an LLM (embedding + retrieval only)
216+ QVAC_LLM_SRC=/path/to/local/model.gguf
217+
218+ # Override the embedding model (default: GTE_LARGE_FP16, ~670 MB)
219+ QVAC_EMB_SRC=
220+
221+ # Port (default: 3001)
222+ QVAC_PORT=3001
223+ ```
152224
153225** Frontend** — create ` apps/web/.env.local ` :
154226
@@ -175,27 +247,74 @@ npm run format # Prettier
175247
176248``` bash
177249cd services/ai
178- mypy . # Type checking
179- pytest # All tests
180- pytest tests/unit -v # Unit tests with coverage
181- pytest tests/integration # Integration tests
250+ pytest # All tests (excludes slow)
251+ pytest tests/unit -v # Unit tests
252+ pytest tests/integration # Integration tests
253+ pytest -m slow # Pipeline e2e (requires fastembed + chromadb)
254+ mypy .
255+ ```
256+
257+ ** QVAC service only:**
258+
259+ ``` bash
260+ cd workers/qvac-service
261+ npm test # node:test unit suite (no model download)
262+ node src/server.js # Start service — downloads models on first run
263+ ```
264+
265+ ** Ingestion pipeline (CLI):**
266+
267+ ``` bash
268+ cd workers/python-ingester
269+ # Index a document into both ChromaDB and QVAC (QVAC service must be running)
270+ python src/main_ingester_pipeline.py lecture.pdf \
271+ --course-id BTC_2025 --lecture-id L01 --docling
272+ ```
273+
274+ ### Document ingestion flow
275+
276+ ```
277+ Upload via API CLI (direct)
278+ │ │
279+ ▼ ▼
280+ pipeline.py (BackgroundTask) main_ingester_pipeline.py
281+ │
282+ ├─ RamSafeIngestor + StructuralParser (PDF/PPTX → blocks)
283+ ├─ VerilocalChunker (section / paragraph / micro)
284+ ├─ fastembed + ChromaDB (paragraph chunks → vector store)
285+ ├─ Write *_contingency.jsonl to QVAC_INGEST_DIR
286+ └─ POST http://localhost:3001/ingest ←── QVAC service
287+ └─ ragIngest → HyperDB workspace
288+ ```
289+
290+ ### Chat query flow
291+
292+ ```
293+ Student question
294+ → POST /api/courses/{id}/chat (FastAPI, JWT required)
295+ → chat_service.py
296+ → POST http://localhost:3001/query (QVAC service)
297+ └─ ragSearch (HyperDB) → optional LLM completion
298+ → ChatResponse { answer, citations: [{snippet, score}], retrieval_used }
182299```
183300
184301---
185302
186303## API
187304
188- Registered routers in ` services/ai/app/main.py ` :
305+ All routers registered in ` services/ai/app/main.py ` :
189306
190- | Prefix | Description |
191- | --------------| ------------------------------|
192- | ` /auth ` | Registration, login, JWT |
193- | ` /courses ` | Course CRUD |
194- | ` /documents ` | PDF upload and indexing |
195- | ` /progress ` | User progress tracking |
196- | ` /health ` | Health check with DB ping |
307+ | Prefix | Description |
308+ | -------------------------------| -------------------------------------|
309+ | ` /api/auth ` | Registration, login, JWT refresh |
310+ | ` /api/courses/{id}/chat ` | RAG-backed Q&A (QVAC service) |
311+ | ` /api/courses ` | Course CRUD and lesson listing |
312+ | ` /api/courses/{id}/documents ` | PDF/PPTX upload and indexing |
313+ | ` /api/users/me/... ` | Progress tracking and certificates |
314+ | ` /api/quizzes ` | Quiz placeholders (not yet active) |
315+ | ` /health ` | Health check with DB ping |
197316
198- > ** Implemented but not yet registered: ** ` quizzes_api.py ` , ` chat_api.py ` , ` certificates_api.py ` exist in ` app/api/ ` but are not included in ` app/main.py ` .
317+ Full interactive reference: ` http://localhost:8000/docs ` (development only) .
199318
200319---
201320
@@ -208,9 +327,10 @@ Registered routers in `services/ai/app/main.py`:
208327
209328** Guidelines:**
210329
211- - TypeScript for frontend, Python for backend
212- - Run ` npm run type-check ` and ` pytest ` before opening a PR
213- - Update this README if you change the project structure or add new routes
330+ - TypeScript for frontend, Python for backend, JavaScript (ESM) for the QVAC service
331+ - Run ` npm run type-check ` , ` pytest ` , and ` npm test ` (in ` workers/qvac-service ` ) before opening a PR
332+ - Node.js ≥ 22.17 is required — earlier versions will fail on ` import "@qvac/sdk" `
333+ - Update this README if you change the project structure, add new routes, or modify the startup sequence
214334
215335---
216336
0 commit comments