| name | wiki-embed-qdrant |
| description | Embed semantic chunks into Qdrant Cloud for the production RAG backend API. |
Wiki Embed Qdrant
Create vector embeddings from semantic chunks using the Gemini embedding API and upsert them into a Qdrant Cloud collection. This powers the production chatbot/RAG backend deployed on Railway.
When to Use
After chunks exist in data/chunks/ (from wiki-chunk). This step makes the wiki searchable via the shared backend API.
Prerequisites
- Chunks exist in
data/chunks/ (JSON files from the chunking pipeline)
- Qdrant Cloud account with a cluster running
- Python dependencies:
qdrant-client, requests, python-dotenv, pyyaml
Environment
| Variable | Required | Source |
|---|
GEMINI_API_KEY | Yes | ~/.zshrc or shared-backend/.env |
QDRANT_API_KEY | Yes | ~/.zshrc or shared-backend/.env |
QDRANT_CLOUD_URL | Yes | ~/.zshrc or shared-backend/.env |
All three variables must be set. The embed script loads from shared-backend/.env via python-dotenv.
Usage
cd wiki-projects/shared-backend
python3 embed_chunks.py --wiki {slug}
python3 embed_chunks.py --wiki {slug} --batch-size 50
python3 embed_chunks.py --wiki {slug} --start-from 500
CLI Arguments
| Flag | Default | Description |
|---|
--wiki | Required | Wiki slug (must be in WIKI_CONFIGS) |
--batch-size | 20 | Chunks per Qdrant upsert batch |
--start-from | 0 | Skip first N chunks (for resuming) |
Adding a New Wiki
Before running for a new wiki, add it to the WIKI_CONFIGS dict in shared-backend/embed_chunks.py:
WIKI_CONFIGS = {
"{slug}": {
"chunks_dir": Path(__file__).parent.parent / "{slug}-wiki/data/chunks",
"collection": "{slug}_chunks",
},
}
Also add the wiki to the backend API config in shared-backend/main.py:
"{slug}": {
"name": "{Wiki Name}",
"collection": "{slug}_chunks",
"backend": "qdrant_cloud",
"prompt_context": "brief description of content domain",
"source_label": "{Show Name}",
}
How It Works
- Load chunks: Read all JSON files from the wiki's chunks directory using the wiki-specific loader function
- Detect embedding dimension: Embed one sample chunk to determine vector size (768 for Gemini embedding-001)
- Create collection: If the Qdrant collection does not exist, create it with cosine distance
- Auto-resume: If the collection already has points and
--start-from is 0, automatically resume from the existing point count
- Batch process: For each batch:
- Truncate chunk text to 8000 characters for embedding
- Call Gemini embedding API (
gemini-embedding-001)
- Create
PointStruct with vector and metadata payload
- Upsert batch to Qdrant
- Verify: Print final vector count
Embedding Details
| Setting | Value |
|---|
| Model | gemini-embedding-001 |
| Vector dimensions | 768 |
| Distance metric | Cosine |
| Max text length | 8000 characters (truncated) |
| API method | REST (generativelanguage.googleapis.com/v1beta) |
Payload Schema
Each point in Qdrant stores:
{
"id": 0,
"vector": [0.123, -0.456, ...],
"payload": {
"text": "Full chunk content...",
"episode_title": "Episode Title",
"episode_date": "",
"topic_title": "Topic Name",
"topic_type": "framework",
"url": "",
"start_timestamp": "05:30"
}
}
MFM and MoneyWise also include key_entities in the payload.
Output
- Vectors in Qdrant Cloud collection
{slug}_chunks
- Collection is immediately queryable via the RAG backend API
Testing the Backend
After embedding, test via the shared backend:
curl https://api-production-4224.up.railway.app/stats/{slug}
curl -X POST https://api-production-4224.up.railway.app/chat \
-H "Content-Type: application/json" \
-H "X-User-Email: test@example.com" \
-d '{"wiki":"{slug}","query":"test query here","limit":5}'
Daily limit is 20 queries per email.
Cost
- Embedding: ~$0.001 per chunk (Gemini embedding API is very cheap)
- Qdrant Cloud: Free tier covers small collections; paid tier for larger wikis
- A 5,000-chunk wiki costs roughly $5 to embed
Quality Checks
After embedding:
wiki.yaml Config Reference
The embed script does not read wiki.yaml directly. It uses the hardcoded WIKI_CONFIGS dict in embed_chunks.py. The convention is:
- Chunks dir:
{slug}-wiki/data/chunks
- Collection name:
{slug}_chunks
Shared Library Reference
| File | Purpose |
|---|
wiki-projects/shared-backend/embed_chunks.py | Embedding and Qdrant upsert script |
wiki-projects/shared-backend/main.py | RAG backend API (FastAPI on Railway) |
wiki-projects/shared-backend/.env | API keys (GEMINI, QDRANT) |
Troubleshooting
"Collection not found" on query: The collection was created but is empty. Check that the embedding step completed without errors.
Auto-resume skips everything: If the collection already has the right number of points, the script correctly skips. Use --start-from 0 and delete/recreate the collection to force re-embedding.
Gemini embedding API 429 (rate limit): Reduce batch size to 10 and add delays. The script does not have built-in rate limiting for embedding calls.
Qdrant connection timeout: Check QDRANT_CLOUD_URL format. It should be https://xxxxxxxx.us-east4-0.gcp.cloud.qdrant.io:6333 (with port).
Partial upload (interrupted): The auto-resume feature handles this. Re-run the same command and it will pick up from where it left off based on existing point count.
Different chunk formats per wiki: The embed script has wiki-specific loader functions (load_mfm_chunks, load_huberman_chunks, etc.) because chunk JSON schemas vary slightly between older and newer wikis. New wikis using the shared lib chunker follow the MFM/MoneyWise format.