Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда. BI.. BI. datalens.. BI. datalens. llm.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure. Блог компании Яндекс.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure. Блог компании Яндекс. бэкенд-разработка.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure. Блог компании Яндекс. бэкенд-разработка. Веб-разработка.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure. Блог компании Яндекс. бэкенд-разработка. Веб-разработка. искусственный интеллект.. BI. datalens. llm. Блог компании Yandex Cloud & Yandex Infrastructure. Блог компании Яндекс. бэкенд-разработка. Веб-разработка. искусственный интеллект. Машинное обучение.
Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда - 1

Привет, это Андрей Мелихов, ведущий разработчик интерфейсов в Yandex Cloud. Я работаю в команде DataLens — BI‑системы для визуализации больших наборов данных на дашбордах и графиках. 

В прошлом году в DataLens появился чат‑интерфейс: пользователь общается с ИИ‑ассистентом, который строит графики, пишет формулы и решает аналитические задачи. В рамках работы над этим продуктом, который получил имя Нейроаналитик, мы пошли не совсем очевидным для многих путём и перераспределили ответственность между командами фронтенда и бэкенда. В статье хочется поделиться этим опытом: внутри вы найдёте демо‑проект в репозитории, чтобы самим увидеть нашу идею изнутри.

ИИ, бэкендеры и фронтендеры

Подключение LLM к продукту — задача, с которой сегодня сталкиваются многие команды. Обычно за неё берётся бэкенд. Мы выбрали другой подход: первый этап интеграции с моделью взяла на себя фронтенд‑команда и считаем, что у такого подхода есть конкретные преимущества.

Важная ремарка. Под фронтендерами мы (как минимум наша команда DataLens) понимаем скорее фуллстек‑инженеров с уклоном в UX и JavaScript/TypeScript. В нашей зоне ответственности как браузерный, так и серверный код на node.js, собственные CI/CD‑пайплайны и DevOps, обслуживающий задачи фронтенда. Но интерфейсы нам всё же ближе, чем данные.

Итак, типичный сценарий: бэкенд интегрирует LLM, поднимает эндпоинты, а фронтенд подключается к ним и рисует красивый интерфейс чата. Рабочая схема, но возникает вопрос о распределении ответственности. Действительно ли вся интеграция с моделью должна лежать на бэкенде?

Фронтенд‑команды обладают собственной технической экспертизой: умеют строить BFF (бэкенд для фронтенда), могут напрямую взаимодействовать с API, и именно они проектируют интерфейс. А в ИИ‑продукте интерфейс — не менее важная часть, чем модель. Помимо этого, у фронтенда есть конкретные преимущества на этапе интеграции:

  • Данные уже под рукой. В современных интерфейсах сходятся данные из множества бэкендов. Если нужно построить ИИ‑инструмент поверх — контекст уже на клиенте, и дозапросить нужное несложно.

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

  • Меньше координации на старте. BFF на Node.js — это привычная инфраструктура. Подключился к совместимому API и можно двигаться, не блокируя другие команды.

Это не значит, что бэкенду здесь нечего делать — с развитием продукта неизбежно появляются задачи, которые должны решаться на сервере. Но начать можно силами фронтенда, и результат будет вполне продуктовым.

Архитектура: как это устроено

В выбранной архитектуре между клиентом и LLM добавляется слой BFF, например на Node.js или Bun, хотя конкретная технология не принципиальна — аналогичное решение можно реализовать и на Python, если фронтенд‑команда готова поддерживать решения на других языках. Это важно, так как классический BFF занимается подготовкой view‑ориентированных данных и находится в зоне ответственности команды разработки фронтенда.

В нашем случае этот слой берёт на себя в том числе и взаимодействие с моделью. Существующий бэкенд остаётся без изменений — интеграция на первом этапе фактически переносится в зону ответственности фронтенд‑команды.

Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда - 2

Схема привычна с точки зрения фронтенд‑разработчика — по сути, просто появляется дополнительный бэкенд. В периметре BFF находятся ключи доступа, реализуется работа с rate limiting и CORS, настраивается мониторинг и логирование. Таким образом, логика взаимодействия с API LLM переносится на сервер — на тот бэкенд, который «бэкенд для фронтенда». 

Чтобы показать, как это выглядит на практике, я собрал демо‑проект на GitHub — монорепозиторий с сервером на Express и клиентом на React. Интерфейс реализует упрощённую BI‑систему: слева дашборд, справа — ИИ‑ассистент. Сценарий использования: пользователь запрашивает, скажем, топ-5 продуктов: ассистент обращается к функции getChartData, получает данные и формирует ответ на их основе.

Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда - 3

Прототип я собрал, конечно, с помощью ИИ. Сначала составил план в Superpowers, затем код‑ассистент всё это реализовал, я проверил результат и подключил Gravity UI для отрисовки интерфейса. В итоге получилось рабочее приложение с простой кодовой базой, которую можно изучить в репозитории.

