La necesidad de procesar contenido en múltiples idiomas crece a medida que las organizaciones amplían su presencia internacional. Contratos, documentación técnica, correos de clientes y materiales de marketing son solo algunos ejemplos de contenidos que requieren traducción rápida, precisa y, en muchos casos, confidencial. translategemma-27b-it es un modelo de traducción basado en Google Gemma 3 que permite ejecutar un servicio de traducción de 55 idiomas directamente en infraestructura propia, sin depender de APIs externas.
En este artículo se describe cómo poner en producción este modelo en un entorno local o privado, analizando sus capacidades, opciones de despliegue, optimizaciones y casos de uso prácticos orientados a medianas empresas y departamentos corporativos.
Motivación para una solución de traducción privada
Las empresas que manejan información sensible enfrentan limitaciones importantes cuando usan servicios de traducción en la nube:
- Confidencialidad: documentos legales, técnicos o médicos no siempre pueden salir de la red corporativa.
- Coste operativo: los modelos de pago por palabra o por carácter se vuelven costosos con volúmenes elevados.
- Latencia: una solución local elimina la dependencia de la red y acelera respuestas críticas.
- Personalización: cada sector tiene terminología específica que los traductores genéricos no capturan siempre bien.
Contar con una infraestructura privada resuelve estos problemas y permite adaptar el modelo a las necesidades internas.
Capacidades principales de translategemma-27b-it
Cobertura de 55 idiomas
El modelo soporta traducción entre 55 lenguas principales, incluyendo:
- Asiáticas: chino, japonés, coreano, tailandés, vietnamita.
- Europeas: inglés, español, francés, alemán, italiano, ruso, portugués.
- Otras: árabe, hindi, turco, hebreo, entre otras.
Esta cobertura permite atender la mayor parte de los mercados internacionales con una única plataforma.
Traducción de texto e imágenes
El modelo admite dos modalidades:
- Texto: recibe una cadena de texto y devuelve la traducción.
- Imagen: procesa imágenes de hasta 896×896 píxeles, identifica el texto presente y lo traduce.
La capacidad multimodal resulta útil para documentos escaneados, fotografías de pizarras, capturas de pantalla o manuales ilustrados.
Diseño ligero y adaptable
Entre sus características técnicas destacan:
- Ventana de contexto de 2K tokens, suficiente para la mayoría de documentos cortos y medios.
- Requisitos de hardware moderados para un modelo de 27 mil millones de parámetros.
- Preprocesamiento automático de imágenes antes de la inferencia.
Preparación del entorno de producción
Requisitos de hardware recomendados
| Componente | Mínimo | Recomendado |
|---|---|---|
| CPU | 8 núcleos | 16+ núcleos |
| RAM | 32 GB | 64 GB o más |
| Almacenamiento | SSD 50 GB | SSD 200 GB |
| GPU | Opcional | NVIDIA con 16+ GB VRAM |
Instalación con Ollama
La forma más sencilla de ejecutar el modelo es mediante Ollama, una herramienta diseñada para desplegar modelos locales de forma similar a cómo Docker gestiona contenedores.
1. Instalar Ollama
# Linux / macOS
curl -fsSL https://ollama.ai/install.sh | sh
# Windows: descargar instalador desde https://ollama.ai/download
2. Iniciar el servicio
ollama serve
3. Descargar el modelo
# Versión 27B recomendada para producción
ollama pull translategemma:27b
# Alternativa ligera si el hardware es limitado
ollama pull translategemma:7b
4. Verificar funcionamiento
ollama run translategemma:27b "Hello, how are you?"
Exposición del modelo como servicio
Opción A: API con FastAPI
En lugar de invocar ollama run mediante subprocess, es más robusto consumir la API REST que Ollama expone por defecto en http://localhost:11434.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
servidor = FastAPI()
OLLAMA_URL = "http://localhost:11434/api/generate"
class PeticionTraduccion(BaseModel):
texto: str
origen: str = "auto"
destino: str = "en"
def crear_instruccion(texto: str, origen: str, destino: str) -> str:
return (
f"Traduce el siguiente texto de {origen} a {destino}. "
f"Mantén la terminología técnica y el tono original. "
f"Devuelve únicamente la traducción, sin comentarios adicionales.\n\n"
f"{texto}"
)
@servidor.post("/traducir")
async def traducir(peticion: PeticionTraduccion):
if not peticion.texto.strip():
raise HTTPException(status_code=400, detail="El texto no puede estar vacío")
cuerpo = {
"model": "translategemma:27b",
"prompt": crear_instruccion(peticion.texto, peticion.origen, peticion.destino),
"stream": False
}
async with httpx.AsyncClient() as cliente:
respuesta = await cliente.post(OLLAMA_URL, json=cuerpo, timeout=120.0)
datos = respuesta.json()
return {
"original": peticion.texto,
"traduccion": datos.get("response", "").strip(),
"origen": peticion.origen,
"destino": peticion.destino
}
Opción B: contenedor Docker
Para producción se recomienda empaquetar el servicio en un contenedor. El siguiente Dockerfile instala Ollama, descarga el modelo y levanta la API.
FROM python:3.11-slim
WORKDIR /app
# Instalar dependencias del sistema
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Instalar Ollama
RUN curl -fsSL https://ollama.ai/install.sh | sh
# Descargar modelo durante la construcción
RUN ollama serve & \
sleep 5 && \
ollama pull translategemma:27b
# Dependencias de Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
EXPOSE 8000
CMD ["python", "main.py"]
El archivo requirements.txt incluiría:
fastapi
uvicorn
httpx
Opción C: cliente para integración con aplicaciones existentes
import httpx
from typing import Optional
class ClienteTraduccion:
def __init__(self, url_base: str = "http://localhost:8000"):
self.url_base = url_base
def traducir(self, texto: str, destino: str, origen: str = "auto") -> str:
payload = {
"texto": texto,
"origen": origen,
"destino": destino
}
respuesta = httpx.post(f"{self.url_base}/traducir", json=payload, timeout=60.0)
respuesta.raise_for_status()
return respuesta.json()["traduccion"]
# Ejemplo de uso
if __name__ == "__main__":
cliente = ClienteTraduccion()
resultado = cliente.traducir("Bienvenido a nuestro producto", destino="en")
print(resultado)
Optimización del rendimiento
Procesamiento por lotes
El siguiente ejemplo muestra cómo traducir múltiples frases en paralelo usando un grupo limitado de workers.
from concurrent.futures import ThreadPoolExecutor, as_completed
class TraductorPorLotes:
def __init__(self, cliente, max_workers: int = 4):
self.cliente = cliente
self.max_workers = max_workers
def traducir_lote(self, textos: list[str], destino: str) -> list[str]:
tareas = {}
with ThreadPoolExecutor(max_workers=self.max_workers) as ejecutor:
for texto in textos:
futuro = ejecutor.submit(self.cliente.traducir, texto, destino)
tareas[futuro] = texto
resultados = {}
for futuro in as_completed(tareas):
original = tareas[futuro]
try:
resultados[original] = futuro.result()
except Exception as exc:
resultados[original] = f"[error: {exc}]"
return [resultados[t] for t in textos]
Caché de traducciones
Almacenar en caché los textos ya traducidos reduce costes computacionales y mejora la latencia.
import hashlib
import json
import os
from datetime import datetime, timedelta
class CacheTraducciones:
def __init__(self, ruta: str = "cache.json", horas_vida: int = 48):
self.ruta = ruta
self.vida = timedelta(hours=horas_vida)
self.datos = self._cargar()
def _clave(self, texto: str, origen: str, destino: str) -> str:
mezcla = f"{texto}::{origen}::{destino}"
return hashlib.sha256(mezcla.encode()).hexdigest()
def _cargar(self) -> dict:
if not os.path.exists(self.ruta):
return {}
with open(self.ruta, "r", encoding="utf-8") as f:
return json.load(f)
def guardar(self):
with open(self.ruta, "w", encoding="utf-8") as f:
json.dump(self.datos, f, ensure_ascii=False, indent=2)
def obtener(self, texto: str, origen: str, destino: str) -> str | None:
clave = self._clave(texto, origen, destino)
entrada = self.datos.get(clave)
if not entrada:
return None
fecha = datetime.fromisoformat(entrada["fecha"])
if datetime.now() - fecha < self.vida:
return entrada["resultado"]
return None
def almacenar(self, texto: str, origen: str, destino: str, resultado: str):
clave = self._clave(texto, origen, destino)
self.datos[clave] = {
"origen": origen,
"destino": destino,
"resultado": resultado,
"fecha": datetime.now().isoformat()
}
self.guardar()
Casos de uso prácticos
Comercio electrónico multilingüe
Automatizar la traducción de catálogos de productos a varios idiomas.
class CatalogoMultilingue:
def __init__(self, cliente: ClienteTraduccion, idiomas: list[str]):
self.cliente = cliente
self.idiomas = idiomas
def localizar_producto(self, producto: dict) -> dict:
localizado = {}
for idioma in self.idiomas:
localizado[idioma] = {
"titulo": self.cliente.traducir(producto["titulo"], idioma),
"descripcion": self.cliente.traducir(producto["descripcion"], idioma),
"especificaciones": {
clave: self.cliente.traducir(valor, idioma)
for clave, valor in producto.get("especificaciones", {}).items()
}
}
return localizado
Documentación técnica corporativa
Traducir documentos largos dividiéndolos en bloques manejables.
<class><code>class TraductorDocumentos:
def __init__(self, cliente: ClienteTraduccion, tamano_bloque: int = 5):
self.cliente = cliente
self.tamano_bloque = tamano_bloque
def traducir_archivo(self, ruta: str, destino: str) -> str:
with open(ruta, "r", encoding="utf-8") as f:
contenido = f.read()
bloques = contenido.split("\n\n")
traducidos = []
for i in range(0, len(bloques), self.tamano_bloque):
lote = bloques[i:i + self.tamano_bloque]
traducidos.extend(self.cliente.traducir_lote(lote, destino))
return "\n\n".join(traducidos)
</code></class>
Atención al cliente multilingüe
class SoporteMultilingue:
def __init__(self, cliente: ClienteTraduccion):
self.cliente = cliente
def responder(self, mensaje_cliente: str, idioma_cliente: str, idioma_equipo: str = "es") -> dict:
traduccion_entrada = self.cliente.traducir(
mensaje_cliente, destino=idioma_equipo, origen=idioma_cliente
)
# Aquí se conectaría con el sistema de respuestas del equipo
respuesta_equipo = self._generar_respuesta(traduccion_entrada)
respuesta_cliente = self.cliente.traducir(
respuesta_equipo, destino=idioma_cliente, origen=idioma_equipo
)
return {
"mensaje_original": mensaje_cliente,
"traduccion_interna": traduccion_entrada,
"respuesta traducida": respuesta_cliente
}
def _generar_respuesta(self, mensaje: str) -> str:
return f"Gracias por contactarnos. Hemos recibido: {mensaje}"
Traducción de imágenes
Para traducir imágenes se combina un motor OCR con el modelo de traducción.
class TraductorImagenes:
def __init__(self, ocr, cliente: ClienteTraduccion):
self.ocr = ocr
self.cliente = cliente
def traducir(self, ruta_imagen: str, destino: str) -> str:
texto_extraido = self.ocr.extraer(ruta_imagen)
if not texto_extraido:
return "No se detectó texto en la imagen."
return self.cliente.traducir(texto_extraido, destino=destino)
def traducir_varias(self, rutas: list[str], destino: str) -> dict:
resultados = {}
for ruta in rutas:
try:
resultados[ruta] = {
"estado": "ok",
"traduccion": self.traducir(ruta, destino)
}
except Exception as exc:
resultados[ruta] = {
"estado": "error",
"detalle": str(exc)
}
return resultados
Optimización de la calidad de traducción
Prompts especializados
El diseño del prompt influye notablemente en el resultado. A continuación se muestran plantillas orientadas a distintos dominios.
Traducción técnica
Actúa como traductor técnico especializado. Traduce el siguiente texto de {origen} a {destino} respetando estas reglas:
1. Conserva los términos técnicos de forma consistente.
2. No traduzcas bloques de código, nombres de variables ni comandos.
3. Usa el estilo propio de la documentación técnica en {destino}.
Texto:
{texto}
Localización de marketing
Eres un experto en localización de contenidos de marketing. Traduce de {origen} a {destino} adaptando el mensaje a la cultura del público objetivo, manteniendo el tono persuasivo y la identidad de marca.
Texto:
{texto}
Monitorización de calidad
Es recomendable registrar métricas básicas para detectar degradaciones en la calidad.
import re
class EvaluadorCalidad:
@staticmethod
def metricas_basicas(original: str, traduccion: str) -> dict:
urls_original = set(re.findall(r"https?://\S+", original))
urls_traduccion = set(re.findall(r"https?://\S+", traduccion))
return {
"ratio_longitud": len(traduccion) / max(len(original), 1),
"urls_conservadas": urls_original == urls_traduccion,
"numeros_conservados": re.findall(r"\d+", original) == re.findall(r"\d+", traduccion)
}
Comparativa con servicios tradicionales
| Aspecto | Servicio de traducción externo | translategemma desplegado en privado |
|---|---|---|
| Inversión inicial | Baja | Media (hardware propio) |
| Coste operativo | Por uso continuo | Bajo tras la inicio |
| Privacidad de datos | Depende del proveedor | Control total |
| Latencia | Variable con la red | Muy baja |
| Personalización | Limitada | Total |
Roadmap de implementación
Fase 1: Validación (1-2 semanas)
- Desplegar en un entorno de pruebas.
- Seleccionar 1 o 2 escenarios representativos.
- Evaluar calidad y rendimiento.
Fase 2: Despliegue piloto (2-4 semanas)
- Migrar a producción con uso controlado.
- Integrar con sistemas clave.
- Implementar monitorización y registro de fallos.
Fase 3: Escalado (1-2 meses)
- Ampliar a todos los departamentos relevantes.
- Optimizar prompts y tiempos de respuesta.
- Definir procedimientos de mantenimiento.
Recomendaciones finales
- Comienza por un caso de uso concreto de alto valor.
- Diseña prompts específicos por dominio para mejorar la precisión.
- Activa caché desde el primer día para aprovechar repeticiones.
- Monitoriza la calidad con reglas automatizables antes de ampliar el despliegue.
- Planfiica el hardware en función del volumen esperado y de la necesidad de respuesta en tiempo real.