Skip to content

Commit 3bea523

Browse files
committed
feat: add support for anthropic models (claude)
1 parent 259dd34 commit 3bea523

File tree

4 files changed

+112
-4
lines changed

4 files changed

+112
-4
lines changed

_build/gpm.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ systemSettings:
1616
description: "Your API key found at https://platform.openai.com/api-keys"
1717
- key: gemini.key
1818
type: text-password
19-
area: chatgpt
19+
area: gemini
2020
description: "Your API key found at https://ai.google.dev/gemini-api/docs/api-key"
21+
- key: anthropic.key
22+
type: text-password
23+
area: anthropic
24+
description: "Your API key found at https://console.anthropic.com/settings/keys"
2125

2226
- key: global.base.output
2327
area: global

core/components/modai/src/Services/AIServiceFactory.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ public static function new($model, modX &$modx): AIService {
99
return new Gemini($modx);
1010
}
1111

12+
if (substr($model, 0, 7) === 'claude-') {
13+
return new Anthropic($modx);
14+
}
15+
1216
switch ($model) {
1317
case 'text-embedding-004':
1418
case 'learnlm-1.5-pro-experimental':
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
namespace modAI\Services;
3+
4+
use modAI\Services\Config\CompletionsConfig;
5+
use modAI\Services\Config\ImageConfig;
6+
use modAI\Services\Config\VisionConfig;
7+
use MODX\Revolution\modX;
8+
9+
class Anthropic implements AIService
10+
{
11+
private modX $modx;
12+
13+
const COMPLETIONS_API = 'https://api.anthropic.com/v1/messages';
14+
15+
public function __construct(modX &$modx)
16+
{
17+
$this->modx =& $modx;
18+
}
19+
20+
/**
21+
* @throws \Exception
22+
*/
23+
public function getCompletions(array $data, CompletionsConfig $config): string
24+
{
25+
$apiKey = $this->modx->getOption('modai.anthropic.key');
26+
if (empty($apiKey)) {
27+
throw new \Exception('Missing modai.anthropic.key');
28+
}
29+
30+
$messages = [];
31+
32+
$system = implode(';', $config->getSystemInstructions());
33+
34+
foreach ($data as $msg) {
35+
$messages[] = [
36+
'role' => 'user',
37+
'content' => $msg
38+
];
39+
}
40+
41+
$input = [
42+
"model" => $config->getModel(),
43+
"max_tokens"=> $config->getMaxTokens(),
44+
"temperature"=> $config->getTemperature(),
45+
"messages" => $messages
46+
];
47+
48+
if (!empty($system)) {
49+
$input['system'] = $system;
50+
}
51+
52+
$ch = curl_init(self::COMPLETIONS_API);
53+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
54+
curl_setopt($ch, CURLOPT_POST, true);
55+
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input));
56+
curl_setopt($ch, CURLOPT_HTTPHEADER, [
57+
'Content-Type: application/json',
58+
'anthropic-version: 2023-06-01',
59+
'x-api-key: ' . $apiKey
60+
]);
61+
62+
$response = curl_exec($ch);
63+
if (curl_errno($ch)) {
64+
$error_msg = curl_error($ch);
65+
curl_close($ch);
66+
throw new \Exception($error_msg);
67+
}
68+
69+
curl_close($ch);
70+
71+
$result = json_decode($response, true);
72+
if (!is_array($result)) {
73+
throw new \Exception('Invalid response');
74+
}
75+
76+
if (isset($result['error'])) {
77+
throw new \Exception($result['error']['message']);
78+
}
79+
80+
if (!isset($result['content'][0]['text'])) {
81+
throw new \Exception("There was an error generating a response.");
82+
}
83+
84+
return $result['content'][0]['text'];
85+
}
86+
87+
public function getVision(string $prompt, string $image, VisionConfig $config): string
88+
{
89+
throw new \Exception("not implemented");
90+
}
91+
92+
public function generateImage(string $prompt, ImageConfig $config): string
93+
{
94+
throw new \Exception("not implemented");
95+
}
96+
97+
}

core/components/modai/src/Services/Gemini.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,18 @@ public function getCompletions(array $data, CompletionsConfig $config): string
4949
"contents" => [
5050
"parts" => $messages,
5151
],
52-
"system_instruction" => [
53-
"parts" => $systemInstruction
54-
],
5552
"generationConfig"=> [
5653
"temperature"=> $config->getTemperature(),
5754
"maxOutputTokens"=> $config->getMaxTokens(),
5855
]
5956
];
6057

58+
if (!empty($systemInstruction)) {
59+
$input['system_instruction'] = [
60+
"parts" => $systemInstruction
61+
];
62+
}
63+
6164
$ch = curl_init($url);
6265
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
6366
curl_setopt($ch, CURLOPT_POST, true);

0 commit comments

Comments
 (0)