Intermedio 16 minSupport

Atención al cliente multilingüe con un LLM local: 6 idiomas sin cloud

Gestionas un servicio de atención al cliente que recibe tickets en francés, inglés, español, alemán, italiano y árabe. Enviar cada mensaje a una API en la nube supone exponer correos electrónicos, números de pedido y, a veces, datos personales a un tercero, además de pagar por token. Esta guía muestra cómo montar un chatbot de atención al cliente multilingüe 100 % local con Qwen 3.8 27B, detección automática del idioma, un tono adaptado a cada cultura e integración directa con Zendesk o Freshdesk mediante webhook.

Por Marie L.·Actualización 2026-08-27·Probado en Windows, macOS y Linux

#¿Por qué un LLM local para soporte multilingüe?

Las API en la nube (GPT-4o, Claude, Gemini) facturan por token y obligan a transferir los mensajes de los clientes fuera de la UE. Para un servicio de soporte B2C que procesa 5.000 tickets al día, la factura mensual supera rápidamente los 1.500 € y cumplir el RGPD se convierte en un ejercicio de acrobacia en cuanto un cliente envía un IBAN o un número de la seguridad social en el cuerpo del ticket.

Un LLM local resuelve los dos problemas a la vez. Qwen 3.8 27B (Alibaba, lanzado el 14 de agosto de 2026) es multilingüe de forma nativa en más de 100 idiomas, maneja las seis lenguas europeas del brief con una calidad que rivaliza con la de los modelos básicos en la nube y funciona en una sola RTX 4090 o un Mac M4 Max. Costo marginal por ticket: cero.

i
¿Por qué Qwen 3.8 27B exactamente?
Es el modelo generalista principal de Alibaba para 2026: ventana de contexto de 262 000 tokens, visión y licencia Apache 2.0 (uso comercial libre). Para soporte, este contexto gigante permite introducir todo el historial de un ticket sin truncarlo, y la calidad multilingüe sigue siendo la mejor de su rango (18 GB en Q4, cabe en una tarjeta de 24 GB). Un ajuste que hay que conocer: configura su esfuerzo de razonamiento en «low». Por defecto, razona demasiado, lo que aumenta la latencia sin necesidad en respuestas de soporte.

#Prerrequisitos

El kit IA Local en la Empresa

Desplegar una IA local en el trabajo: RGPD, AI Act, arquitectura multiusuario, costes, nota para la dirección.

  • Espacio en línea de por vida
  • PDF + archivos
  • Actualizaciones de por vida
GPU con un mínimo de 24 GB de VRAM
RTX 3090, 4090, 5090, o Mac M3/M4 Max con 32 GB de memoria unificada. Qwen 3.8 27B en Q4_K_M ocupa aproximadamente 18 GB.
Ollama instalado
Versión reciente para el soporte nativo de Qwen 3.8 (visión y contexto largo)
Una cuenta de Zendesk o Freshdesk
Con los derechos de administrador para crear una integración webhook y un trigger.
Un endpoint HTTPS accesible
O bien un VPS que actúe como proxy inverso hacia tu Ollama, o bien ngrok / Cloudflare Tunnel para exponer el servidor local.
Python 3.11+
Para la capa de detección de idioma y el enrutador de webhooks. FastAPI + langdetect bastan.

#1. Instalar Qwen 3.8 27B con Ollama

El modelo está disponible directamente en la biblioteca Ollama. Inicia la descarga y un test rápido:

Terminal
ollama pull qwen3.8:27b
ollama run qwen3.8:27b "Réponds en une phrase : qu'est-ce qu'un LLM open-weight ?"

El pull descarga aproximadamente 18 GB. En una RTX 4090, la inferencia funciona a 40–60 tokens/segundo en Q4, suficiente para generar una respuesta de soporte en entre 3 y 5 segundos. Con el esfuerzo de razonamiento en «low», la latencia disminuye aún más.

→
Probar la capacidad multilingüe de inmediato
Haz la misma pregunta en 6 idiomas seguidos con ollama run. Qwen 3.8 no hace transiciones latentes entre idiomas, a diferencia de las generaciones anteriores de Llama, que a veces pasaban al inglés. Es exactamente lo que buscamos para la atención al cliente.

Expón Ollama en la red para que tu webhook pueda acceder a él:

sobrescritura de systemd
sudo systemctl edit ollama
# Ajoutez :
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_KEEP_ALIVE=30m"

sudo systemctl restart ollama

OLLAMA_KEEP_ALIVE=30m mantiene el modelo en VRAM durante 30 minutos después de la última solicitud, lo que evita un cold start en cada ticket durante las horas de baja actividad.

#2. Detección automática del idioma

Antes de enviar un mensaje a Qwen3, se identifica su idioma para elegir el prompt de sistema adecuado. La biblioteca fast-langdetect (basada en fastText de Meta) detecta 176 idiomas en menos de 5 ms por consulta, con una precisión superior al 99 % en mensajes de más de 50 caracteres.

