Tingit 8QL – Formele documentatie van de taal voor LLM-toepassingen
Via reverse engineering van de bestaande broncode naar een formele Tingit 8QL taaldefinitie, waarmee binnen Tingit 8QL expressies gegenereerd kunnen worden.

In het vorige artikel over de taal 8QL binnen ons product Tingit, hebben we duidelijk gemaakt dat we onze gebruikers willen helpen 8QL te genereren. Eén van de volgende stappen is om tot documentatie te komen waarmee de LLM valide 8QL expressies kan genereren. Die documentatie is de sleutel om de intentie van de gebruiker om te zetten naar een werkende 8QL query binnen Tingit.
Geen formele beschrijving 8QL voor de LLM
De huidige beschrijving van 8QL is gericht op gebruikers. Het voldoet tot op zekere hoogte om een LLM mee te voeden die zelfstandig 8QL expressies kan genereren, maar we zien te veel fouten in het resultaat om daar genoegen mee te nemen. Het is zaak om te komen tot een formele beschrijving van de 8QL taal.
In die formele beschrijving willen we terugzien welke symbolen en termen gebruikt mogen worden (lexicale analyse), hoe die met elkaar samenhangen (syntactische analyse) en wat de betekenis daarvan is (semantische analyse). Wenselijk is als gebruik wordt gemaakt van bijvoorbeeld Backus–Naur form (BNF) notatie, voor mensen lastig te lezen, maar een peuleschil en zelfs wenselijk voor de LLM.
Reverse engineering
We hebben gebruik gemaakt van een Claude Code sub agent, eentje die zo is ingericht dat deze op basis van reverse engineering van de bestaande Tingit codebase een formele taalbeschrijving genereert. De agent bestaat uit een tekstbeschrijving, waarin de volgende onderdelen zijn opgenomen:
- Claude Code sub agent metadata; nodig voor kunnen aanroepen van de sub agent in Claude Code
- rolbeschrijving; plaatst de LLM in de rol van compiler-expert
- analysestappen; beschrijving van de stappen die moeten worden uitgevoerd om een volledig beeld te verkrijgen van de bestaande broncode
- documentstructuur; Markdown template met de onderdelen die de documentatie tenminste moet bevatten
- leidende principes; instructies over wat de LLM niet mag doen, zoals het gebruiken van bestaande kennis van talen (bijvoorbeeld van SQL, iets waarvan we proefondervindelijk hebben gezien dat de LLM dat dicht bij 8QL plaatst)
De agent is door een aantal iteraties gegaan, voordat het resultaat goed genoeg was voor de volgende stap. Het meest veelvoorkomende probleem was dat taalconstructies erbij verzonnen werden.
Testen genereren 8QL expressies
De uitgegenereerde formele 8QL taaldefinitie is samen met een lijst van stamgegevens (nodig voor 8QL als argumenten voor functies) toegevoegd aan een Gemini Gem, omgedoopt tot 8QL Expert. Vervolgens zijn prompts ingevoerd en is het resultaat getest in Tingit om te bepalen of i) de 8QL expressie valide is en ii) de 8QL expressie resultaten teruggeeft.
In iteraties is de gegenereerde documentatie teruggebracht naar een scherpere definitie, net zolang tot we tevreden waren over het resultaat. Nadat we hebben vastgesteld dat de documentatie goed genoeg was voor ons doel, moesten we de volgende uitdaging overwinnen: hoe verzorgen we dat de formele 8QL taaldefinitie up-to-date blijft als 8QL zich blijft ontwikkelen?
Taaldefinitie direct uit broncode
Gewapend met de kennis van hoe de documentatie moest worden, gaan we in Java custom annotaties ontwikkelen die toegevoegd worden aan de 8QL parser. Om dat mogelijk te maken moet de code gedeeltelijk herschreven worden, zodat er inhaakpunten beschikbaar komen waar de annotaties op te zetten zijn.
Bij het opstarten van de applicatie worden alle 8QL annotaties opgehaald, waaruit de formele 8QL taaldefinitie wordt gegenereerd. De agent die belast is met het genereren van 8QL expressies wordt geladen met deze altijd up-to-date taaldefinitie. Om te verzorgen dat de annotaties goed worden toegepast worden met behulp van ArchUnit architectuurtests toegevoegd die garanderen dat de annotaties correct worden toegepast.
Code completion uit taaldefinitie

Een volgende stap is om bij het geplande verbeteren van de 8QL editor code completion ook door de LLM te laten uitvoeren. Inleidende tests laten zien dat de LLM die taak goed lijkt aan te kunnen. Wat je dan krijgt is dat bij het handmatig invoeren van een 8QL expressie, na een korte pauze, de backend wordt verzocht om de mogelijke vervolgstappen in de expressie aan te reiken. De gebruiker moet dan suggesties kunnen accepteren, vergelijkbaar zoals een Copilot dat aanbiedt.
Formele 8QL taaldefinitie als hoeksteen
Door te allen tijde te kunnen beschikken over de meest recente versie van de taaldefinitie, ook nadat er nieuwe functies aan de taal zijn toegevoegd, verzorgen we dat de 8QL agent altijd meegaat in de laatste ontwikkelingen. Daarnaast kan de taaldefinitie ondersteunen bij 8QL code completion, een traject wat we nog verder moeten uitwerken.
De werkwijze om eerst goedkoop en via iteraties te komen tot een in proeven vastgesteld succesvol resultaat, maakt dat geen dure investering gemaakt hoeft te worden in software-paden die later toch niet nodig bleken te zijn. Vanuit de definitieve taaldefinitie wordt het gewenste gedrag in de applicatie ingebouwd, waarna het zelf in staat is om de documentatie aan te leveren.