Uso de benchmarks semánticos para crear un agente de texto a consulta que se automejora

@levibkline
INGLÉS03 sept 2026
160K
70
2
6
12

TL;DR

Un análisis técnico profundo sobre la optimización de agentes de texto a consulta mediante el uso de representaciones intermedias, compiladores deterministas y benchmarks semánticos para lograr una latencia de 2 segundos y una precisión del 97%.

Nuestro agente de texto a consulta pasó de 45 segundos en modelos fronterizos a 2 segundos en GLM 5.3 Flash, con la misma precisión a 1/20 del costo.

La mayor parte de nuestro trabajo reciente de IA en Conversion se ha centrado en inteligencia de marketing general.

Los equipos de automatización de marketing realizan una amplia gama de tareas en distintos sistemas: investigar cuentas, construir audiencias, planificar campañas, crear contenido y actuar sobre datos de rendimiento. Hemos estado construyendo agentes que pueden razonar a través de esos flujos de trabajo y usar las mismas herramientas que usaría un especialista en marketing capacitado.

Esos sistemas se benefician de modelos capaces y de propósito general. El trabajo es abierto, y un buen juicio suele ser más importante que completar una tarea rápidamente.

Pero también teníamos un backlog de funciones de IA más pequeñas y enfocadas. Una de ellas eran los filtros en lenguaje natural: permitir que un usuario describa una audiencia en inglés sencillo y convertir esa descripción en un filtro que pudiera inspeccionar y editar en el constructor de declaraciones existente de Conversion. (En Conversion, un filtro se llama declaración).

Al principio, esto parecía una tarea sencilla de generación estructurada. Darle al modelo los campos disponibles, describir el formato de salida y pedirle que produzca JSON. Resultó ser considerablemente más difícil que eso.

Levi - inline image

Declaración compuesta generada en menos de 5 segundos usando GLM 5.3 Flash.

Toma el siguiente ejemplo:

Encuentra contactos que hayan enviado el formulario de demostración al menos una vez en los últimos 30 días y trabajen en una empresa de software con una oportunidad abierta por un valor superior a $50,000.

Esto requiere que el sistema:

  • Encuentre el formulario específico al que el usuario se refiere con "el formulario de demostración"
  • Determine qué campo representa la industria de una empresa
  • Aprenda cómo ese espacio de trabajo representa "software", lo que implica buscar los valores realmente almacenados en ese campo en lugar de adivinar
  • Navegue desde un contacto hasta su empresa y luego hasta las oportunidades de esa empresa
  • Asegure que "abierta" y "más de $50,000" se apliquen a la misma oportunidad
  • Aplique una ventana de eventos relativa

También necesitaba hacer todo esto lo suficientemente rápido como para sentirse como una interfaz de filtro, no como un agente de investigación.

Lo que parecía una pequeña tarea de ingeniería de prompts se había convertido en un problema restringido de texto a consulta. Resolverlo requirió un agente que usa herramientas, una representación intermedia (IR), un compilador determinista y un benchmark semántico.

Ejecutamos ocho modelos en el benchmark resultante, Statement Bench, incluyendo Claude Opus 5, Kimi K3, GLM 5.3 Flash y el lanzamiento de Gemini 3.8 Flash de esta mañana. Los resultados están a continuación.

Dándole herramientas al agente

La mayor parte de la información necesaria para responder a la solicitud anterior es específica del entorno del cliente. Un solo espacio de trabajo puede contener cientos de millones de valores de campo históricos, junto con sus activos y objetos. Por razones obvias, no podíamos poner todo eso en un solo prompt.

Nuestra primera decisión arquitectónica útil fue dejar de tratar el problema como una generación estructurada ordinaria. En cambio, el modelo recibe un pequeño conjunto de herramientas. Puede buscar campos, inspeccionar valores históricos y resolver activos específicos del negocio, como formularios, campañas, correos electrónicos y audiencias. Usa esas herramientas solo cuando la solicitud lo requiere.

Gran parte de esta infraestructura de búsqueda provino de nuestro trabajo reciente de Búsqueda Global, que proporciona búsqueda de texto y semántica sobre todos los registros en Conversion. ¡Planeamos compartir más sobre eso pronto!

El flujo básico se ve así:

text
1Solicitud en lenguaje natural
2 |
3 v
4 Agente que usa herramientas <-----------------+
5 / | \ |
6campos activos relaciones | rechazo con razones
7 \ | / |
8 v |
9 IR restringida |
10 | |
11 v |
12 Validador y compilador --------------------------+
13 |
14 v
15 Declaración de producción

Esto mantiene el contexto inicial pequeño. También hace que los fallos sean mucho más fáciles de entender. Si una declaración es incorrecta, podemos determinar si el agente encontró el activo equivocado, seleccionó el campo incorrecto, malinterpretó una relación, representó la idea correcta incorrectamente o expuso un error en el compilador. Esa distinción luego se volvió importante para nuestro ciclo de evaluación.

