From faecdd96dc23b4d1497e22ab00210450698844e2 Mon Sep 17 00:00:00 2001 From: dev Date: Sat, 17 Oct 2026 14:36:26 +0000 Subject: [PATCH] initial --- .gitignore | 1 + .vscode/settings.json | 4 + Makefile | 14 ++++ assets/example.svg | 6 ++ diagrams.typ | 155 ++++++++++++++++++++++++++++++++++++++ presentation01.typ | 34 +++++++++ references.bib | 0 shell.nix | 8 ++ template.typ | 170 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 392 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Makefile create mode 100644 assets/example.svg create mode 100644 diagrams.typ create mode 100644 presentation01.typ create mode 100644 references.bib create mode 100644 shell.nix create mode 100644 template.typ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a136337 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pdf diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..cb01807 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "tinymist.serverPath": "/nix/store/svghwcmy5qbhf3flz0g09m9i1llfm0m5-tinymist-0.15.8/bin/tinymist", + +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be6b35a --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +TYPST := typst + +SRC := $(filter-out template.typ,$(wildcard *.typ)) +PDF := $(SRC:.typ=.pdf) + +.PHONY: all clean + +all: $(PDF) + +%.pdf: %.typ template.typ references.bib + $(TYPST) compile $< $@ + +clean: + rm -f $(PDF) diff --git a/assets/example.svg b/assets/example.svg new file mode 100644 index 0000000..1d404ad --- /dev/null +++ b/assets/example.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/diagrams.typ b/diagrams.typ new file mode 100644 index 0000000..873fa7a --- /dev/null +++ b/diagrams.typ @@ -0,0 +1,155 @@ +#let accent = rgb("#22617f") +#let ember = rgb("#a85430") +#let paper = rgb("#faf8f3") + +#let _row(label, frac, pct, color) = grid( + columns: (86pt, 1fr, 36pt), + column-gutter: 5pt, + align(right + horizon, text(size: 10pt)[#label]), + place(left + horizon, place(left + horizon, rect(width: 100%, height: 7pt, fill: luma(242), radius: 1.5pt)) + place(left + horizon, rect(width: frac * 100%, height: 7pt, fill: color, radius: 1.5pt))), + align(right + horizon, text(size: 9.5pt, fill: luma(110))[#pct]), +) + +#let next-token-chart() = block(width: 100%, { + box(width: 100%, stroke: 0.8pt + accent.lighten(30%), fill: accent.lighten(94%), radius: 3pt, inset: (x: 8pt, y: 4pt), align(left, text(size: 11.5pt)[„Der Himmel über der Stadt ist …“])) + v(5pt) + _row("blau", 0.58, "58 %", accent) + v(2.5pt) + _row("bedeckt", 0.17, "17 %", accent.lighten(35%)) + v(2.5pt) + _row("dunkel", 0.09, "9 %", accent.lighten(52%)) + v(2.5pt) + _row("grau", 0.07, "7 %", accent.lighten(62%)) + v(2.5pt) + _row("…", 0.09, "9 %", luma(224)) +}) + +#let _pipebox(title, ..lines, highlight: false, dashed: false) = block( + width: 100%, + stroke: ( + paint: if highlight { accent } else { luma(205) }, + thickness: if highlight { 1.1pt } else { 0.6pt }, + dash: if dashed { "dashed" }, + ), + fill: if highlight { accent.lighten(94%) } else { paper }, + radius: 3pt, + inset: (x: 5pt, y: 6pt), + align(center)[ + #text(size: 10pt, weight: "bold")[#title] + #v(2pt) + #for l in lines.pos() [ #text(size: 8.5pt, fill: luma(110))[#l] #v(1pt) ] + ], +) + +#let training-pipeline() = grid( + columns: (1fr, 11pt, 1fr, 11pt, 1fr, 11pt, 1fr, 11pt, 1fr), + align(horizon, _pipebox("Rohdaten", "")), + align(horizon, text(fill: accent)[→]), + _pipebox("Pretraining", "Nächstes Token", "Tausende GPUs", "Wochen–Monate", highlight: true), + align(horizon, text(fill: accent)[→]), + align(horizon, _pipebox("Basismodell", "reiner Text-", "vervollständiger", dashed: true)), + align(horizon, text(fill: accent)[→]), + align(horizon, _pipebox("Fine-Tuning", "SFT: Dialoge", "RLHF: Präferenzen")), + align(horizon, text(fill: accent)[→]), + align(horizon, _pipebox("Assistent", "Chat · API · Agents")), +) + +#let _edot(x, y, c) = place(top + left, dx: x - 2.4pt, dy: y - 2.4pt, circle(radius: 2.4pt, fill: c)) + +#let _head(x, y, ang, color) = { + let c = calc.cos(ang) + let s = calc.sin(ang) + let bx = x - 6.5pt * c + let by = y - 6.5pt * s + place(top + left, dx: 0pt, dy: 0pt, polygon( + (x, y), + (bx - 2.6pt * s, by + 2.6pt * c), + (bx + 2.6pt * s, by - 2.6pt * c), + fill: color, + )) +} + +#let _elabel-c(x, y, body) = place(top, dx: x - 35pt, dy: y, box(width: 70pt, align(center, text(size: 10.5pt, fill: luma(70))[#body]))) + +#let embedding-plot() = align(center, block(width: 330pt, height: 122pt, { + place(top + left, dx: 56pt, dy: 16pt, line(angle: 90deg, length: 76pt, stroke: 0.7pt + luma(175))) + place(top + left, dx: 56pt, dy: 92pt, line(angle: 0deg, length: 250pt, stroke: 0.7pt + luma(175))) + _head(56pt, 16pt, -90deg, luma(175)) + _head(306pt, 92pt, 0deg, luma(175)) + place(top + left, dx: -6pt, dy: 46pt, rotate(-90deg, text(size: 9pt, fill: luma(140))[einfach → königlich])) + place(top, dx: 56pt, dy: 101pt, box(width: 250pt, align(center, text(size: 9pt, fill: luma(140))[männlich → weiblich]))) + place(top, dx: 46pt, dy: -3pt, box(width: 270pt, align(center, text(size: 12pt, weight: "bold")[König − Mann + Frau ≈ Königin]))) + place(top + left, dx: 106pt, dy: 78pt, line(angle: 0deg, length: 94pt, stroke: (paint: luma(160), thickness: 0.8pt, dash: "dashed"))) + place(top + left, dx: 106pt, dy: 78pt, line(angle: -81.3deg, length: 47pt, stroke: 1.1pt + accent)) + place(top + left, dx: 206pt, dy: 78pt, line(angle: -81.3deg, length: 47pt, stroke: 1.1pt + accent)) + _head(200pt, 78pt, 0deg, luma(160)) + _head(113.2pt, 31.6pt, -81.3deg, accent) + _head(213.2pt, 31.6pt, -81.3deg, accent) + place(top, dx: 46pt, dy: 47pt, box(width: 58pt, align(right, text(size: 9pt, fill: accent)[König − Mann]))) + place(top, dx: 111pt, dy: 60pt, box(width: 90pt, align(center, text(size: 9pt, fill: luma(130))[Frau − Mann]))) + place(top, dx: 223pt, dy: 47pt, box(width: 82pt, align(left, text(size: 9pt, fill: accent)[≈ gleicher Vektor]))) + _edot(106pt, 78pt, luma(85)) + _edot(206pt, 78pt, luma(85)) + _edot(114pt, 26pt, accent) + _edot(214pt, 26pt, accent) + _elabel-c(106pt, 84pt, [Mann]) + _elabel-c(206pt, 84pt, [Frau]) + place(top, dx: 48pt, dy: 20pt, box(width: 60pt, align(right, text(size: 10.5pt, fill: luma(70))[König]))) + place(top, dx: 222pt, dy: 20pt, box(width: 66pt, align(left, text(size: 10.5pt, fill: luma(70))[Königin]))) +})) + +#let _tl-fx(y) = 22pt + (y - 2023.0) / 2.72 * 378pt + +#let _tl-ev(yr, above, lvl, label, w: 95pt) = ( + x: _tl-fx(yr), + dy: if above { 17pt - lvl * 17pt } else { 55pt + lvl * 17pt }, + label: label, + w: w, +) + +#let _tl-lane(events, color, title) = block(width: 100%, height: 98pt, { + for yr in (2023, 2024, 2025) { + place(top + left, dx: _tl-fx(yr), dy: 2pt, line(angle: 90deg, length: 94pt, stroke: 0.4pt + luma(235))) + } + place(horizon + left, line(length: 100%, stroke: 0.8pt + luma(205))) + place(top + left, dx: 2pt, dy: 0pt, text(size: 10pt, weight: "bold", fill: color)[#title]) + for e in events { + place(top + left, dx: e.x - e.w / 2, dy: e.dy, box(width: e.w, align(center, text(size: 9.5pt, fill: luma(70))[#e.label]))) + } + for e in events { + place(top + left, dx: e.x - 2.2pt, dy: 46.8pt, circle(radius: 2.2pt, fill: color)) + } +}) + +#let _tl-years() = block(width: 100%, height: 14pt, { + for (yr, name) in ((2023, [2023]), (2024, [2024]), (2025, [2025])) { + place(top, dx: _tl-fx(yr) - 25pt, box(width: 50pt, align(center, text(size: 8.5pt, fill: luma(140), font: "DejaVu Sans Mono")[#name]))) + } +}) + +#let two-llm-timeline() = block(width: 100%, { + _tl-lane(( + _tl-ev(2023.21, true, 0, []), + _tl-ev(2023.87, false, 0, []), + _tl-ev(2024.21, true, 1, []), + _tl-ev(2025.08, false, 1, []), + _tl-ev(2025.24, true, 0, []), + _tl-ev(2025.52, false, 0, [], w: 120pt), + ), ember, []) + _tl-lane(( + _tl-ev(2023.28, true, 0, []), + _tl-ev(2023.71, false, 0, [], w: 120pt), + _tl-ev(2024.54, true, 0, []), + _tl-ev(2025.10, false, 0, []), + _tl-ev(2025.71, true, 1, [], w: 66pt), + ), accent, []) + _tl-years() +}) + +#let hbar(label, value, max, fillc: accent, valstr: "") = grid( + columns: (92pt, 1fr, 42pt), + column-gutter: 5pt, + align(right + horizon, text(size: 10pt)[#label]), + place(left + horizon, place(left + horizon, rect(width: 100%, height: 7pt, fill: luma(242), radius: 1.5pt)) + place(left + horizon, rect(width: value / max * 100%, height: 7pt, fill: fillc, radius: 1.5pt))), + align(right + horizon, text(size: 9.5pt, fill: luma(110))[#valstr]), +) diff --git a/presentation01.typ b/presentation01.typ new file mode 100644 index 0000000..b19e1cb --- /dev/null +++ b/presentation01.typ @@ -0,0 +1,34 @@ +#import "template.typ": * +#import "diagrams.typ": * + +#let src(body) = { + v(0.35em) + block( + width: 100%, + fill: paper.darken(3%), + inset: (x: 6pt, y: 3.5pt), + radius: 2pt, + text(size: 9.5pt, fill: luma(145))[#text(fill: accent)[Quellen:] #body], + ) +} + +#show: presentation.with( + title: "KiCad", + subtitle: "", + author: "Your Name", +) + +#slide(title: "Ablauf")[ + - ..? + - Danach: Worauf besteht besonderes Interesse? +] + +// =================================================================== +#section("Technologie-Grundlagen", note: "30–45 min") +// =================================================================== + +#slide(title: "Was ist KiCad?") + #sample-chart() + #v(0.4em) + #src[@vaswani2017, @brown2020, @bbycroft] +] diff --git a/references.bib b/references.bib new file mode 100644 index 0000000..e69de29 diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..f71c191 --- /dev/null +++ b/shell.nix @@ -0,0 +1,8 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + packages = with pkgs; [ + typst + tinymist + ]; +} diff --git a/template.typ b/template.typ new file mode 100644 index 0000000..5507b50 --- /dev/null +++ b/template.typ @@ -0,0 +1,170 @@ +// ============================================================================ +// template.typ — technical, minimal presentation template +// +// Usage: +// #import "template.typ": * +// #show: presentation.with(title: "...", subtitle: "...", author: "...") +// +// #slide(title: "Title")[ ... ] // two-part slide: title part | content part +// #slide[ ... ] // single-part, full-width slide +// #img("assets/fig.svg") // centered image, optional caption +// ============================================================================ + +// Palette: warm paper, petrol accent, terracotta counterpoint. +// All text/background pairs keep >= 4.5:1 contrast; decorative +// elements (bars, markers, watermarks) never carry information. +#let paper = rgb("#faf8f3") +#let ink = rgb("#2d2a26") +#let accent = rgb("#22617f") +#let accent-soft = rgb("#4c8fad") +#let ember = rgb("#a85430") +#let wash = rgb("#edf2f5") +#let mono = "DejaVu Sans Mono" + +// Short vertical accent rule (petrol -> terracotta). +#let hairline-v = 3.5pt + gradient.linear(accent, ember, angle: 90deg) +// Horizontal hairline for title/section slides. +#let hairline-h = 1pt + gradient.linear(accent, ember, angle: 0deg) + +#let slide-counter = counter("slide") +#let deck-title = state("deck-title", none) + +// Footer: deck title bottom-left, slide counter bottom-right. +#let slide-footer() = context { + let n = slide-counter.get().first() + let total = slide-counter.final().first() + set text(font: mono, size: 0.55em, fill: luma(150)) + place(bottom + left, dy: -1em, deck-title.get()) + place(bottom + right, dy: -1em, { + text(fill: accent, weight: "bold", str(n)) + text(fill: luma(165), " / " + str(total)) + }) +} + +// Tinted content panel with a colored spine — used for paired columns +// (Grok = ember, Mistral = petrol). The spine is decorative reinforcement; +// the column headers carry the information. +#let panel(body, c: accent) = block( + width: 100%, + fill: c.lighten(95%), + stroke: (left: 2.5pt + c), + inset: (x: 0.55em, y: 0.45em), + radius: (top-right: 2pt, bottom-right: 2pt), + { + set par(spacing: 0.85em) + body + }, +) + +// Thin gradient band across the top edge of every page. +#let top-band = place(top + left, rect(width: 100%, height: 2.5pt, fill: gradient.linear(accent, ember, angle: 0deg))) + +// Import an image, centered; optional caption (never numbered). +#let img(path, width: 82%, caption: none) = { + let im = image(path, width: width) + if caption == none { + align(center, im) + } else { + align(center, figure(im, caption: caption, numbering: none)) + } +} + +// Two-part slide: a narrow title part on the left, content on the right. +// Without `title`, the body takes the full width. +#let slide(body, title: none, ..args) = { + slide-counter.update(n => n + 1) + page( + footer: slide-footer(), + ..args, + if title == none { + body + } else { + grid( + columns: (0.3fr, 1.1fr), + column-gutter: 2.2em, + align(top, block( + stroke: (left: hairline-v), + inset: (left: 0.9em, top: 0.4em, bottom: 0.1em), + text(font: mono, weight: "bold", size: 0.85em, tracking: 0.1em, fill: accent, upper(title)), + )), + align(top, body), + ) + }, + ) +} + +// Section divider slide, with a large decorative ghost numeral. +#let section-counter = counter("section") +#let section(name, note: none) = { + section-counter.step() + slide[ + #align(horizon)[ + #block(width: 72%, align(left)[ + #context { + let n = section-counter.get().first() + place(top + right, dy: -1.1em, dx: 0.2em, + text(font: mono, size: 4.2em, weight: "bold", fill: accent.lighten(86%))[ + 0#str(n) + ]) + } + #text(font: mono, size: 0.65em, weight: "bold", tracking: 0.2em, fill: accent)[SECTION] + #v(0.4em) + #text(size: 2em, weight: "bold")[#name] + #v(0.55em) + #box(width: 4.5em, align(left, line(length: 100%, stroke: hairline-h))) + #if note != none [#v(0.5em); #text(font: mono, size: 0.7em, fill: luma(110))[#note]] + ]) + ] + ] +} + +// Title slide. +#let title-slide(title, subtitle: none, author: none, date: none) = { + align(center + horizon)[ + #block(width: 72%, align(left)[ + #text(size: 2.1em, weight: "bold")[#title] + #if subtitle != none [#v(0.4em); #text(size: 1.15em, fill: luma(90))[#subtitle]] + #v(0.9em) + #line(length: 100%, stroke: hairline-h) + #v(0.6em) + #let meta = if author == none { date } else if date == none { author } else { author + " · " + date } + #text(font: mono, size: 0.7em, fill: luma(110))[#meta] + ]) + ] + pagebreak() +} + +// Main presentation wrapper. All options are named; the document content is +// bound to `doc` by the show rule. +#let presentation( + title: "Presentation", + subtitle: none, + author: none, + date: auto, + doc, +) = { + set page(paper: "presentation-16-9", margin: (x: 3em, y: 2.6em), fill: paper, footer: none, background: top-band) + set text(size: 20pt, fill: ink) + set par(justify: false, leading: 0.68em) + show strong: set text(fill: accent) + show list: set list(marker: ( + text(fill: accent-soft)[•], + text(fill: accent-soft)[–], + )) + show raw: set text(font: mono, size: 0.85em) + show raw.where(block: true): it => block(width: 100%, fill: wash, inset: 0.9em, radius: 0pt, it) + + deck-title.update(title) + + let d = datetime.today() + let mm = if d.month() < 10 { "0" + str(d.month()) } else { str(d.month()) } + let dd = if d.day() < 10 { "0" + str(d.day()) } else { str(d.day()) } + let the-date = if date == auto { + str(d.year()) + "-" + mm + "-" + dd + } else { + date + } + + title-slide(title, subtitle: subtitle, author: author, date: the-date) + doc +}