webui: Architecture and UI improvements (#19596)
This commit is contained in:
@@ -1,26 +1,21 @@
|
||||
import { modelsStore } from '$lib/stores/models.svelte';
|
||||
import { isRouterMode } from '$lib/stores/server.svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import type { ModelModalities } from '$lib/types';
|
||||
|
||||
interface UseModelChangeValidationOptions {
|
||||
/**
|
||||
* Function to get required modalities for validation.
|
||||
* For ChatForm: () => usedModalities() - all messages
|
||||
* For ChatMessageAssistant: () => getModalitiesUpToMessage(messageId) - messages before
|
||||
*/
|
||||
getRequiredModalities: () => ModelModalities;
|
||||
|
||||
/**
|
||||
* Optional callback to execute after successful validation.
|
||||
* For ChatForm: undefined - just select model
|
||||
* For ChatMessageAssistant: (modelName) => onRegenerate(modelName)
|
||||
*/
|
||||
onSuccess?: (modelName: string) => void;
|
||||
|
||||
/**
|
||||
* Optional callback for rollback on validation failure.
|
||||
* For ChatForm: (previousId) => selectModelById(previousId)
|
||||
* For ChatMessageAssistant: undefined - no rollback needed
|
||||
*/
|
||||
onValidationFailure?: (previousModelId: string | null) => Promise<void>;
|
||||
}
|
||||
@@ -33,12 +28,10 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
|
||||
async function handleModelChange(modelId: string, modelName: string): Promise<boolean> {
|
||||
try {
|
||||
// Store previous selection for potential rollback
|
||||
if (onValidationFailure) {
|
||||
previousSelectedModelId = modelsStore.selectedModelId;
|
||||
}
|
||||
|
||||
// Load model if not already loaded (router mode only)
|
||||
let hasLoadedModel = false;
|
||||
const isModelLoadedBefore = modelsStore.isModelLoaded(modelName);
|
||||
|
||||
@@ -52,13 +45,11 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch model props to validate modalities
|
||||
const props = await modelsStore.fetchModelProps(modelName);
|
||||
|
||||
if (props?.modalities) {
|
||||
const requiredModalities = getRequiredModalities();
|
||||
|
||||
// Check if model supports required modalities
|
||||
const missingModalities: string[] = [];
|
||||
if (requiredModalities.vision && !props.modalities.vision) {
|
||||
missingModalities.push('vision');
|
||||
@@ -72,7 +63,6 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
`Model "${modelName}" doesn't support required modalities: ${missingModalities.join(', ')}. Please select a different model.`
|
||||
);
|
||||
|
||||
// Unload the model if we just loaded it
|
||||
if (isRouter && hasLoadedModel) {
|
||||
try {
|
||||
await modelsStore.unloadModel(modelName);
|
||||
@@ -81,7 +71,6 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
}
|
||||
}
|
||||
|
||||
// Execute rollback callback if provided
|
||||
if (onValidationFailure && previousSelectedModelId) {
|
||||
await onValidationFailure(previousSelectedModelId);
|
||||
}
|
||||
@@ -90,10 +79,8 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
}
|
||||
}
|
||||
|
||||
// Select the model (validation passed)
|
||||
await modelsStore.selectModelById(modelId);
|
||||
|
||||
// Execute success callback if provided
|
||||
if (onSuccess) {
|
||||
onSuccess(modelName);
|
||||
}
|
||||
@@ -103,7 +90,6 @@ export function useModelChangeValidation(options: UseModelChangeValidationOption
|
||||
console.error('Failed to change model:', error);
|
||||
toast.error('Failed to validate model capabilities');
|
||||
|
||||
// Execute rollback callback on error if provided
|
||||
if (onValidationFailure && previousSelectedModelId) {
|
||||
await onValidationFailure(previousSelectedModelId);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,7 @@
|
||||
import { activeProcessingState } from '$lib/stores/chat.svelte';
|
||||
import { config } from '$lib/stores/settings.svelte';
|
||||
import { STATS_UNITS } from '$lib/constants/processing-info';
|
||||
import type { ApiProcessingState } from '$lib/types';
|
||||
|
||||
interface LiveProcessingStats {
|
||||
tokensProcessed: number;
|
||||
totalTokens: number;
|
||||
timeMs: number;
|
||||
tokensPerSecond: number;
|
||||
etaSecs?: number;
|
||||
}
|
||||
|
||||
interface LiveGenerationStats {
|
||||
tokensGenerated: number;
|
||||
timeMs: number;
|
||||
tokensPerSecond: number;
|
||||
}
|
||||
import type { ApiProcessingState, LiveProcessingStats, LiveGenerationStats } from '$lib/types';
|
||||
|
||||
export interface UseProcessingStateReturn {
|
||||
readonly processingState: ApiProcessingState | null;
|
||||
|
||||
Reference in New Issue
Block a user