П/ВИН

KP Generator: AI-генератор КП-презентаций для B2B

·8 мин чтения
KP Generator: AI-генератор КП-презентаций для B2B

Есть задачи, которые кажутся простыми — «напишем промт, вставим в Stitch, получим красивый слайд». А потом ты начинаешь копать глубже: персонализация под каждого клиента, контроль над структурой слайдов, возможность менять дизайн-систему без кода, хранение кейсов, двухфазная генерация... И понимаешь, что перед тобой полноценный продукт. Именно так родился kp-generator — модуль для создания «лучшей в мире» B2B КП-презентации внутри germanyun.online.

Откуда вообще взялась задача

Программа «Секреты Корпорации» — это консалтинг по операционному управлению для малого и среднего бизнеса. Обещание простое и конкретное: рост прибыли 20–30% за 3 месяца без найма новых сотрудников. Но чтобы продавать такой продукт в B2B, недостаточно красиво рассказать на встрече — нужно коммерческое предложение, которое работает асинхронно: когда тебя нет рядом, клиент открывает PDF или Google Slides и сам проходит путь от «интересно» до «беру».

До этого в проекте уже был /generator — линейный визард, который генерил 3 документа через GPT-4o и @react-pdf/renderer: диагностику, КП и дорожную карту. Дизайн был базовый — бордовый фон, золотые акценты, стандартные таблицы. Работало, но не «вау».

Задача стала амбициознее: сделать КП-презентацию, которая визуально на уровне топовых западных агентств (Bento Grid, насыщенная красная акцентная палитра, светлый минимализм), при этом полностью персонализированную под каждого клиента — с его болями из диагностики, релевантными модулями программы, реальными кейсами.

И главное — с админкой, где можно тонко настраивать всё: порядок слайдов, промты для каждого слайда, дизайн-систему, кейсы, параметры генерации. Без деплоя, без правки кода.

Архитектура: от транскрипта до презентации

Первым делом я разобрал весь пайплайн данных:

Транскрипт звонка
    ↓ (существующий GPT-промт)
Структурированная диагностика (pointA[], keyFindings[])
    +
program-content.ts (10 модулей)
    +
Реальные кейсы
    +
Данные клиента (имя, бизнес, тариф)
    ↓
МЕТА-ПРОМТ (Claude/GPT)
    ↓
12 персонализированных Stitch-промтов
    ↓
Google Stitch → 12 слайдов → PDF / Google Slides

Ключевое решение — двухфазная генерация. Сначала мета-промт собирает все входные данные и генерирует 12 персонализированных промтов для Google Stitch. Потом каждый промт отправляется в Stitch и возвращает HTML-слайд. Это позволяет контролировать каждый слайд отдельно и переделывать точечно, не перегенерируя всё.

База данных: схема kp в Supabase

Для хранения конфигурации создал отдельную схему kp в Supabase — 5 таблиц:

-- Слайды с промтами
CREATE TABLE kp.slides (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  position INTEGER NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  stitch_prompt TEXT NOT NULL,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
 
-- Дизайн-система
CREATE TABLE kp.design_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  key TEXT UNIQUE NOT NULL,
  value TEXT NOT NULL,
  label TEXT
);
 
-- Кейсы клиентов
CREATE TABLE kp.cases (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  client_name TEXT NOT NULL,
  business_type TEXT,
  result TEXT NOT NULL,
  metric TEXT,
  is_active BOOLEAN DEFAULT true
);
 
-- Настройки генерации
CREATE TABLE kp.generation_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  key TEXT UNIQUE NOT NULL,
  value TEXT NOT NULL
);
 
-- Сгенерированные КП (история)
CREATE TABLE kp.generated_kps (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  client_data JSONB NOT NULL,
  slides_output JSONB,
  status TEXT DEFAULT 'pending',
  created_at TIMESTAMPTZ DEFAULT NOW()
);

PostgREST обновлён, чтобы видеть новую схему. TypeScript-интерфейсы сгенерированы автоматически.

12 слайдов: структура «Гибрид»

После ресёрча нескольких фреймворков (Gong's Nexus Model, Raskin's Arc, McKinsey, Prospeo 2026) выбрали гибридную структуру — она объединяет эмоциональный нарратив с data-driven доказательствами:

