Resources/Chatbots, language, and model quality/How to Make an AI Chatbot Understand Moroccan Darija and Other Dialects
How to Make an AI Chatbot Understand Moroccan Darija and Other Dialects
I almost fine-tuned a local model for Moroccan dental support. Real examples written by experienced clinic assistants solved the harder problem first.
Series
Part of our AI Automation for Small Business: The Practical Guideresource series.
Mohamed Amine Saada, Forteuno Web
Published

A customer support chatbot can speak standard Arabic and still sound completely wrong in Moroccan Darija. The grammar may be acceptable. The meaning may even be correct. But the reply feels translated, misses local shorthand, or fails when the customer mixes Darija, French, Arabic, and Latin characters in one sentence. This problem also appears in regional Arabic dialects, African languages, Indian languages, Caribbean Creoles, Spanglish, and local slang that is underrepresented in general training data.
“The best fix was not a bigger model. It was better examples from people who already knew how real patients speak.”
What happened in my Moroccan dental support SaaS
I built a customer support SaaS for dental clinics in Morocco. At first I assumed dialect quality required fine-tuning a local model. That sounded like the technical answer: collect data, train a model, host it, and make Darija part of the weights. Before committing to that work, I tried a smaller intervention. We collected real support examples from assistants who had worked inside dental clinics. They knew the phrases patients use for pain, appointments, prices, emergencies, and follow-up. We placed those examples in the prompt context. The quality improved quickly.
The examples did more than translate vocabulary. They showed tone, intent, clinic policy, when to ask another question, and when to call a booking tool. That distinction matters. A dictionary can explain that a word refers to an appointment. A worked example shows how the assistant should respond when a patient uses that word while describing pain and asking for the earliest available time.
The same pattern held on a very different build: a translation agency wanted customers to submit an order, get a quote, and pay entirely inside a chat conversation, no upload page, no separate checkout. Its customers were Moroccan emigrants scattered across France, the US, and the Gulf, so a single thread could switch between Darija, French, Egyptian Arabic, and English mid-conversation. Across roughly 40 chatbot projects now, most for clinics and dental centers in Morocco and a handful for US companies, the language problem and the architecture problem turned out to be the same problem: a model that understands the words is not enough if the system around it cannot route, verify, and act correctly on what it understood.