Creando un lenguaje más pequeño

El uso de herramientas resolvió el problema del contexto. No resolvió la latencia.

Una lección de los comentarios tempranos: los usuarios toleran mucha menos latencia en una interfaz diseñada para un propósito específico que en un chat.

Esto apunta a una paradoja más amplia. Establecemos expectativas de latencia basadas en lo difícil que nos parece una tarea, no en lo difícil que es para el sistema. Escribir contenido se siente difícil porque vemos el trabajo. Describir un filtro se siente simple porque nuestras mentes resuelven silenciosamente el contexto, las entidades, las relaciones y la intención. Para el modelo, reconstruir esas suposiciones ocultas es la tarea. Cuanto menos trabajo percibe el usuario, menos tiempo le da al sistema para hacerlo.

Basándonos en los comentarios tempranos, establecimos dos objetivos: más del 95 por ciento de precisión y un tiempo de respuesta de alrededor de 5 segundos para consultas comunes.

Conversion tiene un lenguaje de consulta interno expresivo. En nuestras primeras pruebas, usando el formato de producción directamente, solo los modelos más grandes como Claude Opus podían generarlo de manera confiable. Incluso las declaraciones simples tomaban alrededor de 45 segundos.

El constructor visual de declaraciones expone solo un subconjunto del lenguaje completo. Creamos una representación intermedia más pequeña y amigable para el agente para ese subconjunto. Los modelos más pequeños podían producirla usando menos tokens, mientras que un compilador determinista manejaba el formato de producción completo.

Considera la declaración:

El título del trabajo contiene "Director".

La declaración de producción original se ve así:

json
1{
2 "type": "LOGICAL",
3 "version": 1,
4 "logical": {
5 "operator": "OR",
6 "operands": [
7 {
8 "type": "LOGICAL",
9 "version": 1,
10 "logical": {
11 "operator": "AND",
12 "operands": [
13 {
14 "type": "VARIABLE",
15 "version": 1,
16 "variable": {
17 "variableSchemaId": "550e8400-e29b-41d4-a716-446655440000",
18 "where": {
19 "type": "LOGICAL",
20 "version": 1,
21 "logical": {
22 "operator": "AND",
23 "operands": [
24 {
25 "type": "LOGICAL",
26 "version": 1,
27 "logical": {
28 "operator": "CONTAINS",
29 "operands": [
30 {
31 "type": "ATTRIBUTE",
32 "version": 1,
33 "attribute": {
34 "name": "value"
35 }
36 },
37 {
38 "type": "CONSTANT",
39 "version": 1,
40 "constant": {
41 "value": "Director"
42 }
43 }
44 ]
45 }
46 }
47 ]
48 }
49 }
50 }
51 }
52 ]
53 }
54 }
55 ]
56 }
57}

La representación del mismo filtro para el modelo es:

json
1{
2 "field": "550e8400-e29b-41d4-a716-446655440000",
3 "op": "contains",
4 "value": "Director"
5}

La IR ya ha pasado por varias generaciones, y la más reciente fue moldeada al observar cómo los modelos pequeños fallaban en las anteriores. Una gran mejora fue introducir una mejor semántica de mismo registro (algo que la validación de esquemas no puede detectar):

json
1{
2 "related": "OPPORTUNITY",
3 "all": [
4 { "field": "<uuid de etapa>", "op": "equals", "value": "Closed Won" },
5 { "field": "<uuid de monto>", "op": "gt", "value": 100000 }
6 ]
7}

Esta división entre modelo y código nos dio algunas propiedades útiles:

  • Las declaraciones no soportadas son difíciles de expresar
  • La semántica de relaciones de mismo registro es visible
  • Las referencias a campos y relaciones se pueden validar
  • El compilador se puede probar independientemente del modelo
  • Las declaraciones generadas siguen siendo editables en la interfaz de usuario existente

La IR, en última instancia, reduce el trabajo del modelo: el agente resuelve la intención del usuario y produce un plan restringido; el código maneja el formato de producción.

Construyendo un benchmark semántico

Una salida puede ser completamente válida y aún así estar equivocada. Toma esta solicitud:

Contactos en empresas con una oportunidad ganada por un valor superior a $100,000.

Un contacto pertenece a una empresa, y una empresa puede tener muchas oportunidades. Coincidir con este filtro significa navegar por las relaciones (contacto a empresa, empresa a oportunidades) y verificar dos condiciones en el camino: el trato está ganado y el trale vale más de $100,000.

