One of the AI engineering projects I've built is an AI marketing assistant designed for the Nigerian market. The core challenge with any AI assistant like this is the same one every AI engineer runs into: a language model on its own doesn't know today's CBN exchange rate, this week's Google Trends data, or what's currently trending on Nigerian Twitter. That's where retrieval-augmented generation, or RAG, comes in.
The architecture
The system combines a proprietary RAG pipeline built on Supabase pgvector with 12 live web crawlers and the Claude API. The crawlers continuously pull in exchange rates, parallel market rates, e-commerce prices, fuel prices, news, TikTok trends, and Nairaland sentiment. That data gets embedded and stored in pgvector, so when a user asks a question, the system retrieves the most relevant, current context and passes it to Claude alongside the query — instead of relying purely on the model's training data.
Problems that came up in practice
A few issues are worth mentioning because they're common failure points in any RAG system, not just this one:
- Poisoned conversation history — malformed or contradictory context in the conversation log was causing the model to fall into refusal loops. Fixing this meant sanitizing what gets fed back into context on each turn.
- Environment configuration issues — env file path bugs that silently broke API key loading in certain deployment contexts.
- Scraper fragility — sites like Nairaland change their markup, which breaks naive selectors. Switching from rigid tag-based selectors to regex-matched link patterns made the crawlers noticeably more resilient.
Why RAG instead of just a bigger prompt
It's tempting to just stuff more data into a prompt, but that scales badly and gets expensive fast. A proper RAG pipeline retrieves only what's relevant to the specific question, which keeps responses grounded, current, and cost-efficient — the crawler layer keeps the knowledge base fresh, and pgvector's similarity search keeps retrieval fast even as that dataset grows across 12 different data sources.
This is the kind of system design work I focus on: not just calling an LLM API, but building the retrieval, data, and orchestration layers around it that make the output actually reliable.
← Back to Blog