CodeGym /Cursos /ChatGPT Apps /Localización de tools y description: impacto en GPT y exp...

Localización de tools y description: impacto en GPT y experimentos sobre el comportamiento

ChatGPT Apps
Nivel 9 , Lección 3
Disponible

1. Cómo ve el modelo tus herramientas

Empecemos por el hecho de que para el modelo un tool no es «tu bonita función en TypeScript», sino una descripción estructurada del estilo:

  • name: nombre técnico, por ejemplo "search_gifts";
  • description: texto en lenguaje natural que explica cuándo y para qué usar esta herramienta;
  • inputSchema: JSON Schema con campos, cada uno de los cuales también puede tener description, tipo y restricciones.

De forma muy simplificada, el modelo hace algo así (pseudocódigo en la cabeza de GPT):


1. Leer la solicitud del usuario (en cualquier idioma).
2. Leer la lista de tools: name + description + descripciones de argumentos.
3. Para cada tool, estimar si encaja con la tarea.
4. Si se necesita un tool — generar JSON con los argumentos según el esquema.
5. En caso contrario — responder con texto.

Aquí hay dos conclusiones importantes.

En primer lugar, el campo description de una herramienta no es un comentario para desarrolladores, sino la interfaz entre el modelo y tu backend. Si la descripción de la herramienta es ambigua, incompleta o está en un idioma que no coincide con el del usuario, el modelo fallará más a menudo: elegirá un tool incorrecto, rellenará argumentos inadecuados o responderá sin herramientas cuando sí eran necesarias.

En segundo lugar, el description de los campos en JSON Schema es igual de importante que la descripción de la propia herramienta. El modelo realmente lee el description de cada propiedad y a partir de él decide en qué campo poner la «edad», en cuál el «presupuesto» y dónde debería ir el id.

Mini ejemplo para GiftGenius

Tomemos nuestra herramienta search_gifts. En la versión original «solo EN» podría verse así:

// server/tools/searchGifts.ts
export const searchGiftsTool = {
  name: "search_gifts",
  description: "Search for gift ideas based on user preferences.",
  inputSchema: {
    type: "object",
    properties: {
      recipient_age: {
        type: "integer",
        description: "Age of the recipient in years.",
      },
      budget: {
        type: "number",
        description: "Maximum budget in user's currency.",
      },
    },
    required: ["budget"],
  },
};

Si el usuario escribe: «Necesito un regalo para mi madre, tiene 60 años, presupuesto hasta 3000 rublos», el modelo debería:

  1. Entender que search_gifts es la herramienta adecuada.
  2. Entender que «60 años» debe ir en recipient_age, y «3000 rublos» en budget.

Mientras las descripciones estén solo en inglés, GPT aun así se las apaña, pero esto ya le exige una «traducción» interna extra. En múltiples idiomas y con modelos más débiles, esto afecta a la precisión.

2. El problema de las descripciones en inglés en una app multilingüe

En el módulo 9 ya mencionamos de pasada el «mapa de localización» general: widget de UI, catálogos, errores, textos de comercio. Ahora estrechemos el foco y miremos qué ocurre cuando las descripciones de las herramientas están solo en inglés y el usuario se comunica, por ejemplo, en ruso o español: ahí empieza un pequeño caos.

Escenario típico:

  1. Usuario: «Elige un regalo para un amigo informático, presupuesto hasta 50 euros».
  2. El modelo mira la lista de tools y ve descripciones solo en EN.
  3. Si la petición también está en EN, todo bien.
  4. Si la petición está en otro idioma, tiene que:
    • entender primero la petición,
    • emparejarla mentalmente con las descripciones en inglés,
    • elegir la herramienta,
    • y luego extraer los argumentos en JSON.

En modelos potentes esto aún puede funcionar, pero:

  • suele aumentar la proporción de respuestas sin llamar a tools, porque el modelo «cree» que puede arreglárselas solo;
  • sube la probabilidad de errores en los argumentos (especialmente cuando importan la divisa, las unidades de medida o las limitaciones regionales);
  • la lógica de enrutamiento entre varios tools se vuelve menos fiable (herramienta «fuera de lugar»).

