12 KiB
Bouwplan — AI Cliënt Assistent
Projectnaam: Mini-ECD – AI Cliënt Assistent Versie: v1.0 Datum: 01-12-2025 Auteur: Colin Lit
1. Doel en context
Doel: Uitbreiding van de bestaande AI Documentatie Assistent met cliënt-awareness. Wanneer een behandelaar in een cliëntdossier zit, kan de assistent vragen beantwoorden over díe specifieke cliënt.
Aanleiding: Behandelaren besteden veel tijd aan het navigeren door verschillende schermen om informatie over een cliënt te verzamelen. Bij een overdracht of voorbereiding op een consult moeten zij rapportages doorbladeren, risico-assessments opzoeken, behandeladviezen teruglezen en screeningresultaten checken.
Referenties:
- PRD:
docs/specs/ai-integratie/prd-ai-client-assistent-v1.md - FO:
docs/specs/ai-integratie/fo-ai-client-assistent-v1.md - TO:
docs/specs/ai-integratie/to-ai-client-assistent-v1.md
2. Uitgangspunten
2.1 Technische Stack
- Frontend: Next.js 15 + React + Tailwind CSS
- Backend: Next.js API Routes
- Database: Supabase (PostgreSQL) met RLS
- AI/ML: Claude claude-sonnet-4-20250514 (Anthropic)
- Hosting: Vercel
- Auth: Supabase Auth
- Streaming: Server-Sent Events (SSE)
2.2 Projectkaders
- Bouwtijd: ~8-12 uur (MVP)
- Team: 1 developer
- Data: Bestaande demo-data (21 rapportages, 9 intakes, 5 screenings)
- Doel: Werkende cliënt-aware chat in bestaande docs-chat widget
2.3 Bestaande Infrastructuur (Hergebruik)
| Component | Status | Hergebruik |
|---|---|---|
| DocsChatWidget | ✅ Compleet | ~80% |
| Streaming (SSE) | ✅ Werkt | 100% |
| PatientContext | ✅ Werkt | 100% |
| Rate limiting | ✅ Werkt | 100% |
| Chat suggestions | ✅ Werkt | Uitbreiden |
/api/reports |
✅ Bestaat | Direct bruikbaar |
/api/intakes |
✅ Bestaat | Direct bruikbaar |
/api/screenings |
✅ Bestaat | Direct bruikbaar |
2.4 Programmeer Uitgangspunten
- DRY: Hergebruik bestaande docs-chat componenten
- KISS: Minimale wijzigingen aan bestaande code
- SOC: Nieuwe modules in
lib/docs/voor client-specifieke logica - YAGNI: Alleen MVP features, geen toekomstige uitbreidingen
3. Epics & Stories Overzicht
| Epic ID | Titel | Doel | Status | Stories |
|---|---|---|---|---|
| E1 | Backend Modules | Context loader, detector, prompt builder | ✅ Done | 3 |
| E2 | API Uitbreiding | Chat endpoint uitbreiden met clientId | ✅ Done | 2 |
| E3 | Frontend Uitbreiding | Indicator, suggestions, hook aanpassing | ✅ Done | 3 |
| E4 | Testing & Refinement | Integratie testen, prompt tuning | ✅ Done | 2 |
4. Epics & Stories (Uitwerking)
Epic 1 — Backend Modules
Epic Doel: Nieuwe modules voor cliënt-context laden, vraagtype detectie en prompt building.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|---|---|---|---|---|---|
| E1.S1 | Client Context Loader | Laadt patient + reports + intakes + screenings uit Supabase | ✅ | — | 3 |
| E1.S2 | Question Type Detector | Detecteert 'client' vs 'documentation' vs 'ambiguous' | ✅ | — | 2 |
| E1.S3 | Client Prompt Builder | Bouwt system prompt met cliënt-context | ✅ | E1.S1 | 2 |
Technical Notes:
E1.S1 - Client Context Loader (lib/docs/client-context-loader.ts)
interface ClientContext {
patient: { name: string; birthDate: string; status: string }
reports: Array<{ type: string; content: string; date: string }>
intakes: Array<{ title: string; treatmentAdvice: object; status: string }>
screening: { requestForHelp: string; decision: string } | null
riskAssessments: Array<{ type: string; level: string; rationale: string }>
}
// Directe Supabase queries (niet via HTTP voor performance)
// Parallel laden: Promise.all([reports, intakes, screening, risks])
// Laatste 5 rapportages, 3 intakes, 1 screening
E1.S2 - Question Type Detector (lib/docs/question-type-detector.ts)
const CLIENT_KEYWORDS = [
'rapportage', 'risico', 'behandeladvies', 'screening',
'hulpvraag', 'samenvatting', 'dossier', 'deze cliënt'
]
const DOC_KEYWORDS = [
'hoe', 'waar', 'wat is', 'tutorial', 'handleiding',
'functie', 'knop', 'menu', 'systeem', 'epd'
]
// Return: 'client' | 'documentation' | 'ambiguous'
E1.S3 - Client Prompt Builder (lib/docs/client-prompt-builder.ts)
- Strikte regels: alleen beschikbare data, geen hallucinatie
- Geen medisch advies
- Beknopt en professioneel
- Max 4000 tokens context
Epic 2 — API Uitbreiding
Epic Doel: Bestaande chat endpoint uitbreiden met cliënt-awareness.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|---|---|---|---|---|---|
| E2.S1 | Request schema uitbreiden | Accepteert optioneel clientId parameter |
✅ | E1.S1-S3 | 2 |
| E2.S2 | Routing logica | Bij client-vraag: client prompt, bij doc-vraag: bestaande flow | ✅ | E2.S1 | 3 |
Technical Notes:
E2.S1 - Request Schema (app/api/docs/chat/route.ts)
// Huidige schema uitbreiden:
{
messages: Array<{ role: 'user' | 'assistant', content: string }>,
userMessage: string,
clientId?: string // Nieuw: UUID van actieve patiënt
}
E2.S2 - Routing Logica
// Pseudocode:
const questionType = detectQuestionType(userMessage, !!clientId)
if (questionType === 'client' && clientId) {
const context = await loadClientContext(clientId)
const systemPrompt = buildClientPrompt(context, userMessage)
// Skip ai_events logging (privacy)
} else {
// Bestaande documentatie flow
const categories = detectCategories(userMessage)
const knowledgeSections = await loadKnowledgeSections(categories)
const systemPrompt = buildSystemPrompt(knowledgeSections)
}
Epic 3 — Frontend Uitbreiding
Epic Doel: UI aanpassingen voor cliënt-indicator en dynamische suggestions.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|---|---|---|---|---|---|
| E3.S1 | useDocsChat hook uitbreiden | Stuurt clientId mee, exposed hasPatientContext | ✅ | E2.S2 | 2 |
| E3.S2 | Cliënt Indicator | Header toont "Dossier: [Naam]" wanneer in dossier | ✅ | E3.S1 | 1 |
| E3.S3 | Dynamische Suggestions | Cliënt-suggesties in dossier, doc-suggesties daarbuiten | ✅ | E3.S1 | 2 |
Technical Notes:
E3.S1 - Hook Uitbreiding (components/docs-chat/use-docs-chat.ts)
import { usePatientContext } from '@/app/epd/components/patient-context'
// In hook:
const { patient } = usePatientContext()
// Bij sendMessage:
body: JSON.stringify({
messages: recentMessages,
userMessage,
clientId: patient?.id // Meesturen als patient actief
})
// Exposed voor UI:
return {
...state,
hasPatientContext: !!patient,
patientName: patient?.name?.[0]?.text || null
}
E3.S2 - Cliënt Indicator (components/docs-chat/docs-chat-widget.tsx)
{hasPatientContext && patientName && (
<div className="px-4 py-1 text-xs text-amber-700 bg-amber-50 border-b">
Dossier: {patientName}
</div>
)}
E3.S3 - Dynamische Suggestions (components/docs-chat/chat-suggestions.tsx)
const CLIENT_SUGGESTION_CATEGORIES = [
{
id: 'rapportages',
label: 'Rapportages',
icon: 'FileText',
questions: [
'Geef een samenvatting van de rapportages',
'Wat is er de laatste tijd genoteerd?',
'Zijn er behandeladviezen?',
],
},
{
id: 'intake',
label: 'Intake & Behandeling',
icon: 'Building2',
questions: [
'Wat is het behandeladvies?',
'Op welke afdeling loopt de intake?',
'Is de intake afgerond?',
],
},
{
id: 'screening',
label: 'Screening',
icon: 'ClipboardList',
questions: [
'Wat was de hulpvraag?',
'Wat is de screeningbeslissing?',
'Is de cliënt geschikt bevonden?',
],
},
]
// Props toevoegen:
interface ChatSuggestionsProps {
onSelect: (question: string) => void
disabled?: boolean
mode?: 'client' | 'documentation' // Nieuw
}
Epic 4 — Testing & Refinement
Epic Doel: Integratie testen en prompt verfijning.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|---|---|---|---|---|---|
| E4.S1 | Integratie tests | Happy flows werken voor alle 3 categorieën | ✅ | E3.S3 | 2 |
| E4.S2 | Prompt tuning | AI geeft accurate, beknopte antwoorden | ✅ | E4.S1 | 2 |
Test Scenarios:
- Open dossier -> chat toont indicator + cliënt-suggesties
- Vraag "Samenvatting rapportages" -> krijg rapportage overzicht
- Vraag "Wat is het behandeladvies?" -> krijg intake info
- Vraag "Hoe maak ik een intake?" -> krijg documentatie antwoord
- Buiten dossier -> chat toont doc-suggesties
5. Kwaliteit & Testplan
Acceptatiecriteria (uit PRD)
| Criterium | Target |
|---|---|
| Cliënt correct herkend | 100% (via URL/PatientContext) |
| Vraagtype correct | >90% correcte classificatie |
| Eerste token | < 3 seconden |
| Context laden | < 200ms |
| Data-integriteit | Alleen data van actieve cliënt |
Test Checklist
- Cliënt-indicator toont correcte naam in dossier
- Cliënt-suggesties verschijnen in dossier
- Doc-suggesties verschijnen buiten dossier
- Vraag over rapportages geeft correcte samenvatting
- Vraag over risico's toont "geen data" (0 rows)
- Doc-vraag vanuit dossier werkt normaal
- Rate limiting werkt nog steeds
- Streaming werkt nog steeds
6. Bestanden Overzicht
Te wijzigen
| Bestand | Wijziging |
|---|---|
app/api/docs/chat/route.ts |
clientId parameter, routing logica |
components/docs-chat/use-docs-chat.ts |
PatientContext integratie |
components/docs-chat/chat-suggestions.tsx |
mode prop, client categories |
components/docs-chat/docs-chat-widget.tsx |
Cliënt indicator |
Nieuw aan te maken
| Bestand | Doel |
|---|---|
lib/docs/client-context-loader.ts |
Laadt cliëntdata uit Supabase |
lib/docs/question-type-detector.ts |
Detecteert vraagtype |
lib/docs/client-prompt-builder.ts |
Bouwt AI prompt met context |
Referentie (te lezen)
| Bestand | Waarom |
|---|---|
app/epd/components/patient-context.tsx |
PatientContext API |
lib/docs/prompt-builder.ts |
Bestaande prompt structuur |
lib/docs/knowledge-loader.ts |
Bestaande knowledge loading |
7. Risico's & Mitigatie
| Risico | Kans | Impact | Mitigatie |
|---|---|---|---|
| AI hallucineert informatie | Middel | Hoog | Strikte prompt: "alleen beschikbare data" |
| Geen risk_assessments data | Zeker | Laag | "Geen data" response (feature, niet bug) |
| Token overflow | Laag | Middel | Truncatie met limit (4000 tokens) |
| Verkeerde cliëntdata | Laag | Kritiek | clientId uit PatientContext (betrouwbaar) |
| Performance degradatie | Laag | Middel | Parallel queries, geen HTTP overhead |
8. Geschatte Doorlooptijd
| Epic | Schatting |
|---|---|
| E1 - Backend Modules | 3-4 uur |
| E2 - API Uitbreiding | 2-3 uur |
| E3 - Frontend Uitbreiding | 2-3 uur |
| E4 - Testing & Refinement | 1-2 uur |
| Totaal | 8-12 uur |
Versiehistorie
| Versie | Datum | Auteur | Wijziging |
|---|---|---|---|
| v1.0 | 01-12-2025 | Colin Lit | Initiële versie op basis van PRD/FO/TO |
| v1.1 | 02-12-2025 | Colin Lit | E1 (Backend Modules) afgerond, E2 gestart |