Как стать автором
Обновить

api2app: Как из домашнего компьютера сделать сервер для публичного приложения

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров2.4K

Ранее я уже рассказывал, что при разработке api2app вдохновлялся идеей Python-библиотеки Gradio. У этой библиотеки есть очень полезный функционал: можно запустить приложение на локальном компьютере в режиме share (поделиться), тогда будет сгенерирована публичная ссылка, по которой это приложение будет доступно на любом другом компьютере через Интернет.

В этой статье пошагово опишу свой способ. Есть свои плюсы и свои минусы, но в любом случае, думаю, альтернатива не будет лишней. Для примера создам онлайн-приложение для создания транскрипций аудио с помощью проекта whisper.cpp. Делаю всё на Ubuntu, но, думаю, на Windows это повторить будет не сложно.

Установка whisper.cpp

Клонирую репозиторий и перехожу в папку:

git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp

Делаю сборку:

cmake -B build
cmake --build build --config Release

Скачиваю модель medium (~1.5 GB):

bash ./models/download-ggml-model.sh medium

Если скачивание не сработало, можно попробовать в bash-скрипте заменить домен "huggingface.co" на "hf-mirror.com".

Проверяю работу:

./build/bin/whisper-cli --model ./models/ggml-medium.bin \
--language en \
--output-txt \
--file samples/jfk.wav

В папке "samples" должен появиться файл "jfk.wav.txt" с транскрипцией.

Создание обработчика запросов

Сначала нужно создать задачу в Менеджере задач. Открываю приложение: https://api2app.org/ru/apps/shared/666e778a-f6a5-11ef-861d-525400f8f94f

Менеджер очередей
Менеджер очередей

Заполняю поля, нажимаю кнопку "Создать задачу" - получаю идентификатор задачи и API-ключ.

Данное приложение использует API, исходный код которого можно найти здесь:
https://github.com/andchir/queue-manager

Клонирую репозиторий и перехожу в папку:

git clone https://github.com/andchir/queue-manager.git
cd queue-manager

Создаю виртуальное окружение Python и активирую его:

python3.12 -m venv venv
source venv/bin/activate

Локально мне не нужно устанавливать полностью это приложение, поэтому я устанавливаю только минимальное число зависимостей:

pip install -r requirements-min.txt

Создаю .env файл, в котором будут мои локальные настройки:

cp .env-dest .env

В этом файле мне нужно изменить домен API менеджера очередей:

APP_SERVER_NAME=queue.api2app.org

Клонирую дополнительный репозиторий с обработчиками запросов. Я их назвал воркерами (workers):

git clone https://github.com/andchir/api2app-workers.git

Тут уже есть готовый воркер для whisper.cpp, но я опишу немного подробнее как я его создал. Создаю новый файл "whisper-cpp.py" в папке "api2app-workers" пока с таким содержанием:

import os
import sys
import subprocess

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.queue_manager import polling_queue, upload_queue_files, send_queue_error

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def processing(queue_item):
    upload_dir_path = os.path.join(ROOT_DIR, 'uploads', 'whisper')

    # Загрузка всех файлов в локальную папку
    image_file_path, audio_file_path, video_file_path, image_file_path2 = upload_queue_files(queue_item, upload_dir_path)

    print('Получена новая задача', queue_item['uuid'])
    print('Аудио файл:', audio_file_path)

    # Отправка ошибки выполнения
    send_queue_error(queue_item['uuid'], 'Error.')


if __name__ == '__main__':
    # Опрос на появление новых задач
    polling_queue('ea474c9a-c631-4bac-9141-ba26b0ff56c5', processing)

Я думаю из этого кода вы поняли, что функция polling_queue делает периодические запросы к серверу, используя ID задачи, который я получил ранее. Если задача пришла, запускается функция processing.

Теперь мне нужно протестировать работу этого воркера. Я отправлю запрос для создания новой задачи. Нужно отправить аудио-файл, используя ID задачи и API ключ, которые я получил ранее на сайте api2app.org. Позже я создам графический интерфейс для этого, но пока могу отправить запрос с помощью curl:

curl -X POST \
-F "audio_file=@/path/to/audio.mp3" \
-F 'data={"language": "en", "output_type": "txt"}' \
-H "Accept: application/json" \
-H "API-KEY: 47688355-a431-4bc3-8913-35115b2da36c" \
"https://queue.api2app.org/queue/ea474c9a-c631-4bac-9141-ba26b0ff56c5"

Запущу воркер:

python api2app-workers/whisper-cpp.py

Если всё в порядке, должен быть примерно такой вывод:

Waiting for a task...
Получена новая задача 1ab642f7-0c2c-4ff1-868a-a5d38c57d480
Аудио файл:
/path/to/queue-manager/uploads/whisper/962ff1aa-f6ec-11ef-be86-33f5f54d4fd6.mp3

Полный код воркера с комментариями можно посмотреть здесь:
https://github.com/andchir/api2app-workers/blob/main/whisper-cpp.py

Этот воркер запускает "whisper-cli" из проекта whisper.cpp, который в свою очередь создает транскрипцию аудио-файла. Далее с помощью функции send_queue_result_dict результат отправляется менеджеру задач.

Скрипт для управления воркерами (только Linux)

Для более удобного управления воркерами есть bash-скрипт "worker-manager.sh". Для его использования нужно установить права на запуск:

chmod +x api2app-workers/worker-manager.sh

Если открыть его код, в самом начале можно увидеть настройки:

WORKERS=('api2app-workers/whisper-cpp.py')
WORKERS_NUM=(1)
QUEUE_SIZE_URLS=('https://queue.api2app.org/queue_size/ea474c9a-c631-4bac-9141-ba26b0ff56c5')

здесь
WORKERS - массив воркеров, которые нужно запускать (разделяются пробелом).
WORKERS_NUM - массив с числами, сколько нужно запустить копий воркеров (будут выполняться параллельно).
QUEUE_SIZE_URLS - массив URL для проверки размера очереди.

Команды для использования:

./api2app-workers/worker-manager.sh status
./api2app-workers/worker-manager.sh start
./api2app-workers/worker-manager.sh stop

Вывод статуса примерно такой:

-----------------------------------------
                  STATUS                  
-----------------------------------------

- api2app-workers/whisper-cpp.py [1]
Queue size: 1

Создание графического интерфейса для приложения

Теперь создам графический интерфейс для приложения, которое будет создавать транскрипции аудио файлов.

Иду на сайт api2app.org. Сначала нужно создать конфигурацию API (по примеру с кодом curl, который был выше). Иду в раздел "API", затем в подраздел "Мои API", нажимаю кнопку "Импортировать". Вставляю свою curl-команду и нажимаю кнопку "Импортировать".

Импорт конфигурации API из curl-команды
Импорт конфигурации API из curl-команды

Данные успешно импортировались. Теперь нужно только немного подправить и протестировать:

Создание конфигурации API (не переживайте за открытые данные, эта конфигурация уже не используется)
Создание конфигурации API (не переживайте за открытые данные, эта конфигурация уже не используется)

Нажимаю кнопку "Тест", вижу ответ сервера, сохраняю.

Возвращаюсь в подраздел "Мои API", нажимаю кнопку "Поделиться" -> "Сделать публичным" -> "Скрыть".

API должен быть публичным, но может быть скрыт
API должен быть публичным, но может быть скрыт

API добавления задания отдает нам идентификатор задания и URL для получения результата, поэтому нужно ещё создать конфигурацию API для этого (авторизация здесь не нужна):

API для получения результата
API для получения результата

Так же, как с предыдущим, делаю это API публичным и скрытым.

Приступаю к созданию графического интерфейса. Перехожу в раздел "Приложения" -> "Мои приложения", нажимаю кнопку "Создать приложение".

Сначала нужно добавить поле для загрузки аудио-файлов:

Поле "Загрузить файл"
Поле "Загрузить файл"

После добавления поля нажимаю кнопку "Параметры". В поле "Принимать типы файлов" ввожу "audio/*" для фильтрации файлов по типу при выборе с устройства.