| # | Слайд | Логика | |---|-------|--------| | 1 | Титул + Обещание | Имя клиента, ключевой результат | | 2 | Контекст рынка | Почему сейчас важно | | 3 | Точка А | Персонализированный «диагноз» из транскрипта | | 4 | Цена бездействия | Что теряет каждый месяц | | 5 | Before / After | Трансформация операционки | | 6 | Методология | Toyota/Lean адаптация, 10 модулей | | 7 | Кейсы | 2–3 релевантных истории | | 8 | ROI-калькулятор | Конкретные цифры под бизнес клиента | | 9 | Программа | Релевантные модули из диагностики | | 10 | Процесс | Как выглядит работа | | 11 | Тариф + Гарантия | Оффер с защитой | | 12 | Следующий шаг | Конкретный CTA |

Каждый слайд хранится в БД с позицией, заголовком, описанием и Stitch-промтом — детальной инструкцией для AI-генерации визуала.

Backend: 6 API роутов

Архитектура API на Next.js App Router:

// app/api/generator/kp/slides/route.ts
export async function GET() {
  const { data, error } = await supabase
    .schema('kp')
    .from('slides')
    .select('*')
    .order('position');
  
  if (error) return NextResponse.json({ error }, { status: 500 });
  return NextResponse.json(data);
}
 
export async function POST(req: Request) {
  const body = await req.json();
  const { data, error } = await supabase
    .schema('kp')
    .from('slides')
    .insert(body)
    .select()
    .single();
  
  if (error) return NextResponse.json({ error }, { status: 500 });
  return NextResponse.json(data, { status: 201 });
}

Полный список роутов:

  • GET/POST /api/generator/kp/slides — список слайдов, создание
  • PUT/DELETE /api/generator/kp/slides/[id] — редактирование, удаление
  • POST /api/generator/kp/slides/reorder — drag-and-drop реордер
  • GET/PUT /api/generator/kp/settings — дизайн-система и параметры генерации
  • GET/POST/PUT/DELETE /api/generator/kp/cases — кейсы клиентов
  • POST /api/generator/kp/generate — двухфазная генерация КП

Двухфазная генерация: как это работает

Самый интересный роут — /generate. Он принимает данные клиента (имя, бизнес, тариф, итоги диагностики) и запускает двухфазный процесс:

Фаза 1 — Персонализация промтов:

// Для каждого активного слайда
const personalizedPrompts = await Promise.all(
  activeSlides.map(async (slide) => {
    const personalizedPrompt = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages: [{
        role: 'system',
        content: META_PROMPT // инструкция как персонализировать
      }, {
        role: 'user',
        content: `
          Слайд: ${slide.title}
          Базовый промт: ${slide.stitch_prompt}
          Клиент: ${clientData.name}, ${clientData.business}
          Диагностика: ${JSON.stringify(clientData.diagnosis)}
          Кейсы: ${JSON.stringify(relevantCases)}
        `
      }]
    });
    
    return {
      slideId: slide.id,
      prompt: personalizedPrompts.choices[0].message.content
    };
  })
);

Фаза 2 — Генерация в Google Stitch (или сохранение промтов для ручной вставки, в зависимости от режима).

Результат сохраняется в kp.generated_kps с полным JSON всех слайдов и статусом.

Frontend: 3-табный layout с Context

Навигация в /generator обновилась — добавился верхний уровень с тремя табами:

┌─────────────────────────────────────────┐
│  Генератор документов                   │
│  ┌──────────┐ ┌──────────┐ ┌────────┐  │
│  │Документы │ │Презентация│ │ Админ  │  │
│  │  (PDF)   │ │  (КП)    │ │        │  │
│  └──────────┘ └──────────┘ └────────┘  │
└─────────────────────────────────────────┘

Общее состояние через React Context — данные клиента заполняются один раз на табе «Документы» и доступны на всех вкладках без пробрасывания пропсов.

Админка: полный контроль без кода

Это, пожалуй, самая важная часть с точки зрения продукта. Четыре секции:

