Презентация результатов руководству

Первый слайд «было/стало» для владельца кофейни «Зерно» собрался с аккуратной таблицей и верными цифрами. Проверка кодом ответила «ОК»: каждое число в тексте нашлось в данных. А в выводах стояло «1 216 визитов в кофейню», хотя это визиты на сайт. Заголовок обещал, что «реклама работает без сбоев», хотя таблица этого не говорит. Владелец прочёл бы и поверил. В этом уроке вы соберёте слайд, на котором цифры не может испортить модель, и научитесь ловить то, что код не поймает.

Чему научитесь в этом уроке:
• брать цифры для слайда из таблицы «Цифры недели», которую пополняет отчёт 4.4;
• разделять работу: таблицу и пометку «на прежнем уровне» рисует код, модель пишет только заголовок и три вывода;
• просить у модели ответ в JSON и проверять кодом, что каждое число из текста есть в данных;
• получать слайд как HTML-страницу 1280×720 и превращать её в картинку или PDF;
• читать слайд глазами владельца перед отправкой.

Витрина отчёта

Отчёт из урока 4.4 похож на склад: всё есть, но, чтобы найти нужное, надо походить между полками. Владельцу или клиенту нужна витрина. Одна полка, на ней шесть цифр и три подписи: что это значит и что делать дальше. Витрину смотрят полминуты, поэтому любая неточность на ней заметнее, чем в длинном отчёте.

Витрину раскладывают двое. Цифры на полку ставит код: он берёт их из данных и ничего не округляет по своему вкусу. Подписи пишет модель, потому что с человеческими словами она справляется лучше кода. Так модель не может перепутать 10 654 и 10 994: таблицу она не рисует вовсе.

Как устроен сценарий

Сценарий в прогоне курса называется «Т3 прогон 4.6: слайд было/стало». Цепочка такая: запуск вручную (в уроке 4.7 добавим расписание на понедельник, 9:30) → Data Table «Последние цифры» → Code «Цифры и план» → Basic LLM Chain «Текст слайда» → Code «Слайд». Code это узел, в котором пишется короткая программа на JavaScript. Basic LLM Chain отправляет модели системное сообщение и вашу просьбу и возвращает ответ; модель та же, что во всём модуле, через CloseRouter. В прогоне за «Слайдом» стоял ещё узел записи в таблицу «Журнал аналитики», его разберём в уроке 4.7.

Откуда слайд берёт цифры

В первой версии цифры двух недель были вписаны в код руками. Для слайда по расписанию это не годится: каждый понедельник выходил бы один и тот же слайд. Поэтому слайд берёт цифры из таблицы данных «Цифры недели». Её пополняет отчёт из урока 4.4: узел «В таблицу цифр» при каждом запуске дописывает строку с двумя неделями. Если вы собирали 4.4 без этого узла, добавьте его и запустите отчёт один раз, иначе слайду нечего будет взять.

Первым после запуска поставьте узел Data Table с действием Get, имя «Последние цифры», таблица «Цифры недели». В его настройках включите Return All (отдать все строки) и Always Output Data (отдать результат, даже если таблица пустая).

Узел «Цифры и план»

Код берёт из таблицы последнюю строку, раскладывает две недели на «было» и «стало», ставит каждой строке пометку шума по тому же порогу, что в уроке 4.5 (меньше 10% или меньше 5 штук), добавляет план проверок и подпись периода. Вставьте его целиком:

