До списку уроків
9 клас · Урок 2 з 16

LLM як співавтор: промпт, температура, граф сюжету

виконано0%
Крок 1

Що робимо сьогодні

Модуль I · Тема 1 · Мовна модель і граф сюжету · 120 хвилин

Сьогодні читач сам обирає, що буде далі: під кожною сценою кнопки. Тексти сцен пише мовна модель на шкільному сервері. Наприкінці уроку матимеш story.json щонайменше з восьми сцен і сторінку, яка його показує.

Після уроку ти вмієш

Хід уроку

ЕтапХвЩо робимо
Розминка5Дивимось два сайти класу з уроку 1
Як «думає» модель20Токени, розподіл ймовірностей, температура, top-p
Промпт і галюцинації20Анатомія промпту, контекстне вікно, вигадані факти
Проєктування графа20Сцена, вибір, кінцівка, тупик, недосяжна сцена
Генерація і редагування30POST /api/llm, ручне правлення текстів
Публікація і рендер20fetch, FTP, перевірка в браузері
Автоперевірка й рефлексія5check 02 і README.md
Разом120
Модель у класі На шкільному сервері працює Ollama з мовною моделлю. Звертаєшся запитом POST /api/llm зі свого акаунта, запити логуються.
Що летить на сервер Тільки текст: story/story.json, story/index.html, story/meta.json, story/README.md.
Крок 2

Що модель робить насправді

Одна дія, повторена сотні разів: «який шматочок тексту йде далі»

Модель дивиться на весь уже написаний текст, рахує ймовірність кожного наступного шматочка й обирає один. Англійська назва — LLM, large language model.

Шматочок — це токен, а не буква і не слово

Шматочок зветься токен: слово, склад або кома. Ріже текст токенізатор — таблиця на 100–200 тисяч фрагментів.

Англійською близько 4 символів на токен, українською 2–3: той самий текст українською з'їдає більше токенів, а ліміт і ціну рахують у токенах.

Крок генерації: текст → токени → розподіл ймовірностей → вибір Дв ері ·рип нули , ·і ·на ·по розі ·сто яв 32 символи → 11 токенів крапкою позначено пробіл: він теж частина токена модель оцінює кожен токен словника як кандидата на 12-й незнайомець старий хлопчик пес ніхто сторож холод кактус 34,5 % 24,3 % 17,1 % 9,9 % 6,3 % 4,7 % 2,7 % 0,5 % …і ще майже сто тисяч токенів словника, кожен із мізерною часткою відсотка
Числа ілюстративні: розбиття залежить від токенізатора моделі.
Найважливіше речення уроку Модель оптимізована на «правдоподібне продовження», а не на «правду».
Питання

Ти просиш модель: «скільки літер о у слові оборотоздатність?» Вона впевнено відповідає «три». Чому саме цей тип завдання для неї важкий?

Чому дві однакові спроби дають різний текст

З розподілу треба витягти один токен. Береш найімовірніший — текст щоразу однаковий, тягнеш навмання за частками — щоразу інший. Другий спосіб, семплінг, увімкнений майже завжди.

Питання

Ти двічі надіслав абсолютно однаковий промпт, нічого не змінюючи, — і отримав два різні тексти. Модель зламана?

Крок 3

Температура і top-p

Два параметри, якими ти керуєш вибором наступного слова

Перед кожним словом модель дає кандидатам оцінки — логіти. Softmax перетворює їх на відсотки, і температура T стоїть просто в ній:

формула
p(i) = exp(z(i) / T) / SUM_j exp(z(j) / T)

Логіти діляться на T до переведення у відсотки: мала T збільшує розрив між лідером і рештою, велика — зменшує. Значення бери з таблиці.

