miércoles 9 / 09 / 2026

タイラーRetourner

Nunca fue el pipeline

En los últimos dieciocho meses he armado cinco pipelines de voz que reciben audio, lo pasan a texto y lo evalúan. Cada vez pensé que lo difícil iba a ser el modelo, pero nunca lo fue. El problema era distinto en cada caso, así que no vi lo que se repetía hasta que comparé los cinco proyectos juntos. De esa comparación salió lo que estoy construyendo ahora.

El modelo cambió tres veces y lo que venía después no lo notó. Es un ingrediente.

Uno: cambiar el modelo

El primero fue para un call center. Partió con una API de voz a texto, pero a mitad de camino pasamos la transcripción a un prompt para un modelo general, después a uno más nuevo y después a otro. La evaluación y el almacenamiento siguieron iguales, y la gente que leía los resultados no notó los cambios.

Había armado todo el pipeline alrededor del modelo, lo que hizo fácil cambiarlo mientras casi todo lo que había construido alrededor seguía funcionando.

Eso no me convenció de inmediato, y sin los cuatro proyectos que vinieron después, probablemente no lo habría hecho. Todavía pensaba que todo lo demás dependía del modelo que eligiera.

Dos: preparar el audio

El segundo cubría solo el procesamiento del audio antes de pagar por tokens. Cortaba silencios de más de 3 segundos, con un umbral conservador para mantener las pausas reales. Detectaba música de espera, pero esperaba 7 segundos antes de clasificarla así: un falso positivo borraba palabras del cliente, mientras que un falso negativo solo costaba unos centavos, así que prefería dejar pasar algo de música. Después venía bajar la frecuencia de muestreo, pasar a mono y mantener el audio sin pérdida.

Esos umbrales importaban mucho, pero los había dejado como constantes en un archivo que solo yo podía cambiar. Una analista de calidad sabe qué significa una pausa larga en una llamada de cobranza mucho mejor que yo, así que esos ajustes deberían quedar a su cargo, con rangos seguros para que no rompa el procesamiento sin querer.

Tres: la red de salud

El tercero fue para una red de salud. Tenía tres jobs: 50 workers procesando audio, 50 procesando texto y un proceso para juntar los resultados. Como nadie había pedido un producto completo, no necesitaba las pantallas, endpoints ni autenticación de los dos primeros. El trabajo de procesamiento era el mismo, pero armar solo la receta nos permitió sacarlo más rápido que cualquiera de los otros.

Cuatro: revisar el resultado

El cuarto procesaba audio de terreno de una eléctrica: transcribir, resumir y sacar 12 atributos. Cada uno venía con un nivel de confianza y la línea de la transcripción que lo respaldaba cuando la había. Como el supervisor podía revisar una respuesta si se veía mal, en vez de tener que aceptar o rechazar los 12 juntos, el equipo de verdad lo usó.

Había dejado el formato de salida para el final. Después de este proyecto quería dejarlo decidido antes de correr nada.

Para entonces más de una versión tenía su propia calculadora de costos agregada tarde, así que el reporte llegaba después de gastar la plata. Quería que el costo por minuto fuera un límite en la receta desde el principio, para que el pipeline no pudiera pasarse del presupuesto.

Cinco: una llamada por teléfono

El quinto corre en tiempo real y habla con una persona por teléfono, donde varias de las decisiones anteriores no sirven. El silencio ayuda a saber a quién le toca hablar, así que no puedes cortarlo. El modelo lento y preciso se demora demasiado, y tienes que resolver los reintentos mientras hay alguien esperando en la línea.

El primer bug serio fue que la voz perdía el acento chileno después de una interrupción. Tres lugares pedían esa voz: la nota, la audición y la llamada. Cambiamos la frase que fija el acento, pero la misma instrucción también decía qué voz usar después de una interrupción, y ahí todavía decía español neutro. O sea, le pedíamos mantener el acento al inicio, pero soltarlo apenas alguien intervenía. El problema no era el modelo, sino que la instrucción decía dos cosas contrarias.

La solución fue decidir quién mandaba sobre qué antes de la llamada. Dejamos la línea del acento en un solo lugar, y la nota, la audición y la llamada la leen de ahí. Ahora un perfil fija qué habla la voz y qué espera el transcriptor, sin que ningún lado tenga que adivinar. Con ese contrato se fue el bug del acento, y también los otros bugs parecidos.

En qué estoy trabajando ahora

Quiero que una app pida un resultado fijando sus límites, presupuesto, latencia, privacidad y calidad, sin tener que decir demasiado sobre cómo llegar a eso. No debería tener que decir «usa este modelo, este endpoint, este prompt», sino poder pedir «necesito este resultado, bajo estas restricciones».

Algo convierte ese pedido en una receta exacta, fija para esa ejecución. Un procesador especializado corre solo esa receta, y devuelve el resultado con un comprobante de los pasos, el costo y la confianza.

Para el cuarto pipeline pediría 12 atributos por grabación, cada uno con su confianza y la evidencia detrás, acordando el costo por minuto antes de correrlo. (Este ejemplo no necesita tiempo real. Eso viene en el quinto). La receta dice qué modelo usar, así que podríamos cambiarlo el próximo mes sin cambiar el trabajo que viene después. Los umbrales van ahí también, con quién se hace cargo de cada uno, y el supervisor recibe el costo y la confianza en el comprobante.

La aplicación dice qué necesita y bajo qué restricciones. No cómo.

Entonces la receta tiene el modelo, los ajustes a cargo de alguien fuera de ingeniería, un presupuesto que no puede pasarse y el formato de salida, diciendo además si cada paso puede correr dos veces. No lo planifiqué así desde el principio: estas necesidades se repetían en los cinco proyectos, y ahora estoy tratando de resolverlas juntas.