Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STT & Text processing APIs #60

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,14 @@
// Talk bots
['name' => 'talkBot#registerExAppTalkBot', 'url' => '/api/v1/talk_bot', 'verb' => 'POST'],
['name' => 'talkBot#unregisterExAppTalkBot', 'url' => '/api/v1/talk_bot', 'verb' => 'DELETE'],

// Speech-To-Text
['name' => 'speechToText#registerProvider', 'url' => '/api/v1/speech_to_text', 'verb' => 'POST'],
['name' => 'speechToText#unregisterProvider', 'url' => '/api/v1/speech_to_text', 'verb' => 'DELETE'],

// Text-Processing
['name' => 'textProcessing#registerProvider', 'url' => '/api/v1/text_processing', 'verb' => 'POST'],
['name' => 'textProcessing#unregisterProvider', 'url' => '/api/v1/text_processing', 'verb' => 'DELETE'],
['name' => 'textProcessing#registerProvider', 'url' => '/api/v1/text_processing/task_type', 'verb' => 'POST'],
],
];
47 changes: 47 additions & 0 deletions docs/tech_details/api/speechtotext.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
==============
Speech-To-Text
==============

AppAPI provides a Speech-To-Text (STT) service
that can be used to register ExApp as a custom STT model and transcribe audio files via it.

