Guarda de seguridad para modelos de lenguaje grandes en la práctica: qué funciona realmente
Controla el riesgo, no solo el modelo.
Los LLMs son impredecibles. Hallucinan, filtran datos, generan contenido dañino o rechazan solicitudes legítimas. Los guardrails (mecanismos de contención) limitan el comportamiento del modelo sin sacrificar capacidad.
La clave es saber qué guardrails importan y cuáles son solo ruido.
Los guardrails no se tratan de controlar el modelo. Se tratan de controlar el riesgo.

Validación de entrada
El guardrail más importante. Una entrada mala produce una salida mala, y una entrada mala también puede inyectar prompts en tu sistema.
Estrategia 1: Sanitización de Prompts
Sanitiza patrones peligrosos temprano:
import re
class PromptSanitizer:
def __init__(self):
self.dangerous_patterns = [
r"ignore\s+previous\s+instructions",
r"system\s+prompt",
r"you\s+are\s+now\s+free",
r"break\s+out\s+of",
]
def sanitize(self, prompt: str) -> str:
for pattern in self.dangerous_patterns:
prompt = re.sub(pattern, "[REDACTED]", prompt, flags=re.IGNORECASE)
return prompt
Esto no es a prueba de balas. Las entradas adversarias son creativas. Pero atrapa las obvias, y las obvias son las más comunes.
Estrategia 2: Límites de Longitud de Entrada
Los límites de longitud previenen el desperdicio de tokens y los tiempos de espera (timeouts):
class InputValidator:
def __init__(self, max_length: int = 10000):
self.max_length = max_length
def validate(self, prompt: str) -> tuple[bool, str]:
if len(prompt) > self.max_length:
return False, f"Input too long: {len(prompt)} > {self.max_length}"
return True, "OK"
Estrategia 3: Filtrado de Contenido
El filtrado de contenido bloquea violaciones de política. Los patrones aquí dependen de tu dominio:
class ContentFilter:
def __init__(self):
self.blocked_topics = [
"violence", "hate speech", "self-harm",
"sexual content", "illegal activities",
]
def filter(self, prompt: str) -> tuple[bool, str]:
prompt_lower = prompt.lower()
for topic in self.blocked_topics:
if topic in prompt_lower:
return False, f"Blocked: {topic}"
return True, "OK"
La coincidencia de cadenas simple es rápida pero imprecisa. Para producción, usa un modelo clasificador — incluso uno pequeño como qwen3-1.7b — para detectar violaciones de política. Es más preciso y más difícil de eludir.
Filtrado de salida
La salida del modelo también necesita revisión. Estructura, contenido y hechos.
Estrategia 1: Validación de Respuesta
Valida la estructura primero. Si esperas JSON, verifica el JSON:
class ResponseValidator:
def __init__(self):
self.required_fields = ["answer", "confidence"]
def validate(self, response: dict) -> tuple[bool, str]:
for field in self.required_fields:
if field not in response:
return False, f"Missing field: {field}"
return True, "OK"
Estrategia 2: Filtrado de Contenido
Filtra contenido dañino:
class OutputFilter:
def __init__(self):
self.blocked_patterns = [
r"kill\s+someone",
r"bomb\s+recipe",
r"hate\s+speech",
r"self-harm",
]
def filter(self, response: str) -> tuple[bool, str]:
for pattern in self.blocked_patterns:
if re.search(pattern, response, re.IGNORECASE):
return False, f"Blocked: {pattern}"
return True, "OK"
Estrategia 3: Verificación de Hechos
La verificación de hechos es más difícil. No puedes validar cada afirmación, así que elige las que importan:
class FactChecker:
def __init__(self):
self.known_facts = {
"capital of france": "Paris",
"population of usa": "330 million",
"speed of light": "299,792,458 m/s",
}
def check(self, claim: str) -> tuple[bool, str]:
claim_lower = claim.lower()
for fact, truth in self.known_facts.items():
if fact in claim_lower and truth not in claim_lower:
return False, f"Fact check failed: {fact}"
return True, "OK"
Para una verificación de hechos real, necesitas una tubería de recuperación (retrieval pipeline). Verifica las afirmaciones contra una base de conocimientos, no contra un diccionario codificado.
Mecanismos de seguridad
Estrategia 1: Limitación de Tasa (Rate Limiting)
La limitación de tasa previene el abuso:
import time
from collections import deque
class RateLimiter:
def __init__(self, max_requests: int = 10, window: int = 60):
self.max_requests = max_requests
self.window = window
self.requests = deque()
def allow(self) -> bool:
now = time.time()
while self.requests and self.requests[0] < now - self.window:
self.requests.popleft()
if len(self.requests) >= self.max_requests:
return False
self.requests.append(now)
return True
Estrategia 2: Presupuesto de Tokens
El presupuesto de tokens limita los costos por solicitud:
class TokenBudget:
def __init__(self, max_tokens: int = 1000):
self.max_tokens = max_tokens
def validate(self, response: str) -> tuple[bool, str]:
token_count = len(response.split())
if token_count > self.max_tokens:
return False, f"Token limit exceeded: {token_count} > {self.max_tokens}"
return True, "OK"
Estrategia 3: Gestión de la Ventana de Contexto
La gestión de la ventana de contexto previene el desbordamiento:
class ContextManager:
def __init__(self, max_context: int = 4096):
self.max_context = max_context
self.context = []
def add(self, message: str):
self.context.append(message)
self.trim()
def trim(self):
while len(" ".join(self.context)) > self.max_context:
self.context.pop(0)
El recorte de ventana deslizante es simple pero pierde el contexto inicial. Enfoques mejores utilizan resumen o compresión basada en atención, pero estos añaden latencia.
Cumplimiento
Los sistemas empresariales necesitan guardrails de cumplimiento. Dos que importan más:
Patrón 1: Residencia de Datos
Residencia de datos: asegúrate de que los datos permanezcan dentro de los límites geográficos requeridos:
class DataResidency:
def __init__(self, allowed_regions: list[str]):
self.allowed_regions = allowed_regions
def validate(self, region: str) -> tuple[bool, str]:
if region not in self.allowed_regions:
return False, f"Region not allowed: {region}"
return True, "OK"
Patrón 2: Registro de Auditoría
Registro de auditoría: registra todas las interacciones del modelo:
import json
from datetime import datetime
class AuditLogger:
def __init__(self, log_file: str = "audit.log"):
self.log_file = log_file
def log(self, request: dict, response: dict):
entry = {
"timestamp": datetime.now().isoformat(),
"request": request,
"response": response,
}
with open(self.log_file, "a") as f:
f.write(json.dumps(entry) + "\n")
Los registros de auditoría son críticos para la depuración y el cumplimiento. Hazlos estructurados, de solo adición (append-only) y almacenados de forma segura.
Poniéndolo todo junto
Patrón 1: Guardrails Simples
Una tubería de guardrails simple:
class SimpleGuardrails:
def __init__(self):
self.input_validator = InputValidator(max_length=10000)
self.output_filter = OutputFilter()
def process(self, prompt: str) -> str:
valid, message = self.input_validator.validate(prompt)
if not valid:
return f"Error: {message}"
response = self.call_model(prompt)
valid, message = self.output_filter.filter(response)
if not valid:
return f"Error: {message}"
return response
Patrón 2: Guardrails Avanzados
Los guardrails avanzados añaden sanitización, limitación de tasa y presupuestos de tokens:
class AdvancedGuardrails:
def __init__(self):
self.sanitizer = PromptSanitizer()
self.input_validator = InputValidator(max_length=10000)
self.content_filter = ContentFilter()
self.output_filter = OutputFilter()
self.rate_limiter = RateLimiter(max_requests=10)
self.token_budget = TokenBudget(max_tokens=1000)
def process(self, prompt: str) -> str:
prompt = self.sanitizer.sanitize(prompt)
valid, message = self.input_validator.validate(prompt)
if not valid:
return f"Error: {message}"
valid, message = self.content_filter.filter(prompt)
if not valid:
return f"Error: {message}"
if not self.rate_limiter.allow():
return "Error: Rate limit exceeded"
response = self.call_model(prompt)
valid, message = self.output_filter.filter(response)
if not valid:
return f"Error: {message}"
valid, message = self.token_budget.validate(response)
if not valid:
return f"Error: {message}"
return response
Cuando importan los guardrails
Los guardrails importan cuando estás construyendo sistemas orientados al usuario, manejando datos sensibles o ejecutando en producción. También importan cuando tienes requisitos de cumplimiento — GDPR, HIPAA, SOC 2.
No importan cuando estás prototipando, usando modelos solo para herramientas internas o no manejando datos sensibles. Omítelos hasta que los necesites.
El compromiso es siempre capacidad versus seguridad. Más guardrails significan menos fallos, pero también menos capacidades. Encuentra el equilibrio que funcione para tu sistema.
Los guardrails cubren la conversación del modelo, pero se detienen en el punto donde un agente llama a una herramienta o transfiere trabajo a otro agente. Una vez que despliegas herramientas MCP o agentes A2A, también necesitas seguridad de protocolo: identidad, autorización con alcance, límites de delegación y registros de auditoría para quién puede actuar en nombre de quién. Esta capa se cubre en Seguridad de Agentes A2A y MCP: Identidad, Delegación y Registros de Auditoría.
Compromisos
| Estrategia | Seguridad | Capacidad | Latencia |
|---|---|---|---|
| Sin guardrails | Más baja | Más alta | Más baja |
| Validación de entrada | Alta | Media | Baja |
| Filtrado de salida | Alta | Media | Baja |
| Mecanismos de seguridad | Más alta | Más baja | Más alta |
| Cumplimiento | Más alta | Más baja | Más alta |
Relacionado
- Estrategias de Enrutamiento de Modelos — enrutamiento basado en capacidad, consciente del costo y de la latencia
- Optimización de Costos para Sistemas LLM — presupuesto de tokens, modelos de respaldo, caché
- Diseño de Sistemas Multi-Modelo — arquitectura para múltiples modelos
- Arquitectura LLM — pilar de diseño de sistemas: enrutamiento, costo, guardrails y orquestación