Skip to content

Commit 374344a

Browse files
committed
feat: add user preference to set default language for AudioToText
Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
1 parent e5fb43c commit 374344a

File tree

5 files changed

+66
-8
lines changed

5 files changed

+66
-8
lines changed

lib/Service/OpenAiAPIService.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ public function transcribeFile(
693693
File $file,
694694
bool $translate = false,
695695
string $model = Application::DEFAULT_MODEL_ID,
696-
string $language = 'detect_language',
696+
string $language = 'default',
697697
): string {
698698
try {
699699
$transcriptionResponse = $this->transcribe($userId, $file->getContent(), $translate, $model, $language);
@@ -719,7 +719,7 @@ public function transcribe(
719719
string $audioFileContent,
720720
bool $translate = true,
721721
string $model = Application::DEFAULT_MODEL_ID,
722-
string $language = 'detect_language',
722+
string $language = 'default',
723723
): string {
724724
if ($this->isQuotaExceeded($userId, Application::QUOTA_TYPE_TRANSCRIPTION)) {
725725
throw new Exception($this->l10n->t('Audio transcription quota exceeded'), Http::STATUS_TOO_MANY_REQUESTS);
@@ -735,6 +735,10 @@ public function transcribe(
735735
'response_format' => 'verbose_json',
736736
// Verbose needed for extraction of audio duration
737737
];
738+
// Gets the user's preferred language if it's not the default one
739+
if ($language === 'default') {
740+
$language = $this->openAiSettingsService->getUserSTTLanguage($userId);
741+
}
738742
if ($language !== 'detect_language') {
739743
$params['language'] = $language;
740744
}

lib/Service/OpenAiSettingsService.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class OpenAiSettingsService {
5353
'api_key' => 'string',
5454
'basic_user' => 'string',
5555
'basic_password' => 'string',
56+
'stt_language' => 'string',
5657
];
5758

5859

@@ -158,6 +159,14 @@ public function getUserApiKey(?string $userId, bool $fallBackOnAdminValue = fals
158159
return $userApiKey ?: $fallBackApiKey;
159160
}
160161

162+
/**
163+
* @param string|null $userId
164+
* @return string
165+
*/
166+
public function getUserSTTLanguage(?string $userId): string {
167+
return $this->config->getUserValue($userId, Application::APP_ID, 'stt_language', 'detect_language');
168+
}
169+
161170
/**
162171
* @return string
163172
*/
@@ -408,7 +417,7 @@ public function getAdminConfig(): array {
408417

409418
/**
410419
* Get the user config for the settings page
411-
* @return array{api_key: string, basic_password: string, basic_user: string, is_custom_service: bool, use_basic_auth: bool}
420+
* @return array{api_key: string, basic_password: string, basic_user: string, is_custom_service: bool, use_basic_auth: bool, stt_language: string}
412421
*/
413422
public function getUserConfig(string $userId): array {
414423
$isCustomService = $this->getServiceUrl() !== '' && $this->getServiceUrl() !== Application::OPENAI_API_BASE_URL;
@@ -418,6 +427,7 @@ public function getUserConfig(string $userId): array {
418427
'basic_password' => $this->getUserBasicPassword($userId, false),
419428
'use_basic_auth' => $this->getUseBasicAuth(),
420429
'is_custom_service' => $isCustomService,
430+
'stt_language' => $this->getUserSTTLanguage($userId)
421431

422432
];
423433
}
@@ -544,6 +554,15 @@ public function setUserApiKey(string $userId, string $apiKey): void {
544554
$this->invalidateModelsCache();
545555
}
546556

557+
/**
558+
* @param string $userId
559+
* @param string $language
560+
* @throws PreConditionNotMetException
561+
*/
562+
public function setUserSTTLanguage(string $userId, string $language): void {
563+
$this->config->setUserValue($userId, Application::APP_ID, 'stt_language', $language);
564+
}
565+
547566
/**
548567
* @param string $defaultCompletionModelId
549568
* @return void
@@ -886,6 +905,9 @@ public function setUserConfig(string $userId, array $userConfig): void {
886905
if (isset($userConfig['basic_password'])) {
887906
$this->setUserBasicPassword($userId, $userConfig['basic_password']);
888907
}
908+
if (isset($userConfig['stt_language'])) {
909+
$this->setUserSttLanguage($userId, $userConfig['stt_language']);
910+
}
889911
}
890912

891913
/**

lib/Settings/Personal.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
use OCA\OpenAi\Service\OpenAiSettingsService;
1212
use OCP\AppFramework\Http\TemplateResponse;
1313
use OCP\AppFramework\Services\IInitialState;
14+
use OCP\IL10N;
1415
use OCP\Settings\ISettings;
1516

1617
class Personal implements ISettings {
1718
public function __construct(
1819
private IInitialState $initialStateService,
1920
private OpenAiSettingsService $openAiSettingsService,
21+
private IL10N $l,
2022
private ?string $userId,
2123
) {
2224
}
@@ -31,6 +33,25 @@ public function getForm(): TemplateResponse {
3133
$userConfig = $this->openAiSettingsService->getUserConfig($this->userId);
3234
$userConfig['api_key'] = $userConfig['api_key'] === '' ? '' : 'dummyApiKey';
3335
$userConfig['basic_password'] = $userConfig['basic_password'] === '' ? '' : 'dummyPassword';
36+
$languages = Application::AUDIO_TO_TEXT_LANGUAGES;
37+
array_unshift($languages, ['detect_language', $this->l->t('Detect language')]);
38+
$languages = array_map(static function (array $language) use ($userConfig) {
39+
return [
40+
'value' => $language[0],
41+
'label' => $language[1],
42+
];
43+
}, $languages);
44+
$this->initialStateService->provideInitialState('languages', $languages);
45+
$STTLanguage = $userConfig['stt_language'];
46+
47+
// Sets the correct value and label for the frontend
48+
$userConfig['stt_language'] = ['value' => '', 'label' => ''];
49+
foreach ($languages as $language) {
50+
if ($language['value'] === $STTLanguage) {
51+
$userConfig['stt_language'] = $language;
52+
break;
53+
}
54+
}
3455
$this->initialStateService->provideInitialState('config', $userConfig);
3556
return new TemplateResponse(Application::APP_ID, 'personalSettings');
3657
}

lib/TaskProcessing/AudioToTextProvider.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use OCP\Files\File;
1616
use OCP\IAppConfig;
1717
use OCP\IL10N;
18-
use OCP\L10N\IFactory;
1918
use OCP\TaskProcessing\EShapeType;
2019
use OCP\TaskProcessing\ISynchronousProvider;
2120
use OCP\TaskProcessing\ShapeDescriptor;
@@ -30,7 +29,6 @@ public function __construct(
3029
private OpenAiAPIService $openAiAPIService,
3130
private LoggerInterface $logger,
3231
private IAppConfig $appConfig,
33-
private IFactory $l10nFactory,
3432
private IL10N $l,
3533
) {
3634
}
@@ -72,11 +70,12 @@ public function getOptionalInputShapeEnumValues(): array {
7270
return new ShapeEnumValue($language[1], $language[0]);
7371
}, Application::AUDIO_TO_TEXT_LANGUAGES);
7472
$detectLanguageEnumValue = new ShapeEnumValue($this->l->t('Detect language'), 'detect_language');
75-
return ['language' => array_merge([$detectLanguageEnumValue], $languageEnumValues)];
73+
$defaultLanguageEnumValue = new ShapeEnumValue($this->l->t('Default'), 'default');
74+
return ['language' => array_merge([$detectLanguageEnumValue, $defaultLanguageEnumValue], $languageEnumValues)];
7675
}
7776

7877
public function getOptionalInputShapeDefaults(): array {
79-
return ['language' => 'detect_language'];
78+
return ['language' => 'default'];
8079
}
8180

8281
public function getOutputShapeEnumValues(): array {
@@ -96,7 +95,7 @@ public function process(?string $userId, array $input, callable $reportProgress)
9695
throw new RuntimeException('Invalid input file');
9796
}
9897
$inputFile = $input['input'];
99-
$language = $input['language'] ?? 'detect_language';
98+
$language = $input['language'] ?? 'default';
10099
if (!is_string($language)) {
101100
throw new RuntimeException('Invalid language');
102101
}

src/components/PersonalSettings.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
{{ t('integration_openai', 'OpenAI and LocalAI integration') }}
1010
</h2>
1111
<div id="openai-content">
12+
<h4>
13+
{{ t('integration_openai', 'Speech to Text Default Language') }}
14+
</h4>
15+
<NcSelect
16+
v-model="state.stt_language"
17+
:options="languages"
18+
:input-label="t('integration_openai', 'Default language')"
19+
@update:model-value="onInput()" />
1220
<p v-if="state.is_custom_service" class="settings-hint">
1321
<InformationOutlineIcon :size="20" class="icon" />
1422
{{ t('integration_openai', 'Your administrator defined a custom service address') }}
@@ -131,6 +139,7 @@ import OpenAiIcon from './icons/OpenAiIcon.vue'
131139
132140
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
133141
import NcTextField from '@nextcloud/vue/components/NcTextField'
142+
import NcSelect from '@nextcloud/vue/components/NcSelect'
134143
135144
import axios from '@nextcloud/axios'
136145
import { showError, showSuccess } from '@nextcloud/dialogs'
@@ -150,13 +159,15 @@ export default {
150159
InformationOutlineIcon,
151160
NcNoteCard,
152161
NcTextField,
162+
NcSelect,
153163
},
154164
155165
props: [],
156166
157167
data() {
158168
return {
159169
state: loadState('integration_openai', 'config'),
170+
languages: loadState('integration_openai', 'languages'),
160171
// to prevent some browsers to fill fields with remembered passwords
161172
readonly: true,
162173
apiKeyUrl: 'https://platform.openai.com/account/api-keys',
@@ -186,6 +197,7 @@ export default {
186197
methods: {
187198
onInput: debounce(function() {
188199
this.saveOptions({
200+
stt_language: this.state.stt_language.value,
189201
})
190202
}, 2000),
191203
onSensitiveInput: debounce(async function() {

0 commit comments

Comments
 (0)