A synthetic conversation that reads fine can still be unusable, and the reasons are specific enough to check mechanically. Here is the full gate one Arabic support dataset runs on every row, grouped by what each group is defending against.
The point of listing them is not the count. It is that each one exists because something went wrong without it.
Structure — 5 checks
| Check | What it stops |
|---|---|
| Turn count bounds | Two-line "conversations" that resolve nothing |
| Role alternation | Two consecutive customer turns with no agent reply |
| Minimum turn length | Filler turns like "ok" padding the count |
| No adjacent duplicates | The model restating the previous turn |
| Every turn has content | Empty strings surviving the parser |
These are cheap and catch parse-level damage. Nothing subtle, but a corpus without them contains rows no consumer can use.
Dialect integrity — 6 checks
This is where Arabic synthetic data usually fails, and where generic pipelines have nothing.
Cross-dialect contamination. The model reaches for Levantine or Egyptian vocabulary because that is what dominates its Arabic training data. A Saudi support conversation containing بدي or عايز is not a Saudi support conversation. Each banned list is dialect-specific.
Robotic support phrasing. Template politeness — the Arabic equivalent of "how may I assist you today" — appears constantly because it is over-represented in scraped support text. It marks a row as synthetic to any native reader.
English inside the dialogue. Support vocabulary in Latin script leaking into an Arabic turn.
Caricature. The subtle one. A row can be dialectally correct and still wrong because it is laying the dialect on too thick — every marker the region has, in four consecutive sentences. Real speakers do not do this.
Register markers present. The inverse check: the agent's voice has to carry at least one genuine hospitality marker for the dialect, or it reads as translated MSA.
Forbidden register slang. Agents and customers do not speak identically. A support agent using the customer's most informal constructions is a register error even when the dialect is right.
Entities and ordering — 7 checks
These enforce that the conversation is internally consistent with the facts the generator injected.
- The injected amount appears in the conversation
- The injected reference number appears
- The agent names the brand
- The agent introduces itself in its first turn
- The customer does not know the agent's name before it is given — a leak of generator state into the customer's mouth, and one of the most common failures
- The agent does not offer a capability the brand does not have
- Verification happens before resolution, not after
The last two are the ones that make a corpus usable for training a support model rather than just a language model. A brand that does not do refunds must not offer one, and an agent that resolves a case before verifying identity is teaching a behaviour you do not want.
Sector vocabulary and frequency caps — 4 checks
Sector vocabulary present and resolution fits the sector: a telecom complaint resolved with a banking remedy is coherent Arabic and useless data.
Dialect marker frequency and hospitality phrase repetition are corpus-aware caps. Any single marker or courtesy phrase may only appear so many times across the agent's turns. Without these, the gate's own incentives push every row toward the same safe phrasing, and the corpus collapses into a narrow register.
The pattern worth stealing
Three of these groups check things a human reader would notice. The fourth — frequency caps — checks something no single reader can see, because it is a property of the corpus rather than the row.
That is the category most pipelines miss entirely. A per-row validator cannot enforce "this phrase appears in under 5% of rows", and by the time you notice at read-through you have 40,000 rows sharing a tic.