Sprint 2.1 — Database Migratie: ChromaDB → Weaviate¶
Versie: 1.0 | Datum: 15 maart 2026 | Auteur: Claude (projectleider) | Akkoord: Niels (architect)
Samenvatting¶
Migratie van ChromaDB (embedded, in-process) naar Weaviate (standalone, Docker) als primaire vector store voor het Buurts Ecosysteem. Doel: schaalbare basis voor meerdere Kenniswerkplaatsen (KWP's) vóór pilotstart.
Kernbeslissing: Eén database (Weaviate), geen dual-DB. ArangoDB wordt niet geïntroduceerd — de BNS Causal Engine (sidecar) krijgt eigen lichtgewicht opslag in BNS Sprint 0.
Motivatie¶
Waarom nu migreren?¶
- Schaalbaarheid vóór pilot. Na succesvolle pilot worden nieuwe KWP's (GGZ, LVB, Jeugd) snel ingericht. ChromaDB is embedded/single-process — geen concurrent writes, geen multi-tenancy.
- Operationele scheiding. Weaviate draait als standalone service: meerdere FastAPI workers kunnen er tegelijk tegenaan. Essentieel bij meerdere KWP's.
- Zone-isolatie versterken. Weaviate's native multi-tenancy biedt betere RED/YELLOW/GREEN isolatie dan fysiek gescheiden ChromaDB directories.
- Interactie-opslag. Gebruikersinteracties (queries + responses) worden een aparte collection in dezelfde Weaviate-instantie. Geen tweede database nodig.
Waarom géén ArangoDB?¶
- BNS Causal Engine is een sidecar die gescheiden draait (Phantom Mode) totdat wiskundige betrouwbaarheid bewezen is.
pgmpywerkt met in-memory NetworkX DAGs + CPT-tabellen — geen graph database nodig.- ArangoDB's vector search is jong en scoort lager op recall dan gespecialiseerde vector stores.
- Twee databases = dubbele operationele overhead voor een pilot-team.
Waarom gién embedding model switch?¶
Het huidige model paraphrase-multilingual-MiniLM-L12-v2 is bewust gekozen voor Nederlandse tekst. Grok's suggestie all-MiniLM-L6-v2 (384 dim) is Engels-geoptimaliseerd — een stap achteruit voor een Nederlandstalige zorgtoepassing.
Architectuurontwerp¶
Huidige architectuur (ChromaDB)¶
FastAPI → HubOrchestrator → ScoutAgent → VectorStore (ChromaDB in-process)
└─ ZonedVectorStore
├─ buurts_red (ChromaDB dir)
├─ buurts_yellow (ChromaDB dir)
└─ buurts_green (ChromaDB dir)
Doelarchitectuur (Weaviate)¶
FastAPI → HubOrchestrator → ScoutAgent → VectorStore (Weaviate HTTP client)
└─ ZonedVectorStore
├─ BuurtsRed (Weaviate collection)
├─ BuurtsYellow (Weaviate collection)
└─ BuurtsGreen (Weaviate collection)
└─ InteractionStore
└─ BuurtsInteraction (Weaviate collection)
Docker: weaviate:1.27.6 (poort 8080)
Ontwerpprincipe: Interface blijft, implementatie wisselt¶
De ZonedVectorStore en VectorStore klassen in rag/vector_store.py behouden hun publieke interface:
add_chunk(chunk: DocumentChunk) → stradd_chunks(chunks: List[DocumentChunk]) → List[str]query(request: RetrievalRequest) → RetrievalResponsecount(zone?) → intcount_by_zone() → Dict[str, int]reset(zone?) → None
Alles wat tegen deze interface praat (ScoutAgent, SharePointIngestPipeline, tests) hoeft niet te veranderen. Alleen de interne implementatie schakelt van ChromaDB naar Weaviate.
Fasering¶
Fase 1: Infra + Weaviate Docker (dag 1)¶
Doel: Weaviate draait lokaal, schema's aangemaakt.
Taken:
- docker-compose.yml uitbreiden met Weaviate service (1.27.6)
weaviate-client>=4.9.0toevoegen aan requirements.txt- Config uitbreiden:
WEAVIATE_HOST,WEAVIATE_PORT,VECTOR_BACKEND("chromadb" | "weaviate") - Health check endpoint:
GET /health/weaviate - 4 Weaviate collections aanmaken:
BuurtsRed,BuurtsYellow,BuurtsGreen,BuurtsInteraction - Schema per collection met UDS V2 properties (domain_id, knowledge_domain, zone, ldf_level, etc.)
Oplevert: docker compose up weaviate werkt, collections bestaan.
Fase 2: WeaviateVectorStore implementatie (dag 2-3)¶
Doel: Drop-in vervanging voor ChromaDB backend achter bestaande interface.
Taken:
- Nieuwe klasse
WeaviateZonedVectorStoreinrag/vector_store.py(of nieuw bestandrag/weaviate_store.py) - Implementeert exact dezelfde interface als
ZonedVectorStore - Embedding:
paraphrase-multilingual-MiniLM-L12-v2behouden (Weaviatenonevectorizer + client-side embeddings via sentence-transformers) _serialize/_deserializeaanpassen voor Weaviate property-formaat- Factory functie:
get_vector_store(backend: str)→ retourneert ChromaDB of Weaviate variant InteractionStoreals aparte klasse (hergebruik Copilot PR #20 als basis)- Config:
VECTOR_BACKENDswitch inconfig.py
Oplevert: ZonedVectorStore interface werkt met Weaviate backend.
Fase 3: Integratie + migratiescript (dag 4)¶
Doel: Bestaande pipeline schakelt over naar Weaviate.
Taken:
agents/scout.py→ gebruiktget_vector_store()factory i.p.v. directeVectorStoreimportsharepoint/ingest_pipeline.py→ idemmain.py→ DI via factory- Migratiescript
scripts/migrate_chromadb_to_weaviate.py: leest alle ChromaDB collections, schrijft naar Weaviate - Backwards-compat:
VECTOR_BACKEND=chromadbblijft werken (geen breaking change)
Oplevert: volledige pipeline draait op Weaviate met één config-switch.
Fase 4: Tests + CI (dag 5)¶
Doel: Alle tests groen, CI aangepast.
Taken:
- Nieuwe testsuite
tests/test_sprint_2_1.pyvoor Weaviate-specifieke functionaliteit - Bestaande tests draaien ongewijzigd (interface is gelijk) — ChromaDB EphemeralClient als test-backend
- Optionele integratietests met Weaviate Docker (CI:
services: weaviate) - Bandit scan op nieuwe code
- Ruff lint check
- PR #20 branch opruimen (functionaliteit is geïntegreerd)
Oplevert: 321+ tests groen, CI pipeline aangepast.
Impact-analyse¶
Bestanden die veranderen (code)¶
| Bestand | Wijziging | Risico |
|---|---|---|
rag/vector_store.py |
Nieuwe WeaviateZonedVectorStore klasse + factory |
Hoog — kern van de migratie |
config.py |
Weaviate settings toevoegen | Laag |
docker-compose.yml |
Weaviate service toevoegen | Laag |
requirements.txt |
weaviate-client>=4.9.0 toevoegen |
Laag |
agents/scout.py |
Factory i.p.v. directe import | Medium — type hint aanpassen |
sharepoint/ingest_pipeline.py |
Factory i.p.v. directe import | Medium |
main.py |
DI via factory | Medium — main.py is momenteel kapot (Copilot) |
scripts/migrate_chromadb_to_weaviate.py |
Nieuw bestand | Laag |
Bestanden die NIET veranderen¶
| Bestand | Reden |
|---|---|
src/domain/entities.py |
UDSMetadata, DataZone, enums — ongewijzigd |
agents/hub.py |
Praat tegen ScoutAgent interface — ongewijzigd |
agents/curator.py |
Geen vector store dependency |
agents/synthesizer.py |
Geen vector store dependency |
safety/policy.py |
Zone-logica ongewijzigd |
mcp_server/server.py |
Praat tegen FastAPI endpoints |
rag/chunker.py |
Onafhankelijk van storage backend |
Test-impact¶
| Testsuite | Impact | Actie |
|---|---|---|
test_sprint_a.py (39 tests) |
ZonedVectorStore tests — draaien op ChromaDB EphemeralClient | Geen wijziging nodig — testen interface |
test_sprint5.py t/m test_sprint9.py |
VectorStore tests — idem | Geen wijziging nodig |
test_sprint_b.py (40 tests) |
SharePoint + ZonedVectorStore | Geen wijziging nodig |
test_rag.py, test_main.py |
Basis RAG + API tests | Geen wijziging nodig |
Nieuw: test_sprint_2_1.py |
Weaviate-specifieke tests | Nieuw te schrijven |
Cruciale garantie: Bestaande 321 tests worden NIET aangepast. Ze blijven draaien op ChromaDB EphemeralClient (in-memory) als test-backend. Nieuwe Weaviate-tests komen erbij.
Risico's en mitigatie¶
| Risico | Impact | Kans | Mitigatie |
|---|---|---|---|
| Weaviate Docker niet beschikbaar in CI | CI breekt | Laag | GitHub Actions services: block + fallback naar ChromaDB |
| Embedding mismatch ChromaDB ↔ Weaviate | Query recall daalt | Medium | Zelfde model behouden, migratiescript valideert recall |
| main.py is kapot (Copilot) | Integratie geblokkeerd | Hoog | main.py eerst repareren (pre-sprint) |
| Performance regressie (netwerk-hop) | Latency stijgt | Laag | Weaviate draait lokaal, benchmarks in testsuite |
| Copilot branches conflicteren | Merge issues | Medium | Alle Copilot branches evalueren en opruimen vóór start |
Pre-condities (vóór sprint start)¶
- main.py repareren — huidige staat is kapot door Copilot wijzigingen
- Copilot branches evalueren — welke mergen, welke sluiten
- Open GitHub Actions fixen — CI moet groen zijn vóór nieuwe sprint
- Akkoord Niels op dit sprintplan
Definition of Done¶
- [ ] Weaviate 1.27.6 draait via
docker compose up - [ ]
WeaviateZonedVectorStoreimplementeert exact dezelfde interface alsZonedVectorStore - [ ] Zone-isolatie (RED/YELLOW/GREEN) werkt via Weaviate collections
- [ ] Interactie-opslag werkt in aparte Weaviate collection
- [ ] Embedding model
paraphrase-multilingual-MiniLM-L12-v2behouden - [ ] Config switch
VECTOR_BACKEND= "chromadb" (default) | "weaviate" - [ ] Migratiescript
migrate_chromadb_to_weaviate.pybeschikbaar - [ ] Alle 321+ bestaande tests groen (ongewijzigd, op ChromaDB)
- [ ] Nieuwe tests voor Weaviate-specifieke functionaliteit
- [ ] Bandit security scan: geen medium/high findings
- [ ] Ruff lint: geen errors
- [ ] PR naar main met volledige CI groen
- [ ]
main.pyis functioneel (pre-conditie opgelost)
Relatie tot BNS Roadmap¶
Sprint 2.1 bereidt de data-laag voor op schaalbaarheid. De BNS Causal Engine (Sprint 0, Q2 2026) blijft een gescheiden sidecar:
RAG Pipeline (Sprint 2.1) BNS Sidecar (Sprint 0)
┌─────────────────────┐ ┌─────────────────────┐
│ Weaviate │ │ pgmpy + NetworkX │
│ ├─ BuurtsGreen │ │ ├─ DAG (in-memory) │
│ ├─ BuurtsYellow │ │ ├─ CPT tabellen │
│ ├─ BuurtsRed │ │ └─ /causal/infer │
│ └─ BuurtsInteraction│ │ │
└─────────┬───────────┘ └──────────┬──────────┘
│ │
└──── Koppeling pas in BNS Sprint 2 (Q4 2026) ────┘
via LDF-filter + VERA
De twee systemen delen geen database. Pas in BNS Sprint 2 worden outputs gecombineerd via het LDF-filter, en alleen na Go/No-Go beslissing.
Openstaande beslissingen¶
| # | Beslissing | Eigenaar | Blokkeert |
|---|---|---|---|
| 6 | Weaviate multi-tenancy per KWP of collections per zone? | Niels | Fase 2 |
| 7 | Copilot branches: welke sluiten, welke mergen? | Niels | Pre-conditie |
| 8 | main.py: herstellen vanuit git history of herschrijven? | Claude | Pre-conditie |