Речь и изображения

Кроме текстовых моделей во Flow есть три ноды, которые работают с файлами: Речь → Текст расшифровывает аудио, Текст → Речь озвучивает текст, Генерация изображения рисует картинку. Все три устроены одинаково: вы выбираете модель из общего медиа-каталога, нода сама находит нужного провайдера, вызывает его и кладёт результат в файловое хранилище воркспейса.

На бесплатном тарифе медиа-ноды доступны, но упираются в две вещи сразу: 100 кредитов в месяц без права уходить в минус (генерация картинок расходует их заметно быстрее текста) и публикация только в веб-чат — телеграм-бот, вебхук и расписание доступны на платном. Актуальные лимиты — на странице Тарифные лимиты.

Каталог медиа-моделей

Медиа-каталог отдельный от каталога текстовых моделей (Каталог моделей) и собирается из живого API вендора, поэтому конкретные модели приходят и уходят между релизами. Сегодня доступно 38 моделей для изображений, 18 для синтеза речи и 4 для распознавания.

Пересчитать по репозиторию:

grep -o "modality: \(image\|tts\|stt\)" backend/config/media/openrouter.yaml | sort | uniq -c

Форма ноды меняется вместе с моделью

Это первое, что удивляет. Собственных полей у медиа-ноды немного, и они одни и те же при любой модели: Модель и необязательный ID подключения со своим ключом есть у всех трёх; у генерации изображения к ним добавляется Промпт, а у изображения и синтеза речи — ещё Режим ноды и настройки работы в роли инструмента агента. Зато всё, что описывает саму картинку или голос — размер, качество, число изображений, голос, формат, — приезжает из выбранной модели: каждая запись каталога несёт собственное описание параметров, и редактор строит форму по нему. Смените модель — часть этих полей исчезнет, часть появится, значения по умолчанию станут другими.

Настройки ноды «Генерация изображения»

Size, Quality и Number of images приходят из выбранной модели

Модель*
OpenAI: GPT Image 1
Промпт
Акварельная красная панда на ветке бамбука

Используется, когда вход 'prompt' не подключён

Size
1024x1024
Quality
medium
Number of images
1
ID подключения
Ключ платформы

Пусто — ключ платформы

Так сделано потому, что вендоры не договорились между собой: у одной модели картинки задаются размером 1024x1024, у другой — соотношением сторон 16:9, у третьей есть прозрачный фон и уровень сжатия. Держать объединение всех параметров в одной форме значило бы показывать поля, которые выбранная модель отвергнет ошибкой 400.

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

  • Параметры не переносятся между моделями. Ключ, которого нет в схеме новой модели, при запуске молча отбрасывается, а не отправляется провайдеру.
  • Список параметров — это то, что вендор про модель сообщил. Он неполон: например, какие именно форматы аудио принимает конкретный синтез речи, discovery не раскрывает, и такие частности приходится править вручную в каталоге платформы.
  • Свободные текстовые параметры рендерятся как шаблоны. В подсказку для распознавания речи можно подставить {{ variables.glossary }}. Параметры со списком значений (голос, формат, размер) шаблонами не рендерятся: подстановка могла бы только превратить допустимое значение в недопустимое.

Распознавание речи

Речь → Текст
AudioText

На вход — файл (audio), на выходе — текст. Файл может прийти откуда угодно: вложение из чата, голосовое сообщение из телеграма, файл из хранилища. Параметров у моделей распознавания минимум — язык и необязательная подсказка с именами и жаргоном, которая заметно улучшает расшифровку на терминах.

Вход
Речь → Текст
ИИ-агент
Выход
  • Исполнение + данные
  • Исполнение + данные + стрим
Голосовое сообщение → текст → ответ агента.

Синтез речи

Текст → РечьT
TextAudio

На вход — текст, на выходе — аудиофайл. Главная особенность: голос почти везде обязателен и публикуется отдельно для каждой модели. Голоса не общие — у одного вендора это Zephyr и Puck, у другого aura-2-thalia-en, и список у каждой модели свой. Поэтому голос — тоже параметр модели, а не поле ноды: каталог подставляет первый голос по умолчанию, чтобы только что добавленная нода запускалась без ручной настройки.

Из 18 моделей синтеза у 12 каталог перечисляет конкретные голоса выпадающим списком; у остальных голос — свободная строка (там вендор ждёт идентификатор голоса из вашего личного кабинета, в том числе клонированного). Пересчитать:

python3 -c "import yaml;m=yaml.safe_load(open('backend/config/media/openrouter.yaml'))['models'];t=[x for x in m if x['modality']=='tts'];print(len(t), sum(1 for x in t if x['param_schema']['properties']['voice'].get('enum')))"