Un ejemplo sencillo de error: en el campo budget se espera «en la moneda del usuario», pero la descripción no lo dice en absoluto. El modelo decide que es USD por defecto y envía al backend 50 dólares donde el usuario quería claramente 50 euros.

Y aquí entra en juego la localización de las descripciones.

3. Enfoques de localización: tools separados vs descripciones multilingües

Hay dos enfoques arquitectónicos básicos, y ambos son válidos.

Herramientas separadas para cada idioma

En esta variante, creas varios tools con distintos nombres, cada uno con su «propio» idioma de descripciones.

Para GiftGenius podría verse así:

export const searchGiftsEn = {
  name: "search_gifts_en",
  description: "Search for gift ideas based on user preferences.",
  // ...
};

export const searchGiftsRu = {
  name: "search_gifts_ru",
  description: "Selección de regalos según las preferencias del usuario.",
  // ...
};

Para una ChatGPT App es importante que la lista de tools disponibles dependa de locale. Si locale = "ru-RU", tu servidor MCP debe devolver solo search_gifts_ru. Si locale = "en-US", — solo search_gifts_en.

Ventajas de este enfoque: las descriptions son lo más «limpias» y monolingües posible. Puedes pensar en la App como varias versiones monolingües, cada una con sus propios prompts y descripciones. Es cómodo cuando hay pocos idiomas y los mercados difieren mucho.

Desventajas: duplicación de lógica y complicaciones analíticas. En el backend, probablemente el manejador será el mismo, pero a nivel de MCP/manifiestos ya son dos herramientas distintas. Hay que recordar actualizar las descripciones de ambas en cada cambio.

Insight (datos a 2025-12-01)

Experimentalmente no se detectaron ventajas notables del description en el idioma del usuario/locale. Las herramientas se eligieron con una frecuencia prácticamente igual, independientemente del idioma de la descripción. Si había 2 herramientas con descripciones parecidas (en diferentes idiomas), confundían a ChatGPT.

Además, tu aplicación tendrá que pasar una revisión al registrarse en el Store. Así que recomiendo simplemente escribir todas las tool descriptions y argument descriptions en inglés.

Sin embargo, si en el futuro hay miles de aplicaciones en ChatGPT y crece la competencia por la «elección de herramienta», es posible que la description en la locale del usuario obtenga ventaja. Esperamos la aparición de Tool Search Optimization.

Un solo tool con descripciones multilingües

En la segunda variante dejas un único name (por ejemplo, search_gifts), pero haces multilingües su description y las descripciones de los campos del JSON Schema.

Hay distintos estilos:

  1. Forma breve bilingüe:
    description: "Search gifts for a recipient. / Búsqueda de regalos según las preferencias del destinatario.",
  2. Bloques marcados por idioma:
    description: "[EN] Search for gifts based on user preferences. [RU] Selección de regalos según las preferencias del destinatario.",
  3. Campos separados, unidos en una cadena (menos cómodo):
    description: `EN: ${enDescription} RU: ${ruDescription}`,

Ventajas: un único tool, una única fuente de la verdad (single source of truth), más sencillo desplegar una arquitectura con MCP Gateway: siempre expones la misma interfaz a ChatGPT, sin importar el idioma del usuario.

Desventajas: las descripciones se alargan. Si «mezclas» idiomas sin cuidado, el modelo puede confundirse un poco — especialmente cuando el texto en inglés y el local van intercalados sin marcas claras [EN], [RU].

Para un proyecto didáctico como GiftGenius recomendamos una variante híbrida: dejar las descripciones principalmente en inglés, pero añadir con cuidado una breve aclaración en el idioma local, y llevar toda la «semántica» real (qué idioma usar, cómo dirigirse al usuario) a través de los argumentos (locale) y del system prompt.

4. Localización de JSON Schema: descripciones de campos

Ahora vamos más profundo: a los argumentos de la herramienta.

En JSON Schema cada campo puede (y debe) indicar description. El modelo lee esta cadena cuando genera el JSON para invocar la herramienta.

