- Implement Fake repositories and services for testing purposes. - Create tests for Article API including creation, validation, and listing. - Develop ProcessTicketJobFlowTest to validate ticket processing logic. - Add QuickReplyAdminTest for creating and updating quick replies. - Implement TicketAndArticleModelTest to ensure proper cascading deletes and credential encryption. - Create TicketIngestionTest for ticket creation and job dispatching. - Add TicketShowPageTest to verify rendering of quick replies and tool calls. - Implement unit tests for ClassifierPromptBuilder, EmbeddingService, LlmJsonDecoder, QuickReplyResolver, SupportReplyService, TicketResultPayloadBuilder, TicketToolCallService, and ToolCallRequestValidator.
206 lines
12 KiB
PHP
206 lines
12 KiB
PHP
<x-layouts.admin title="Proces">
|
|
<div class="space-y-6">
|
|
<section class="bg-white rounded-xl p-5 shadow">
|
|
<div class="flex items-start justify-between gap-6">
|
|
<div>
|
|
<h2 class="text-xl font-semibold">Hoe werkt de Ticket Assistant?</h2>
|
|
<p class="mt-2 max-w-3xl text-sm text-slate-600">
|
|
Zie het systeem als een supportmedewerker met een hele grote map handleidingen. Eerst maakt hij
|
|
de vraag netjes leesbaar, daarna zoekt hij de beste stukjes uitleg, en daarna schrijft hij een
|
|
kort advies dat een supportmedewerker kan controleren.
|
|
</p>
|
|
</div>
|
|
<div class="rounded bg-slate-100 px-3 py-2 text-xs text-slate-600">
|
|
Draait lokaal met je eigen kennisbank en je eigen AI-model
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="grid gap-4 lg:grid-cols-2">
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Wat gebeurt er met een ticket?</h3>
|
|
<div class="mt-4 space-y-4">
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">1. De vraag komt binnen</div>
|
|
<p class="text-sm text-slate-600">
|
|
Een klantvraag komt binnen via de API of via het handmatige testveld in het admin scherm.
|
|
Het ticket komt eerst in de wachtrij, zodat de zware stappen op de achtergrond kunnen lopen.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">2. De vraag wordt netjes gemaakt</div>
|
|
<p class="text-sm text-slate-600">
|
|
De AI haalt ruis, typefouten en privegegevens weg. Denk aan: naam, adres, IBAN of andere
|
|
gegevens die niet nodig zijn om het probleem op te lossen.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">3. De betekenis wordt omgezet naar een zoekcode</div>
|
|
<p class="text-sm text-slate-600">
|
|
De app maakt van de nette vraag een soort getallen-code. Die code beschrijft niet de exacte
|
|
woorden, maar waar de vraag over gaat. Daardoor kan "mail doet het niet" ook artikelen
|
|
vinden
|
|
waarin "e-mail storing" staat.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">4. De kennisbank wordt doorzocht</div>
|
|
<p class="text-sm text-slate-600">
|
|
Artikelen zijn opgeknipt in kleine tekstkaartjes. De app zoekt de kaartjes die het meest
|
|
lijken op de klantvraag en groepeert die daarna terug naar artikelen.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">5. De AI kiest het beste artikel</div>
|
|
<p class="text-sm text-slate-600">
|
|
De AI krijgt de beste kandidaten te zien en kiest welk artikel het beste past. Daarbij geeft
|
|
hij ook aan hoe zeker hij is en waarom hij dat artikel kiest.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">6. Eventueel wordt extra informatie opgehaald</div>
|
|
<p class="text-sm text-slate-600">
|
|
Sommige artikelen mogen extra hulpmiddelen gebruiken. Voor nu is dat alleen domeininformatie
|
|
ophalen. Dat gebeurt alleen als het artikel dit toestaat en de vraag genoeg gegevens bevat.
|
|
</p>
|
|
</div>
|
|
<div class="border-l-4 border-slate-900 pl-4">
|
|
<div class="font-medium">7. Er komt een advies of een melding</div>
|
|
<p class="text-sm text-slate-600">
|
|
Als het artikel een snelantwoord heeft, gebruikt de app dat direct. Anders maakt de AI een
|
|
korte conceptreactie. Als er geen passend artikel is, schrijft de app geen klantantwoord
|
|
maar
|
|
meldt hij dat de kennisbank iets mist.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Hoe werkt de kennisbank?</h3>
|
|
<div class="mt-4 space-y-4">
|
|
<div>
|
|
<div class="font-medium">Artikelen zijn de handleidingen</div>
|
|
<p class="text-sm text-slate-600">
|
|
Elk artikel is een uitleg die support kan gebruiken. Artikelen kunnen uit de externe
|
|
helpdesk komen of handmatig worden aangemaakt.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium">Artikelen worden in kleine kaartjes geknipt</div>
|
|
<p class="text-sm text-slate-600">
|
|
Een lang artikel kan over meerdere dingen gaan. Daarom knippen we het in kleine stukken.
|
|
Zo kan de app precies het stukje vinden dat bij de vraag hoort.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium">Elk kaartje krijgt een betekenis-code</div>
|
|
<p class="text-sm text-slate-600">
|
|
Die code helpt zoeken op betekenis. Het gaat dus niet alleen om dezelfde woorden, maar om
|
|
dezelfde bedoeling.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium">Bij een nieuw AI-model opnieuw indexeren</div>
|
|
<p class="text-sm text-slate-600">
|
|
Als je het model wijzigt dat deze betekenis-codes maakt, moeten de kaartjes opnieuw worden
|
|
berekend. Dat kan via Settings bij Embeddings.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="grid gap-4 lg:grid-cols-3">
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Wat zie je op een ticket?</h3>
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
Je ziet de originele vraag, de opgeschoonde vraag, de gekozen artikelen, eventuele hulpmiddelen die
|
|
gebruikt zijn, fouten, en alle stappen in volgorde. De nieuwste stap staat bovenaan.
|
|
</p>
|
|
</div>
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Wanneer komt er geen antwoord?</h3>
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
Als de app geen passend artikel vindt, maakt hij bewust geen reactie naar de klant. Dan zie je een
|
|
melding dat de kennisbank tekortschiet, plus een suggestie voor wat er mist.
|
|
</p>
|
|
</div>
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Waarvoor zijn artikelnotities?</h3>
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
Een artikelnotitie is een interne tip voor de AI. Bijvoorbeeld: "Gebruik dit artikel alleen voor
|
|
domeinen" of "Vraag eerst om klantnummer als dit ontbreekt". De notitie is geen klanttekst.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="grid gap-4 lg:grid-cols-2">
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Snelantwoorden</h3>
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
Sommige artikelen hebben uiteindelijk hetzelfde antwoord nodig. Dan kun je een snelantwoord maken en
|
|
aan meerdere artikelen koppelen. Als zo'n artikel wordt gekozen, gebruikt de app het snelantwoord en
|
|
hoeft de AI geen nieuwe klantreactie te schrijven.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Hulpmiddelen en allowed actions</h3>
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
Sommige antwoorden worden beter als de app iets kan nakijken. Daarom kan een artikel aangeven welke
|
|
hulpmiddelen toegestaan zijn. De AI mag zo'n hulpmiddel alleen voorstellen; de applicatie
|
|
controleert
|
|
daarna zelf of het echt mag.
|
|
</p>
|
|
<div class="mt-4 rounded border p-3">
|
|
<div class="font-medium">Nu beschikbaar: domain_inf</div>
|
|
<p class="mt-1 text-sm text-slate-600">
|
|
Hiermee kan de app domeininformatie ophalen. Dat kan alleen als het artikel `domain_inf`
|
|
toestaat,
|
|
als de vraag een domeinnaam bevat, en als er API-gegevens op het ticket zijn opgeslagen.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Woordenlijst</h3>
|
|
<div class="mt-4 space-y-3 text-sm text-slate-600">
|
|
<div><span class="font-medium text-slate-900">Embedding:</span> een betekenis-code van tekst.</div>
|
|
<div><span class="font-medium text-slate-900">Chunk:</span> een klein stukje van een artikel.</div>
|
|
<div><span class="font-medium text-slate-900">Confidence:</span> hoe zeker de AI is van zijn keuze.
|
|
</div>
|
|
<div><span class="font-medium text-slate-900">Knowledge gap:</span> de kennisbank heeft
|
|
waarschijnlijk nog geen goed artikel voor deze vraag.</div>
|
|
<div><span class="font-medium text-slate-900">Toolcall:</span> een gecontroleerde actie waarmee de
|
|
app extra informatie kan ophalen.</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="bg-white rounded-xl p-5 shadow">
|
|
<h3 class="font-semibold">Voorbeeld in gewone taal</h3>
|
|
<div class="mt-4 grid gap-3 lg:grid-cols-4">
|
|
<div class="rounded border p-3">
|
|
<div class="font-medium">Klant vraagt</div>
|
|
<p class="mt-1 text-sm text-slate-600">"Mijn mail doet het niet op mijn domein."</p>
|
|
</div>
|
|
<div class="rounded border p-3">
|
|
<div class="font-medium">App zoekt</div>
|
|
<p class="mt-1 text-sm text-slate-600">De app zoekt kaartjes over mail, domeinen en instellingen.
|
|
</p>
|
|
</div>
|
|
<div class="rounded border p-3">
|
|
<div class="font-medium">AI kiest</div>
|
|
<p class="mt-1 text-sm text-slate-600">De AI kiest het artikel dat het meest bruikbaar lijkt.</p>
|
|
</div>
|
|
<div class="rounded border p-3">
|
|
<div class="font-medium">Support controleert</div>
|
|
<p class="mt-1 text-sm text-slate-600">Support ziet het advies, de reden en de gebruikte stappen.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</x-layouts.admin>
|