Что такое эквивалентный запрос 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 с здесь
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!"}
@ jubilatious1 Будем очень признательны за любое решение! :)
Использование модуля 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
. ХТН.
Я проголосовал за этот ответ - я не знал о «http:: Tinyish» и не рассматривал решения, отличные от Cro. Тем не менее, в конечном итоге этот ответ мне не пригодился. (То есть для успешной загрузки аудиофайла в OpenAI.)
@AntonAntonov Интересно, интересно, следует ли подавать жалобу на Github? В конце концов, бинарник есть бинарник.
Смотрите мое обновление вопроса с рабочим решением. Если у вас есть ключ аутентификации OpenAI, запуск этого кода или подобного не должен быть слишком дорогим... (Скажем, на основе "http::Tinyish".)
@AntonAntonov, так что HTTP::Tinyish
должно работать. Может быть, у @shoichi (или даже у @miyagawa) есть предложения на будущее? С наилучшими пожеланиями.
Было бы полезно знать, что вы пытались сделать, чтобы решить, как это исправить. В любом случае, я ожидаю, что пример запроса в 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.
@AntonAntonov Ваши ссылки не имеют для меня смысла. Например, часть 2 прямо сейчас находится на пустой строке. Последние фиксации этих файлов отмечены GH как 2-дневные, но ваш комментарий выше помечен SO как «вчера». Я весьма озадачен!
@raiph Да, ссылки указывали на «предыдущую» неработающую реализацию, которая у меня была. На данный момент я реализовал предложения Джонатана, данные в этом ответе. Я до сих пор не могу заставить OpenAI принимать/обрабатывать POST-сообщение (я строю). Я предоставлю более подробное описание в обновлении моего вопроса. (продолжение)
(продолжение) Я не хотел сформулировать первоначальный вопрос о создании аудиофайла POST для OpenAI, поскольку для работы над ответом потребуется ключ аутентификации (для использования веб-API OpenAI).
@AntonAntonov Наверное, мой юмор не переводился. Моя точка зрения заключалась в том, что я копался в истории коммитов и не видел возможности, чтобы кто-нибудь разумно догадался, какой код вы действительно имели в виду. И ваши ответы не помогли. Итак, все еще спотыкаясь в темноте, но все еще пытаясь быть полезным, я вижу, что явно является ошибкой здесь. Это актуально?
@raiph Спасибо за ваши комментарии! Указанная вами ошибка актуальна, но мне просто не удалось использовать Cro для транскрипции аудио OpenAI. И поскольку (1) я потратил слишком много времени, пытаясь использовать Cro, (2) этот ответ работает, и (3) моя реализация с использованием curl
работает, решение Cro сейчас гораздо менее важно.
ХОРОШО. Мы все заняты, а у Антона есть решение их нужд, а это главное. Но на случай, если кто-то, читающий это, интересуется Кро и думает, что это может быть проблематично, я хотел бы, чтобы вы знали, что это ТАК не об этом. К сожалению, Антон написал :$body
, когда они имели в виду :@body
(эта ошибка не была обнаружена, потому что они объявили обе переменные $body
и @body
). Стандарт SO для вопроса, который в конечном итоге касается опечатки, - закрыть его. Но теперь у него есть принятый ответ. В общем, можно с уверенностью предположить, что проблема была не в Кро, а в данном случае была просто отвлекающим маневром.
@raiph Ну ... исправление этой ошибки не заставило мое (текущее) решение Cro работать. (Я пробовал некоторые другие версии до и после публикации вопроса здесь.) Минимальный воспроизводимый пример требует наличия учетной записи OpenAI - я думал, что это не норма SO.
Хотя это не идеально, что кому-то может понадобиться учетная запись для воспроизведения, правильное предположение состоит в том, что вы сделали (другую) ошибку кодирования, для которой не требуется учетная запись. Действительно, я вижу другие подобные возможные проблемы, но я думаю, что это спорно. Я просто хотел, чтобы читатели поняли, что проблема почти наверняка не в Cro, а просто в каком-то коде с ошибками, но не очевидно, где искать в вашем модуле, чтобы прибить его. Так что, похоже, мы не докопаемся до сути вещей через этот SO. Возможно, вы вернетесь к этому однажды или опубликуете еще один SO с MRE, или кто-то еще выяснит, что пошло не так. Я сейчас остановлюсь! 🤐
@raiph Не нужно «останавливаться»! :) В моем списке TODO есть обновление с правильным кодом примера и соответствующими аудиофайлами. Надеюсь, к концу недели сделаю.
Почему файлы во множественном числе? Конечно, «правильным» примером был бы код jnthn, в котором не было изменено ни одного символа, просто файл, который вы тестируете и подтверждаете, не работает с его использованием. Возможно, я что-то упускаю, но даже если это так, я все же предполагаю, что единственным продуктивным примером, учитывая, что ведущий автор Кро написал этот ответ, будет тот, который является точной копией его 16 строк кода, за исключением минимальных отличий. (конечно, не более 5 строк максимум?) с комментариями, обильно обосновывающими и объясняющими каждое изменение в коде jnthn. YMMV, но я надеюсь, что вы или другие не будете тратить время зря. 💚
@raiph Наконец, я обновил свой вопрос рабочим примером.
Вот как это будет выглядеть с 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.)
Мы все заняты, а Антон делает отличные вещи, и это решение сработало для них. Но хотя у него не было времени/мотивации, чтобы выяснить ошибку, которую он совершал с Кро, я хочу, чтобы последующие читатели поняли, что это ТАК почти наверняка не имело ничего общего с Кро, что отлично подходит для случая Антона. Мы знаем это, потому что, хотя Антон не предоставил минимальный воспроизводимый пример в своем вопросе, и лучшее, что кто-либо может сделать с информацией в комментарии Антона «моя попытка состоит из следующих двух частей» к ответу jnthn, это угадать, какой код Антон пользовался, я покопался и быстро нашел базовую ошибку в коде, не связанную с Кро.
О, конечно. О проблемах или ограничениях с Cro не сообщалось, поэтому я не думаю, что они есть. Поскольку был комментарий, в котором говорилось, что решения, не основанные на Cro (= переводы из curl), приветствуются, я подумал, что это было бы полезно иметь.
@jja Еще раз спасибо за решение «http:: Tiny»! Я провел рефакторинг "WWW::OpenAI" , чтобы использовать его в качестве основного метода доступа OpenAI.
Это должно быть
Cro
? Вам подходит что-то вродеHTTP::Tiny
илиHTTP::Tinyish
?