Offline RAG (Retrieval-Augmented Generation) service for CHANGLI-AI
The knowledge backbone of ditdev.kyuzenstudio.com
ditdev-rag is a lightweight, fully offline RAG service that powers CHANGLI-AI - the shrine maiden AI guide of Rahmat Aditya's pixel art portfolio.
Instead of stuffing all portfolio data into the LLM system prompt (expensive & slow), this service:
- Embeds structured portfolio data into a local vector database
- Retrieves only the most relevant chunks for each user query
- Injects that context into the prompt before sending to the LLM
This keeps token usage minimal while keeping CHANGLI-AI's answers accurate and grounded in real data.
- π Semantic search - finds relevant data by meaning, not just keywords
- β‘ Incremental indexing - add, update, delete single chunks without full rebuild
- ποΈ Persistent vector store - ChromaDB stores embeddings locally on disk
- π‘οΈ Graceful fallback - if RAG is down, the LLM still responds from its base persona
- π Real-time sync - portfolio data stays in sync with PostgreSQL via Node.js hooks
User Query
β
βΌ
Node.js Backend (Express)
β
βββ POST /api/chat βββββββββββββββββββββββββββββββββββ
β β
β 1. Fetch relevant chunks from RAG β
β 2. Inject context into system prompt β
β 3. Send to Cerebras LLM (qwen-3-235b) β
β 4. Return response to user β
β β
βββ Admin CRUD βββββββββββββββββββββββββββββββββββββββ€
β β
βββ Project/Cert Created β POST /index/add β
βββ Project/Cert Updated β POST /index/update β
βββ Project/Cert Deleted β POST /index/delete β
β
ditdev-rag (this) ββββ
β
ββββββββββββ΄βββββββββββ
β β
sentence-transformers ChromaDB
(all-MiniLM-L6-v2) (persistent)
embedding model vector store
Portfolio data is split into semantic chunks across categories:
| Category | Source | Example |
|---|---|---|
skill |
skills_data.json |
Unity (Advanced), React (Intermediate) |
project |
PostgreSQL (dynamic) | Game projects, web apps |
certificate |
PostgreSQL (dynamic) | Certificates earned |
education |
skills_data.json |
SMK Negeri 4 Payakumbuh |
about |
skills_data.json |
Background, location, links |
contact |
skills_data.json |
Availability, open for work |
- Python 3.11+
- PostgreSQL database (for dynamic data)
# Clone the repo
git clone https://github.com/rillToMe/ditdev-rag.git
cd ditdev-rag
# Create virtual environment
python -m venv rag-env
source rag-env/bin/activate # Windows: rag-env\Scripts\activate
# Install dependencies
pip install -r requirements.txtcp .env.example .envEdit .env:
DATABASE_URL=postgresql://user:password@host/dbname
RAG_PORT=8765
RAG_REBUILD_SECRET=your_secret_hereuvicorn main:app --host 0.0.0.0 --port 8765On first run, the service will automatically:
- Load all chunks from
skills_data.jsonand PostgreSQL - Generate embeddings using
all-MiniLM-L6-v2 - Store vectors in
chroma_store/(created automatically)
Check service status and chunk count.
{ "status": "ok", "chunks": 20 }Semantic search - returns most relevant chunks for a query.
// Request
{ "query": "what is adit's unity skill level?", "top_k": 4 }
// Response
{
"context": "β’ Skill: Unity | Category: Game Dev | Level: Advanced | ...",
"found": true
}Add a new chunk (called automatically on project/cert creation).
{ "chunk_id": "project_32", "text": "Project by Adit-san: ...", "metadata": {} }Update an existing chunk (called automatically on edit).
Delete a chunk (called automatically on deletion).
{ "chunk_id": "project_32" }Full index rebuild - for emergencies only.
{ "secret": "your_rebuild_secret" }This is the key design decision. Instead of rebuilding the entire index on every change:
INSERT project β embed 1 chunk β upsert to ChromaDB (~50ms)
UPDATE project β re-embed 1 chunk β upsert to ChromaDB (~50ms)
DELETE project β delete by chunk_id from ChromaDB (~5ms)
vs.
Full rebuild β embed ALL chunks β store ALL (~5-30s)
Node.js hooks in the Express backend call these endpoints automatically after every admin CRUD operation - no manual intervention needed.
ditdev-rag/
βββ main.py # FastAPI app & endpoints
βββ rag_engine.py # Core RAG logic (embed, retrieve, CRUD)
βββ data_loader.py # Load static + dynamic data
βββ skills_data.json # Static portfolio data (skills, education, contact)
βββ requirements.txt # Python dependencies
βββ .env.example # Environment template
βββ chroma_store/ # ChromaDB vector store (gitignored)
| Component | Technology |
|---|---|
| API Framework | FastAPI |
| Embedding Model | all-MiniLM-L6-v2 (sentence-transformers) |
| Vector Database | ChromaDB (persistent, local) |
| LLM | Cerebras API - qwen-3-235b-a22b-instruct-2507 |
| Database | Neon PostgreSQL |
This service is designed to work with the ditdev portfolio backend (private). The Node.js backend calls /retrieve on every chat message and /index/* on every admin CRUD operation.
MIT Β© Rahmat Aditya