1. Слайды — drag-and-drop менеджер с inline-редактором каждого слайда. Можно менять порядок, включать/выключать слайды, редактировать промты прямо в интерфейсе. Сохраняется в Supabase.

2. Дизайн-система — настройки цветов, шрифтов, отступов. Выбрали светлый минимализм с насыщенным красным акцентом (не бордо — именно благородный насыщенный красный, #C0392B зона).

3. Кейсы — библиотека историй клиентов с результатами и метриками. При генерации система выбирает релевантные кейсы по типу бизнеса.

4. Настройки — параметры модели (GPT-4o / GPT-4o-mini), температура, режим генерации (промты для Stitch или полная автоматизация).

// Компонент drag-and-drop реордера
const SlidesManager = () => {
  const [slides, setSlides] = useState<Slide[]>([]);
  
  const handleDragEnd = async (result: DropResult) => {
    if (!result.destination) return;
    
    const reordered = Array.from(slides);
    const [moved] = reordered.splice(result.source.index, 1);
    reordered.splice(result.destination.index, 0, moved);
    
    // Optimistic update
    setSlides(reordered);
    
    // Сохраняем новый порядок
    await fetch('/api/generator/kp/slides/reorder', {
      method: 'POST',
      body: JSON.stringify(
        reordered.map((s, i) => ({ id: s.id, position: i + 1 }))
      )
    });
  };
  
  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="slides">
        {/* слайды */}
      </Droppable>
    </DragDropContext>
  );
};

Деплой: Dokploy и ручной запуск

После пуша на origin/main вебхук должен был автоматически триггернуть деплой через Dokploy. Но контейнер не обновился — Dokploy не знал, на какую ветку реагировать. Пришлось:

  1. Настроить ветку main в конфигурации сервиса
  2. Запустить деплой вручную через API Dokploy
  3. Дождаться билда (~3.5 минуты: клонирование репо → npm install → next build → старт контейнера)

Через SSH мониторинг показал успешный старт нового контейнера. API /api/generator/kp/slides начал отвечать 200.

Результат

За одну сессию пайплайна (brainstorming → дизайн-спек → ревью → реализация → деплой) создан полноценный модуль:

  • 21 файл, 3261 строка нового кода
  • 5 таблиц в Supabase с seed-данными (12 слайдов с детальными промтами)
  • 6 API роутов с полным CRUD
  • Админ-панель с 4 секциями
  • Двухфазная генерация промтов через GPT-4o
  • Drag-and-drop реордер слайдов
  • Деплой на germanyun.online/generator

Выводы

Главный урок этого проекта — граница между «набором промтов» и «полноценным продуктом» очень тонкая. Начинаешь с идеи «напишем 12 промтов для Stitch», а приходишь к системе с БД, API, админкой и двухфазной генерацией. Это не плохо — это правильно. Потому что промты без управления — это хрупкий артефакт. Промты с версионированием в БД и UI для редактирования — это инструмент, которым можно пользоваться и итерировать без разработчика.

Второй урок — персонализация критична для конверсии. Исследование Gong по 67К записям показывает 3.2x рост конверсии при персонализированных КП. Именно поэтому мы не сделали статичные промты — каждый слайд динамически адаптируется под данные конкретного клиента из диагностики. Это сложнее в реализации, но именно это создаёт разницу между «ещё одним КП» и презентацией, от которой клиент говорит «это про меня».

Третий урок — двухфазная архитектура даёт гибкость. Разделение «мета-промт → персонализированные Stitch-промты» и «Stitch-промты → слайды» позволяет работать в разных режимах: полная автоматизация, полуавтоматизация (промты генерируются, вставляются вручную), или только ручная работа. Один и тот же пайплайн данных, разные режимы исполнения.

Четвёртый урок — Dokploy надо настраивать заранее. Автоматический деплой по вебхуку — отличная фича, но она требует явной привязки ветки к сервису. Без этого молча не работает. Теперь в чеклист перед пушем добавил проверку конфигурации вебхука.

Дальше — тестирование на реальных клиентах, итерация по промтам на основе обратной связи и, возможно, полная интеграция с Google Stitch API для автоматической генерации слайдов без ручного шага.

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.

Связанный проект

Slides Generator