- Truss operó durante los últimos 6 meses varias funcionalidades centradas en LLM y procesó más de 500 millones de tokens con modelos de OpenAI; resume los límites con los que se toparon en la práctica en resumen, análisis y extracción de texto B2B
- Los prompts no fueron más estables por incluir muchas instrucciones detalladas; en casos donde GPT ya conocía el sentido común, las instrucciones más breves y menos específicas produjeron mejores resultados
- Sin Langchain, JSON mode, function calling ni assistants, operaron varias funciones usando solo la API
chaty una función de extracción de JSON; el código central era básicamente una función de 40 líneas, más manejo de errores y recorte automático - GPT era débil para manejar hipótesis nulas como “si no existe, devuelve un valor vacío” y para salidas largas; más allá de la ventana de entrada de 128k de GPT-4, la salida seguía quedándose en torno a 4k
- RAG y las bases de datos vectoriales no encajaron bien con las tareas acotadas de extracción de texto de Truss; el análisis, resumen y extracción con todo el contexto son confiables, pero los problemas crecen cuando la entrada está vacía o no hay información relevante
Alcance de uso y supuestos
- Durante los últimos 6 meses, Truss lanzó algunas funcionalidades centradas en LLM, y el uso estimado supera ligeramente los 500 millones de tokens
- Los modelos usados son de la familia OpenAI, y el consumo de tokens fue 85% GPT-4 y 15% GPT-3.5
- Los datos tratados son solo texto; no se incluyen funciones no textuales como
gpt-4-vision, Sora o Whisper - El contexto del producto es B2B, y las tareas principales son resumen, análisis y extracción
- 500 millones de tokens equivalen a aproximadamente 750 mil páginas de texto
Los prompts pueden mejorar cuando son menos específicos
- Cuando se agregaban en exceso listas e instrucciones exactas sobre conocimiento general que GPT ya conoce, los resultados podían empeorar
- Un pipeline debía clasificar si un bloque de texto estaba relacionado con alguno de los 50 estados de EE. UU. o con el gobierno federal
- El prompt inicial incluía en formato JSON una lista de IDs de los 50 estados y
federalen el campolocality_id, para que eligiera uno - Este enfoque funcionaba en torno a más del 98% de las veces, pero había suficientes fallas como para requerir más investigación
- El prompt inicial incluía en formato JSON una lista de IDs de los 50 estados y
- Otro campo,
name, devolvía de forma estable el nombre completo del estado correcto aunque no se le pidiera explícitamente- Después, al cambiar a un método que buscaba el estado a partir de la cadena que aparecía en
name, funcionó bien
- Después, al cambiar a un método que buscaba el estado a partir de la cadena que aparecía en
- Un mejor enfoque fue un prompt que dejaba el trabajo al sentido común, como “ya conoces los 50 estados; devuelve el nombre completo del estado correspondiente o Federal”
- También hubo observaciones adicionales
- Las fallas aparecían con más frecuencia en estados que empiezan con M, como Maryland, Maine, Massachusetts y Michigan
- Al hacer que eligiera un ID de una lista, un JSON legible con cada estado en una línea confundía menos que una lista corrida separada por comas
La API y las abstracciones se mantuvieron simples
- En este caso, Langchain fue casi una abstracción prematura, y después de millones de tokens y 3 o 4 funcionalidades variadas en producción, en el archivo
openai_servicesolo quedó una función de 40 líneas - En la práctica, la única API utilizada fue
chat- Siempre se extrae JSON
- No hicieron falta JSON mode, function calling ni assistants
- Tampoco se usó system prompt
- Cuando se lanzó
gpt-4-turbo, solo se cambió una cadena en el codebase
- La mayor parte de la función se encarga de manejar errores de la API de OpenAI, como errores 500 o cierres de socket
- Estos errores han mejorado, y no los consideran sorprendentes dada la carga de OpenAI
- El límite de longitud de contexto se maneja con recorte automático propio
- Si la longitud de la cadena es mayor que
model_context_size * 3, se recorta - Cuando hay muchísimos puntos o números, la proporción de tokens puede ser menor que 1 token por cada 3 caracteres y fallar
- Si aparece
context_length_exceeded, se vuelve a recortar con el criteriomodel_context_size * 3 / 1.3y se reintenta
- Si la longitud de la cadena es mayor que
Es difícil sobreestimar la UX de streaming
- Usar la API de streaming para reducir la latencia y mostrar al usuario caracteres que aparecen a velocidad variable al principio parecía una broma
- En la práctica, los usuarios recibieron muy positivamente la indicación de “escritura” a velocidad variable
- Esta experiencia se sintió como un momento equivalente al mouse y al cursor en la UX de la IA
Los resultados vacíos y las salidas largas son puntos débiles
- “Si no lo encuentras, devuelve una salida vacía” fue una de las frases de prompt más propensas a errores
- En realidad, no significaba que no debía imprimir nada, sino que debía devolver una representación de valor vacío como
{value: ""} - El problema no era una falla del límite de salida, sino más bien la dificultad de determinar la hipótesis nula
- En realidad, no significaba que no debía imprimir nada, sino que debía devolver una representación de valor vacío como
- GPT a veces elegía alucinar cuando debía devolver un valor vacío y, al contrario, otras veces perdía confianza y devolvía valores vacíos con demasiada frecuencia
- Cuando había un bug por el que el bloque de texto podía estar vacío, las alucinaciones se disparaban
- Como ejemplos, aparecieron nombres falsos de panaderías como Sunshine Bakery, Golden Grain Bakery y Bliss Bakery
- La solución fue no enviar directamente el prompt si no había texto
- GPT-4 puede tener una ventana de 128k tokens para la entrada, pero la ventana de salida sigue estando alrededor de 4k
- La expresión “context window” hace que se confundan entrada y salida
- Al pedirle que devuelva una lista de objetos JSON, incluso con objetos simples era difícil superar los 10 elementos
- Estiman que al pedir 15 elementos solo tenía éxito alrededor del 15% de las veces
- Incluso cuando se detenía cerca de los 10 elementos, la salida era de apenas unos 700 a 800 tokens
- Se puede sortear el límite de salida pidiendo un elemento a la vez y reenviando los resultados anteriores, pero eso se convierte en una especie de teléfono descompuesto con GPT y lleva a lidiar con herramientas como Langchain
RAG y las bases de datos vectoriales no encajan bien con este caso de uso
- Las bases de datos vectoriales y RAG/embeddings fueron mayormente inútiles en el caso de Truss
- Consideran que las bases de datos vectoriales y RAG encajan mejor con la búsqueda, y más concretamente con búsqueda real como Google o Bing
- El problema central es el criterio de relevancia
- No hay un punto de corte claro para la relevancia
- Puede haber soluciones como rerank de Cohere o heurísticas propias, pero no son estables
- Existe el riesgo de contaminar los resultados con elementos irrelevantes, o de ser demasiado conservador y perder resultados importantes
- Guardar vectores en una base de datos especializada y propietaria, separada de los datos generales, también implica una gran pérdida
- Si no se está a la escala de Google o Bing, consideran que la pérdida de contexto no justifica el trade-off
- En la búsqueda dentro de apps de negocio, muchas veces los usuarios son expertos del dominio
- Consideran que no les gusta la búsqueda semántica que infiere y devuelve significados que el usuario no escribió directamente
- En la mayoría de los casos de búsqueda, puede ser mejor usar un LLM con un prompt de completion común para convertir la consulta del usuario en faceted search, consultas complejas o SQL
- Eso no es RAG
Las alucinaciones disminuyen mucho cuando hay suficiente contexto
- La mayoría de los casos de uso de Truss tienen la forma de “darle un bloque de texto y extraer algo de ahí”
- Si se le pide el nombre de una empresa mencionada en el texto, GPT por lo general no devuelve una empresa al azar
- Pero si no hay ninguna empresa en el texto, reaparece el problema de la hipótesis nula
- También con código, cuando GPT reescribe un bloque de código proporcionado, no suele alucinar en el sentido de inventar variables o introducir errores tipográficos aleatorios en medio del código
- Sin embargo, si se le pide que cree algo, puede inventar la existencia de una función de la biblioteca estándar
- Esto también parece más cercano al problema de no poder decir “no sé”
- En tareas donde se proporciona todo el contexto y se le pide analizar, resumir o extraer, fue muy confiable
- Es una estructura cercana a: si se ingresan buenos datos, se obtienen buenas respuestas con tokens de GPT
Opinión sobre el futuro
- Consideran que con los transformers actuales, datos de internet y acceso a infraestructura de decenas de miles de millones de dólares no se llegará a la AGI
- GPT-4 no es marketing, sino una tecnología 100% útil, y todavía lo ven en una etapa similar a los inicios de internet
- No es una tecnología que vaya a despedir a todo el mundo
- Tiene un gran efecto al bajar la barrera de entrada al ML/AI, a la que antes solo Google podía acceder
- No hicieron pruebas A/B rigurosas con Claude, Gemini y otros
- Al probarlos en programación cotidiana, sintieron que no estaban cerca de GPT-4 en las sutilezas de intuir la intención
- Consideran que no hace falta seguir todo el flujo de LLM/AI
- A la luz de The Bitter Lesson, si las mejoras generales de los modelos son más importantes que las mejoras especializadas, entonces basta con prestar atención a si sale GPT-5
- Salvo áreas separadas como Sora, consideran que la mayoría de los lanzamientos intermedios de OpenAI son más bien ruido
- Es probable que GPT-5 sea una mejora incremental más que algo que lo cambie todo
- Al pasar de GPT-3 a GPT-3.5, se esperaba una mejora superlineal, donde duplicar la intensidad de entrenamiento mejorara el rendimiento 2.2 veces
- En la práctica, parece más una mejora logarítmica, y ven una situación donde la velocidad de tokens y el costo por token crecen exponencialmente para lograr mejoras incrementales
- GPT-4 puede ser el punto óptimo para el conjunto de tareas actual
- Estaban dispuestos a pagar 20 veces más por GPT-4 frente a GPT-3.5, pero no creen que vayan a pagar 20 veces más por token para pasar de GPT-4 a GPT-5
- GPT-5 podría romper esa expectativa, o podría ser algo como pasar de un iPhone 4 a un iPhone 5
1 comentarios
Opiniones de Hacker News
El equipo en el que estoy procesa más de 5 mil millones de tokens al mes y la cifra sigue creciendo; hay algunas cosas que aprendimos.
Primero, hay mucha abstracción prematura. Herramientas como Langchain quizá sean útiles algún día, pero al final un prompt no es más que una llamada a una API, y es más fácil tratar las llamadas a LLM con código estándar como llamadas a API inestables, en vez de tratarlas como algo especial.
Segundo, las alucinaciones son sin duda un gran problema. La sumarización resulta bastante robusta en las pruebas, pero el razonamiento es realmente difícil, y los modelos de acción que toman la entrada del usuario y hacen que el LLM decida el siguiente paso son especialmente difíciles en cuanto a entender el contexto y lograr que diga “no estoy seguro”. Aun así, el solo hecho de que esto sea posible cambia las reglas del juego.
Tercero, estoy un poco más cerca que el autor de pensar que “cambia las reglas del juego”, pero no creo que sea el fin del mundo. Algunos trabajos se verán muy afectados, y puede que vengan unos años difíciles con bots manipulando la opinión en plataformas. En general, más que un avance tipo internet, parece un amplificador de capacidades.
Personalmente, me recuerda al cambio de DevOps en los años 2000. Ya no necesitas un enorme equipo dedicado a ayudar con los despliegues; contratas a unos pocos especialistas y compras soluciones listas para usar para la mayoría de las cosas. Del mismo modo, algunas tareas de machine learning se volvieron lo bastante fáciles como para que incluso un desarrollador web como yo pueda implementarlas.
También hubo compromisos en la evolución de DevOps. Por ejemplo, como resultado directo de “solo usa AWS RDS”, desaparecieron competencias clave como la administración de bases de datos, y las facturas de la nube también se dispararon. En particular, aumentaron los costos operativos incluso para startups sin gran escala de datos ni complejidad regional, y creo que esta tendencia también llevó a incidentes similares a la gran caída de GitLab.
Es parecido a cuando te piden adivinar cara o cruz y respondes “cara”: antes de contestar podrías hablar de la incertidumbre, como Pr[cara] = .5, pero en la predicción real y en el resultado del lanzamiento esa incertidumbre desaparece. En los LLM también, en la predicción final del token desaparece la incertidumbre del cálculo, así que a menos que la predicción misma sea una expresión de incertidumbre, casi nunca aparecerá una salida como “no entendí”. Aunque la razón es que, para empezar, predice sin entender.
Básicamente, creo que estamos usando GPT como el equivalente de PaaS/Heroku/Render para las operaciones de IA.
Me da curiosidad la parte de “siempre extraemos JSON; no necesitamos el modo JSON”. En mi caso funcionó bastante bien.
Estoy muy de acuerdo con “Lección 4: GPT es realmente malo para crear hipótesis nulas”. Ayer mismo estaba probando un prompt con reglas de edición de texto y al final escribí: “si ninguna regla aplica al texto, devuelve el texto original sin cambios”.
¿Saben qué respondió ChatGPT con un texto al que no se aplicaba ninguna regla? Literalmente la cadena “The original text without any changes”.
Una vez estaba creando una imagen para una carta de tarot con tres mujeres bebiendo vino en un jardín elegante, y al poner “lush vegetation” al final del prompt, por la ambigüedad de lush, pasó de una atmósfera elegante a una vibra de universitarias de fiesta con la nariz roja.
Con mejores prompts puedes usar modelos más baratos.
“Si no encuentras nada, no devuelvas nada” es una técnica de nivel 0 que le da al LLM una vía de escape. Es mejor darle una salida más suave. Por ejemplo, escribir algo como: “si no hay información suficiente para hacer una afirmación concluyente, puedes formular una hipótesis siempre que dejes claro que eso es lo que estás haciendo y escribas las evidencias y la base lógica de la hipótesis”, y al final pedirle que evalúe su propia respuesta.
Si no hay un método automatizado, hay que probar iterativamente las respuestas del modelo ante diversas entradas, entender cómo interpreta la solicitud y dónde falla, y tapar esos huecos. Incluso hay que verificar si el modelo sabe qué significa nothing.
Estoy suscrito a los tres servicios principales en el campo de los LLM y suelo lanzarles el mismo prompt; la ventaja de GPT-4 es abrumadora. Es sorprendente incluso considerando que ya pasó un año desde que salió GPT-4 y que hubo varias actualizaciones en el medio.
Al menos con mi patrón de uso, las alucinaciones son relativamente raras. En cambio, Claude inventa con bastante facilidad APIs plausibles que no existen cuando escribe código. GPT-4 es más terco y menos complaciente cuando sabe que tiene razón. Estas diferencias casi no aparecen en las métricas, así que solo se ven al usarlo personalmente.
Incluso en tareas de programación, más que pedirle que escriba código, le pido explicaciones sobre temas o sobre código, y tiende a dar respuestas mucho más matizadas. Cuando le doy un texto largo y converso sobre él, Claude Opus se siente como si entendiera el contenido con más profundidad; GPT-4 se queda más en resumir el texto dado, mientras que Claude lo amplía y razona mejor.
Dicho eso, con prompts bien construidos, Claude Opus tiende a producir mejores resultados que GPT-4. Claude ofrece respuestas más flexibles y largas, mientras que ChatGPT/GPT-4 siempre suele sonar como su respuesta corta y “típica” característica.
En los ejemplos de código que pedía, el código generado por GPT-4 muchas veces ni siquiera compilaba, y con Claude casi nunca me pasó eso.
Mi prueba de fuego últimamente es: “Dime 10 bares raros a menos de 200 millas de Austin”. Es tremendamente difícil para todos; GPT-4 estuvo más o menos cerca, pero Claude simplemente inventó cosas y Gemini se desplomó por completo.
GPT es muy genial, pero no estoy nada de acuerdo con la interpretación de dos párrafos del artículo.
Se puede resumir que un mejor enfoque habría sido algo como: “GPT, claramente conoces los 50 estados, así que dame el nombre completo del estado al que corresponda esto, o responde Federal si corresponde al gobierno de EE. UU.”.
Pero me parece exagerado interpretar que, cuando se le habla de forma más ambigua, la calidad y la generalización de GPT mejoran como una señal típica de delegación/pensamiento de alto nivel. El lenguaje natural es la salida más probable para GPT, porque se parece al texto con el que fue entrenado. En este caso, el desarrollador simplemente se apoyó más en lo que GPT hace bien; no le pidió que hiciera más trabajo.
Hay muchas tareas simples que hacen fallar a GPT. Tareas como sustitución de letras u errores ortográficos intencionales son muy difíciles para GPT. Lo mismo pasa con mapeos de IDs, especialmente cuando difieren mucho de los mapeos que vio durante el entrenamiento. Por ejemplo, códigos de países de tres letras parecidos, pero que no son ISO.
Lo interesante es el hecho mismo de que GPT “entienda” el mapeo. Eso me parece más bien una verdadera pista de reconocimiento de patrones de alto nivel.
Consejo sobre el problema de ‘null’: los LLM están hechos para emitir tokens, no para no emitir tokens.
Por eso, en vez de decir “no devuelvas nada”, conviene decirle que cuando no haya resultado “devuelva el valor predeterminado de XYZ”, y luego buscar ese valor predeterminado, por ejemplo XYZ, en el resultado como texto, igual que buscarías el nombre de un estado.
Además, el prompt de sistema puede ser muy útil. Básicamente es una oportunidad para hacer que el LLM interprete el rol X. Sería bueno poder pasar directamente el prompt de sistema, pero aun así es mejor que no tenerlo.
Que GPT no pueda devolver correctamente más de 10 objetos JSON en una lista es un problema de prompt. Yo he logrado que devuelva de forma estable hasta 200 en el orden correcto.
El truco es no usar listas en absoluto y usar claves JSON en la salida como
"item1": {...}. Cuando para una entrada puede haber de 0 a n salidas, se puede usar una lista como valor.Si le doy a GPT-4 una lista existente de elementos con una estructura definida y le pido que la convierta a JSON, como una transformación de esquema, lo hace bien todo el día. Pero si requiere cualquier tipo de inferencia y en la práctica tiene que crear su propia lista, solo da un subconjunto muy limitado.
Tengo problemas similares con otros LLM. Me interesa mucho saber cómo lo abordas.
Tareas como “extrae los nombres de empresas de este bloque de texto” se pueden dividir en dos pasos.
Primero preguntar: “¿Se menciona alguna empresa en este bloque de texto?”. Si no, ya obtuviste un resultado null. Si sí, entonces decir: “Enumera los nombres de las empresas que aparecen en este bloque de texto”.
Uso modelos de OpenAI en una app personal de escritura, y este artículo es realmente acertado. Aprendí algo relacionado con la Lección 1, “cuanto menos prompt, mejor”.
Mientras creaba una función de búsqueda inteligente para notas, intenté que ChatGPT devolviera datos JSON estructurados. Por ejemplo, quería preguntar “dame todas mis notas de los últimos 2 años que mencionen Haskell y estén marcadas como borrador”, y que ChatGPT decidiera qué devolver. Eso funcionaba solo a veces.
En cambio, puse los datos en una base de datos SQLite, le envié el esquema a ChatGPT y le pedí que escribiera una consulta para devolver el resultado deseado. Funcionó mucho mejor.
response_format=json_object.Para obtener respuestas estructuradas, las llamadas a funciones encajaban mejor, pero tienen más restricciones que simplemente recibir un cuerpo JSON.
El ejemplo de que dar instrucciones demasiado precisas reduce la exactitud tiene sentido según mi comprensión rudimentaria de cómo funcionan estos sistemas.
Si incluyes la lista completa de estados, en cierto modo estás activando los vectores de todos los estados. Si simplemente dices “state” y el texto que pasaste contiene un estado explícito, se activan menos vectores relacionados con lo que buscas. Por eso, al aplicar softmax, aumenta la probabilidad de que se elija el estado correcto.
En la misma línea, la comparación entre
/ny comas probablemente se deba a una diferencia de tokenización.