# Phase 2 — Claude + RAG + Tavily Opportunities This adds three things to the HF Space **without removing anything**: 1. `POST /api/chat/claude` — Claude-powered chat with RAG over uploaded docs. 2. `POST /api/documents/upload`, `GET /api/documents`, `DELETE /api/documents/:id` — manage docs from the frontend. 3. `GET /api/opportunities` — Tavily-backed student opportunities feed. Your existing `/api/chat` (alu_brain + Groq) is untouched. ## What you need to do before deploying ### 1. Add secrets in the HF Space settings Go to https://huggingface.co/spaces/Ngum/alu-chatbot/settings → **Variables and secrets** → **New secret**. | Name | Where to get it | |------|-----------------| | `ANTHROPIC_API_KEY` | https://console.anthropic.com/settings/keys | | `TAVILY_API_KEY` | https://app.tavily.com/ (free tier: 1,000 searches/month) | | `CLAUDE_MODEL` *(optional)* | Defaults to `claude-sonnet-4-6`. Override if you want Haiku for cost. | Do **not** add these to any file in the repo. They are read at runtime from `os.getenv`. ### 2. Commit and push the three new Python files + updated `requirements.txt` + updated `app.py` ```powershell cd C:\Users\Ngum\alu-chatbot git add claude_engine.py opportunities_service.py app.py requirements.txt PHASE2_DEPLOY.md git commit -m "Phase 2: Claude RAG chat, document upload, Tavily opportunities" git push ``` The Space will rebuild automatically. First boot will be slower (~3-5 min) while it installs `anthropic` and `tavily-python`. ### 3. Verify everything works After the Space restarts, hit these URLs in a browser: - `https://ngum-alu-chatbot.hf.space/api/services/status` → should show `claude.enabled: true` and `opportunities.enabled: true`. - `https://ngum-alu-chatbot.hf.space/api/opportunities` → should return ~15-20 real opportunities from Tavily. - `https://ngum-alu-chatbot.hf.space/api/documents` → empty list (no docs uploaded yet). If `claude.enabled` is `false`, the secret didn't get loaded. Restart the Space from the HF UI. ## How it integrates with the existing code - `claude_engine.py` mirrors the pattern in `groq_fallback.py` — module-level singleton, `enabled` flag, fails gracefully if no key. - The new `/api/chat/claude` route calls `retrieval_engine.retrieve_context()` (your existing ChromaDB) for context, then asks Claude. If Claude fails, it transparently falls back to Groq. If Groq fails too, you get a friendly error string. - Document upload reuses your existing `DocumentProcessor` (it already supports PDF/DOCX/TXT) and `ExtendedRetrievalEngine.update_vector_store()`. - Tavily queries rotate between 8 pre-written prompts; results cached in-memory for 30 minutes so the free tier lasts. ## Frontend changes Just one line in [`frontend/src/services/aiService.ts`](../alu_student_frontbatoo-main%20(2)/alu_student_frontbatoo-main/frontend/src/services/aiService.ts): ```ts const CHAT_ENDPOINT = `${API_URL}/api/chat/claude`; // was /api/chat ``` The OpportunityWidget already calls `/api/opportunities` and falls back to its curated list if the endpoint isn't available — so it'll start showing real Tavily results the moment the backend is live. ## Cost / quota at a glance - **Anthropic Claude Sonnet 4.6**: ~$3/M input, $15/M output tokens. Prompt caching on the system prompt cuts repeat input by ~10x. Average student question = ~0.5¢. - **Tavily**: 1,000 searches/month free. The opportunities cache means one full refresh = 2 searches, so 30-min refresh = ~96 searches/day = well under quota. - **Groq**: Still wired as the fallback. 14,400 free requests/day. ## Rollback If anything misbehaves, revert one line in `aiService.ts` (back to `/api/chat`). The backend changes are additive — no existing route was modified.