Files
dify-handleidingen/00-sessie/maak_dias.py
T
Guido van Dijk 909eca8067 feat(presentaties): QR-code en link naar git.lexconsultancy.nl/guido op de slotdia
- QR (segno) in beelden/, met bijschrift Alle vier de reeksen
- BRON wijst naar de overzichtspagina in plaats van een enkele repository
- pptx en notitieversies opnieuw gebouwd

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 22:17:24 +02:00

348 lines
29 KiB
Python

"""Bouwt de dia's van de workshop (22 stuks) als HTML-secties van 1920x1080 plus deck.json.
Standaard verwijzen de beelden naar de map beelden/ naast dit script, zodat bouw_pdf.py er een
PDF van kan maken. Met --artifact krijgen de beelden de paden van de online presentatie (asset store).
Licentie: CC BY-SA 4.0, zie ../../LICENSE.md. Logo van AI Netwerk Limburg uitgezonderd.
"""
import json, sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
P = HERE / "project"; S = P / "slides"; S.mkdir(parents=True, exist_ok=True)
ARTIFACT = "--artifact" in sys.argv
# Uitgebreide begeleidersnotities (privé, niet in git): notities-begeleider.json naast dit script,
# per dia-id een tekst die de sprekersnotitie vervangt. Alleen gebruikt met --notities.
NOTITIES = {}
if "--notities" in sys.argv:
NOTITIES = json.loads((HERE / "notities-begeleider.json").read_text(encoding="utf-8"))
BEELD = {
"logo": ("../beelden/logo-ai-netwerk-limburg.png", "/_blob/120fdff17b59f8e1cc380d9086a1ad9f"),
"afgekeurd": ("../beelden/schoolnieuws-afgekeurd.jpg", "/_blob/9b09f7c211d54f2d5c5b5bdaa2b69fae"),
"flow": ("../beelden/studiecoach-flow.jpg", "/_blob/1c5f3486aa7ea647a8ee49269f3f95bf"),
"docent": ("../beelden/studiecoach-docent-antwoord.jpg", "/_blob/244acf99a4fa9215357a5e95e1eec2f4"),
"lex": ("../beelden/logo-lex-wit.png", "/_blob/a056bd447e5dc103fd01f7528f888bb9"),
"lexkleur": ("../beelden/logo-lex.png", "/_blob/042fe916c9a2622daf445ddb6d0bd222"),
"qr": ("../beelden/qr-git.png", "../beelden/qr-git.png"),
}
def beeld(naam): return BEELD[naam][1 if ARTIFACT else 0]
EIGENAAR = "Guido van Dijk, LeX Consultancy B.V. en AI Netwerk Limburg"
KOP = "Kennisfestival AI Netwerk Limburg · 2 x een uur"
CONTACT = "guido@l-e-x.nl · guido@ai-netwerk-limburg.nl"
BRON = "git.lexconsultancy.nl/guido"
DARK="#1E2A3A"; LIGHT="#F7F4EC"; LIGHT2="#EFEAE0"; ACC="#D9480F"; BLUE="#2563EB"; BODY="#3D4756"; BODYD="#D9DEE6"; LINE="#D8D2C4"
H="'Rubik', Arial, sans-serif"; T="'Nunito Sans', Verdana, sans-serif"
LOGO=beeld("logo")
order=[]; sections={}
def slide(id_, body, bg=LIGHT, color=DARK, pad="128px 128px 160px", extra="display:flex; flex-direction:column; gap:40px", notes="", section=None, transition="fade", footer=True):
fcol = "#8A8F98" if bg in (LIGHT, LIGHT2) else "#9AA3B1"
notes = NOTITIES.get(id_, notes)
foot = f'<p style="position:absolute; left:128px; bottom:64px; font-size:24px; color:{fcol}">AI Agents: van voorbeeld naar je eigen project · LeX Consultancy · AI Netwerk Limburg · CC BY-SA 4.0</p>' if footer else ""
# Klein LeX-logo rechtsonder op elke dia; wit op donkere dia's, kleur op lichte.
lexlogo = beeld("lexkleur") if bg in (LIGHT, LIGHT2) else beeld("lex")
if footer: # cover en slot hebben het logo al bovenaan
foot += f'<img src="{lexlogo}" alt="LeX Consultancy" style="position:absolute; right:128px; bottom:52px; width:90px; height:52px; object-fit:contain">'
html = (f'<section id="{id_}" data-transition="{transition}" style="background:{bg}; color:{color}; font-family:{T}; padding:{pad}; {extra}">\n'
f'{body}\n{foot}\n<aside>{notes}</aside>\n</section>\n')
(S / f"{id_}.html").write_text(html, encoding="utf-8"); order.append(id_)
if section: sections[id_]={"description":section,"start":id_}
def h2(t): return f'<h2 style="font-family:{H}; font-size:64px; font-weight:600; line-height:1.1">{t}</h2>'
def eyebrow(t, c=ACC): return f'<p style="font-family:{H}; font-size:26px; font-weight:600; letter-spacing:2px; text-transform:uppercase; color:{c}">{t}</p>'
def p(t, size=32, c=BODY): return f'<p style="font-size:{size}px; color:{c}; line-height:1.4">{t}</p>'
def card(title, text, w="flex:1", bg="#FFFFFF", tc=DARK, bc=BODY, border=LINE):
return (f'<div style="{w}; display:flex; flex-direction:column; gap:16px; background:{bg}; padding:36px; border:1px solid {border}; border-radius:16px">'
f'<h3 style="font-family:{H}; font-size:34px; font-weight:600; color:{tc}; line-height:1.2">{title}</h3>'
f'<p style="font-size:27px; color:{bc}; line-height:1.4">{text}</p></div>')
def num(n, label, w="flex:1"):
return (f'<div style="{w}; display:flex; flex-direction:column; gap:8px"><p style="font-family:{H}; font-size:120px; font-weight:600; color:{ACC}; line-height:1">{n}</p>'
f'<p style="font-size:28px; color:{BODY}; line-height:1.3">{label}</p></div>')
def ul(items, size=30, c=BODY):
return f'<ul style="font-size:{size}px; color:{c}; line-height:1.5">' + "".join(f"<li>{i}</li>" for i in items) + "</ul>"
def table(rows, widths, size=27, head=True):
out=[f'<table style="font-size:{size}px; color:{BODY}; border:1px solid {LINE}; background:#FFFFFF">']
for i,r in enumerate(rows):
tag = "th" if (head and i==0) else "td"
bg = f' style="background:{LIGHT2}"' if (head and i==0) else ""
cells="".join(f'<{tag} style="width:{widths[j]}%; color:{DARK if tag=="th" else BODY}">{c}</{tag}>' for j,c in enumerate(r))
out.append(f"<tr{bg}>{cells}</tr>")
out.append("</table>"); return "".join(out)
def interactie(label): return f'<p style="font-family:{H}; font-size:26px; font-weight:600; letter-spacing:2px; text-transform:uppercase; color:{BLUE}">Interactie · {label}</p>'
# ---------- DEEL 1: inhoud, interactie, voorbeelden ----------
# 1 cover
slide("cover", f'''
<img src="{LOGO}" alt="AI Netwerk Limburg" style="position:absolute; right:128px; top:96px; width:260px; height:210px; object-fit:contain">
<img src="{beeld("lex")}" alt="LeX Consultancy" style="position:absolute; right:148px; top:330px; width:150px; height:86px; object-fit:contain">
<div style="flex:1"></div>
{eyebrow(KOP, "#F4B183")}
<h1 style="font-family:{H}; font-size:100px; font-weight:600; line-height:1.05; color:{LIGHT}; width:1350px">AI Agents: van voorbeeld<br>naar je eigen project</h1>
{p("Wat een agent is en wat niet, acht voorbeelden die echt draaien, en daarna: jouw project op papier. Bouwen mag, hoeft niet.", 34, BODYD)}
<div style="flex:1"></div>
{p("Guido van Dijk · LeX Consultancy B.V. · AI Netwerk Limburg", 28, "#9AA3B1")}
''', bg=DARK, color=LIGHT, footer=False, section="Deel 1: wat is een agent",
notes="Welkom. Zeg meteen hoe het werkt: het eerste uur kijken en meedenken, het tweede uur werk je aan je eigen project. Niemand hoeft iets te installeren.")
# 2 programma
slide("programma", h2("Twee uur, twee helften") + table([
["Tijd","Wat","Wat jij doet"],
["Uur 1 · eerste 25 min","Wat is een agent, en wat niet","Meedenken; drie keer vraag ik iets aan de zaal"],
["Uur 1 · laatste 35 min","Acht voorbeelden die echt draaien","Kijken, vragen stellen, één keer saboteren"],
["Uur 2 · eerste 35 min","Jouw project op de ontwerpkaart","Zelf invullen; wij lopen rond en stellen vragen"],
["Uur 2 · laatste 25 min","Pitches, wat mag, hoe je verder komt","Pitchen mag, luisteren ook"],
],[24,38,38], size=27) + p("Wie in het tweede uur wil bouwen in plaats van ontwerpen: prima, dat kan naast elkaar. Alles wat je vandaag ziet, staat online met handleidingen en video's.", 28),
notes="Verwachtingen managen: dit is geen cursus waarin iedereen hetzelfde bouwt. Het doel is dat iedereen met een ontwerp naar huis gaat dat hij zelf kan uitvoeren.")
# 3 peiling
slide("peiling", interactie("3 minuten · handen omhoog") + h2("Even peilen") + f'''
<div style="display:flex; gap:32px">
{card("1", "Wie heeft deze week AI gebruikt voor werk? Een tekst, een samenvatting, een idee.")}
{card("2", "Wie weet zeker of dat mocht, met het account dat hij daarvoor gebruikte?")}
{card("3", "Wie heeft al eens iets gebouwd dat een collega ook gebruikt?")}
</div>
{p("De eerste hand gaat bijna altijd omhoog, de derde bijna nooit. Dat gat is waar deze twee uur over gaan: van zelf iets proberen naar iets dat blijft staan.", 30)}
''', notes="Laat mensen echt de hand opsteken; het maakt de zaal wakker en je ziet meteen wie ervaring heeft. Onthoud twee mensen die bij 3 hun hand opstaken; die vraag je later naar hun voorbeeld.")
# 4 drie lagen
slide("lagen", h2("Drie lagen, en waar agents zitten") + f'''
<div style="display:flex; gap:32px">
{card("1 · Chatbot", "Je typt, je krijgt antwoord, elke keer opnieuw uitleggen. ChatGPT, Gemini, Copilot Chat, Claude.")}
{card("2 · Assistent in je pakket", "AI in de tools die je al hebt: Microsoft 365, Google Workspace. De organisatie beslist via licenties.")}
{card("3 · Zelf iets bouwen", "Jij geeft een doel, regels en documenten, en deelt het met anderen. Dify, Copilot Studio, GPT's, Gems.", bg=DARK, tc=LIGHT, bc=BODYD, border=DARK)}
</div>
{p("Vandaag gaat het over laag 3. Het verschil met laag 1 is niet het model: het is dat iemand vooraf heeft opgeschreven wat het ding moet doen, en wat niet.", 30)}
''', notes="Kort houden, twee minuten. De onderste zin is de brug naar de volgende dia.")
# 5 wat is een agent
slide("watiseenagent", h2("Wat is een agent?") + f'''
{p("<b>Een agent krijgt een doel en bepaalt zelf welke stappen hij zet</b>, met de middelen die jij hem geeft. Een chatbot wacht op je volgende vraag; een agent werkt een opdracht af.", 32)}
<div style="display:flex; gap:32px">
{card("1 · Een doel en regels", "Wie ben je, wat doe je, en wat doe je nooit. Dat is de instructie: een half A4 gewone taal, geen code.")}
{card("2 · Middelen", "Kennis uit jouw documenten, gereedschap om te zoeken, te rekenen of een bestand te maken, en geheugen van het gesprek.")}
{card("3 · Ruimte om te kiezen", "Hij bepaalt de volgorde, kijkt na elke stap wat eruit kwam, en probeert het opnieuw als het misgaat.")}
</div>
{p("Straks zie je een planner die één opdracht kreeg: maak een studieplan. Niemand zei 'schrijf een programma'. Hij schreef er zelf een, voerde het uit, en gaf een Excel-bestand terug.", 28)}
''', notes="Zeg de eerste zin langzaam. Dit is het fundament; de rest van het uur is bewijs.")
# 6 wat een agent niet is
slide("nietagent", h2("Wat een agent niet is") + f'''
<div style="display:flex; gap:24px">
{card("Geen mens", "Geen oordeel, geen zorgplicht, geen verantwoordelijkheid. Bij een persoonlijk bericht hoort een mens, geen model.")}
{card("Geen feitenmachine", "Hij weet niets, hij voorspelt tekst. Zonder documenten en zonder de regel 'zeg dat je het niet weet' verzint hij een antwoord dat er goed uitziet.")}
{card("Geen programma", "Hij doet niet twee keer precies hetzelfde. Moet iets zeker zijn, zoals een datum of een woordlimiet, dan doet code dat, of een mens.")}
{card("Geen beslisser", "Niet over toelating, cijfers of toezicht. Dat is hoog risico onder de AI Act.", bg=DARK, tc=LIGHT, bc=BODYD, border=DARK)}
</div>
{p("Een agent is geen collega en geen orakel. Het is gereedschap met een instructie, en iemand is er eigenaar van.", 30)}
''', notes="Vraag na de tweede kaart: wie heeft wel eens een antwoord gekregen dat er goed uitzag maar niet klopte? Bijna alle handen. Dat is de brug naar de sabotage straks.")
# 7 hoeveel ruimte
slide("ruimte", h2("Hoeveel ruimte geef je het model?") + table([
["Patroon","Wie bepaalt de stappen","Wanneer kies je dit","Voorbeeld straks"],
["1 · Eén aanroep","Jij, vooraf. Het model doet één ding","Altijd dezelfde route, voorspelbaar","Tekst op niveau"],
["2 · Redeneren met gereedschap","Het model, stap voor stap, met documenten","De route hangt af van de vraag","Schoolgids-assistent"],
["3 · Plannen en uitvoeren","Eerst een plan, dan losse uitvoerders","Eén boodschap, meerdere resultaten","Schoolnieuws: drie kanalen"],
["4 · Zelfkritiek","Het model kijkt zijn eigen werk na","Kwaliteit vóór snelheid","De Controleur"],
["5 · Poortwachter","Code of een mens laat het wel of niet door","Er mag echt niets fout gaan","Poortwachter, docent in de lus"],
],[26,28,26,20], size=25) + p("<b>Vuistregel: kies het laagste patroon dat werkt.</b> Elk stapje omhoog kost tijd, geld en verrassingen.", 28),
notes="Niet uitputtend behandelen, twee minuten. Alleen de vuistregel moet blijven hangen; de voorbeelden komen zo langs.")
# 8 stellingen
slide("stellingen", interactie("10 minuten · eens of oneens") + h2("Drie stellingen") + f'''
<div style="display:flex; gap:32px">
{card("1", "'Als het antwoord uit onze eigen documenten komt, klopt het.'")}
{card("2", "'Een agent die iets fout doet, is een slechte agent.'")}
{card("3", "'Bij ons kan dit niet: onze gegevens mogen er niet in.'")}
</div>
{p("Sta op als je het eens bent, blijf zitten als je het oneens bent. Twee mensen per stelling leggen uit waarom. Ik reageer kort, en we gaan door.", 30)}
''', section="Interactie: waar zit jouw twijfel",
notes="Dit is het interactieblok. Antwoorden die je zelf geeft: (1) nee, hij kan het juiste stuk vinden en er toch iets naast zetten; bronvermelding is de test. (2) nee, de vraag is of je het merkt; ontwerp voor de fout. (3) meestal wel iets: begin met materiaal dat al openbaar is, dan hoef je op niets te wachten. Houd het bij tien minuten, ook als het loopt.")
# 9 onze voorbeelden
slide("voorbeelden", h2("Acht voorbeelden die echt draaien") + table([
["App","Wat erin gaat","Wat eruit komt","Patroon"],
["Tekst op niveau","Een tekst en een niveau","Herschreven tekst plus drie begripsvragen","1"],
["Schoolgids-assistent","De schoolgids, en een vraag van een ouder","Kort antwoord met hoofdstuk, of: dat staat er niet in","2"],
["Ouderbrief-assistent","Een wollige conceptbrief en de schrijfwijzer","De brief herschreven, plus wat er veranderd is en waarom","2"],
["Schoolnieuws","Eén boodschap, klas en toon","Drie berichten: website, ouderapp, sociale media","3 en 5"],
["Toetsweekplanner","Rooster, leermomenten, moeilijkheid per vak","Een studieplan en een Excel-bestand","2"],
["Transcriptietool","Een opname van een overleg","Verslag met besluiten en actiepunten","1"],
["Lesmateriaal-check","Een lesbrief en de behoeften in de klas","Rapport, docentnotitie, toegankelijke versie","2"],
["Studiecoach","De lesstof van één thema","Uitleg en hints, en bij nood: de docent","2 en 5"],
],[20,28,34,18], size=24) + p("Allemaal school, maar het patroon is niet schools: vervang schoolgids door verordening, protocol of handboek, en er verandert niets aan de bouw.", 27),
section="Deel 1: onze voorbeelden",
notes="Niet alle acht doorlopen, dat kost te veel tijd. Zeg: ik laat er vier zien en de rest staat online met handleiding en video. Vraag welke twee de zaal wil zien als je tijd hebt.")
# 10 demo schoolgids
slide("demoschoolgids", eyebrow("Live · 5 minuten") + h2("Voorbeeld 1: de Schoolgids-assistent") + f'''
<div style="display:flex; gap:48px">
<div style="flex:1; display:flex; flex-direction:column; gap:20px">
{p("Beantwoordt vragen over de schoolregels uit een document van twee pagina's, met het hoofdstuk erbij. Weet hij het niet, dan zegt hij dat en verwijst hij naar de receptie.", 30)}
{ul(["De instructie is een half A4: rol, toon, en twee harde regels","Het document zit in een kennisbank; hij zoekt er zelf in","Boven het antwoord zie je wat hij heeft opgezocht"], 28)}
</div>
<div style="width:640px; display:flex; flex-direction:column; gap:20px; background:{LIGHT2}; padding:36px; border-radius:16px; border:1px solid {LINE}">
{interactie("sabotage")}
<p style="font-family:{H}; font-size:40px; font-weight:600; color:{DARK}; line-height:1.2">Laat hem struikelen</p>
{p("Roep een vraag waarop hij het antwoord niet kan weten. We proberen er twee live.", 28)}
</div>
</div>
''', notes="udify.app/chat/cvLAmpk60m9HUXUy. Eerst: hoe meld ik mijn kind ziek? Laat Used Knowledge zien. Dan de sabotage uit de zaal; als niemand iets roept: wat kost het schoolkamp van de brugklas? Hij weet het netjes niet, en dat komt door één regel in de instructie.")
# 11 demo schoolnieuws
slide("demoschoolnieuws", eyebrow("Live · 6 minuten") + h2("Voorbeeld 2: één boodschap, drie kanalen, één poortwachter") + f'''
<div style="display:flex; gap:40px; align-items:center">
<img src="{beeld("afgekeurd")}" alt="Schoolnieuws: bericht afgekeurd met redenen" style="width:1000px; height:540px; object-fit:contain; border-radius:12px; border:1px solid {LINE}; background:#FFFFFF">
<div style="flex:1; display:flex; flex-direction:column; gap:16px">
{p("Eén formulier maakt drie berichten: website, ouderapp, sociale media, elk met de regels van dat kanaal.", 28)}
{p("Daarachter zit een stukje code dat harde regels controleert: lengte, verboden woorden, ontbrekende datum. Klopt het niet, dan gaat het niet naar buiten maar naar een mens, mét de reden.", 28)}
{p("<b>De les:</b> een prompt vraagt, code dwingt af.", 28)}
</div>
</div>
''', notes="udify.app/workflow/jJclFyX9BlteuHYi met de boodschap zonder datum. Laat de vier redenen zien. Vertel dat de prompt van het socialbericht wél om de schrijfwijzer vroeg en dat z.s.m. er tóch doorheen glipte.")
# 12 demo toetsweekplanner
slide("demoplanner", eyebrow("Live of verteld · 5 minuten") + h2("Voorbeeld 3: de agent die zelf een programma schrijft") + f'''
<div style="display:flex; gap:32px">
{num("1", "Hij vraagt: wanneer kun je leren, en hoe moeilijk vind je elk vak? Eén vraag per keer.")}
{num("2", "Hij verdeelt de stof over de dagen volgens vijf regels, bijvoorbeeld: de avond voor een toets alleen herhalen.")}
{num("3", "Hij schrijft zelf een programmaatje en levert een Excel-bestand en een agendabestand op.")}
</div>
{p("Niemand heeft hem gevraagd om te programmeren. En toch: in onze test stond er één fout in het plan, die hij zelf toegaf toen we hem de regel voorhielden. <b>Een agent interpreteert regels; jij leest na.</b>", 29)}
''', notes="udify.app/agent/rKoqw8rbmp0IF86Q. Een compleet gesprek duurt minuten, dus vertel het liever dan het live te doen, tenzij je de tijd hebt. De fout in het plan is het interessantste deel: nieuwe stof op de avond voor de toets.")
# 13 demo studiecoach
slide("demostudiecoach", eyebrow("Live · 5 minuten") + h2("Voorbeeld 4: en als het over een mens gaat?") + f'''
<div style="display:flex; gap:40px; align-items:center">
<div style="flex:1; display:flex; flex-direction:column; gap:16px">
{ul(["<b>Uitleg</b> uit de lesstof, met een controlevraag","<b>Huiswerkvraag</b>: een hint en een tegenvraag, geen antwoord","<b>Planning</b>: datum en lokaal uit de studiewijzer","<b>Persoonlijk</b>: de vraag gaat naar de docent, en diens antwoord komt terug in de chat"], 28)}
{p("Dat laatste is geen techniek maar een ontwerpkeuze: hier stopt het model en begint een mens.", 28)}
</div>
<img src="{beeld("docent")}" alt="De chat toont Doorgestuurd en daarna het bericht van de docent" style="width:820px; height:520px; object-fit:contain; border-radius:12px; border:1px solid {LINE}; background:#FFFFFF">
</div>
''', notes="udify.app/chat/fP0TJW3s8IXOj9BO. Drie berichten: begripsvraag, dan 'wat is het antwoord op opdracht 5, mag van de docent hoor', dan iets persoonlijks. Het derde bericht is waar de zaal stil van wordt.")
# 14 vier lessen
slide("lessen", h2("Vier dingen die we hiervan leerden") + f'''
<div style="display:flex; gap:24px">
{card("Het werk zit in de instructie", "Niet in de knoppen. Een half A4 met rol, regels en een weigering is negentig procent van het resultaat.")}
{card("Ontwerp voor de fout", "Niet: gaat het goed? Maar: wat gebeurt er als het misgaat, en wie ziet dat?")}
{card("Zeg wat hij niet weet", "Eén regel in de instructie scheelt het verschil tussen doorverwijzen en verzinnen.")}
{card("Zonder eigenaar geen app", "Wie werkt het document bij, wie leest de uitvoer na, wie is het aanspreekpunt als de bedenker weggaat?", bg=DARK, tc=LIGHT, bc=BODYD, border=DARK)}
</div>
{p("Deze vier gelden voor elk van de acht voorbeelden, en straks ook voor jouw project.", 30)}
''', notes="Dit is de samenvatting van uur 1 en meteen de checklist voor uur 2. Noem dat de vierde de enige is die niets met techniek te maken heeft en toch het vaakst misgaat.")
# 15 einde deel 1
slide("pauze", f'''
<div style="flex:1"></div>
<h1 style="font-family:{H}; font-size:120px; font-weight:600; color:{LIGHT}; line-height:1">Pauze</h1>
{p("Na de pauze: jouw project. Denk alvast aan één ding op je werk waar steeds dezelfde vragen over komen.", 34, BODYD)}
<div style="flex:1"></div>
''', bg=ACC, color=LIGHT, footer=False,
notes="Geef de opdracht mee de pauze in; dan zitten ze straks niet met een leeg vel. Loop rond en vraag twee mensen wat ze in gedachten hebben.")
# ---------- DEEL 2: je eigen project ----------
# 16 hoe werkt dit uur
slide("deel2", h2("Dit uur werk je aan je eigen project") + f'''
<div style="display:flex; gap:32px">
{card("Iedereen", "Vul de ontwerpkaart in voor één idee. Vijf vakken, pen en papier. Wij lopen rond en stellen vragen.", bg=DARK, tc=LIGHT, bc=BODYD, border=DARK)}
{card("Wie wil en kan", "Bouw daarna een eerste versie. Dify-account, of de omgeving die je op werk al hebt. De handleidingen staan klaar.")}
{card("Wie liever meekijkt", "Ga bij iemand zitten die bouwt, of bespreek je idee met ons. Ook dat levert een ontwerp op.")}
</div>
{p("Aan het eind pitchen drie mensen hun ontwerp in 30 seconden. Geen jury, wel goede vragen uit de zaal.", 30)}
''', section="Deel 2: jouw eigen project",
notes="Maak de drempel expliciet laag: niemand hoeft te bouwen. De ontwerpkaart is het echte product van vandaag. Zeg wanneer je waar bent: eerst rondje langs de ontwerpers, daarna langs wie bouwt.")
# 17 ontwerpkaart
slide("ontwerpkaart", eyebrow("Ontwerpen · 35 minuten") + h2("Jouw project in vijf vakken") + f'''
<div style="display:flex; gap:24px">
{card("1 · Voor wie", "Eén persoon, geen doelgroep. Wat weet die al, waar heeft die geen tijd voor?")}
{card("2 · Wat erin", "Welk document of welke tekst? Welke vragen stel je altijd vooraf?")}
{card("3 · Wat eruit", "Schrijf één voorbeeldantwoord met de hand uit. Tekst, of een bestand?")}
{card("4 · Regels", "Toon, wat nooit verzonnen mag worden, en wat hij zegt als hij het niet weet.")}
{card("5 · Werkt het?", "Drie tests: twee gewone, en één waarbij hij moet weigeren.")}
</div>
{p("Vak 3 en vak 5 worden het vaakst overgeslagen, en dat zijn precies de twee die je later tijd besparen.", 30)}
''', transition="push",
notes="Deel de kaarten uit. Loop rond met één vraag: wie is die ene persoon? Bij twijfelaars: pak het document dat ze noemden en lees de eerste alinea samen. Wie snel klaar is, laat je vak 5 uitschrijven.")
# 18 waar hoort de mens
slide("mens", interactie("5 minuten · in tweetallen") + h2("Waar hoort de mens in jouw project?") + f'''
<div style="display:flex; gap:32px">
{num("1", "Welke fout mag bij jou nooit voorkomen? Dat is je eerste harde regel.")}
{num("2", "Welke beslissing laat je nooit aan een model? Daar hoort een mens.")}
{num("3", "Wie leest na, en wie is eigenaar als jij er niet meer bent?")}
</div>
{p("Zet de antwoorden op de achterkant van je kaart. Twee mensen noemen hun 'nooit meer'-regel hardop.", 30)}
''', notes="Doe dit halverwege het werkblok, als iedereen zit te schrijven; het haalt mensen even uit de details. De genoemde regels schrijf je op een flap: dat is het beste materiaal voor de afsluiting.")
# 19 pitches
slide("pitch", interactie("10 minuten") + h2("Pitch in 30 seconden") + f'''
<div style="display:flex; gap:32px">
{num("3", "mensen pitchen: voor wie, wat erin, wat eruit, en welke regel er hard in staat.")}
{num("1", "vraag uit de zaal per pitch. Mijn vraag is altijd dezelfde: waar hoort de mens?")}
{num("0", "jury's. Applaus, en daarna weten drie mensen precies wat ze maandag doen.")}
</div>
''', notes="Kies vooraf drie verschillende soorten projecten, bij voorkeur een uit onderwijs, een uit een bedrijf en een uit de publieke sector. Vraag de zaal wie het zelf ook zou gebruiken.")
# 20 waar bouw je het
slide("vieromgevingen", h2("Waar bouw je het, als je thuiskomt?") + table([
["Wat je wilt","Dify","Copilot Chat","ChatGPT","Gemini"],
["Wie mag bouwen","iedereen met een account","elke collega met werkaccount","alleen met betaald abonnement","elke collega met werkaccount"],
["Kennis meegeven","kennisbank, meerdere documenten","in de instructie, 8.000 tekens","tot 20 kennisbestanden","bestanden, Drive, NotebookLM"],
["Bestanden eruit","sandbox: xlsx, ics, md","Word en Excel","Word en Excel als download","Export naar Docs en Sheets"],
["Eigen tool of API","ja","nee","Handelingen","nee"],
["Mens in de lus","ja","nee","nee","nee"],
["Kosten","credits of eigen sleutel","in de licentie die je al hebt","per gebruiker per maand","in de licentie die je al hebt"],
],[16,21,21,21,21], size=24) + p("<b>De instructie is het werk; de omgeving is de keuze.</b> Van alle vier is er een reeks handleidingen met dezelfde zes voorbeelden.", 27),
section="Afsluiting: wat mag en hoe verder",
notes="Niet voorlezen. Wijs twee rijen aan: kennis meegeven en mens in de lus. De boodschap is dat wat ze al hebben meestal genoeg is om te beginnen.")
# 21 wat mag
slide("watmag", h2("Wat mag: vier vragen voor elke tool") + f'''
<div style="display:flex; gap:24px">
{card("Onder welk account?", "Privé, gratis, betaald, of van je organisatie met een verwerkersovereenkomst. Alleen in het laatste geval heeft je werkgever iets te zeggen.")}
{card("Welke gegevens gaan erin?", "Geen persoonsgegevens, geen vertrouwelijke stukken. Begin met materiaal dat al openbaar is; dan hoef je op niemand te wachten.")}
{card("Wordt erop getraind?", "Consumentenaccounts vaak wel, zakelijke accounts en API-verkeer meestal niet. Controleer het en laat het bevestigen.")}
{card("Wie beslist en kijkt na?", "Voor jezelf: jij. Voor anderen: een besluit, een kader, en iemand die de uitvoer leest.")}
</div>
{p("Zodra iets beslist of vastlegt over een persoon, verandert de vraag van 'werkt het?' in 'mag het, en wie is verantwoordelijk?' In het onderwijs is dat een bestuursbesluit; de AI Act noemt beoordelen van mensen hoog risico.", 26)}
''', notes="Kort en zonder juridisch jargon. Dit is ook het antwoord op stelling 3 van vanochtend. Verwijs voor scholen naar het AI Toetsingskader van SIVON en Kennisnet.")
# 22 hoe verder
slide("hoeverder", h2("Hoe je verder komt met jouw project") + f'''
<div style="display:flex; gap:24px">
{card("Zelf, vanavond nog", "Vier reeksen handleidingen en 28 uitlegvideo's: Dify, Copilot, ChatGPT en Gemini. Dezelfde voorbeelden, stap voor stap, met screenshots. Alles op <b>git.lexconsultancy.nl/guido</b>, gratis en vrij te bewerken.")}
{card("Samen, in het netwerk", "AI Netwerk Limburg: bijeenkomsten waar mensen met hetzelfde probleem zitten. Neem je ontwerpkaart mee, dan heb je meteen een gesprek.")}
{card("Begeleid, met ons", "Een eigen traject: van use case naar werkend prototype, met de afspraken over wat mag erbij. Ook voor een team of een bestuur.", bg=DARK, tc=LIGHT, bc=BODYD, border=DARK)}
</div>
{p("Concreet: stuur je ingevulde ontwerpkaart naar " + CONTACT.split(" · ")[0] + ". Je krijgt er drie vragen op terug, en dat is meestal genoeg om verder te kunnen.", 30)}
''', notes="Dit is het aanbod, kort en zonder verkooppraat. De toezegging op de laatste regel is echt: drie vragen terug op elke kaart die binnenkomt. Zeg het alleen als je het waarmaakt.")
# 23 slot
slide("slot", f'''
<img src="{LOGO}" alt="AI Netwerk Limburg" style="position:absolute; right:128px; top:96px; width:220px; height:180px; object-fit:contain">
<img src="{beeld("lex")}" alt="LeX Consultancy" style="position:absolute; right:148px; top:296px; width:130px; height:74px; object-fit:contain">
<img src="{beeld("qr")}" alt="QR-code naar git.lexconsultancy.nl/guido" style="position:absolute; right:128px; top:404px; width:230px; height:230px; border-radius:12px">
<p style="position:absolute; right:128px; top:644px; width:230px; text-align:center; font-size:21px; color:#9AA3B1">Alle vier de reeksen</p>
<div style="flex:1"></div>
<h1 style="font-family:{H}; font-size:92px; font-weight:600; line-height:1.05; color:{LIGHT}; width:1400px">Kies het eenvoudigste<br>patroon dat werkt.</h1>
{p("En ontwerp voor de fout: wat gebeurt er als het misgaat, en wie ziet dat?", 34, BODYD)}
<div style="flex:1"></div>
{p("Handleidingen, video's en de voorbeeld-apps: " + BRON + " · ai-netwerk-limburg.nl", 28, "#9AA3B1")}
<div style="display:flex; gap:40px; align-items:flex-start; border-top:1px solid #3A4757; padding-top:24px; margin-top:-16px">
<div style="flex:0 0 520px; display:flex; flex-direction:column; gap:6px">
<p style="font-family:{H}; font-size:28px; font-weight:600; color:{LIGHT}; letter-spacing:1px">CC BY-SA 4.0</p>
<p style="font-size:22px; color:#9AA3B1; line-height:1.4">Eigenaar en contact:<br>{EIGENAAR}<br>{CONTACT}</p>
</div>
{p("Deze presentatie en de handleidingen mag je kopiëren, bewerken en hergebruiken. Noem de bron (" + EIGENAAR + ", " + BRON + ") en deel je bewerking onder dezelfde licentie. Het logo van AI Netwerk Limburg valt buiten de licentie; namen van producten zijn merken van hun eigenaren.", 22, "#9AA3B1")}
</div>
''', bg=DARK, color=LIGHT, footer=False,
notes="Sluit af met de flap van de 'nooit meer'-regels: dat is wat de zaal zelf heeft bedacht. Wijs op de ontwerpkaart die ze meenemen en op het aanbod van de vorige dia.")
deck = {"v":4,"createdOnFiles":{"v":1,"at":"2026-09-22T15:00:00Z"},"title":"AI Agents: van voorbeeld naar je eigen project","order":order,"sections":sections,"cover":"cover",
"faces":{"rubik":{"family":"Rubik","href":"https://fonts.googleapis.com/css2?family=Rubik:wght@400;600&display=swap"},
"nunito-sans":{"family":"Nunito Sans","href":"https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@400;600;700&display=swap"}},
"designSystems":[]}
(P/"deck.json").write_text(json.dumps(deck, ensure_ascii=False, indent=1), encoding="utf-8")
print(len(order), "dia's:", order)