diff options
author | Marcel Klehr <mklehr@gmx.net> | 2023-07-14 15:59:50 +0200 |
---|---|---|
committer | Marcel Klehr <mklehr@gmx.net> | 2023-08-09 10:05:05 +0200 |
commit | cf2c42ae36a3c7280887bd3f15329739f9a6d221 (patch) | |
tree | 3e682483cc8177afd7b9e682fcaa103791f78d2a | |
parent | 696a45ddf1d460de7ffa6f252912375efd7e190e (diff) | |
download | nextcloud-server-cf2c42ae36a3c7280887bd3f15329739f9a6d221.tar.gz nextcloud-server-cf2c42ae36a3c7280887bd3f15329739f9a6d221.zip |
Massive refactoring: Turn LanguageModel OCP API into TextProcessing API
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
(cherry picked from commit ffe27ce14ca74b509c8721c9fba7c759498fa471)
31 files changed, 553 insertions, 748 deletions
diff --git a/core/Controller/LanguageModelApiController.php b/core/Controller/TextProcessingApiController.php index 74ed26e604a..7cc7199dfbd 100644 --- a/core/Controller/LanguageModelApiController.php +++ b/core/Controller/TextProcessingApiController.php @@ -32,17 +32,24 @@ use OCP\AppFramework\Http\DataResponse; use OCP\Common\Exception\NotFoundException; use OCP\IL10N; use OCP\IRequest; -use OCP\LanguageModel\AbstractLanguageModelTask; -use OCP\LanguageModel\ILanguageModelManager; +use OCP\TextProcessing\ITaskType; +use OCP\TextProcessing\Task; +use OCP\TextProcessing\IManager; use OCP\PreConditionNotMetException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerInterface; -class LanguageModelApiController extends \OCP\AppFramework\OCSController { +class TextProcessingApiController extends \OCP\AppFramework\OCSController { public function __construct( - string $appName, - IRequest $request, - private ILanguageModelManager $languageModelManager, - private IL10N $l, - private ?string $userId, + string $appName, + IRequest $request, + private IManager $languageModelManager, + private IL10N $l, + private ?string $userId, + private ContainerInterface $container, + private LoggerInterface $logger, ) { parent::__construct($appName, $request); } @@ -51,13 +58,31 @@ class LanguageModelApiController extends \OCP\AppFramework\OCSController { * This endpoint returns all available LanguageModel task types * * @PublicPage - * @return DataResponse<Http::STATUS_OK, array{types: string[]}, array{}> + * @return DataResponse<Http::STATUS_OK, array{types: list<array{id: string, name: string, description: string}>}, array{}> * * 200: Task types returned */ public function taskTypes(): DataResponse { + $typeClasses = $this->languageModelManager->getAvailableTaskTypes(); + /** @var list<array{id: string, name: string, description: string}> $types */ + $types = []; + foreach ($typeClasses as $typeClass) { + /** @var ITaskType $object */ + try { + $object = $this->container->get($typeClass); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this->logger->warning('Could not find ' . $typeClass, ['exception' => $e]); + continue; + } + $types[] = [ + 'id' => $typeClass, + 'name' => $object->getName(), + 'description' => $object->getDescription(), + ]; + } + return new DataResponse([ - 'types' => $this->languageModelManager->getAvailableTaskTypes(), + 'types' => $types, ]); } @@ -79,14 +104,13 @@ class LanguageModelApiController extends \OCP\AppFramework\OCSController { */ public function schedule(string $input, string $type, string $appId, string $identifier = ''): DataResponse { try { - $task = AbstractLanguageModelTask::factory($type, $input, $this->userId, $appId, $identifier); - } catch (InvalidArgumentException $e) { + $task = Task::factory($type, $input, $this->userId, $appId, $identifier); + } catch (InvalidArgumentException) { return new DataResponse(['message' => $this->l->t('Requested task type does not exist')], Http::STATUS_BAD_REQUEST); } try { $this->languageModelManager->scheduleTask($task); - /** @var array{id: int|null, type: string, status: int, userId: string|null, appId: string, input: string, output: string|null, identifier: string} $json */ $json = $task->jsonSerialize(); return new DataResponse([ @@ -117,7 +141,6 @@ class LanguageModelApiController extends \OCP\AppFramework\OCSController { return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND); } - /** @var array{id: int|null, type: string, status: int, userId: string|null, appId: string, input: string, output: string|null, identifier: string} $json */ $json = $task->jsonSerialize(); return new DataResponse([ diff --git a/core/routes.php b/core/routes.php index 24af95cd7af..4790f32af32 100644 --- a/core/routes.php +++ b/core/routes.php @@ -146,9 +146,9 @@ $application->registerRoutes($this, [ ['root' => '/translation', 'name' => 'TranslationApi#languages', 'url' => '/languages', 'verb' => 'GET'], ['root' => '/translation', 'name' => 'TranslationApi#translate', 'url' => '/translate', 'verb' => 'POST'], - ['root' => '/languagemodel', 'name' => 'LanguageModelApi#taskTypes', 'url' => '/tasktypes', 'verb' => 'GET'], - ['root' => '/languagemodel', 'name' => 'LanguageModelApi#schedule', 'url' => '/schedule', 'verb' => 'POST'], - ['root' => '/languagemodel', 'name' => 'LanguageModelApi#getTask', 'url' => '/task/{id}', 'verb' => 'GET'], + ['root' => '/textprocessing', 'name' => 'TextProcessingApi#taskTypes', 'url' => '/tasktypes', 'verb' => 'GET'], + ['root' => '/textprocessing', 'name' => 'TextProcessingApi#schedule', 'url' => '/schedule', 'verb' => 'POST'], + ['root' => '/textprocessing', 'name' => 'TextProcessingApi#getTask', 'url' => '/task/{id}', 'verb' => 'GET'], ], ]); diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php index 67e8b390c15..5aea2a7a744 100644 --- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php +++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php @@ -33,7 +33,7 @@ use Closure; use OCP\Calendar\Resource\IBackend as IResourceBackend; use OCP\Calendar\Room\IBackend as IRoomBackend; use OCP\Collaboration\Reference\IReferenceProvider; -use OCP\LanguageModel\ILanguageModelProvider; +use OCP\TextProcessing\IProvider as ITextProcessingProvider; use OCP\SpeechToText\ISpeechToTextProvider; use OCP\Talk\ITalkBackend; use OCP\Translation\ITranslationProvider; @@ -116,8 +116,8 @@ class RegistrationContext { /** @var ServiceRegistration<ISpeechToTextProvider>[] */ private $speechToTextProviders = []; - /** @var ServiceRegistration<ILanguageModelProvider>[] */ - private $languageModelProviders = []; + /** @var ServiceRegistration<ITextProcessingProvider>[] */ + private $textProcessingProviders = []; /** @var ServiceRegistration<ICustomTemplateProvider>[] */ private $templateProviders = []; @@ -266,8 +266,8 @@ class RegistrationContext { $providerClass ); } - public function registerLanguageModelProvider(string $providerClass): void { - $this->context->registerLanguageModelProvider( + public function registerTextProcessingProvider(string $providerClass): void { + $this->context->registerTextProcessingProvider( $this->appId, $providerClass ); @@ -439,8 +439,8 @@ class RegistrationContext { $this->speechToTextProviders[] = new ServiceRegistration($appId, $class); } - public function registerLanguageModelProvider(string $appId, string $class): void { - $this->languageModelProviders[] = new ServiceRegistration($appId, $class); + public function registerTextProcessingProvider(string $appId, string $class): void { + $this->textProcessingProviders[] = new ServiceRegistration($appId, $class); } public function registerTemplateProvider(string $appId, string $class): void { @@ -722,10 +722,10 @@ class RegistrationContext { } /** - * @return ServiceRegistration<ILanguageModelProvider>[] + * @return ServiceRegistration<ITextProcessingProvider>[] */ - public function getLanguageModelProviders(): array { - return $this->languageModelProviders; + public function getTextProcessingProviders(): array { + return $this->textProcessingProviders; } /** diff --git a/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php b/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php index 713192b06f9..94ae39f2183 100644 --- a/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php +++ b/lib/private/Repair/AddRemoveOldTasksBackgroundJob.php @@ -25,7 +25,7 @@ declare(strict_types=1); */ namespace OC\Repair; -use OC\LanguageModel\RemoveOldTasksBackgroundJob; +use OC\TextProcessing\RemoveOldTasksBackgroundJob; use OCP\BackgroundJob\IJobList; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; diff --git a/lib/private/Server.php b/lib/private/Server.php index d1f18a1235f..516dc0b6e8b 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -110,7 +110,6 @@ use OC\IntegrityCheck\Checker; use OC\IntegrityCheck\Helpers\AppLocator; use OC\IntegrityCheck\Helpers\EnvironmentHelper; use OC\IntegrityCheck\Helpers\FileAccessHelper; -use OC\LanguageModel\LanguageModelManager; use OC\LDAP\NullLDAPProviderFactory; use OC\KnownUser\KnownUserService; use OC\Lock\DBLockingProvider; @@ -229,7 +228,6 @@ use OCP\IURLGenerator; use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory; -use OCP\LanguageModel\ILanguageModelManager; use OCP\LDAP\ILDAPProvider; use OCP\LDAP\ILDAPProviderFactory; use OCP\Lock\ILockingProvider; @@ -1463,7 +1461,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(ISpeechToTextManager::class, SpeechToTextManager::class); - $this->registerAlias(ILanguageModelManager::class, LanguageModelManager::class); + $this->registerAlias(\OCP\TextProcessing\IManager::class, \OC\TextProcessing\Manager::class); $this->connectDispatcher(); } diff --git a/lib/private/Setup.php b/lib/private/Setup.php index a80afee6d86..3c1ac559c87 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -53,7 +53,7 @@ use Exception; use InvalidArgumentException; use OC\Authentication\Token\PublicKeyTokenProvider; use OC\Authentication\Token\TokenCleanupJob; -use OC\LanguageModel\RemoveOldTasksBackgroundJob; +use OC\TextProcessing\RemoveOldTasksBackgroundJob; use OC\Log\Rotate; use OC\Preview\BackgroundCleanupJob; use OCP\AppFramework\Utility\ITimeFactory; diff --git a/lib/private/LanguageModel/Db/Task.php b/lib/private/TextProcessing/Db/Task.php index 4e46f19e8a9..bc1bbdc13db 100644 --- a/lib/private/LanguageModel/Db/Task.php +++ b/lib/private/TextProcessing/Db/Task.php @@ -23,11 +23,10 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -namespace OC\LanguageModel\Db; +namespace OC\TextProcessing\Db; use OCP\AppFramework\Db\Entity; -use OCP\LanguageModel\AbstractLanguageModelTask; -use OCP\LanguageModel\ILanguageModelTask; +use OCP\TextProcessing\Task as OCPTask; /** * @method setType(string $type) @@ -87,7 +86,7 @@ class Task extends Entity { }, self::$fields)); } - public static function fromLanguageModelTask(ILanguageModelTask $task): Task { + public static function fromPublicTask(OCPTask $task): Task { /** @var Task $task */ $task = Task::fromParams([ 'id' => $task->getId(), @@ -103,8 +102,8 @@ class Task extends Entity { return $task; } - public function toLanguageModelTask(): ILanguageModelTask { - $task = AbstractLanguageModelTask::factory($this->getType(), $this->getInput(), $this->getuserId(), $this->getAppId(), $this->getIdentifier()); + public function toPublicTask(): OCPTask { + $task = OCPTask::factory($this->getType(), $this->getInput(), $this->getuserId(), $this->getAppId(), $this->getIdentifier()); $task->setId($this->getId()); $task->setStatus($this->getStatus()); $task->setOutput($this->getOutput()); diff --git a/lib/private/LanguageModel/Db/TaskMapper.php b/lib/private/TextProcessing/Db/TaskMapper.php index 9b93ea1990f..508f3fdf3b8 100644 --- a/lib/private/LanguageModel/Db/TaskMapper.php +++ b/lib/private/TextProcessing/Db/TaskMapper.php @@ -23,7 +23,7 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -namespace OC\LanguageModel\Db; +namespace OC\TextProcessing\Db; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\Entity; diff --git a/lib/private/LanguageModel/LanguageModelManager.php b/lib/private/TextProcessing/Manager.php index 970d968c883..34e4b2bb4cc 100644 --- a/lib/private/LanguageModel/LanguageModelManager.php +++ b/lib/private/TextProcessing/Manager.php @@ -23,34 +23,27 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -namespace OC\LanguageModel; +namespace OC\TextProcessing; use OC\AppFramework\Bootstrap\Coordinator; -use OC\LanguageModel\Db\Task; -use OC\LanguageModel\Db\TaskMapper; +use OC\TextProcessing\Db\Task as DbTask; +use \OCP\TextProcessing\Task as OCPTask; +use OC\TextProcessing\Db\TaskMapper; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\BackgroundJob\IJobList; use OCP\Common\Exception\NotFoundException; use OCP\DB\Exception; use OCP\IServerContainer; -use OCP\LanguageModel\FreePromptTask; -use OCP\LanguageModel\HeadlineTask; -use OCP\LanguageModel\IHeadlineProvider; -use OCP\LanguageModel\ILanguageModelManager; -use OCP\LanguageModel\ILanguageModelProvider; -use OCP\LanguageModel\ILanguageModelTask; -use OCP\LanguageModel\ISummaryProvider; -use OCP\LanguageModel\ITopicsProvider; -use OCP\LanguageModel\SummaryTask; -use OCP\LanguageModel\TopicsTask; +use OCP\TextProcessing\IManager; +use OCP\TextProcessing\IProvider; use OCP\PreConditionNotMetException; use Psr\Log\LoggerInterface; use RuntimeException; use Throwable; -class LanguageModelManager implements ILanguageModelManager { - /** @var ?ILanguageModelProvider[] */ +class Manager implements IManager { + /** @var ?IProvider[] */ private ?array $providers = null; public function __construct( @@ -74,12 +67,12 @@ class LanguageModelManager implements ILanguageModelManager { $this->providers = []; - foreach ($context->getLanguageModelProviders() as $providerServiceRegistration) { + foreach ($context->getTextProcessingProviders() as $providerServiceRegistration) { $class = $providerServiceRegistration->getService(); try { $this->providers[$class] = $this->serverContainer->get($class); } catch (Throwable $e) { - $this->logger->error('Failed to load LanguageModel provider ' . $class, [ + $this->logger->error('Failed to load Text processing provider ' . $class, [ 'exception' => $e, ]); } @@ -93,78 +86,57 @@ class LanguageModelManager implements ILanguageModelManager { if ($context === null) { return false; } - return count($context->getLanguageModelProviders()) > 0; + return count($context->getTextProcessingProviders()) > 0; } /** * @inheritDoc */ - public function getAvailableTaskClasses(): array { + public function getAvailableTaskTypes(): array { $tasks = []; foreach ($this->getProviders() as $provider) { - $tasks[FreePromptTask::class] = true; - if ($provider instanceof ISummaryProvider) { - $tasks[SummaryTask::class] = true; - } - if ($provider instanceof IHeadlineProvider) { - $tasks[HeadlineTask::class] = true; - } - if ($provider instanceof ITopicsProvider) { - $tasks[TopicsTask::class] = true; - } + $tasks[$provider->getTaskType()] = true; } return array_keys($tasks); } - /** - * @inheritDoc - */ - public function getAvailableTaskTypes(): array { - return array_map(fn ($taskClass) => $taskClass::TYPE, $this->getAvailableTaskClasses()); - } - - public function canHandleTask(ILanguageModelTask $task): bool { - foreach ($this->getAvailableTaskClasses() as $class) { - if ($task instanceof $class) { - return true; - } - } - return false; + public function canHandleTask(OCPTask $task): bool { + return in_array($task->getType(), $this->getAvailableTaskTypes()); } /** * @inheritDoc */ - public function runTask(ILanguageModelTask $task): string { + public function runTask(OCPTask $task): string { if (!$this->canHandleTask($task)) { - throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task'); + throw new PreConditionNotMetException('No text processing provider is installed that can handle this task'); } foreach ($this->getProviders() as $provider) { if (!$task->canUseProvider($provider)) { continue; } try { - $task->setStatus(ILanguageModelTask::STATUS_RUNNING); + $task->setStatus(OCPTask::STATUS_RUNNING); if ($task->getId() === null) { - $taskEntity = $this->taskMapper->insert(Task::fromLanguageModelTask($task)); + $taskEntity = $this->taskMapper->insert(DbTask::fromPublicTask($task)); $task->setId($taskEntity->getId()); } else { - $this->taskMapper->update(Task::fromLanguageModelTask($task)); + $this->taskMapper->update(DbTask::fromPublicTask($task)); } $output = $task->visitProvider($provider); $task->setOutput($output); - $task->setStatus(ILanguageModelTask::STATUS_SUCCESSFUL); - $this->taskMapper->update(Task::fromLanguageModelTask($task)); + $task->setStatus(OCPTask::STATUS_SUCCESSFUL); + $this->taskMapper->update(DbTask::fromPublicTask($task)); return $output; } catch (\RuntimeException $e) { $this->logger->info('LanguageModel call using provider ' . $provider->getName() . ' failed', ['exception' => $e]); - $task->setStatus(ILanguageModelTask::STATUS_FAILED); - $this->taskMapper->update(Task::fromLanguageModelTask($task)); + $task->setStatus(OCPTask::STATUS_FAILED); + $this->taskMapper->update(DbTask::fromPublicTask($task)); throw $e; } catch (\Throwable $e) { $this->logger->info('LanguageModel call using provider ' . $provider->getName() . ' failed', ['exception' => $e]); - $task->setStatus(ILanguageModelTask::STATUS_FAILED); - $this->taskMapper->update(Task::fromLanguageModelTask($task)); + $task->setStatus(OCPTask::STATUS_FAILED); + $this->taskMapper->update(DbTask::fromPublicTask($task)); throw new RuntimeException('LanguageModel call using provider ' . $provider->getName() . ' failed: ' . $e->getMessage(), 0, $e); } } @@ -176,12 +148,12 @@ class LanguageModelManager implements ILanguageModelManager { * @inheritDoc * @throws Exception */ - public function scheduleTask(ILanguageModelTask $task): void { + public function scheduleTask(OCPTask $task): void { if (!$this->canHandleTask($task)) { throw new PreConditionNotMetException('No LanguageModel provider is installed that can handle this task'); } - $task->setStatus(ILanguageModelTask::STATUS_SCHEDULED); - $taskEntity = Task::fromLanguageModelTask($task); + $task->setStatus(OCPTask::STATUS_SCHEDULED); + $taskEntity = DbTask::fromPublicTask($task); $this->taskMapper->insert($taskEntity); $task->setId($taskEntity->getId()); $this->jobList->add(TaskBackgroundJob::class, [ @@ -191,14 +163,14 @@ class LanguageModelManager implements ILanguageModelManager { /** * @param int $id The id of the task - * @return ILanguageModelTask + * @return OCPTask * @throws RuntimeException If the query failed * @throws NotFoundException If the task could not be found */ - public function getTask(int $id): ILanguageModelTask { + public function getTask(int $id): OCPTask { try { $taskEntity = $this->taskMapper->find($id); - return $taskEntity->toLanguageModelTask(); + return $taskEntity->toPublicTask(); } catch (DoesNotExistException $e) { throw new NotFoundException('Could not find task with the provided id'); } catch (MultipleObjectsReturnedException $e) { diff --git a/lib/private/LanguageModel/RemoveOldTasksBackgroundJob.php b/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php index fa3a716a2c6..89d329acfbb 100644 --- a/lib/private/LanguageModel/RemoveOldTasksBackgroundJob.php +++ b/lib/private/TextProcessing/RemoveOldTasksBackgroundJob.php @@ -24,9 +24,9 @@ declare(strict_types=1); */ -namespace OC\LanguageModel; +namespace OC\TextProcessing; -use OC\LanguageModel\Db\TaskMapper; +use OC\TextProcessing\Db\TaskMapper; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; use OCP\DB\Exception; diff --git a/lib/private/LanguageModel/TaskBackgroundJob.php b/lib/private/TextProcessing/TaskBackgroundJob.php index 5ac37baf332..4c24b3e531f 100644 --- a/lib/private/LanguageModel/TaskBackgroundJob.php +++ b/lib/private/TextProcessing/TaskBackgroundJob.php @@ -24,19 +24,19 @@ declare(strict_types=1); */ -namespace OC\LanguageModel; +namespace OC\TextProcessing; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\QueuedJob; use OCP\EventDispatcher\IEventDispatcher; -use OCP\LanguageModel\Events\TaskFailedEvent; -use OCP\LanguageModel\Events\TaskSuccessfulEvent; -use OCP\LanguageModel\ILanguageModelManager; +use OCP\TextProcessing\Events\TaskFailedEvent; +use OCP\TextProcessing\Events\TaskSuccessfulEvent; +use OCP\TextProcessing\IManager; class TaskBackgroundJob extends QueuedJob { public function __construct( - ITimeFactory $timeFactory, - private ILanguageModelManager $languageModelManager, + ITimeFactory $timeFactory, + private IManager $textProcessingManager, private IEventDispatcher $eventDispatcher, ) { parent::__construct($timeFactory); @@ -51,9 +51,9 @@ class TaskBackgroundJob extends QueuedJob { */ protected function run($argument) { $taskId = $argument['taskId']; - $task = $this->languageModelManager->getTask($taskId); + $task = $this->textProcessingManager->getTask($taskId); try { - $this->languageModelManager->runTask($task); + $this->textProcessingManager->runTask($task); $event = new TaskSuccessfulEvent($task); } catch (\Throwable $e) { $event = new TaskFailedEvent($task, $e->getMessage()); diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php index 66435d45934..720803a78d1 100644 --- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php +++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php @@ -37,7 +37,7 @@ use OCP\Collaboration\Reference\IReferenceProvider; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Template\ICustomTemplateProvider; use OCP\IContainer; -use OCP\LanguageModel\ILanguageModelProvider; +use OCP\TextProcessing\IProvider as ITextProcessingProvider; use OCP\Notification\INotifier; use OCP\Preview\IProviderV2; use OCP\SpeechToText\ISpeechToTextProvider; @@ -221,14 +221,14 @@ interface IRegistrationContext { public function registerSpeechToTextProvider(string $providerClass): void; /** - * Register a custom LanguageModel provider class that provides a promptable language model - * through the OCP\LanguageModel APIs + * Register a custom text processing provider class that provides a promptable language model + * through the OCP\TextProcessing APIs * * @param string $providerClass - * @psalm-param class-string<ILanguageModelProvider> $providerClass + * @psalm-param class-string<ITextProcessingProvider> $providerClass * @since 27.1.0 */ - public function registerLanguageModelProvider(string $providerClass): void; + public function registerTextProcessingProvider(string $providerClass): void; /** * Register a custom template provider class that is able to inject custom templates diff --git a/lib/public/LanguageModel/Events/TaskSuccessfulEvent.php b/lib/public/LanguageModel/Events/TaskSuccessfulEvent.php deleted file mode 100644 index 77a61ac5c6e..00000000000 --- a/lib/public/LanguageModel/Events/TaskSuccessfulEvent.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace OCP\LanguageModel\Events; - -use OCP\LanguageModel\ILanguageModelTask; - -/** - * @since 27.1.0 - */ -class TaskSuccessfulEvent extends AbstractLanguageModelEvent { - /** - * @param ILanguageModelTask $task - * @since 27.1.0 - */ - public function __construct(ILanguageModelTask $task) { - parent::__construct($task); - } -} diff --git a/lib/public/LanguageModel/HeadlineTask.php b/lib/public/LanguageModel/HeadlineTask.php deleted file mode 100644 index 4c62b9722a9..00000000000 --- a/lib/public/LanguageModel/HeadlineTask.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -namespace OCP\LanguageModel; - -/** - * This LanguageModel Task represents headline generation - * which generates a headline for the passed text - * @since 27.1.0 - * @template-extends AbstractLanguageModelTask<IHeadlineProvider> - */ -final class HeadlineTask extends AbstractLanguageModelTask { - /** - * @since 27.1.0 - */ - public const TYPE = 'headline'; - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function visitProvider(ILanguageModelProvider $provider): string { - if (!$this->canUseProvider($provider)) { - throw new \RuntimeException('HeadlineTask#visitProvider expects IHeadlineProvider'); - } - return $provider->findHeadline($this->getInput()); - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function canUseProvider(ILanguageModelProvider $provider): bool { - return $provider instanceof IHeadlineProvider; - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function getType(): string { - return self::TYPE; - } -} diff --git a/lib/public/LanguageModel/IHeadlineProvider.php b/lib/public/LanguageModel/IHeadlineProvider.php deleted file mode 100644 index 30185f4d4b3..00000000000 --- a/lib/public/LanguageModel/IHeadlineProvider.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2022 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -namespace OCP\LanguageModel; - -use RuntimeException; - -/** - * This LanguageModel Provider represents headline generation - * which generates a headline for the passed text - * @since 27.1.0 - */ -interface IHeadlineProvider extends ILanguageModelProvider { - /** - * @param string $text The text to find headline for - * @returns string the headline - * @since 27.1.0 - * @throws RuntimeException If the text could not be transcribed - */ - public function findHeadline(string $text): string; -} diff --git a/lib/public/LanguageModel/ILanguageModelTask.php b/lib/public/LanguageModel/ILanguageModelTask.php deleted file mode 100644 index 0f552c8de54..00000000000 --- a/lib/public/LanguageModel/ILanguageModelTask.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -namespace OCP\LanguageModel; - -/** - * @since 27.1.0 - * @template T of ILanguageModelProvider - */ -interface ILanguageModelTask extends \JsonSerializable { - /** - * @since 27.1.0 - */ - public const STATUS_FAILED = 4; - /** - * @since 27.1.0 - */ - public const STATUS_SUCCESSFUL = 3; - /** - * @since 27.1.0 - */ - public const STATUS_RUNNING = 2; - /** - * @since 27.1.0 - */ - public const STATUS_SCHEDULED = 1; - /** - * @since 27.1.0 - */ - public const STATUS_UNKNOWN = 0; - - /** - * @since 27.1.0 - */ - public const TYPES = [ - FreePromptTask::TYPE => FreePromptTask::class, - SummaryTask::TYPE => SummaryTask::class, - HeadlineTask::TYPE => HeadlineTask::class, - TopicsTask::TYPE => TopicsTask::class, - ]; - - /** - * @psalm-param T $provider - * @param ILanguageModelProvider $provider - * @return string - * @since 27.1.0 - */ - public function visitProvider(ILanguageModelProvider $provider): string; - - /** - * @psalm-param T $provider - * @param ILanguageModelProvider $provider - * @return bool - * @since 27.1.0 - */ - public function canUseProvider(ILanguageModelProvider $provider): bool; - - - /** - * @return string - * @since 27.1.0 - */ - public function getType(): string; - - /** - * @return ILanguageModelTask::STATUS_* - * @since 27.1.0 - */ - public function getStatus(): int; - - /** - * @param ILanguageModelTask::STATUS_* $status - * @since 27.1.0 - */ - public function setStatus(int $status): void; - - /** - * @param int|null $id - * @since 27.1.0 - */ - public function setId(?int $id): void; - - /** - * @return int|null - * @since 27.1.0 - */ - public function getId(): ?int; - - /** - * @return string - * @since 27.1.0 - */ - public function getInput(): string; - - /** - * @param string|null $output - * @since 27.1.0 - */ - public function setOutput(?string $output): void; - - /** - * @return null|string - * @since 27.1.0 - */ - public function getOutput(): ?string; - - /** - * @return string - * @since 27.1.0 - */ - public function getAppId(): string; - - /** - * @return string - * @since 27.1.0 - */ - public function getIdentifier(): string; - - /** - * @return string|null - * @since 27.1.0 - */ - public function getUserId(): ?string; -} diff --git a/lib/public/LanguageModel/ISummaryProvider.php b/lib/public/LanguageModel/ISummaryProvider.php deleted file mode 100644 index c286e74eb19..00000000000 --- a/lib/public/LanguageModel/ISummaryProvider.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2022 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -namespace OCP\LanguageModel; - -use RuntimeException; - -/** - * This LanguageModel Provider implements summarization - * which sums up the passed text. - * @since 27.1.0 - */ -interface ISummaryProvider extends ILanguageModelProvider { - /** - * @param string $text The text to summarize - * @returns string the summary - * @since 27.1.0 - * @throws RuntimeException If the text could not be transcribed - */ - public function summarize(string $text): string; -} diff --git a/lib/public/LanguageModel/SummaryTask.php b/lib/public/LanguageModel/SummaryTask.php deleted file mode 100644 index 47864532ae3..00000000000 --- a/lib/public/LanguageModel/SummaryTask.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -namespace OCP\LanguageModel; - -/** - * This is an absctract LanguageModel Task represents summarization - * which sums up the passed text. - * @since 27.1.0 - * @template-extends AbstractLanguageModelTask<ISummaryProvider> - */ -final class SummaryTask extends AbstractLanguageModelTask { - /** - * @since 27.1.0 - */ - public const TYPE = 'summarize'; - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function visitProvider(ILanguageModelProvider $provider): string { - if (!$this->canUseProvider($provider)) { - throw new \RuntimeException('SummaryTask#visitProvider expects ISummaryProvider'); - } - return $provider->summarize($this->getInput()); - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function canUseProvider(ILanguageModelProvider $provider): bool { - return $provider instanceof ISummaryProvider; - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function getType(): string { - return self::TYPE; - } -} diff --git a/lib/public/LanguageModel/TopicsTask.php b/lib/public/LanguageModel/TopicsTask.php deleted file mode 100644 index ab2c5916061..00000000000 --- a/lib/public/LanguageModel/TopicsTask.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> - * - * @author Marcel Klehr <mklehr@gmx.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -namespace OCP\LanguageModel; - -/** - * This LanguageModel Task represents topics synthesis - * which outputs comma-separated topics for the passed text - * @since 27.1.0 - * @template-extends AbstractLanguageModelTask<ITopicsProvider> - */ -final class TopicsTask extends AbstractLanguageModelTask { - /** - * @since 27.1.0 - */ - public const TYPE = 'topics'; - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function visitProvider(ILanguageModelProvider $provider): string { - if (!$this->canUseProvider($provider)) { - throw new \RuntimeException('TopicsTask#visitProvider expects ITopicsProvider'); - } - return $provider->findTopics($this->getInput()); - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function canUseProvider(ILanguageModelProvider $provider): bool { - return $provider instanceof ITopicsProvider; - } - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function getType(): string { - return self::TYPE; - } -} diff --git a/lib/public/LanguageModel/Events/AbstractLanguageModelEvent.php b/lib/public/TextProcessing/Events/AbstractTextProcessingEvent.php index c8abc7373eb..10c592fe031 100644 --- a/lib/public/LanguageModel/Events/AbstractLanguageModelEvent.php +++ b/lib/public/TextProcessing/Events/AbstractTextProcessingEvent.php @@ -23,29 +23,30 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ -namespace OCP\LanguageModel\Events; +namespace OCP\TextProcessing\Events; use OCP\EventDispatcher\Event; -use OCP\LanguageModel\ILanguageModelTask; +use OCP\TextProcessing\ILanguageModelTask; +use OCP\TextProcessing\Task; /** * @since 27.1.0 */ -abstract class AbstractLanguageModelEvent extends Event { +abstract class AbstractTextProcessingEvent extends Event { /** * @since 27.1.0 */ public function __construct( - private ILanguageModelTask $task + private Task $task ) { parent::__construct(); } /** - * @return ILanguageModelTask + * @return Task * @since 27.1.0 */ - public function getTask(): ILanguageModelTask { + public function getTask(): Task { return $this->task; } } diff --git a/lib/public/LanguageModel/Events/TaskFailedEvent.php b/lib/public/TextProcessing/Events/TaskFailedEvent.php index f42203a6e48..f9765e362dc 100644 --- a/lib/public/LanguageModel/Events/TaskFailedEvent.php +++ b/lib/public/TextProcessing/Events/TaskFailedEvent.php @@ -1,20 +1,20 @@ <?php -namespace OCP\LanguageModel\Events; +namespace OCP\TextProcessing\Events; -use OCP\LanguageModel\ILanguageModelTask; +use OCP\TextProcessing\Task; /** * @since 27.1.0 */ -class TaskFailedEvent extends AbstractLanguageModelEvent { +class TaskFailedEvent extends AbstractTextProcessingEvent { /** - * @param ILanguageModelTask $task + * @param Task $task * @param string $errorMessage * @since 27.1.0 */ public function __construct( - ILanguageModelTask $task, + Task $task, private string $errorMessage, ) { parent::__construct($task); diff --git a/lib/public/TextProcessing/Events/TaskSuccessfulEvent.php b/lib/public/TextProcessing/Events/TaskSuccessfulEvent.php new file mode 100644 index 00000000000..73fbbb87f45 --- /dev/null +++ b/lib/public/TextProcessing/Events/TaskSuccessfulEvent.php @@ -0,0 +1,18 @@ +<?php + +namespace OCP\TextProcessing\Events; + +use OCP\TextProcessing\Task; + +/** + * @since 27.1.0 + */ +class TaskSuccessfulEvent extends AbstractTextProcessingEvent { + /** + * @param Task $task + * @since 27.1.0 + */ + public function __construct(Task $task) { + parent::__construct($task); + } +} diff --git a/lib/public/LanguageModel/FreePromptTask.php b/lib/public/TextProcessing/FreePromptTaskType.php index 560d6e7d1fb..aa1d6842b54 100644 --- a/lib/public/LanguageModel/FreePromptTask.php +++ b/lib/public/TextProcessing/FreePromptTaskType.php @@ -23,39 +23,38 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -namespace OCP\LanguageModel; +namespace OCP\TextProcessing; + +use OCP\IL10N; /** + * This is the text processing task type for free prompting * @since 27.1.0 - * @template-extends AbstractLanguageModelTask<ILanguageModelProvider> */ -final class FreePromptTask extends AbstractLanguageModelTask { +class FreePromptTaskType implements ITaskType { /** + * Constructor for FreePromptTaskType + * + * @param IL10N $l * @since 27.1.0 */ - public const TYPE = 'free_prompt'; - - /** - * @inheritDoc - * @since 27.1.0 - */ - public function visitProvider(ILanguageModelProvider $provider): string { - return $provider->prompt($this->getInput()); + public function __construct( + private IL10N $l, + ) { } + /** * @inheritDoc - * @since 27.1.0 */ - public function canUseProvider(ILanguageModelProvider $provider): bool { - return true; + public function getName(): string { + return $this->l->t('Free prompt'); } /** * @inheritDoc - * @since 27.1.0 */ - public function getType(): string { - return self::TYPE; + public function getDescription(): string { + return $this->l->t('Runs an arbitrary prompt through the built-in language model.'); } } diff --git a/lib/public/LanguageModel/ITopicsProvider.php b/lib/public/TextProcessing/HeadlineTaskType.php index f061976a3ba..4ced298fd4d 100644 --- a/lib/public/LanguageModel/ITopicsProvider.php +++ b/lib/public/TextProcessing/HeadlineTaskType.php @@ -23,22 +23,38 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +namespace OCP\TextProcessing; -namespace OCP\LanguageModel; - -use RuntimeException; +use OCP\IL10N; /** - * This LanguageModel Provider implements topics synthesis - * which outputs comma-separated topics for the passed text + * This is the text processing task type for creating headline * @since 27.1.0 */ -interface ITopicsProvider extends ILanguageModelProvider { +class HeadlineTaskType implements ITaskType { /** - * @param string $text The text to find topics for - * @returns string the topics, comma separated + * Constructor for HeadlineTaskType + * + * @param IL10N $l * @since 27.1.0 - * @throws RuntimeException If the text could not be transcribed */ - public function findTopics(string $text): string; + public function __construct( + private IL10N $l, + ) { + } + + + /** + * @inheritDoc + */ + public function getName(): string { + return $this->l->t('Generate headline'); + } + + /** + * @inheritDoc + */ + public function getDescription(): string { + return $this->l->t('Generates a possible headline for a text'); + } } diff --git a/lib/public/LanguageModel/ILanguageModelManager.php b/lib/public/TextProcessing/IManager.php index 0afc99b91ab..90e25894d4f 100644 --- a/lib/public/LanguageModel/ILanguageModelManager.php +++ b/lib/public/TextProcessing/IManager.php @@ -24,7 +24,7 @@ declare(strict_types=1); */ -namespace OCP\LanguageModel; +namespace OCP\TextProcessing; use OCP\Common\Exception\NotFoundException; use OCP\PreConditionNotMetException; @@ -35,47 +35,43 @@ use RuntimeException; * without known which providers are installed * @since 27.1.0 */ -interface ILanguageModelManager { +interface IManager { /** * @since 27.1.0 */ public function hasProviders(): bool; /** - * @return string[] - * @since 27.1.0 - */ - public function getAvailableTaskClasses(): array; - - /** - * @return string[] + * @return class-string<ITaskType>[] * @since 27.1.0 */ public function getAvailableTaskTypes(): array; /** + * @param Task $task The task to run * @throws PreConditionNotMetException If no or not the requested provider was registered but this method was still called * @throws RuntimeException If something else failed * @since 27.1.0 */ - public function runTask(ILanguageModelTask $task): string; + public function runTask(Task $task): string; /** * Will schedule an LLM inference process in the background. The result will become available * with the \OCP\LanguageModel\Events\TaskSuccessfulEvent * If inference fails a \OCP\LanguageModel\Events\TaskFailedEvent will be dispatched instead * + * @param Task $task The task to schedule * @throws PreConditionNotMetException If no or not the requested provider was registered but this method was still called * @since 27.1.0 */ - public function scheduleTask(ILanguageModelTask $task) : void; + public function scheduleTask(Task $task) : void; /** * @param int $id The id of the task - * @return ILanguageModelTask + * @return Task * @throws RuntimeException If the query failed * @throws NotFoundException If the task could not be found * @since 27.1.0 */ - public function getTask(int $id): ILanguageModelTask; + public function getTask(int $id): Task; } diff --git a/lib/public/TextProcessing/IProvider.php b/lib/public/TextProcessing/IProvider.php new file mode 100644 index 00000000000..3eb83aef8c3 --- /dev/null +++ b/lib/public/TextProcessing/IProvider.php @@ -0,0 +1,61 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> + * + * @author Marcel Klehr <mklehr@gmx.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +namespace OCP\TextProcessing; + +use RuntimeException; + +/** + * This is the interface that is implemented by apps that + * implement a text processing provider + * @template T of ITaskType + * @since 27.1.0 + */ +interface IProvider { + /** + * The localized name of this provider + * @since 27.1.0 + */ + public function getName(): string; + + /** + * Processes a text + * + * @param string $prompt The input text + * @return string the output text + * @since 27.1.0 + * @throws RuntimeException If the text could not be processed + */ + public function process(string $prompt): string; + + /** + * Returns the task type class string of the task type, that this + * provider handles + * + * @return class-string<T> + */ + public function getTaskType(): string; +} diff --git a/lib/public/LanguageModel/ILanguageModelProvider.php b/lib/public/TextProcessing/ITaskType.php index 34e7eb6c4e5..d08da3f7ac7 100644 --- a/lib/public/LanguageModel/ILanguageModelProvider.php +++ b/lib/public/TextProcessing/ITaskType.php @@ -23,27 +23,27 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -namespace OCP\LanguageModel; - -use RuntimeException; +namespace OCP\TextProcessing; /** - * This is the minimum interface that is implemented by apps that - * implement a LanguageModel provider + * This is a task type interface that is implemented by text processing + * task types * @since 27.1.0 */ -interface ILanguageModelProvider { +interface ITaskType { /** + * Returns the localized name of this task type + * * @since 27.1.0 + * @return string */ public function getName(): string; /** - * @param string $prompt The prompt to call the model with - * @return string the output + * Returns the localized description of this task type + * * @since 27.1.0 - * @throws RuntimeException If the text could not be transcribed + * @return string */ - public function prompt(string $prompt): string; + public function getDescription(): string; } diff --git a/lib/public/TextProcessing/SummaryTaskType.php b/lib/public/TextProcessing/SummaryTaskType.php new file mode 100644 index 00000000000..7db695c18f7 --- /dev/null +++ b/lib/public/TextProcessing/SummaryTaskType.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> + * + * @author Marcel Klehr <mklehr@gmx.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCP\TextProcessing; + +use OCP\IL10N; + +/** + * This is the text processing task type for summaries + * @since 27.1.0 + */ +class SummaryTaskType implements ITaskType { + /** + * Constructor for SummaryTaskType + * + * @param IL10N $l + * @since 27.1.0 + */ + public function __construct( + private IL10N $l, + ) { + } + + + /** + * @inheritDoc + */ + public function getName(): string { + return $this->l->t('Summarize'); + } + + /** + * @inheritDoc + */ + public function getDescription(): string { + return $this->l->t('Summarizes text by reducing its length without losing key information.'); + } +} diff --git a/lib/public/LanguageModel/AbstractLanguageModelTask.php b/lib/public/TextProcessing/Task.php index 91b81b9615b..59cd38b720c 100644 --- a/lib/public/LanguageModel/AbstractLanguageModelTask.php +++ b/lib/public/TextProcessing/Task.php @@ -23,25 +23,55 @@ declare(strict_types=1); * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -namespace OCP\LanguageModel; +namespace OCP\TextProcessing; /** - * This is an abstract LanguageModel task that implements basic - * goodies for downstream tasks - * @since 28.0. - * @template T of ILanguageModelProvider - * @template-implements ILanguageModelTask<T> + * This is a text processing task + * @since 27.1.0 + * @template T of ITaskType */ -abstract class AbstractLanguageModelTask implements ILanguageModelTask { +final class Task implements \JsonSerializable { protected ?int $id = null; protected ?string $output = null; /** - * @psalm-var ILanguageModelTask::STATUS_* + * @since 27.1.0 + */ + public const TYPES = [ + FreePromptTaskType::class, + SummaryTaskType::class, + HeadlineTaskType::class, + TopicsTaskType::class, + ]; + + /** + * @since 27.1.0 + */ + public const STATUS_FAILED = 4; + /** + * @since 27.1.0 + */ + public const STATUS_SUCCESSFUL = 3; + /** + * @since 27.1.0 + */ + public const STATUS_RUNNING = 2; + /** + * @since 27.1.0 + */ + public const STATUS_SCHEDULED = 1; + /** + * @since 27.1.0 + */ + public const STATUS_UNKNOWN = 0; + + /** + * @psalm-var self::STATUS_* */ - protected int $status = ILanguageModelTask::STATUS_UNKNOWN; + protected int $status = self::STATUS_UNKNOWN; /** + * @param class-string<T> $type * @param string $input * @param string $appId * @param string|null $userId @@ -49,6 +79,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { * @since 27.1.0 */ final public function __construct( + protected string $type, protected string $input, protected string $appId, protected ?string $userId, @@ -57,10 +88,36 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { } /** + * @psalm-param IProvider<T> $provider + * @param IProvider $provider * @return string * @since 27.1.0 */ - abstract public function getType(): string; + public function visitProvider(IProvider $provider): string { + if ($this->canUseProvider($provider)) { + return $provider->process($this->getInput()); + } else { + throw new \RuntimeException('Task of type ' . $this->getType() . ' cannot visit provider with task type ' . $provider->getTaskType()); + } + } + + /** + * @psalm-param IProvider<T> $provider + * @param IProvider $provider + * @return bool + * @since 27.1.0 + */ + public function canUseProvider(IProvider $provider): bool { + return $provider->getTaskType() === $this->getType(); + } + + /** + * @return class-string<T> + * @since 27.1.0 + */ + final public function getType(): string { + return $this->type; + } /** * @return string|null @@ -79,7 +136,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { } /** - * @psalm-return ILanguageModelTask::STATUS_* + * @psalm-return self::STATUS_* * @since 27.1.0 */ final public function getStatus(): int { @@ -87,7 +144,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { } /** - * @psalm-param ILanguageModelTask::STATUS_* $status + * @psalm-param self::STATUS_* $status * @since 27.1.0 */ final public function setStatus(int $status): void { @@ -143,10 +200,10 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { } /** - * @return array + * @return array{id: ?string, type: class-string<T>, status: int, userId: ?string, appId: string, input: string, output: ?string, identifier: string} * @since 27.1.0 */ - public function jsonSerialize() { + public function jsonSerialize(): array { return [ 'id' => $this->getId(), 'type' => $this->getType(), @@ -165,14 +222,14 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask { * @param string|null $userId * @param string $appId * @param string $identifier - * @return ILanguageModelTask + * @return Task * @throws \InvalidArgumentException * @since 27.1.0 */ - final public static function factory(string $type, string $input, ?string $userId, string $appId, string $identifier = ''): ILanguageModelTask { - if (!in_array($type, array_keys(self::TYPES))) { + final public static function factory(string $type, string $input, ?string $userId, string $appId, string $identifier = ''): Task { + if (!in_array($type, self::TYPES)) { throw new \InvalidArgumentException('Unknown task type'); } - return new (ILanguageModelTask::TYPES[$type])($input, $appId, $userId, $identifier); + return new Task($type, $input, $appId, $userId, $identifier); } } diff --git a/lib/public/TextProcessing/TopicsTaskType.php b/lib/public/TextProcessing/TopicsTaskType.php new file mode 100644 index 00000000000..8b41b3ee61a --- /dev/null +++ b/lib/public/TextProcessing/TopicsTaskType.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> + * + * @author Marcel Klehr <mklehr@gmx.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCP\TextProcessing; + +use OCP\IL10N; + +/** + * This is the text processing task type for topics extraction + * @since 27.1.0 + */ +class TopicsTaskType implements ITaskType { + /** + * Constructor for TopicsTaskType + * + * @param IL10N $l + * @since 27.1.0 + */ + public function __construct( + private IL10N $l, + ) { + } + + + /** + * @inheritDoc + */ + public function getName(): string { + return $this->l->t('Extract topics'); + } + + /** + * @inheritDoc + */ + public function getDescription(): string { + return $this->l->t('Extracts topics from a text and outputs them separated by commas.'); + } +} diff --git a/tests/lib/LanguageModel/LanguageModelManagerTest.php b/tests/lib/TextProcessing/TextProcessingTest.php index 6f8d6cd868d..797571019ce 100644 --- a/tests/lib/LanguageModel/LanguageModelManagerTest.php +++ b/tests/lib/TextProcessing/TextProcessingTest.php @@ -6,93 +6,97 @@ * See the COPYING-README file. */ -namespace Test\LanguageModel; +namespace Test\TextProcessing; use OC\AppFramework\Bootstrap\Coordinator; use OC\AppFramework\Bootstrap\RegistrationContext; use OC\AppFramework\Bootstrap\ServiceRegistration; use OC\EventDispatcher\EventDispatcher; -use OC\LanguageModel\Db\Task; -use OC\LanguageModel\Db\TaskMapper; -use OC\LanguageModel\LanguageModelManager; -use OC\LanguageModel\RemoveOldTasksBackgroundJob; -use OC\LanguageModel\TaskBackgroundJob; +use OC\TextProcessing\Db\Task as DbTask; +use OC\TextProcessing\Db\TaskMapper; +use OC\TextProcessing\Manager; +use OC\TextProcessing\RemoveOldTasksBackgroundJob; +use OC\TextProcessing\TaskBackgroundJob; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Common\Exception\NotFoundException; use OCP\EventDispatcher\IEventDispatcher; use OCP\IServerContainer; -use OCP\LanguageModel\Events\TaskFailedEvent; -use OCP\LanguageModel\Events\TaskSuccessfulEvent; -use OCP\LanguageModel\FreePromptTask; -use OCP\LanguageModel\HeadlineTask; -use OCP\LanguageModel\IHeadlineProvider; -use OCP\LanguageModel\ILanguageModelManager; -use OCP\LanguageModel\ILanguageModelProvider; -use OCP\LanguageModel\ILanguageModelTask; -use OCP\LanguageModel\ISummaryProvider; -use OCP\LanguageModel\SummaryTask; -use OCP\LanguageModel\TopicsTask; +use OCP\TextProcessing\Events\TaskFailedEvent; +use OCP\TextProcessing\Events\TaskSuccessfulEvent; +use OCP\TextProcessing\FreePromptTaskType; +use OCP\TextProcessing\IManager; +use OCP\TextProcessing\IProvider; +use OCP\TextProcessing\SummaryTaskType; use OCP\PreConditionNotMetException; +use OCP\TextProcessing\Task; +use OCP\TextProcessing\TopicsTaskType; use PHPUnit\Framework\Constraint\IsInstanceOf; use Psr\Log\LoggerInterface; use Test\BackgroundJob\DummyJobList; -class TestVanillaLanguageModelProvider implements ILanguageModelProvider { +class SuccessfulSummaryProvider implements IProvider { public bool $ran = false; public function getName(): string { return 'TEST Vanilla LLM Provider'; } - public function prompt(string $prompt): string { + public function process(string $prompt): string { $this->ran = true; - return $prompt . ' Free Prompt'; + return $prompt . ' Summarize'; + } + + public function getTaskType(): string { + return SummaryTaskType::class; } } -class TestFailingLanguageModelProvider implements ILanguageModelProvider { +class FailingSummaryProvider implements IProvider { public bool $ran = false; public function getName(): string { return 'TEST Vanilla LLM Provider'; } - public function prompt(string $prompt): string { + public function process(string $prompt): string { $this->ran = true; throw new \Exception('ERROR'); } + + public function getTaskType(): string { + return SummaryTaskType::class; + } } -class TestAdvancedLanguageModelProvider implements ILanguageModelProvider, ISummaryProvider, IHeadlineProvider { +class FreePromptProvider implements IProvider { + public bool $ran = false; + public function getName(): string { - return 'TEST Full LLM Provider'; + return 'TEST Free Prompt Provider'; } - public function prompt(string $prompt): string { + public function process(string $prompt): string { + $this->ran = true; return $prompt . ' Free Prompt'; } - public function findHeadline(string $text): string { - return $text . ' Headline'; - } - - public function summarize(string $text): string { - return $text. ' Summarize'; + public function getTaskType(): string { + return FreePromptTaskType::class; } } -class LanguageModelManagerTest extends \Test\TestCase { - private ILanguageModelManager $languageModelManager; +class TextProcessingTest extends \Test\TestCase { + private IManager $manager; private Coordinator $coordinator; protected function setUp(): void { parent::setUp(); $this->providers = [ - TestVanillaLanguageModelProvider::class => new TestVanillaLanguageModelProvider(), - TestAdvancedLanguageModelProvider::class => new TestAdvancedLanguageModelProvider(), - TestFailingLanguageModelProvider::class => new TestFailingLanguageModelProvider(), + SuccessfulSummaryProvider::class => new SuccessfulSummaryProvider(), + FailingSummaryProvider::class => new FailingSummaryProvider(), + FreePromptProvider::class => new FreePromptProvider(), ]; $this->serverContainer = $this->createMock(IServerContainer::class); @@ -117,7 +121,7 @@ class LanguageModelManagerTest extends \Test\TestCase { $this->taskMapper ->expects($this->any()) ->method('insert') - ->willReturnCallback(function (Task $task) { + ->willReturnCallback(function (DbTask $task) { $task->setId(count($this->tasksDb) ? max(array_keys($this->tasksDb)) : 1); $task->setLastUpdated($this->currentTime->getTimestamp()); $this->tasksDb[$task->getId()] = $task->toRow(); @@ -126,7 +130,7 @@ class LanguageModelManagerTest extends \Test\TestCase { $this->taskMapper ->expects($this->any()) ->method('update') - ->willReturnCallback(function (Task $task) { + ->willReturnCallback(function (DbTask $task) { $task->setLastUpdated($this->currentTime->getTimestamp()); $this->tasksDb[$task->getId()] = $task->toRow(); return $task; @@ -138,7 +142,7 @@ class LanguageModelManagerTest extends \Test\TestCase { if (!isset($this->tasksDb[$id])) { throw new DoesNotExistException('Could not find it'); } - return Task::fromRow($this->tasksDb[$id]); + return DbTask::fromRow($this->tasksDb[$id]); }); $this->taskMapper ->expects($this->any()) @@ -153,7 +157,7 @@ class LanguageModelManagerTest extends \Test\TestCase { $this->jobList->expects($this->any())->method('add')->willReturnCallback(function () { }); - $this->languageModelManager = new LanguageModelManager( + $this->manager = new Manager( $this->serverContainer, $this->coordinator, \OC::$server->get(LoggerInterface::class), @@ -163,57 +167,54 @@ class LanguageModelManagerTest extends \Test\TestCase { } public function testShouldNotHaveAnyProviders() { - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([]); - $this->assertCount(0, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(0, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertFalse($this->languageModelManager->hasProviders()); + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([]); + $this->assertCount(0, $this->manager->getAvailableTaskTypes()); + $this->assertFalse($this->manager->hasProviders()); $this->expectException(PreConditionNotMetException::class); - $this->languageModelManager->runTask(new FreePromptTask('Hello', 'test', null)); + $this->manager->runTask(new \OCP\TextProcessing\Task(FreePromptTaskType::class, 'Hello', 'test', null)); } public function testProviderShouldBeRegisteredAndRun() { - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([ - new ServiceRegistration('test', TestVanillaLanguageModelProvider::class) + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([ + new ServiceRegistration('test', SuccessfulSummaryProvider::class) ]); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertTrue($this->languageModelManager->hasProviders()); - $this->assertEquals('Hello Free Prompt', $this->languageModelManager->runTask(new FreePromptTask('Hello', 'test', null))); + $this->assertCount(1, $this->manager->getAvailableTaskTypes()); + $this->assertTrue($this->manager->hasProviders()); + $this->assertEquals('Hello Summarize', $this->manager->runTask(new Task(SummaryTaskType::class, 'Hello', 'test', null))); // Summaries are not implemented by the vanilla provider, only free prompt $this->expectException(PreConditionNotMetException::class); - $this->languageModelManager->runTask(new SummaryTask('Hello', 'test', null)); + $this->manager->runTask(new Task(FreePromptTaskType::class, 'Hello', 'test', null)); } public function testProviderShouldBeRegisteredAndScheduled() { // register provider - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([ - new ServiceRegistration('test', TestVanillaLanguageModelProvider::class) + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([ + new ServiceRegistration('test', SuccessfulSummaryProvider::class) ]); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertTrue($this->languageModelManager->hasProviders()); + $this->assertCount(1, $this->manager->getAvailableTaskTypes()); + $this->assertTrue($this->manager->hasProviders()); // create task object - $task = new FreePromptTask('Hello', 'test', null); + $task = new Task(SummaryTaskType::class, 'Hello', 'test', null); $this->assertNull($task->getId()); $this->assertNull($task->getOutput()); // schedule works - $this->assertEquals(ILanguageModelTask::STATUS_UNKNOWN, $task->getStatus()); - $this->languageModelManager->scheduleTask($task); + $this->assertEquals(Task::STATUS_UNKNOWN, $task->getStatus()); + $this->manager->scheduleTask($task); // Task object is up-to-date $this->assertNotNull($task->getId()); $this->assertNull($task->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_SCHEDULED, $task->getStatus()); + $this->assertEquals(Task::STATUS_SCHEDULED, $task->getStatus()); // Task object retrieved from db is up-to-date - $task2 = $this->languageModelManager->getTask($task->getId()); + $task2 = $this->manager->getTask($task->getId()); $this->assertEquals($task->getId(), $task2->getId()); $this->assertEquals('Hello', $task2->getInput()); $this->assertNull($task2->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_SCHEDULED, $task2->getStatus()); + $this->assertEquals(Task::STATUS_SCHEDULED, $task2->getStatus()); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new IsInstanceOf(TaskSuccessfulEvent::class)); @@ -221,79 +222,74 @@ class LanguageModelManagerTest extends \Test\TestCase { // run background job $bgJob = new TaskBackgroundJob( \OC::$server->get(ITimeFactory::class), - $this->languageModelManager, + $this->manager, $this->eventDispatcher, ); $bgJob->setArgument(['taskId' => $task->getId()]); $bgJob->start($this->jobList); - $provider = $this->providers[TestVanillaLanguageModelProvider::class]; + $provider = $this->providers[SuccessfulSummaryProvider::class]; $this->assertTrue($provider->ran); // Task object retrieved from db is up-to-date - $task3 = $this->languageModelManager->getTask($task->getId()); + $task3 = $this->manager->getTask($task->getId()); $this->assertEquals($task->getId(), $task3->getId()); $this->assertEquals('Hello', $task3->getInput()); - $this->assertEquals('Hello Free Prompt', $task3->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_SUCCESSFUL, $task3->getStatus()); + $this->assertEquals('Hello Summarize', $task3->getOutput()); + $this->assertEquals(Task::STATUS_SUCCESSFUL, $task3->getStatus()); } public function testMultipleProvidersShouldBeRegisteredAndRunCorrectly() { - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([ - new ServiceRegistration('test', TestVanillaLanguageModelProvider::class), - new ServiceRegistration('test', TestAdvancedLanguageModelProvider::class), + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([ + new ServiceRegistration('test', SuccessfulSummaryProvider::class), + new ServiceRegistration('test', FreePromptProvider::class), ]); - $this->assertCount(3, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(3, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertTrue($this->languageModelManager->hasProviders()); + $this->assertCount(2, $this->manager->getAvailableTaskTypes()); + $this->assertTrue($this->manager->hasProviders()); // Try free prompt again - $this->assertEquals('Hello Free Prompt', $this->languageModelManager->runTask(new FreePromptTask('Hello', 'test', null))); - - // Try headline task - $this->assertEquals('Hello Headline', $this->languageModelManager->runTask(new HeadlineTask('Hello', 'test', null))); + $this->assertEquals('Hello Free Prompt', $this->manager->runTask(new Task(FreePromptTaskType::class, 'Hello', 'test', null))); // Try summary task - $this->assertEquals('Hello Summarize', $this->languageModelManager->runTask(new SummaryTask('Hello', 'test', null))); + $this->assertEquals('Hello Summarize', $this->manager->runTask(new Task(SummaryTaskType::class, 'Hello', 'test', null))); // Topics are not implemented by both the vanilla provider and the full provider $this->expectException(PreConditionNotMetException::class); - $this->languageModelManager->runTask(new TopicsTask('Hello', 'test', null)); + $this->manager->runTask(new Task(TopicsTaskType::class, 'Hello', 'test', null)); } public function testNonexistentTask() { $this->expectException(NotFoundException::class); - $this->languageModelManager->getTask(98765432456); + $this->manager->getTask(98765432456); } public function testTaskFailure() { // register provider - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([ - new ServiceRegistration('test', TestFailingLanguageModelProvider::class), + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([ + new ServiceRegistration('test', FailingSummaryProvider::class), ]); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertTrue($this->languageModelManager->hasProviders()); + $this->assertCount(1, $this->manager->getAvailableTaskTypes()); + $this->assertTrue($this->manager->hasProviders()); // create task object - $task = new FreePromptTask('Hello', 'test', null); + $task = new Task(SummaryTaskType::class, 'Hello', 'test', null); $this->assertNull($task->getId()); $this->assertNull($task->getOutput()); // schedule works - $this->assertEquals(ILanguageModelTask::STATUS_UNKNOWN, $task->getStatus()); - $this->languageModelManager->scheduleTask($task); + $this->assertEquals(Task::STATUS_UNKNOWN, $task->getStatus()); + $this->manager->scheduleTask($task); // Task object is up-to-date $this->assertNotNull($task->getId()); $this->assertNull($task->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_SCHEDULED, $task->getStatus()); + $this->assertEquals(Task::STATUS_SCHEDULED, $task->getStatus()); // Task object retrieved from db is up-to-date - $task2 = $this->languageModelManager->getTask($task->getId()); + $task2 = $this->manager->getTask($task->getId()); $this->assertEquals($task->getId(), $task2->getId()); $this->assertEquals('Hello', $task2->getInput()); $this->assertNull($task2->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_SCHEDULED, $task2->getStatus()); + $this->assertEquals(Task::STATUS_SCHEDULED, $task2->getStatus()); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new IsInstanceOf(TaskFailedEvent::class)); @@ -301,31 +297,30 @@ class LanguageModelManagerTest extends \Test\TestCase { // run background job $bgJob = new TaskBackgroundJob( \OC::$server->get(ITimeFactory::class), - $this->languageModelManager, + $this->manager, $this->eventDispatcher, ); $bgJob->setArgument(['taskId' => $task->getId()]); $bgJob->start($this->jobList); - $provider = $this->providers[TestFailingLanguageModelProvider::class]; + $provider = $this->providers[FailingSummaryProvider::class]; $this->assertTrue($provider->ran); // Task object retrieved from db is up-to-date - $task3 = $this->languageModelManager->getTask($task->getId()); + $task3 = $this->manager->getTask($task->getId()); $this->assertEquals($task->getId(), $task3->getId()); $this->assertEquals('Hello', $task3->getInput()); $this->assertNull($task3->getOutput()); - $this->assertEquals(ILanguageModelTask::STATUS_FAILED, $task3->getStatus()); + $this->assertEquals(Task::STATUS_FAILED, $task3->getStatus()); } public function testOldTasksShouldBeCleanedUp() { - $this->registrationContext->expects($this->any())->method('getLanguageModelProviders')->willReturn([ - new ServiceRegistration('test', TestVanillaLanguageModelProvider::class) + $this->registrationContext->expects($this->any())->method('getTextProcessingProviders')->willReturn([ + new ServiceRegistration('test', SuccessfulSummaryProvider::class) ]); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskClasses()); - $this->assertCount(1, $this->languageModelManager->getAvailableTaskTypes()); - $this->assertTrue($this->languageModelManager->hasProviders()); - $task = new FreePromptTask('Hello', 'test', null); - $this->assertEquals('Hello Free Prompt', $this->languageModelManager->runTask($task)); + $this->assertCount(1, $this->manager->getAvailableTaskTypes()); + $this->assertTrue($this->manager->hasProviders()); + $task = new Task(SummaryTaskType::class, 'Hello', 'test', null); + $this->assertEquals('Hello Summarize', $this->manager->runTask($task)); $this->currentTime = $this->currentTime->add(new \DateInterval('P1Y')); // run background job @@ -338,6 +333,6 @@ class LanguageModelManagerTest extends \Test\TestCase { $bgJob->start($this->jobList); $this->expectException(NotFoundException::class); - $this->languageModelManager->getTask($task->getId()); + $this->manager->getTask($task->getId()); } } |