Skip to content

Commit 64edf9f

Browse files
committed
feat: Enable calling AI services on serverside, instead of from the client
1 parent 2420b20 commit 64edf9f

File tree

22 files changed

+323
-59
lines changed

22 files changed

+323
-59
lines changed

_build/gpm.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ plugins:
1010
- OnManagerPageBeforeRender
1111

1212
systemSettings:
13+
- key: api.execute_on_server
14+
area: api
15+
type: combo-boolean
16+
value: 0
1317
- key: api.chatgpt.key
1418
type: text-password
1519
area: api

assets/components/modai/js/mgr/serviceExecutor.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
modAI.serviceExecutor = async (details) => {
2+
if (!details.forExecutor) {
3+
return details;
4+
}
5+
6+
const executorDetails = details.forExecutor;
7+
28
const callService = async (details) => {
39
const res = await fetch(details.url, {
410
method: 'POST',
@@ -88,15 +94,15 @@ modAI.serviceExecutor = async (details) => {
8894
}
8995
};
9096

91-
if (!details.service || !details.parser) {
97+
if (!executorDetails.service || !executorDetails.parser) {
9298
throw new Error(_('modai.cmp.service_required'));
9399
}
94100

95-
if (!services[details.service]?.[details.parser]) {
101+
if (!services[executorDetails.service]?.[executorDetails.parser]) {
96102
throw new Error(_('modai.cmp.service_unsupported'));
97103
}
98104

99-
const data = await callService(details);
105+
const data = await callService(executorDetails);
100106

101-
return services[details.service][details.parser](data);
107+
return services[executorDetails.service][executorDetails.parser](data);
102108
}

core/components/modai/elements/plugins/modai.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@
4444
$modx->regClientStartupScript($assetsUrl . 'js/mgr/autosummary.js');
4545
$modx->regClientStartupScript($assetsUrl . 'js/mgr/widgets/image_prompt.window.js');
4646
$modx->regClientStartupScript($assetsUrl . 'js/mgr/widgets/text_prompt.window.js');
47-
}
47+
}

core/components/modai/lexicon/en/default.inc.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
$_lang['setting_modai.image.path_desc'] = 'Path including file name where the AI generated image will be stored. Available placeholders: {hash}, {shortHash}, {resourceId}.';
6363
$_lang['setting_modai.image.download_domains'] = 'Allowed Download Domains';
6464
$_lang['setting_modai.image.download_domains_desc'] = 'Additional domains to allow downloading generated images from.';
65+
$_lang['setting_modai.api.execute_on_server'] = 'Execute AI\'s request on server';
66+
$_lang['setting_modai.api.execute_on_server_desc'] = 'If enabled, allAI requests will be executed on server side. Be aware of increased load for your server.';
6567

6668
$_lang['modai.error.compatability_mode'] = "Unsupported API compatibility mode (modai.api.custom.compatibility).";
6769
$_lang['modai.error.invalid_api_key'] = "Missing modai.api.[[+service]].key";
@@ -77,4 +79,4 @@
7779
$_lang['modai.error.image_required'] = "Image or URL is required";
7880
$_lang['modai.error.ms_required'] = "Media Source is required";
7981
$_lang['modai.error.prompt_required'] = "Prompt is required";
80-
$_lang['modai.error.resource_required'] = "Resource is required";
82+
$_lang['modai.error.resource_required'] = "Resource is required";
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
namespace modAI\Exceptions;
3+
4+
use Throwable;
5+
6+
class LexiconException extends \Exception {
7+
private string $lexicon;
8+
private array $lexiconParams = [];
9+
10+
public function __construct($lexicon = "", array $lexiconParams = [], $code = 0, Throwable $previous = null)
11+
{
12+
$this->lexicon = $lexicon;
13+
$this->lexiconParams = $lexiconParams;
14+
15+
parent::__construct($lexicon, $code, $previous);
16+
}
17+
18+
public function getLexicon(): string
19+
{
20+
return $this->lexicon;
21+
}
22+
23+
public function getLexiconParams(): array
24+
{
25+
return $this->lexiconParams;
26+
}
27+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function process()
4444
$aiService = AIServiceFactory::new($model, $this->modx);
4545
$result = $aiService->getCompletions([$prompt], CompletionsConfig::new($model)->maxTokens($maxTokens)->temperature($temperature)->systemInstructions($systemInstructions));
4646

47-
return $this->success('', $result->toArray());
47+
return $this->success('', $result->generate());
4848
} catch (\Exception $e) {
4949
return $this->failure($e->getMessage());
5050
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function process()
3232
$aiService = AIServiceFactory::new($model, $this->modx);
3333
$result = $aiService->generateImage($prompt, ImageConfig::new($model)->size($size)->quality($quality));
3434

35-
return $this->success('', $result->toArray());
35+
return $this->success('', $result->generate());
3636
} catch (\Exception $e) {
3737
return $this->failure($e->getMessage());
3838
}

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

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

4+
use modAI\Exceptions\LexiconException;
45
use modAI\RequiredSettingException;
56
use modAI\Services\AIServiceFactory;
67
use modAI\Services\ChatGPT;
78
use modAI\Services\Config\CompletionsConfig;
9+
use modAI\Services\Executor\ServiceExecutor;
810
use modAI\Settings;
911
use MODX\Revolution\Processors\Processor;
1012

@@ -79,7 +81,9 @@ public function process()
7981
$aiService = AIServiceFactory::new($model, $this->modx);
8082
$result = $aiService->getCompletions([$content], CompletionsConfig::new($model)->maxTokens($maxTokens)->temperature($temperature)->systemInstructions($systemInstructions));
8183

82-
return $this->success('', $result->toArray());
84+
return $this->success('', $result->generate());
85+
} catch(LexiconException $e) {
86+
return $this->failure($this->modx->lexicon($e->getLexicon(), $e->getLexiconParams()));
8387
} catch (\Exception $e) {
8488
return $this->failure($e->getMessage());
8589
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function process()
2626
$aiService = AIServiceFactory::new($model, $this->modx);
2727
$result = $aiService->getVision($prompt, $image, VisionConfig::new($model));
2828

29-
return $this->success('', $result->toArray());
29+
return $this->success('', $result->generate());
3030
} catch (\Exception $e) {
3131
return $this->failure($e->getMessage());
3232
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,26 @@
22

33
namespace modAI\Services;
44

5+
use modAI\Exceptions\LexiconException;
56
use modAI\Services\Config\CompletionsConfig;
67
use modAI\Services\Config\ImageConfig;
78
use modAI\Services\Config\VisionConfig;
89
use modAI\Services\Response\AIResponse;
910

1011
interface AIService {
1112

13+
/**
14+
* @throws LexiconException
15+
*/
1216
public function getCompletions(array $data, CompletionsConfig $config): AIResponse;
17+
18+
/**
19+
* @throws LexiconException
20+
*/
1321
public function getVision(string $prompt, string $image, VisionConfig $config): AIResponse;
22+
23+
/**
24+
* @throws LexiconException
25+
*/
1426
public function generateImage(string $prompt, ImageConfig $config): AIResponse;
1527
}

0 commit comments

Comments
 (0)