Spaces:
Running
Running
| ts | |
| import { PromptValidation, CharacterWarning } from '@/types' | |
| import { CHARACTER_LIMITS } from './constants' | |
| /** | |
| * Validates user prompt input | |
| * @param prompt - The prompt to validate | |
| * @returns Validation result with errors, warnings, and suggestions | |
| */ | |
| export function validatePrompt(prompt: string): PromptValidation { | |
| const trimmedPrompt = prompt.trim() | |
| const errors: string[] = [] | |
| const warnings: string[] = [] | |
| const suggestions: string[] = [] | |
| // Check for empty or very short prompts | |
| if (trimmedPrompt.length === 0) { | |
| suggestions.push('Gib hier deinen Prompt ein, den du optimieren möchtest...') | |
| } else if (trimmedPrompt.length < CHARACTER_LIMITS.MINIMUM) { | |
| warnings.push('Prompt ist sehr kurz. Mehr Details können zu besseren Ergebnissen führen.') | |
| suggestions.push('Erwäge folgende Elemente hinzuzufügen:') | |
| suggestions.push('• Kontext und Hintergrundinformationen') | |
| suggestions.push('• Spezifische Anforderungen') | |
| suggestions.push('• Gewünschtes Ausgabeformat') | |
| } | |
| // Check for questionable content | |
| if (isQuestionablePrompt(trimmedPrompt)) { | |
| warnings.push('Prompt enthält nur Fragenzeichen oder ist unklar formuliert.') | |
| suggestions.push('Formuliere deine Anfrage als klare Anweisung:') | |
| suggestions.push('• Verwende aktive Sprache ("Erstelle..." statt "Kannst du erstellen...")') | |
| suggestions.push('• Sei spezifisch über das gewünschte Ergebnis') | |
| suggestions.push('• Füge Beispiele oder Referenzen hinzu') | |
| } | |
| // Check character limits | |
| if (trimmedPrompt.length > CHARACTER_LIMITS.INPUT) { | |
| errors.push(`Prompt überschreitet die maximale Länge von ${CHARACTER_LIMITS.INPUT} Zeichen.`) | |
| } else if (trimmedPrompt.length > CHARACTER_LIMITS.WARNING) { | |
| warnings.push(`Prompt ist sehr lang (${trimmedPrompt.length} Zeichen). Einige KIs haben Token-Limits.`) | |
| } | |
| // Check for control characters | |
| if (hasControlCharacters(trimmedPrompt)) { | |
| warnings.push('Prompt enthält Steuerzeichen, die entfernt wurden.') | |
| } | |
| // Check for repetitive content | |
| if (isRepetitiveContent(trimmedPrompt)) { | |
| warnings.push('Prompt scheint repetitive Inhalte zu haben.') | |
| suggestions.push('Entferne Wiederholungen für klarere Anweisungen.') | |
| } | |
| // Check for proper structure for different prompt types | |
| const structureSuggestions = analyzePromptStructure(trimmedPrompt) | |
| suggestions.push(...structureSuggestions) | |
| return { | |
| isValid: errors.length === 0 && trimmedPrompt.length > 0, | |
| errors, | |
| warnings, | |
| suggestions | |
| } | |
| } | |
| /** | |
| * Sanitizes prompt input by removing unwanted characters | |
| * @param prompt - The prompt to sanitize | |
| * @returns Sanitized prompt | |
| */ | |
| export function sanitizePrompt(prompt: string): string { | |
| return prompt | |
| .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '') // Remove control characters | |
| .replace(/\r\n/g, '\n') // Normalize line endings | |
| .replace(/\t/g, ' ') // Replace tabs with spaces | |
| .replace(/[^\S\n]+$/gm, '') // Remove trailing spaces | |
| .trim() | |
| } | |
| /** | |
| * Checks if prompt contains only question marks or similar unclear content | |
| */ | |
| function isQuestionablePrompt(prompt: string): boolean { | |
| const cleaned = prompt.toLowerCase().replace(/[^?]/g, '') | |
| const questionMarkRatio = cleaned.length / Math.max(prompt.length, 1) | |
| return questionMarkRatio > 0.7 || | |
| prompt.length < 10 || | |
| /^\?+$/.test(prompt.trim()) | |
| } | |
| /** | |
| * Checks for control characters in prompt | |
| */ | |
| function hasControlCharacters(prompt: string): boolean { | |
| return /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(prompt) | |
| } | |
| /** | |
| * Checks for repetitive content patterns | |
| */ | |
| function isRepetitiveContent(prompt: string): boolean { | |
| const words = prompt.toLowerCase().split(/\s+/) | |
| const wordCount = words.length | |
| const uniqueWords = new Set(words).size | |
| // If less than 30% unique words, likely repetitive | |
| return wordCount > 10 && (uniqueWords / wordCount) < 0.3 | |
| } | |
| /** | |
| * Analyzes prompt structure and suggests improvements | |
| */ | |
| function analyzePromptStructure(prompt: string): string[] { | |
| const suggestions: string[] = [] | |
| // Check for missing role/context/task structure | |
| const hasRole = /^(du bist|sie sind|you are|act as|role:|als)/i.test(prompt) | |
| const hasContext = /^(kontext|context|background:|background situation:|bei)/i.test(prompt) | |
| const hasTask = /^(aufgabe|task|erstelle|erstellen|create|schreibe|write)/i.test(prompt) | |
| if (!hasRole && !hasContext && !hasTask && prompt.length > 50) { | |
| suggestions.push('Strukturiere deinen Prompt nach dem Schema:') | |
| suggestions.push('1. Rolle (wer bist du?)') | |
| suggestions.push('2. Kontext (worüber?)') | |
| suggestions.push('3. Aufgabe (was ist zu tun?)') | |
| } | |
| // Check for missing output format specification | |
| const hasOutputFormat = /(formatiere|format|ausgabe als|output as|strukturiere)/i.test(prompt) | |
| if (!hasOutputFormat && prompt.length > 100) { | |
| suggestions.push('Spezifiziere das gewünschte Ausgabeformat:') | |
| suggestions.push('• Liste, Tabelle, Absatz, JSON, etc.') | |
| suggestions.push('• Gewünschte Länge (kurz, detailliert, etc.)') | |
| } | |
| return suggestions | |
| } | |
| /** | |
| * Estimates token count from character count | |
| */ | |
| export function estimateTokenCount(characterCount: number): number { | |
| return Math.ceil(characterCount / CHARACTER_LIMITS.TOKEN_ESTIMATE_FACTOR) | |
| } | |
| /** | |
| * Gets character count warnings | |
| */ | |
| export function getCharacterWarnings(count: number): CharacterWarning[] { | |
| const warnings: CharacterWarning[] = [] | |
| if (count === 0) return warnings | |
| if (count < CHARACTER_LIMITS.MINIMUM) { | |
| warnings.push({ | |
| type: 'warning', | |
| message: 'Prompt ist sehr kurz. Erwäge mehr Details hinzuzufügen.' | |
| }) | |
| } | |
| if (count > CHARACTER_LIMITS.WARNING) { | |
| warnings.push({ | |
| type: 'warning', | |
| message: `Achtung: Sehr langer Prompt (${count} Zeichen) könnte Token-Limits überschreiten.`, | |
| threshold: CHARACTER_LIMITS.WARNING | |
| }) | |
| } | |
| if (count > CHARACTER_LIMITS.INPUT) { | |
| warnings.push({ | |
| type: 'error', | |
| message: `Prompt überschreitet die maximale Länge von ${CHARACTER_LIMITS.INPUT} Zeichen.` | |
| }) | |
| } | |
| return warnings | |
| } | |
| </html> |