What a strong few-shot example should contain
Why code-switching breaks generic models, and what actually fixes it
Darija is already a blend of Arabic, French, Spanish, and Amazigh influence, so a single customer message routinely mixes languages inside one sentence. Fixing that is not about finding a bigger model. It is disciplined few-shot coverage of the mix, combined with picking a base model that is genuinely strong across Arabic, French, and English rather than one built primarily for English with Arabic bolted on. The agent also always replies in Arabic script, never Arabizi (Latin-character transliteration). Answers in Arabic letters produce fewer downstream errors and read more naturally to a Moroccan customer than transliterated text does.
One recurring failure is worth naming exactly, because it is not a vocabulary gap: a customer types نرف meaning roughly “I want to know” (from the Darija verb عرف, to know). In Arabizi the correct spelling keeps the numeral: n3rf, where the 3 stands in for the Arabic letter ع. When someone drops the numeral and types nerf, the message becomes visually and phonetically identical to the French word for “nerve.” A multilingual model with no specific bracing for this reads French and answers about nerves instead of recognizing the Darija intent. The fix is not a longer glossary. It is prompting the agent to treat this exact class of ambiguity, a Darija word colliding with a real word in another language once a numeral is dropped, as a signal to ask a one-line clarifying question rather than guess. That is the same discipline a human assistant applies without thinking. Left alone, a model will confidently pick the wrong language instead.
The architecture behind it: an orchestrator, not one long prompt
Once a chatbot needs to do more than answer questions, one long system prompt stops being a language problem and becomes an architecture problem. The order-and-payment build above used an orchestrator that routes each turn to a specialized sub-agent: one owns FAQs, one owns order creation and status, one owns payment, one owns greetings and small talk. Each sub-agent has a narrow prompt scoped to its own job and its own tools, exposed through MCP, some of which write directly into the client’s existing order platform: create an order, check a status, confirm a payment. The orchestrator composes their outputs into one reply. This keeps any single prompt short enough to stay reliable, and it means a change to the payment agent’s behavior cannot accidentally shift how the FAQ agent answers a pricing question.
Few-shot examples are injected at runtime inside this structure, not baked into one static system prompt. When a message arrives in Darija, the routing layer detects that and injects Darija examples scoped to the sub-agent handling that intent, not a fixed set glued to the top of every conversation. That keeps the context focused and makes it possible to fix one dialect edge case without touching every other behavior in the system.
The payment agent gets the least trust in the system
Any sub-agent connected to a tool that can create an order, move money, or write to a client’s live system is a genuine attack surface. Prompt injection has held the #1 spot on OWASP’s LLM Top 10 across every edition, and it gets more dangerous exactly when an LLM has tools that can send messages, call APIs, or make purchases: a successful injection lets an attacker use whatever the tool can do. In practice that means the payment and order-writing agents get the narrowest tool permissions available, structured output validation before anything executes, and an explicit confirmation step before an irreversible action goes through, rather than trusting the model’s own judgment on when an action is safe.
Start with a high escalation rate, and earn autonomy
Every one of these agents launches with a deliberately high escalation-to-human rate. The instinct to make an agent fully autonomous on day one is exactly what causes irreversible mistakes: a wrongly confirmed order, a booking that was never real, an answer a patient acts on. Autonomy gets earned incrementally, one resolved edge case at a time, until the agent reaches the highest hands-off rate that still holds up under real traffic. An agent that never escalates is not a sign of quality. As of 2026, I have not shipped one I would trust to run that way.
How to evaluate dialect quality
In practice this runs as a growing regression set. Every real failure that shows up in testing becomes a permanent test case, split between per-agent evaluations (does the payment agent pick the right tool and arguments) and whole-conversation evaluations (does the orchestrated reply make sense end to end). Easy, well-understood cases get graded automatically by an LLM judge. Anything new, or anything the automated judge has not proven reliable on yet, gets scored manually. A native speaker only sits down to actually talk to the bot after that automated pass, because by then most of the obvious breakage has already been caught, and that review can focus on tone and naturalness instead of hunting for bugs.
For the Darija-specific agents I have kept GPT-4.1 as the production default rather than moving to a newer release, mainly on cost efficiency given comparable or better quality on this specific language task. It is not the strongest model at tool calling, which is exactly why tool-calling responsibility stays with narrow specialized agents instead of one general-purpose prompt asked to do everything at once. When benchmarking any model for Darija or another underrepresented dialect, general leaderboards are close to useless. Purpose-built Arabic benchmarks that specifically test dialect and script variation are a far better signal.
Source: Arabic LLM Broad Leaderboard (Silma AI)
Source: Awesome Arabic NLP (curated resource list)
Few-shot examples will not solve every language problem. Fine-tuning can help when the behavior must stay consistent across a large volume and the prompt has become too expensive or fragile. But I would not start there. I would first prove that good examples and a representative evaluation set can produce the behavior. That gives you cleaner data if you later decide to fine-tune.
Choose the lightest model adaptation method that solves the measured problem.
Few-shot vs. fine-tuningSee how to build the wider support system around the conversation.
AI chatbot setup guideContinue exploring
Resource
Few-Shot Prompting vs. Fine-Tuning vs. Training: Which Fix Do You Need?
Technical teams often jump to fine-tuning too early. A small set of excellent examples can fix tone, format, tool use, and edge-case handling without changing model weights.
Read itResource
The Latest AI Model Is Not Always the Best Model for Your Task
I have kept GPT-4.1 and GPT-4o in production tasks when they produced fewer errors than newer models. Release date is not an evaluation metric.
Read itResource
AI Chatbots for Customer Service: Use Cases and Setup
How to design a chatbot that answers from approved information, performs useful actions, and hands difficult cases to people.
Read it