|
|
@@ -5,11 +5,12 @@ namespace App\Services;
|
|
|
use App\Enums\UserTypeEnum;
|
|
|
use GuzzleHttp\Client;
|
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
|
+use GuzzleHttp\Exception\RequestException;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
class GeminiService
|
|
|
{
|
|
|
- private const API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
|
|
|
+ private const API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models';
|
|
|
|
|
|
private Client $client;
|
|
|
|
|
|
@@ -21,6 +22,7 @@ class GeminiService
|
|
|
public function sendMessage(string $message, UserTypeEnum $userType, array $history = []): string
|
|
|
{
|
|
|
$apiKey = config('services.gemini.api_key');
|
|
|
+ $model = config('services.gemini.model');
|
|
|
$contents = $this->buildContents($history, $message);
|
|
|
|
|
|
$payload = [
|
|
|
@@ -35,8 +37,9 @@ class GeminiService
|
|
|
];
|
|
|
|
|
|
try {
|
|
|
- $response = $this->client->post(self::API_URL . '?key=' . $apiKey, [
|
|
|
+ $response = $this->client->post($this->buildApiUrl($model), [
|
|
|
'json' => $payload,
|
|
|
+ 'query' => ['key' => $apiKey],
|
|
|
]);
|
|
|
|
|
|
$data = json_decode($response->getBody()->getContents(), true);
|
|
|
@@ -44,12 +47,39 @@ class GeminiService
|
|
|
return $data['candidates'][0]['content']['parts'][0]['text']
|
|
|
?? __('chatbot.error_response');
|
|
|
} catch (GuzzleException $e) {
|
|
|
- Log::error('Gemini API error', ['error' => $e->getMessage()]);
|
|
|
+ $this->logGeminiError($e, $model);
|
|
|
|
|
|
return __('chatbot.error_response');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private function buildApiUrl(string $model): string
|
|
|
+ {
|
|
|
+ return self::API_BASE_URL . '/' . rawurlencode($model) . ':generateContent';
|
|
|
+ }
|
|
|
+
|
|
|
+ private function logGeminiError(GuzzleException $e, string $model): void
|
|
|
+ {
|
|
|
+ $context = [
|
|
|
+ 'model' => $model,
|
|
|
+ 'message' => $this->sanitizeApiKey($e->getMessage()),
|
|
|
+ ];
|
|
|
+
|
|
|
+ if ($e instanceof RequestException && $e->hasResponse()) {
|
|
|
+ $response = $e->getResponse();
|
|
|
+
|
|
|
+ $context['status'] = $response->getStatusCode();
|
|
|
+ $context['body'] = $this->sanitizeApiKey((string) $response->getBody());
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::error('Gemini API error', $context);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function sanitizeApiKey(string $message): string
|
|
|
+ {
|
|
|
+ return preg_replace('/([?&]key=)[^&\s"]+/i', '$1[REDACTED]', $message);
|
|
|
+ }
|
|
|
+
|
|
|
private function buildContents(array $history, string $newMessage): array
|
|
|
{
|
|
|
$contents = [];
|