Para GiftGenius se puede hacer así:

export const searchGiftsTool = {
  name: "search_gifts",
  description:
    "Search gifts based on user preferences (RU: selección de regalos según las preferencias del destinatario).",
  inputSchema: {
    type: "object",
    properties: {
      recipient_age: {
        type: "integer",
        description:
          "Recipient age in years. RU: edad del destinatario (número entero).",
      },
      budget: {
        type: "number",
        description:
          "Maximum budget in user's currency. RU: presupuesto máximo en la moneda del usuario.",
      },
      locale: {
        type: "string",
        description:
          "User locale (e.g. 'en-US', 'ru-RU'). RU: idioma de la interfaz y de las respuestas.",
      },
    },
    required: ["budget", "locale"],
  },
};

Algunas observaciones prácticas.

Primero, los nombres de campos (recipient_age, budget, locale) normalmente se dejan en inglés. Lo que se traduce es el description. Esto es importante para que el formato JSON no cambie entre idiomas y no tengas que mantener dos contratos diferentes.

Segundo, en el description es útil indicar explícitamente la divisa, las unidades de medida y las restricciones importantes. Esto reduce mucho los argumentos «defectuosos».

Tercero, si ya usas MCP Gateway, puedes acordar que reenvíe automáticamente locale en los argumentos de la herramienta, para que el modelo no tenga que proporcionarlo por sí mismo. Incluso así, conviene recordar la descripción de locale: el modelo entiende mejor qué es este parámetro y para qué sirve.

5. Cómo elegir el idioma de las descripciones: estrategias para una app real

La pregunta práctica principal: ¿qué idioma hacer principal para las descripciones y cuándo localizarlas por completo?

Las recomendaciones y la experiencia muestran que los modelos GPT siguen funcionando mejor en contexto inglés, y muchos desarrolladores dejan las descripciones solo en EN. Pero para una app multilingüe esto puede ser una decisión de compromiso.

Veamos varias estrategias.

Solo descripciones EN

La opción más simple: todo en inglés.

Ventajas: una sola base de código, un idioma que mantener, más fácil escribir formulaciones buenas y precisas. El modelo es feliz cuando todo alrededor está en inglés.

Desventajas: para usuarios que escriben en otros idiomas, la calidad de la elección de herramientas y de los argumentos puede ser menor. Especialmente con modelos «perezosos» o herramientas complejas con muchos parámetros.

EN + breve cola local

Enfoque de compromiso: la descripción principal en EN y, al final, un bloque corto en el idioma local que ayude al modelo a emparejar las palabras del usuario con los argumentos.

Ejemplo:

description:
  "Search for gifts based on user preferences. RU: la herramienta selecciona regalos en función de la descripción del destinatario, su edad y presupuesto.",

Para JSON Schema:

description:
  "Age of the recipient in years. RU: edad del destinatario (en años).",

Ventajas: el modelo sigue en un «mundo inglés», pero tiene una pista en el idioma del usuario.

Desventajas: las descripciones se alargan, pero normalmente no es crítico.

Localización completa de descripciones según locale

El enfoque más serio: las descripciones de herramientas y campos cambian según la locale que obtienes de ChatGPT. Para en-US devuelves descripciones puramente en inglés, para ru-RU — puramente en ruso, y para de-DE — en alemán.

Ya no es «un único JSON Schema para siempre», sino un conjunto de esquemas que el MCP/Gateway elige sobre la marcha.

A nivel de MCP se ve así:

function getSearchGiftsToolDescription(locale: string) {
  if (locale.startsWith("ru")) {
    return {
      name: "search_gifts",
      description: "Selección de regalos según las preferencias del destinatario.",
      // ru‑schema...
    };
  }
  return {
    name: "search_gifts",
    description: "Search for gifts based on user preferences.",
    // en‑schema...
  };
}

Ventajas: el modelo ve la interfaz en el mismo idioma en el que escribe el usuario. Máxima comodidad.

Desventajas: mantenimiento y pruebas más complejas. Hay que establecer un proceso que garantice que todas las variantes localizadas de las descripciones se mantengan sincronizadas en significado, y que no olvidarás actualizar, por ejemplo, el esquema en alemán al añadir un campo nuevo en el inglés.

