AI & Machine Learning
How I Built the EuroParts Lanka AI Part Finder with Claude
TL;DR
Most customers searching for European car parts in Sri Lanka don't know the OEM part number. They know symptoms: "grinding noise when braking," "car pulls to the left," "clicking sound when turning the steering wheel." I built an AI Part Finder for europartslanka.lk that lets customers type a plain-English description of their problem and get back the exact part name, OEM number range, compatible vehicle models, and a path to order. It runs on Claude's API (claude-sonnet) with a carefully designed system prompt, vehicle context injection, and a Cloudflare Worker proxy for reliability. Since launch: 966 customers have used the finder, 1,444 parts have been delivered through it, and the average time from "I don't know what's wrong" to "I found the right part" dropped from days of back-and-forth WhatsApp messages to under 30 seconds.
The Problem: Customers Don't Know Part Names
Here's something you learn fast when you build an ecommerce platform for European car parts in Sri Lanka: your customers almost never search for "OEM 1K0 615 301 AA." They search for "Audi A4 brake disc" or, more often, they don't search at all. They send a WhatsApp message saying "bro my car is making a weird sound when I turn."
Before the AI Part Finder, the workflow looked like this:
- Customer messages on WhatsApp or calls the shop
- Staff asks 4-5 clarifying questions (brand, model, year, what exactly is happening)
- Staff cross-references symptoms against their knowledge of common failures
- Staff looks up the OEM catalog, finds the part number
- Staff quotes a price
- Customer decides
That's 15-30 minutes per inquiry. Sometimes more, because the customer doesn't reply for hours. Multiply that by 40-60 inquiries a day, and you have a bottleneck that no amount of hiring can fix.
The real problem isn't volume. It's the knowledge gap. European cars — Audi, BMW, Mercedes, Volkswagen, Porsche — have deeply specific part numbers. A brake pad for a 2019 Audi A4 B9 is not the same as one for a 2015 A4 B8. The fuel type matters. The engine code matters. And most customers have no idea about any of it.
I needed to bridge that gap without dumbing down the experience. The answer had to be technically accurate enough for a parts specialist to trust, and simple enough for someone who just knows "my car doesn't feel right."
The Architecture
I built europartslanka.lk on a PHP backend with a Supabase-hosted PostgreSQL database, vanilla JavaScript frontend, and Cloudflare for CDN and edge workers. The AI Part Finder fits into this stack as a conversational interface that lives at /ai-part-finder.
The high-level architecture:
[Browser] --> [AI Chat UI] --> POST /api/ai/finder
|
[Rate Limiter]
|
[Input Sanitizer]
|
[AIFinder Class] --> [Cloudflare Worker Proxy]
| |
| [Claude Sonnet API]
|
[Query Logger] --> [Supabase/PostgreSQL]Three design decisions mattered most:
Cloudflare Worker as primary, direct API as fallback. The Worker proxy means the Anthropic API key never touches the client or even the origin server in the hot path. If the Worker goes down, the backend falls back to a direct Anthropic API call. In practice, the Worker handles 98% of requests. The fallback has fired maybe a dozen times in production.
Vehicle context injection before the user message. When a customer selects their brand, model, year, and fuel type from the dropdowns, that context gets prepended to every message. Claude doesn't have to ask "what car do you drive?" — it already knows.
Conversation history with a hard cap. The API endpoint accepts up to 10 previous messages. This lets the AI ask follow-up questions ("Is the noise coming from the front or rear?") without losing context. But I cap it at 10 to control token costs and prevent prompt injection through long conversation chains.
How the AI Part Finder Works
The System Prompt
The system prompt is the single most important piece of the entire feature. I rewrote it eleven times before landing on something that consistently produced useful output. Here's the core structure (sanitized):
You are an expert European automotive parts specialist
at EUROPARTS LANKA in Sri Lanka.
Your role:
- Identify exact OEM part names and part number ranges
from user descriptions
- Ask for brand, model, year, and VIN if not provided
- Categorize parts: engine, transmission, suspension,
brakes, electrical, body, interior, filters,
cooling, exhaust, steering
- Provide Sri Lanka-relevant advice
- Be conversational, helpful, and technically precise
- Format identified parts clearly with: Part Name,
OEM Part Number Range, Compatible Models, Category
Rules:
- Always respond in English
(accept Sinhala input but respond in English)
- Never invent specific prices
- Suggest ordering through EUROPARTS LANKA
or WhatsApp +94 71 177 7222
- If unsure, ask clarifying questions rather than guessing
- Keep responses concise: 100-300 wordsA few things I learned about prompt design for ecommerce:
"Never invent specific prices" is non-negotiable. Early versions of the prompt didn't have this constraint, and Claude would occasionally hallucinate a price. In automotive parts, a wrong price is worse than no price. One customer screenshotted an AI-generated "estimated price" and tried to hold us to it. That was the last day the AI was allowed to mention numbers.
"Accept Sinhala input but respond in English" solved a real problem. About 30% of our users type in Sinhala or Singlish (a mix of Sinhala and English). Claude handles this remarkably well. A user types "mage car eke brake padle press karama ahari handa enawa" and Claude correctly identifies it as a brake noise issue and responds in clear English with the right part recommendations.
The security block at the end matters. Without it, users would occasionally try to jailbreak the AI into doing their homework or generating unrelated content. The explicit "you are ONLY an automotive parts assistant" instruction reduced off-topic responses to near zero.
Context Injection
When the user selects a vehicle from the dropdowns, the backend prepends this to every message:
$vehicleStr = 'Vehicle: '
. ($vehicleContext['brand'] ? $vehicleContext['brand'] . ' ' : '')
. ($vehicleContext['model'] ? $vehicleContext['model'] . ' ' : '')
. ($vehicleContext['year'] ? $vehicleContext['year'] . ' ' : '')
. (($vehicleContext['fuel'] ?? '') ? '(' . $vehicleContext['fuel'] . ')' : '');So if someone selects "Audi > A4 > 2019 > Diesel" and types "my brakes are squealing," Claude actually receives: Vehicle: Audi A4 2019 (Diesel). my brakes are squealing.
This is simple, but the effect on response quality is dramatic. Without vehicle context, Claude gives generic advice. With it, Claude can narrow down to the exact generation (B9), the correct brake pad compound for that engine variant, and the specific OEM numbers that fit.
Response Parsing and Display
I intentionally did not parse Claude's response into structured JSON. Early prototypes tried this — asking Claude to return a JSON object with partName, oemNumber, compatibleModels, etc. It worked 85% of the time. The other 15% it would return malformed JSON, or the format would subtly break when Claude wanted to ask a clarifying question instead of recommend a part.
Instead, Claude returns natural language, and I display it as-is in the chat interface. The formatting instructions in the system prompt ("format it clearly with: Part Name, OEM Part Number Range, Compatible Models, Category") give enough structure for readability without the brittleness of forced JSON output.
This was a pragmatic choice. For a higher-volume system, I'd invest in structured output with validation. For 40-60 queries a day, natural language with good formatting instructions is more reliable and more pleasant to read.
Rate Limiting and Security
Every AI endpoint is behind a rate limiter:
(new RateLimiter())->enforce('ai_finder', RATE_LIMIT_AI, RATE_LIMIT_WINDOW);The limits are generous enough for real customers (about 20 queries per 15-minute window) but tight enough to stop someone from running up our API bill. Input is sanitized and capped at 2,000 characters. Conversation history is sanitized server-side — I never trust the client's version of the chat history.
The IP hash logging (hash('sha256', $_SERVER['REMOTE_ADDR'])) gives us analytics without storing personally identifiable information. I can see how many unique users interact with the finder, what categories of parts are most requested, and where users drop off, without ever knowing who they are.
The Results: 966 Customers, 1,444 Parts
Since launching the AI Part Finder on europartslanka.lk:
- 966 unique customers have used the AI Part Finder
- 1,444 parts have been delivered through AI-initiated inquiries
- Average conversation length: 3.2 messages (user asks, AI identifies, user confirms or asks one follow-up)
- Time to part identification: Under 30 seconds, down from 15-30 minutes of manual back-and-forth
- WhatsApp inquiry volume dropped 34% in the first month — not because customers stopped reaching out, but because the AI handled the first triage
The most searched categories:
- Brakes (28%) — pads, discs, sensors
- Filters (19%) — oil, air, cabin, fuel
- Suspension (14%) — control arms, ball joints, bushings
- Engine (12%) — timing kits, gaskets, sensors
- Electrical (10%) — alternators, starters, sensors
The 7% that stumped the AI? Mostly very specific interior trim pieces and rare model-year combinations. For those, the AI correctly says "I'm not confident about this one — contact our team on WhatsApp for manual lookup." That fallback is by design. An AI that admits uncertainty is infinitely more useful than one that guesses confidently.
One metric I track that most people don't: false confidence rate. I manually reviewed 200 random AI responses in the first month. Of those, 11 contained a part number that was close but not exactly right (correct part family, wrong specific variant). That's a 5.5% near-miss rate. Not catastrophic — the order team catches these before fulfillment — but it's the number I'm working to bring under 2%.
What I Learned
1. The system prompt is 80% of the product. I spent more time writing and rewriting the system prompt than I spent on the entire chat UI. Prompt engineering for production is nothing like prompt engineering for demos. In a demo, "close enough" works. In production, "close enough" means a customer gets the wrong brake pad and you eat the return shipping cost.
2. Don't force structured output if you don't need it. JSON mode sounds elegant. In practice, it creates a brittle contract between your prompt and your parser. For a chat interface, let the AI speak naturally and use formatting instructions to guide structure. Save structured output for when you're feeding the response into another system.
3. Vehicle context is the highest-leverage data you can inject. The difference between "my brakes squeal" and "my 2019 Audi A4 B9 2.0 TDI brakes squeal" is the difference between a generic answer and a genuinely useful one. Invest in good dropdown selectors that capture vehicle data before the conversation starts.
4. Rate limiting is not optional. Someone will find your AI endpoint. Someone will try to use it as a free Claude proxy. Build rate limiting from day one, not after you get a surprise API bill.
5. Log everything, identify no one. IP hashing gives you analytics without liability. You can see patterns (which parts are most asked about, what time of day usage peaks, how many messages per conversation) without collecting PII. GDPR-friendly by design.
6. The Cloudflare Worker proxy pattern is underrated. It keeps your API key off the origin server, adds a layer of caching potential, and gives you a fallback path. The 10 minutes it takes to set up saves hours of debugging when your origin has issues.
What I'd Do Differently
Streaming responses. Right now, the user sends a message and waits 2-4 seconds for the full response. With streaming, they'd see tokens appear in real-time. It feels faster even when it isn't. I avoided streaming initially because the PHP backend doesn't handle SSE as cleanly as Node.js would. If I were starting today, I'd build the AI endpoint as a Cloudflare Worker with streaming from the start.
Structured output for the order pipeline. While I stand by natural language for the chat display, I'd add a second pass that extracts structured data (part name, OEM number, category) from the AI response and pre-fills the order form. Right now, the customer reads the AI's recommendation and manually types the part name into the order form. That's friction I should remove.
Embedding-based part matching. Instead of relying entirely on Claude's training data for OEM numbers, I'd build a vector database of our actual parts catalog and use RAG (retrieval-augmented generation) to ground responses in real inventory. This would eliminate the 5.5% near-miss rate almost entirely and let the AI say "we have this in stock" or "this is a 2-week import."
Multilingual output. The current system accepts Sinhala but responds in English. For a Sri Lankan audience, offering Sinhala responses would remove another barrier. Claude's Sinhala output quality has improved significantly — I'd test it seriously now.
A/B testing the prompt. I have an ABTest class in the codebase that I use for other features. I should have wired it into the AI finder from the start to test prompt variations systematically instead of relying on gut feeling and manual review.
Key Takeaways
- AI in ecommerce works best when it bridges a knowledge gap, not when it replaces human expertise. The Part Finder handles triage; the team handles fulfillment and edge cases.
- System prompt engineering for production requires iteration measured in weeks, not hours. Budget for 10+ revisions.
- Vehicle context injection (brand, model, year, fuel) is the single highest-leverage improvement for automotive AI. Capture it before the conversation starts.
- Natural language output with formatting instructions beats forced JSON for customer-facing chat interfaces. Save structured parsing for machine-to-machine flows.
- Log aggressively, identify minimally. IP hashing gives you the analytics you need without the liability you don't.
- Build the fallback path before you need it. Cloudflare Worker primary, direct API fallback, graceful error message as the last resort.
- Track false confidence rate, not just usage metrics. An AI that's wrong 5% of the time in a way that's hard to detect is more dangerous than one that's wrong 20% of the time obviously.
*Last updated: March 2024*
Written by Uvin Vindula
Uvin Vindula (IAMUVIN) is a Web3 and AI engineer based in Sri Lanka and the United Kingdom. He built europartslanka.lk, Sri Lanka's leading platform for European car parts, and consults on AI integration for ecommerce and automotive platforms. He is the author of The Rise of Bitcoin, Director of Blockchain and Software Solutions at Terra Labz, and founder of uvin.lk — Sri Lanka's Bitcoin education platform with 10,000+ learners.
For AI integration projects: hello@iamuvin.com↗ Explore services: iamuvin.com/services Book a call: calendly.com/iamuvin↗
Working on a Web3 or AI project?

Uvin Vindula
Web3 and AI engineer based in Sri Lanka and the UK. Author of The Rise of Bitcoin. Director of Blockchain and Software Solutions at Terra Labz. Founder of uvin.lk — Sri Lanka's Bitcoin education platform with 10,000+ learners.