Registering ExApp STT provider (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``POST /apps/app_api/api/v1/speech_to_text``

Request data
************

.. code-block:: json

{
"name": "unique_provider_name",
"display_name": "Provider Display Name",
"action_handler_route": "/handler_route_on_ex_app",
}

Response
********

On successful registration response with status code 200 is returned.

Unregistering ExApp STT provider (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``DELETE /apps/app_api/api/v1/speech_to_text``

Request data
************

.. code-block:: json

{
"name": "unique_provider_name",
}

Response
********

On successful unregister response with status code 200 is returned.

90 changes: 90 additions & 0 deletions docs/tech_details/api/textprocessing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
===============
Text-Processing
===============

AppAPI provides a text-processing service
that can be used to register ExApps providers and to process passed through text.

Registering text-processing provider (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``POST /apps/app_api/api/v1/text_processing``

Request data
************

.. code-block:: json

{
"name": "unique_provider_name",
"display_name": "Provider Display Name",
"description": "Provider Description",
"action_handler_route": "/handler_route_on_ex_app",
"action_type": "unique_task_type_name",
}

Response
********

On successful registration response with status code 200 is returned.

Unregistering text-processing provider (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``DELETE /apps/app_api/api/v1/text_processing``

Request data
************

.. code-block:: json

{
"name": "unique_provider_name",
}

Response
********

On successful unregister response with status code 200 is returned.


Registering Text-Processing task type (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``POST /apps/app_api/api/v1/text_processing/task_type``

Request data
************

.. code-block:: json

{
"name": "unique_task_type_name",
"display_name": "Task Type Display Name",
"description": "Task Type Description",
}

Response
********

On successful registration response with status code 200 is returned.

Unregistering Text-Processing task type (OCS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OCS endpoint: ``DELETE /apps/app_api/api/v1/text_processing/task_type``

Request data
************

.. code-block:: json

{
"name": "unique_task_type_name",
}

Response
********

On successful unregister response with status code 200 is returned.

26 changes: 22 additions & 4 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use OCA\AppAPI\Profiler\AppAPIDataCollector;
use OCA\AppAPI\PublicCapabilities;

use OCA\AppAPI\Service\SpeechToTextService;
use OCA\AppAPI\Service\TextProcessingService;
use OCA\DAV\Events\SabrePluginAuthInitEvent;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCP\AppFramework\App;
Expand Down Expand Up @@ -56,6 +58,19 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerNotifierService(ExAppNotifier::class);
$context->registerNotifierService(ExAppAdminNotifier::class);

// Dynamic anonymous providers registration
$container = $this->getContainer();
try {
/** @var TextProcessingService $textProcessingService */
$textProcessingService = $container->get(TextProcessingService::class);
$textProcessingService->registerExAppTextProcessingProviders($context);

/** @var SpeechToTextService $speechToTextService */
$speechToTextService = $container->get(SpeechToTextService::class);
$speechToTextService->registerExAppSpeechToTextProviders($context);
} catch (NotFoundExceptionInterface|ContainerExceptionInterface) {
}
}

public function boot(IBootContext $context): void {
Expand All @@ -73,10 +88,13 @@ public function boot(IBootContext $context): void {
public function registerDavAuth(): void {
$container = $this->getContainer();

$dispatcher = $container->query(IEventDispatcher::class);
$dispatcher->addListener('OCA\DAV\Connector\Sabre::addPlugin', function (SabrePluginEvent $event) use ($container) {
$event->getServer()->addPlugin($container->query(DavPlugin::class));
});
try {
$dispatcher = $container->get(IEventDispatcher::class);
$dispatcher->addListener('OCA\DAV\Connector\Sabre::addPlugin', function (SabrePluginEvent $event) use ($container) {
$event->getServer()->addPlugin($container->get(DavPlugin::class));
});
} catch (NotFoundExceptionInterface|ContainerExceptionInterface) {
}
}

/**
Expand Down
86 changes: 86 additions & 0 deletions lib/Controller/SpeechToTextController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

declare(strict_types=1);

namespace OCA\AppAPI\Controller;

use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Attribute\AppAPIAuth;
use OCA\AppAPI\Service\AppAPIService;
use OCA\AppAPI\Service\SpeechToTextService;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCSController;
use OCP\IRequest;

class SpeechToTextController extends OCSController {
protected $request;
private AppAPIService $service;
private SpeechToTextService $speechToTextService;

public function __construct(
IRequest $request,
AppAPIService $service,
SpeechToTextService $speechToTextService,
) {
parent::__construct(Application::APP_ID, $request);

$this->request = $request;
$this->service = $service;
$this->speechToTextService = $speechToTextService;
}

/**
* @NoAdminRequired
* @PublicPage
*
* @param string $name
* @param string $displayName
* @param string $actionHandlerRoute
*
* @throws OCSBadRequestException
* @return Response
*/
#[NoCSRFRequired]
#[PublicPage]
#[AppAPIAuth]
public function registerProvider(string $name, string $displayName, string $actionHandlerRoute): Response {
$appId = $this->request->getHeader('EX-APP-ID');
$exApp = $this->service->getExApp($appId);

$provider = $this->speechToTextService->registerSpeechToTextProvider($exApp, $name, $displayName, $actionHandlerRoute);

if ($provider === null) {
throw new OCSBadRequestException('Failed to register STT provider');
}

return new DataResponse();
}

/**
* @NoAdminRequired
* @PublicPage
*
* @param string $name
*
* @throws OCSBadRequestException
* @return Response
*/
#[NoCSRFRequired]
#[PublicPage]
#[AppAPIAuth]
public function unregisterProvider(string $name): Response {
$appId = $this->request->getHeader('EX-APP-ID');
$exApp = $this->service->getExApp($appId);
$unregistered = $this->speechToTextService->unregisterSpeechToTextProvider($exApp, $name);

if ($unregistered === null) {
throw new OCSBadRequestException('Failed to unregister STT provider');
}

return new DataResponse();
}
}
88 changes: 88 additions & 0 deletions lib/Controller/TextProcessingController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace OCA\AppAPI\Controller;

use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Attribute\AppEcosystemAuth;
use OCA\AppAPI\Service\AppAPIService;
use OCA\AppAPI\Service\TextProcessingService;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCSController;
use OCP\IRequest;

class TextProcessingController extends OCSController {
protected $request;
private AppEcosystemV2Service $service;

Check failure on line 21 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedClass

lib/Controller/TextProcessingController.php:21:10: UndefinedClass: Class, interface or enum named OCA\AppAPI\Controller\AppEcosystemV2Service does not exist (see https://psalm.dev/019)
private TextProcessingService $textProcessingService;

public function __construct(
IRequest $request,
AppEcosystemV2Service $service,

Check failure on line 26 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedClass

lib/Controller/TextProcessingController.php:26:3: UndefinedClass: Class, interface or enum named OCA\AppAPI\Controller\AppEcosystemV2Service does not exist (see https://psalm.dev/019)
TextProcessingService $textProcessingService,
) {
parent::__construct(Application::APP_ID, $request);

$this->request = $request;
$this->service = $service;
$this->textProcessingService = $textProcessingService;
}

/**
* @NoAdminRequired
* @PublicPage
*
* @param string $name
* @param string $displayName
* @param string $description
* @param string $actionHandlerRoute
* @param string $actionType
*
* @throws OCSBadRequestException
* @return Response
*/
#[NoCSRFRequired]
#[PublicPage]
#[AppEcosystemAuth]

Check failure on line 51 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedAttributeClass

lib/Controller/TextProcessingController.php:51:4: UndefinedAttributeClass: Attribute class OCA\AppAPI\Attribute\AppEcosystemAuth does not exist (see https://psalm.dev/241)
public function registerProvider(string $name, string $displayName, string $description, string $actionHandlerRoute, string $actionType): Response {
$appId = $this->request->getHeader('EX-APP-ID');
$exApp = $this->service->getExApp($appId);

Check failure on line 54 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedClass

lib/Controller/TextProcessingController.php:54:12: UndefinedClass: Class, interface or enum named OCA\AppAPI\Controller\AppEcosystemV2Service does not exist (see https://psalm.dev/019)

$provider = $this->textProcessingService->registerTextProcesingProvider($exApp, $name, $displayName, $description, $actionHandlerRoute);

Check failure on line 56 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedMethod

lib/Controller/TextProcessingController.php:56:45: UndefinedMethod: Method OCA\AppAPI\Service\TextProcessingService::registerTextProcesingProvider does not exist (see https://psalm.dev/022)

if ($provider === null) {
throw new OCSBadRequestException('Failed to register text processing provider');
}

return new DataResponse();
}

/**
* @NoAdminRequired
* @PublicPage
*
* @param string $name
*
* @throws OCSBadRequestException
* @return Response
*/
#[NoCSRFRequired]
#[PublicPage]
#[AppEcosystemAuth]

Check failure on line 76 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedAttributeClass

lib/Controller/TextProcessingController.php:76:4: UndefinedAttributeClass: Attribute class OCA\AppAPI\Attribute\AppEcosystemAuth does not exist (see https://psalm.dev/241)
public function unregisterProvider(string $name): Response {
$appId = $this->request->getHeader('EX-APP-ID');
$exApp = $this->service->getExApp($appId);

Check failure on line 79 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedClass

lib/Controller/TextProcessingController.php:79:12: UndefinedClass: Class, interface or enum named OCA\AppAPI\Controller\AppEcosystemV2Service does not exist (see https://psalm.dev/019)
$unregistered = $this->textProcessingService->unregisterTextProcessingProvider($exApp, $name);

Check failure on line 80 in lib/Controller/TextProcessingController.php

View workflow job for this annotation

GitHub Actions / php-psalm-analysis (8.1)

UndefinedMethod

lib/Controller/TextProcessingController.php:80:49: UndefinedMethod: Method OCA\AppAPI\Service\TextProcessingService::unregisterTextProcessingProvider does not exist (see https://psalm.dev/022)

if ($unregistered === null) {
throw new OCSBadRequestException('Failed to unregister text processing provider');
}

return new DataResponse();
}
}
Loading
Loading