Skip to content
Open
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
2 changes: 0 additions & 2 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ class Application extends App implements IBootstrap {
public const DEFAULT_QUOTA_PERIOD = 30;
public const MAX_QUOTA_PERIOD_DAYS = 3650;
public const MAX_QUOTA_PERIOD_MONTHS = 120;
public const DEFAULT_SUMMARY_SYSTEM_PROMPT = 'You are a helpful assistant that summarizes text in the same language as the text. '
. 'You should only return the summary without any additional information.';
public const DEFAULT_QUOTA_CONFIG = ['length' => self::DEFAULT_QUOTA_PERIOD, 'unit' => 'day', 'day' => 1];

public const DEFAULT_OPENAI_TEXT_GENERATION_TIME = 10; // seconds
Expand Down
29 changes: 1 addition & 28 deletions lib/Service/OpenAiSettingsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class OpenAiSettingsService {
private const ADMIN_CONFIG_TYPES = [
'quota_period' => 'array',
'usage_storage_time' => 'integer',
'summary_system_prompt' => 'string',
];

private const USER_CONFIG_TYPES = [
Expand Down Expand Up @@ -136,19 +135,6 @@ public function getUsageStorageTime(): int {
return $this->appConfig->getValueInt(Application::APP_ID, 'usage_storage_time', Application::DEFAULT_QUOTA_PERIOD, lazy: true);
}

/**
* System prompt for the summary provider. Empty falls back to the default unless $raw is true.
*/
public function getSummarySystemPrompt(bool $raw = false): string {
$default = $raw ? '' : Application::DEFAULT_SUMMARY_SYSTEM_PROMPT;
return $this->appConfig->getValueString(
Application::APP_ID,
'summary_system_prompt',
$default,
lazy: true
) ?: $default;
}

/**
* @param string|null $userId
* @return string
Expand All @@ -160,13 +146,12 @@ public function getUserSTTLanguage(?string $userId): string {
/**
* Get the instance-wide admin config for the settings page
*
* @return array{quota_period: array, usage_storage_time: int, summary_system_prompt: string}
* @return array{quota_period: array, usage_storage_time: int}
*/
public function getAdminConfig(): array {
return [
'quota_period' => $this->getQuotaPeriod(),
'usage_storage_time' => $this->getUsageStorageTime(),
'summary_system_prompt' => $this->getSummarySystemPrompt(true),
];
}

Expand Down Expand Up @@ -233,15 +218,6 @@ public function setUsageStorageTime(int $usageStorageTime): void {
$this->appConfig->setValueInt(Application::APP_ID, 'usage_storage_time', $usageStorageTime, lazy: true);
}

public function setSummarySystemPrompt(string $summarySystemPrompt): void {
$this->appConfig->setValueString(
Application::APP_ID,
'summary_system_prompt',
$summarySystemPrompt,
lazy: true
);
}

/**
* @param string $userId
* @param string $language
Expand Down Expand Up @@ -274,9 +250,6 @@ public function setAdminConfig(array $adminConfig): void {
if (isset($adminConfig['usage_storage_time'])) {
$this->setUsageStorageTime($adminConfig['usage_storage_time']);
}
if (isset($adminConfig['summary_system_prompt'])) {
$this->setSummarySystemPrompt($adminConfig['summary_system_prompt']);
}
}

/**
Expand Down
28 changes: 28 additions & 0 deletions lib/Service/ServiceConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ServiceConfig implements JsonSerializable {
'llm_extra_params' => 'string',
'max_tokens' => 'integer',
'chunk_size' => 'integer',
'system_prompt_summary' => 'string',
'system_prompt_translate' => 'string',
'multimodal_image_enabled' => 'boolean',
'multimodal_audio_enabled' => 'boolean',
'multimodal_video_enabled' => 'boolean',
Expand Down Expand Up @@ -83,6 +85,8 @@ public function __construct(
private string $llmExtraParams = '',
private int $maxTokens = Application::DEFAULT_MAX_NUM_OF_TOKENS,
private int $chunkSize = Application::DEFAULT_CHUNK_SIZE,
private string $systemPromptSummary = '',
private string $systemPromptTranslate = '',
// these mirror the defaults of the single-service configuration, so
// that a migrated service and a newly connected one accept the same
// kinds of attachment
Expand Down Expand Up @@ -150,6 +154,10 @@ public function with(array $values): self {
break;
case 'chunk_size': $new->chunkSize = (int)$value === 0 ? 0 : max(Application::MIN_CHUNK_SIZE, (int)$value);
break;
case 'system_prompt_summary': $new->systemPromptSummary = (string)$value;
break;
case 'system_prompt_translate': $new->systemPromptTranslate = (string)$value;
break;
case 'multimodal_image_enabled': $new->multimodalImageEnabled = (bool)$value;
break;
case 'multimodal_audio_enabled': $new->multimodalAudioEnabled = (bool)$value;
Expand Down Expand Up @@ -349,6 +357,24 @@ public function getChunkSize(): int {
return $this->chunkSize;
}

/**
* The admin-configured fallback system prompt for the summary task type.
* An empty string means the built-in default prompt is used.
*/
Comment on lines +360 to +363

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment isn't relevant to this particular function. Plus, it is redundant anyway, so it should be removed.

public function getSystemPromptSummary(): string {
return $this->systemPromptSummary;
}

/**
* The admin-configured system prompt appended to the built-in translation
* prompt for the translation task type. The built-in prompt is always kept,
* as it enforces the expected JSON response format.
* An empty string means only the built-in prompt is used.
*/
Comment on lines +368 to +373

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment isn't relevant to this particular function. Also, I think the code is TranslateService is clear enough to know what is happening, so I don't think it's necessary either.

public function getSystemPromptTranslate(): string {
return $this->systemPromptTranslate;
}

public function getMultimodalImageEnabled(): bool {
return $this->multimodalImageEnabled;
}
Expand Down Expand Up @@ -466,6 +492,8 @@ public function jsonSerialize(): array {
'llm_extra_params' => $this->llmExtraParams,
'max_tokens' => $this->maxTokens,
'chunk_size' => $this->chunkSize,
'system_prompt_summary' => $this->systemPromptSummary,
'system_prompt_translate' => $this->systemPromptTranslate,
'multimodal_image_enabled' => $this->multimodalImageEnabled,
'multimodal_audio_enabled' => $this->multimodalAudioEnabled,
'multimodal_video_enabled' => $this->multimodalVideoEnabled,
Expand Down
10 changes: 8 additions & 2 deletions lib/Service/TranslateService.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public function translate(
$promptStart = 'Translate the following text to ' . $toLanguage . ': ';
}

$systemPrompt = self::SYSTEM_PROMPT;
$adminSystemPrompt = $service->getSystemPromptTranslate();
if ($adminSystemPrompt !== '') {
$systemPrompt .= PHP_EOL . $adminSystemPrompt;
}

$cache = $this->cacheFactory->createDistributed('integration_openai');
foreach ($chunks as $chunk) {
$progress += $increase;
Expand All @@ -105,12 +111,12 @@ public function translate(

if ($service->isUsingOpenAi() || $service->getChatEndpointEnabled()) {
$completionsObj = $this->openAiAPIService->createChatCompletion(
$userId, $service, $model, $prompt, TranslateService::SYSTEM_PROMPT, null, 1, $maxTokens, TranslateService::JSON_RESPONSE_FORMAT
$userId, $service, $model, $prompt, $systemPrompt, null, 1, $maxTokens, TranslateService::JSON_RESPONSE_FORMAT
);
$completions = $completionsObj['messages'];
} else {
$completions = $this->openAiAPIService->createCompletion(
$userId, $service, $prompt . PHP_EOL . TranslateService::SYSTEM_PROMPT . PHP_EOL . PHP_EOL, 1, $model, $maxTokens
$userId, $service, $prompt . PHP_EOL . $systemPrompt . PHP_EOL . PHP_EOL, 1, $model, $maxTokens
);
}

Expand Down
4 changes: 1 addition & 3 deletions lib/TaskProcessing/ProviderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use OCA\OpenAi\AppInfo\Application;
use OCA\OpenAi\Service\ChunkService;
use OCA\OpenAi\Service\OpenAiAPIService;
use OCA\OpenAi\Service\OpenAiSettingsService;
use OCA\OpenAi\Service\ServiceConfig;
use OCA\OpenAi\Service\ServicesService;
use OCA\OpenAi\Service\TranslateService;
Expand All @@ -36,7 +35,6 @@ class ProviderFactory {
public function __construct(
private ServicesService $servicesService,
private OpenAiAPIService $openAiAPIService,
private OpenAiSettingsService $openAiSettingsService,
private ChunkService $chunkService,
private TranslateService $translateService,
private WatermarkingService $watermarkingService,
Expand Down Expand Up @@ -82,7 +80,7 @@ private function getTextProviders(ServiceConfig $service, string $model): array
new TextToTextProvider($this->openAiAPIService, $this->l, $service, $model),
new TextToTextChatProvider($this->openAiAPIService, $this->l, $service, $model),
new TextToTextChatWithToolsProvider($this->openAiAPIService, $this->l, $service, $model),
new SummaryProvider($this->openAiAPIService, $this->l, $this->chunkService, $this->openAiSettingsService, $service, $model),
new SummaryProvider($this->openAiAPIService, $this->l, $this->chunkService, $service, $model),
new HeadlineProvider($this->openAiAPIService, $this->l, $service, $model),
new TopicsProvider($this->openAiAPIService, $this->l, $this->chunkService, $this->logger, $service, $model),
new ContextWriteProvider($this->openAiAPIService, $this->chunkService, $this->l, $service, $model),
Expand Down
16 changes: 13 additions & 3 deletions lib/TaskProcessing/SummaryProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use OCA\OpenAi\Service\ChunkService;
use OCA\OpenAi\Service\OpenAiAPIService;
use OCA\OpenAi\Service\OpenAiSettingsService;
use OCA\OpenAi\Service\ServiceConfig;
use OCP\IL10N;
use OCP\TaskProcessing\EShapeType;
Expand All @@ -25,11 +24,13 @@
class SummaryProvider implements ISynchronousProvider {
use ProviderIdentity;

public const DEFAULT_SYSTEM_PROMPT = 'You are a helpful assistant that summarizes text in the same language as the text. '
. 'You should only return the summary without any additional information. ';

public function __construct(
private OpenAiAPIService $openAiAPIService,
private IL10N $l,
private ChunkService $chunkService,
private OpenAiSettingsService $openAiSettingsService,
private ServiceConfig $service,
private string $model,
) {
Expand Down Expand Up @@ -144,7 +145,15 @@ public function process(?string $userId, array $input, callable $reportProgress)

try {
$completions = [];
$summarySystemPrompt = $this->openAiSettingsService->getSummarySystemPrompt() . ' ';

// Use the admin-configured prompt, then default. Format and complexity appended
$summarySystemPrompt = $this->service->getSystemPromptSummary();
if ($summarySystemPrompt === '') {
$summarySystemPrompt = self::DEFAULT_SYSTEM_PROMPT;
} else {
$summarySystemPrompt .= ' ';
}

if (isset($input['format'])) {
if ($input['format'] === 'paragraph') {
$summarySystemPrompt .= 'Return the summary as a paragraph. ';
Expand All @@ -161,6 +170,7 @@ public function process(?string $userId, array $input, callable $reportProgress)
$summarySystemPrompt .= 'Use simple language and vocabulary appropriate for a 5 year old. ';
}
}

if ($this->service->isUsingOpenAi() || $this->service->getChatEndpointEnabled()) {

foreach ($prompts as $p) {
Expand Down
26 changes: 2 additions & 24 deletions src/components/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,6 @@
</NcButton>
</div>

<h3>{{ t('integration_openai', 'Text generation') }}</h3>
<div class="line line--full">
<NcTextArea
id="summary-system-prompt"
v-model="state.summary_system_prompt"
class="input input--full"
:label="t('integration_openai', 'Summary system prompt')"
:helper-text="t('integration_openai', 'System prompt used when generating text summaries. Leave empty to use the default prompt.')"
:rows="5"
resize="vertical"
@update:model-value="onInput()" />
</div>

<h3>{{ t('integration_openai', 'Usage limits') }}</h3>
<div class="line">
<QuotaPeriodPicker
Expand Down Expand Up @@ -128,7 +115,6 @@ import NcInputField from '@nextcloud/vue/components/NcInputField'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
import NcSelect from '@nextcloud/vue/components/NcSelect'
import NcTextArea from '@nextcloud/vue/components/NcTextArea'

import axios from '@nextcloud/axios'
import { showError, showSuccess, showWarning } from '@nextcloud/dialogs'
Expand All @@ -155,7 +141,6 @@ export default {
NcLoadingIcon,
NcNoteCard,
NcSelect,
NcTextArea,
},

data() {
Expand Down Expand Up @@ -385,6 +370,8 @@ export default {
llm_extra_params: service.llm_extra_params,
max_tokens: parseInt(service.max_tokens) || 1,
chunk_size: parseInt(service.chunk_size) || 0,
system_prompt_summary: service.system_prompt_summary,
system_prompt_translate: service.system_prompt_translate,
multimodal_image_enabled: service.multimodal_image_enabled,
multimodal_audio_enabled: service.multimodal_audio_enabled,
multimodal_video_enabled: service.multimodal_video_enabled,
Expand Down Expand Up @@ -430,7 +417,6 @@ export default {
await this.saveAdminConfig({
quota_period: this.state.quota_period,
usage_storage_time: parseInt(this.state.usage_storage_time) || 1,
summary_system_prompt: this.state.summary_system_prompt,
})
}, 2000),
async saveAdminConfig(values) {
Expand Down Expand Up @@ -491,14 +477,6 @@ export default {
width: 300px;
}

.line--full {
width: 100%;
}

.line .input--full {
width: 100%;
}
Comment on lines -494 to -500

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the new text boxes should keep their full width too. The current boxes are too small to comfortably fit longer prompts.


.services {
display: flex;
flex-wrap: wrap;
Expand Down
33 changes: 33 additions & 0 deletions src/components/ServiceForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,37 @@
@update:model-value="onInput({ translation_enabled: $event })">
{{ t('integration_openai', 'Offer translation') }}
</NcCheckboxRadioSwitch>
<h5>{{ t('integration_openai', 'System prompts') }}</h5>
<div class="line">
<NcTextArea
:id="'openai-summary-system-prompt-' + service.id"
:model-value="service.system_prompt_summary"
class="input"
:label="t('integration_openai', 'Summary system prompt')"
:placeholder="t('integration_openai', 'Leave empty to use the default summary prompt')"
@update:model-value="onInput({ system_prompt_summary: $event })" />
<NcButton variant="tertiary"
:title="t('integration_openai', 'When set, it replaces default summary prompt. The Format and Complexity options are still appended to it.')">
<template #icon>
<HelpCircleOutlineIcon />
</template>
</NcButton>
</div>
<div class="line">
<NcTextArea
:id="'openai-translate-system-prompt-' + service.id"
:model-value="service.system_prompt_translate"
class="input"
:label="t('integration_openai', 'Translation system prompt')"
:placeholder="t('integration_openai', 'Leave empty to use the default translation prompt')"
@update:model-value="onInput({ system_prompt_translate: $event })" />
<NcButton variant="tertiary"
:title="t('integration_openai', 'Additional instructions for translations.')">
<template #icon>
<HelpCircleOutlineIcon />
</template>
</NcButton>
</div>
<h5>{{ t('integration_openai', 'Multimodal LLM Support') }}</h5>
<NcNoteCard type="info">
{{ t('integration_openai', 'Which kinds of attachments the models of this service accept.') }}
Expand Down Expand Up @@ -412,6 +443,7 @@ import NcInputField from '@nextcloud/vue/components/NcInputField'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
import NcSelect from '@nextcloud/vue/components/NcSelect'
import NcTextArea from '@nextcloud/vue/components/NcTextArea'
import NcTextField from '@nextcloud/vue/components/NcTextField'

import axios from '@nextcloud/axios'
Expand Down Expand Up @@ -439,6 +471,7 @@ export default {
NcLoadingIcon,
NcNoteCard,
NcSelect,
NcTextArea,
NcTextField,
},

Expand Down
Loading
Loading