Van bronnen naar een chatbot die zijn antwoorden kan bewijzen.
API.Bot is de service die achter het portal draait: je geeft het PDF's, pagina's, databases, API's en wiki-tekst — het maakt daar een doorzoekbare index van en beantwoordt vragen met Groq, met citaten terug naar de brontekst.
Alle endpoints vereisen Authorization: Bearer <BOT_SERVER_KEY>.
01 — Architectuur
Twee gescheiden paden: publiceren (traag, async) en chatten (snel, synchroon).
Het portal praat via één API met de bot-server. Publiceren van een bot start alleen een
achtergrondjob — de portal krijgt direct een deployment_id terug en pollt daarna
de voortgang. Chat-verzoeken lopen wél synchroon: die moeten binnen enkele seconden een
antwoord geven.
02 — De ingest-pipeline
Elke bron doorloopt dezelfde vijf stappen, plus één gezamenlijke healthcheck.
De voortgang van elke stap wordt weggeschreven naar deployment_steps, zodat het
portal live kan tonen waar een publish op dat moment staat.
Ophalen
PDF, URL, database-rows of API-response binnenhalen. Bij een HTML-snapshot: de signed snapshot-URL, niet de originele pagina.
Extraheren
Leesbare tekst uit PDF (pdf-parse), HTML (Readability) of API-response (JSON/XML/HTML) halen.
Opknippen
Recursief gesplitst op alinea → zin → spatie, ~800 tokens per stuk met 100 tokens overlap.
Embedden
Lokaal ONNX-model (all-MiniLM-L6-v2, 384 dimensies) — geen externe embedding-kosten.
Indexeren
Chunks + vectors in chunks, doorzoekbaar via een HNSW-index.
Controleren
Eén keer per deployment: staat er nu daadwerkelijk iets doorzoekbaars klaar?
content_hash mee. Blijft die
gelijk aan de laatst succesvol geïndexeerde hash, dan wordt de hele pipeline voor die bron
overgeslagen (status skipped). Stuurt het portal
null, dan wordt altijd volledig herverwerkt — zo forceer je een reindex na een
configuratiewijziging.
03 — Bron-types
Vijf manieren om kennis in de bot te krijgen.
Bestand via signed URL, tekst geëxtraheerd met pdf-parse. Citaties kunnen
naar een paginanummer wijzen.
Webpagina, tekst via Readability. Optioneel een source_snapshot: het portal
stuurt dan een vooraf gedownloade HTML-snapshot (tegen bot-detectie), maar citaties blijven
linken naar de echte origin_url.
Rechtstreekse connectie, tabellen als markdown-tabellen weggeschreven (max 500 rijen per
tabel, instelbaar via rowLimit in de source-config).
GET/POST naar een externe API. Auth: none, bearer, of
api_key (in header óf query-param). Response-type (JSON/XML/HTML) bepaalt de
extractie.
Wiki-tekst die het portal zelf meestuurt. Geen fetch, geen chunks — de volledige inhoud gaat als always-on context mee bij élke chatvraag, ongeacht relevantie.
04 — Chat & RAG
Een vraag wordt pas beantwoord als er ook echt iets te citeren valt.
Vraag embedden
Het laatste user-bericht wordt met hetzelfde lokale model omgezet naar een vector.
Top-k ophalen
Cosine-similarity search in pgvector (top_k, standaard 6) — plus, indien
aanwezig, de volledige markdown-wiki als vaste context.
Zelfvertrouwen checken
Geen wiki én te weinig chunks boven RAG_MIN_SCORE (standaard 0.72,
RAG_MIN_HITS keer)? Dan gaat het antwoord niet naar het taalmodel, maar komt
direct de fallback_answer terug — met fallback_used: true en een
lege citations-array.
System-prompt samenstellen
Bot-naam/beschrijving + wiki-context + opgehaalde chunks, gevolgd door de
system-berichten die het portal meestuurt (system_instructions,
antwoordlengte) — die krijgen zo effectief het laatste woord.
Groq aanroepen
Model llama-3.3-70b-versatile, non-stream of als SSE
(event:delta / citation / done /
error).
Citaten teruggeven
Per citatie: source_id, label, snippet,
score, type: "index", optioneel url/page.
Geen inline [#1]-markers in de tekst zelf.
05 — Deployments & logs
Elke publish is te volgen als een reeks statussen, niet als een zwarte doos.
Een deployment gaat door queued →
running → done (of
failed). Per bron zie je dezelfde vijf pipeline-stappen
afzonderlijk terug, plus de gezamenlijke healthcheck. Logs zijn op te vragen als
platte JSON (met since/level) of als live SSE-stream tot de
deployment eindigt.
06 — Endpoints
De volledige interface van de bot-server.
| Methode | Pad | Beschrijving |
|---|---|---|
| GET | /v1/bots | Alle bots + status en source-stats |
| POST | /v1/bots | Bot publiceren/updaten — start async ingest |
| GET | /v1/bots/:id | Status en source-stats van één bot |
| POST | /v1/bots/:id/deactivate | Bot uitzetten, data blijft staan |
| DELETE | /v1/bots/:id | Bot en alle data verwijderen |
| GET | /v1/bots/:id/deployments/:dep_id | Deployment-status + stappen |
| GET | /v1/bots/:id/deployments/:dep_id/logs | Logs — JSON of SSE live-tail |
| POST | /v1/bots/:id/chat | RAG-chat, optioneel als SSE-stream |
| GET | /healthz | Liveness |
| GET | /readyz | Readiness — db + redis + llm |
07 — Nieuw in deze versie
Wat de bot-server sinds kort erbij kan.
Betrouwbaar overslaan
null forceert nu altijd een volledige reindex, in plaats van stil te vertrouwen op een zelfberekende hash.
HTML-snapshots
Citaties linken naar de echte origin_url, ook als het portal een snapshot liet ophalen.
Wiki-bronnen
Always-on context die bij elke vraag meegaat, los van de vector-search.
Auth + content-types
Bearer- en API-key-auth (header of query), plus JSON/XML/HTML-detectie op de response.
Eerlijk "ik weet het niet"
Onder de relevantie-drempel krijgt de gebruiker een fallback_answer in plaats van een verzonnen antwoord.
Type-veld
Elke citatie draagt nu type: "index", klaar voor toekomstige live_query-resultaten.