Instalación
pip install fast-langdetect fastapi uvicorn httpx
detector.py
from fast_langdetect import detect

SUPPORTED = {"fr", "en", "es", "de", "it", "ar"}

def detect_language(text: str) -> str:
    text = text.replace("\n", " ").strip()
    if len(text) < 10:
        return "en"  # message trop court, fallback raisonnable
    result = detect(text, low_memory=False)
    lang = result["lang"]
    return lang if lang in SUPPORTED else "en"
!
La trampa de los mensajes mixtos
Un cliente francés que pega un mensaje de error en inglés puede hacer que el detector cambie de idioma. Detecta el idioma solo a partir del primer párrafo (antes de la primera línea en blanco), no del mensaje completo. De lo contrario, responderás en inglés a un cliente francófono.

#3. Prompts de sistema adaptados por idioma y tono

Un buen soporte multilingüe no traduce un prompt francés al inglés: adapta el registro. El francés profesional utiliza el tratamiento de usted, el inglés empresarial sigue siendo más directo, el alemán exige una cortesía formal marcada, el español latinoamericano admite más calidez, el italiano es más expresivo y el árabe requiere fórmulas de cortesía al principio y al final del mensaje.

prompts.py
SYSTEM_PROMPTS = {
    "fr": (
        "Tu es un agent de support client professionnel. "
        "Réponds en français, avec vouvoiement systématique. "
        "Sois concis, empathique, factuel. Ne promets jamais de remboursement "
        "sans validation. Si tu ne sais pas, propose une escalade humaine."
    ),
    "en": (
        "You are a professional customer support agent. "
        "Reply in English, business-friendly tone, direct and concise. "
        "Never commit to a refund without confirmation. "
        "Escalate to a human if uncertain."
    ),
    "es": (
        "Eres un agente de soporte profesional. Responde en español, "
        "trato de usted, tono cálido pero conciso. Nunca prometas reembolsos "
        "sin confirmación. Escala a un humano en caso de duda."
    ),
    "de": (
        "Du bist ein professioneller Kundensupport-Agent. Antworte auf Deutsch "
        "mit Sie-Form, höflich-formell, präzise und sachlich. Versprich nie eine "
        "Rückerstattung ohne Bestätigung. Eskaliere im Zweifel an einen Menschen."
    ),
    "it": (
        "Sei un agente di assistenza clienti professionale. Rispondi in italiano, "
        "forma di cortesia (Lei), tono cordiale e conciso. Mai promettere rimborsi "
        "senza conferma. Scala a un umano in caso di dubbio."
    ),
    "ar": (
        "أنت موظف دعم عملاء محترف. أجب باللغة العربية الفصحى، "
        "بأسلوب رسمي ومهذب يبدأ بتحية وينتهي بعبارة لطيفة. "
        "لا تعد بأي استرداد دون تأكيد. إذا لم تكن متأكدًا، اطلب تدخل موظف بشري."
    ),
}
→
Salvaguardas del negocio en el prompt
Las tres líneas «nunca prometas un reembolso», «escala el caso si no sabes» y «no ofrezcas descuentos» son las únicas que impiden que un LLM cause daños reales en soporte. Inclúyelas en todos los idiomas. El tono cambia; las reglas de negocio, no.

#4. Integrar un webhook de Zendesk o Freshdesk

Zendesk y Freshdesk activan un webhook HTTP POST cada vez que se crea un nuevo ticket. Se expone un punto de acceso FastAPI que detecta el idioma, elige el prompt, llama a Ollama, y devuelve la respuesta a la API de soporte para que sea añadida como comentario interno (el agente humano la valida antes de enviarla).

webhook_server.py
from fastapi import FastAPI, Request
import httpx
from detector import detect_language
from prompts import SYSTEM_PROMPTS

app = FastAPI()
OLLAMA_URL = "http://localhost:11434/api/chat"

@app.post("/webhook/zendesk")
async def handle_ticket(req: Request):
    payload = await req.json()
    ticket_id = payload["ticket"]["id"]
    message = payload["ticket"]["description"]

    lang = detect_language(message)
    system = SYSTEM_PROMPTS[lang]

    async with httpx.AsyncClient(timeout=60) as client:
        r = await client.post(OLLAMA_URL, json={
            "model": "qwen3.8:27b",
            "messages": [
                {"role": "system", "content": system},
                {"role": "user", "content": message},
            ],
            "stream": False,
            "options": {"temperature": 0.3, "num_ctx": 8192},
        })
    draft = r.json()["message"]["content"]

    # Ajoute la réponse en note interne sur le ticket
    await post_internal_note(ticket_id, lang, draft)
    return {"status": "ok", "lang": lang}

