Skip to content

Commit dbc3bd0

Browse files
committed
feat: add support for gemini
1 parent d65c986 commit dbc3bd0

File tree

13 files changed

+411
-123
lines changed

13 files changed

+411
-123
lines changed

_build/gpm.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ systemSettings:
1313
- key: chatgpt.key
1414
type: text-password
1515
area: chatgpt
16-
description: "Your API key found at https://platform.openai.com/api-keys."
16+
description: "Your API key found at https://platform.openai.com/api-keys"
17+
- key: gemini.key
18+
type: text-password
19+
area: chatgpt
20+
description: "Your API key found at https://ai.google.dev/gemini-api/docs/api-key"
1721

1822
- key: global.base.output
1923
area: global

assets/components/modai/js/mgr/widgets/image_prompt.window.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ Ext.extend(modAI.window.ImagePrompt,MODx.Window, {
167167
listeners: {
168168
success: {
169169
fn: (r) => {
170-
this.pagination.addItem({prompt: this.prompt.getValue(), url: r.object.data.url});
170+
this.pagination.addItem({prompt: this.prompt.getValue(), url: r.object.url});
171171
Ext.Msg.hide();
172172
}
173173
},

core/components/modai/src/Processors/Prompt/FreeText.php

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
namespace modAI\Processors\Prompt;
33

44
use modAI\RequiredSettingException;
5-
use modAI\Services\ChatGPT;
5+
use modAI\Services\AIServiceFactory;
6+
use modAI\Services\Config\CompletionsConfig;
67
use modAI\Settings;
78
use MODX\Revolution\Processors\Processor;
89

@@ -17,9 +18,8 @@ public function process()
1718
return $this->failure('Prompt is required.');
1819
}
1920

20-
$chatGPT = new ChatGPT($this->modx);
2121

22-
$messages = [];
22+
$systemInstructions = [];
2323

2424
try {
2525
$model = Settings::getFieldSetting($this->modx, $field, 'model');
@@ -31,42 +31,20 @@ public function process()
3131
}
3232

3333
if (!empty($output)) {
34-
$messages[] = [
35-
'role' => 'system',
36-
'content' => $output,
37-
];
34+
$systemInstructions[] = $output;
3835
}
3936

4037
$base = Settings::getPrompt($this->modx, 'global.base');
4138
if (!empty($base)) {
42-
$messages[] = [
43-
'role' => 'system',
44-
'content' => $base,
45-
];
39+
$systemInstructions[] = $base;
4640
}
4741

48-
$messages[] = [
49-
'role' => 'user',
50-
'content' => $prompt
51-
];
52-
53-
$data = [
54-
'model' => $model,
55-
'messages' => $messages,
56-
'max_tokens' => $maxTokens,
57-
'temperature' => $temperature
58-
];
42+
$aiService = AIServiceFactory::new($model, $this->modx);
5943

6044
try {
61-
$result = $chatGPT->getCompletions($data);
62-
63-
if (!isset($result['choices'][0]['message']['content'])) {
64-
return $this->failure('Error from ChatGPT API: ' . print_r($result, true));
65-
}
66-
67-
$response = trim($result['choices'][0]['message']['content']);
45+
$result = $aiService->getCompletions([$prompt], CompletionsConfig::new($model)->maxTokens($maxTokens)->temperature($temperature)->systemInstructions($systemInstructions));
6846

69-
return $this->success('', ['content' => $response]);
47+
return $this->success('', ['content' => $result]);
7048
} catch (\Exception $e) {
7149
return $this->failure($e->getMessage());
7250
}

core/components/modai/src/Processors/Prompt/Image.php

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace modAI\Processors\Prompt;
44

5-
use modAI\Services\ChatGPT;
5+
use modAI\Services\AIServiceFactory;
6+
use modAI\Services\Config\ImageConfig;
67
use modAI\Settings;
78
use MODX\Revolution\Processors\Processor;
89

@@ -30,24 +31,12 @@ public function process()
3031
return $this->failure('image.quality setting is required');
3132
}
3233

33-
$chatGPT = new ChatGPT($this->modx);
34-
35-
$data = [
36-
'model' => $model,
37-
'prompt' => $prompt,
38-
'n' => 1,
39-
'size' => $size,
40-
'quality' => $quality
41-
];
34+
$aiService = AIServiceFactory::new($model, $this->modx);
4235

4336
try {
44-
$result = $chatGPT->generateImage($data);
45-
46-
if (!isset($result['data'][0]['url'])) {
47-
return $this->failure('Error from ChatGPT API: ' . print_r($result, true));
48-
}
37+
$result = $aiService->generateImage($prompt, ImageConfig::new($model)->size($size)->quality($quality));
4938

50-
return $this->success('', ['data' => $result['data'][0]]);
39+
return $this->success('', ['url' => $result]);
5140
} catch (\Exception $e) {
5241
return $this->failure($e->getMessage());
5342
}

core/components/modai/src/Processors/Prompt/Text.php

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
namespace modAI\Processors\Prompt;
33

44
use modAI\RequiredSettingException;
5-
use modAI\Services\ChatGPT;
5+
use modAI\Services\AIServiceFactory;
6+
use modAI\Services\Config\CompletionsConfig;
67
use modAI\Settings;
78
use MODX\Revolution\Processors\Processor;
89

@@ -46,10 +47,7 @@ public function process()
4647
return $this->failure('There\'s no content');
4748
}
4849

49-
$chatGPT = new ChatGPT($this->modx);
50-
51-
52-
$messages = [];
50+
$systemInstructions = [];
5351

5452
try {
5553
$model = Settings::getFieldSetting($this->modx, $field, 'model');
@@ -61,50 +59,25 @@ public function process()
6159
}
6260

6361
if (!empty($output)) {
64-
$messages[] = [
65-
'role' => 'system',
66-
'content' => $output,
67-
];
62+
$systemInstructions[] = $output;
6863
}
6964

7065
$base = Settings::getPrompt($this->modx, 'global.base');
7166
if (!empty($base)) {
72-
$messages[] = [
73-
'role' => 'system',
74-
'content' => $base,
75-
];
67+
$systemInstructions[] = $base;
7668
}
7769

7870
$fieldPrompt = Settings::getPrompt($this->modx, $field);
7971
if (!empty($fieldPrompt)) {
80-
$messages[] = [
81-
'role' => 'system',
82-
'content' => $fieldPrompt,
83-
];
72+
$systemInstructions[] = $fieldPrompt;
8473
}
8574

86-
$messages[] = [
87-
'role' => 'user',
88-
'content' => $content
89-
];
90-
91-
$data = [
92-
'model' => $model,
93-
'messages' => $messages,
94-
'max_tokens' => $maxTokens,
95-
'temperature' => $temperature
96-
];
75+
$aiService = AIServiceFactory::new($model, $this->modx);
9776

9877
try {
99-
$result = $chatGPT->getCompletions($data);
100-
101-
if (!isset($result['choices'][0]['message']['content'])) {
102-
return $this->failure('Error from ChatGPT API: ' . print_r($result, true));
103-
}
104-
105-
$response = trim($result['choices'][0]['message']['content']);
78+
$result = $aiService->getCompletions([$content], CompletionsConfig::new($model)->maxTokens($maxTokens)->temperature($temperature)->systemInstructions($systemInstructions));
10679

107-
return $this->success('', ['content' => $response]);
80+
return $this->success('', ['content' => $result]);
10881
} catch (\Exception $e) {
10982
return $this->failure($e->getMessage());
11083
}

core/components/modai/src/Processors/Prompt/Vision.php

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<?php
22
namespace modAI\Processors\Prompt;
33

4-
use modAI\Services\ChatGPT;
4+
use modAI\Services\AIServiceFactory;
5+
use modAI\Services\Config\VisionConfig;
56
use modAI\Settings;
67
use MODX\Revolution\Processors\Processor;
78

@@ -14,8 +15,6 @@ public function process()
1415
return $this->failure('Image is required');
1516
}
1617

17-
$chatGPT = new ChatGPT($this->modx);
18-
1918
$model = Settings::getSetting($this->modx, 'vision.model');
2019
if (empty($model)) {
2120
return $this->failure('vision.model setting is required');
@@ -26,37 +25,12 @@ public function process()
2625
return $this->failure('vision.prompt setting is required');
2726
}
2827

29-
$messages = [];
30-
31-
$messages[] = [
32-
'role' => 'user',
33-
'content' => [
34-
[
35-
"type"=> "text",
36-
"text"=> $prompt,
37-
],
38-
[
39-
"type" => "image_url",
40-
"image_url" => ["url" => $image],
41-
],
42-
]
43-
];
44-
45-
$data = [
46-
'model' => $model,
47-
'messages' => $messages,
48-
];
28+
$aiService = AIServiceFactory::new($model, $this->modx);
4929

5030
try {
51-
$result = $chatGPT->getCompletions($data);
52-
53-
if (!isset($result['choices'][0]['message']['content'])) {
54-
return $this->failure('Error from ChatGPT API: ' . print_r($result, true));
55-
}
56-
57-
$response = trim($result['choices'][0]['message']['content']);
31+
$result = $aiService->getVision($prompt, $image, VisionConfig::new($model));
5832

59-
return $this->success('', ['content' => $response]);
33+
return $this->success('', ['content' => $result]);
6034
} catch (\Exception $e) {
6135
return $this->failure($e->getMessage());
6236
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace modAI\Services;
4+
5+
use modAI\Services\Config\CompletionsConfig;
6+
use modAI\Services\Config\ImageConfig;
7+
use modAI\Services\Config\VisionConfig;
8+
9+
interface AIService {
10+
11+
public function getCompletions(array $data, CompletionsConfig $config): string;
12+
public function getVision(string $prompt, string $image, VisionConfig $config): string;
13+
public function generateImage(string $prompt, ImageConfig $config): string;
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
namespace modAI\Services;
3+
4+
use MODX\Revolution\modX;
5+
6+
class AIServiceFactory {
7+
public static function new($model, modX &$modx): AIService {
8+
if (substr($model, 0, 7) === 'gemini-') {
9+
return new Gemini($modx);
10+
}
11+
12+
switch ($model) {
13+
case 'text-embedding-004':
14+
case 'learnlm-1.5-pro-experimental':
15+
return new Gemini($modx);
16+
default:
17+
return new ChatGPT($modx);
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)