TЩо з розподіломЩо з текстомКоли брати
0один переможецьзавжди однаковий, зациклюєтьсявитягти факт
0,2–0,4гострий пікрівний, передбачуванийінструкції, JSON
0,7–0,9лідер помітнийживий текстсцени історії
1,2–1,5майже платонесподівані образи й дурниціназви, штурм ідей
> 1,8розподіл рівнийнабір слівніколи
Один і той самий набір логітів, дві температури. Шкала однакова T = 0,25 — розподіл загострений лідер забирає три чверті T = 1,5 — розподіл розмитий верхівка зрізана, хвіст піднявся незнайомець старий хлопчик пес ніхто сторож холод кактус 76,0 % 18,7 % 4,6 % 0,5 % 0,1 % 0,0 % 0,0 % 0,0 % незнайомець старий хлопчик пес ніхто сторож холод кактус 27,2 % 21,5 % 17,0 % 11,8 % 8,8 % 7,2 % 5,0 % 1,5 % логіти незмінні: 3,10 · 2,75 · 2,40 · 1,85 · 1,40 · 1,10 · 0,55 · −1,20 — змінюється лише дільник T невизначеність: 1,01 біта ліворуч, 2,68 біта праворуч (0 біт — вибору немає, 3 біти — усі 8 рівні)
Логіти вигадані, відсотки — справжній softmax від них; ті самі числа рахує демонстратор.

Зроби на демонстраторі

1. Натисни кнопку T = 0,05. Один стовпчик займе майже всю ширину. Стовпчики не рухаються — перезавантаж сторінку.

2. Натисни «витягнути 20 разів». Усі двадцять слів вийдуть однакові.

3. Натисни T = 1,50 і витягни ще двадцять разів. Різних слів стане щонайменше п'ять.

4. Постав T = 0,80: це робоче значення для сцен історії.

температура: 0,80 робоче значення для прози
top-p (ядро): 1,00 відсічення вимкнене
найімовірніший
шанс не лідеразвідси різноманітність
слів у ядрі8відсічення вимкнене
невизначеністьбіт: 0 — вибору немає, 3 — усі рівні
Тут з'являться двадцять витягнутих слів.
Питання

Ти просиш модель придумати назву й удесяте отримуєш ту саму. Що покрутити першим?

top-p: відсікти маловірогідних кандидатів

Температура піднімає і вдалі варіанти, і дурниці. Тому поруч ставлять top-p: кандидатів сортують за ймовірністю і беруть згори стільки, щоб сума дотягнула до p. Решта відпадає, верхню групу звуть ядром.

5. Перемкни демонстратор на набір «Столиця України — …» і постав T = 1,50. «Київ» впаде до 87,7 %: кожна восьма спроба дасть інше місто.

6. Зсунь top-p на 0,90. У полі «слів у ядрі» стане 2, «Київ» підніметься до 96,6 %.

7. Для сцен із фактами лиши низьку T: top-p не рятує, якщо температура завелика.

Питання

Однокласник поставив температуру 1,8 «для креативності». Модель написала, що дія відбувається у 2087 році, а через абзац — що торік. Твоя порада?

Крок 4

Контекстне вікно і галюцинації

Чому модель «забуває» ім'я героя і чому впевнено вигадує факти

Пам'яті між запитами немає взагалі

Кожен запит модель отримує з нуля: клієнт щоразу надсилає весь текст розмови. Скільки влазить, задає контекстне вікно в токенах; коли розмова більша, найстаріше випадає разом із правилами.

Контекстне вікно 2 048 токенів. Вікно тримається за кінець розмови розмова на 1 470 токенів — вміщається, місце ще є пр 1 2 3 ? вільно 578 ← межа вікна розмова на 3 100 токенів — вікно з'їхало вперед пр 1 2 3 4 5 6 7 ? 1 052 токени випали: системний промпт і сцени 1–2 зникли 2 048 токенів, які модель справді бачить цього разу «пр» — системний промпт із правилами, «?» — твоє нове питання, цифри — сцени розмови
Розмір вікна задає num_ctx. Правила повторюй у кожному запиті.
Питання

Ти на початку сесії написав «героїню звати Мирослава, пиши українською». Двадцять сцен по тому модель раптом назвала її Марією й перейшла на англійську. Що сталося і як лікувати?

Галюцинація — це коли модель робить свою роботу

Галюцинація — вигаданий факт, написаний правдоподібно: бази даних усередині немає, лише статистика слів. Тон при цьому не змінюється.

