README.md
March 28, 2026 · View on GitHub
1|# kol_hatorah
2|
3|An AI chat that knows all of the Torah - Hebrew RAG project monorepo.
4|
5|## Prerequisites
6|
7|- Node.js >= 20
8|- npm (comes with Node.js)
9|- Qdrant Cloud account and credentials
10|- OpenAI API Key
11|
12|## Setup
13|
14|1. Clone the repository:
15| bash 16| git clone <repo-url> 17| cd kol_hatorah 18|
19|
20|2. Install dependencies:
21| bash 22| npm ci 23|
24|
25|3. Set up environment variables:
26| bash 27| cp .env.example .env 28|
29|
30|4. Edit .env and add your credentials:
31| - Get your QDRANT_URL from your Qdrant Cloud cluster dashboard
32| - Get your QDRANT_API_KEY from your Qdrant Cloud API keys section
33| - Get your OPENAI_API_KEY from the OpenAI platform
34| - Adjust QDRANT_COLLECTION_PREFIX if needed (default: hebrag_dev)
35| - Set SEFARIA_EXPORT_PATH to the local path of your Sefaria export data.
- Optional for Tanakh commentaries ingest:
QDRANT_UPSERT_TIMEOUT_MS(default 300000),QDRANT_UPSERT_BATCH_SIZE(default 32),QDRANT_UPSERT_CONCURRENCY(default 6). 36| 37|## Running the Qdrant Smoke Test 38| 39|To verify your Qdrant Cloud connection: 40| 41|bash 42|npm --workspace packages/worker run qdrant:smoke 43|44| 45|This will: 46|- Connect to Qdrant Cloud using your credentials 47|- Create a test collection 48|- Verify it exists 49|- Delete the test collection 50|- Exit with code 0 on success 51| 52|## Stage 3: Real Embeddings, RAG Answering, and Sefaria Ingestion 53| 54|This stage integrates real OpenAI embeddings for ingestion and retrieval, implements RAG-based question answering, and provides tools for inspecting and ingesting Sefaria data. 55| 56|### Ingesting Fake Corpus with Embeddings 57| 58|To ingest a fake Hebrew corpus with real OpenAI embeddings into Qdrant: 59| 60|bash 61|npm --workspace packages/worker run ingest:fake:emb 62|63| 64|This command will: 65|- Ensure thechunks_v2collection exists in Qdrant (creates it if missing, throws error on vector size mismatch). 66|- Generate a set of fake Hebrew chunks. 67|- Generate real OpenAI embeddings for each chunk text. 68|- Upsert these chunks and their embeddings into the Qdrant collection, storing the full text and rich metadata in the payload. 69|- Log the number of ingested chunks. 70| 71|### Inspecting Sefaria Export Data 72| 73|To inspect the structure of your local Sefaria export data (useful before full ingestion): 74| 75|bash 76|npm --workspace packages/worker run sefaria:inspect 77|78| 79|This command will: 80|- ReadSEFARIA_EXPORT_PATH. 81|- Print discovered Sefaria files (e.g.,Genesis.json). 82|- Parse a small sample from relevant files and print a preview of extracted raw text and metadata. 83| 84|### Ingesting Sefaria Taste Data 85| 86|To ingest a subset of Sefaria data (Genesis 1-3, Avot 1, Berakhot 2a-5a) with real OpenAI embeddings into Qdrant: 87| 88|bash 89|npm --workspace packages/worker run ingest:sefaria:taste [-- --reset] [-- --limit N] 90|91| 92|Arguments: 93|---reset: (Optional) Ignore the checkpoint and re-ingest all data. 94|---limit N: (Optional) Stop after ingesting N chunks (for debugging). 95| 96|This command will: 97|- Extract and chunk Hebrew text from the specified Sefaria subset. 98|- Generate real OpenAI embeddings for each chunk. 99|- Upsert these chunks and embeddings into thechunks_v2Qdrant collection. 100|- Support resumable ingestion via a checkpoint file (.checkpoints/sefaria-taste.json). 101| 102|### Ingesting Bavli (Gemara) from local Sefaria export 103| 104|bash 105|npm --workspace packages/worker run ingest:bavli -- --tractates bavli-core 106|107| 108|Other examples:--tractates "Berakhot,Shabbat",--limit 500,--no-embed(SQLite + API enrichment only),--reset/--reset-work Berakhot, tuning flags--load-batch-size,--api-concurrency,--embed-batch-size,--qdrant-batch-size. 109| 110|Hebrew text comes fromjson/Talmud/Bavli/.../Hebrew/merged.json. Segment refs follow Sefaria’s daf-line shape (for exampleBerakhot 2a:1), derived from export indices aligned withGET /api/texts/{tractate}?index_only=1(firstAvailableSectionRef) and validated with the name API when possible. Metadata and outgoing links are written via existingsegmentsenrichment columns andref_links; tractate-level index fields go tocorpus_works. API errors log warnings and do not stop the run. 111| 112|### Asking Questions with RAG 113| 114|To query the Qdrant collection and get RAG answers using OpenAI: 115| 116|bash 117|npm --workspace packages/worker run ask -- --q "מה נאמר על ...?" [--k 8] [--type bavli] [--work Berakhot] [--json] 118|119| 120|Arguments: 121|---q "...": The question string (required). 122|---k <number>: Maximum number of retrieved chunks to consider (default: 8 from RAG_TOP_K env var). 123|---type <tanakh|mishnah|bavli>: Filter retrieved chunks by text type. 124|---work <string>: Filter retrieved chunks by work title (e.g., "Genesis", "Berakhot"). 125|---json: (Optional) Output the answer and details in structured JSON format. 126| 127|This command will: 128|- Embed the user's question. 129|- Search thechunks_v2Qdrant collection with the query embedding and filters. 130|- Determine if a sufficient number of relevant sources are found. 131|- If sufficient: build a Hebrew RAG prompt with the top chunks and call the OpenAI Responses API (gpt-4o-mini). 132|- If insufficient: return a refusal message in Hebrew. 133|- Output the answer and citations (human-readable or JSON). 134|- Report optional latency timings and number of chunks used (in JSON output). 135| 136|## Available Scripts 137| 138|-npm run build- Build all packages 139|-npm run dev- Run dev mode for all packages 140|-npm run lint- Lint all packages 141|-npm ci- Clean install dependencies 142|-npm --workspace packages/worker run qdrant:smoke- Verify Qdrant Cloud connection 143|-npm --workspace packages/worker run ingest:fake:emb- Ingest fake corpus with real embeddings 144|-npm --workspace packages/worker run sefaria:inspect- Inspect Sefaria export data 145|-npm --workspace packages/worker run ingest:sefaria:taste- Ingest Sefaria taste data 146|-npm --workspace packages/worker run ingest:bavli- Ingest Bavli tractates (see “Ingesting Bavli” above) 147|-npm --workspace packages/worker run ask -- --q "..."- Ask a RAG question 147| 148|## Project Structure 149| 150|-packages/core- Shared libraries (config, Qdrant client, logging, data models, IDs, vectors, OpenAI client, RAG logic, citations, utils) 151|-packages/worker- CLI tools and ingestion workers (fake corpus generation, Sefaria ingestion, RAG query) 152|-packages/web- Web API server (Express) 153| 154|## Getting Qdrant Cloud Credentials 155| 156|1. Sign up or log in to Qdrant Cloud 157|2. Create a cluster or use an existing one 158|3. In the cluster dashboard, find: 159| - URL: Your cluster endpoint (e.g.,https://xyz-123.qdrant.io) 160| - API Key: Generate or copy from the API Keys section 161|4. Add these to your.envfile 162| 163|## Web UI (Chat)
A minimal React UI for querying Kol HaTorah in the browser, with proper RTL support for Hebrew:
npm install
npm run build # Build worker first (required for web to import it)
npm run dev # Starts web API (port 3000) + UI (port 5173)
Then open http://localhost:5173 in your browser.
- POST /api/ask – API endpoint:
{ "q": "שאילתה", "debug": false }→{ "text": "...", "debug?": {...} } - Debug toggle – When enabled, shows raw JSON from the server in a collapsible section under each response.
Development
154|
155|Each package can be developed independently:
156|
157|bash 158|# Build a specific package 159|npm --workspace packages/core run build 160| 161|# Run dev mode for a specific package 162|npm --workspace packages/worker run dev 163|