Цель этого примера — показать, что для фронтенд‑разработчика, знакомого с Express, реализация базовой интеграции с LLM не представляет особой сложности. А дальше уже можно наращивать: тулинг, контекст, продвинутые сценарии.

Что же нам нужно для того, чтобы реализовать интеграцию с LLM в реальном продукте?

Четыре компонента интеграции

Для добавления ИИ в продукт фронтенд‑разработчику понадобятся четыре вещи:

  1. UI‑кит — компоненты для чат‑интерфейса.

  2. API SDK — библиотека для общения с LLM.

  3. Тулинг — механизм, позволяющий модели вызывать функции и получать данные.

  4. Контекст — данные и состояние приложения, которые передаются модели вместе с запросом.

Разберём каждый.

UI-кит

Антон Непша сделал хороший обзор UI‑китов для создания ИИ‑агентов: там и AI Elements от Vercel, и опенсорс‑решения вроде Assistant UI, prompt‑kit, shadcn‑chatbot‑kit.

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

Мы используем AIKit от команды Gravity UI. У него проработанный визуал, корректная отрисовка ответов, встроенная история вызовов — и не нужно вручную подключать обработку маркдауна или расширения вроде GFM для таблиц. Кстати, мой коллега Илья Ломтев уже писал о нём на Хабре.

Сейчас AIKit внедряется во все продукты Yandex Cloud, включая консоль и SourceCraft. Это значит, что он будет активно развиваться — в нём появится функциональность, нужная разным командам.

Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда - 4

Конечно же, в моём демо доступна версия с AIKit — она заметно симпатичнее. Эта версия лежит в отдельной ветке.

API SDK

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

Сегодня провайдеров и моделей множество, но хорошая новость в том, что большинство ориентируется на совместимость с OpenAI API. Поддержан OpenAI API и в Yandex AI Studio — про это, конечно же, тоже есть статья на Хабре. Смена baseURL позволяет использовать Mistral, Groq, Fireworks, Ollama, Together, xAI и другие платформы. Для разработчика это означает: один клиент — много моделей.

Стоит отметить: помимо OpenAI API, рынок снова присматривается к поддержке Anthropic API — во многом благодаря популярности Claude Code и желанию провайдеров привлечь его пользователей. Но в остальном OpenAI API доминирует.

Во многих туториалах сразу предлагают использовать LangChain. Инструмент мощный — есть реализации на Python, JavaScript/TypeScript, Java, Go,.NET. Но начинать с него, на мой взгляд, не стоит. Это очень высокоуровневая абстракция, которая скрывает слишком много. Дебажить её непросто — часто требуются отдельные инструменты вроде LangSmith для трассировки.

Начинать с LangChain — как изучать веб‑разработку с React. Сначала стоит понять, как всё работает на уровне API, а LangChain (или аналоги) подключить, когда проект разрастётся.

Давайте возьмём OpenAI SDK для Node.js. Минимальный пример:

import OpenAI from "openai";

const openai = new OpenAI({ apiKey, baseURL });

const completion = await openai.chat.completions.create({

  messages: [

    { role: "system", content: "Ты очень умный ассистент." },

    { role: "user", content: "Что умеют большие языковые модели?" }

  ],

  model: "gpt://<идентификатор_каталога>/yandexgpt/latest",

});

console.log(completion.choices[0]);

Создаём клиент, передаём массив сообщений, system задаёт поведение модели, user содержит запрос. Вся коммуникация строится как цепочка сообщений — на этом и основан Chat Completions API.

Ответ API включает usage с количеством токенов (полезно для логирования и контроля затрат) и choices с результатом. Забираем текст, отображаем в интерфейсе — чат готов.

Но без тулинга такая система — просто красивая обёртка над генерацией текста. Модель ничего не знает о данных в вашем продукте.

Тулинг

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

В 2023 году OpenAI добавили в API возможность передавать модели список доступных функций. Теперь модель может явно сообщить: «Хочу вызвать вот эту функцию с такими параметрами». Аналогичный подход используется в MCP — разработчик описывает инструменты, а модель учится их вызывать.

Как это выглядит на практике? В параметре tools передаём описание доступных функций:

const completion = await openai.chat.completions.create({

  messages: [

    { role: "system", content: "Ты аналитик." },

    { role: "user", content: "Проанализируй дашборд с чартами: цены, магазины, доходность" }

  ],

  tools,

});

Описание инструмента — это JSON, где указано название функции, её назначение и параметры. Например: «У тебя есть функция getChartData, которая принимает массив ID чартов и возвращает их данные».

В ответ модель возвращает массив tool_calls — список функций, которые хочет вызвать:

[

  {

    "id": "chatcmpl-tool-087c7a6c...",

    "type": "function",

    "function": {

      "name": "getChartData",

      "arguments": "{"chartIds": ["цены", "магазины", "доходность"]}"

    }

  }

]

Дальше — дело разработчика. Вызываем реальную функцию, получаем данные и возвращаем результат модели в сообщении с ролью tool:

