webui: split raw output into backend parsing and frontend display options

This commit is contained in:
Pascal 2026-01-03 17:30:52 +01:00 committed by Aleksander Grygier
parent 4f9d9d41b9
commit fc7218ae11
9 changed files with 26 additions and 24 deletions

View File

@ -139,6 +139,6 @@ sequenceDiagram
Note over settingsStore: UI-only (not synced):
rect rgb(255, 240, 240)
Note over settingsStore: systemMessage, custom (JSON)<br/>showStatistics, enableContinueGeneration<br/>autoMicOnEmpty, disableAutoScroll<br/>apiKey, pdfAsImage, disableReasoningFormat
Note over settingsStore: systemMessage, custom (JSON)<br/>showStatistics, enableContinueGeneration<br/>autoMicOnEmpty, disableAutoScroll<br/>apiKey, pdfAsImage, disableReasoningParsing, showRawOutputSwitch
end
```

View File

@ -261,7 +261,7 @@
{onConfirmDelete}
{onNavigateToSibling}
{onShowDeleteDialogChange}
showRawOutputSwitch={currentConfig.disableReasoningFormat}
showRawOutputSwitch={currentConfig.showRawOutputSwitch}
rawOutputEnabled={showRawOutput}
onRawOutputToggle={(enabled) => (showRawOutput = enabled)}
/>

View File

@ -276,8 +276,13 @@
icon: Code,
fields: [
{
key: 'disableReasoningFormat',
label: 'Enable raw LLM output switch',
key: 'disableReasoningParsing',
label: 'Disable reasoning content parsing',
type: 'checkbox'
},
{
key: 'showRawOutputSwitch',
label: 'Enable raw output toggle',
type: 'checkbox'
},
{

View File

@ -6,7 +6,8 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
showSystemMessage: true,
theme: 'system',
showThoughtInProgress: false,
disableReasoningFormat: false,
disableReasoningParsing: false,
showRawOutputSwitch: false,
keepStatsVisible: false,
showMessageStats: true,
askForTitleConfirmation: false,
@ -95,8 +96,10 @@ export const SETTING_CONFIG_INFO: Record<string, string> = {
max_tokens: 'The maximum number of token per output. Use -1 for infinite (no limit).',
custom: 'Custom JSON parameters to send to the API. Must be valid JSON format.',
showThoughtInProgress: 'Expand thought process by default when generating messages.',
disableReasoningFormat:
'Enable raw LLM output switch to show unprocessed model output without backend parsing and frontend Markdown rendering to inspect streaming across different models.',
disableReasoningParsing:
'Send reasoning_format=none to prevent server-side extraction of reasoning tokens into separate field',
showRawOutputSwitch:
'Show toggle button to display messages as plain text instead of Markdown-formatted content',
keepStatsVisible: 'Keep processing statistics visible after generation finishes.',
showMessageStats:
'Display generation statistics (tokens/second, token count, duration) below each assistant message.',

View File

@ -90,7 +90,7 @@ export class ChatService {
custom,
timings_per_token,
// Config options
disableReasoningFormat
disableReasoningParsing
} = options;
const normalizedMessages: ApiChatMessageData[] = messages
@ -127,7 +127,7 @@ export class ChatService {
requestBody.model = options.model;
}
requestBody.reasoning_format = disableReasoningFormat ? 'none' : 'auto';
requestBody.reasoning_format = disableReasoningParsing ? 'none' : 'auto';
if (temperature !== undefined) requestBody.temperature = temperature;
if (max_tokens !== undefined) {

View File

@ -69,12 +69,6 @@ export const SYNCABLE_PARAMETERS: SyncableParameter[] = [
type: 'boolean',
canSync: true
},
{
key: 'disableReasoningFormat',
serverKey: 'disableReasoningFormat',
type: 'boolean',
canSync: true
},
{ key: 'keepStatsVisible', serverKey: 'keepStatsVisible', type: 'boolean', canSync: true },
{ key: 'showMessageStats', serverKey: 'showMessageStats', type: 'boolean', canSync: true },
{

View File

@ -1456,7 +1456,7 @@ class ChatStore {
// Config options needed by ChatService
if (currentConfig.systemMessage) apiOptions.systemMessage = currentConfig.systemMessage;
if (currentConfig.disableReasoningFormat) apiOptions.disableReasoningFormat = true;
if (currentConfig.disableReasoningParsing) apiOptions.disableReasoningParsing = true;
if (hasValue(currentConfig.temperature))
apiOptions.temperature = Number(currentConfig.temperature);

View File

@ -18,8 +18,8 @@ export interface SettingsChatServiceOptions {
model?: string;
// System message to inject
systemMessage?: string;
// Disable reasoning format (use 'none' instead of 'auto')
disableReasoningFormat?: boolean;
// Disable reasoning parsing (use 'none' instead of 'auto')
disableReasoningParsing?: boolean;
// Generation parameters
temperature?: number;
max_tokens?: number;

View File

@ -93,7 +93,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', false);
settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@ -105,7 +105,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', false);
settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@ -117,7 +117,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', false);
settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@ -129,7 +129,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', true);
settingsStore.updateConfig('showRawOutputSwitch', true);
}}
/>
@ -141,7 +141,7 @@
asChild
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', false);
settingsStore.updateConfig('showRawOutputSwitch', false);
// Phase 1: Stream reasoning content in chunks
let reasoningText =
'I need to think about this carefully. Let me break down the problem:\n\n1. The user is asking for help with something complex\n2. I should provide a thorough and helpful response\n3. I need to consider multiple approaches\n4. The best solution would be to explain step by step\n\nThis approach will ensure clarity and understanding.';
@ -193,7 +193,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
settingsStore.updateConfig('disableReasoningFormat', false);
settingsStore.updateConfig('showRawOutputSwitch', false);
// Import the chat store to simulate loading state
const { chatStore } = await import('$lib/stores/chat.svelte');