Що просишЩо приходитьЧому саме тут
назвати джерело або посиланнягарний URL, що не відкриваєтьсяструктуру посилання модель знає, а самої сторінки — ні
точну дату або цифрурівне правдоподібне числорідкісні числа погано запам'ятовуються вагами
цитату відомої людинифраза «в її стилі»стиль відтворити легше, ніж конкретне речення
деталі малої темивпевнена вигадкау навчальних текстах цієї теми було замало
«яка сьогодні дата»дата з минулогогодинника в моделі немає — про це нижче

Чому вона не знає сьогоднішньої дати

Годинника й мережі в моделі немає, тож дату вона дописує з навчальних текстів. Пиши дату в промпті: «Сьогодні 2 вересня 2026 року». Свіжі факти шукаєш ти.

Питання

Ти питаєш локальну модель: «Скільки днів лишилося до Нового року?» Вона впевнено відповідає числом — і воно неправильне. Що з цим робити?

Де вигадка нешкідлива, а де фатальна

В історії вигадане — матеріал: тримай температуру 0,8 і стеж, щоб текст не суперечив сам собі. У рефераті така сама вигадка — помилка. Різниця в тому, чи можна перевірити результат.

Правило перевірки: модель — чернетка, не джерело Ім'я, дату, число, назву, цитату й посилання звіряй із зовнішнім джерелом. Посилання відкривай руками.
Історія на цьому уроціРеферат чи новина
Ціна вигадкинульова, це і є задумвисока: помилка йде далі як факт
Температура0,7–0,90–0,3
Що перевіряєшнесуперечливість: імена, час, логіку сценкожен факт по зовнішньому джерелу
Джерелане потрібніобов'язкові, знайдені тобою, а не моделлю
Маркуванняу meta.json: що згенеровано, що переписанопрямо в тексті роботи
Питання

Модель дала тобі для реферату абзац із трьома посиланнями на наукові статті. Абзац звучить бездоганно. Твоя перша дія?

Крок 5

Анатомія промпту

Чотири блоки, які роблять відповідь передбачуваною

«Напиши історію» — це не промпт: модель заповнить порожній контекст найсереднішим — замок, дракон, обраний хлопчик. Керований промпт має чотири блоки, кожен прибирає один вид невизначеності. Пиши свій за зразком нижче.

Роль → контекст → задача → формат що пишеш що буде, якщо цього блоку немає РОЛЬ КОНТЕКСТ ЗАДАЧА ФОРМАТ хто пише про що світ що зробити як виглядає Ти — редактор підліткової інтерактивної прози. Пишеш стисло, без пафосу, українською. Історія: ліфт застряг між поверхами. Героїня — Мирослава, 14 років, боїться темряви, має ліхтарик. Напиши сцену «голос у динаміку»: героїня чує чужий голос і мусить вирішити, чи відповідати. 250–300 символів, минулий час, третя особа, рівно один абзац, без діалогів і без заголовка. тон стрибає від казки до інструкції імена й деталі модель вигадає свої, щоразу нові прийде переказ теми замість живої сцени довжина щоразу інша, у JSON таке не вставиш один абзац, який одразу лягає в поле text сцени story.json п'ятий, необов'язковий блок — приклад: покажи один готовий абзац і скажи «зроби так само»
Порядок такий: хто пише, у якому світі, що зробити і як має виглядати відповідь.

Приклад як п'ятий блок

1. Додай у кінець промпту один готовий абзац своєї історії й рядок «пиши так само за стилем і довжиною». Цей прийом звуть few-shot: один приклад працює краще, ніж три абзаци пояснень.

Як звернутися до моделі

2. Зайди на сервер по SSH. Модель відповідає там на POST /api/llm, ключі й реєстрація не потрібні.

3. Набери команду нижче, підставивши свій промпт після -d. У відповідь прийде рядок JSON із полем text. Порожня відповідь — перевір, чи закрита кожна лапка.

SSH-сесія на сервері · Linux
$ curl -s -X POST http://localhost/api/llm -H 'Content-Type: application/json' -d '{"prompt":"Ти — редактор підліткової прози. Напиши сцену 250-300 символів.","temperature":0.8,"top_p":0.9,"max_tokens":300}' {"text":"Ліфт стало на мить, і світло згасло...","tokens":78,"model":"qwen2.5:3b"}

4. Довгий промпт із лапками всередині ламає команду: термінал бачить закриту лапку раніше, ніж ти думаєш. Тому набери текст промпту в окремий файл.

5. Виконай два рядки нижче. nano зберігає Ctrl+O, закриває Ctrl+X. jq -Rs сам покладе текст у поле prompt, а jq -r .text дістане з відповіді саму сцену. Побачив parse error — файл порожній.

промпт із файлу
$ nano ~/notes/prompt-03.txt $ curl -s -X POST http://localhost/api/llm -H 'Content-Type: application/json' --data-binary "$(jq -Rs '{prompt:., temperature:0.8}' ~/notes/prompt-03.txt)" | jq -r .text

6. Перечитай свій промпт і прибери з нього справжні прізвища, адреси й телефони.

Ніяких персональних даних у промпті Усі запити до /api/llm логуються, і саме за цим логом перевірка побачить твою роботу з моделлю. Героїв історії вигадуй.
Якщо працюєш у Windows У PowerShell 5.1 curl означає Invoke-WebRequest: ключів -X, -H, -d вона не розуміє. Там пишуть Invoke-RestMethod, і && теж не працює. Набирай усе в SSH-сесії на сервері.
Питання

Ти просиш «напиши сцену про ліфт» і щоразу отримуєш різне: то два рядки, то півтори тисячі символів. Якого блоку бракує?

Крок 6

Історія як граф

Сцена, вибір, кінцівка — і дві помилки, які ламають нелінійну історію

Нелінійна історія — це граф: вузли-сцени і стрілки-переходи. Читач бачить під сценою кнопки й переходить далі. Словник:

ТермінЩо це в графіЩо це у файлі
Сценавузолоб'єкт з id і text
Вибірстрілка з вузлаелемент choices[]: text і next
Стартперший вузолid: "start"
Кінцівкавузол без стрілок назовніпорожній choices плюс ending: true
Тупикбез виходу, не кінцівкапомилка: читач застряг
Недосяжна сценабез вхідних стрілокпомилка: її ніхто не побачить
Граф історії про ліфт: що правильно і що зламано кнопка двері чекати правда мовчати кликати заснути start intercom shaft wait dark freeze rescue roof тупик: виходу немає, а кінцівкою не позначена недосяжна: жодна стрілка сюди не веде кінцівка кінцівка старт, три вибори До rescue ведуть дві різні стрілки — це нормально й навіть корисно: маршрути сходяться, а текстів менше
Дві сцени зламані: shaft — тупик, roof — недосяжна. JSON валідний, тому їх ловлять обходом графа.

Як це виглядає у файлі

story.json · фрагмент
{ "title": "Ліфт між поверхами", "start": "start", "scenes": [ { "id": "start", "text": "Ліфт стало між третім і четвертим...", "choices": [ { "text": "Натиснути кнопку виклику", "next": "intercom" }, { "text": "Розсунути двері руками", "next": "shaft" }, { "text": "Просто чекати", "next": "wait" } ] }, { "id": "rescue", "text": "Двері розійшлися...", "ending": true, "choices": [] } ] }

Редактор графа

Кроки роби в редакторі нижче: стартовий приклад містить обидві помилки з рисунка.

1. Впиши назву в поле «Назва історії» — вона піде в title.

2. Прочитай блок «Діагностика»: там названі обидві зламані сцени.

3. Полагодь shaft: додай йому перехід або постав галочку «це кінцівка» і натисни «додати / оновити».

4. Полагодь roof: додай перехід у нього з будь-якої сцени. Діагностика має спорожніти; якщо ні — перехід веде не туди.

5. Заміни заглушки своїми сценами. Лічильник під полем показує довжину: менше 200 символів не зарахується.

6. Натисни «копіювати» під готовим story.json і встав текст у редактор у себе.

1. Назва історії

2. Сцена

0 символів

3. Перехід

4. Граф

5. Діагностика

    6. Сцени

    7. Готовий story.json

    story.json
    Пастка кодування Зберігай story.json у UTF-8 без BOM. Виведеш його через > у PowerShell 5.1 — вийде UTF-16 і чекер скаже «невалідний JSON»; там пиши | Out-File -Encoding utf8.
    Питання

    Ти написав сцену «вихід на дах», а троє однокласників її не побачили. story.json валідний. Що шукати?

    Питання

    Читач натискає «Розсунути двері» — і сторінка порожня: ні тексту, ні кнопок. Решта кнопок працює. Причина?

    Крок 7

    Сторінка, яка читає story.json

    Дані окремо, розмітка окремо

    Тексти сцен у HTML не вписуй: інакше кожна правка тексту стане правкою верстки. Три файли:

    1. Створи index.html і встав у нього код нижче: він запитує story.json і малює сцену з кнопками.

    index.html · код рендера
    let story = null; fetch('story.json') .then(r => r.json()) .then(data => { story = data; show(data.start || 'start'); }); function show(id){ const sc = story.scenes.find(s => s.id === id); const box = document.getElementById('scene'); if(!sc){ box.textContent = 'Сцена ' + id + ' не знайдена'; return; } box.textContent = sc.text; const nav = document.getElementById('choices'); nav.textContent = ''; (sc.choices || []).forEach(c => { const b = document.createElement('button'); b.textContent = c.text; b.onclick = () => show(c.next); nav.appendChild(b); }); if(!(sc.choices || []).length) nav.textContent = 'Кінець історії.'; }

    2. Перевір, що тексти сцен не продубльовані в HTML: критерій cross вимагає їх тільки в story.json.

    3. Рядок if(!sc) не викидай: через помилку в next читач побачить ім'я сцени, а не порожню сторінку.

    meta.json: автор, модель, правки

    4. Створи meta.json за зразком: клас, модель, температура кожної сцени.

    meta.json
    { "author": "Мирослава К., 9-Б", "model": "qwen2.5:3b (Ollama, локально в класі)", "prompts": [ { "scene": "start", "temperature": 0.8, "text": "Ти — редактор підліткової прози..." }, { "scene": "dark", "temperature": 0.9, "text": "Ти — редактор підліткової прози..." }, { "scene": "rescue", "temperature": 0.6, "text": "Ти — редактор підліткової прози..." } ], "human_edit_note": "Сцену dark модель написала від першої особи і з діалогом. Я переписала її повністю: третя особа, минулий час, забрала репліки, додала ліхтарик, бо він потрібен у сцені roof." }

    5. Напиши human_edit_note своїми словами, від 80 символів: що було не так у тексті моделі і що ти зробив.

    Шлях здачі

    6. Завантаж чотири файли через FileZilla або WinSCP у ~/upload/ — логін і пароль ті самі, що по SSH — і перенеси в ~/www/story/.

    у себе на комп'ютері → FTP → сервер
    story.json ~28 КБ ← складаєш редактором графа, правиш у себе index.html ~3 КБ ← верстаєш у себе meta.json ~2 КБ ← пишеш руками README.md ~1 КБ ← рефлексія ↓ FileZilla / WinSCP, той самий логін і пароль, що по SSH ~/upload/ → розкладаєш у ~/www/story/

    7. Відкрий сторінку в браузері й натисни першу кнопку. Порожній екран — story.json лежить не поруч із index.html.

    Сьогодні все легке Уся робота — текст: чотири файли на кілька десятків кілобайтів. Ні відео, ні аудіо на сервер не йде.
    Питання

    Ти відкриваєш історію локально, клацнувши по index.html: сцени немає, у консолі щось про CORS. На сайті все працює. Чому?

    Крок 8

    Практика: збираємо історію

    Виконуй по черзі. Галочки зберігаються — сторінку можна закрити.

    Чекліст роботи

    1. Зайди на сервер по SSH під своїм логіном і перевір, де ти опинився.

    термінал
    $ whoami $ pwd

    Має вийти твій логін і шлях до твоєї домашньої теки. Логін чужий — набери exit і зайди знову.

    2. Створи теку, з якої вебсервер віддаватиме історію.

    термінал
    $ mkdir -p ~/www/story

    Команда нічого не друкує — так і має бути. Permission denied означає, що ти не у своїй домашній теці.

    3. Намалюй граф на папері: щонайменше вісім сцен, дві кінцівки, жодного тупика. Далі працюватимеш за цим малюнком.

    4. Напиши промпт із чотирьох блоків у файл. Зберігає Ctrl+O, закриває Ctrl+X.

    термінал
    $ nano ~/notes/prompt-03.txt

    У файлі мають бути роль, контекст, задача і формат. Без блоку формату довжина сцени щоразу буде інша.

    5. Згенеруй першу сцену.

    термінал
    $ curl -s -X POST http://localhost/api/llm -H 'Content-Type: application/json' --data-binary "$(jq -Rs '{prompt:., temperature:0.8}' ~/notes/prompt-03.txt)" | jq -r .text

    У відповідь прийде один абзац. Побачив parse error — файл промпту порожній або названий інакше.

    6. Повтори крок 5 для кожної сцени, міняючи текст промпту й температуру: 0,8 для звичайних сцен, 0,6 для сцен із фактами.

    7. Перепиши кожен абзац своїми словами й запиши, що саме ти правив, — це знадобиться для human_edit_note.

    8. Внеси сцени й переходи в редактор графа з кроку 6, поки блок «Діагностика» не спорожніє. Потім натисни «копіювати» під story.json.

    9. Збережи в себе на комп'ютері чотири файли: story.json у кодуванні UTF-8 без BOM, index.html із кодом кроку 7, meta.json і README.md.

    10. Завантаж їх через FileZilla або WinSCP у ~/upload/, а потім перенеси в теку сторінки.

    термінал
    $ mv ~/upload/story.json ~/upload/index.html ~/upload/meta.json ~/upload/README.md ~/www/story/ $ ls -l ~/www/story/

    У списку мають бути всі чотири файли. No such file означає, що завантаження через FTP не завершилося.

    11. Відкрий свою сторінку в браузері й пройди історію двома різними маршрутами до двох різних кінцівок. Порожній екран — story.json лежить не в тій самій теці.

    12. Перейди на вкладку «Перевірка» і натисни кнопку. Спроби не обмежені.

    Крок 9

    Автоперевірка check 02

    Система розбере твій story.json, обійде граф, відкриє сторінку в браузері й натисне першу кнопку. Спроби не обмежені.

    Демонстраційний режим: результат згенеровано для показу. На сервері ця кнопка викликає POST /api/check, який запускає чекер уроку від імені учня.

    Що вчитель дивиться на екрані

    Крок 10

    Шкала виконання

    Це те, що бачить учитель, коли виставляє оцінку.

    СкладникВагаРезультат
    Виконано
    0%
    Рекомендований бал за 12-бальною

    Шість пасток цього уроку

    СимптомПричина й лікування
    Історія працює, а критерій «текст тільки в story.json» червонийтексти сцен вставлені ще й прямо в HTML; лиши їх тільки в story.json
    Кнопка є, після натискання порожньодрукарська помилка в next: rescu замість rescue
    Сцену ніхто не бачивнедосяжна: жоден choice на неї не веде — додай стрілку
    Читач застряг без кнопоктупик: або додай вибір, або постав "ending": true
    «Невалідний JSON», хоч у редакторі все гараздфайл збережено в UTF-16 через > у PowerShell; перезбережи в UTF-8 без BOM
    Не зараховано розповідь про власні правки — поле human_edit_noteвона скопійована з відповіді моделі; напиши своїми словами, що саме правив

    Домашнє завдання

    Додай секретну кінцівку — сцену, до якої веде рівно один маршрут. Щоб її побачити, читач має зробити дві-три конкретні дії поспіль.

    Онови story.json і meta.json. А в README.md опиши цей маршрут трьома реченнями. Так учитель перевірить, що сцена справді досяжна.

    Довідка

    Джерела

    Звідки взяте те, що написано на цій сторінці — можеш перевірити сам

    Токени й токенізація

    Температура, softmax і семплінг

    Контекстне вікно і модель у класі

    Галюцинації

    Граф і формат історії

    Логіти в демонстраторі температури вигадані для наочності — але всі відсотки, ентропія і жеребкування рахуються з них справжнім softmax просто у твоєму браузері. Розбиття речення на токени в першій схемі теж ілюстративне: у різних моделей воно різне.