From 2a3ef102f7527041609ad96bc59d6b21f42980d4 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Tue, 25 Jul 2023 14:17:57 +0200 Subject: [PATCH] AI admin settings: Use config values in AI feature managers Signed-off-by: Marcel Klehr --- .../Settings/Admin/ArtificialIntelligence.php | 2 +- .../SpeechToText/SpeechToTextManager.php | 15 ++++++++++- lib/private/TextProcessing/Manager.php | 18 ++++++++++++- .../Translation/TranslationManager.php | 25 ++++++++++++++++--- 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php index ad5425d8ded9b..2f36e4b033070 100644 --- a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php +++ b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php @@ -112,7 +112,7 @@ public function getForm() { $value = $defaultValue; $json = $this->config->getAppValue('core', $key, ''); if ($json !== '') { - $value = json_decode($json, JSON_OBJECT_AS_ARRAY); + $value = json_decode($json, true); switch($key) { case 'ai.textprocessing_provider_preferences': // fill $value with $defaultValue values diff --git a/lib/private/SpeechToText/SpeechToTextManager.php b/lib/private/SpeechToText/SpeechToTextManager.php index 757fc02485e98..bdd04ad365176 100644 --- a/lib/private/SpeechToText/SpeechToTextManager.php +++ b/lib/private/SpeechToText/SpeechToTextManager.php @@ -34,6 +34,7 @@ use OCP\Files\File; use OCP\Files\InvalidPathException; use OCP\Files\NotFoundException; +use OCP\IConfig; use OCP\IServerContainer; use OCP\PreConditionNotMetException; use OCP\SpeechToText\ISpeechToTextManager; @@ -53,6 +54,7 @@ public function __construct( private Coordinator $coordinator, private LoggerInterface $logger, private IJobList $jobList, + private IConfig $config, ) { } @@ -111,7 +113,18 @@ public function transcribeFile(File $file): string { throw new PreConditionNotMetException('No SpeechToText providers have been registered'); } - foreach ($this->getProviders() as $provider) { + $providers = $this->getProviders(); + + $json = $this->config->getAppValue('core', 'ai.stt_provider', ''); + if ($json !== '') { + $className = json_decode($json, true); + $provider = current(array_filter($providers, fn ($provider) => $provider::class === $className)); + if ($provider !== false) { + $providers = [$provider]; + } + } + + foreach ($providers as $provider) { try { return $provider->transcribeFile($file); } catch (\Throwable $e) { diff --git a/lib/private/TextProcessing/Manager.php b/lib/private/TextProcessing/Manager.php index f52482bbb3219..05e046a004978 100644 --- a/lib/private/TextProcessing/Manager.php +++ b/lib/private/TextProcessing/Manager.php @@ -27,6 +27,7 @@ use OC\AppFramework\Bootstrap\Coordinator; use OC\TextProcessing\Db\Task as DbTask; +use OCP\IConfig; use OCP\TextProcessing\Task as OCPTask; use OC\TextProcessing\Db\TaskMapper; use OCP\AppFramework\Db\DoesNotExistException; @@ -52,6 +53,7 @@ public function __construct( private LoggerInterface $logger, private IJobList $jobList, private TaskMapper $taskMapper, + private IConfig $config, ) { } @@ -111,7 +113,21 @@ public function runTask(OCPTask $task): string { if (!$this->canHandleTask($task)) { throw new PreConditionNotMetException('No text processing provider is installed that can handle this task'); } - foreach ($this->getProviders() as $provider) { + $providers = $this->getProviders(); + $json = $this->config->getAppValue('core', 'ai.textprocessing_provider_preferences', ''); + if ($json !== '') { + $preferences = json_decode($json, true); + if (isset($preferences[$task->getType()])) { + // If a preference for this task type is set, move the preferred provider to the start + $provider = current(array_filter($providers, fn ($provider) => $provider::class === $preferences[$task->getType()])); + if ($provider !== false) { + $providers = array_filter($providers, fn ($p) => $p !== $provider); + array_unshift($providers, $provider); + } + } + } + + foreach ($providers as $provider) { if (!$task->canUseProvider($provider)) { continue; } diff --git a/lib/private/Translation/TranslationManager.php b/lib/private/Translation/TranslationManager.php index 8456c41cdfceb..48a0e2cdebdda 100644 --- a/lib/private/Translation/TranslationManager.php +++ b/lib/private/Translation/TranslationManager.php @@ -28,6 +28,7 @@ use InvalidArgumentException; use OC\AppFramework\Bootstrap\Coordinator; +use OCP\IConfig; use OCP\IServerContainer; use OCP\PreConditionNotMetException; use OCP\Translation\CouldNotTranslateException; @@ -48,6 +49,7 @@ public function __construct( private IServerContainer $serverContainer, private Coordinator $coordinator, private LoggerInterface $logger, + private IConfig $config, ) { } @@ -64,8 +66,25 @@ public function translate(string $text, ?string &$fromLanguage, string $toLangua throw new PreConditionNotMetException('No translation providers available'); } + $providers = $this->getProviders(); + $json = $this->config->getAppValue('core', 'ai.translation_provider_preferences', ''); + + if ($json !== '') { + $precedence = json_decode($json, true); + $newProviders = []; + foreach ($precedence as $className) { + $provider = current(array_filter($providers, fn ($provider) => $provider::class === $className)); + if ($provider !== false) { + $newProviders[] = $provider; + } + } + // Add all providers that haven't been added so far + $newProviders += array_udiff($providers, $newProviders, fn ($a, $b) => $a::class > $b::class ? 1 : ($a::class < $b::class ? -1 : 0)); + $providers = $newProviders; + } + if ($fromLanguage === null) { - foreach ($this->getProviders() as $provider) { + foreach ($providers as $provider) { if ($provider instanceof IDetectLanguageProvider) { $fromLanguage = $provider->detectLanguage($text); } @@ -84,11 +103,11 @@ public function translate(string $text, ?string &$fromLanguage, string $toLangua return $text; } - foreach ($this->getProviders() as $provider) { + foreach ($providers as $provider) { try { return $provider->translate($fromLanguage, $toLanguage, $text); } catch (RuntimeException $e) { - $this->logger->warning("Failed to translate from {$fromLanguage} to {$toLanguage}", ['exception' => $e]); + $this->logger->warning("Failed to translate from {$fromLanguage} to {$toLanguage} using provider {$provider->getName()}", ['exception' => $e]); } }