La función post_internal_note envía el borrador como comentario privado a través de la API de Zendesk (PUT /api/v2/tickets/{id}.json) o Freshdesk (POST /api/v2/tickets/{id}/notes). El agente humano revisa, ajusta y hace clic en "Enviar". Ahorras aproximadamente un 60 % del tiempo de redacción sin dejar nunca que el bot responda solo.

  1. 01
    Exponer el endpoint
    Cloudflare Tunnel o ngrok apunta a http://localhost:8000. Anota la URL pública HTTPS.
  2. 02
    Crear el destino del webhook
    En Zendesk Admin → Apps y integraciones → Webhooks, crea un destino con tu URL y el método POST.
  3. 03
    Conectar un desencadenador
    En Triggers, condición "Ticket Created", acción "Notify webhook" con un payload JSON que contiene {ticket: {id, description, requester}}.
  4. 04
    Probar con un ticket ficticio
    Crea un ticket en alemán. El endpoint debe recibir el evento, detectar "de" y publicar un borrador en alemán en las notas internas.
  5. 05
    Activar en producción progresivamente
    Empieza con una sola cola (por ejemplo, la cola en español). Mide la calidad durante una semana. Amplía cola por cola.
!
Nunca respondas directamente al cliente
El LLM redacta, el humano valida. Esa es la regla. Un Qwen 3.8 que alucina un número de pedido o inventa una política de reembolso acaba en una reseña de Trustpilot de 1 estrella. Mientras no tengas 6 meses de medición de calidad por idioma, quédate en modo borrador.

#5. Medir la calidad por idioma

Qwen 3.8 no tiene la misma calidad en las seis lenguas. El francés y el inglés son excelentes, el español e italiano muy buenos, el alemán correcto, el árabe variable según el dialecto (el estándar MSA funciona bien, los dialectos magrebíes menos). Hay que medir para controlar.

Tres indicadores que registrar por idioma, desde el primer día:

Tasa de validación sin edición
Porcentaje de borradores que el agente envía tal cual. Es el indicador más sencillo y claro. Meta: 40–60 % a los 3 meses.
Tasa de edición (palabras cambiadas / palabras generadas)
Mide con un diff entre la respuesta final y el borrador. Si en un idioma la tasa de edición supera el 30 %, hay que revisar el prompt.
CSAT por idioma
La encuesta de satisfacción realizada tras la resolución, cruzada con el idioma del ticket. Si el alemán baja a 3,5/5 mientras el francés se mantiene en 4,5, tienes un problema de tono.
i
Caso concreto de ajuste
En un despliegue real en un comercio electrónico francés que se había expandido a Alemania, la tasa de validación en alemán se estancaba en un 18 %. Causa identificada: el prompt traducido literalmente decía "sé empático". En el ámbito empresarial alemán, "empathisch" suena a terapeuta. Sustituido por "verbindlich und lösungsorientiert" (amable y orientado a soluciones) → 45 % en dos semanas.

#Errores comunes

El bot responde en el idioma incorrecto
Es casi siempre un mensaje mixto (firma en inglés debajo de un ticket en francés). Detecta el idioma a partir del primer párrafo, o fuerza el idioma del borrador con una instrucción explícita "Reply in {lang}" además del prompt de sistema.
Latencia > 10 segundos
Comprueba que OLLAMA_KEEP_ALIVE esté activo y que el modelo permanezca en VRAM. ollama ps debe mostrar 100 % GPU. Si no es así, reduce num_ctx a 4096 para los tickets cortos.
Respuestas árabes mal formateadas (RTL)
Qwen3 genera bien el árabe, pero algunas interfaces de soporte no muestran automáticamente el texto de derecha a izquierda (RTL). Añade dir="rtl" lang="ar" al bloque de respuesta en Zendesk/Freshdesk.
Alucinación de promociones inexistentes
Reduce la temperatura a 0.2 y especifica en el prompt «no menciones ninguna promoción ni código de descuento salvo que aparezca en el ticket». Al LLM le gusta ofrecer regalos que no existen.
Webhook que se vuelve a ejecutar varias veces
Zendesk puede reintentar en caso de timeout. Almacena ticket_id en Redis con un TTL de 10 minutos para garantizar la idempotencia; de lo contrario, generarás 3 borradores para el mismo ticket.

#Para ir más allá

Una vez que la base sea estable, dos extensiones aumentan considerablemente la tasa de validación: conectar un RAG local a tu base de conocimientos (preguntas frecuentes, política de devoluciones, condiciones de garantía) para fundamentar las respuestas en hechos, y añadir una capa de fine-tuning con LoRA usando unos pocos miles de tickets resueltos para ajustar el tono de la empresa. Para la puesta en producción en varios puestos de trabajo, el despliegue en una intranet detrás de Nginx cubre los aspectos de red y autenticación.

¿Esta guía te ha ayudado?

¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.