{

  role: "tool",

  tool_call_id: "chatcmpl-tool-087c7a6c...",

  content: JSON.stringify([

    { chartId: "цены", описание: "средний чек 500р" },

    { chartId: "магазины", описание: "Два магазина, один другого хуже" },

    { chartId: "доходность", описание: "Никакая" }

  ])

}

Полный массив сообщений, который уходит модели на следующем шаге:

messages: [

  { role: "system", content: "Ты аналитик." },

  { role: "user", content: "Проанализируй дашборд со ..." },

  { role: "assistant", content: null, tool_calls: [...] },

  { role: "tool", tool_call_id: "chatcmpl-tool-...", content: "..." },

]

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

Responses API: что дальше

OpenAI представили новый Responses API и предлагают постепенно переходить к нему от Chat Completions. По их словам, предыдущий API был спроектирован и развёрнут в крайне сжатые сроки, но быстро стал настолько востребованным, что лёг в основу значительной части современных интеграций с LLM. Буквально, в пятницу задизайнили, а во вторник она была доступна по всему миру. И вот уже все завязаны на этот API.

Эволюция OpenAI API отражает то, как менялись потребности разработчиков:

  • Первое поколение — простая схема «запрос → ответ».

  • Второе поколение — Chat Completions, адаптированный под диалог.

  • Третье поколение — Responses API, заточенный под агентные сценарии.

Responses API встраивает в себя RAG, function calling, поиск — всё, что раньше приходилось собирать вручную. Для фронтенд‑разработчика это упрощает жизнь ещё сильнее: нужен BFF на Express, обращение к API, а остальная магия — внутри.

Правда, есть нюанс доверия: передача данных стороннему провайдеру означает, что информация хранится вне вашего периметра. Для продуктовых решений это не всегда приемлемо. Но концепция «агентность по умолчанию» набирает обороты и упрощает порог входа.

Контекст

Если отправить модели два сообщения по отдельности — сначала представиться, потом спросить «как меня зовут?» — она не ответит. У LLM нет памяти. Она опирается только на то, что передано в текущем запросе.

Поэтому в каждом обращении нужно отправлять историю переписки. Но на практике одной истории чата мало. Для нормальной работы ИИ‑функциональности в продукте модели нужен более широкий контекст.

Проблема в том, что контекстное окно ограничено: 128–256 тысяч токенов, у некоторых моделей — до миллиона. Но даже при большом окне модели не всегда эффективно используют весь объём — они фокусируются на части переданных данных. Возникает инженерная задача: какие фрагменты передавать, а какие отбросить?

Если рассматривать DataLens Editor, то значимым контекстом становится не только история чата. 

Добавим приставку нейро: взгляд на интеграцию LLM в продукт со стороны фронтенда - 5

Модели нужно знать о коде пользователя, о результатах выполнения, об ошибках в консоли. Всё это живёт на клиенте. И это территория фронтенда — бэкенд до этих данных не добирается.

Вот что делает управление контекстом BI‑системы сложной задачей:

  • Данные могут быть огромными. Микротаблицу в нашем простом примере легко уложить в контекст. В реальности данные разбиты на страницы, и передать их целиком зачастую невозможно.

  • Модели плохо считают. Если дать LLM большой массив чисел и попросить посчитать среднее — нет гарантий, что модель учтёт все данные. Точные вычисления нужно делать на стороне приложения.

  • Контекст быстро растёт. С каждым сообщением и каждым вызовом инструмента объём передаваемых данных увеличивается.

Степень участия бэкенда зависит от архитектуры. Если основная логика на сервере — часть задач можно делегировать ему. Однако клиентский контекст — код, состояние интерфейса, результаты выполнения — доступен только фронтенд‑слою. Поэтому даже при классической архитектуре фронтенд‑разработчикам приходится самостоятельно управлять этим объёмом информации. В крупных приложениях контекста становится особенно много, и его обработка превращается в отдельную инженерную задачу.

С развитием продукта неизбежно появляются задачи, которые нужно решать на бэкенде: фоновые длительные операции, взаимодействие с клиентом через API. Но реализовать их на бэкенде (будь то Python или Node.js) будет значительно проще, если в качестве работающего примера перед глазами уже есть полезная фича на клиенте.

Работы хватит всем

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

Здесь хватает серьёзных инженерных задач: управление клиентским контекстом и его размером, проектирование удобных ИИ‑интерфейсов, работа со стримингом и function calling. Форматы взаимодействия тоже продолжают меняться: ещё недавно все сидели в IDE, а сейчас набирают популярность консольные агенты. Всё это указывает на то, что пространство для работы в этой области только расширяется.

Фронтенд‑команда может взять на себя интеграцию с LLM и получить продуктовый результат с понятной архитектурой, знакомым стеком и готовыми SDK. А по мере роста продукта подключатся и бэкендеры — для фоновых операций, масштабирования и более глубокой интеграции.

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

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

Автор: melikhov-dev

Источник