Engineering note

AI narrates, it doesn’t invent: keeping facts deterministic in AI-generated content

Every EmlakKlip video has a voice-over written by a language model. The model never writes a number. It writes a template with placeholders; code fills in the area, the distances and the place names, and code decides whether the text may be used at all.

Why a fluent model is the wrong place for facts

A property video makes factual statements: the parcel is 9,013 square metres, it lies in Burhaniye, the nearest school is so many kilometres away. A buyer acts on those numbers. Language models are good at sentences and unreliable with figures: they round, convert units, swap one place’s distance for another’s, or add a feature nobody stated.

We saw the failure mode in a competing product’s video: the on-screen list said 4.3 km, while the voice said “four and a half”. Two outputs of the same fact disagreed. Our rule is simpler than any prompt: geographic facts are computed by deterministic code; the model only tells them.

The model writes a template, code writes the numbers

The model receives the facts as named placeholders — {alan} (area), {ilce} (district), {poi1.ad} and {poi1.mesafe} (name and distance of the first nearby place) — and returns text that uses them. It never sees the values of the numeric placeholders, so it cannot copy, round or “improve” them.

Code then fills each placeholder twice: once for the screen (“8,398.17 m²”, “1.5 km”) and once for the voice, as words a speech engine reads correctly. The spoken distance is generated from the same label the screen shows, so the voice and the screen cannot disagree by construction — and a test holds that property.

Personal data stays out of the prompt: the agent’s phone number and name are added by the layout, never sent to the model.

Code decides whether the text is usable

Every template passes a validator written in plain code before it can be used. The model is not trusted to follow instructions; its output is checked. A template is rejected when:

  • it contains a digit, a number word or a unit of measure outside a placeholder;
  • it uses a placeholder that does not exist for this parcel;
  • a distance is not attached to the place it belongs to — the nearest place name before every distance must be that distance’s own place;
  • the area or a location placeholder is missing, or a place the customer added by hand is not mentioned with its distance;
  • it implies building or living on a parcel registered as agricultural land, when nobody stated zoning;
  • a customer’s own note is merged into the middle of a sentence, or the filled-in text repeats the same phrase within a few words;
  • it is too long for the video’s narration slot or too short to be useful.

Most of these rules come from outputs we actually measured — a distance that turned out to be the school’s, not the road’s; a customer note pasted after “also” with a capital letter; a sentence inviting the buyer to “build a life” on farmland. Each became a rule and a test.

Retry with the reason, then fall back

When a template is rejected, the model gets the validator’s message — which rule failed and why — and tries again, at most twice. If the third template still fails, the system uses a deterministic, AI-free template built from the same facts. The text is plainer, but the video is still delivered, and nothing in it is invented.

The same validator checks text the customer edits by hand. Typing “300 metres” into the narration is rejected exactly as it would be from the model: distances enter only through placeholders.

Open data needs the same suspicion

Facts can be wrong before any model touches them. In the open map data we use, the “beach” category also carries parks and hotels; a park named after a singer was classified as a beach. If the place name contains no word for sea, beach or shore, we treat it as a generic place, and the template has no way to call it a beach.

Reproducible even though the model is not

Model output is not deterministic: the same request can return a different sentence tomorrow. So the accepted template is stored with the job, and every render — including a later re-render — uses the stored template, not a new model call. The narration of a delivered video can always be reproduced.

The rules are covered by 93 automated tests that run without network access, so changing a rule or a prompt cannot silently weaken a check.

Takeaways for any AI-generated content with facts

  • Let code compute every fact; let the model choose words around placeholders.
  • Do not show the model values it must not change.
  • Validate output with code, and feed the reason back on retry.
  • Always have a deterministic fallback, so a bad model day does not stop delivery.
  • Store what was accepted; never regenerate it at render time.

See the EmlakKlip case study and our enterprise AI work.

Have a project in mind?

Send a short description. If you need a mutual NDA first, we will send ours before you share details.

Message us on WhatsApp