summaryrefslogtreecommitdiff
path: root/llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
commitb333b06772c89d96aacb5490d6a219fba7c09cc6 (patch)
tree211df60083a5946baa2ed61d33d8121b7e251b06 /llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts
downloadllmnpc-b333b06772c89d96aacb5490d6a219fba7c09cc6.tar.gz
Engage!
Diffstat (limited to 'llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts')
-rw-r--r--llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts162
1 files changed, 162 insertions, 0 deletions
diff --git a/llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts b/llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts
new file mode 100644
index 0000000..136c084
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/utils/modality-file-validation.ts
@@ -0,0 +1,162 @@
+/**
+ * File validation utilities based on model modalities
+ * Ensures only compatible file types are processed based on model capabilities
+ */
+
+import { getFileTypeCategory } from '$lib/utils';
+import { FileTypeCategory } from '$lib/enums';
+
+/** Modality capabilities for file validation */
+export interface ModalityCapabilities {
+ hasVision: boolean;
+ hasAudio: boolean;
+}
+
+/**
+ * Check if a file type is supported by the given modalities
+ * @param filename - The filename to check
+ * @param mimeType - The MIME type of the file
+ * @param capabilities - The modality capabilities to check against
+ * @returns true if the file type is supported
+ */
+export function isFileTypeSupportedByModel(
+ filename: string,
+ mimeType: string | undefined,
+ capabilities: ModalityCapabilities
+): boolean {
+ const category = mimeType ? getFileTypeCategory(mimeType) : null;
+
+ // If we can't determine the category from MIME type, fall back to general support check
+ if (!category) {
+ // For unknown types, only allow if they might be text files
+ // This is a conservative approach for edge cases
+ return true; // Let the existing isFileTypeSupported handle this
+ }
+
+ switch (category) {
+ case FileTypeCategory.TEXT:
+ // Text files are always supported
+ return true;
+
+ case FileTypeCategory.PDF:
+ // PDFs are always supported (will be processed as text for non-vision models)
+ return true;
+
+ case FileTypeCategory.IMAGE:
+ // Images require vision support
+ return capabilities.hasVision;
+
+ case FileTypeCategory.AUDIO:
+ // Audio files require audio support
+ return capabilities.hasAudio;
+
+ default:
+ // Unknown categories - be conservative and allow
+ return true;
+ }
+}
+
+/**
+ * Filter files based on model modalities and return supported/unsupported lists
+ * @param files - Array of files to filter
+ * @param capabilities - The modality capabilities to check against
+ * @returns Object with supportedFiles and unsupportedFiles arrays
+ */
+export function filterFilesByModalities(
+ files: File[],
+ capabilities: ModalityCapabilities
+): {
+ supportedFiles: File[];
+ unsupportedFiles: File[];
+ modalityReasons: Record<string, string>;
+} {
+ const supportedFiles: File[] = [];
+ const unsupportedFiles: File[] = [];
+ const modalityReasons: Record<string, string> = {};
+
+ const { hasVision, hasAudio } = capabilities;
+
+ for (const file of files) {
+ const category = getFileTypeCategory(file.type);
+ let isSupported = true;
+ let reason = '';
+
+ switch (category) {
+ case FileTypeCategory.IMAGE:
+ if (!hasVision) {
+ isSupported = false;
+ reason = 'Images require a vision-capable model';
+ }
+ break;
+
+ case FileTypeCategory.AUDIO:
+ if (!hasAudio) {
+ isSupported = false;
+ reason = 'Audio files require an audio-capable model';
+ }
+ break;
+
+ case FileTypeCategory.TEXT:
+ case FileTypeCategory.PDF:
+ // Always supported
+ break;
+
+ default:
+ // For unknown types, check if it's a generally supported file type
+ // This handles edge cases and maintains backward compatibility
+ break;
+ }
+
+ if (isSupported) {
+ supportedFiles.push(file);
+ } else {
+ unsupportedFiles.push(file);
+ modalityReasons[file.name] = reason;
+ }
+ }
+
+ return { supportedFiles, unsupportedFiles, modalityReasons };
+}
+
+/**
+ * Generate a user-friendly error message for unsupported files
+ * @param unsupportedFiles - Array of unsupported files
+ * @param modalityReasons - Reasons why files are unsupported
+ * @param capabilities - The modality capabilities to check against
+ * @returns Formatted error message
+ */
+export function generateModalityErrorMessage(
+ unsupportedFiles: File[],
+ modalityReasons: Record<string, string>,
+ capabilities: ModalityCapabilities
+): string {
+ if (unsupportedFiles.length === 0) return '';
+
+ const { hasVision, hasAudio } = capabilities;
+
+ let message = '';
+
+ if (unsupportedFiles.length === 1) {
+ const file = unsupportedFiles[0];
+ const reason = modalityReasons[file.name];
+ message = `The file "${file.name}" cannot be uploaded: ${reason}.`;
+ } else {
+ const fileNames = unsupportedFiles.map((f) => f.name).join(', ');
+ message = `The following files cannot be uploaded: ${fileNames}.`;
+ }
+
+ // Add helpful information about what is supported
+ const supportedTypes: string[] = ['text files', 'PDFs'];
+ if (hasVision) supportedTypes.push('images');
+ if (hasAudio) supportedTypes.push('audio files');
+
+ message += ` This model supports: ${supportedTypes.join(', ')}.`;
+
+ return message;
+}
+
+/**
+ * Generate file input accept string based on model modalities
+ * @param capabilities - The modality capabilities to check against
+ * @returns Accept string for HTML file input element
+ */