AI-Strategie Analyse & Integratie met Buurts Ecosysteem¶
Datum: 2026-03-15 Bronnen: "LLM Mechanics and Implementation Strategies" (3 YouTube-analyses) + "Beyond Vibe Coding: Engineering Through Interactive Intelligence" (Jeremy Howard interview) + "Vector Search with LLMs" (Grok-analyse, Computerphile) Doel: Vertaal inzichten naar concrete verbeteringen voor BORIS/Buurts Ecosysteem
1. Key Insights uit de Bronnen¶
Bron 1: LLM Mechanics — Drie Video-analyses¶
Categorie: Tech + Ethics + Strategy
De drie geanalyseerde bronnen (Palisade Research, Theos Theory, Computerphile) bieden samen een genuanceerd beeld van wat LLMs zijn, waar ze falen, en hoe RAG dat kan compenseren.
Kernpunten:
-
Scaling Laws & Task Length: De autonome taakduur van LLMs verdubbelt elke 7 maanden. Claude 4.5 zat op 4+ uur. Dit maakt het realistisch om grotere herstructureringstaken als één opdracht te formuleren, maar vereist tussentijdse verificatie.
-
Jagged Intelligence: LLMs presteren inconsistent — ze lossen olympiade-wiskunde op maar falen bij simpele vermenigvuldigingen. De oorzaak is token-patroonherkenning vs. formele logica. Elke numerieke of telbare output van een agent moet deterministisch worden geverifieerd.
-
Rationalisatie ≠ Redenering: Chain-of-Thought (CoT) is vaak post-hoc rationalisatie, niet werkelijke redenering. Het model genereert eerst een antwoord en construeert daarna een plausibele uitleg. Dit betekent dat "aha-momenten" in reasoning traces geen betrouwbaar signaal zijn.
-
Model Collapse: Training op AI-gegenereerde data leidt tot informatieverlies in de staarten van de distributie. Dit is direct relevant voor onze documentatiestructuur: als agents documenten herschrijven op basis van eerder door AI geschreven tekst, degenereert de kwaliteit progressief.
-
RAG als Oplossing: Vector search met cosine similarity is robuust (spelfouten, meertalig) en reduceert hallucinatie door de agent te beperken tot verstrekte context. Chunking met overlap (800 tokens, 10% overlap) voorkomt dat feiten worden doorgesneden.
Bron 2: Jeremy Howard — Beyond Vibe Coding¶
Categorie: Strategy + Integration + Ethics
Jeremy Howard's kritiek op "vibe coding" is fundamenteel: AI-coding via een terminal is een stochastisch proces dat de illusie van controle wekt maar "understanding debt" opbouwt.
Kernpunten:
-
Slot Machine Coding: De gebruiker trekt aan een hendel met een stochastische uitkomst. Incidentele "wins" maken het verslavend, maar er bouwt zich technische schuld op als niemand de geproduceerde code begrijpt.
-
Interpolatie vs. Extrapolatie: AI is uitstekend in stijltransfer en combinatorische creativiteit (interpolatie), maar faalt bij het ontwerpen van nieuwe abstractiehiërarchieën (extrapolatie). Dit is cruciaal: BORIS's agentarchitectuur is een nieuw ontwerp, geen remix van bestaande GitHub-code.
-
"Reality Pushes Back": Engineering gebeurt alleen wanneer er frictie is — tests die falen, data die niet klopt, stakeholders die weerstand bieden. Zonder frictie leert niemand iets en erodeert organisatiekennis.
-
Interactieve Loops: Howard pleit voor stateful omgevingen (Jupyter-stijl) waar mens en AI objecten in real-time manipuleren. De huidige CLI-aanpak is volgens hem "inhumaan" omdat het de mens uit het exploratieve proces verwijdert.
-
Literate Programming: SOP's als "living documents" die niet alleen beschrijven maar ook de code bevatten om de taak uit te voeren. NBDEV-filosofie.
Bron 3: Grok-analyse — Vector Search & RAG-architectuur¶
Categorie: Tech + Integration
Op basis van de Computerphile video over vector search stelt Grok dat het systeem "onvoldoende ingericht" is. Dit was op het moment van schrijven deels correct. De huidige status na Sprint 2.1:
- Chunking & overlap: opgelost — SmartChunker doet 400-woord chunks met 10% overlap, semantische grenzen gerespecteerd.
- Zone-isolatie als pre-filter: sterker opgelost dan Grok voorstelt — ZonedVectorStore scheidt fysiek op database-niveau (niet alleen mappenstructuur).
- Metadata-verrijkte retrieval: opgelost — UDSMetadata V2 met 6 filterbare velden.
- "Weiger als geen context": deels open — Curator verwerpt lage-similarity chunks, maar er is geen hard gate op de Synthesizer die generatie blokkeert bij nul goedgekeurde chunks.
- Tegenstrijdigheidsdetectie: open — geen mechanisme dat semantisch overlappende maar inhoudelijk conflicterende chunks detecteert.
- "Truth" prioritering: open —
docs/truth/is aangelegd maar chunks daarin worden niet preferent opgehaald.
2. Alignment met Buurts Ecosysteem: Gaps & Opportunities¶
Wat BORIS al goed doet¶
| Inzicht uit bronnen | Huidige implementatie | Status |
|---|---|---|
| RAG voor contextbeheer | ZonedVectorStore (3 zones), SmartChunker met overlap | Solide |
| Safety zones | RED/YELLOW/GREEN isolatie, HITL verplicht bij YELLOW | Solide |
| Content filtering | Block list + green zone allow list in safety/policy.py |
Basisniveau |
| Stakeholder-specifieke output | HERALD met 9 doelgroepen, C1-C5, DES 0-20 | Net geïntegreerd |
| Deterministische CI | Ruff + Bandit + pytest + pip-audit in CI pipeline | Werkend |
| Configuratie-scheiding | Pydantic BaseSettings, .env, YAML configs | Goed |
Gaps geïdentificeerd¶
| # | Gap | Bron | Impact | Huidige staat |
|---|---|---|---|---|
| G1 | Geen output-validatieloop | Jagged Intelligence, Howard | HOOG | Curator checkt input-chunks, maar er is geen deterministische validatie van gegenereerde output (alleen HERALD's interne B1-check) |
| G2 | Model Collapse risico in docs | Model Collapse | MIDDEL | Geen mechanisme om te garanderen dat agents schrijven op basis van mens-geschreven bronnen i.p.v. eerder AI-gegenereerde samenvattingen |
| G3 | Geen "Reality Pushes Back" loop | Howard | HOOG | Geen mechanisme om agent-output te testen tegen de werkelijkheid (bijv. feitelijke claims checken tegen vectorstore) |
| G4 | CoT-vertrouwen zonder verificatie | Rationalisatie vs. Redenering | MIDDEL | OllamaSynthesizer stuurt antwoord terug zonder reasoning-trace validatie |
| G5 | Geen provenance tracking | Model Collapse, RAG | MIDDEL | DocumentChunk bevat similarity_score maar geen generation_source (mens vs. AI) |
| G6 | HERALD quality checks zijn soft | Jagged Intelligence | MIDDEL | B1-check is heuristisch (zinslengte/woordlengte), niet gevalideerd tegen gestandaardiseerde readability metrics |
| G7 | Geen interactieve feedback loop | Howard, Interactieve Loops | LAAG | Systeem is request/response, geen iteratieve verfijning met stakeholder feedback |
| G8 | Living Documents ontbreken | Howard, NBDEV | LAAG | SOP's zijn statische Markdown, geen executable documenten |
| G9 | Geen hard "no context, no answer" gate | Grok-analyse, RAG | HOOG | Curator verwerpt chunks, maar Synthesizer kan nog steeds genereren uit trainingsdata bij 0 goedgekeurde chunks |
| G10 | Geen Source Priority Boost voor docs/truth/ | Grok-analyse | MIDDEL | docs/truth/ bestaat maar chunks daarin worden niet preferent opgehaald boven oudere content |
| G11 | Geen Contradiction Detector | Grok-analyse | MIDDEL | Oude en nieuwe roadmaps kunnen semantisch dicht bij elkaar liggen zonder dat conflicterende claims worden gesignaleerd |
3. Integratie-aanbevelingen¶
Prioriteit 1: HIGH IMPACT, LOW EFFORT — Sprint 2.x fit¶
R1. Output Validator Agent (sluit Gap G1, G3, G4)¶
Wat: Een deterministische validatielaag die na elke Synthesizer-output draait.
Hoe: Nieuwe klasse OutputValidator in agents/output_validator.py.
# agents/output_validator.py
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class ValidationResult:
is_valid: bool
warnings: List[str]
factual_claims_verified: int
factual_claims_total: int
readability_score: Optional[float] # Flesch-Douma voor NL
source_coverage: float # % claims traceable naar chunks
class OutputValidator:
"""Deterministisch valideert agent-output tegen bronchunks."""
def validate(self, output_text: str, source_chunks: list,
audience: str = "algemeen") -> ValidationResult:
warnings = []
# 1. Factual grounding check
claims = self._extract_claims(output_text)
verified = self._verify_against_chunks(claims, source_chunks)
# 2. Readability (Flesch-Douma voor Nederlands)
readability = self._flesch_douma(output_text)
# 3. Hallucination detection: zoek beweringen niet in chunks
ungrounded = [c for c in claims if c not in verified]
if ungrounded:
warnings.append(f"HALLUCINATION_RISK: {len(ungrounded)} claims niet traceerbaar naar bronchunks")
# 4. Lengte-check per audience
# 5. Verboden termen check (uit config)
return ValidationResult(
is_valid=len(ungrounded) == 0,
warnings=warnings,
factual_claims_verified=len(verified),
factual_claims_total=len(claims),
readability_score=readability,
source_coverage=len(verified) / max(len(claims), 1)
)
Integratie in pipeline:
# In hub.py, na synthesizer
result = await self.synthesizer.synthesize(query, approved_chunks)
validation = self.output_validator.validate(
result.answer, approved_chunks, audience=request.audience
)
if not validation.is_valid:
result.warnings.extend(validation.warnings)
result.requires_hitl = True
Effort: Medium (2-3 dagen) Sprint fit: Sprint 2.2 of 2.3
R2. Provenance Tagging (sluit Gap G2, G5)¶
Wat: Voeg generation_source veld toe aan UDSMetadata om mens-geschreven vs. AI-gegenereerde content te onderscheiden.
Hoe: Extend UDSMetadata V2.
# In src/domain/entities.py
class GenerationSource(str, Enum):
HUMAN = "human" # Mens-geschreven origineel
AI_GENERATED = "ai_generated" # Door agent gegenereerd
AI_REVIEWED = "ai_reviewed" # AI-gegenereerd, mens-gereviewd
HYBRID = "hybrid" # Samenwerking mens + AI
# In UDSMetadata
generation_source: GenerationSource = GenerationSource.HUMAN
generation_model: Optional[str] = None # bijv. "llama3.2" of "herald-v1"
original_source_ids: List[str] = [] # chunk_ids van bronmateriaal
Anti-collapse regel: Agents krijgen in hun system prompt:
"Wanneer je schrijft, gebruik ALLEEN chunks met
generation_source=HUMANofgeneration_source=AI_REVIEWEDals primaire bron. Gebruik NOOITAI_GENERATEDchunks als enige bron voor nieuwe content."
Effort: Low (halve dag entity-wijziging + chunker-aanpassing) Sprint fit: Sprint 2.2
R3. Flesch-Douma Readability voor Nederlands (sluit Gap G6)¶
Wat: Vervang HERALD's heuristische B1-check door de gestandaardiseerde Flesch-Douma formule.
Hoe: Utility-functie in utils/readability.py.
# utils/readability.py
import re
def flesch_douma(text: str) -> float:
"""
Flesch-Douma leesbaarheidsscore voor Nederlands.
206.835 - 0.93 * (woorden/zinnen) - 77 * (lettergrepen/woorden)
Interpretatie:
90-100: Zeer makkelijk (groep 5)
60-70: Standaard (B1-niveau)
30-50: Moeilijk (vakpublicatie)
0-30: Zeer moeilijk (wetenschappelijk)
"""
sentences = [s.strip() for s in re.split(r'[.!?]+', text) if s.strip()]
words = text.split()
syllables = sum(_count_dutch_syllables(w) for w in words)
if not sentences or not words:
return 0.0
asl = len(words) / len(sentences) # avg sentence length
asw = syllables / len(words) # avg syllables per word
return 206.835 - (0.93 * asl) - (77.0 * asw)
def _count_dutch_syllables(word: str) -> int:
"""Heuristiek voor Nederlandse lettergrepen."""
word = word.lower().strip(".,!?;:'\"")
vowels = "aeiouyèéêëïîôöüû"
count = 0
prev_vowel = False
for char in word:
is_vowel = char in vowels
if is_vowel and not prev_vowel:
count += 1
prev_vowel = is_vowel
return max(count, 1)
def readability_level(score: float) -> str:
"""Vertaal score naar taalniveau."""
if score >= 80: return "A2"
if score >= 60: return "B1"
if score >= 40: return "B2"
if score >= 20: return "C1"
return "C2"
Integratie in HERALD:
# In herald_synthesizer.py _run_kwaliteitscheck()
from utils.readability import flesch_douma, readability_level
score = flesch_douma(document_text)
level = readability_level(score)
if comm_niveau == "C5" and score < 60:
warnings.append(f"READABILITY: score {score:.0f} ({level}), verwacht B1+ (≥60)")
Effort: Low (1 dag) Sprint fit: Sprint 2.2
Prioriteit 2: HIGH IMPACT, MEDIUM EFFORT¶
R4. Grounded Generation Protocol (sluit Gap G3)¶
Wat: Dwing agents om bij elke claim een [bron: chunk_id] referentie te geven, en valideer die referenties automatisch.
Hoe: Aanpassing in OllamaSynthesizer system prompt + post-processing.
# System prompt toevoeging voor OllamaSynthesizer
GROUNDING_INSTRUCTION = """
REGEL: Elke feitelijke bewering MOET worden gevolgd door een bronverwijzing
in het formaat [bron: CHUNK_ID]. Gebruik ALLEEN informatie uit de aangeleverde
chunks. Als je een bewering niet kunt onderbouwen met een chunk, schrijf dan:
"[bron: niet beschikbaar — HITL vereist]".
"""
# Post-processing in output_validator.py
def _verify_source_references(self, text: str, chunks: list) -> list:
"""Check of alle [bron: X] referenties daadwerkelijk bestaan."""
import re
refs = re.findall(r'\[bron:\s*([^\]]+)\]', text)
chunk_ids = {c.metadata.chunk_id for c in chunks}
invalid = [r for r in refs if r not in chunk_ids and "niet beschikbaar" not in r]
return invalid
Effort: Medium (2 dagen: prompt engineering + validator + tests) Sprint fit: Sprint 2.3
R5. Anti-Autopilot Guardrails (sluit Gap G1, Howard's "small steps")¶
Wat: Beperk de maximale output-lengte per agent-call en dwing stapsgewijze bevestiging af voor grote taken. Hoe: Configureerbaar per agent in config.
# Toe te voegen aan herald_config.yml of een nieuw agents_config.yml
guardrails:
max_output_tokens: 2000 # Per synthesize() call
max_chunks_per_query: 10 # Voorkom context overload
require_hitl_above_tokens: 1500 # Automatisch HITL als output lang is
step_verification: true # Toon tussenresultaat voor bevestiging
Effort: Medium (1-2 dagen) Sprint fit: Sprint 2.3
Prioriteit 3: MEDIUM IMPACT, HIGH EFFORT — Later plannen¶
R6. Interactive Feedback Loop (sluit Gap G7)¶
Wat: Stakeholders kunnen via een simpel formulier (web UI of MS Teams) feedback geven op agent-output, die terugvloeit als metadata in de vectorstore.
Hoe: Nieuw endpoint /feedback + FeedbackStore.
Effort: High (1-2 weken: UI + storage + feedback-loop in agents) Sprint fit: Sprint 3+
R7. Living Documents / NBDEV-stijl SOP's (sluit Gap G8)¶
Wat: SOP's die naast instructies ook uitvoerbare code-blokken bevatten. Hoe: MkDocs + mkdocs-jupyter plugin, of custom Markdown executor.
Effort: High (experimenteel) Sprint fit: Sprint 4+
4. Risico's & Mitigaties¶
| # | Risico | Bron | Mitigatie |
|---|---|---|---|
| R-1 | Model Collapse in documentatie | Bron 1 | Provenance tagging (R2) + anti-collapse regel in agent prompts |
| R-2 | Hallucinatie in stakeholderdocs | Bron 1, Bron 2 | Output Validator (R1) + Grounded Generation (R4) + HITL |
| R-3 | Understanding Debt (team begrijpt code niet meer) | Howard | Code reviews verplicht, agent moet # WHY: comments schrijven, geen grote refactors zonder architectenreview |
| R-4 | Vendor lock-in | Algemeen | Alle agents gebruiken BaseSynthesizer interface, Ollama als LLM-backend (lokaal), Weaviate is OSS. Geen cloud-only dependencies |
| R-5 | Stochastische output bij beslisdocumenten | Howard (slot machine) | Deterministisch post-processing (R1), twee-staps review (agent → HITL), nooit autonome publicatie |
| R-6 | Readability drift (B1 claimen maar feitelijk B2/C1) | Jagged Intelligence | Flesch-Douma scoring (R3) als hard gate, niet als suggestie |
| R-7 | Pilot-readiness | Alle bronnen | Alle agents werken in YELLOW_ZONE (geen autonome RED output), MockSynthesizer als fallback, feature flags per KWP |
Vendor-free architectuur bevestigd¶
De huidige stack is volledig vendor-free: - LLM: Ollama (lokaal, open-source modellen) - Vector DB: Weaviate (OSS, Docker) of ChromaDB (OSS, embedded) - Embeddings: sentence-transformers (lokaal, geen API-calls) - MCP: Open protocol, geen Anthropic lock-in - CI: GitHub Actions (migreerbaar naar GitLab CI/Jenkins)
Geen enkele aanbeveling introduceert een vendor-dependency.
5. Next Steps — YAML Plan¶
# AI Strategy Integration Roadmap
# Gebaseerd op: LLM Mechanics + Beyond Vibe Coding analyse
# Datum: 2026-03-15
sprint_2_2:
naam: "Output Quality & Provenance"
doel: "Deterministische validatie van agent-output + anti-collapse"
taken:
- id: T1
naam: "Provenance tagging in UDSMetadata"
beschrijving: |
Voeg GenerationSource enum + generation_model + original_source_ids
toe aan UDSMetadata. Update SmartChunker om generation_source mee
te geven bij ingest.
bestanden:
- src/domain/entities.py
- rag/chunker.py
- tests/test_entities.py
effort: low
- id: T2
naam: "Flesch-Douma readability module"
beschrijving: |
Nieuwe module utils/readability.py met flesch_douma() en
readability_level(). Integreer in HERALD _run_kwaliteitscheck().
bestanden:
- utils/readability.py (nieuw)
- agents/herald_synthesizer.py (wijzig)
- tests/test_readability.py (nieuw)
effort: low
- id: T3
naam: "OutputValidator basisversie"
beschrijving: |
Nieuwe agent agents/output_validator.py met:
- Factual grounding check (claims vs chunks)
- Readability score (via T2)
- Hallucination risk scoring
- Source coverage percentage
bestanden:
- agents/output_validator.py (nieuw)
- tests/test_output_validator.py (nieuw)
effort: medium
afhankelijk_van: [T1, T2]
sprint_2_3:
naam: "Grounded Generation & Guardrails"
doel: "Agents produceren verifieerbare, brongebonden output"
taken:
- id: T4
naam: "Grounded Generation protocol"
beschrijving: |
System prompt wijziging voor OllamaSynthesizer en HERALD:
verplichte [bron: chunk_id] referenties. Post-processing
validatie van referenties in OutputValidator.
bestanden:
- agents/synthesizer.py (prompt wijziging)
- agents/herald_synthesizer.py (prompt wijziging)
- agents/output_validator.py (extend)
effort: medium
afhankelijk_van: [T3]
- id: T5
naam: "Anti-autopilot guardrails"
beschrijving: |
Configureerbare limieten per agent: max_output_tokens,
max_chunks_per_query, require_hitl_above_tokens.
Implementeer in BaseSynthesizer als optionele post-hook.
bestanden:
- config.py (nieuwe settings)
- agents/synthesizer.py (post-hook)
- agents/herald_config.yml (guardrails sectie)
effort: medium
- id: T6
naam: "Anti-collapse prompt engineering"
beschrijving: |
Update alle agent system prompts met:
- "Gebruik ALLEEN chunks met generation_source=HUMAN of AI_REVIEWED"
- "Vermeld generation_source in output metadata"
- Test met mixed corpus (50% AI-slop, 50% human)
bestanden:
- agents/synthesizer.py
- agents/herald_synthesizer.py
- tests/test_anti_collapse.py (nieuw)
effort: low
afhankelijk_van: [T1]
- id: T7
naam: "Hard 'no context, no answer' gate in hub.py"
beschrijving: |
Als Curator 0 chunks goedkeurt, blokkeert Hub de Synthesizer-call
en retourneert een expliciete "onvoldoende informatie" HubResult.
Voorkomt dat OllamaSynthesizer genereert vanuit trainingsdata.
bestanden:
- agents/hub.py (wijzig: check op len(approved_chunks) == 0)
- tests/test_agents.py (extend: test no-context scenario)
effort: low
sluit_gap: G9
- id: T8
naam: "Source Priority Boost in scout.py"
beschrijving: |
Chunks met bron_type=PROTOCOL of source.startswith("docs/truth/")
krijgen een 1.25x boost op similarity_score vóór re-ranking.
Configureerbaar via TRUTH_BOOST_FACTOR in config.py.
bestanden:
- agents/scout.py (wijzig: _apply_truth_boost() methode)
- config.py (nieuw: TRUTH_BOOST_FACTOR: float = 1.25)
- tests/test_scout_boost.py (nieuw)
effort: low
sluit_gap: G10
- id: T9
naam: "Contradiction Detector in OutputValidator"
beschrijving: |
Vergelijk chunks paarsgewijs op semantische contradictie:
als twee chunks hoge similarity hebben (>0.85) maar conflicterende
datum- of versie-claims bevatten, markeer als CONTRADICTION_RISK.
Heuristisch: datum-extractie + versienummer-vergelijking.
bestanden:
- agents/output_validator.py (extend: _detect_contradictions())
- tests/test_output_validator.py (extend)
effort: medium
sluit_gap: G11
afhankelijk_van: [T3]
sprint_3_plus:
naam: "Feedback & Interactive Loops"
doel: "Stakeholder feedback terugkoppelen naar vectorstore"
taken:
- id: T7
naam: "Feedback endpoint + storage"
effort: high
sprint: "3.0"
- id: T8
naam: "Living Documents (NBDEV-stijl SOP's)"
effort: high
sprint: "4.0"
Samenvatting¶
De twee documenten bevestigen dat de architectuurkeuzes van BORIS (RAG-first, zone-isolatie, HITL, vendor-free) fundamenteel juist zijn. De belangrijkste verbetermogelijkheden zitten niet in nieuwe features maar in kwaliteitsborging van output: deterministisch valideren dat agents niet hallucineren, dat ze schrijven op basis van menselijke bronnen, en dat ze leesbaar schrijven voor de beoogde doelgroep.
De drie quick wins (Provenance Tagging, Flesch-Douma, OutputValidator) kosten samen ~4 werkdagen en sluiten de vier ernstigste gaps. De "Beyond Vibe Coding" inzichten vertalen zich vooral naar werkwijze-principes: kleine stappen, verplichte HITL, en het besef dat agent-output een concept is — nooit een eindproduct.