Параметры элемента для выбора файла
Параметры элемента для выбора файла

Далее добавляю поле с типом "Выбор (select)" для выбора языка. Язык может быть определен автоматически, поэтому по умолчанию будет значение "auto":

Поле для выбора языка
Поле для выбора языка

Теперь нужно добавить поле для выбора формата транскрипции (txt, json, srt и т.д.):

Поле для выбора формата транскрипции
Поле для выбора формата транскрипции

Добавляю кнопку с текстом "Создать транскрипцию". На этом шаге у меня получился такой интерфейс в редакторе:

Интерфейс приложения в редакторе
Интерфейс приложения в редакторе

API возвращает идентификатор задачи, по которому потом можно получить результат, для этого мне нужно создать скрытое поле и элемент "Прогресс операции".

У скрытого поля в параметрах нужно обязательно включить опцию "Хранить значение поля". Для элемента "Прогресс операции" нужно указать среднее время выполнения операции - параметр "Время выполнения операции (в секундах)", остальные значения можно не менять.

Параметры элемента "Прогресс операции"
Параметры элемента "Прогресс операции"

Добавляю элемент "Текст", в нём будет выводиться результат. Устанавливаю такие параметры:

В параметрах первого блока включаю опцию "Очищать после отправки".

Результат у меня будет появляться во второй колонке. Также я добавил ещё текстовую информацию:

Окончательный вид приложения в редакторе
Окончательный вид приложения в редакторе

Теперь нужно связать все поля с ранее созданными конфигурациями API.

Поле файла служит для ввода данных (выбора файла), поэтому нужно указать Действие ввода - какое поле API использовать. Нажимаю кнопку "Действие ввода" у этого поля:

Кнопка "Действие ввода" элемента "Файл"
Кнопка "Действие ввода" элемента "Файл"

Нахожу конфигурацию API для добавления задания, которое создал ранее, выбираю поле "audio_file", сохраняю.

Действие ввода для загрузки фйла
Действие ввода для загрузки фйла

Для выбора языка тоже выбираю это API в окне "Действие ввода" и поле "data.language" (поле из JSON).

Действие ввода для выбора языка
Действие ввода для выбора языка

То же самое делаю для поля "Формат транскрипции", только выбираю поле "data.output_type".

Действие ввода для кнопки только одно - "Отправить". Выбираю его и сохраняю.

Действие ввода для кнопки
Действие ввода для кнопки

Теперь нужно установить действие вывода для текстового элемента. Здесь уже нужно использовать API получения результата. Выбираю поле "result_data.result":

Действие вывода для текстового элемента (вывод результата)
Действие вывода для текстового элемента (вывод результата)

Для скрытого поля нудно выбрать действие вывода - откуда поле получает значение. Выбираю API добавления задания и поле "uuid".

Действие вывода скрытого поля
Действие вывода скрытого поля

Действие ввода - получение результата. Значение используется в URL запроса:

Действие ввода скрытого поля
Действие ввода скрытого поля

Для получения результата я не добавлял кнопку, поэтому запрос будет отправлен автоматически после того как скрытое поле получит значение (ID задания).

Последним добавлю действие вывода для элемента "Прогресс операции":

Кнопка "Действие вывода" элемента "Прогресс операции"
Кнопка "Действие вывода" элемента "Прогресс операции"
Действие вывода элемента "Прогресс операции"
Действие вывода элемента "Прогресс операции"

Для элемента нужны все данные, которые отдаёт API, поэтому выбираю поле "value".

На этом создание графического интерфейса окончено. Результат можно увидеть и протестировать по ссылке:
https://api2app.org/ru/apps/shared/dc6481f4-f778-11ef-9fb8-525400f8f94f

Результат
Результат

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

Предупреждение:
Всё описанное Вы можете повторить на свой страх и риск, безопасность пока под вопросом.

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
+3
Комментарии2

Публикации

Истории

Работа

Data Scientist
49 вакансий

Ближайшие события

25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань