78 lines
2.2 KiB
PHP
78 lines
2.2 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace App\Services\Runware;
|
||
|
|
|
||
|
|
use Illuminate\Support\Facades\Http;
|
||
|
|
use RuntimeException;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Thin wrapper around Runware's HTTP API. Image and video generation use the
|
||
|
|
* batched task-array endpoint (POST /v1, body is a JSON array of tasks);
|
||
|
|
* text/LLM generation uses Runware's separate OpenAI-compatible endpoint
|
||
|
|
* (POST /v1/chat/completions). See https://runware.ai/docs/platform/introduction
|
||
|
|
* and https://runware.ai/docs/platform/openai.
|
||
|
|
*/
|
||
|
|
class RunwareClient
|
||
|
|
{
|
||
|
|
public function __construct(
|
||
|
|
protected string $apiKey,
|
||
|
|
protected string $baseUrl,
|
||
|
|
) {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<int, array<string, mixed>> $tasks
|
||
|
|
* @return array<int, array<string, mixed>>
|
||
|
|
*/
|
||
|
|
public function runTasks(array $tasks): array
|
||
|
|
{
|
||
|
|
$response = Http::withToken($this->apiKey)
|
||
|
|
->timeout(120)
|
||
|
|
->post($this->baseUrl, $tasks);
|
||
|
|
|
||
|
|
if ($response->failed()) {
|
||
|
|
throw new RuntimeException('Runware API request failed: '.$response->body());
|
||
|
|
}
|
||
|
|
|
||
|
|
$data = $response->json('data');
|
||
|
|
|
||
|
|
if (! is_array($data)) {
|
||
|
|
throw new RuntimeException('Unexpected Runware response shape: '.$response->body());
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($data as $result) {
|
||
|
|
if (isset($result['error']) || ($result['status'] ?? null) === 'error') {
|
||
|
|
throw new RuntimeException('Runware task failed: '.json_encode($result));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $data;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function pollTask(string $taskUUID): array
|
||
|
|
{
|
||
|
|
$results = $this->runTasks([[
|
||
|
|
'taskType' => 'getResponse',
|
||
|
|
'taskUUID' => $taskUUID,
|
||
|
|
]]);
|
||
|
|
|
||
|
|
return $results[0] ?? throw new RuntimeException("No poll result for task {$taskUUID}");
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $payload
|
||
|
|
* @return array<string, mixed>
|
||
|
|
*/
|
||
|
|
public function chatCompletion(array $payload): array
|
||
|
|
{
|
||
|
|
$response = Http::withToken($this->apiKey)
|
||
|
|
->timeout(120)
|
||
|
|
->post(rtrim($this->baseUrl, '/').'/chat/completions', $payload);
|
||
|
|
|
||
|
|
if ($response->failed()) {
|
||
|
|
throw new RuntimeException('Runware chat completion failed: '.$response->body());
|
||
|
|
}
|
||
|
|
|
||
|
|
return $response->json();
|
||
|
|
}
|
||
|
|
}
|