Files
OllaHub/lib/query-validation.ts
Evandro Fonseca Junior 84ea2dec19 feat: add emoji-regex and remove-accents dependencies; enhance chat and setup pages
- Added `emoji-regex` and `remove-accents` packages to improve text processing capabilities.
- Implemented automatic Ollama startup in the chat page for better user experience.
- Enhanced setup page to include GPU selection based on hardware specifications.
- Updated chat input to support real-time validation and improved user feedback.
- Refactored message handling in chat to incorporate new processing features.
2025-11-26 16:12:16 -03:00

178 lines
4.4 KiB
TypeScript

import emojiRegex from 'emoji-regex';
import { normalizeText } from './text-normalization';
export interface ValidationOptions {
minLength?: number;
maxLength?: number;
irrelevantPatterns?: string[];
allowEmojis?: boolean;
}
export interface ValidationResult {
isValid: boolean;
errors: string[];
warnings: string[];
normalizedLength: number;
}
const DEFAULT_OPTIONS: Required<ValidationOptions> = {
minLength: 3,
maxLength: 2000,
irrelevantPatterns: [
'oi',
'olá',
'ola',
'teste',
'test',
'hello',
'hi',
'hey',
'ok',
'okay',
'sim',
'não',
'nao',
'yes',
'no',
],
allowEmojis: false,
};
/**
* Valida uma query do usuário
*
* @param text - Texto a ser validado
* @param options - Opções de validação
* @returns Resultado da validação
*/
export function validateQuery(
text: string,
options: ValidationOptions = {}
): ValidationResult {
const opts = { ...DEFAULT_OPTIONS, ...options };
const errors: string[] = [];
const warnings: string[] = [];
let normalizedLength = 0;
// Verificar se o texto existe e é string
if (!text || typeof text !== 'string') {
return {
isValid: false,
errors: ['Texto vazio ou inválido'],
warnings: [],
normalizedLength: 0,
};
}
// Normalizar texto para validação
const normalized = normalizeText(text);
normalizedLength = normalized.length;
// Verificar comprimento mínimo
if (normalizedLength < opts.minLength) {
errors.push(
`Texto muito curto. Mínimo de ${opts.minLength} caracteres necessário.`
);
}
// Verificar comprimento máximo
if (normalizedLength > opts.maxLength) {
errors.push(
`Texto muito longo. Máximo de ${opts.maxLength} caracteres permitido.`
);
}
// Verificar se é apenas espaços em branco após normalização
if (normalized.trim().length === 0) {
errors.push('Texto contém apenas espaços em branco ou caracteres especiais.');
}
// Verificar se contém apenas emojis
if (!opts.allowEmojis) {
const emojiPattern = emojiRegex();
const textWithoutEmojis = text.replace(emojiPattern, '').trim();
if (textWithoutEmojis.length === 0 && text.trim().length > 0) {
errors.push('Texto contém apenas emojis.');
}
}
// Verificar se contém apenas pontuação
const textWithoutPunctuation = normalized.replace(/[.,?!:;]/g, '').trim();
if (textWithoutPunctuation.length === 0 && normalized.length > 0) {
errors.push('Texto contém apenas pontuação.');
}
// Verificar padrões irrelevantes
if (isIrrelevantQuery(normalized, opts.irrelevantPatterns)) {
warnings.push(
'Pergunta pode ser irrelevante ou muito simples. Considere ser mais específico.'
);
}
return {
isValid: errors.length === 0,
errors,
warnings,
normalizedLength,
};
}
/**
* Verifica se uma query é irrelevante baseado em padrões
*
* @param text - Texto normalizado a ser verificado
* @param patterns - Lista de padrões irrelevantes
* @returns true se a query for irrelevante
*/
export function isIrrelevantQuery(
text: string,
patterns: string[] = DEFAULT_OPTIONS.irrelevantPatterns
): boolean {
if (!text || typeof text !== 'string') {
return true;
}
const normalized = normalizeText(text);
const normalizedPatterns = patterns.map((p) => normalizeText(p));
// Verificar se o texto normalizado está exatamente na lista de padrões
if (normalizedPatterns.includes(normalized)) {
return true;
}
// Verificar se o texto começa com um padrão irrelevante seguido apenas de pontuação/espaços
for (const pattern of normalizedPatterns) {
const regex = new RegExp(`^${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s.,?!]*$`, 'i');
if (regex.test(normalized)) {
return true;
}
}
return false;
}
/**
* Validação rápida (apenas comprimento)
* Útil para validação em tempo real no input
*
* @param text - Texto a ser validado
* @param minLength - Comprimento mínimo
* @param maxLength - Comprimento máximo
* @returns true se válido
*/
export function quickValidate(
text: string,
minLength: number = DEFAULT_OPTIONS.minLength,
maxLength: number = DEFAULT_OPTIONS.maxLength
): boolean {
if (!text || typeof text !== 'string') {
return false;
}
const normalized = normalizeText(text);
return (
normalized.length >= minLength && normalized.length <= maxLength
);
}