Содержание

Встроить LLM в продукт — значит не просто вызвать API модели, а построить вокруг неё слой, который готовит контекст, проверяет ответ, считает стоимость и переживает ошибки провайдера. Сам вызов занимает пару строк кода; основная работа — в данных, которые вы передаёте модели, и в проверке того, что она вернула. С этого и стоит начинать проектирование.

Ниже — архитектура, которую мы используем для AI-функций, и подводные камни, которые обычно всплывают уже после запуска.

С чего начать интеграцию LLM в продукт?

Начинать стоит с одной конкретной задачи пользователя и способа измерить, хорошо ли модель её решает. «Добавить AI» — не задача; «сократить время ответа поддержки на типовые вопросы» или «извлекать реквизиты из загруженных счетов» — задача, у которой есть метрика и понятная цена ошибки.

Перед разработкой ответьте на четыре вопроса:

  1. Что пользователь получает на выходе и в каком формате — текст, структурированные данные, действие в системе?
  2. Какие данные нужны модели, чтобы ответить правильно, и где они лежат?
  3. Что будет, если модель ошибётся, — и кто это заметит?
  4. Сколько запросов в день ожидается и какой бюджет на них допустим?

Ответ на третий вопрос определяет архитектуру сильнее всего. Черновик письма, который человек перечитает, прощает ошибки. Автоматическое изменение цены в каталоге — нет.

Как устроена архитектура AI-функции?

Архитектура AI-функции состоит из нескольких слоёв вокруг модели: сбор контекста, шаблон запроса, вызов через шлюз с лимитами, проверка ответа и журналирование. Модель в этой схеме — заменяемый компонент, а ценность продукта — в остальных слоях.

Слой Что делает Зачем
Сбор контекста Достаёт нужные данные: документы, историю, профиль Модель знает только то, что ей передали
Шаблон запроса Инструкции, примеры, формат ответа — с версией Изменения промпта отслеживаются, как код
LLM-шлюз Выбор модели, ретраи, таймауты, лимиты затрат Смена провайдера не трогает бизнес-логику
Валидация ответа Проверка структуры, допустимых значений, запретов Ошибка модели не попадает к пользователю
Журнал и оценка Сохраняет запросы, ответы, стоимость, отзывы Видно качество и стоимость на реальных данных

Абстрактная сфера из точек и линий Фото: Unsplash

Структурированный ответ вместо свободного текста

Если результат обрабатывает код, а не человек, просите модель вернуть данные по схеме и проверяйте их так же строго, как ввод пользователя. Большинство провайдеров поддерживают структурированный вывод и вызов инструментов.

import { z } from 'zod'

const Invoice = z.object({
  supplier: z.string().min(1),
  total: z.number().positive(),
  currency: z.enum(['RUB', 'USD', 'EUR']),
  dueDate: z.string().date(),
})

export async function extractInvoice(text: string) {
  const raw = await llm.complete({
    prompt: prompts.get('invoice-extract', 'v3'),
    input: text,
    responseFormat: 'json',
    maxCostUsd: 0.02,
  })
  const parsed = Invoice.safeParse(JSON.parse(raw))
  if (!parsed.success) {
    // Не угадываем: отправляем документ на ручную проверку
    return { status: 'needs_review', errors: parsed.error.issues }
  }
  return { status: 'ok', invoice: parsed.data }
}

Здесь llm — ваш шлюз, а не SDK конкретного провайдера, и промпт хранится с версией. Это позволяет поменять модель или улучшить инструкции, не переписывая функцию.

Как выбрать модель и провайдера?

Модель выбирают по результату на ваших данных, а не по рейтингам: соберите 50–100 реальных примеров с правильными ответами и прогоните их через несколько моделей. Часто оказывается, что для конкретной задачи хватает быстрой и дешёвой модели, а мощную стоит оставить для сложных случаев.

Что ещё учитывают при выборе:

  • где обрабатываются данные — для персональных и коммерческих данных важны регион и условия провайдера;
  • задержка — чат-интерфейсу нужен потоковый ответ, фоновой обработке — нет;
  • стоимость на объёме — умножьте средний размер запроса на ожидаемое число вызовов;
  • открытые модели — развёртывание у себя даёт контроль над данными, но требует GPU-инфраструктуры и команды.

Шлюз в архитектуре позволяет не делать выбор навсегда: маршрутизировать простые запросы на дешёвую модель, сложные — на мощную, и переключаться при сбоях.

Какие подводные камни появляются после запуска?

После запуска проблемы возникают там, где их не видно на демо: на редких входных данных, на объёме и в стоимости. Модель, которая отлично работала на десяти примерах, начинает ошибаться на тысяче реальных.

Что мы закладываем заранее:

  • Оценка качества на наборе примеров при каждом изменении промпта или модели — как регрессионные тесты.
  • Лимиты стоимости на запрос, пользователя и день, с оповещением при превышении.
  • Кеширование одинаковых запросов и переиспользование контекста там, где провайдер это поддерживает.
  • Защита от prompt injection: данные пользователя и документы не должны менять инструкции модели и не должны давать ей права на опасные действия.
  • Запасной путь: что видит пользователь, если провайдер недоступен или ответ не прошёл проверку.

Отдельно — персональные данные. Прежде чем отправлять их внешнему провайдеру, проверьте, что это разрешено вашей политикой и законом, и по возможности маскируйте всё, что не нужно для ответа.

Как встроить AI-функцию в существующую архитектуру?

AI-функцию проще всего встроить как отдельный модуль с чётким интерфейсом внутри существующего приложения, а тяжёлые вызовы выполнять в фоновых задачах. Выделять под неё отдельный сервис с первого дня обычно не нужно — те же рассуждения, что и в статье о монолите и микросервисах.

Практические правила:

  1. Долгие вызовы — через очередь задач, а пользователь видит статус или получает потоковый ответ.
  2. Промпты и схемы ответа — в репозитории, с версиями и ревью, как обычный код.
  3. Каждый вызов логируется с версией промпта, моделью, стоимостью и временем ответа.
  4. Пользователь может оценить ответ — это лучший источник примеров для улучшений.

Коротко

  • Начинайте с конкретной задачи, метрики и понимания цены ошибки, а не с выбора модели.
  • Модель — заменяемый компонент; ценность — в контексте, валидации и журналировании вокруг неё.
  • Просите структурированный ответ и проверяйте его так же строго, как ввод пользователя.
  • Выбирайте модель по тестам на своих данных и закладывайте лимиты стоимости с первого дня.
  • Встраивайте AI как модуль существующего приложения, а тяжёлые вызовы выносите в фон.

Частые вопросы

  • Нужно ли дообучать модель под свой продукт?

    Чаще всего нет. Большинство задач решаются хорошими инструкциями, примерами в запросе и передачей нужных данных через поиск по документам. Дообучение имеет смысл, когда этого не хватает и есть тысячи качественных примеров.

  • Сколько времени занимает разработка первой AI-функции?

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

  • Можно ли использовать LLM без отправки данных внешнему провайдеру?

    Да, через открытые модели, развёрнутые на своих серверах или в частном облаке. Это даёт контроль над данными, но требует GPU и команды для эксплуатации, а качество может уступать лучшим коммерческим моделям.

  • Как понять, что AI-функция окупается?

    Сравните метрику задачи до и после — время обработки, долю автоматически решённых обращений, конверсию — с затратами на вызовы и поддержку. Если метрику нельзя измерить, окупаемость тоже не посчитать.