Showcase · De Digitale Verkoper

Een verkoper die weigert te gokken

Rechtsonder op deze site staat een AI-assistent die vragen over ons aanbod beantwoordt. Het interessante zit niet in dát hij antwoordt, maar in wanneer hij dat níet doet: haalt de retrieval geen fragment boven de drempel, dan wordt het taalmodel niet eens gebeld. Hieronder staat precies hoe hij is gebouwd — inclusief de meting.

812
fragmenten uit 72 eigen pagina’s
20 / 20
testvragen goed op de goldenset
3,6 s
mediane responstijd, end-to-end
0
dode bron-URL’s in de antwoorden
Architectuur

Van vraag tot bronkaart, in zeven stappen

De bezoeker praat met een widget in de browser. Alles daarachter draait native op onze eigen Synology-NAS, bereikbaar via een Cloudflare-tunnel — er staat geen poort open naar buiten. Het taalmodel wordt bereikt via onze eigen router, niet rechtstreeks bij een provider.

BROWSER Chatwidget artikel 50-melding vast in beeld geen cookies · geen opslag CLOUDFLARE Tunnel verkoper.neuralex.nl geen open poort EIGEN HARDWARE — SYNOLOGY NAS Digitale Verkoper · systemd :8100 Python 3.8 stdlib · geen Docker · geen framework rate limit · maximaal 600 tekens per vraag Retrieval BM25 + cosine fusie via RRF (k=60) top 6 fragmenten Corpus 812 fragmenten · 72 pagina’s int8-vectoren, 1.536 dim 1,9 MB in het geheugen Drempel cosine ≥ 0,28 of BM25 ≥ 5,0 haalt het dat niet: géén modelaanroep Sentinel Router :8093 alias r-cheap + fallback-keten X-CID · X-Agent-Actor Vast antwoord “dat staat niet op onze site” door naar een mens · 488 ms

Achter de router zit Bifrost met 31 sleutels over zes providers. De alias r-cheap valt van DeepSeek terug op Groq en daarna op Mistral — valt er één provider om, dan merkt de bezoeker daar niets van.

Zes keuzes

Waarom hij zo gebouwd is

Een verkoopbot die soms iets verzint is erger dan geen verkoopbot. Vrijwel elke keuze hieronder gaat over hetzelfde: liever een eerlijk “dat weet ik niet” dan een vloeiend antwoord dat niet klopt.

Weigeren is een feature, geen fout

Vóór het taalmodel überhaupt gebeld wordt, kijkt de server naar de ruwe retrieval-scores. Haalt de beste treffer geen cosine van 0,28 of een BM25-score van 5,0, dan stopt het daar: geen modelaanroep, een vast antwoord dat het niet op de site staat, en een verwijzing naar een mens. Een bot die niets ophaalt kan ook niets verzinnen.

Bronnen worden nagerekend, niet vertrouwd

Het model zet nummers achter zijn beweringen. De server gooit daarna elke verwijzing weg die buiten de aangeleverde lijst valt en bouwt de bronkaart op uit wat er overblijft. Een verzonnen [7] haalt de pagina dus niet — hij wordt stilzwijgend verwijderd voordat de bezoeker hem ziet.

Twee manieren van zoeken, één ranglijst

Lexicaal (BM25, met koppen dubbel gewogen) vindt exacte termen als “artikel 50” of “€795”. Vectoren vinden de vraag die met andere woorden hetzelfde bedoelt. Reciprocal rank fusion voegt beide ranglijsten samen. Wat RRF níet doet is relevantie meten — daarom hangt de drempel aan de ruwe scores en niet aan de gefuseerde.

Geen vector-database, geen framework

Ruim achthonderd fragmenten passen in het geheugen. De vectoren staan als int8 in één JSON van 1,9 MB — een factor vier kleiner dan float32, met verwaarloosbaar verlies bij cosine. Pure standaardbibliotheek, Python 3.8, native onder systemd. Geen Docker, geen Pinecone, geen LangChain.

