Обработка POST-запроса аудиофайла

Что такое эквивалентный запрос POST с использованием:

для этой команды оболочки curl:

curl --request POST \
  --url https://api.someservice.com/v1/ \
  --header 'Authorization: Bearer TOKEN' \
  --header 'Content-Type: multipart/form-data' \
  --form file=@/path/to/file/audio.mp3 \
  --form transformer=trans-2 \
  --form format=text

Я попытался следовать примерам в "Кро::http::Клиент" безуспешно...

(Смотрите пример, начинающийся с my $resp = await Cro::HTTP::Client.post: 'we.love.pand.as/pandas',)


Обновлять

Вот рабочий пример, использующий ответ @jja, который требует:

  • Иметь OpenAI (учетную запись и) ключ авторизации

  • Загрузите один из файлов MP3 с здесь

    • Или используйте другой файл MP3 с записью речи.
use HTTP::Tiny;


my $fileName = $*HOME ~ '/Downloads/HelloRaccoonsEN.mp3';


say .<content>.decode given HTTP::Tiny.post: 'https://api.openai.com/v1/audio/transcriptions',
        headers => { authorization => "Bearer {%*ENV<OPENAI_API_KEY>}" },
        content => {
            file        => $fileName.IO,
            model       => 'whisper-1',
            format      => 'text'
        };

Вот ожидаемый результат:

# {"text":"Raku practitioners around the world, eat more onions!"}

Это должно быть Cro? Вам подходит что-то вроде HTTP::Tiny или HTTP::Tinyish?

jubilatious1 29.03.2023 23:05

@ jubilatious1 Будем очень признательны за любое решение! :)

Anton Antonov 29.03.2023 23:31
5 способов использования оповещений, предупреждений, ошибок, сообщений об успехе в Bootstrap
5 способов использования оповещений, предупреждений, ошибок, сообщений об успехе в Bootstrap
Bootstrap - это популярный front-end фреймворк, который делает веб-разработку проще и быстрее. Использование Bootstrap растет по мере того, как все...
Библиотека Bootstrap
Библиотека Bootstrap
Bootstrap - это бесплатный набор инструментов для разработки веб-приложений с открытым исходным кодом, разработанный компанией Twitter. Написанный на...
HTML И VS CODE Для Веб-разработки
HTML И VS CODE Для Веб-разработки
Прежде чем начать кодировать html в "VS CODE", мы должны сначала создать папку и назвать ее x.html, здесь я принимаю x как имя файла, который мы...
Красиво оформленное веб-приложение для отправки HTML писем на PHP
Красиво оформленное веб-приложение для отправки HTML писем на PHP
В современный цифровой век маркетинг электронной почты играет жизненно важную роль в успехе любого бизнеса, а создание красиво оформленных HTML-писем...
Раскройте весь потенциал вашего проекта Angular с помощью экспертного знания команд Angular CLI
Раскройте весь потенциал вашего проекта Angular с помощью экспертного знания команд Angular CLI
Angular - это популярный JavaScript-фреймворк для создания веб-приложений. Одной из ключевых особенностей Angular является его мощный интерфейс...
Соскабливание и загрузка изображений Google с помощью Python
Соскабливание и загрузка изображений Google с помощью Python
Растущая распространенность веб-скрейпинга значительно расширила области его использования. Многие приложения искусственного интеллекта сегодня...
4
2
269
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Использование модуля Raku http::Tinyish

Мне очень повезло загрузить биоинформационные данные из Европейского института биоинформатики (EBI/Ensembl) с помощью HTTP::Tinyish. Может быть, приведенный ниже код POST подойдет вам?

use HTTP::Tinyish;

my $http = HTTP::Tinyish.new(agent => "Mozilla/4.0");

my $server = 'https://rest.ensembl.org';
my $ext = '/archive/id';
my %response = $http.post: $server ~ $ext, 
  headers => { 
    'Content-type' => 'application/json',
    'Accept' => 'application/json'
  },
  content => '{ "id" : ["ENSG00000157764", "ENSG00000248378"] }';

die "Failed: " ~ %response<status> ~ "\n" ~ %response<content> ~ "\n" unless %response<success>; 


"\n1.________\n\n".put; #json output
use JSON::Fast <immutable>;
# .put for to-json(from-json(%response<content>));


"\n2.________\n\n".put; #below provides sorted output:
use PrettyDump;
for ( %response<content> ) {
  my $pretty = PrettyDump.new;
  put $pretty.dump: from-json(%response<content>);
};


"\n3.________\n\n".put; #below provides very compact `.raku` output:
# .say for from-json(%response<content>).raku;

Пример вывода (только версия 2, PrettyDump):

2.________


List=(
    Map=(
            :assembly("GRCh38"),
            :id("ENSG00000157764"),
            :is_current("1"),
            :latest("ENSG00000157764.14"),
            :peptide(Any),
            :possible_replacement(List=()),
            :release("109"),
            :type("Gene"),
            :version(14)
    ),
    Map=(
            :assembly("GRCh38"),
            :id("ENSG00000248378"),
            :is_current("1"),
            :latest("ENSG00000248378.1"),
            :peptide(Any),
            :possible_replacement(List=()),
            :release("109"),
            :type("Gene"),
            :version(1)
    )
)

Комментируйте/декомментируйте различные результаты (см. выше), пока не найдете тот, который соответствует вашим потребностям.

@AntonAntonov согласно документам HTTP::Tinyish, чтобы получить обратно двоичный файл (например, файл mp3), добавьте параметр bin => True в строку объявления хэша %response. ХТН.

jubilatious1 30.03.2023 00:02

Я проголосовал за этот ответ - я не знал о «http:: Tinyish» и не рассматривал решения, отличные от Cro. Тем не менее, в конечном итоге этот ответ мне не пригодился. (То есть для успешной загрузки аудиофайла в OpenAI.)

Anton Antonov 17.04.2023 16:28

@AntonAntonov Интересно, интересно, следует ли подавать жалобу на Github? В конце концов, бинарник есть бинарник.

jubilatious1 17.04.2023 17:06

Смотрите мое обновление вопроса с рабочим решением. Если у вас есть ключ аутентификации OpenAI, запуск этого кода или подобного не должен быть слишком дорогим... (Скажем, на основе "http::Tinyish".)

Anton Antonov 17.04.2023 17:58

@AntonAntonov, так что HTTP::Tinyish должно работать. Может быть, у @shoichi (или даже у @miyagawa) есть предложения на будущее? С наилучшими пожеланиями.

jubilatious1 17.04.2023 19:29

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

my $resp = await Cro::HTTP::Client.post: 'https://api.someservice.com/v1/',
    headers => [ Authorization => 'Bearer TOKEN' ],
    content-type => 'multipart/form-data',
    body => [
        transformer => 'trans-2',
        format => 'text',
        Cro::HTTP::Body::MultiPartFormData::Part.new(
            headers => [Cro::HTTP::Header.new(
                name => 'Content-type',
                value => 'audio/mpeg'
            )],
            name => 'file',
            filename => 'audio.mp3',
            body-blob => slurp('/path/to/file/audio.mp3', :bin)
        )
    ];

Я точно не знаю, какой тип пантомимы curl подходит, поэтому он может немного отличаться от того, что делает curl в этом отношении.

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

Anton Antonov 30.03.2023 00:03

@AntonAntonov Ваши ссылки не имеют для меня смысла. Например, часть 2 прямо сейчас находится на пустой строке. Последние фиксации этих файлов отмечены GH как 2-дневные, но ваш комментарий выше помечен SO как «вчера». Я весьма озадачен!

raiph 31.03.2023 22:41

@raiph Да, ссылки указывали на «предыдущую» неработающую реализацию, которая у меня была. На данный момент я реализовал предложения Джонатана, данные в этом ответе. Я до сих пор не могу заставить OpenAI принимать/обрабатывать POST-сообщение (я строю). Я предоставлю более подробное описание в обновлении моего вопроса. (продолжение)

Anton Antonov 01.04.2023 03:32

(продолжение) Я не хотел сформулировать первоначальный вопрос о создании аудиофайла POST для OpenAI, поскольку для работы над ответом потребуется ключ аутентификации (для использования веб-API OpenAI).

Anton Antonov 01.04.2023 03:35

@AntonAntonov Наверное, мой юмор не переводился. Моя точка зрения заключалась в том, что я копался в истории коммитов и не видел возможности, чтобы кто-нибудь разумно догадался, какой код вы действительно имели в виду. И ваши ответы не помогли. Итак, все еще спотыкаясь в темноте, но все еще пытаясь быть полезным, я вижу, что явно является ошибкой здесь. Это актуально?

raiph 03.04.2023 20:25

@raiph Спасибо за ваши комментарии! Указанная вами ошибка актуальна, но мне просто не удалось использовать Cro для транскрипции аудио OpenAI. И поскольку (1) я потратил слишком много времени, пытаясь использовать Cro, (2) этот ответ работает, и (3) моя реализация с использованием curl работает, решение Cro сейчас гораздо менее важно.

Anton Antonov 05.04.2023 10:32

ХОРОШО. Мы все заняты, а у Антона есть решение их нужд, а это главное. Но на случай, если кто-то, читающий это, интересуется Кро и думает, что это может быть проблематично, я хотел бы, чтобы вы знали, что это ТАК не об этом. К сожалению, Антон написал :$body, когда они имели в виду :@body (эта ошибка не была обнаружена, потому что они объявили обе переменные $body и @body). Стандарт SO для вопроса, который в конечном итоге касается опечатки, - закрыть его. Но теперь у него есть принятый ответ. В общем, можно с уверенностью предположить, что проблема была не в Кро, а в данном случае была просто отвлекающим маневром.

raiph 05.04.2023 14:56

@raiph Ну ... исправление этой ошибки не заставило мое (текущее) решение Cro работать. (Я пробовал некоторые другие версии до и после публикации вопроса здесь.) Минимальный воспроизводимый пример требует наличия учетной записи OpenAI - я думал, что это не норма SO.

Anton Antonov 05.04.2023 16:25

Хотя это не идеально, что кому-то может понадобиться учетная запись для воспроизведения, правильное предположение состоит в том, что вы сделали (другую) ошибку кодирования, для которой не требуется учетная запись. Действительно, я вижу другие подобные возможные проблемы, но я думаю, что это спорно. Я просто хотел, чтобы читатели поняли, что проблема почти наверняка не в Cro, а просто в каком-то коде с ошибками, но не очевидно, где искать в вашем модуле, чтобы прибить его. Так что, похоже, мы не докопаемся до сути вещей через этот SO. Возможно, вы вернетесь к этому однажды или опубликуете еще один SO с MRE, или кто-то еще выяснит, что пошло не так. Я сейчас остановлюсь! 🤐

raiph 06.04.2023 00:15

@raiph Не нужно «останавливаться»! :) В моем списке TODO есть обновление с правильным кодом примера и соответствующими аудиофайлами. Надеюсь, к концу недели сделаю.

Anton Antonov 07.04.2023 03:42

Почему файлы во множественном числе? Конечно, «правильным» примером был бы код jnthn, в котором не было изменено ни одного символа, просто файл, который вы тестируете и подтверждаете, не работает с его использованием. Возможно, я что-то упускаю, но даже если это так, я все же предполагаю, что единственным продуктивным примером, учитывая, что ведущий автор Кро написал этот ответ, будет тот, который является точной копией его 16 строк кода, за исключением минимальных отличий. (конечно, не более 5 строк максимум?) с комментариями, обильно обосновывающими и объясняющими каждое изменение в коде jnthn. YMMV, но я надеюсь, что вы или другие не будете тратить время зря. 💚

raiph 07.04.2023 13:04

@raiph Наконец, я обновил свой вопрос рабочим примером.

Anton Antonov 17.04.2023 18:01
Ответ принят как подходящий

Вот как это будет выглядеть с http::Tiny:

say .<content>.decode given HTTP::Tiny.post: 'https://httpbin.org/anything',
    headers => { authorization => 'Bearer TOKEN' },
    content => {
        file        => 'path/to/your/file'.IO,
        transformer => 'trans-2',
        format      => 'text'
    }

Если вы установите content на хеш, по умолчанию будет использоваться кодировка составной формы, и если какое-либо из значений поддерживает метод slurp (в данном случае IO::Path, который вы получаете, вызывая IO на своем пути), который будет используется для получения значения перед отправкой.

И вывод, чтобы вы могли проверить, что было отправлено:

{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "data:application/octet-stream;base64,...."
  }, 
  "form": {
    "format": "text", 
    "transformer": "trans-2"
  }, 
  "headers": {
    "Authorization": "Bearer TOKEN", 
    "Content-Length": "...", 
    "Content-Type": "multipart/form-data; boundary=\"VfaSnFoNawbxJQnMbtJr\"", 
    "Host": "httpbin.org", 
    "User-Agent": "HTTP::Tiny/0.2.5 Raku", 
    "X-Amzn-Trace-Id": "Root=1-deadbeef-deadbeefdeadbeefdeadbeef"
  }, 
  "json": null, 
  "method": "POST", 
  "origin": "123.45.67.89", 
  "url": "https://httpbin.org/anything"
}

Отлично работает - спасибо! (Только что попробовал транскрипцию аудио OpenAI.)

Anton Antonov 05.04.2023 10:23

Мы все заняты, а Антон делает отличные вещи, и это решение сработало для них. Но хотя у него не было времени/мотивации, чтобы выяснить ошибку, которую он совершал с Кро, я хочу, чтобы последующие читатели поняли, что это ТАК почти наверняка не имело ничего общего с Кро, что отлично подходит для случая Антона. Мы знаем это, потому что, хотя Антон не предоставил минимальный воспроизводимый пример в своем вопросе, и лучшее, что кто-либо может сделать с информацией в комментарии Антона «моя попытка состоит из следующих двух частей» к ответу jnthn, это угадать, какой код Антон пользовался, я покопался и быстро нашел базовую ошибку в коде, не связанную с Кро.

raiph 05.04.2023 15:00

О, конечно. О проблемах или ограничениях с Cro не сообщалось, поэтому я не думаю, что они есть. Поскольку был комментарий, в котором говорилось, что решения, не основанные на Cro (= переводы из curl), приветствуются, я подумал, что это было бы полезно иметь.

jja 06.04.2023 16:39

@jja Еще раз спасибо за решение «http:: Tiny»! Я провел рефакторинг "WWW::OpenAI" , чтобы использовать его в качестве основного метода доступа OpenAI.

Anton Antonov 09.04.2023 21:21

Другие вопросы по теме