add les 12

This commit is contained in:
2026-05-21 08:52:47 +02:00
parent 634789e615
commit eb1ba2e28d
42 changed files with 11012 additions and 8 deletions

View File

@@ -0,0 +1,228 @@
# Les 12 — Lesopdracht
## Refactor jouw thema-app naar Tool Calling
**Vak:** AI-Assisted Development
**Opleiding:** NOVI Hogeschool Utrecht
**Wanneer:** Thuis, vóór volgende les
**Inleveren:** GitHub URL + screenshots van werkende multi-step chat
---
## Doel
Bouw voort op je **eigen thema-app** uit Les 11. Refactor de chat-route — weg met de hele dataset meesturen. Vervang door **tools** die AI zelf kan aanroepen.
Je oefent:
- Tools definiëren met description + inputSchema + execute
- `stopWhen: stepCountIs(N)` voor multi-step queries
- System prompts voor tool-gebruik aansturen
- Multi-step vragen testen
---
## Vereisten
- Werkende app uit Les 11 (Next.js + Supabase + chat met data)
- Eigen thema (geen Polderfest namaken)
- 100+ records in je Supabase
- OpenAI key in `.env.local`
> Heb je geen werkende Les 11 app? Eerst die afmaken. Deze opdracht bouwt erop voort.
---
## Wat moet er staan?
### Code
- [ ] **Chat-route gerefactord** — geen `.select("*")` aan begin van POST meer
- [ ] **Minstens 3 tools** gedefinieerd voor jouw dataset
- [ ] Eén tool met **enum parameters** (vaste keuze)
- [ ] Eén tool met **optional filters** (`.optional()` parameters)
- [ ] `stopWhen: stepCountIs(5)` in `streamText`
- [ ] System prompt aangepast: "gebruik tools, verzin niet"
### Werking
- [ ] Chat werkt nog (geen 500-errors)
- [ ] Minstens 3 vragen die elk **1 tool** triggeren
- [ ] Minstens 1 vraag die **2+ tools** triggert (multi-step)
- [ ] AI verzint niet meer — tool-results worden gebruikt
---
## Tools voor jouw thema — voorbeelden
### Restaurant-aggregator
| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchRestaurants` | cuisine?, price_range?, neighborhood? | Filter restaurants |
| `getRestaurantById` | id | Detail + menu |
| `getCuisineStats` | (geen) | Verdeling per cuisine |
### Scriptie-archief
| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchTheses` | year?, supervisor?, keyword? | Filter scripties |
| `getThesisAbstract` | id | Volledige samenvatting |
| `getYearStats` | (geen) | Telling per jaar |
### Museum-collectie
| Tool | Parameters | Wat |
|------|-----------|-----|
| `searchArtworks` | artist?, period?, medium? | Filter kunstwerken |
| `getArtworkDetails` | id | Detail + provenance |
| `getPeriodStats` | (geen) | Verdeling per stroming |
**Voor jouw thema — bedenk:**
- Wat filtert iemand vaak? → `searchX` met filter-parameters
- Wat is een unieke entiteit? → `getXById` of `getXByName`
- Welke aggregaties zijn interessant? → `getStats`
---
## Stappenplan
### Stap 1 — Backup huidige chat-route (2 min)
```bash
cp app/api/chat/route.ts app/api/chat/route.les11.ts.bak
```
Voor het geval de refactor faalt.
### Stap 2 — Refactor route.ts (20 min)
Open `app/api/chat/route.ts`. Verwijder:
- `const { data: bands } = await supabase...select("*")` aan begin
- De grote `context` string
- De grote system prompt met alle data
Voeg toe:
- `import { tool } from "ai"` en `import { z } from "zod"`
- Tool-definities boven je POST-functie
- `tools: { ... }` en `stopWhen: stepCountIs(5)` in `streamText` (importeer `stepCountIs` uit `"ai"`)
- Kortere system prompt — alleen rol + tool-tips
### Stap 3 — Eerste tool: searchX (15 min)
Hier het patroon — pas aan voor jouw thema:
```typescript
const searchItems = tool({
description:
"Zoek items in [thema-naam]. Filter op X, Y, of Z. " +
"Gebruik dit voor filtervragen.",
inputSchema: z.object({
category: z.enum(["A", "B", "C"]).optional(),
minRating: z.number().min(1).max(5).optional(),
keyword: z.string().optional().describe("Zoekterm in titel of beschrijving"),
}),
execute: async ({ category, minRating, keyword }) => {
let q = supabase.from("items").select("*");
if (category) q = q.eq("category", category);
if (minRating) q = q.gte("rating", minRating);
if (keyword) q = q.ilike("title", `%${keyword}%`);
const { data, error } = await q.limit(20);
if (error) return { error: error.message };
return { count: data.length, items: data };
},
});
```
### Stap 4 — Twee extra tools (15 min)
Voeg minstens 2 meer toe. Inspiratie boven.
### Stap 5 — System prompt aanpassen (5 min)
```typescript
const system = `Je bent een assistent voor [thema-naam].
Gebruik de beschikbare tools om vragen te beantwoorden.
Tips:
- Voor "welke X met Y?" → searchItems
- Voor "vertel me over X" → getItemById
- Voor "hoeveel" of "verdeling" → getStats
Verzin nooit data. Antwoord in het Nederlands.`;
```
### Stap 6 — Test multi-step (15 min)
In je chat, probeer:
1. **Single tool** (`searchItems` triggert):
```
Welke [items] hebben [filter]?
```
2. **Single tool** (`getItemById` triggert):
```
Vertel me alles over [specifieke item].
```
3. **Single tool** (`getStats` triggert):
```
Hoeveel [items] in totaal? En per [groep]?
```
4. **Multi-step** (2+ tools):
```
Geef me 3 [items] in categorie X, en vergelijk ze qua [eigenschap].
```
### Stap 7 — Screenshots maken (8 min)
Voor je inleveren bij Brightspace:
- 1 screenshot per single-tool vraag (3 stuks)
- 1 screenshot van multi-step vraag (waar je 2 tool-calls ziet — als je UI ze toont)
---
## Inleveren
1. **GitHub URL** in Brightspace
2. **4 screenshots** in je README (3× single + 1× multi-step)
3. **Eén alinea** in README: welke tools heb je gedefinieerd? Waarom deze?
---
## Veelvoorkomende problemen
| Probleem | Oplossing |
|----------|-----------|
| AI roept geen tools aan | Description verbeteren — wees specifieker |
| AI gebruikt 1 tool meerdere keren | System prompt — zeg "kies juiste tool" |
| AI returnt foutmelding "Tool args invalid" | Zod schema te strict — gebruik `.optional()` waar nodig |
| `Cannot find module 'zod'` | `npm install zod` |
| Tool execute crasht | Error throwen → niet doen, return `{ error: "..." }` |
| Multi-step werkt niet | `stopWhen: stepCountIs(5)` toegevoegd? Default is 1 stap. |
---
## Tijd-indicatie
| Stap | Tijd |
|------|------|
| Backup + refactor route | 22 min |
| 3 tools definiëren | 30 min |
| System prompt + multi-step | 20 min |
| Testen + screenshots | 23 min |
| **Totaal** | **~1,5 uur** |
Loop je vast? Vraag op Brightspace.
---
## Tips
- **Begin klein** — eerst één tool werkend. Dan twee. Dan drie. Niet alles tegelijk.
- **Schrijf descriptions zoals voor een collega** — "Doe X als gebruiker vraagt om Y."
- **Test direct na elke tool** — werkt 't? Goed. Werkt 't niet? Beschrijving aanpassen.
- **Gebruik enums** voor vaste keuzes — AI respecteert ze automatisch.
Succes! Volgende les zien we hoe ver dit kan met Agents.