6. Implementación en nuestra aplicación GiftGenius

Pasemos a lo concreto. Haremos en GiftGenius una variante híbrida: una sola herramienta search_gifts, descripciones principalmente en EN pero con aclaraciones en ruso, más el argumento locale.

Supongamos que tienes un servidor MCP en TypeScript que describe los tools al estilo del MCP SDK.

// mcp/tools/searchGifts.ts
import { z } from "zod";

export const searchGiftsInputSchema = z.object({
  recipient_age: z
    .number()
    .int()
    .describe(
      "Age of the recipient in years. RU: edad del destinatario (número entero)."
    ),
  budget: z
    .number()
    .describe(
      "Maximum budget in user's currency. RU: presupuesto máximo en la moneda del usuario."
    ),
  locale: z
    .string()
    .describe(
      "User locale (e.g. 'en-US', 'ru-RU'). RU: idioma de la interfaz y de las respuestas."
    ),
});

export const searchGiftsTool = {
  name: "search_gifts",
  description:
    "Search for gifts based on user preferences (RU: selección de regalos según las preferencias del destinatario).",
  inputSchema: searchGiftsInputSchema,
  // execute(...) ...
};

Importante:

  • locale es obligatorio. Si el widget lo conoce (y lo conocemos desde _meta["openai/locale"]), o bien lo incluirá él mismo en la llamada callTool, o el MCP Gateway lo insertará automáticamente de su lado;
  • las descripciones ya contienen palabras clave en ruso como «edad», «presupuesto», «idioma de la interfaz», por lo que al modelo le resulta más fácil entender qué del texto del usuario va en cada campo.

En el lado del Apps SDK puedes, por ejemplo, tener una función que invoque directamente este tool (si widgetAccessible está activado), pasándole el locale del widget.

// widget/hooks/useSearchGifts.ts
export async function searchGiftsFromWidget(params: {
  recipientAge: number;
  budget: number;
  locale: string;
}) {
  const openai = (window as any).openai;
  const result = await openai.callTool("search_gifts", {
    recipient_age: params.recipientAge,
    budget: params.budget,
    locale: params.locale,
  });
  return result;
}

Este encadenado refuerza la arquitectura: locale llega desde ChatGPT → entra en el tool → este elige el catálogo y los formatos de precios correctos, que luego renderizarás con estilo en el frontend.

7. Experimentos de comportamiento: cómo medir el impacto de la localización

Ahora lo más interesante: ¿cómo saber que la localización de tools y descripciones realmente mejora el comportamiento del modelo y que no gastaste tiempo en balde?

Puedes montar un pequeño «experimento científico» directamente en Dev Mode con GiftGenius.

Dos variantes de la App: base vs localized

Prepara dos configuraciones de tu App:

  • base: descripciones de herramientas y JSON Schema solo en EN;
  • localized: descripciones con EN+RU (o versiones ru completas, si estás listo).

Mantén el resto (catálogos, UI, prompts) igual para no mezclar efectos.

Para simplificar puedes:

  • en Dev Mode (y con más razón en el Store) tener solo la versión localized;
  • y ejecutar base localmente en una rama separada para comparar resultados con un conjunto preparado de solicitudes.

Qué medir

Hay tres métricas clave.

Primera — frecuencia de elecciones correctas de herramientas. Para un conjunto de consultas de prueba en ruso (y/o otro idioma) miras cuántas veces el modelo:

  • decidió llamar a una herramienta cuando era necesario;
  • eligió exactamente search_gifts, y no otro tool.

Segunda — corrección de los argumentos. Comprueba con qué frecuencia el JSON de la llamada se ajusta a lo esperado: campos no confundidos, presupuesto en la divisa correcta, edad claramente entero, locale no perdido.

Tercera — cantidad de llamadas extrañas o sin sentido. Por ejemplo, el modelo invoca search_gifts para la pregunta «¿qué hora es ahora?» o pone recipient_age: 3000 en lugar del presupuesto.

Puedes testear a mano o mediante logs de MCP/Agents — de todos modos los logs te serán útiles en el futuro, así que mejor acostumbrarse a esta analítica desde ya.

Cómo organizar un conjunto de pruebas manual

Puedes crear un pequeño «golden prompt set» para localización:

1. "Necesito un regalo barato de hasta 30 euros para una niña de 10 años, le gusta dibujar."
2. "Elige un regalo para un colega programador, 35 años, presupuesto 100$."
3. "Necesito un regalo para mi abuela por su aniversario, 70 años, presupuesto hasta 5000 rublos."

Y pasarlos por ambas versiones de la App (base y localized), observando:

  • qué tools elige el modelo;
  • qué argumentos rellena;
  • cómo cambia el texto de la respuesta si no se invocó ninguna herramienta.

Truco semiprofesional: puedes hacer un simple envoltorio por script que rote estas solicitudes a través de la API de ChatGPT, pero para el curso basta con el modo manual en Dev Mode. Una categoría aparte de consultas que conviene incluir en ese conjunto son los mensajes mezclados por idioma y combinaciones raras de locale. Les dedicaremos un bloque aparte.

Si desarrollas una aplicación comercial seria y hablamos de millones de dólares, entonces asegúrate de probar estos puntos exactamente para tu aplicación. El módulo 20 está dedicado al trabajo profesional con el «golden prompt set» — estudia este tema.

8. Idiomas mezclados y combinaciones raras de locale

Nada divierte tanto a un desarrollador de LLM como un usuario que escribe en dos idiomas a la vez. Por ejemplo:

"Necesito un regalo for my friend, le gusta Star Wars, budget 100€"

Ya sabemos que el modelo es multilingüe y la mayoría de las veces se apaña. Pero con idiomas mezclados y descripciones «en inglés» la probabilidad de error crece.

Hay varias situaciones típicas.

Primera — el usuario escribe en RU y las descripciones de herramientas están en EN. El modelo puede entender, pero a veces se lía, sobre todo con terminología específica (nombres de categorías, etiquetas raras de campos).

Segunda — locale = "ru-RU", pero el usuario escribe por algún motivo en inglés. ChatGPT te envía señales de que es mejor construir la interfaz en ruso, pero el idioma del texto es EN. Puedes:

  • entregar igualmente descripciones en ruso, considerando locale como la verdad principal;
  • o implementar detección del idioma del mensaje como señal adicional y adaptar las descripciones al idioma real.

Tercera — locale = "en", y el usuario a veces mete palabras en ruso. En este caso, por lo general, las descripciones en inglés funcionan perfectamente.

En la práctica basta con elegir una política clara. Por ejemplo:

  • si locale empieza por "ru" — añades trozos en ruso a las descripciones;
  • si no — las descripciones son solo en inglés.

Una regla clara es útil porque podrás probar a propósito cada rama, sin preguntarte por qué hoy las descripciones estuvieron en un idioma u otro.

9. Documentación, proceso y «idioma canónico»

La localización de descripciones no es un acto puntual, sino un proceso. A los usuarios les encanta cuando aparecen funciones y a ti cuando nada se rompe. Por eso conviene decidir de antemano:

  • qué idioma considerar «canónico» respecto al cual hacer todas las traducciones;
  • dónde guardar las descripciones localizadas;
  • cómo comprobar la consistencia.

Normalmente el idioma canónico es el inglés. Todas las herramientas y campos nuevos se describen primero en EN, pasan revisión y solo entonces se localizan a otros idiomas. En la base de código se puede expresar así:

  • archivo tools.en.json con la descripción completa de name/description/campos;
  • archivos tools.ru.json, tools.de.json como «derivados» para idiomas concretos;
  • un pequeño generador que compile los JSON Schema finales para MCP a partir de estos diccionarios.

En la versión simple puedes apañarte de momento con cadenas en el código, pero estructurarlas de forma que luego sea fácil pasarlas a diccionarios separados.

