Модуль I · Тема 1 · Мовна модель і граф сюжету · 120 хвилин
Сьогодні читач сам обирає, що буде далі: під кожною сценою кнопки. Тексти
сцен пише мовна модель на шкільному сервері. Наприкінці уроку матимеш
story.json щонайменше з восьми сцен і сторінку, яка його показує.
story.json і показати історію.| Етап | Хв | Що робимо |
|---|---|---|
| Розминка | 5 | Дивимось два сайти класу з уроку 1 |
| Як «думає» модель | 20 | Токени, розподіл ймовірностей, температура, top-p |
| Промпт і галюцинації | 20 | Анатомія промпту, контекстне вікно, вигадані факти |
| Проєктування графа | 20 | Сцена, вибір, кінцівка, тупик, недосяжна сцена |
| Генерація і редагування | 30 | POST /api/llm, ручне правлення текстів |
| Публікація і рендер | 20 | fetch, FTP, перевірка в браузері |
| Автоперевірка й рефлексія | 5 | check 02 і README.md |
| Разом | 120 |
POST /api/llm зі свого акаунта, запити логуються.story/story.json, story/index.html,
story/meta.json, story/README.md.Одна дія, повторена сотні разів: «який шматочок тексту йде далі»
Модель дивиться на весь уже написаний текст, рахує ймовірність кожного наступного шматочка й обирає один. Англійська назва — LLM, large language model.
Шматочок зветься токен: слово, склад або кома. Ріже текст токенізатор — таблиця на 100–200 тисяч фрагментів.
Англійською близько 4 символів на токен, українською 2–3: той самий текст українською з'їдає більше токенів, а ліміт і ціну рахують у токенах.
Ти просиш модель: «скільки літер о у слові оборотоздатність?» Вона впевнено відповідає «три». Чому саме цей тип завдання для неї важкий?
З розподілу треба витягти один токен. Береш найімовірніший — текст щоразу однаковий, тягнеш навмання за частками — щоразу інший. Другий спосіб, семплінг, увімкнений майже завжди.
Ти двічі надіслав абсолютно однаковий промпт, нічого не змінюючи, — і отримав два різні тексти. Модель зламана?
Два параметри, якими ти керуєш вибором наступного слова
Перед кожним словом модель дає кандидатам оцінки — логіти.
Softmax перетворює їх на відсотки, і температура T
стоїть просто в ній:
Логіти діляться на T до переведення у відсотки: мала
T збільшує розрив між лідером і рештою, велика — зменшує.
Значення бери з таблиці.
| T | Що з розподілом | Що з текстом | Коли брати |
|---|---|---|---|
| 0 | один переможець | завжди однаковий, зациклюється | витягти факт |
| 0,2–0,4 | гострий пік | рівний, передбачуваний | інструкції, JSON |
| 0,7–0,9 | лідер помітний | живий текст | сцени історії |
| 1,2–1,5 | майже плато | несподівані образи й дурниці | назви, штурм ідей |
| > 1,8 | розподіл рівний | набір слів | ніколи |
1. Натисни кнопку T = 0,05. Один стовпчик займе майже
всю ширину. Стовпчики не рухаються — перезавантаж сторінку.
2. Натисни «витягнути 20 разів». Усі двадцять слів вийдуть однакові.
3. Натисни T = 1,50 і витягни ще двадцять разів.
Різних слів стане щонайменше п'ять.
4. Постав T = 0,80: це робоче значення для сцен
історії.
Ти просиш модель придумати назву й удесяте отримуєш ту саму. Що покрутити першим?
Температура піднімає і вдалі варіанти, і дурниці. Тому поруч ставлять
top-p: кандидатів сортують за ймовірністю і беруть згори стільки, щоб
сума дотягнула до p. Решта відпадає, верхню групу звуть ядром.
5. Перемкни демонстратор на набір «Столиця України — …» і постав
T = 1,50. «Київ» впаде до 87,7 %: кожна восьма спроба дасть
інше місто.
6. Зсунь top-p на 0,90. У полі «слів у ядрі»
стане 2, «Київ» підніметься до 96,6 %.
7. Для сцен із фактами лиши низьку T: top-p не рятує,
якщо температура завелика.
Однокласник поставив температуру 1,8 «для креативності». Модель написала, що дія відбувається у 2087 році, а через абзац — що торік. Твоя порада?
Чому модель «забуває» ім'я героя і чому впевнено вигадує факти
Кожен запит модель отримує з нуля: клієнт щоразу надсилає весь текст розмови. Скільки влазить, задає контекстне вікно в токенах; коли розмова більша, найстаріше випадає разом із правилами.
num_ctx. Правила повторюй
у кожному запиті.Ти на початку сесії написав «героїню звати Мирослава, пиши українською». Двадцять сцен по тому модель раптом назвала її Марією й перейшла на англійську. Що сталося і як лікувати?
Галюцинація — вигаданий факт, написаний правдоподібно: бази даних усередині немає, лише статистика слів. Тон при цьому не змінюється.
| Що просиш | Що приходить | Чому саме тут |
|---|---|---|
| назвати джерело або посилання | гарний URL, що не відкривається | структуру посилання модель знає, а самої сторінки — ні |
| точну дату або цифру | рівне правдоподібне число | рідкісні числа погано запам'ятовуються вагами |
| цитату відомої людини | фраза «в її стилі» | стиль відтворити легше, ніж конкретне речення |
| деталі малої теми | впевнена вигадка | у навчальних текстах цієї теми було замало |
| «яка сьогодні дата» | дата з минулого | годинника в моделі немає — про це нижче |
Годинника й мережі в моделі немає, тож дату вона дописує з навчальних текстів. Пиши дату в промпті: «Сьогодні 2 вересня 2026 року». Свіжі факти шукаєш ти.
Ти питаєш локальну модель: «Скільки днів лишилося до Нового року?» Вона впевнено відповідає числом — і воно неправильне. Що з цим робити?
В історії вигадане — матеріал: тримай температуру 0,8 і стеж, щоб текст не суперечив сам собі. У рефераті така сама вигадка — помилка. Різниця в тому, чи можна перевірити результат.
| Історія на цьому уроці | Реферат чи новина | |
|---|---|---|
| Ціна вигадки | нульова, це і є задум | висока: помилка йде далі як факт |
| Температура | 0,7–0,9 | 0–0,3 |
| Що перевіряєш | несуперечливість: імена, час, логіку сцен | кожен факт по зовнішньому джерелу |
| Джерела | не потрібні | обов'язкові, знайдені тобою, а не моделлю |
| Маркування | у meta.json: що згенеровано, що переписано | прямо в тексті роботи |
Модель дала тобі для реферату абзац із трьома посиланнями на наукові статті. Абзац звучить бездоганно. Твоя перша дія?
Чотири блоки, які роблять відповідь передбачуваною
«Напиши історію» — це не промпт: модель заповнить порожній контекст найсереднішим — замок, дракон, обраний хлопчик. Керований промпт має чотири блоки, кожен прибирає один вид невизначеності. Пиши свій за зразком нижче.
1. Додай у кінець промпту один готовий абзац своєї історії й рядок «пиши так само за стилем і довжиною». Цей прийом звуть few-shot: один приклад працює краще, ніж три абзаци пояснень.
2. Зайди на сервер по SSH. Модель відповідає там на
POST /api/llm, ключі й реєстрація не потрібні.
3. Набери команду нижче, підставивши свій промпт після
-d. У відповідь прийде рядок JSON із полем text.
Порожня відповідь — перевір, чи закрита кожна лапка.
4. Довгий промпт із лапками всередині ламає команду: термінал бачить закриту лапку раніше, ніж ти думаєш. Тому набери текст промпту в окремий файл.
5. Виконай два рядки нижче. nano зберігає
Ctrl+O, закриває Ctrl+X. jq -Rs сам
покладе текст у поле prompt, а jq -r .text дістане
з відповіді саму сцену. Побачив parse error — файл порожній.
6. Перечитай свій промпт і прибери з нього справжні прізвища, адреси й телефони.
/api/llm логуються, і саме за цим логом перевірка
побачить твою роботу з моделлю. Героїв історії вигадуй.curl означає Invoke-WebRequest:
ключів -X, -H, -d вона не розуміє.
Там пишуть Invoke-RestMethod, і && теж не
працює. Набирай усе в SSH-сесії на сервері.Ти просиш «напиши сцену про ліфт» і щоразу отримуєш різне: то два рядки, то півтори тисячі символів. Якого блоку бракує?
Сцена, вибір, кінцівка — і дві помилки, які ламають нелінійну історію
Нелінійна історія — це граф: вузли-сцени і стрілки-переходи. Читач бачить під сценою кнопки й переходить далі. Словник:
| Термін | Що це в графі | Що це у файлі |
|---|---|---|
| Сцена | вузол | об'єкт з id і text |
| Вибір | стрілка з вузла | елемент choices[]: text і next |
| Старт | перший вузол | id: "start" |
| Кінцівка | вузол без стрілок назовні | порожній choices плюс ending: true |
| Тупик | без виходу, не кінцівка | помилка: читач застряг |
| Недосяжна сцена | без вхідних стрілок | помилка: її ніхто не побачить |
shaft — тупик,
roof — недосяжна. JSON валідний, тому їх ловлять обходом
графа.Кроки роби в редакторі нижче: стартовий приклад містить обидві помилки з рисунка.
1. Впиши назву в поле «Назва історії» — вона піде в
title.
2. Прочитай блок «Діагностика»: там названі обидві зламані сцени.
3. Полагодь shaft: додай йому перехід або постав
галочку «це кінцівка» і натисни «додати / оновити».
4. Полагодь roof: додай перехід у нього з будь-якої
сцени. Діагностика має спорожніти; якщо ні — перехід веде не туди.
5. Заміни заглушки своїми сценами. Лічильник під полем показує довжину: менше 200 символів не зарахується.
6. Натисни «копіювати» під готовим story.json і встав
текст у редактор у себе.
0 символів
story.json у UTF-8 без BOM. Виведеш його через
> у PowerShell 5.1 — вийде UTF-16 і чекер скаже
«невалідний JSON»; там пиши | Out-File -Encoding utf8.Ти написав сцену «вихід на дах», а троє однокласників її не побачили.
story.json валідний. Що шукати?
Читач натискає «Розсунути двері» — і сторінка порожня: ні тексту, ні кнопок. Решта кнопок працює. Причина?
Дані окремо, розмітка окремо
Тексти сцен у HTML не вписуй: інакше кожна правка тексту стане правкою верстки. Три файли:
story.json — текст і структура історії;index.html — каркас і код, що покаже будь-яку таку
історію;meta.json — автор, модель, промпти, правки.1. Створи index.html і встав у нього код нижче: він
запитує story.json і малює сцену з кнопками.
2. Перевір, що тексти сцен не продубльовані в HTML: критерій
cross вимагає їх тільки в story.json.
3. Рядок if(!sc) не викидай: через помилку в
next читач побачить ім'я сцени, а не порожню сторінку.
4. Створи meta.json за зразком: клас, модель,
температура кожної сцени.
5. Напиши human_edit_note своїми словами, від 80
символів: що було не так у тексті моделі і що ти зробив.
6. Завантаж чотири файли через FileZilla або WinSCP у
~/upload/ — логін і пароль ті самі, що по SSH — і перенеси
в ~/www/story/.
7. Відкрий сторінку в браузері й натисни першу кнопку. Порожній
екран — story.json лежить не поруч із index.html.
Ти відкриваєш історію локально, клацнувши по index.html:
сцени немає, у консолі щось про CORS. На сайті все працює. Чому?
Виконуй по черзі. Галочки зберігаються — сторінку можна закрити.
1. Зайди на сервер по SSH під своїм логіном і перевір, де ти опинився.
Має вийти твій логін і шлях до твоєї домашньої теки. Логін чужий — набери
exit і зайди знову.
2. Створи теку, з якої вебсервер віддаватиме історію.
Команда нічого не друкує — так і має бути. Permission denied
означає, що ти не у своїй домашній теці.
3. Намалюй граф на папері: щонайменше вісім сцен, дві кінцівки, жодного тупика. Далі працюватимеш за цим малюнком.
4. Напиши промпт із чотирьох блоків у файл. Зберігає
Ctrl+O, закриває Ctrl+X.
У файлі мають бути роль, контекст, задача і формат. Без блоку формату довжина сцени щоразу буде інша.
5. Згенеруй першу сцену.
У відповідь прийде один абзац. Побачив 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/,
а потім перенеси в теку сторінки.
У списку мають бути всі чотири файли. No such file означає,
що завантаження через FTP не завершилося.
11. Відкрий свою сторінку в браузері й пройди історію двома різними
маршрутами до двох різних кінцівок. Порожній екран — story.json
лежить не в тій самій теці.
12. Перейди на вкладку «Перевірка» і натисни кнопку. Спроби не обмежені.
check 02Система розбере твій story.json, обійде граф,
відкриє сторінку в браузері й натисне першу кнопку. Спроби не обмежені.
Демонстраційний режим: результат згенеровано для показу. На сервері
ця кнопка викликає POST /api/check, який запускає чекер уроку
від імені учня.
Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
| Симптом | Причина й лікування |
|---|---|
Історія працює, а критерій «текст тільки в 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 опиши цей маршрут трьома реченнями. Так учитель
перевірить, що сцена справді досяжна.
Звідки взяте те, що написано на цій сторінці — можеш перевірити сам
temperature,
top_p, top_k, num_ctx,
seed і їхні значення за замовчуванням.story.json
і чому це не працює з file://.Логіти в демонстраторі температури вигадані для наочності — але всі відсотки, ентропія і жеребкування рахуються з них справжнім softmax просто у твоєму браузері. Розбиття речення на токени в першій схемі теж ілюстративне: у різних моделей воно різне.