OpenAIAdapter::getName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Squareetlabs\LaravelToon\Adapters;
6
7
use Illuminate\Http\Client\PendingRequest;
8
use Illuminate\Support\Facades\Http;
9
10
class OpenAIAdapter extends BaseLLMAdapter
11
{
12
    private ?PendingRequest $client = null;
13
14
    public function getName(): string
15
    {
16
        return 'OpenAI';
17
    }
18
19
    public function isEnabled(): bool
20
    {
21
        return config('laravel-toon.adapters.openai.enabled', false);
22
    }
23
24
    public function sendMessage(
25
        string $message,
26
        ?string $model = null,
27
        ?array $options = null
28
    ): array {
29
        if (!$this->isEnabled()) {
30
            return ['success' => false, 'error' => 'OpenAI adapter not enabled'];
31
        }
32
33
        $model ??= $this->getDefaultModel();
34
        $options ??= [];
35
36
        $toonMessage = $this->compressMessage($message);
37
38
        $payload = array_merge([
39
            'model' => $model,
40
            'messages' => [
41
                ['role' => 'user', 'content' => $toonMessage],
42
            ],
43
            'temperature' => 0.7,
44
        ], $options);
45
46
        try {
47
            $response = $this->getClient()
48
                ->post('/chat/completions', $payload)
49
                ->throw()
50
                ->json();
51
52
            return [
53
                'success' => true,
54
                'adapter' => 'openai',
55
                'model' => $model,
56
                'original_message_tokens' => $this->tokenAnalyzer->estimate($message),
57
                'compressed_message_tokens' => $this->tokenAnalyzer->estimate($toonMessage),
58
                'response' => $response,
59
                'compressed_message' => $toonMessage,
60
            ];
61
        } catch (\Exception $e) {
62
            return [
63
                'success' => false,
64
                'error' => $e->getMessage(),
65
            ];
66
        }
67
    }
68
69
    public function chat(
70
        array $messages,
71
        ?string $model = null,
72
        ?array $options = null
73
    ): array {
74
        if (!$this->isEnabled()) {
75
            return ['success' => false, 'error' => 'OpenAI adapter not enabled'];
76
        }
77
78
        $model ??= $this->getDefaultModel();
79
        $options ??= [];
80
81
        // Compress messages
82
        $compressedMessages = array_map(fn ($msg) => [
83
            ...$msg,
84
            'content' => $this->compressMessage($msg['content']),
85
        ], $messages);
86
87
        $payload = array_merge([
88
            'model' => $model,
89
            'messages' => $compressedMessages,
90
            'temperature' => 0.7,
91
        ], $options);
92
93
        try {
94
            $response = $this->getClient()
95
                ->post('/chat/completions', $payload)
96
                ->throw()
97
                ->json();
98
99
            $originalTokens = array_sum(array_map(
100
                fn ($msg) => $this->tokenAnalyzer->estimate($msg['content']),
101
                $messages
102
            ));
103
104
            $compressedTokens = array_sum(array_map(
105
                fn ($msg) => $this->tokenAnalyzer->estimate($msg['content']),
106
                $compressedMessages
107
            ));
108
109
            return [
110
                'success' => true,
111
                'adapter' => 'openai',
112
                'model' => $model,
113
                'messages_count' => count($messages),
114
                'original_tokens' => $originalTokens,
115
                'compressed_tokens' => $compressedTokens,
116
                'tokens_saved' => $originalTokens - $compressedTokens,
117
                'response' => $response,
118
            ];
119
        } catch (\Exception $e) {
120
            return [
121
                'success' => false,
122
                'error' => $e->getMessage(),
123
            ];
124
        }
125
    }
126
127
    public function getDefaultModel(): string
128
    {
129
        return config('laravel-toon.adapters.openai.default_model', 'gpt-4o');
130
    }
131
132
    public function getAvailableModels(): array
133
    {
134
        return [
135
            'gpt-4o',
136
            'gpt-4-turbo',
137
            'gpt-4',
138
            'gpt-3.5-turbo',
139
        ];
140
    }
141
142
    private function getClient(): PendingRequest
143
    {
144
        if (null === $this->client) {
145
            $baseUrl = config('laravel-toon.adapters.openai.base_url', 'https://api.openai.com/v1');
146
            $apiKey = config('laravel-toon.adapters.openai.api_key');
147
            $timeout = config('laravel-toon.adapters.openai.timeout', 30);
148
149
            $this->client = Http::baseUrl($baseUrl)
150
                ->withHeader('Authorization', 'Bearer '.$apiKey)
151
                ->withHeader('Content-Type', 'application/json')
152
                ->timeout($timeout);
153
        }
154
155
        return $this->client;
156
    }
157
}
158
159