How the assistant answers a question about Yalova
Residents ask short questions in everyday Turkish, often with typos, slang or a district name. The assistant's job is to give the right local answer quickly and never to invent one.
1 · Understand the question
The question is cleaned up (typo correction, follow-up context, the district or topic the resident was already talking about) so "and tomorrow?" after a ferry question still means the ferry.
2 · Live city data first
An intent registry routes questions with one correct, live answer to structured data: time, food, ferries, pharmacies, weather, statistics, exchange rates, prayer times, health, utilities, emergencies, the airport, transport and jobs. These answers do not need a language model.
3 · Local knowledge and news
Other questions go to a local knowledge base (institutions, people, places, transit lines, procedures, neighbourhoods, businesses, events) and to retrieval over the news archive.
4 · Claude Haiku for language
The language model understands the question and turns retrieved sources into a short Turkish answer. Claude Haiku powers this language layer.
5 · Honesty check
An honesty gate checks whether an answer is supported by its sources and can annotate, downgrade or refuse it. It currently runs in monitoring mode while we tune it. General answers without local grounding are off by default.
6 · Learn by verifying
Questions the assistant can't answer go into a learning queue in the admin panel, so the knowledge base grows from real residents' questions, not from guesses.
Guardrails we run
- A gate of golden test suites (negation, follow-up questions, district and topic memory, privacy, humour and absurd questions) that we run before deploys.
- Monthly hard caps on language-model, grounding and voice spend.
- Rate limits on the public assistant so one visitor can't exhaust the budget.
- Stale data is withheld: when a pharmacy source failed, we stopped serving the old list instead of showing it.
The stack
Mobile app in Expo / React Native for iOS and Android; a Fastify (TypeScript) API with Prisma and SQLite; push notifications and phone-number sign-in. The news feed is updated from the newsroom's RSS feed every few minutes.
See it for yourself
The assistant is live on the web. Questions are answered in Turkish.
Frequently asked questions
Why not send every question straight to a language model?
Many city questions have one correct, live answer: the next ferry, today's on-duty pharmacy. Those are answered from structured data. The language model is used where language is the hard part, and it works from local sources.
What happens when the assistant doesn't know?
It says so and the question goes into a learning queue. General answers without local grounding are switched off by default.