// Цифры двух недель — последняя строка таблицы «Цифры недели», её пишет отчёт 4.4
const rows = $('Последние цифры').all().map(i => i.json).filter(r => r.weeks);
if (!rows.length) throw new Error('В таблице «Цифры недели» пусто: сначала запустите отчёт 4.4 со свежими выгрузками');
const last = rows.sort((a, b) => b.id - a.id)[0];
const [p, c] = JSON.parse(last.weeks);
const pick = x => ({ расход: x.расход, клики: x.клики, ctr: Number(x.ctr), конверсии: x.конверсии, цена_конверсии: x.цена_конверсии, визиты: x.визиты });
const was = pick(p), now = pick(c);
// План проверок — гипотезы, принятые в уроке 4.5; меняйте, когда принимаете новые
const hyps = ['Серия постов «Закулисье» в канале: визиты 1216 → 1338 за 7 дней', 'Оффер «сет-дегустация» в Директе: конверсии 52 → 60 в неделю за 14 дней'];
const rowsOut = Object.keys(now).map(k => { const pc = (now[k] - was[k]) / was[k] * 100; return { k, was: was[k], now: now[k], p: +pc.toFixed(1), noise: Math.abs(pc) < 10 || Math.abs(now[k] - was[k]) < 5 }; });
return [{ json: { rows: rowsOut, hyps, period: p.неделя + ' → ' + c.неделя } }];

Менять для себя нужно только список hyps: это две гипотезы, принятые в уроке 4.5. Когда примете новые, перепишите строки. Цифры трогать не нужно, они приходят из таблицы. Если таблица пустая, узел остановится с ошибкой «сначала запустите отчёт 4.4 со свежими выгрузками». Слово «Оффер» из плана модель тоже увидит; в промпте ниже его просят заменить на «предложение в рекламе».

Узел «Текст слайда»

Модель получает таблицу и план, а отвечает только JSON (текст в строгом формате «поле: значение»): заголовок и три вывода. Системное сообщение, с которым закончился прогон курса:

