AnthropicAdapter::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 AnthropicAdapter extends BaseLLMAdapter
11
{
12
    private ?PendingRequest $client = null;
13
14
    public function getName(): string
15
    {
16
        return 'Anthropic/Claude';
17
    }
18
19
    public function isEnabled(): bool
20
    {
21
        return config('laravel-toon.adapters.anthropic.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' => 'Anthropic 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
            'max_tokens' => 1024,
41
            'messages' => [
42
                ['role' => 'user', 'content' => $toonMessage],
43
            ],
44
        ], $options);
45
46
        try {
47
            $response = $this->getClient()
48
                ->post('/messages', $payload)
49
                ->throw()
50
                ->json();
51
52
            return [
53
                'success' => true,
54
                'adapter' => 'anthropic',
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' => 'Anthropic 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
            'max_tokens' => 2048,
90
            'messages' => $compressedMessages,
91
        ], $options);
92
93
        try {
94
            $response = $this->getClient()
95
                ->post('/messages', $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' => 'anthropic',
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.anthropic.default_model', 'claude-3-sonnet-20240229');
130
    }
131
132
    public function getAvailableModels(): array
133
    {
134
        return [
135
            'claude-3-opus-20240229',
136
            'claude-3-sonnet-20240229',
137
            'claude-3-haiku-20240307',
138
            'claude-2.1',
139
            'claude-2',
140
        ];
141
    }
142
143
    private function getClient(): PendingRequest
144
    {
145
        if (null === $this->client) {
146
            $baseUrl = config('laravel-toon.adapters.anthropic.base_url', 'https://api.anthropic.com');
147
            $apiKey = config('laravel-toon.adapters.anthropic.api_key');
148
            $timeout = config('laravel-toon.adapters.anthropic.timeout', 30);
149
150
            $this->client = Http::baseUrl($baseUrl)
151
                ->withHeader('x-api-key', $apiKey)
152
                ->withHeader('anthropic-version', '2023-06-01')
153
                ->withHeader('content-type', 'application/json')
154
                ->timeout($timeout);
155
        }
156
157
        return $this->client;
158
    }
159
}
160
161