diff --git a/00-ai-tools/ai-tools-in-het-onderwijs.pdf b/00-ai-tools/ai-tools-in-het-onderwijs.pdf index babccf5..6b42181 100644 Binary files a/00-ai-tools/ai-tools-in-het-onderwijs.pdf and b/00-ai-tools/ai-tools-in-het-onderwijs.pdf differ diff --git a/00-ontwerpkaart/ontwerpkaart.pdf b/00-ontwerpkaart/ontwerpkaart.pdf index a93a005..6e04434 100644 Binary files a/00-ontwerpkaart/ontwerpkaart.pdf and b/00-ontwerpkaart/ontwerpkaart.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-01-tekst-op-niveau.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-01-tekst-op-niveau.pdf index 29d6fb9..d4d1c4a 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-01-tekst-op-niveau.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-01-tekst-op-niveau.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-02-schoolgids-assistent.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-02-schoolgids-assistent.pdf index 25e8fa7..2cf51e0 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-02-schoolgids-assistent.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-02-schoolgids-assistent.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-03-ouderbrief-assistent.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-03-ouderbrief-assistent.pdf index 75ec161..faa5979 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-03-ouderbrief-assistent.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-03-ouderbrief-assistent.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-04-toetsweekplanner.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-04-toetsweekplanner.pdf index 6637802..08b83e4 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-04-toetsweekplanner.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-04-toetsweekplanner.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-05-transcriptietool.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-05-transcriptietool.pdf index 20362a1..0a138e1 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-05-transcriptietool.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-05-transcriptietool.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-06-lesmateriaal-check.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-06-lesmateriaal-check.pdf index b8c8ce8..64be9aa 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-06-lesmateriaal-check.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-06-lesmateriaal-check.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-07-schoolnieuws-met-controle.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-07-schoolnieuws-met-controle.pdf index a43e245..16ce478 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-07-schoolnieuws-met-controle.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-07-schoolnieuws-met-controle.pdf differ diff --git a/00-ontwerpkaart/voorbeelden/ontwerpkaart-08-studiecoach-biologie.pdf b/00-ontwerpkaart/voorbeelden/ontwerpkaart-08-studiecoach-biologie.pdf index 9cfd42c..27dc175 100644 Binary files a/00-ontwerpkaart/voorbeelden/ontwerpkaart-08-studiecoach-biologie.pdf and b/00-ontwerpkaart/voorbeelden/ontwerpkaart-08-studiecoach-biologie.pdf differ diff --git a/00-ontwerppatronen/ontwerppatronen-voor-agents.pdf b/00-ontwerppatronen/ontwerppatronen-voor-agents.pdf index 056fe9d..3f58bce 100644 Binary files a/00-ontwerppatronen/ontwerppatronen-voor-agents.pdf and b/00-ontwerppatronen/ontwerppatronen-voor-agents.pdf differ diff --git a/00-presentatie/presentatie-workshop-ai-agents.pdf b/00-presentatie/presentatie-workshop-ai-agents.pdf index 137ef59..953f4be 100644 Binary files a/00-presentatie/presentatie-workshop-ai-agents.pdf and b/00-presentatie/presentatie-workshop-ai-agents.pdf differ diff --git a/00-workshop/draaiboek-workshop.pdf b/00-workshop/draaiboek-workshop.pdf index 6154281..151fb6a 100644 Binary files a/00-workshop/draaiboek-workshop.pdf and b/00-workshop/draaiboek-workshop.pdf differ diff --git a/01-workflow/handleiding-dify.pdf b/01-workflow/handleiding-dify.pdf index 42bd59e..1492897 100644 Binary files a/01-workflow/handleiding-dify.pdf and b/01-workflow/handleiding-dify.pdf differ diff --git a/02-agent-kennisbank/handleiding-dify-agent.pdf b/02-agent-kennisbank/handleiding-dify-agent.pdf index f1f8c00..ea2e270 100644 Binary files a/02-agent-kennisbank/handleiding-dify-agent.pdf and b/02-agent-kennisbank/handleiding-dify-agent.pdf differ diff --git a/03-schoolcommunicatie/handleiding-dify-schoolcommunicatie.pdf b/03-schoolcommunicatie/handleiding-dify-schoolcommunicatie.pdf index 7d900b7..552532f 100644 Binary files a/03-schoolcommunicatie/handleiding-dify-schoolcommunicatie.pdf and b/03-schoolcommunicatie/handleiding-dify-schoolcommunicatie.pdf differ diff --git a/04-agent-console/handleiding-dify-agent-console.pdf b/04-agent-console/handleiding-dify-agent-console.pdf index f4ccfd5..5e6785d 100644 Binary files a/04-agent-console/handleiding-dify-agent-console.pdf and b/04-agent-console/handleiding-dify-agent-console.pdf differ diff --git a/05-transcriptietool/handleiding-dify-transcriptietool.pdf b/05-transcriptietool/handleiding-dify-transcriptietool.pdf index e4e3119..97e95ab 100644 Binary files a/05-transcriptietool/handleiding-dify-transcriptietool.pdf and b/05-transcriptietool/handleiding-dify-transcriptietool.pdf differ diff --git a/05-transcriptietool/maak_opname_drie_stemmen.py b/05-transcriptietool/maak_opname_drie_stemmen.py new file mode 100644 index 0000000..5dbf271 --- /dev/null +++ b/05-transcriptietool/maak_opname_drie_stemmen.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Maakt van sectieoverleg-script.txt een testopname met drie verschillende computerstemmen, +zodat de sprekerherkenning (gpt-4o-transcribe-diarize) iets te onderscheiden heeft. + +Gebruik: OPENAI_API_KEY=sk-... python3 maak_opname_drie_stemmen.py +Vereist: ffmpeg (aanwezig) en een OpenAI-sleutel in de omgevingsvariabele; de sleutel wordt + nergens opgeslagen. Kosten: circa 4.000 tekens bij tts-1, ongeveer 6 cent. + +Uitvoer: sectieoverleg-drie-stemmen.mp3 (128 kbps, om te beluisteren) + sectieoverleg-drie-stemmen-klein.mp3 (32 kbps mono, onder de 5 MB-grens van de tool) +""" +import json +import os +import re +import subprocess +import sys +import tempfile +import urllib.request +from pathlib import Path + +HERE = Path(__file__).resolve().parent +SCRIPT = HERE / "sectieoverleg-script.txt" +STEMMEN = {"Karin": "nova", "Bram": "echo", "Fatima": "alloy"} # drie duidelijk verschillende stemmen +VERTELLER = "onyx" # voor de openingsregel + +key = os.environ.get("OPENAI_API_KEY") +if not key: + sys.exit("Zet de sleutel in de omgevingsvariabele OPENAI_API_KEY en start opnieuw.") + + +def spreek(tekst: str, stem: str, doel: Path) -> None: + req = urllib.request.Request( + "https://api.openai.com/v1/audio/speech", + data=json.dumps({"model": "tts-1", "voice": stem, "input": tekst, "response_format": "mp3"}).encode(), + headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"}, + ) + with urllib.request.urlopen(req, timeout=120) as r: + doel.write_bytes(r.read()) + + +regels = [r.strip() for r in SCRIPT.read_text(encoding="utf-8").splitlines() if r.strip()] +with tempfile.TemporaryDirectory() as tmp: + tmp = Path(tmp) + delen = [] + for i, regel in enumerate(regels): + m = re.match(r"^(Karin|Bram|Fatima):\s*(.+)$", regel) + if m: + stem, tekst = STEMMEN[m.group(1)], m.group(2) + else: + stem, tekst = VERTELLER, regel + deel = tmp / f"{i:03d}.mp3" + spreek(tekst, stem, deel) + delen.append(deel) + print(f"{i + 1}/{len(regels)} {stem}: {tekst[:50]}...") + lijst = tmp / "lijst.txt" + lijst.write_text("".join(f"file '{d}'\n" for d in delen)) + # Korte stilte tussen sprekers komt vanzelf door de pauze aan het eind van elke zin. + subprocess.run(["ffmpeg", "-y", "-loglevel", "error", "-f", "concat", "-safe", "0", "-i", str(lijst), + "-c:a", "libmp3lame", "-b:a", "128k", str(HERE / "sectieoverleg-drie-stemmen.mp3")], check=True) + subprocess.run(["ffmpeg", "-y", "-loglevel", "error", "-i", str(HERE / "sectieoverleg-drie-stemmen.mp3"), + "-ac", "1", "-ar", "16000", "-b:a", "32k", str(HERE / "sectieoverleg-drie-stemmen-klein.mp3")], check=True) +for naam in ("sectieoverleg-drie-stemmen.mp3", "sectieoverleg-drie-stemmen-klein.mp3"): + p = HERE / naam + print(f"{naam}: {p.stat().st_size // 1024} kB") diff --git a/06-inclusief-lesmateriaal/handleiding-dify-lesmateriaal-check.pdf b/06-inclusief-lesmateriaal/handleiding-dify-lesmateriaal-check.pdf index c9e3e16..820fc6a 100644 Binary files a/06-inclusief-lesmateriaal/handleiding-dify-lesmateriaal-check.pdf and b/06-inclusief-lesmateriaal/handleiding-dify-lesmateriaal-check.pdf differ diff --git a/07-schoolnieuws-met-controle/handleiding-dify-schoolnieuws-met-controle.pdf b/07-schoolnieuws-met-controle/handleiding-dify-schoolnieuws-met-controle.pdf index d076530..41dbb62 100644 Binary files a/07-schoolnieuws-met-controle/handleiding-dify-schoolnieuws-met-controle.pdf and b/07-schoolnieuws-met-controle/handleiding-dify-schoolnieuws-met-controle.pdf differ diff --git a/08-chatflow-studiecoach/handleiding-dify-studiecoach.pdf b/08-chatflow-studiecoach/handleiding-dify-studiecoach.pdf index 63c16c2..2a65f31 100644 Binary files a/08-chatflow-studiecoach/handleiding-dify-studiecoach.pdf and b/08-chatflow-studiecoach/handleiding-dify-studiecoach.pdf differ diff --git a/LICENSE.md b/LICENSE.md index 5abc6dc..3893fc7 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -38,10 +38,10 @@ de handleidingen vallen onder de MIT-licentie: ## Uitzonderingen - Het logo van AI Netwerk Limburg (`_gereedschap/logo-ai-netwerk-limburg.png` en de kopie in - `00-presentatie/beelden/`) en het logo van LeX Consultancy (`00-presentatie/beelden/logo-lex*.png`) - zijn merken en vallen niet onder deze licentie. Wie de + `00-presentatie/beelden/`) en het logo van LeX Consultancy (`_gereedschap/logo-lex.png`, + `00-presentatie/beelden/logo-lex*.png`) zijn merken en vallen niet onder deze licentie. Wie de handleidingen of dia's bewerkt, vervangt het logo door het eigen logo of laat het weg - (`build_handleiding.py` en `maak_dias.py` verwachten een PNG op dat pad). + (`build_handleiding.py` en `maak_dias.py` verwachten PNG's op die paden). - `08-chatflow-studiecoach/stercollectie-voedselweb-hv3.pdf` en de kopie in `06-inclusief-lesmateriaal/` zijn van VO-content (Stercollecties, https://maken.wikiwijs.nl/157495), CC BY-SA 4.0. De bronvermelding van VO-content blijft staan. diff --git a/README.md b/README.md index b0fd2ef..6a95a5c 100644 --- a/README.md +++ b/README.md @@ -73,5 +73,5 @@ De PDF's staan naast de bronnen in git; HTML en Word maak je zelf met build.py. Opmaak in de bronnen: genummerde lijst = handelingen, tabel "Wat je intypt" = veldwaarden, codeblok = letterlijk overtypen (label "Intypen"), oranje kader = valkuil, groen kader = "Zelf kiezen" -(blockquote die met **Zelf kiezen** begint). Opmaak en logo staan in `_gereedschap/build_handleiding.py`; -vervang het logo door dat van je eigen school of netwerk. +(blockquote die met **Zelf kiezen** begint). Opmaak en logo's staan in `_gereedschap/build_handleiding.py`; +vervang de logo's door die van je eigen school of netwerk. diff --git a/_gereedschap/build_handleiding.py b/_gereedschap/build_handleiding.py index 20886e0..8a17027 100644 --- a/_gereedschap/build_handleiding.py +++ b/_gereedschap/build_handleiding.py @@ -18,6 +18,7 @@ import markdown TOOLS = Path(__file__).resolve().parent LOGO = TOOLS / "logo-ai-netwerk-limburg.png" +LOGO_LEX = TOOLS / "logo-lex.png" # kleiner, naast het LAI-logo # Licentie en contact, komen als colofon onderaan elk document (HTML, PDF en Word). EIGENAAR = "Guido van Dijk, LeX Consultancy B.V. en AI Netwerk Limburg" @@ -33,7 +34,9 @@ body { font-family: "Noto Sans", "DejaVu Sans", Arial, sans-serif; color: #1a1a1 .kop { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5em; margin-bottom: 1em; } .kop-tekst { flex: 1 1 auto; } -.kop img { flex: 0 0 auto; width: 3.4cm; height: auto; } +.kop .logos { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: .3em; } +.kop img { width: 3.4cm; height: auto; } +.kop img.lex { width: 2cm; } h1 { font-size: 22pt; margin: 0 0 .3em; line-height: 1.2; } h2 { font-size: 15pt; margin: 1.6em 0 .5em; padding-top: .3em; border-top: 2px solid #1d4ed8; page-break-after: avoid; break-after: avoid; } @@ -73,6 +76,7 @@ ol li { margin: .25em 0; } .voet { margin-top: 3em; padding-top: .6em; border-top: 1px solid #ddd; font-size: .85em; color: #555; display: flex; align-items: center; gap: .8em; } .voet img { width: 1.6cm; height: auto; } +.voet img.lex { width: 1.1cm; } """ @@ -85,16 +89,16 @@ def read_source(src: Path) -> str: return re.sub(r"(\n> [^\n]*\n)\n(?=> )", r"\1\n\n\n", text) -def logo_src(embed: bool) -> str: +def logo_src(embed: bool, pad: Path = LOGO) -> str: if embed: - return "data:image/png;base64," + base64.b64encode(LOGO.read_bytes()).decode() - return LOGO.as_uri() + return "data:image/png;base64," + base64.b64encode(pad.read_bytes()).decode() + return pad.as_uri() COMPACT_CSS = """ html { font-size: 9.2pt; } h1 { font-size: 17pt; } h2 { margin-top: 1em; } @page { margin: 1.5cm 2cm 1.5cm 2cm; } p { margin: .35em 0; } table { margin: .5em 0; } th, td { padding: .25em .5em; } -.colofon { margin-top: .5em; padding: .3em .5em; font-size: .75em; border: 0; border-top: 1px solid #ddd; border-radius: 0; background: none; } .voet { margin-top: .6em; } .voet img { width: 1.1cm; } .kop img { width: 2.8cm; } ul, ol { margin: .3em 0 .3em 1.3em; } +.colofon { margin-top: .5em; padding: .3em .5em; font-size: .75em; border: 0; border-top: 1px solid #ddd; border-radius: 0; background: none; } .voet { margin-top: .6em; } .voet img { width: 1.1cm; } .voet img.lex { width: .8cm; } .kop img { width: 2.8cm; } .kop img.lex { width: 1.6cm; } ul, ol { margin: .3em 0 .3em 1.3em; } """ @@ -102,6 +106,7 @@ def to_html(md_text: str, here: Path, embed_images: bool, compact: bool = False) body = markdown.markdown(md_text, extensions=["tables", "sane_lists", "smarty", "fenced_code"]) title = re.search(r"
| {m.group(1)} | ' f''
- f' |
.*?
)", lambda m: (f'