La dificultad es que esas condiciones deben cumplirse para la misma oportunidad. Si se verifican de forma independiente, una empresa con un trato ganado de $20,000 y un trato abierto de $150,000 cumple ambas: una condición coincide con cada una. La validación de esquemas nunca detectará esto.

Una vez que algunos ejemplos como este pasaron, editar el prompt corría el riesgo de revertirlos. Necesitábamos una forma de verificar el significado, no solo la validez, y verificarlo cada vez que algo cambiara.

Construimos Statement Bench en torno a los comportamientos del producto, derivados de patrones de audiencia anonimizados que nuestros clientes habían construido anteriormente. El conjunto ahora contiene 100 casos en quince categorías, como condiciones de campo simples, eventos, ventanas de tiempo relativas y de calendario, relaciones y consultas compuestas.

Cada caso se ejecuta contra un espacio de trabajo sandbox realista. El agente recibe los mismos datos y herramientas que recibe en producción.

El evaluador verifica varias capas:

  1. ¿El agente devolvió una declaración?
  2. ¿La IR cumple con su esquema?
  3. ¿Existen los campos y relaciones referenciados?
  4. ¿Puede la declaración compilarse y pasar la validación de producción?
  5. ¿Representa el significado solicitado?
  6. ¿Cuántos pasos del modelo, llamadas a herramientas, tokens y envíos rechazados requirió?

La quinta es la más interesante, ya que la validez no garantiza la igualdad semántica.

Las comprobaciones semánticas leen la declaración compilada, afirmando cosas como "una condición de oportunidad que lleva tanto la etapa como el monto", "un evento de correo electrónico cuyo tipo es un clic, no una apertura" o "una condición de seminario web en lugar de una de campaña personalizada".

Ejecutando un ciclo de optimización basado en evaluación

El benchmark cambió la forma en que podíamos seguir trabajando en la función. En lugar de pedirle a un agente de codificación que "mejore el prompt" o "implemente una nueva IR", podíamos darle una definición ejecutable de mejora.

El ciclo se veía así:

  1. Ejecutar el benchmark
  2. Agrupar los fallos por su causa subyacente
  3. Inspeccionar la trayectoria de herramientas del agente y la IR enviada
  4. Cambiar el prompt, las herramientas, los validadores o el compilador
  5. Ejecutar el benchmark completo nuevamente
  6. Mantener el cambio solo si mejora el sistema sin introducir regresiones

Los agentes de codificación podían usar el benchmark para comparar modelos, experimentar con la IR, mejorar las descripciones de herramientas y refinar el prompt de forma autónoma. Ejecutar el conjunto completo después de cada cambio también nos evitó sobreajustarnos a fallos individuales, y reservamos otros 50 casos para confirmarlo.

Algunos cambios mejoraron los resultados más que otros:

  • Mover rutas, tipos y estructura al compilador. Nuestra primera IR hacía que el modelo escribiera todas las relaciones explícitamente: contacto a empresa, empresa a oportunidad. Los metadatos del campo ya implican esa ruta, por lo que el compilador ahora la infiere. Hicimos lo mismo con las fechas, la conversión de tipos, la colocación de negaciones y el anidamiento de grupos. Mover reglas al compilador simplificó la IR y redujo los fallos de esquema.
  • Rechazar con explicaciones y correcciones. Cada rechazo de esquema y compilador dice qué escribir en su lugar (cuando está disponible): "gt no se puede negar en este campo; usa lte", "copia el id de campaign_list". Los modelos pequeños convergen en uno o dos reintentos, y el modelo de producción es rechazado en unas pocas solicitudes por cada cien.
  • Estructurar el prompt para modelos pequeños. Reorganizar el prompt no cambió la precisión, pero redujo a la mitad el número de reintentos, lo que mejoró directamente la latencia. Esto se inspiró en las Mejores prácticas de prompting de Anthropic.
  • Usar ejemplos en lugar de prosa. Dos ejemplos adicionales en nuestra referencia de formato resolvieron una clase de errores que los párrafos de explicación no habían logrado, reduciendo los envíos rechazados aproximadamente a la mitad.
  • Dar contexto completo o ninguno. Los modelos recurren a lo que está en contexto antes de llamar a una herramienta. Cuando el contexto incluía un conjunto parcial o sin etiquetar de campos, el modelo usaba el más cercano en lugar de buscar, produciendo declaraciones semánticamente incorrectas. Al reducir el contexto parcial en favor de las llamadas a herramientas, aumentamos las tasas de construcción y redujimos los tokens de entrada en una quinta parte.

La configuración de producción final, GLM 5.3 Flash, completó los 100 casos del benchmark con una latencia mediana de 2.3 segundos y un percentil 95 de 7.1 segundos. Y, 97 de los 100 fueron semánticamente correctos. En comparación con el enfoque original de formato de producción, los filtros simples pasaron de aproximadamente 45 segundos a un poco más de un segundo a 1/20 del costo.

