SuperSeller3000/src/Infrastructure/AI/MistralClient.php

80 lines
2.5 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Infrastructure\AI;
use Symfony\Contracts\HttpClient\HttpClientInterface;
final class MistralClient implements OllamaClientInterface
{
public function __construct(
private readonly HttpClientInterface $httpClient,
private readonly string $mistralApiKey,
private readonly string $mistralBaseUrl,
) {
}
public function generate(string $model, string $prompt): string
{
$response = $this->httpClient->request('POST', $this->mistralBaseUrl.'/v1/chat/completions', [
'headers' => [
'Authorization' => 'Bearer '.$this->mistralApiKey,
],
'json' => [
'model' => $model,
'messages' => [
['role' => 'user', 'content' => $prompt],
],
],
'timeout' => 120,
]);
/** @var array{choices: array{0: array{message: array{content: string}}}} $data */
$data = $response->toArray();
return $data['choices'][0]['message']['content'];
}
public function generateWithImage(string $model, string $prompt, string $imagePath): string
{
$imageData = base64_encode((string) file_get_contents($imagePath));
$mimeType = $this->guessMimeType($imagePath);
$response = $this->httpClient->request('POST', $this->mistralBaseUrl.'/v1/chat/completions', [
'headers' => [
'Authorization' => 'Bearer '.$this->mistralApiKey,
],
'json' => [
'model' => $model,
'messages' => [
[
'role' => 'user',
'content' => [
['type' => 'text', 'text' => $prompt],
['type' => 'image_url', 'image_url' => ['url' => 'data:'.$mimeType.';base64,'.$imageData]],
],
],
],
],
'timeout' => 180,
]);
/** @var array{choices: array{0: array{message: array{content: string}}}} $data */
$data = $response->toArray();
return $data['choices'][0]['message']['content'];
}
private function guessMimeType(string $path): string
{
return match (strtolower(pathinfo($path, PATHINFO_EXTENSION))) {
'jpg', 'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'webp' => 'image/webp',
default => 'image/jpeg',
};
}
}