chat suggestions, SEo integration, and more
This commit is contained in:
341
docs/specs/ai-integratie/bouwplan-ai-client-assistent-v1.md
Normal file
341
docs/specs/ai-integratie/bouwplan-ai-client-assistent-v1.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# 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 |
|
||||
@@ -1,321 +0,0 @@
|
||||
# Mission Control — Bouwplan AI Documentatie Assistent
|
||||
|
||||
**Projectnaam:** Mini-ECD – AI Documentatie Assistent
|
||||
**Versie:** v1.0
|
||||
**Datum:** 01-12-2025
|
||||
**Auteur:** Colin van der Heijden
|
||||
|
||||
---
|
||||
|
||||
## 1. Doel en context
|
||||
|
||||
**Doel:** Een floating chat widget bouwen die eindgebruikers van het EPD helpt door vragen te beantwoorden op basis van de systeemdocumentatie.
|
||||
|
||||
**Context:** Dit is de eerste AI-integratie in het Mini-ECD prototype. Het dient als fundament voor toekomstige AI features (zoals AI Pre-fill Behandelplan). De widget maakt documentatie direct toegankelijk via een conversatie-interface.
|
||||
|
||||
**Relatie met andere documenten:**
|
||||
- PRD: `prd-ai-docs-assistent-v1.md` — Wat en waarom
|
||||
- FO: `fo-ai-docs-assistent-v1.md` — Hoe het werkt voor gebruikers
|
||||
|
||||
---
|
||||
|
||||
## 2. Uitgangspunten
|
||||
|
||||
### 2.1 Technische Stack
|
||||
|
||||
| Laag | Technologie |
|
||||
|------|-------------|
|
||||
| **Frontend** | Next.js 14.2 + React + Tailwind CSS |
|
||||
| **Backend** | Next.js API Routes (App Router) |
|
||||
| **Database** | Supabase PostgreSQL (alleen voor auth check) |
|
||||
| **AI** | Claude API (claude-sonnet-4-20250514) met streaming |
|
||||
| **Hosting** | Vercel |
|
||||
| **Icons** | Lucide React (Sparkles, X, Send) |
|
||||
|
||||
### 2.2 Projectkaders
|
||||
|
||||
| Aspect | Waarde |
|
||||
|--------|--------|
|
||||
| **Bouwtijd** | 1-2 dagen |
|
||||
| **Team** | 1 developer |
|
||||
| **Data** | Alleen bestaande MDX documentatie |
|
||||
| **Scope** | MVP — chat widget met streaming responses |
|
||||
| **Persistentie** | Sessie-only (geen database opslag) |
|
||||
|
||||
### 2.3 Programmeer Uitgangspunten
|
||||
|
||||
**Code Quality Principles:**
|
||||
|
||||
- **DRY** — Herbruikbare hook voor chat state, centrale prompt configuratie
|
||||
- **KISS** — Eenvoudige fetch naar Claude API, geen SDK overhead
|
||||
- **SOC** — UI componenten gescheiden van API logic en knowledge base
|
||||
- **YAGNI** — Geen RAG, geen database opslag, geen multi-provider support
|
||||
|
||||
**Security:**
|
||||
- API key alleen server-side (Next.js API route)
|
||||
- Widget alleen voor ingelogde gebruikers
|
||||
- Geen logging van conversaties
|
||||
|
||||
---
|
||||
|
||||
## 3. Epics & Stories Overzicht
|
||||
|
||||
| Epic ID | Titel | Doel | Status | Stories |
|
||||
|---------|-------|------|--------|---------|
|
||||
| E0 | Knowledge Base Content | FAQ's en guidelines in markdown | ✅ Done | 2 |
|
||||
| E1 | Knowledge Services | CategoryDetector, KnowledgeLoader, PromptBuilder | ✅ Done | 3 |
|
||||
| E2 | API Endpoint | Streaming Claude integratie | ✅ Done | 1 |
|
||||
| E3 | Chat UI Components | Widget, messages, input | ✅ Done | 4 |
|
||||
| E4 | Integratie & Testing | Widget in EPD, testen | ✅ Done | 2 |
|
||||
|
||||
**Totaal:** 12 stories, ~18 story points
|
||||
|
||||
---
|
||||
|
||||
## 4. Epics & Stories (Uitwerking)
|
||||
|
||||
### Epic 0 — Knowledge Base Content
|
||||
|
||||
**Epic Doel:** Gestructureerde FAQ's en guidelines in markdown bestanden.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||||
|----------|--------------|---------------------|--------|-----|
|
||||
| E0.S1 | FAQ markdown bestanden | 6 FAQ bestanden met Q&A per categorie | ✅ | 2 |
|
||||
| E0.S2 | Guidelines bestanden | 2 guideline bestanden (interface, technisch) | ✅ | 1 |
|
||||
|
||||
**Deliverables:**
|
||||
```
|
||||
lib/docs/knowledge/
|
||||
├── faq_clientbeheer.md # Cliënt aanmaken, zoeken, verwijderen
|
||||
├── faq_intake.md # Intake starten, notities, spraak
|
||||
├── faq_screening.md # Screening resultaten, vragenlijsten
|
||||
├── faq_behandelplan.md # Plan maken, doelen, interventies
|
||||
├── faq_spraak.md # Microfoon, dicteren, transcriptie
|
||||
├── faq_inloggen.md # Login, wachtwoord, rechten
|
||||
├── guidelines_interface.md # UI uitleg, navigatie, menu's
|
||||
└── guidelines_technisch.md # FHIR API, data model (devs)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 1 — Knowledge Services
|
||||
|
||||
**Epic Doel:** Intelligente services voor dynamische knowledge loading.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||||
|----------|--------------|---------------------|--------|-----|
|
||||
| E1.S1 | CategoryDetector | Keyword matching om relevante categorieën te bepalen | ✅ | 2 |
|
||||
| E1.S2 | KnowledgeLoader | Laadt alleen relevante markdown bestanden | ✅ | 2 |
|
||||
| E1.S3 | PromptBuilder | Combineert base prompt + relevante knowledge | ✅ | 2 |
|
||||
|
||||
**Deliverables:**
|
||||
```
|
||||
lib/docs/
|
||||
├── category-detector.ts # Analyseert vraag → categorieën
|
||||
├── knowledge-loader.ts # Laadt relevante knowledge
|
||||
└── prompt-builder.ts # Bouwt geoptimaliseerde prompt
|
||||
```
|
||||
|
||||
**Category Mapping:**
|
||||
```typescript
|
||||
const CATEGORY_KEYWORDS: Record<Category, string[]> = {
|
||||
clientbeheer: ['cliënt', 'patient', 'aanmaken', 'zoeken', 'dossier'],
|
||||
intake: ['intake', 'gesprek', 'notitie', 'verslag'],
|
||||
screening: ['screening', 'vragenlijst', 'score', 'resultaat'],
|
||||
behandelplan: ['behandelplan', 'doel', 'interventie', 'plan'],
|
||||
spraak: ['spraak', 'microfoon', 'dicteren', 'stem', 'transcriptie'],
|
||||
inloggen: ['inloggen', 'wachtwoord', 'login', 'account'],
|
||||
interface: ['menu', 'knop', 'scherm', 'navigatie', 'waar vind'],
|
||||
technisch: ['api', 'fhir', 'endpoint', 'database', 'developer']
|
||||
};
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
```
|
||||
Vraag: "Hoe maak ik een intake aan?"
|
||||
↓
|
||||
CategoryDetector → ['intake']
|
||||
↓
|
||||
KnowledgeLoader → laadt faq_intake.md
|
||||
↓
|
||||
PromptBuilder → base prompt + intake FAQ
|
||||
↓
|
||||
Claude API → streaming response
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 2 — API Endpoint
|
||||
|
||||
**Epic Doel:** Streaming API endpoint met dynamische knowledge.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||||
|----------|--------------|---------------------|--------|-----|
|
||||
| E2.S1 | Streaming endpoint | `POST /api/docs/chat` met dynamic knowledge, SSE stream | ✅ | 3 |
|
||||
|
||||
**Deliverables:**
|
||||
```
|
||||
app/api/docs/chat/
|
||||
route.ts # Streaming API endpoint
|
||||
```
|
||||
|
||||
**API Contract:**
|
||||
```typescript
|
||||
// Request
|
||||
POST /api/docs/chat
|
||||
{
|
||||
messages: Array<{ role: 'user' | 'assistant', content: string }>,
|
||||
userMessage: string
|
||||
}
|
||||
|
||||
// Response: Server-Sent Events stream
|
||||
event: content_block_delta
|
||||
data: {"delta":{"text":"..."}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Epic 3 — Chat UI Components
|
||||
|
||||
**Epic Doel:** Complete chat widget UI volgens FO specificaties.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||||
|----------|--------------|---------------------|--------|-----|
|
||||
| E3.S1 | Chat state hook | `use-docs-chat.ts` met messages, loading, sendMessage, streaming | ✅ | 2 |
|
||||
| E3.S2 | Message list component | `chat-messages.tsx` met styling, auto-scroll, streaming cursor | ✅ | 1 |
|
||||
| E3.S3 | Input component | `chat-input.tsx` met textarea, send, Enter/Shift+Enter | ✅ | 1 |
|
||||
| E3.S4 | Widget container | `docs-chat-widget.tsx` met trigger, panel, header, animaties | ✅ | 2 |
|
||||
|
||||
**Deliverables:**
|
||||
```
|
||||
components/docs-chat/
|
||||
use-docs-chat.ts # Custom hook
|
||||
chat-messages.tsx # Message list
|
||||
chat-input.tsx # Input area
|
||||
docs-chat-widget.tsx # Main container
|
||||
```
|
||||
|
||||
**UI Specs (uit FO):**
|
||||
|
||||
| Element | Specificatie |
|
||||
|---------|--------------|
|
||||
| Trigger button | 56x56px, amber gradient, Sparkles icon, `fixed bottom-6 right-6` |
|
||||
| Panel | 384px breed, max 80vh, slide-in animatie |
|
||||
| User messages | Rechts, `bg-amber-100`, rounded |
|
||||
| Assistant messages | Links, `bg-slate-100`, rounded |
|
||||
| Streaming | Pulserende cursor `▊` |
|
||||
|
||||
---
|
||||
|
||||
### Epic 4 — Integratie & Testing
|
||||
|
||||
**Epic Doel:** Widget geïntegreerd in EPD en getest.
|
||||
|
||||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||||
|----------|--------------|---------------------|--------|-----|
|
||||
| E4.S1 | Widget integratie | `DocsChatWidget` in EPD layout, alleen ingelogde users | ✅ | 1 |
|
||||
| E4.S2 | Smoke tests | Happy flow, error states, category detection werkt | ✅ | 1 |
|
||||
|
||||
**Te wijzigen bestand:**
|
||||
```
|
||||
app/epd/components/epd-layout-client.tsx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Kwaliteit & Testplan
|
||||
|
||||
### Test Types
|
||||
|
||||
| Test Type | Scope | Methode |
|
||||
|-----------|-------|---------|
|
||||
| Unit | Knowledge base loader | Console test |
|
||||
| Integration | API endpoint | curl/Postman |
|
||||
| Smoke | Volledige flow | Manual in browser |
|
||||
|
||||
### Manual Test Checklist
|
||||
|
||||
- [ ] Widget trigger button zichtbaar in EPD
|
||||
- [ ] Klik opent chat panel met animatie
|
||||
- [ ] Welkomstbericht wordt getoond
|
||||
- [ ] Vraag versturen werkt (Enter + button)
|
||||
- [ ] Streaming response verschijnt woord-voor-woord
|
||||
- [ ] Vervolgvraag behoudt context
|
||||
- [ ] X-knop sluit panel
|
||||
- [ ] Conversatie blijft behouden na sluiten/openen
|
||||
- [ ] Error state toont bij API failure
|
||||
- [ ] Widget verdwijnt bij uitloggen
|
||||
|
||||
### Acceptatiecriteria (uit PRD)
|
||||
|
||||
| Criterium | Target |
|
||||
|-----------|--------|
|
||||
| First token | < 2 seconden |
|
||||
| Volledige response | < 30 seconden |
|
||||
| Error rate | < 5% |
|
||||
|
||||
---
|
||||
|
||||
## 6. Demo & Presentatieplan
|
||||
|
||||
**Duur:** 3 minuten
|
||||
**Scenario:**
|
||||
|
||||
1. **Intro** (30s): "Dit is de documentatie assistent"
|
||||
2. **Vraag 1** (45s): "Hoe maak ik een intake aan?" → streaming antwoord
|
||||
3. **Vraag 2** (45s): "En hoe gebruik ik spraakherkenning?" → context behouden
|
||||
4. **Edge case** (30s): "Wat is de beste behandeling?" → "weet ik niet" response
|
||||
5. **Afsluiting** (30s): Widget sluiten, conversatie behouden
|
||||
|
||||
---
|
||||
|
||||
## 7. Risico's & Mitigatie
|
||||
|
||||
| Risico | Kans | Impact | Mitigatie |
|
||||
|--------|------|--------|-----------|
|
||||
| AI hallucineert | Middel | Hoog | Strikte system prompt, FAQ's eerst, "alleen uit docs" regel |
|
||||
| Trage response | Laag | Middel | Streaming UX, timeout na 30s |
|
||||
| Context te groot | Laag | Middel | ~119KB past in context window, monitoring |
|
||||
| API rate limits | Laag | Middel | Sessie-based (geen caching nodig) |
|
||||
|
||||
---
|
||||
|
||||
## 8. Referenties
|
||||
|
||||
### Mission Control Documents
|
||||
|
||||
- **PRD:** `prd-ai-docs-assistent-v1.md`
|
||||
- **FO:** `fo-ai-docs-assistent-v1.md`
|
||||
- **Gerelateerd:** `prd-ai-prefill-behandelplan-v1.md`
|
||||
|
||||
### Bestaande Code Patterns
|
||||
|
||||
| Bestand | Pattern |
|
||||
|---------|---------|
|
||||
| `app/api/reports/classify/route.ts` | Claude API fetch pattern |
|
||||
| `lib/mdx/documentatie.ts` | MDX loading met gray-matter |
|
||||
| `components/ui/ai-button.tsx` | Amber AI styling |
|
||||
|
||||
### Externe Referenties
|
||||
|
||||
- [Claude API Docs](https://docs.anthropic.com)
|
||||
- [Anthropic Streaming](https://docs.anthropic.com/en/api/streaming)
|
||||
|
||||
---
|
||||
|
||||
## 9. Glossary
|
||||
|
||||
| Term | Betekenis |
|
||||
|------|-----------|
|
||||
| SSE | Server-Sent Events (streaming protocol) |
|
||||
| Knowledge Base | Verzameling documentatie voor AI context |
|
||||
| FAQ | Frequently Asked Questions |
|
||||
| Streaming | Real-time response, woord-voor-woord |
|
||||
|
||||
---
|
||||
|
||||
**Versiehistorie:**
|
||||
|
||||
| Versie | Datum | Auteur | Wijziging |
|
||||
|--------|-------|--------|-----------|
|
||||
| v1.0 | 01-12-2025 | Colin van der Heijden | Initiële versie |
|
||||
367
docs/specs/ai-integratie/fo-ai-client-assistent-v1.md
Normal file
367
docs/specs/ai-integratie/fo-ai-client-assistent-v1.md
Normal file
@@ -0,0 +1,367 @@
|
||||
# 🧩 Functioneel Ontwerp (FO) – AI Cliënt Assistent
|
||||
|
||||
**Projectnaam:** Mini-ECD – AI Cliënt Assistent
|
||||
**Versie:** v1.0
|
||||
**Datum:** 01-12-2025
|
||||
**Auteur:** Colin Lit
|
||||
|
||||
---
|
||||
|
||||
## 1. Doel en relatie met het PRD
|
||||
|
||||
**Doel van dit document:**
|
||||
Dit FO beschrijft hoe de AI Cliënt Assistent functioneel werkt vanuit gebruikersperspectief. Het PRD beschrijft *wat* we bouwen (cliënt-aware chat), dit FO laat zien *hoe* de gebruiker dit ervaart.
|
||||
|
||||
**Scope (prototype):**
|
||||
Gebaseerd op de huidige data in het EPD:
|
||||
- **21 rapportages** (16 vrije notities, 5 behandeladviezen)
|
||||
- **9 intakes** (7 Volwassenen, 1 Jeugd)
|
||||
- **5 screenings** (1 geschikt, 1 niet geschikt, 3 open)
|
||||
- **0 risico-assessments** (tabel bestaat, geen data)
|
||||
|
||||
---
|
||||
|
||||
## 2. Overzicht van de onderdelen
|
||||
|
||||
| Onderdeel | Beschrijving | Status |
|
||||
|-----------|--------------|--------|
|
||||
| **Chat Widget** | Bestaande floating widget rechtsonder | Uitbreiden |
|
||||
| **Cliënt Indicator** | Header die toont welke cliënt actief is | Nieuw |
|
||||
| **Cliënt Suggesties** | Voorbeeldvragen over de actieve cliënt | Nieuw |
|
||||
| **Vraagtype Detectie** | Herkent of vraag over cliënt of systeem gaat | Nieuw |
|
||||
|
||||
---
|
||||
|
||||
## 3. User Stories
|
||||
|
||||
| ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit |
|
||||
|----|-----|--------------|------------------|------------|
|
||||
| US-01 | Behandelaar | Samenvatting van rapportages opvragen | Snel overzicht voor consult | Hoog |
|
||||
| US-02 | Behandelaar | Behandeladvies opvragen | Inzicht in geadviseerde zorg | Hoog |
|
||||
| US-03 | Verpleegkundige | Recente notities bekijken | Overdracht voorbereiding | Hoog |
|
||||
| US-04 | Intaker | Hulpvraag en screening status opvragen | Intake afronden | Middel |
|
||||
| US-05 | Behandelaar | Documentatie-vraag stellen vanuit dossier | Hulp bij EPD gebruik | Middel |
|
||||
|
||||
---
|
||||
|
||||
## 4. Functionele werking per onderdeel
|
||||
|
||||
### 4.1 Chat Widget (uitgebreid)
|
||||
|
||||
**Huidige situatie:**
|
||||
- Floating button rechtsonder (amber, sparkles icon)
|
||||
- Beantwoordt alleen documentatie-vragen
|
||||
- Toont 3 categorieën met voorbeeldvragen
|
||||
|
||||
**Nieuwe situatie:**
|
||||
- Detecteert automatisch of gebruiker in cliëntdossier zit
|
||||
- Toont cliënt-indicator in header wanneer in dossier
|
||||
- Schakelt tussen cliënt- en documentatie-suggesties
|
||||
- Beantwoordt vragen over de actieve cliënt
|
||||
|
||||
### 4.2 Cliënt Indicator
|
||||
|
||||
**Locatie:** Header van chat widget, onder "EPD Assistent"
|
||||
|
||||
**Weergave:**
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ ✨ EPD Assistent │
|
||||
│ 📋 Dossier: Jan de Vries │ ← Nieuw: cliënt indicator
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
**Gedrag:**
|
||||
| Context | Indicator |
|
||||
|---------|-----------|
|
||||
| In cliëntdossier | `📋 Dossier: [Cliëntnaam]` |
|
||||
| Buiten dossier | Geen indicator (alleen "EPD Assistent") |
|
||||
|
||||
### 4.3 Cliënt Suggesties
|
||||
|
||||
**Wanneer tonen:** Bij eerste opening chat in cliëntdossier, alleen welkomstbericht zichtbaar
|
||||
|
||||
**Categorieën en vragen (gebaseerd op beschikbare data):**
|
||||
|
||||
| Categorie | Icon | Voorbeeldvragen |
|
||||
|-----------|------|-----------------|
|
||||
| **Rapportages** | 📝 | "Geef een samenvatting van de rapportages", "Wat is er de laatste tijd genoteerd?", "Zijn er behandeladviezen?" |
|
||||
| **Intake & Behandeling** | 🏥 | "Wat is het behandeladvies?", "Op welke afdeling loopt de intake?", "Is de intake afgerond?" |
|
||||
| **Screening** | 📋 | "Wat was de hulpvraag?", "Wat is de screeningbeslissing?", "Is de cliënt geschikt bevonden?" |
|
||||
|
||||
**Interactie:**
|
||||
1. Gebruiker ziet 3 categorieën (knoppen)
|
||||
2. Klik op categorie → toont 3 voorbeeldvragen
|
||||
3. Klik op vraag → vraag wordt direct verstuurd
|
||||
4. "Terug" knop om naar categorieën te gaan
|
||||
|
||||
### 4.4 Vraagtype Detectie
|
||||
|
||||
**Doel:** Bepalen of een vraag over de cliënt of over het systeem gaat
|
||||
|
||||
**Gedrag:**
|
||||
|
||||
| Vraag | Detectie | Actie |
|
||||
|-------|----------|-------|
|
||||
| "Geef een samenvatting van de rapportages" | Cliënt | Beantwoord met cliëntdata |
|
||||
| "Hoe maak ik een intake aan?" | Documentatie | Beantwoord met systeemdocumentatie |
|
||||
| "Wat zijn de risico's?" | Cliënt | Beantwoord met cliëntdata (of "geen data") |
|
||||
| "Hoe werkt de spraakherkenning?" | Documentatie | Beantwoord met systeemdocumentatie |
|
||||
|
||||
**Edge cases:**
|
||||
| Situatie | Gedrag |
|
||||
|----------|--------|
|
||||
| Ambigue vraag in dossier | Default naar documentatie, toon hint |
|
||||
| Cliënt-vraag buiten dossier | "Open eerst een cliëntdossier om vragen te stellen" |
|
||||
| Data ontbreekt | "Er zijn nog geen [rapportages/risico's] voor deze cliënt" |
|
||||
|
||||
---
|
||||
|
||||
## 5. UI-overzicht
|
||||
|
||||
### 5.1 Chat Widget Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ✨ EPD Assistent [X] │ ← Header
|
||||
│ 📋 Dossier: Jan de Vries │ ← Cliënt indicator (nieuw)
|
||||
├─────────────────────────────────────┤
|
||||
│ │
|
||||
│ [Welkomstbericht] │ ← Messages area
|
||||
│ │
|
||||
│ [Gebruiker vraag] → │
|
||||
│ [Assistent antwoord] ← │
|
||||
│ │
|
||||
├─────────────────────────────────────┤
|
||||
│ Kies een onderwerp: │ ← Suggesties (context-aware)
|
||||
│ [📝 Rapportages] │
|
||||
│ [🏥 Intake & Behandeling] │
|
||||
│ [📋 Screening] │
|
||||
├─────────────────────────────────────┤
|
||||
│ [Typ een vraag... ] [Send] │ ← Input
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.2 Suggestie Flow (twee stappen)
|
||||
|
||||
**Stap 1: Categorieën**
|
||||
```
|
||||
Kies een onderwerp:
|
||||
┌──────────────────────┐
|
||||
│ 📝 Rapportages │
|
||||
├──────────────────────┤
|
||||
│ 🏥 Intake & Behandeling │
|
||||
├──────────────────────┤
|
||||
│ 📋 Screening │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
**Stap 2: Vragen (na klik op categorie)**
|
||||
```
|
||||
← Terug
|
||||
📝 Rapportages
|
||||
┌────────────────────────────────────┐
|
||||
│ Geef een samenvatting van de │
|
||||
│ rapportages │
|
||||
├────────────────────────────────────┤
|
||||
│ Wat is er de laatste tijd genoteerd?│
|
||||
├────────────────────────────────────┤
|
||||
│ Zijn er behandeladviezen? │
|
||||
└────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5.3 Context Switching
|
||||
|
||||
| Locatie in EPD | Chat Gedrag |
|
||||
|----------------|-------------|
|
||||
| Dashboard (geen cliënt) | Documentatie-modus, standaard suggesties |
|
||||
| Cliëntdossier | Cliënt-modus, cliënt-indicator, cliënt-suggesties |
|
||||
| Cliënt → Dashboard | Terug naar documentatie-modus |
|
||||
|
||||
---
|
||||
|
||||
## 6. Interacties met AI
|
||||
|
||||
### 6.1 Cliënt-vragen
|
||||
|
||||
| Vraag | AI Context | Verwacht Antwoord |
|
||||
|-------|------------|-------------------|
|
||||
| "Samenvatting rapportages" | Laatste 5 reports | Bullets per rapportage met datum en type |
|
||||
| "Wat is het behandeladvies?" | intakes.treatment_advice | Advies, programma, afdeling |
|
||||
| "Wat was de hulpvraag?" | screenings.request_for_help | Hulpvraag tekst of "niet ingevuld" |
|
||||
| "Zijn er risico's?" | risk_assessments (leeg) | "Er zijn nog geen risico-assessments" |
|
||||
|
||||
### 6.2 Voorbeeld Antwoorden
|
||||
|
||||
**Vraag: "Geef een samenvatting van de rapportages"**
|
||||
|
||||
```
|
||||
De laatste rapportages voor Jan de Vries:
|
||||
|
||||
📝 28-11-2025 - Vrije notitie
|
||||
Cliënt ervaart stemming als overwegend somber, maar benoemt ook
|
||||
positieve momenten tijdens sport. Slaapproblemen blijven aandachtspunt.
|
||||
|
||||
📝 25-11-2025 - Vrije notitie
|
||||
Gesprek over terugvalpreventie. Cliënt toont inzet en motivatie.
|
||||
|
||||
📋 22-11-2025 - Behandeladvies
|
||||
Doorzetten naar behandeling, FACT programma, afdeling Volwassenen.
|
||||
```
|
||||
|
||||
**Vraag: "Wat is het behandeladvies?"**
|
||||
|
||||
```
|
||||
Het behandeladvies voor Jan de Vries:
|
||||
|
||||
• Advies: Doorzetten naar behandeling
|
||||
• Programma: FACT
|
||||
• Afdeling: Volwassenen
|
||||
• Uitkomst: In zorg
|
||||
|
||||
Dit advies is vastgelegd bij intake "Intake Depressie" (afgerond).
|
||||
```
|
||||
|
||||
**Vraag: "Wat zijn de risico's?"**
|
||||
|
||||
```
|
||||
Er zijn nog geen risico-assessments vastgelegd voor Jan de Vries.
|
||||
|
||||
Risico-assessments kunnen worden toegevoegd via de intake of
|
||||
het tabblad 'Risico's' in het cliëntdossier.
|
||||
```
|
||||
|
||||
### 6.3 Foutafhandeling
|
||||
|
||||
| Situatie | Gebruiker ziet |
|
||||
|----------|----------------|
|
||||
| Geen rapportages | "Er zijn nog geen rapportages voor [naam]" |
|
||||
| API error | "Er ging iets mis. Probeer het opnieuw." |
|
||||
| Rate limit bereikt | Countdown timer + uitleg (bestaand) |
|
||||
|
||||
---
|
||||
|
||||
## 7. Gebruikersrollen en rechten
|
||||
|
||||
**Prototype scope:** Alle ingelogde gebruikers hebben dezelfde rechten.
|
||||
|
||||
| Rol | Toegang Chat | Cliënt Data |
|
||||
|-----|--------------|-------------|
|
||||
| Behandelaar | ✅ | Eigen cliënten (via RLS) |
|
||||
| Demo-user | ✅ | Fictieve demo-cliënten |
|
||||
|
||||
**Security:**
|
||||
- Cliënt-ID komt uit URL/PatientContext (betrouwbaar)
|
||||
- RLS policies op database niveau
|
||||
- Geen cliëntdata in logs
|
||||
|
||||
---
|
||||
|
||||
## 8. Configuratie Suggesties
|
||||
|
||||
### 8.1 Cliënt Suggesties (nieuw)
|
||||
|
||||
```typescript
|
||||
const CLIENT_SUGGESTION_CATEGORIES = [
|
||||
{
|
||||
id: 'rapportages',
|
||||
label: 'Rapportages',
|
||||
icon: '📝',
|
||||
questions: [
|
||||
'Geef een samenvatting van de rapportages',
|
||||
'Wat is er de laatste tijd genoteerd?',
|
||||
'Zijn er behandeladviezen?',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'intake',
|
||||
label: 'Intake & Behandeling',
|
||||
icon: '🏥',
|
||||
questions: [
|
||||
'Wat is het behandeladvies?',
|
||||
'Op welke afdeling loopt de intake?',
|
||||
'Is de intake afgerond?',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'screening',
|
||||
label: 'Screening',
|
||||
icon: '📋',
|
||||
questions: [
|
||||
'Wat was de hulpvraag?',
|
||||
'Wat is de screeningbeslissing?',
|
||||
'Is de cliënt geschikt bevonden?',
|
||||
],
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### 8.2 Documentatie Suggesties (bestaand, behouden)
|
||||
|
||||
```typescript
|
||||
const DOC_SUGGESTION_CATEGORIES = [
|
||||
{
|
||||
id: 'clienten',
|
||||
label: 'Cliënten & Dossiers',
|
||||
icon: '👤',
|
||||
questions: [
|
||||
'Hoe maak ik een nieuwe cliënt aan?',
|
||||
'Hoe zoek ik een bestaande cliënt?',
|
||||
'Hoe open ik een cliëntdossier?',
|
||||
],
|
||||
},
|
||||
// ... bestaande categorieën
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Acceptatiecriteria
|
||||
|
||||
### 9.1 Functioneel
|
||||
|
||||
| Criterium | Test |
|
||||
|-----------|------|
|
||||
| Cliënt-indicator toont correcte naam | Open dossier → check header |
|
||||
| Cliënt-suggesties verschijnen in dossier | Open chat in dossier → zie 3 categorieën |
|
||||
| Documentatie-suggesties buiten dossier | Open chat op dashboard → zie bestaande categorieën |
|
||||
| Vraag over rapportages werkt | Stel vraag → ontvang samenvatting |
|
||||
| Ontbrekende data wordt gemeld | Vraag naar risico's → "geen data" bericht |
|
||||
|
||||
### 9.2 Niet-functioneel
|
||||
|
||||
| Criterium | Target |
|
||||
|-----------|--------|
|
||||
| Eerste antwoord | < 3 seconden |
|
||||
| Context laden | < 200ms |
|
||||
| Correcte cliënt | 100% (via URL) |
|
||||
|
||||
---
|
||||
|
||||
## 10. Bijlagen & Referenties
|
||||
|
||||
### Projectdocumenten
|
||||
|
||||
| Document | Locatie |
|
||||
|----------|---------|
|
||||
| PRD | `docs/specs/ai-integratie/prd-ai-client-assistent-v1.md` |
|
||||
| TO | `docs/specs/ai-integratie/to-ai-client-assistent-v1.md` |
|
||||
| Bestaande chat widget | `components/docs-chat/docs-chat-widget.tsx` |
|
||||
| Bestaande suggesties | `components/docs-chat/chat-suggestions.tsx` |
|
||||
|
||||
### Data beschikbaarheid (prototype)
|
||||
|
||||
| Tabel | Rows | Bruikbaar voor vragen |
|
||||
|-------|------|----------------------|
|
||||
| reports | 21 | ✅ Samenvatting rapportages |
|
||||
| intakes | 9 | ✅ Behandeladvies, status |
|
||||
| screenings | 5 | ✅ Hulpvraag, beslissing |
|
||||
| risk_assessments | 0 | ⚠️ "Geen data" response |
|
||||
|
||||
---
|
||||
|
||||
## Versiehistorie
|
||||
|
||||
| Versie | Datum | Auteur | Wijziging |
|
||||
|--------|-------|--------|-----------|
|
||||
| v1.0 | 01-12-2025 | Colin Lit | Initiële versie, prototype scope |
|
||||
@@ -1,386 +0,0 @@
|
||||
# Functioneel Ontwerp (FO) – AI Documentatie Assistent
|
||||
|
||||
**Projectnaam:** Mini-ECD – AI Documentatie Assistent
|
||||
**Versie:** v1.0
|
||||
**Datum:** 01-12-2025
|
||||
**Auteur:** Colin van der Heijden
|
||||
|
||||
---
|
||||
|
||||
## 1. Doel en relatie met het PRD
|
||||
|
||||
**Doel van dit document:**
|
||||
Dit Functioneel Ontwerp beschrijft **hoe** de AI Documentatie Assistent functioneel werkt — wat de gebruiker ziet, doet en ervaart. Waar het PRD (`prd-ai-docs-assistent-v1.md`) uitlegt *wat en waarom*, laat dit FO zien *hoe dit in de praktijk werkt*.
|
||||
|
||||
**Toelichting aan de lezer:**
|
||||
De AI Documentatie Assistent is een floating chat widget die eindgebruikers van het EPD helpt door vragen te beantwoorden op basis van de systeemdocumentatie. Dit is de eerste AI-integratie in het Mini-ECD prototype en dient als fundament voor toekomstige AI features.
|
||||
|
||||
---
|
||||
|
||||
## 2. Overzicht van de belangrijkste onderdelen
|
||||
|
||||
1. **Floating Trigger Button** — Amber knop rechtsonder om widget te openen
|
||||
2. **Chat Panel** — Uitklapbaar gesprekspaneel
|
||||
3. **Message List** — Weergave van conversatie (gebruiker + assistent)
|
||||
4. **Input Area** — Tekstveld voor vragen stellen
|
||||
5. **Streaming Response** — Real-time weergave van AI antwoorden
|
||||
|
||||
---
|
||||
|
||||
## 3. Userstories
|
||||
|
||||
| ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit |
|
||||
|----|------|---------------|------------------|-------------|
|
||||
| US-01 | Behandelaar | Vraag stellen over EPD functie | Direct antwoord zonder zoeken | Hoog |
|
||||
| US-02 | Verpleegkundige | Uitleg krijgen over onbekende functie | Zelfstandig werken zonder collega's te storen | Hoog |
|
||||
| US-03 | Nieuwe medewerker | Systeem leren kennen via vragen | Interactieve onboarding | Hoog |
|
||||
| US-04 | Behandelaar | Vervolgvraag stellen | Context behouden in gesprek | Middel |
|
||||
| US-05 | Developer | Technische vraag over API | Snelle referentie zonder docs te openen | Middel |
|
||||
| US-06 | Alle gebruikers | Widget sluiten | Terug naar werk zonder afleiding | Hoog |
|
||||
|
||||
**User Story Details:**
|
||||
|
||||
> **US-01:** Als behandelaar wil ik een vraag kunnen stellen over het EPD zodat ik direct antwoord krijg zonder door documentatie te hoeven zoeken.
|
||||
|
||||
> **US-02:** Als verpleegkundige wil ik uitleg kunnen vragen over een functie die ik niet ken zodat ik zelfstandig verder kan werken.
|
||||
|
||||
> **US-03:** Als nieuwe medewerker wil ik via vragen het systeem leren kennen zodat ik sneller productief ben.
|
||||
|
||||
---
|
||||
|
||||
## 4. Functionele werking per onderdeel
|
||||
|
||||
### 4.1 Floating Trigger Button
|
||||
|
||||
**Locatie:** Rechtsonder in het scherm, altijd zichtbaar binnen EPD (`/epd/*` routes)
|
||||
|
||||
**Gedrag:**
|
||||
- Amber gradient knop (56x56px) met Sparkles icon
|
||||
- Hover: lichte kleurverandering
|
||||
- Klik: opent chat panel, knop verdwijnt
|
||||
- Altijd bovenop andere content (z-index: 50)
|
||||
|
||||
**States:**
|
||||
| State | Weergave |
|
||||
|-------|----------|
|
||||
| Default | Amber gradient met wit icon |
|
||||
| Hover | Donkerder amber |
|
||||
| Widget open | Knop verborgen |
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Chat Panel
|
||||
|
||||
**Afmetingen:** 384px breed × max 80vh hoog
|
||||
|
||||
**Structuur:**
|
||||
```
|
||||
┌────────────────────────────────────┐
|
||||
│ Header: titel + sluit-knop │
|
||||
├────────────────────────────────────┤
|
||||
│ │
|
||||
│ Message List (scrollbaar) │
|
||||
│ │
|
||||
│ │
|
||||
├────────────────────────────────────┤
|
||||
│ Input Area: tekstveld + verzenden │
|
||||
└────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Header:**
|
||||
- Sparkles icon + "Documentatie Assistent" tekst
|
||||
- X-knop rechts om te sluiten
|
||||
- Amber/amber-100 achtergrond gradient
|
||||
|
||||
**Gedrag bij openen:**
|
||||
1. Panel verschijnt met slide-in animatie (van onder)
|
||||
2. Welkomstbericht wordt getoond (indien eerste keer)
|
||||
3. Focus gaat naar input veld
|
||||
|
||||
**Gedrag bij sluiten:**
|
||||
- Klik op X-knop → panel verdwijnt
|
||||
- Trigger button verschijnt weer
|
||||
- Conversatie blijft behouden (sessie)
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Message List
|
||||
|
||||
**Weergave van berichten:**
|
||||
|
||||
| Type | Positie | Styling |
|
||||
|------|---------|---------|
|
||||
| Gebruiker | Rechts uitgelijnd | `bg-amber-100`, rounded |
|
||||
| Assistent | Links uitgelijnd | `bg-slate-100`, rounded |
|
||||
|
||||
**Welkomstbericht (eerste bericht):**
|
||||
```
|
||||
Hallo! Ik ben de documentatie assistent voor het Mini-ECD.
|
||||
|
||||
Stel gerust vragen over hoe het systeem werkt, bijvoorbeeld:
|
||||
• Hoe maak ik een nieuwe intake aan?
|
||||
• Hoe werkt de spraakherkenning?
|
||||
• Waar vind ik de screening resultaten?
|
||||
```
|
||||
|
||||
**Scroll gedrag:**
|
||||
- Automatisch scrollen naar nieuwste bericht
|
||||
- Gebruiker kan omhoog scrollen door historie
|
||||
- Bij nieuw bericht: scroll naar beneden
|
||||
|
||||
**Streaming weergave:**
|
||||
- Tekst verschijnt woord-voor-woord
|
||||
- Pulserende cursor aan einde tijdens streaming
|
||||
- Cursor verdwijnt wanneer response compleet is
|
||||
|
||||
---
|
||||
|
||||
### 4.4 Input Area
|
||||
|
||||
**Componenten:**
|
||||
- Textarea (auto-resize, max 4 regels)
|
||||
- Verzend-knop (amber, pijl icon)
|
||||
|
||||
**Interacties:**
|
||||
|
||||
| Actie | Resultaat |
|
||||
|-------|-----------|
|
||||
| Enter | Verstuur bericht |
|
||||
| Shift + Enter | Nieuwe regel |
|
||||
| Klik verzend-knop | Verstuur bericht |
|
||||
| Leeg bericht versturen | Geen actie |
|
||||
|
||||
**States:**
|
||||
|
||||
| State | Textarea | Verzend-knop |
|
||||
|-------|----------|--------------|
|
||||
| Idle | Enabled, placeholder | Enabled (amber) |
|
||||
| Typing | Enabled, tekst zichtbaar | Enabled |
|
||||
| Loading | Disabled | Disabled (grijs) |
|
||||
| Error | Enabled | Enabled |
|
||||
|
||||
**Placeholder tekst:** "Stel een vraag..."
|
||||
|
||||
---
|
||||
|
||||
### 4.5 Streaming Response
|
||||
|
||||
**Proces:**
|
||||
1. Gebruiker verstuurt vraag
|
||||
2. Input wordt disabled
|
||||
3. Nieuw assistent-bericht verschijnt (leeg)
|
||||
4. Tekst streamt woord-voor-woord in
|
||||
5. Bij completion: input wordt enabled
|
||||
|
||||
**Visuele feedback tijdens streaming:**
|
||||
- Pulserende cursor (`▊`) aan einde van tekst
|
||||
- Tekst verschijnt met ~50ms interval per chunk
|
||||
|
||||
**Timeout:**
|
||||
- Na 30 seconden zonder response: toon foutmelding
|
||||
- Gebruiker kan opnieuw proberen
|
||||
|
||||
---
|
||||
|
||||
## 5. UI-overzicht (visuele structuur)
|
||||
|
||||
### Widget Gesloten
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ EPD Interface │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ┌─────┐ │
|
||||
│ │ ✨ │ │
|
||||
│ └─────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
↑
|
||||
Trigger Button
|
||||
```
|
||||
|
||||
### Widget Open
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ EPD Interface │
|
||||
│ │
|
||||
│ ┌────────────────────────┤
|
||||
│ │ ✨ Docs Assistent ✕ │
|
||||
│ ├────────────────────────┤
|
||||
│ │ Welkomstbericht... │
|
||||
│ │ │
|
||||
│ │ ┌──────────────────┐ │
|
||||
│ │ │ Hoe maak ik... │←──│── User
|
||||
│ │ └──────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌──────────────────┐ │
|
||||
│ │ │ Om een intake... │←──│── Assistant
|
||||
│ │ │ ... │ │
|
||||
│ │ └──────────────────┘ │
|
||||
│ ├────────────────────────┤
|
||||
│ │ [Stel een vraag...] ➤ │
|
||||
│ └────────────────────────┘
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Interacties met AI (functionele beschrijving)
|
||||
|
||||
| Locatie | AI-actie | Trigger | Output |
|
||||
|---------|----------|---------|--------|
|
||||
| Chat widget | Vraag beantwoorden | Gebruiker verstuurt bericht | Streaming tekst-antwoord |
|
||||
| Chat widget | Vervolgvraag beantwoorden | Gebruiker stuurt vervolgvraag | Context-aware antwoord |
|
||||
| Chat widget | Buiten scope afhandelen | Vraag niet in documentatie | Eerlijk "weet ik niet" + suggesties |
|
||||
|
||||
### AI Gedragsregels
|
||||
|
||||
**Wel doen:**
|
||||
- Antwoorden baseren op de 14 MDX documentatiebestanden
|
||||
- Nederlands schrijven
|
||||
- Bullet points gebruiken voor stappen
|
||||
- Verwijzen naar specifieke menu's en knoppen
|
||||
- Eerlijk zeggen als informatie ontbreekt
|
||||
|
||||
**Niet doen:**
|
||||
- Informatie verzinnen die niet in de documentatie staat
|
||||
- Medisch advies geven
|
||||
- Behandelsuggesties doen
|
||||
- Engels antwoorden (tenzij gevraagd)
|
||||
|
||||
### Beschikbare Knowledge Base
|
||||
|
||||
De assistent heeft toegang tot deze documentatie:
|
||||
|
||||
| Bestand | Onderwerp |
|
||||
|---------|-----------|
|
||||
| `authentication.mdx` | Inloggen en authenticatie |
|
||||
| `client-management.mdx` | Cliëntbeheer |
|
||||
| `intake-system.mdx` | Intake proces |
|
||||
| `screening-system.mdx` | Screening functionaliteit |
|
||||
| `treatment-planning.mdx` | Behandelplannen |
|
||||
| `interface-design.mdx` | UI uitleg |
|
||||
| `spraakgestuurde-verslaglegging.mdx` | Spraakfuncties (NL) |
|
||||
| `voice-controlled-reporting.mdx` | Spraakfuncties (EN) |
|
||||
| `verpleegkundige-overdracht.mdx` | Overdracht workflow |
|
||||
| `fhir-datamodel.mdx` | Data model |
|
||||
| `fhir-api.mdx` | API documentatie |
|
||||
| `release-notes-system.mdx` | Release notes |
|
||||
| `build-errors-fix.mdx` | Troubleshooting |
|
||||
| `webpack-module-resolution.mdx` | Technische docs |
|
||||
|
||||
---
|
||||
|
||||
## 7. Gebruikersrollen en rechten
|
||||
|
||||
| Rol | Toegang tot widget | Beperkingen |
|
||||
|-----|-------------------|-------------|
|
||||
| Behandelaar | Ja, binnen EPD | Geen |
|
||||
| Verpleegkundige | Ja, binnen EPD | Geen |
|
||||
| Admin | Ja, binnen EPD | Geen |
|
||||
| Niet-ingelogd | Nee | Widget niet zichtbaar |
|
||||
|
||||
**Authenticatie:** Widget is alleen zichtbaar voor ingelogde gebruikers binnen `/epd/*` routes.
|
||||
|
||||
---
|
||||
|
||||
## 8. Error States en Edge Cases
|
||||
|
||||
### Error States
|
||||
|
||||
| Situatie | Weergave | Gebruikersactie |
|
||||
|----------|----------|-----------------|
|
||||
| API timeout (>30s) | "Het duurt langer dan verwacht. Probeer het opnieuw." | Retry knop |
|
||||
| API error | "Er ging iets mis. Probeer het later opnieuw." | Retry knop |
|
||||
| Netwerk offline | "Geen internetverbinding." | - |
|
||||
| Rate limit | "Te veel verzoeken. Wacht even." | Automatisch retry |
|
||||
|
||||
### Edge Cases
|
||||
|
||||
| Situatie | Gedrag |
|
||||
|----------|--------|
|
||||
| Zeer lange vraag (>2000 chars) | Vraag wordt afgekapt met waarschuwing |
|
||||
| Lege vraag | Verzenden geblokkeerd |
|
||||
| Alleen spaties | Behandeld als lege vraag |
|
||||
| Snelle opeenvolgende vragen | Vorige request wordt geannuleerd |
|
||||
| Browser tab wisselen | Streaming gaat door |
|
||||
| Page refresh | Conversatie verloren (sessie-based) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Bijlagen & Referenties
|
||||
|
||||
### Project Documentatie
|
||||
|
||||
- PRD AI Documentatie Assistent (`prd-ai-docs-assistent-v1.md`)
|
||||
- PRD AI Pre-fill Behandelplan (`prd-ai-prefill-behandelplan-v1.md`)
|
||||
- UX Stylesheet (`ux-stylesheet.md`)
|
||||
- Technisch Ontwerp Mini-ECD (`to-mini-ecd-v1_2.md`)
|
||||
|
||||
### Externe Referenties
|
||||
|
||||
- [Claude API Documentation](https://docs.anthropic.com)
|
||||
- [Anthropic Streaming Guide](https://docs.anthropic.com/en/api/streaming)
|
||||
|
||||
---
|
||||
|
||||
## Appendix A: Conversatie Voorbeelden
|
||||
|
||||
### Voorbeeld 1: Intake Vraag
|
||||
|
||||
**Gebruiker:** "Hoe maak ik een nieuwe intake aan?"
|
||||
|
||||
**Assistent:**
|
||||
```
|
||||
Om een nieuwe intake aan te maken:
|
||||
|
||||
1. Ga naar het cliëntdossier via **Cliënten** in het hoofdmenu
|
||||
2. Selecteer de gewenste cliënt
|
||||
3. Klik op het tabblad **Intake**
|
||||
4. Klik op de knop **Nieuwe Intake**
|
||||
5. Vul de intake-informatie in het formulier
|
||||
6. Klik op **Opslaan** om de intake te bewaren
|
||||
|
||||
Je kunt ook spraakherkenning gebruiken om de intake
|
||||
in te spreken via de microfoon-knop.
|
||||
```
|
||||
|
||||
### Voorbeeld 2: Buiten Scope
|
||||
|
||||
**Gebruiker:** "Wat is de beste behandeling voor depressie?"
|
||||
|
||||
**Assistent:**
|
||||
```
|
||||
Die informatie heb ik niet. Ik kan alleen helpen met
|
||||
vragen over hoe het Mini-ECD systeem werkt.
|
||||
|
||||
Misschien kan ik je helpen met:
|
||||
• Hoe maak ik een behandelplan aan?
|
||||
• Hoe voeg ik een diagnose toe?
|
||||
• Hoe werkt de screening functie?
|
||||
```
|
||||
|
||||
### Voorbeeld 3: Technische Vraag
|
||||
|
||||
**Gebruiker:** "Welke FHIR resources worden ondersteund?"
|
||||
|
||||
**Assistent:**
|
||||
```
|
||||
Het Mini-ECD ondersteunt de volgende FHIR R4 resources:
|
||||
|
||||
**Kern resources:**
|
||||
• Patient — Cliëntgegevens
|
||||
• Practitioner — Behandelaren
|
||||
• Encounter — Contactmomenten
|
||||
• Condition — Diagnoses/problemen
|
||||
• Observation — Metingen en observaties
|
||||
• CarePlan — Behandelplannen
|
||||
|
||||
Zie de API documentatie voor endpoints en voorbeelden.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Document gegenereerd als onderdeel van AI Speedrun — Week 3*
|
||||
205
docs/specs/ai-integratie/prd-ai-client-assistent-v1.md
Normal file
205
docs/specs/ai-integratie/prd-ai-client-assistent-v1.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# 📄 Product Requirements Document (PRD) – AI Cliënt Assistent
|
||||
|
||||
**Projectnaam:** Mini-ECD – AI Cliënt Assistent
|
||||
**Versie:** v1.0
|
||||
**Datum:** 01-12-2025
|
||||
**Auteur:** Colin Lit
|
||||
|
||||
---
|
||||
|
||||
## 1. Doelstelling
|
||||
|
||||
**Probleem:** 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
|
||||
- Screeningresultaten checken
|
||||
|
||||
**Oplossing:** De bestaande AI Documentatie Assistent uitbreiden met cliënt-awareness. Wanneer een behandelaar in een cliëntdossier zit, kan de assistent vragen beantwoorden over díe specifieke cliënt.
|
||||
|
||||
**Voorbeeld interacties:**
|
||||
> "Geef een samenvatting van de laatste rapportages"
|
||||
> "Wat zijn de risico's van deze cliënt?"
|
||||
> "Wat staat er in het behandeladvies?"
|
||||
|
||||
**Type:** MVP-uitbreiding op bestaande feature (AI Documentatie Assistent)
|
||||
|
||||
---
|
||||
|
||||
## 2. Doelgroep
|
||||
|
||||
| Rol | Situatie | Behoefte |
|
||||
|-----|----------|----------|
|
||||
| **Behandelaar** | Voorbereiding op consult | Snel overzicht van recente rapportages en behandeladvies |
|
||||
| **Verpleegkundige** | Overdracht dienst | Risico's en actuele status checken |
|
||||
| **Intaker** | Afsluiten intake | Samenvatting van screeningresultaat en hulpvraag |
|
||||
| **Regiebehandelaar** | Caseload review | Per cliënt snel de status kunnen opvragen |
|
||||
|
||||
**Kernbehoefte:** Informatie opvragen via natuurlijke taal, zonder te navigeren door meerdere schermen.
|
||||
|
||||
---
|
||||
|
||||
## 3. Kernfunctionaliteiten (MVP-scope)
|
||||
|
||||
### 3.1 Automatische cliënt-herkenning
|
||||
De assistent weet automatisch over welke cliënt je praat op basis van het dossier waarin je zit. Geen handmatige selectie nodig.
|
||||
|
||||
**Gedrag:**
|
||||
- In dossier van Jan de Vries → assistent beantwoordt vragen over Jan de Vries
|
||||
- Buiten cliëntdossier → assistent beantwoordt alleen documentatie-vragen
|
||||
|
||||
### 3.2 Cliënt-indicator in chat
|
||||
De gebruiker ziet duidelijk dat de assistent in "cliënt-modus" staat:
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ ✨ EPD Assistent │
|
||||
│ 📋 Dossier: Jan de Vries │ ← Zichtbaar wanneer in dossier
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 Ondersteunde vragen
|
||||
|
||||
| Categorie | Voorbeeldvragen |
|
||||
|-----------|-----------------|
|
||||
| **Rapportages** | "Samenvatting van de rapportages", "Wat is er de laatste tijd genoteerd?" |
|
||||
| **Risico's** | "Wat zijn de risico's?", "Is er suïciderisico?" |
|
||||
| **Behandeladvies** | "Wat is het behandeladvies?", "Welke zorg is geadviseerd?" |
|
||||
| **Screening** | "Wat was de hulpvraag?", "Is de screening afgerond?" |
|
||||
| **Overzicht** | "Geef een samenvatting van dit dossier" |
|
||||
|
||||
### 3.4 Context-aware suggesties
|
||||
Wanneer je in een cliëntdossier zit, toont de assistent relevante voorbeeldvragen:
|
||||
- "Geef een samenvatting van de rapportages"
|
||||
- "Wat zijn de risico's?"
|
||||
- "Wat staat in het behandeladvies?"
|
||||
|
||||
### 3.5 Gescheiden vraagtypen
|
||||
De assistent beantwoordt óf vragen over de cliënt óf vragen over het systeem, niet gemengd. Dit voorkomt verwarring.
|
||||
|
||||
| Vraag | Type | Antwoord gebaseerd op |
|
||||
|-------|------|----------------------|
|
||||
| "Wat zijn de risico's?" | Cliënt | Dossiergegevens |
|
||||
| "Hoe maak ik een intake aan?" | Systeem | Documentatie |
|
||||
|
||||
---
|
||||
|
||||
## 4. Gebruikersflows
|
||||
|
||||
### Flow 1: Snelle cliënt-check voor consult
|
||||
```
|
||||
Behandelaar opent dossier van cliënt
|
||||
↓
|
||||
Ziet chat-widget rechtsonder, header toont "Dossier: Jan de Vries"
|
||||
↓
|
||||
Klikt op suggestie "Wat zijn de risico's?"
|
||||
↓
|
||||
Assistent toont overzicht: "Jan heeft 2 risico-assessments:
|
||||
• Suïciderisico: laag (beoordeeld 15-11-2025)
|
||||
• Agressierisico: middel (beoordeeld 10-11-2025)"
|
||||
```
|
||||
|
||||
### Flow 2: Overdracht voorbereiding
|
||||
```
|
||||
Verpleegkundige opent dossier
|
||||
↓
|
||||
Vraagt: "Geef een samenvatting van de laatste rapportages"
|
||||
↓
|
||||
Assistent toont: "De laatste 3 rapportages:
|
||||
• 28-11: Stabiele stemming, medicatie ongewijzigd
|
||||
• 25-11: Gesprek over terugvalpreventie
|
||||
• 22-11: Contactmoment familie, zorgen over isolatie"
|
||||
```
|
||||
|
||||
### Flow 3: Documentatie-vraag vanuit dossier
|
||||
```
|
||||
Gebruiker is in dossier maar vraagt: "Hoe werkt de spraakherkenning?"
|
||||
↓
|
||||
Systeem herkent: dit is een documentatie-vraag
|
||||
↓
|
||||
Bestaande documentatie-flow wordt gevolgd
|
||||
↓
|
||||
Antwoord komt uit systeemdocumentatie, niet uit cliëntdossier
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Niet in Scope
|
||||
|
||||
| Uitgesloten | Reden |
|
||||
|-------------|-------|
|
||||
| **Schrijven naar dossier** | Privacy, audit trail vereisten |
|
||||
| **Medisch advies geven** | Liability, AI mag niet adviseren |
|
||||
| **Multi-cliënt vergelijkingen** | Complexiteit, privacy |
|
||||
| **Historische trends** | "Hoe ging het vorige maand?" - te complex voor MVP |
|
||||
| **Bijlagen/PDF's lezen** | Technische complexiteit |
|
||||
| **Gemengde vragen** | "Hoe maak ik een intake voor deze cliënt?" - te ambigu |
|
||||
|
||||
---
|
||||
|
||||
## 6. Succescriteria
|
||||
|
||||
| Criterium | Meetbaar doel |
|
||||
|-----------|---------------|
|
||||
| **Cliënt correct herkend** | 100% - als je in dossier zit, moet juiste cliënt actief zijn |
|
||||
| **Vraagtype correct** | >90% correcte classificatie (cliënt vs. documentatie) |
|
||||
| **Responstijd** | Eerste woord binnen 3 seconden |
|
||||
| **Data-integriteit** | Alleen data van actieve cliënt wordt getoond |
|
||||
| **Gebruikersacceptatie** | Positieve feedback in demo |
|
||||
|
||||
---
|
||||
|
||||
## 7. Risico's & Mitigatie
|
||||
|
||||
| Risico | Impact | Kans | Mitigatie |
|
||||
|--------|--------|------|-----------|
|
||||
| **Verkeerde cliëntdata tonen** | Kritiek | Laag | Cliënt-ID uit betrouwbare context (URL), niet uit vraag |
|
||||
| **AI hallucineert informatie** | Hoog | Middel | Strikte prompt: "alleen beschikbare data, zeg eerlijk als info ontbreekt" |
|
||||
| **Privacy-schending** | Kritiek | Laag | Bestaande autorisatie, RLS, geen logging van cliëntdata |
|
||||
| **Ambigue vragen** | Middel | Middel | Duidelijke vraagtype-detectie, bij twijfel → documentatie-modus |
|
||||
| **Te veel data in context** | Middel | Laag | Maximum 5 items per categorie laden |
|
||||
|
||||
---
|
||||
|
||||
## 8. Roadmap / Vervolg (Post-MVP)
|
||||
|
||||
### Fase 2: Uitgebreidere context
|
||||
- Diagnoses en condities
|
||||
- Contactmomenten/encounters
|
||||
- Behandelplan doelen en voortgang
|
||||
- Medicatie-overzicht
|
||||
|
||||
### Fase 3: Slimme acties
|
||||
- "Start een rapportage op basis van dit gesprek"
|
||||
- Suggesties voor behandelplan-updates
|
||||
- Pre-fill formulieren met AI
|
||||
|
||||
### Fase 4: Caseload-niveau
|
||||
- "Welke cliënten hebben hoog risico?"
|
||||
- Overzicht van openstaande acties
|
||||
- Prioritering suggesties
|
||||
|
||||
---
|
||||
|
||||
## 9. Bijlagen & Referenties
|
||||
|
||||
### Gerelateerde documenten
|
||||
| Document | Beschrijving |
|
||||
|----------|--------------|
|
||||
| `prd-ai-docs-assistent-v1.md` | PRD van basis documentatie assistent |
|
||||
| `fo-ai-docs-assistent-v1.md` | Functioneel ontwerp chat widget |
|
||||
| `bouwplan-ai-docs-assistent-v1.md` | Technisch implementatieplan v1 |
|
||||
|
||||
### Beschikbare cliëntdata (voor context)
|
||||
- **Rapportages** - Vrije notities en behandeladviezen
|
||||
- **Intakes** - Behandeladviezen, notities, status
|
||||
- **Risico-assessments** - Type, niveau, onderbouwing
|
||||
- **Screening** - Hulpvraag, beslissing
|
||||
|
||||
---
|
||||
|
||||
## Versiehistorie
|
||||
|
||||
| Versie | Datum | Auteur | Wijziging |
|
||||
|--------|-------|--------|-----------|
|
||||
| v1.0 | 01-12-2025 | Colin Lit | Initiële versie |
|
||||
483
docs/specs/ai-integratie/to-ai-client-assistent-v1.md
Normal file
483
docs/specs/ai-integratie/to-ai-client-assistent-v1.md
Normal file
@@ -0,0 +1,483 @@
|
||||
# ⚙️ Technisch Ontwerp (TO) – AI Cliënt Assistent
|
||||
|
||||
**Projectnaam:** Mini-ECD – AI Cliënt Assistent
|
||||
**Versie:** v1.0
|
||||
**Datum:** 01-12-2025
|
||||
**Auteur:** Colin Lit
|
||||
|
||||
---
|
||||
|
||||
## 1. Doel en relatie met PRD en FO
|
||||
|
||||
**Doel van dit document:**
|
||||
Dit TO beschrijft de technische implementatie van de AI Cliënt Assistent: een uitbreiding op de bestaande AI Documentatie Assistent die vragen over specifieke cliënten kan beantwoorden.
|
||||
|
||||
**Relatie met PRD:**
|
||||
- PRD beschrijft *wat* we bouwen: cliënt-aware chat die rapportages, risico's en behandeladvies kan samenvatten
|
||||
- TO beschrijft *hoe* we dit technisch realiseren binnen de bestaande architectuur
|
||||
|
||||
**Scope:**
|
||||
- Uitbreiding van bestaande `docs-chat` component
|
||||
- Nieuwe context loader voor cliëntdata
|
||||
- Vraagtype-detectie (cliënt vs. documentatie)
|
||||
- Cliënt-specifieke prompt templates
|
||||
|
||||
---
|
||||
|
||||
## 2. Technische Architectuur Overzicht
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (Next.js) │
|
||||
│ ┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐ │
|
||||
│ │ DocsChatWidget │ │ PatientContext │ │ ChatSuggestions│ │
|
||||
│ │ (uitgebreid) │──│ (bestaand) │ │ (dynamisch) │ │
|
||||
│ └────────┬────────┘ └────────┬─────────┘ └────────────────┘ │
|
||||
│ │ │ │
|
||||
└───────────┼────────────────────┼─────────────────────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ API Route: /api/docs/chat │
|
||||
│ ┌──────────────────┐ ┌───────────────────┐ ┌────────────────┐ │
|
||||
│ │ QuestionDetector │ │ ClientContextLoader│ │ PromptBuilder │ │
|
||||
│ │ (nieuw) │ │ (nieuw) │ │ (uitgebreid) │ │
|
||||
│ └────────┬─────────┘ └─────────┬──────────┘ └───────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └──────────────────────┼─────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌───────────────┐ │
|
||||
│ │ Claude API │ │
|
||||
│ │ (streaming) │ │
|
||||
│ └───────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ Supabase (PostgreSQL) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌─────────────────┐ │
|
||||
│ │ patients │ │ reports │ │ intakes │ │ risk_assessments│ │
|
||||
│ │ (6 rows) │ │ (21 rows)│ │ (9 rows) │ │ (via intake) │ │
|
||||
│ └──────────┘ └──────────┘ └────────────┘ └─────────────────┘ │
|
||||
│ ┌──────────────┐ ┌────────────┐ │
|
||||
│ │ screenings │ │ care_plans │ │
|
||||
│ │ (5 rows) │ │ (0 rows) │ │
|
||||
│ └──────────────┘ └────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Techstack Selectie
|
||||
|
||||
| Component | Technologie | Argumentatie |
|
||||
|-----------|-------------|--------------|
|
||||
| Frontend | Next.js 15 + React | Bestaande stack, geen wijziging |
|
||||
| State | PatientContext | Bestaande context, hergebruiken |
|
||||
| API | Next.js API Routes | Bestaande `/api/docs/chat` uitbreiden |
|
||||
| AI | Claude claude-sonnet-4-20250514 | Huidige model, goed voor Nederlands |
|
||||
| Database | Supabase (PostgreSQL) | Bestaand, RLS enabled |
|
||||
| Streaming | Server-Sent Events | Bestaande implementatie |
|
||||
|
||||
**Geen nieuwe dependencies nodig** - alles bouwt voort op bestaande technologie.
|
||||
|
||||
---
|
||||
|
||||
## 4. Datamodel Analyse
|
||||
|
||||
### 4.1 Beschikbare data per cliënt
|
||||
|
||||
Op basis van database-analyse is de volgende data beschikbaar:
|
||||
|
||||
| Tabel | Veld | Beschikbaar | Bruikbaar voor AI |
|
||||
|-------|------|-------------|-------------------|
|
||||
| **patients** | name, birth_date, status | ✅ 6 patiënten | Context header |
|
||||
| **reports** | content, type, created_at | ✅ 21 rapportages | Samenvatting rapportages |
|
||||
| **intakes** | treatment_advice (JSONB), notes | ✅ 9 intakes | Behandeladvies vragen |
|
||||
| **screenings** | request_for_help, decision | ✅ 5 screenings | Hulpvraag/beslissing |
|
||||
| **risk_assessments** | risk_type, risk_level, rationale | ⚠️ 0 rows (via intake) | Risico-overzicht |
|
||||
| **care_plans** | goals, activities (JSONB) | ⚠️ 0 rows | Behandelplan doelen |
|
||||
|
||||
### 4.2 Datastructuur voorbeelden
|
||||
|
||||
**Reports (content):**
|
||||
```
|
||||
S – Subjectief: Cliënt geeft aan dat piekergedachten over werk...
|
||||
O – Objectief: Cliënt verschijnt op tijd en verzorgd...
|
||||
E – Evaluatie: Er is sprake van lichte verbetering...
|
||||
P – Plan: Cliënt gaat komende week dagelijks...
|
||||
```
|
||||
|
||||
**Intakes (treatment_advice JSONB):**
|
||||
```json
|
||||
{
|
||||
"advice": "<p>Doorzetten naar behandeling</p>",
|
||||
"outcome": "in_zorg",
|
||||
"program": "FACT",
|
||||
"department": "Volwassenen",
|
||||
"psychologist": "Colin"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Context Loading Query
|
||||
|
||||
```sql
|
||||
-- Rapportages (laatste 5)
|
||||
SELECT type, content, created_at
|
||||
FROM reports
|
||||
WHERE patient_id = $1 AND deleted_at IS NULL
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 5;
|
||||
|
||||
-- Intakes met behandeladvies
|
||||
SELECT title, department, status, treatment_advice, notes
|
||||
FROM intakes
|
||||
WHERE patient_id = $1
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 3;
|
||||
|
||||
-- Screening hulpvraag
|
||||
SELECT request_for_help, decision, decision_notes
|
||||
FROM screenings
|
||||
WHERE patient_id = $1
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1;
|
||||
|
||||
-- Risico-assessments (via intake)
|
||||
SELECT ra.risk_type, ra.risk_level, ra.rationale, ra.assessment_date
|
||||
FROM risk_assessments ra
|
||||
JOIN intakes i ON ra.intake_id = i.id
|
||||
WHERE i.patient_id = $1
|
||||
ORDER BY ra.assessment_date DESC
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API Ontwerp
|
||||
|
||||
### 5.1 Bestaande API's Analyse
|
||||
|
||||
**FHIR API's (bestaand):**
|
||||
|
||||
| Endpoint | Methode | Bruikbaar voor AI Chat |
|
||||
|----------|---------|------------------------|
|
||||
| `/api/fhir/Patient/[id]` | GET | ⚠️ Beperkt - alleen demographics |
|
||||
| `/api/fhir/Patient` | GET/POST | ❌ Niet nodig |
|
||||
| `/api/fhir/Practitioner/[id]` | GET | ❌ Niet relevant |
|
||||
|
||||
**REST API's (bestaand):**
|
||||
|
||||
| Endpoint | Methode | Data | Bruikbaar |
|
||||
|----------|---------|------|-----------|
|
||||
| `/api/reports?patientId=` | GET | Rapportages met content | ✅ **Zeer bruikbaar** |
|
||||
| `/api/intakes/[id]` | GET | Intake + treatment_advice | ✅ **Zeer bruikbaar** |
|
||||
| `/api/screenings/[id]` | GET | Hulpvraag + beslissing + activities | ✅ **Zeer bruikbaar** |
|
||||
|
||||
### 5.2 Data Access Strategie
|
||||
|
||||
**Overwogen opties:**
|
||||
|
||||
| Optie | Beschrijving | Voordelen | Nadelen |
|
||||
|-------|--------------|-----------|---------|
|
||||
| **A: Bestaande API's** | Fetch naar `/api/reports`, `/api/intakes`, etc. | Hergebruik, consistentie | Extra HTTP overhead, intakes/screenings list endpoints ontbreken |
|
||||
| **B: Directe Supabase** | Server-side queries in API route | Sneller, 1 DB roundtrip, RLS automatisch | Duplicatie van query logic |
|
||||
| **C: FHIR $summary** | Nieuw endpoint `GET /api/fhir/Patient/[id]/$summary` | FHIR-compliant, extern bruikbaar | Meeste werk, overkill voor MVP |
|
||||
|
||||
**Gekozen: Optie B - Directe Supabase queries**
|
||||
|
||||
Argumentatie:
|
||||
1. **Performance**: 1 database roundtrip vs. 3-4 HTTP calls
|
||||
2. **Simpliciteit**: Geen nieuwe endpoints nodig voor MVP
|
||||
3. **Security**: RLS policies werken automatisch op server-side queries
|
||||
4. **Latency**: ~50ms vs. ~200ms+ bij HTTP calls
|
||||
|
||||
**Post-MVP overweging:** Een FHIR `$summary` operation kan waardevol zijn voor externe systeem-integraties.
|
||||
|
||||
### 5.3 Chat endpoint uitbreiden
|
||||
|
||||
**Endpoint:** `POST /api/docs/chat`
|
||||
|
||||
**Huidige input:**
|
||||
```typescript
|
||||
{
|
||||
messages: Array<{ role: 'user' | 'assistant', content: string }>
|
||||
}
|
||||
```
|
||||
|
||||
**Uitgebreide input:**
|
||||
```typescript
|
||||
{
|
||||
messages: Array<{ role: 'user' | 'assistant', content: string }>,
|
||||
clientId?: string // UUID van actieve patiënt (optioneel)
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Ongewijzigd (SSE streaming)
|
||||
|
||||
### 5.4 Nieuwe interne modules
|
||||
|
||||
```typescript
|
||||
// lib/docs/question-type-detector.ts
|
||||
export type QuestionType = 'client' | 'documentation' | 'ambiguous'
|
||||
|
||||
export function detectQuestionType(
|
||||
question: string,
|
||||
hasClientContext: boolean
|
||||
): QuestionType
|
||||
|
||||
// lib/docs/client-context-loader.ts
|
||||
export interface ClientContext {
|
||||
patient: { name: string; birthDate: string; status: string }
|
||||
reports: Array<{ type: string; content: string; date: string }>
|
||||
intakes: Array<{ title: string; treatmentAdvice: object }>
|
||||
screening: { requestForHelp: string; decision: string } | null
|
||||
riskAssessments: Array<{ type: string; level: string; rationale: string }>
|
||||
}
|
||||
|
||||
export async function loadClientContext(
|
||||
clientId: string
|
||||
): Promise<ClientContext>
|
||||
|
||||
// lib/docs/client-prompt-builder.ts
|
||||
export function buildClientPrompt(
|
||||
context: ClientContext,
|
||||
question: string
|
||||
): string
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Security & Compliance
|
||||
|
||||
### 6.1 Bestaande beveiliging (behouden)
|
||||
|
||||
| Maatregel | Status | Implementatie |
|
||||
|-----------|--------|---------------|
|
||||
| **Authentication** | ✅ | Supabase Auth, sessie vereist |
|
||||
| **RLS Policies** | ✅ | Alle tabellen hebben RLS enabled |
|
||||
| **Rate Limiting** | ✅ | 10 req/min per user (in-memory) |
|
||||
| **HTTPS** | ✅ | Vercel enforced |
|
||||
|
||||
### 6.2 Aanvullende maatregelen
|
||||
|
||||
| Maatregel | Implementatie |
|
||||
|-----------|---------------|
|
||||
| **Client ID validatie** | UUID format check + bestaat in database |
|
||||
| **Context isolatie** | Alleen data van opgegeven clientId laden |
|
||||
| **Geen logging cliëntdata** | AI responses niet loggen naar ai_events |
|
||||
| **Token limit** | Max 4000 tokens context om data-lekkage te beperken |
|
||||
|
||||
### 6.3 Privacy overwegingen
|
||||
|
||||
```typescript
|
||||
// NIET loggen naar ai_events bij cliënt-vragen
|
||||
if (questionType === 'client') {
|
||||
// Skip ai_events insert - geen cliëntdata in logs
|
||||
}
|
||||
|
||||
// Wel loggen bij documentatie-vragen (bestaand gedrag)
|
||||
if (questionType === 'documentation') {
|
||||
await logAiEvent({ kind: 'chat', request, response })
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. AI/LLM Integratie
|
||||
|
||||
### 7.1 Vraagtype Detectie
|
||||
|
||||
**Heuristiek voor detectie:**
|
||||
|
||||
```typescript
|
||||
const CLIENT_KEYWORDS = [
|
||||
'rapportage', 'risico', 'behandeladvies', 'screening',
|
||||
'hulpvraag', 'samenvatting', 'dossier', 'deze cliënt',
|
||||
'zijn/haar', 'behandeling', 'medicatie', 'diagnose'
|
||||
]
|
||||
|
||||
const DOC_KEYWORDS = [
|
||||
'hoe', 'waar', 'wat is', 'tutorial', 'handleiding',
|
||||
'functie', 'knop', 'menu', 'systeem', 'epd'
|
||||
]
|
||||
|
||||
function detectQuestionType(question: string, hasClientContext: boolean): QuestionType {
|
||||
if (!hasClientContext) return 'documentation'
|
||||
|
||||
const q = question.toLowerCase()
|
||||
const clientScore = CLIENT_KEYWORDS.filter(k => q.includes(k)).length
|
||||
const docScore = DOC_KEYWORDS.filter(k => q.includes(k)).length
|
||||
|
||||
if (clientScore > docScore) return 'client'
|
||||
if (docScore > clientScore) return 'documentation'
|
||||
return 'ambiguous' // Fallback naar documentation
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 Client Prompt Template
|
||||
|
||||
```typescript
|
||||
const CLIENT_SYSTEM_PROMPT = `Je bent een EPD-assistent die vragen beantwoordt over een specifieke cliënt.
|
||||
|
||||
BELANGRIJKE REGELS:
|
||||
1. Beantwoord ALLEEN op basis van de gegeven context
|
||||
2. Als informatie ontbreekt, zeg dit eerlijk
|
||||
3. Geef NOOIT medisch advies of diagnoses
|
||||
4. Verzin NOOIT informatie die niet in de context staat
|
||||
5. Antwoord beknopt en professioneel
|
||||
|
||||
CLIËNT: {patientName}
|
||||
GEBOORTEDATUM: {birthDate}
|
||||
STATUS: {status}
|
||||
|
||||
RAPPORTAGES (laatste {reportCount}):
|
||||
{reportsFormatted}
|
||||
|
||||
BEHANDELADVIES:
|
||||
{treatmentAdviceFormatted}
|
||||
|
||||
SCREENING/HULPVRAAG:
|
||||
{screeningFormatted}
|
||||
|
||||
RISICO-ASSESSMENTS:
|
||||
{riskAssessmentsFormatted}
|
||||
`
|
||||
```
|
||||
|
||||
### 7.3 Fallback bij ambigue vragen
|
||||
|
||||
Bij `questionType === 'ambiguous'`:
|
||||
- Default naar documentatie-modus
|
||||
- Toon hint: "Bedoelde je een vraag over de documentatie of over deze cliënt?"
|
||||
|
||||
---
|
||||
|
||||
## 8. Performance & Scalability
|
||||
|
||||
### 8.1 Performance Targets
|
||||
|
||||
| Metric | Target | Huidige baseline |
|
||||
|--------|--------|------------------|
|
||||
| Context laden | < 200ms | N.v.t. (nieuw) |
|
||||
| Vraagtype detectie | < 10ms | N.v.t. (nieuw) |
|
||||
| Eerste token | < 3 sec | ~2 sec (docs) |
|
||||
| Totale response | < 10 sec | ~5-8 sec (docs) |
|
||||
|
||||
### 8.2 Optimalisaties
|
||||
|
||||
```typescript
|
||||
// Parallel laden van context
|
||||
const [reports, intakes, screening, risks] = await Promise.all([
|
||||
loadReports(clientId),
|
||||
loadIntakes(clientId),
|
||||
loadScreening(clientId),
|
||||
loadRiskAssessments(clientId)
|
||||
])
|
||||
|
||||
// Token budget management
|
||||
const MAX_CONTEXT_TOKENS = 4000
|
||||
const contextText = truncateToTokenLimit(
|
||||
formatContext(reports, intakes, screening, risks),
|
||||
MAX_CONTEXT_TOKENS
|
||||
)
|
||||
```
|
||||
|
||||
### 8.3 Caching strategie
|
||||
|
||||
| Data | Cache | TTL |
|
||||
|------|-------|-----|
|
||||
| Cliënt context | Geen | - |
|
||||
| Documentatie chunks | In-memory | Session |
|
||||
| Rate limit state | In-memory | 60 sec |
|
||||
|
||||
**Geen caching van cliëntdata** - altijd verse data uit database voor medische nauwkeurigheid.
|
||||
|
||||
---
|
||||
|
||||
## 9. Haalbaarheidsanalyse
|
||||
|
||||
### 9.1 Technische haalbaarheid: ✅ HOOG
|
||||
|
||||
| Aspect | Beoordeling | Toelichting |
|
||||
|--------|-------------|-------------|
|
||||
| **Datamodel** | ✅ Compleet | Alle benodigde tabellen bestaan en bevatten data |
|
||||
| **API structuur** | ✅ Eenvoudig | Kleine uitbreiding op bestaande endpoint |
|
||||
| **Frontend** | ✅ Minimaal | PatientContext bestaat al |
|
||||
| **AI integratie** | ✅ Bewezen | Zelfde Claude API als documentatie-chat |
|
||||
|
||||
### 9.2 Data beschikbaarheid
|
||||
|
||||
| Categorie | PRD Requirement | Database Status |
|
||||
|-----------|-----------------|-----------------|
|
||||
| Rapportages | ✅ | 21 rows, SOAP-format content |
|
||||
| Behandeladvies | ✅ | JSONB in intakes.treatment_advice |
|
||||
| Risico's | ⚠️ | Tabel bestaat, 0 rows (seed data nodig) |
|
||||
| Screening | ✅ | 5 rows, hulpvraag veld beschikbaar |
|
||||
|
||||
### 9.3 Geschatte implementatietijd
|
||||
|
||||
| Component | Schatting |
|
||||
|-----------|-----------|
|
||||
| `question-type-detector.ts` | 2 uur |
|
||||
| `client-context-loader.ts` | 3 uur |
|
||||
| `client-prompt-builder.ts` | 2 uur |
|
||||
| API route uitbreiding | 2 uur |
|
||||
| Frontend (indicator + suggestions) | 3 uur |
|
||||
| Testing & refinement | 4 uur |
|
||||
| **Totaal** | **~16 uur** |
|
||||
|
||||
### 9.4 Risico's en mitigatie
|
||||
|
||||
| Risico | Impact | Mitigatie |
|
||||
|--------|--------|-----------|
|
||||
| **Geen risk_assessments data** | Middel | Seed data toevoegen of feature uitstellen |
|
||||
| **Token overflow** | Laag | Truncatie met prioriteit (nieuwste eerst) |
|
||||
| **Hallucinatie** | Hoog | Strikte prompt + "ik weet het niet" response |
|
||||
| **Performance** | Laag | Parallel queries, geen joins |
|
||||
|
||||
---
|
||||
|
||||
## 10. Conclusie & Aanbeveling
|
||||
|
||||
### Haalbaarheid: ✅ JA
|
||||
|
||||
De AI Cliënt Assistent is technisch haalbaar binnen de huidige architectuur:
|
||||
|
||||
1. **Datamodel is compleet** - Alle benodigde tabellen bestaan met RLS
|
||||
2. **Geen nieuwe dependencies** - Bouwt voort op bestaande stack
|
||||
3. **Minimale frontend wijzigingen** - PatientContext hergebruiken
|
||||
4. **Bewezen AI integratie** - Zelfde Claude API als docs-chat
|
||||
|
||||
### Aanbevolen aanpak
|
||||
|
||||
1. **Fase 1:** Seed data voor risk_assessments (test coverage)
|
||||
2. **Fase 2:** Backend modules (detector, loader, prompt builder)
|
||||
3. **Fase 3:** API route uitbreiding
|
||||
4. **Fase 4:** Frontend indicator en dynamische suggestions
|
||||
5. **Fase 5:** Integratie testing met echte cliëntdata
|
||||
|
||||
---
|
||||
|
||||
## 11. Bijlagen & Referenties
|
||||
|
||||
### Projectdocumenten
|
||||
| Document | Locatie |
|
||||
|----------|---------|
|
||||
| PRD | `docs/specs/ai-integratie/prd-ai-client-assistent-v1.md` |
|
||||
| Bestaande docs-chat | `components/docs-chat/` |
|
||||
| API route | `app/api/docs/chat/route.ts` |
|
||||
| PatientContext | `contexts/patient-context.tsx` |
|
||||
|
||||
### Database schema
|
||||
- Volledige schema via `mcp__supabase__list_tables`
|
||||
- RLS policies actief op alle tabellen
|
||||
|
||||
---
|
||||
|
||||
## Versiehistorie
|
||||
|
||||
| Versie | Datum | Auteur | Wijziging |
|
||||
|--------|-------|--------|-----------|
|
||||
| v1.0 | 01-12-2025 | Colin Lit | Initiële versie met haalbaarheidsanalyse |
|
||||
| v1.1 | 01-12-2025 | Colin Lit | FHIR/REST API analyse toegevoegd, data access strategie onderbouwd |
|
||||
Reference in New Issue
Block a user