Comparando modelos en Statement Bench

El benchmark también nos dio una forma de comparar modelos en la tarea real.

El 2 de septiembre de 2026, ejecutamos los mismos 100 casos en ocho modelos. Cada modelo recibió el mismo prompt, herramientas, IR, compilador y tiempo de espera de solicitud de 30 segundos.

El enrutamiento del proveedor, el almacenamiento en caché de prompts y la carga de inferencia temporal afectan la latencia.

Modelo

Construcciones válidas

Semánticamente correctas

Latencia P50

Latencia P95

Lectura de caché

Llamadas a herramientas

Envíos rechazados

Costo estimado por 1,000 solicitudes

Claude Opus 5

100/100 (100%)

100/100 (100%)

3.16s

8.53s

91.1%

162

0

$27.51

GLM 5.2

100/100 (100%)

100/100 (100%)

4.38s

13.02s

93.5%

201

5

$14.94

Kimi K3

100/100 (100%)

100/100 (100%)

5.17s

11.84s

34.3%

157

0

$48.51

GLM 5.3 Flash

100/100 (100%)

97/100 (97%)

2.34s

7.07s

92.8%

163

2

$1.33

DeepSeek V4 Pro

96/100 (96%)

96/96 (100%)

5.53s

24.31s

47.8%

172

1

$12.00

Gemini 3.7 Flash

77/100 (77%)

77/77 (100%)

15.14s

30.01s

26.5%

228

1

$18.24

Gemini 3.8 Flash

76/100 (76%)

76/76 (100%)

14.29s

30.01s

35.4%

266

1

$27.44

DeepSeek V4 Flash

56/100 (56%)

55/56 (98%)

6.79s

30.00s

41.5%

100

1

$0.56

Los costos estimados son por cada 1,000 solicitudes intentadas utilizando los tokens de entrada, entrada en caché y salida observados a la tarifa no promocional publicada de cada proveedor el 2 de septiembre de 2026. La entrada en caché se factura a la tarifa de lectura de caché publicada cuando el proveedor publica una, y a la tarifa de entrada completa en caso contrario.

Levi - inline image

Figura 1. Corrección frente a costo. GLM 5.3 Flash alcanza el 97 por ciento a aproximadamente una vigésima parte del costo de Claude Opus 5.

Levi - inline image

Figura 2. Distribución de latencia, mediana y percentil 95, ordenados por P95.

Algunos hallazgos destacaron.

Ni el tamaño del modelo ni el precio predijeron la latencia. El modelo más rápido fue el más pequeño y el más barato. El segundo más rápido fue el más grande y el más caro.

El fallo ha pasado de respuestas incorrectas a respuestas lentas. Seis de los ocho modelos fueron semánticamente correctos en cada declaración que terminaron; las diferencias entre ellos son casi completamente en cuántas solicitudes terminaron dentro del tiempo de espera. En iteraciones tempranas de la IR y los prompts, la mayoría de los modelos más pequeños fallaban el benchmark en el paso de construcción con una precisión semántica inferior al 50%.

Los tokens de razonamiento superan a las llamadas a herramientas. Gemini 3.8 Flash gastó 180,000 de sus 192,000 tokens de salida en razonamiento e hizo 266 llamadas a herramientas; Claude Opus 5 gastó 813 tokens en razonamiento, hizo 162 y terminó todos los casos. Nuestros esfuerzos de Búsqueda Global redujeron cada búsqueda de herramienta al rango de milisegundos, por lo que el costo restante es el turno del modelo entre ellas.

Conclusión

Los modelos son buenos para resolver ambigüedades, el código es bueno para imponer precisión, y la mayoría de nuestros fallos tempranos provinieron de pedirle al modelo que hiciera ambas cosas. Construir este agente fue el trabajo de decidir cuál de los dos debería poseer cada parte. Esperamos que lo mismo sea cierto para texto a SQL y la mayoría de las otras interfaces de lenguaje natural.

Si estás interesado en alguno de estos problemas, ¡contáctanos! Estamos contratando.

Guardar con un clic

Lee artículos virales en profundidad con IA en YouMind

Guarda la fuente, haz preguntas concretas, resume el argumento y convierte un artículo viral en notas reutilizables en un único espacio de trabajo con IA.

Explora YouMind
Para creadores

Convierte tu Markdown en un artículo de 𝕏 impecable

Cuando publicas tus propios textos largos, dar formato en 𝕏 a imágenes, tablas y bloques de código es un fastidio. YouMind convierte un borrador completo en Markdown en un artículo de 𝕏 impecable y listo para publicar.

Prueba Markdown a 𝕏

Más patrones por descifrar

Artículos virales recientes

Explorar más artículos virales