Ты готовишь один слайд для владельца кофейни «Зерно». Таблица цифр уже есть на слайде — НЕ пересказывай её. Напиши JSON без пояснений и без ```:
{"заголовок":"до 60 знаков, главный вывод недели","выводы":["…","…","…"]}
Правила:
- 3 вывода, каждый до 120 знаков: что эти цифры значат для владельца и что с этим делать.
- Без терминов: не «конверсии», «CTR», «оффер», а «построили маршрут», «доля кликнувших», «предложение в рекламе».
- Строку с пометкой «шум» не называй ни ростом, ни падением.
- Числа — только из таблицы и плана, ничего не досчитывай; пиши их с пробелом между тысячами и с запятой: 10 994, 3,32.
- Последний вывод — что проверяем на следующей неделе и по какой цифре поймём результат.

Сообщение пользователя собирает строки таблицы с пометкой «шум» и план проверок:

{{ "Неделя к неделе:\n" + $json.rows.map(r => r.k + ": было " + r.was + ", стало " + r.now + " (" + r.p + "%)" + (r.noise ? " — шум" : "")).join("\n") + "\n\nПлан проверок:\n" + $json.hyps.join("\n") }}

Каждая строка здесь появилась после ошибки. О ней ниже.

Узел «Слайд»

Этот узел делает три вещи. Сначала разбирает JSON модели. Потом проверяет: каждое число из заголовка и выводов должно найтись в данных, пробел между тысячами при этом снимается, так что «10 994» и 10994 считаются одним числом. И наконец рисует HTML-страницу 1280×720: слева таблица «Показатель / Было / Стало / Итог», справа три вывода. Где у строки пометка «шум», в колонке «Итог» стоит «на прежнем уровне». Подписи строк тоже задаёт код: «Расход, ₽», «Клики», «Доля кликнувших, %», «Построили маршрут», «Цена одного маршрута, ₽», «Визиты на сайт». Готовый файл slide-zerno.html узел отдаёт как вложение (binary).

Вставьте код целиком. Узел перед ним должен называться ровно «Цифры и план»: код обращается к нему по имени.

// Слайд
const d=$('Цифры и план').first().json;
let t;try{t=JSON.parse(String($input.first().json.text).replace(/^\s*```(json)?/,'').replace(/```\s*$/,''))}catch(e){return [{json:{ok:false,ошибка:'модель вернула не JSON'}}]}
// Проверка: каждое число в тексте слайда есть в данных
const known=new Set();d.rows.forEach(r=>[r.was,r.now,Math.abs(r.p)].forEach(x=>known.add(String(x).replace('.',','))&&known.add(String(x))));d.hyps.join(' ').match(/\d+/g).forEach(x=>known.add(x));[7,14].forEach(x=>known.add(String(x)));
const text=[t.заголовок,...t.выводы].join(' ');const nums=(text.replace(/(\d)[\s\u00a0](?=\d{3}\b)/g,'$1').match(/\d+(?:[.,]\d+)?/g)||[]);const unknown=nums.filter(x=>!known.has(x)&&!known.has(x.replace(',','.')));
const names={расход:'Расход, ₽',клики:'Клики',ctr:'Доля кликнувших, %',конверсии:'Построили маршрут',цена_конверсии:'Цена одного маршрута, ₽',визиты:'Визиты на сайт'};
const esc=s=>String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;');
const fmt=v=>String(v).replace('.',',').replace(/\B(?=(\d{3})+(?!\d))/g,' ');
const tr=d.rows.map(r=>'<tr><td>'+names[r.k]+'</td><td>'+fmt(r.was)+'</td><td>'+fmt(r.now)+'</td><td class="'+(r.noise?'n':(r.p>0?'u':'d'))+'">'+(r.noise?'на прежнем уровне':(r.p>0?'+':'')+fmt(r.p)+'%')+'</td></tr>').join('');
const html='<!doctype html><meta charset="utf-8"><title>Зерно: неделя</title><style>body{font-family:Arial,sans-serif;margin:0;background:#f6f1ea;color:#2b211a}.s{width:1280px;height:720px;box-sizing:border-box;padding:56px 72px}h1{font-size:40px;margin:0 0 8px}.p{color:#7a6a5c;font-size:20px;margin-bottom:28px}.g{display:flex;gap:48px}table{border-collapse:collapse;font-size:21px;width:640px}td{padding:10px 12px;white-space:nowrap;border-bottom:1px solid #dccfc2}tr:first-child td{font-weight:bold;color:#7a6a5c}.u{color:#2e7d32}.d{color:#c62828}.n{color:#7a6a5c}ul{font-size:22px;line-height:1.45;padding-left:22px;margin:0;width:460px}li{margin-bottom:14px}</style><div class="s"><h1>'+esc(t.заголовок)+'</h1><div class="p">Кофейня «Зерно» · '+esc(d.period)+'</div><div class="g"><table><tr><td>Показатель</td><td>Было</td><td>Стало</td><td>Итог</td></tr>'+tr+'</table><ul>'+t.выводы.map(x=>'<li>'+esc(x)+'</li>').join('')+'</ul></div></div>';
return [{json:{заголовок:t.заголовок,выводы:t.выводы,проверка_чисел:unknown.length?'чисел нет в данных: '+unknown.join(', '):'ОК',html},binary:{slide:await this.helpers.prepareBinaryData(Buffer.from(html,'utf8'),'slide-zerno.html','text/html')}}];

Две строки стоит узнать в лицо. В строке с known код собирает все числа из данных и плана, в строке с unknown ищет в тексте модели числа, которых среди них нет. Результат попадает в поле проверка_чисел: «ОК» или «чисел нет в данных» со списком. На учебных цифрах в таблице выходит шесть строк, и у всех шести итог «на прежнем уровне».

Как показать слайд

Скачайте slide-zerno.html из вывода узла и откройте в браузере. Дальше два пути: сделать снимок экрана и вставить картинку в сообщение или презентацию, либо выбрать в браузере печать и сохранить страницу в PDF. В прогоне курса слайд смотрели в браузере и снимали снимком экрана, печать в PDF не пробовали.

Что показал прогон

Прогон 1. Числа были верными, но вид и текст подвели. Числа в таблице переносились посередине: «10 / 654» на двух строках. Выводы пересказывали таблицу, то есть повторяли то, что владелец и так видит слева. Модель написала «конверсии», хотя промпт просил без терминов, и «3.32» с точкой. Исправили так: в вёрстке запретили перенос внутри числа, в промпт добавили «НЕ пересказывай её» и «что это значит и что с этим делать», задали образец «10 994, 3,32». Проверку чисел научили понимать пробел между тысячами.

Прогон 2. Вёрстка чистая, проверка чисел «ОК». Вот этот слайд:

Слайд кофейни «Зерно» на светлом фоне. Заголовок: «Результаты недели стабильны: реклама работает без сбоев», под ним «Кофейня «Зерно» · 28.09–04.10 → 05.10–11.10». Слева таблица из шести строк с колонками Показатель, Было, Стало, Итог: Расход, ₽ 10 654 и 10 994; Клики 833 и 800; Доля кликнувших, % 3,61 и 3,32; Построили маршрут 53 и 52; Цена одного маршрута, ₽ 201 и 211; Визиты на сайт 1 228 и 1 216; у всех строк итог «на прежнем уровне». Справа три вывода: при расходе 10 994 рублей получили 1 216 визитов «в кофейню»; доля кликнувших 3,32 и цена целевого действия 211 рублей стабильны, «реклама приносит устойчивый поток»; на неделе проверяем посты «Закулисье», результат поймём по визитам с 1 216 до 1 338 за 7 дней. Смысловые ошибки в заголовке и первых двух выводах оставлены как пример.

Все числа на месте, и всё же слайд нельзя отправлять. Первый вывод говорит про «1 216 визитов в кофейню», а в таблице прямо написано «Визиты на сайт». Модель видела только слово «визиты» и додумала самое понятное владельцу. Заголовок «реклама работает без сбоев» данными не подтверждён: таблица говорит лишь, что за неделю ничего заметно не изменилось. Это разные утверждения.

Запуск с цифрами из таблицы. После того как слайд научился брать цифры из «Цифр недели», его запустили ещё раз. Период на слайде пришёл из таблицы, все шесть показателей тоже, проверка чисел «ОК». А в выводах снова натяжка: «52 гостя построили маршрут… реклама работает стабильно». Число верное, а вывод о рекламе из таблицы не следует. Это ошибка того же рода, что «визиты в кофейню».

Правило: проверка кодом ловит выдуманные числа, но не подмену смысла. Перед отправкой прочитайте слайд глазами владельца: что он поймёт из каждой фразы и правда ли это по таблице.

Чтение глазами владельца

Это последний шаг перед отправкой, и он ручной. Задайте себе три вопроса:

  • Тот ли это показатель? Визиты на сайт не равны гостям в зале, построенный маршрут не равен покупке.
  • Следует ли вывод из таблицы? Если все строки «на прежнем уровне», слова «растёт», «падает», «работает отлично» не подходят.
  • Понятно ли, что делать? Последний вывод должен называть проверку на следующую неделю и цифру, по которой судить.

Есть и вторая мера. Модели не хватило подписей, значит, их стоит дать ей прямо в промпте. Например, добавить к правилам такие строки:

- Подписи показателей: «визиты» — это визиты на сайт, не в кофейню; «конверсии» — гости, которые построили маршрут в Картах.
- Заголовок говорит только то, что видно из таблицы. Если все строки «на прежнем уровне», так и пиши: неделя без заметных изменений.
В прогоне курса не проверено. Подписи в промпт в прогоне не добавляли: и во втором прогоне, и в запуске с цифрами из таблицы промпт был тот же, что выше, и натяжка повторилась. Мы ожидаем, что с подписями таких ошибок станет меньше, но чтение глазами всё равно остаётся.

Если не получилось

  • «Цифры и план» пишет, что в таблице пусто. Отчёт 4.4 ещё ни разу не записал строку в «Цифры недели». Проверьте, что в нём есть узел «В таблицу цифр», и запустите отчёт формой.
  • «Слайд» падает на разборе ответа. Откройте вывод «Текста слайда». Если ответ обёрнут в ```json или начинается со слов, проверьте строку промпта «JSON без пояснений и без «`» и снимите обёртку в коде так же, как в узле «Проверка гипотез» урока 4.5.
  • Проверка чисел ругается на верное число. Скорее всего, модель написала его по-другому: с точкой вместо запятой или с пробелом, который код не снимает. Посмотрите, как число записано в выводе, и сравните с образцом «10 994, 3,32».
  • Число в таблице разрывается на две строки. В вёрстке ячеек с числами нужен запрет переноса (в CSS это white-space: nowrap).
  • Выводы повторяют таблицу. Проверьте, что в промпте есть «НЕ пересказывай её» и правило «что эти цифры значат для владельца и что с этим делать».

Контрольный вопрос. Проверка кодом ответила «ОК», а в выводе стоит «1 216 визитов в кофейню». Почему проверка это пропустила?

АКод не смог разобрать JSON модели
БКод сверяет только числа, а число 1 216 в данных есть
ВПорог шума скрыл эту строку от проверки
ГМодель записала число без пробела

Подсказка: Вспомните, что именно сравнивает узел «Слайд» с данными.

На курсе задания проверяются автоматически. Подобрать курс

Контрольный вопрос. Что на слайде делает код, а не модель? Выберите все верные варианты.

Выберите все верные варианты.

АПишет заголовок
БРисует таблицу «было/стало/итог»
ВСтавит пометку «на прежнем уровне» для шума
ГПишет три вывода
ДПроверяет, что числа из текста есть в данных

Подсказка: Модель отвечает JSON с двумя полями. Всё остальное делают узлы Code.

На курсе задания проверяются автоматически. Подобрать курс

Контрольный вопрос. Все шесть строк таблицы помечены «на прежнем уровне». Какой заголовок слайда честный?

АРеклама работает без сбоев
БНеделя без заметных изменений, план проверки готов
ВВизиты в кофейню падают
ГКлики выросли благодаря рекламе

Подсказка: Заголовок может говорить только то, что видно в колонке «Итог».

На курсе задания проверяются автоматически. Подобрать курс

Задание. МИССИЯ «Витрина отчёта». Запустите отчёт урока 4.4 с узлом «В таблицу цифр», чтобы в таблице «Цифры недели» была строка. Соберите в n8n сценарий слайда: запуск, Data Table «Последние цифры», Code «Цифры и план», Basic LLM Chain «Текст слайда», Code «Слайд». В «Цифрах и плане» впишите свои гипотезы из урока 4.5. Запустите, откройте slide-zerno.html в браузере и прочитайте слайд глазами владельца. Если нашли подмену смысла, добавьте в промпт подписи показателей и запустите ещё раз. Приложите: (1) системное сообщение «Текста слайда»; (2) снимок экрана слайда (или PDF); (3) вывод проверки чисел; (4) скриншот последней строки таблицы «Цифры недели»; (5) две-три фразы: что вы нашли при чтении глазами владельца и что поменяли. Принято, если: цифры слайд берёт из таблицы «Цифры недели», а не из чисел, вписанных в код; период на слайде совпадает с последней строкой таблицы; таблицу и пометку «на прежнем уровне» рисует код, а модель возвращает JSON только с заголовком и тремя выводами; проверка чисел есть и её результат приложен; на слайде шесть показателей с понятными подписями; заголовок и выводы не называют шум ростом или падением и не утверждают того, чего нет в таблице; последний вывод называет проверку на следующую неделю и цифру; персональные данные клиентов не указаны.

Подсказка: Если при чтении вы не нашли ни одной подмены смысла, это тоже результат: напишите, какие три вопроса задали себе и что ответили.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

На курсе задания проверяются автоматически. Подобрать курс

Что дальше

Слайд собирается по кнопке и берёт последние посчитанные недели. В практикуме модуля поставим его и мониторинг конкурентов на расписание по понедельникам и будем записывать итог каждого запуска в таблицу «Журнал аналитики».

Итог:
• цифры слайд берёт из последней строки таблицы «Цифры недели», её пишет отчёт 4.4;
• таблицу «было/стало/итог» и пометку «на прежнем уровне» рисует код, модель пишет только заголовок и три вывода;
• код проверяет, что каждое число из текста есть в данных;
• верные числа не гарантируют верный смысл: в прогоне визиты на сайт стали «визитами в кофейню», а ровная неделя «стабильной работой рекламы»;
• перед отправкой слайд читают глазами владельца, а подписи показателей стоит дать модели в промпте.

← Назад  ·  ↑ В начало урока  ·  ⌂ В начало курса  ·  Вперёд →

Школа Виктора Комлева