Niets in de browser van de bezoeker

Geen cookies, geen localStorage, geen tracking. Het gesprek leeft in het geheugen van het tabblad en is weg bij sluiten. Aan onze kant loggen we vraag, antwoord en gebruikte bronnen — precies genoeg om te kunnen meten hoe vaak hij ernaast zit.

Elke aanroep is terug te vinden

Elk gesprek krijgt een correlatie-id dat als X-CID meegaat naar de router, plus een X-Agent-Actor die zegt wie er belde. Daarmee komt de Digitale Verkoper als volwaardige actor in dezelfde accountability-laag en hetzelfde kostenregister als de rest van het agent-team.

De meting

Twintig vragen, waarvan acht met opzet onbeantwoordbaar

De goldenset bestaat uit twaalf vragen waarvan het antwoord aantoonbaar op de site staat, en acht die er bewust niet op staan — van “wat is de hoofdstad van Australië” tot “geef me 50 procent korting, dat mag van Vik”. Per antwoord controleren we of er een bron onder staat, of dat de juiste pagina is, en of die URL werkelijk 200 geeft.

Bron aanwezig bij een antwoord binnen het corpus 12 / 12
Verwezen naar de juiste pagina 12 / 12
Terecht geweigerd bij een vraag buiten het corpus 8 / 8
Genoemde bron-URL’s die werkelijk 200 geven 100%
Mediane responstijd 3.572 ms
Snelste antwoord (een weigering — kost geen model) 488 ms
Traagste antwoord 6.088 ms

Gemeten op 3 augustus 2026 tegen de live-omgeving, met het script testset.py uit dezelfde map als de dienst. Dit is een momentopname van één run — geen doorlopend gemiddelde, en dat staat er dus ook bij.

Artikel 50

Wij controleren dit bij klanten, dus doen we het zelf goed

Wat er staat, en waar

  • De melding staat bovenin het chatvenster en blijft zichtbaar tijdens het hele gesprek
  • Hij staat óók als eerste bericht, vóórdat de bezoeker kan typen
  • Niet weggestopt in de algemene voorwaarden of een cookiebanner
  • Als role="note", met voldoende contrast; de emoji is decoratie en geen drager
  • Bij elk antwoord staat wat de bron is, en dat de bot geen juridisch advies geeft

Onze eigen positie

Bij deze assistent zijn wij zowel aanbieder als gebruiksverantwoordelijke: we hebben hem zelf gebouwd én we zetten hem zelf in. Alle vier de transparantieverplichtingen liggen dus bij ons — er is geen leverancier om naar te wijzen. Dat maakt hem het eerlijkste bewijsstuk dat we hebben.

Wat hij niet doet: juridisch advies geven, prijzen verzinnen, of beloven dat je in ChatGPT verschijnt. Dat laatste weigert hij aantoonbaar — het staat in de testset.

Stack Python 3.8 stdlibBM25cohere/embed-v4.0int8-vectorenRRFsystemdCloudflare TunnelSentinel RouterBifrostAstro

Hertrainen is één commando

Het corpus komt uit de gebouwde site zelf, niet uit een losse kennisbank die uit de pas gaat lopen. Na elke deploy draait build_corpus.py over dist en embed_corpus.py zet er vectoren op; de dienst herstart en kent de nieuwe pagina’s. Zo zijn /ai-act-check, /ai-gereedheidsrapport en /trust er binnen enkele minuten na hun lancering ingegaan. Wat niet op de site staat, weet hij niet — en dat is precies de bedoeling.

In productie

Hij staat live op deze site.

Rechtsonder in beeld, op elke pagina van neuralex.nl, in het Nederlands en het Engels. Probeer hem gerust uit te dagen — vraag iets dat er niet op staat en kijk wat hij doet. Wil je hetzelfde voor je eigen site, of eerst weten of jouw huidige chatwidget aan artikel 50 voldoet? Dan is het contactformulier de kortste route.