Генерация изображений

Генерация изображенияT
PromptImages
Input image

Одна нода закрывает оба режима, и переключателя между ними нет:

  • По тексту (text2img) — вход image ничем не занят, картинка рисуется по промпту.
  • По тексту и картинке (img2img, правка) — во вход image приходит файл, и он уезжает провайдеру как референс. Режим определяется наличием ребра, а не галочкой в настройках.

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

Вход
Генерация изображенияT
Выход
  • Исполнение + данные
  • Данные
Правка присланного фото: картинка приходит по чистому data-проводу, текст запускает ноду.

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

python3 -c "import yaml;m=yaml.safe_load(open('backend/config/media/openrouter.yaml'))['models'];i=[x for x in m if x['modality']=='image'];print(len(i), sum(1 for x in i if not ((x.get('capabilities') or {}).get('accepts_input_image') or (x.get('capabilities') or {}).get('requires_input_image'))))"

Ещё один честный отказ: если провайдер ответил успехом, но без картинки (обычно это срабатывание его же контентной политики), нода считается упавшей, а не успешной с пустым результатом. Ветку on_error у неё можно включить, как у любой ноды-шага.

Куда девается сгенерированный файл

Ни одна из трёх нод не возвращает байты в граф. Результат сохраняется в файловое хранилище воркспейса, а по проводу едет ссылка: метаданные (имя, mime-тип, размер) и локатор вида filestore://…. Байты подгружаются только тем, кому они действительно нужны — например, когда файл уходит модели или пользователю.

Так сделано по трём причинам: результат виден в разделе Файлы и не теряется вместе с логом выполнения; журнал выполнения не раздувается вложенным base64; и один и тот же файл можно передавать между нодами, не копируя его.

Чтобы файл увидел пользователь, соедините выход ноды со входом files ноды Выход — это отдельный порт именно для файлов (Вход и выход). В чате картинка покажется картинкой, аудио — проигрывателем, остальное — вложением.

Вход
ИИ-агент
Текст → РечьT
Выход
  • Исполнение + данные
  • Исполнение + данные + стрим
  • Данные
Озвучка ответа: текст уходит и в ответ, и в синтез речи, а файл прицепляется к тому же сообщению.

Картинка и озвучка как инструменты агента

Генерация изображения и Текст → Речь умеют работать не шагом графа, а инструментом, который агент вызывает сам, когда сочтёт нужным. Переключатель — поле режима работы в настройках ноды: в режиме шага у ноды обычные порты запуска и результата, в режиме инструмента — только выход подключения к агенту. Подробно про этот механизм — Инструменты агента.

Что важно знать про инструментальный режим:

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

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

Ключи провайдера

Откуда ключЧто настроитьКогда применяется
Ключ платформыпеременная окружения OPENROUTER_API_KEY на серверепо умолчанию, поле интеграции пустое
Свой ключ (BYO)интеграция вида OpenRouter в разделе «Интеграции» и выбор её в поле нодыкогда выбрана в настройках конкретной ноды

Ключ выбирается на каждой ноде отдельно, полем в разделе дополнительных настроек (— выберите подключение — означает «ключ платформы»). Интеграция заводится в НастройкиИнтеграции кнопкой Добавить интеграцию; см. Интеграции.

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

Каталог загружается и без ключа: модели видны в списке, ошибка приходит при запуске. Пустой список моделей у ноды означает, что каталог не загрузился вовсе — это проблема установки, а не настройки воркфлоу.

Сколько это стоит

Каждая генерация — отдельная строка расхода Генерация медиа в разделе Использование. Цена берётся одним из двух способов:

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

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

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

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

СимптомПричинаЧто делать
«Unknown media model» при запускемодель исчезла из каталога вендораоткрыть ноду и выбрать модель заново
Список моделей в ноде пусткаталог не загрузилсяпроверить установку сервера; настройкой воркфлоу это не лечится
Ошибка про отсутствие ключанет ни ключа платформы, ни интеграцииуказать интеграцию OpenRouter в поле ноды
Порт входной картинки пропалвыбранная модель не принимает референсвыбрать модель, которая умеет img2img
«Модель не принимает входное изображение»ребро осталось от прежней моделиудалить ребро или вернуть прежнюю модель
Нода упала, хотя провайдер ответил успехомответ без картинки — обычно контентная политикапереформулировать промпт
Файл сгенерировался, но пользователь его не видитвыход не подключён к порту files ноды Exitсоединить с портом files