GeminiService.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\UserTypeEnum;
  4. use GuzzleHttp\Client;
  5. use GuzzleHttp\Exception\GuzzleException;
  6. use Illuminate\Support\Facades\Log;
  7. class GeminiService
  8. {
  9. private const API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
  10. private Client $client;
  11. public function __construct()
  12. {
  13. $this->client = new Client(['timeout' => 30]);
  14. }
  15. public function sendMessage(string $message, UserTypeEnum $userType, array $history = []): string
  16. {
  17. $apiKey = config('services.gemini.api_key');
  18. $contents = $this->buildContents($history, $message);
  19. $payload = [
  20. 'systemInstruction' => [
  21. 'parts' => [['text' => $this->loadContext($userType)]],
  22. ],
  23. 'contents' => $contents,
  24. 'generationConfig' => [
  25. 'temperature' => 0.4,
  26. 'maxOutputTokens' => 512,
  27. ],
  28. ];
  29. try {
  30. $response = $this->client->post(self::API_URL . '?key=' . $apiKey, [
  31. 'json' => $payload,
  32. ]);
  33. $data = json_decode($response->getBody()->getContents(), true);
  34. return $data['candidates'][0]['content']['parts'][0]['text']
  35. ?? __('chatbot.error_response');
  36. } catch (GuzzleException $e) {
  37. Log::error('Gemini API error', ['error' => $e->getMessage()]);
  38. return __('chatbot.error_response');
  39. }
  40. }
  41. private function buildContents(array $history, string $newMessage): array
  42. {
  43. $contents = [];
  44. foreach ($history as $entry) {
  45. $role = $entry['role'] === 'model' ? 'model' : 'user';
  46. $contents[] = [
  47. 'role' => $role,
  48. 'parts' => [['text' => $entry['text']]],
  49. ];
  50. }
  51. $contents[] = [
  52. 'role' => 'user',
  53. 'parts' => [['text' => $newMessage]],
  54. ];
  55. return $contents;
  56. }
  57. private function loadContext(UserTypeEnum $userType): string
  58. {
  59. $restrictionsFile = resource_path('chatbot/restricoes.md');
  60. $restrictions = file_exists($restrictionsFile) ? file_get_contents($restrictionsFile) : '';
  61. $contextFile = match ($userType) {
  62. UserTypeEnum::CLIENT => resource_path('chatbot/context_cliente.txt'),
  63. UserTypeEnum::PROVIDER => resource_path('chatbot/context_prestador.txt'),
  64. default => resource_path('chatbot/context_cliente.txt'),
  65. };
  66. $context = file_exists($contextFile) ? file_get_contents($contextFile) : '';
  67. return $restrictions . "\n\n" . $context;
  68. }
  69. }