RAG Chatbot
Complete AI Build Guide
For GPT-4.1 Codex / AI Coding Assistants
Stack: FastAPI · ChromaDB · Ollama · Celery · Redis · Playwright
Target Hardware: RTX 3050 4GB · i7 11th Gen · 16GB RAM · Windows 10/11
SECTION 1: PRE-CODING SETUP (Do This First)
Complete ALL steps below before giving any code to the AI.
1.1 Install Python 3.11
Download from [Link]. During install, check Add Python to PATH. Verify:
python --version
pip --version
1.2 Install Ollama
Download from [Link] and install. Then open a terminal and pull the model:
ollama pull phi3:mini
ollama serve
Keep ollama serve running in a separate terminal window at all times.
1.3 Install Docker Desktop
Download from [Link]. Used to run Redis (required for job queue).
# After installing Docker, run Redis:
docker run -d -p 6379:6379 --name redis redis
1.4 Install Playwright Browser
pip install playwright
playwright install chromium
1.5 Create Project Folder
mkdir ragbot
cd ragbot
python -m venv venv
venv\Scripts\activate
1.6 Install All Python Dependencies
pip install fastapi uvicorn python-multipart
pip install chromadb sentence-transformers
pip install langchain langchain-community
pip install pymupdf python-docx unstructured
pip install playwright beautifulsoup4 requests
pip install celery redis
pip install python-jose[cryptography] passlib[bcrypt] slowapi
pip install rank-bm25 python-dotenv pydantic pydantic-settings httpx
1.7 Create .env File
Create a file named .env in the ragbot folder:
OLLAMA_BASE_URL=[Link]
OLLAMA_MODEL=phi3:mini
CHROMA_PERSIST_DIR=./chromadb
REDIS_URL=redis://localhost:6379
SECRET_KEY=change-this-to-any-random-string
ACCESS_TOKEN_EXPIRE_MINUTES=60
SECTION 2: PROJECT STRUCTURE
Tell the AI to create this exact folder and file structure:
ragbot/
■■■ app/
■ ■■■ [Link] ← FastAPI entry point, all routes
■ ■■■ [Link] ← loads .env settings
■ ■■■ auth/
■ ■ ■■■ __init__.py
■ ■ ■■■ [Link] ← JWT token creation + validation
■ ■■■ ingestion/
■ ■ ■■■ __init__.py
■ ■ ■■■ [Link] ← extract text from PDF
■ ■ ■■■ [Link] ← extract text/json from files
■ ■ ■■■ url_scraper.py ← scrape websites with Playwright
■ ■■■ pipeline/
■ ■ ■■■ __init__.py
■ ■ ■■■ [Link] ← split text into 500-token chunks
■ ■ ■■■ [Link] ← convert text to vectors (CPU)
■ ■ ■■■ vector_store.py ← ChromaDB read/write
■ ■ ■■■ [Link] ← hybrid search (vector + BM25)
■ ■■■ chat/
■ ■ ■■■ __init__.py
■ ■ ■■■ [Link] ← Redis session memory
■ ■ ■■■ [Link] ← Ollama streaming + prompts
■ ■■■ tasks/
■ ■ ■■■ __init__.py
■ ■ ■■■ [Link] ← Celery async tasks
■ ■■■ utils/
■ ■■■ __init__.py
■ ■■■ [Link] ← logging config
■■■ uploads/ ← temp uploaded files
■■■ chromadb/ ← vector database (auto-created)
■■■ .env
■■■ [Link]
SECTION 3: AI PROMPTS — BUILD ORDER
Feed these prompts to GPT-4.1 Codex IN ORDER. Build and test each before moving to the next.
Prompt 1 — [Link]
Build app/[Link].
Use pydantic-settings BaseSettings.
Load these fields from .env:
- OLLAMA_BASE_URL (str)
- OLLAMA_MODEL (str)
- CHROMA_PERSIST_DIR (str)
- REDIS_URL (str)
- SECRET_KEY (str)
- ACCESS_TOKEN_EXPIRE_MINUTES (int, default 60)
Class name: Settings. Instance name: settings.
Prompt 2 — [Link]
Build app/utils/[Link].
Create a logger named 'ragbot'.
Format: timestamp [LEVEL] message.
Level: INFO.
Prompt 3 — PDF Ingestion
Build app/ingestion/[Link].
Function: extract_pdf(file_path: str) -> str
Use PyMuPDF (fitz).
Extract text from every page.
Prefix each page with [Page N].
Return full text string.
Prompt 4 — Text/JSON Ingestion
Build app/ingestion/[Link].
Two functions:
1. extract_text(file_path: str) -> str
Read any plain text file (txt, md, docx, csv).
For docx use python-docx.
Return full text.
2. extract_json(file_path: str) -> str
Load JSON, return [Link](data, indent=2).
Prompt 5 — URL Scraper
Build app/ingestion/url_scraper.py.
Async function: scrape_url(url: str) -> str
Use Playwright (async_api, chromium, headless=True).
Wait for networkidle.
Parse with BeautifulSoup.
Remove: script, style, nav, footer, header, aside tags.
Return clean text.
Prompt 6 — Chunker
Build app/pipeline/[Link].
Function: chunk_text(text: str, source: str) -> list[dict]
Use LangChain RecursiveCharacterTextSplitter.
chunk_size=500, chunk_overlap=50.
separators=[double-newline, newline, period, space].
Return list of dicts: {text, source, chunk_index}.
Prompt 7 — Embedder
Build app/pipeline/[Link].
Load SentenceTransformer model 'nomic-ai/nomic-embed-text-v1' on CPU.
Function: embed(texts: list[str]) -> list[list[float]]
Use [Link](), return as list of lists.
Device must be CPU to save VRAM for Ollama LLM.
Prompt 8 — Vector Store
Build app/pipeline/vector_store.py.
Use ChromaDB PersistentClient with path from settings.CHROMA_PERSIST_DIR.
Functions:
1. get_collection(collection_id: str) -> collection
2. store_chunks(collection_id: str, chunks: list[dict])
- embed all chunk texts
- generate uuid for each
- add to chromadb with metadata {source, chunk_index}
3. delete_collection(collection_id: str)
4. list_collections() -> list[str]
Prompt 9 — Hybrid Retriever
Build app/pipeline/[Link].
Function: retrieve(collection_id: str, query: str, top_k: int = 5) -> list[dict]
Step 1: Vector search using ChromaDB query with embedded query.
Step 2: BM25 keyword search on all docs using rank_bm25.
Step 3: Merge results, deduplicate by text content.
Step 4: Return top_k unique results as list[{text, source}].
Import from vector_store and embedder.
Prompt 10 — Memory
Build app/chat/[Link].
Use Redis from settings.REDIS_URL.
Functions:
1. get_history(session_id: str, max_turns: int = 6) -> list[dict]
Key: session:{session_id}. Return last max_turns items.
2. save_history(session_id: str, history: list[dict])
Save with 1 hour expiry (ex=3600).
3. clear_history(session_id: str)
Delete the key.
Prompt 11 — Generator
Build app/chat/[Link].
Three async functions:
1. stream_response(prompt: str) -> AsyncGenerator[str]
POST to {OLLAMA_BASE_URL}/api/generate with model and stream=True.
Use httpx AsyncClient. Yield each response token string.
2. build_prompt(context_chunks, history, query) -> str
System: answer ONLY from context, say I don't know if not found.
Include context with source labels, conversation history, then USER/ASSISTANT format.
3. generate_suggestions(context_chunks) -> list[str]
Prompt Ollama to return exactly 3 questions as JSON array.
Parse and return. Fallback: return 3 generic questions.
4. generate_summary(context_chunks) -> str
Prompt Ollama to summarize all chunks concisely.
Collect and return full response.
Prompt 12 — Celery Worker
Build app/tasks/[Link].
Create Celery app with broker and backend from settings.REDIS_URL.
Two tasks:
1. ingest_file_task(file_path, file_type, collection_id)
file_type options: pdf, json, text
Call correct extractor → chunk_text → store_chunks
Return {status: done, chunks: N}
2. ingest_url_task(url, collection_id)
Use [Link](scrape_url(url)) → chunk_text → store_chunks
Return {status: done, chunks: N}
Prompt 13 — JWT Auth
Build app/auth/[Link].
Two functions:
1. create_token(user_id: str) -> str
Use python-jose [Link].
Expire: utcnow + ACCESS_TOKEN_EXPIRE_MINUTES.
Algorithm: HS256. Key: settings.SECRET_KEY.
2. decode_token(token: str) -> str
Decode and return sub field.
Prompt 14 — [Link] (Full API)
Build app/[Link] — the complete FastAPI application.
Setup:
- FastAPI app with title RAG Chatbot API
- CORS middleware: allow all origins, methods, headers
- Rate limiter with slowapi
- uploads/ directory auto-created
Endpoints:
POST /ingest/file
Form: file (UploadFile), collection_id (str)
Save file to uploads/ with uuid filename
Detect type from extension (pdf/json/text)
Queue with ingest_file_task.delay()
Return {task_id, status: queued}
POST /ingest/url
Form: url (str), collection_id (str)
Queue with ingest_url_task.delay()
Return {task_id, status: queued}
POST /query
Form: message (str), collection_id (str), session_id (str)
Get history from memory
Retrieve chunks from vector store
Build prompt, stream response via StreamingResponse
After stream: save updated history
Header X-Sources: list of source names
POST /suggest
Form: collection_id (str)
Retrieve chunks for overview query
Return {suggestions: [q1, q2, q3]}
POST /summarize
Form: collection_id (str), query (str, default summarize everything)
Retrieve top 10 chunks
Return {summary: text}
DELETE /session/{session_id}
Clear session memory
Return {status: cleared}
DELETE /collection/{collection_id}
Delete vector collection
Return {status: deleted}
GET /collections
Return list of all collection names
GET /health
Return {status: ok}
SECTION 4: HOW TO RUN
Open 4 separate terminal windows. Run each command in its own window:
Terminal 1 — Ollama
ollama serve
Terminal 2 — Redis
docker run -d -p 6379:6379 --name redis redis
# (only first time, after that:)
docker start redis
Terminal 3 — Celery Worker
cd ragbot
venv\Scripts\activate
celery -A [Link] worker --loglevel=info --pool=solo
Terminal 4 — FastAPI
cd ragbot
venv\Scripts\activate
uvicorn [Link]:app --reload --port 8000
Verify Running
Open browser and go to: [Link]
You should see: {"status": "ok"}
Full API docs: [Link]
SECTION 5: TESTING THE API
Use these curl commands to test each feature:
Ingest a PDF
curl -X POST [Link] \
-F "file=@[Link]" \
-F "collection_id=my-docs"
Ingest a URL
curl -X POST [Link] \
-F "url=[Link] \
-F "collection_id=my-docs"
Ask a Question
curl -X POST [Link] \
-F "message=what is this about?" \
-F "collection_id=my-docs" \
-F "session_id=user-123"
Get 3 Suggested Questions
curl -X POST [Link] \
-F "collection_id=my-docs"
Summarize
curl -X POST [Link] \
-F "collection_id=my-docs"
Clear Chat History
curl -X DELETE [Link]
SECTION 6: TROUBLESHOOTING
Problem Cause Fix
CUDA out of memory LLM + embedder both on GPU Embedder must use device=cpu
Ollama not responding Server not started Run: ollama serve in terminal
Redis connection refused Docker not running Run: docker start redis
Celery task never completes Worker not started Start celery worker (Terminal 3)
Empty answers from bot Bad chunk retrieval Check collection_id spelling
Playwright timeout JS-heavy site slow Increase timeout in scraper
ModuleNotFoundError Wrong venv active Run venv\Scripts\activate first
SECTION 7: QUICK REFERENCE
Key URLs
Service URL
FastAPI App [Link]
API Docs (Swagger) [Link]
Health Check [Link]
Ollama [Link]
Redis localhost:6379
Tech Stack Summary
Component Tool Purpose
LLM Ollama + phi3:mini Answer questions (GPU)
Embeddings nomic-embed-text Text to vectors (CPU)
Vector DB ChromaDB Store + search chunks
Web Framework FastAPI API server
Job Queue Celery + Redis Async file processing
Web Scraping Playwright + BS4 URL content extraction
PDF Parsing PyMuPDF Extract PDF text
Session Memory Redis Chat history per user
Keyword Search BM25 (rank-bm25) Hybrid retrieval
Build Order Checklist
Check off each step as you complete it:
[ ] Python 3.11 installed + PATH set
[ ] Ollama installed + phi3:mini pulled
[ ] Docker installed + Redis container running
[ ] Project folder created + venv activated
[ ] All pip packages installed
[ ] .env file created with correct values
[ ] Folder structure created
[ ] [Link] built and tested
[ ] All ingestion modules built (pdf, text, url)
[ ] Chunker + embedder + vector store built
[ ] Hybrid retriever built
[ ] Memory module built
[ ] Generator module built
[ ] Celery worker built
[ ] [Link] built with all endpoints
[ ] All 4 terminals running
[ ] /health returns OK
[ ] PDF ingestion tested
[ ] URL ingestion tested
[ ] Query endpoint tested
[ ] Suggest endpoint tested
[ ] Summarize endpoint tested