Files
triqura-ecd/docs/specs/ai-integratie/bouwplan-ai-client-assistent-v1.md
2025-12-02 13:37:45 +01:00

342 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)
```typescript
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`)
```typescript
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`)
```typescript
// Huidige schema uitbreiden:
{
messages: Array<{ role: 'user' | 'assistant', content: string }>,
userMessage: string,
clientId?: string // Nieuw: UUID van actieve patiënt
}
```
**E2.S2 - Routing Logica**
```typescript
// 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`)
```typescript
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`)
```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`)
```typescript
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:**
1. Open dossier -> chat toont indicator + cliënt-suggesties
2. Vraag "Samenvatting rapportages" -> krijg rapportage overzicht
3. Vraag "Wat is het behandeladvies?" -> krijg intake info
4. Vraag "Hoe maak ik een intake?" -> krijg documentatie antwoord
5. 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 |