Es importante recordar que las descripciones también son texto de producto. Deben revisarse con la misma seriedad que los textos de UI: comprobar claridad, ausencia de ambigüedades y de «paja» innecesaria. Especialmente en la variante multilingüe, no queremos que la parte en ruso contradiga a la inglesa.

10. Esquema visual: cómo recorre el idioma el stack

Para ponerlo todo en orden, veamos un esquema simplificado del flujo de la solicitud teniendo en cuenta la localización de las herramientas.

flowchart TD
    U[El usuario escribe en RU] --> C[ChatGPT UI]
    C -->|"_meta.openai/locale = 'ru-RU'"| W[Widget GiftGenius]
    W -->|"locale = 'ru-RU'"| T["Tool descriptions (EN+RU)"]
    T --> M[Modelo GPT]
    M -->|callTool search_gifts| MCP[MCP / Gateway]
    MCP -->|"locale = 'ru-RU'"| B[Backend / catálogos RU]
    B --> MCP --> M2["Modelo GPT (respuesta)"]
    M2 --> C2[ChatGPT UI + widget RU]

Aquí el idioma del usuario y locale determinan:

  • en qué idioma el widget muestra la UI;
  • qué descripciones de herramientas y campos ve el modelo;
  • qué catálogos y divisas elige el backend;
  • cómo se formatean las respuestas (por el modelo y por el widget).

11. Errores típicos al localizar tools y descripciones

Error n.º 1: considerar el campo description «técnico» y no localizarlo en absoluto.
Este enfoque funciona mientras solo tengas usuarios angloparlantes. En cuanto aparecen otros idiomas, el modelo empieza más a menudo a responder sin tools o a pasar argumentos defectuosos según los esquemas. Has traducido la UI, pero la App se comporta «en inglés».

Error n.º 2: cambiar los nombres de los campos en JSON según el idioma.
A veces surge la tentación de hacer agevozrast, budjet, etc. Esto conduce a una pesadilla en el backend: esquemas distintos, formatos distintos, análisis de logs complicado. Mejor dejar el name de los campos estable y localizar solo las descripciones.

Error n.º 3: mezclar idiomas caóticamente en las descripciones.
Frases del tipo «Búsqueda de gifts según las preferencias del user» no ayudan ni al modelo ni a la persona. Si haces descripciones multilingües, separa los bloques de forma explícita: [EN] ... [RU] .... Así el modelo ve la estructura, no una ensalada.

Error n.º 4: no pasar locale a las herramientas.
Aunque localices las descripciones, si no pasas locale al tool (o el MCP Gateway no la propaga), el backend no sabe qué catálogos y formatos usar. Al final el modelo intenta ser «multilingüe», pero el servidor devuelve datos solo para un mercado.

Error n.º 5: traducir automáticamente las descripciones sin revisión.
Parece que puedes pasarlas por un traductor automático y listo. En la práctica, a menudo son inexactas, especialmente con términos y argumentos. Como resultado, el modelo puede interpretar mal el significado de la herramienta o del campo. Mejor tener una buena versión en EN bien pensada y variantes localizadas cuidadas, que veinte idiomas «automáticos».

Error n.º 6: falta de tests/experimentos para diferentes locales.
Si no verificas el comportamiento de la App al menos con un conjunto básico de consultas para cada locale, todo puede «romperse» durante meses, hasta que llegue el primer usuario real con ese idioma. Un pequeño conjunto golden de consultas y pruebas manuales en Dev Mode reducen mucho este riesgo.

Error n.º 7: desincronización entre las descripciones canónicas y las localizadas.
Has añadido un campo nuevo occasion («motivo» del regalo) al esquema en inglés, pero olvidaste actualizar el ruso. Como resultado, en la locale RU el modelo no conoce ese campo y no lo rellena, aunque el backend ya lo espera. Por ejemplo, el servidor intenta filtrar regalos por el motivo, recibe null y muestra una lista demasiado general — en EN todo funciona, y en RU el comportamiento «se rompe» de forma silenciosa. Por eso, cualquier cambio en las descripciones de herramientas debe pasar por un proceso sencillo pero regular: actualizar EN → actualizar locales → pasar pruebas breves.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION