la misma forma de respuesta. Uno quiere un solo número con una cita, otro una lista con un elemento por fila, un tercero un sí o no con una advertencia. Oblígalos a todos a través de una llamada generacional y cada forma degrada a las demás. La solución es un pequeño conjunto de patrones de generación, uno por forma de respuesta.
Este artículo complementa Enterprise Document Intelligence, la serie cuya filosofía se expone en Amplify the Expert. Se acerca al ladrillo 4 (generación) de la arquitectura de cuatro ladrillos y retrocede en el vocabulario que los equipos utilizan cuando una respuesta RAG es incorrecta.
La alucinación, en sentido estricto, es una invención a partir de la memoria paramétrica del modelo: el LLM inventa un hecho sin ninguna base en la información. En RAG el modelo lee el contexto; cuando la respuesta es errónea, la causa está aguas arriba, en la cadena de extracción (análisis, interrogación, recuperación o el propio contrato de generación). Llamar a cada fracaso una alucinación cierra el debate sobre dónde actuar. Nombrar la causa real la abre de nuevo.
La historia principal tiene generación como enviar fragmentos recuperados + pregunta al LLM y obtener una cadena de respuestas. Rechazamos todo este marco. La respuesta no es una cuerda. Es un objeto Pydantic escrito con citas, indicadores de fidelidad y campos de autoevaluación. El LLM es una función, no un oráculo. El esquema es el contrato. El validador se ejecuta antes de que el usuario vea algo.
📓 Reproduzca los siete patrones en el cuaderno enviado: complete el esquema AnswerWithEvidence escrito en una pregunta de corpus de intermediario, observe cómo se mueve cada bandera de autoevaluación y luego vuelva a ejecutar con el esquema descompuesto para ver cómo un modelo pequeño alcanza uno de frontera. Repositorio → doc-intel/notebooks-vol1.
La ingenua línea de base que este artículo rechaza
El ingenuo oleoducto pide una respuesta al LLM y confía en lo que regresa. No hay separación entre lo encontrado y lo inventado, no hay lugar para registrar la confianza y no hay forma de marcar lo no encontrado como un resultado de primera clase. En su lugar, completamos el esquema: cada campo es una pregunta que hace el canal y cada respuesta se puede verificar.
A continuación se muestran los siete patrones que mantienen la generación en el lado del contrato mecanografiado. Los primeros seis son el contrato en sí. El séptimo menciona una restricción que el contrato debe respetar cuando el modelo es pequeño.
Patrón 1: el LLM es una función, no un oráculo
El esquema de respuesta es un contrato: recuperación estructurada, un objeto Pydantic escrito, con citas, indicadores de fidelidad y campos de retroalimentación, nunca “la respuesta como una cadena”. Todo lo que hace el ladrillo de generación está al servicio de cumplir ese contrato, campo por campo.
Tomemos como ejemplo “¿cuál es el monto de la prima?”. La ingenua línea de base devuelve una frase: “La prima es de 124 dólares al mes, según el contrato”. Para usar eso en sentido descendente, debe analizar el número nuevamente fuera de la prosa, y nada le dice de dónde vino o qué tan seguro era el modelo. En su lugar, la serie devuelve una fila: Importe(valor=124,0, moneda=”USD”, unidad=”mes”, evidencia=[Span(line_start=42, line_end=42, quote=”premium of $124 / month”)]respuesta_encontrada=Verdadero, confianza=0,95). El valor ya está escrito, la evidencia apunta a la línea exacta y los campos de autoevaluación viajan con ella. La persona que llama lee valores estructurados, no texto que tiene que volver a leer.
→ El artículo 8A (el contrato de respuesta) desarrolla íntegramente el contrato mecanografiado.
Patrón 2: extraer valores escritos, nunca calcular
Solicite Cantidad (valor, moneda, unidad) y deje que Python lo compare con un tipo de cambio visible; El cálculo dentro del modelo borra el rastro de auditoría y realiza silenciosamente conversiones que ningún ser humano puede reproducir. El LLM extrae, Python calcula.
Tomemos como ejemplo “¿la prima es superior a 100 euros al mes?”. Pregúntale directamente al LLM y te responde “sí, la prima ronda los 130 EUR/mes”, habiendo convertido 124 dólares a euros con una tasa que nunca te muestra. No se puede comprobar la aritmética, y el próximo mes la misma pregunta podría convertirse a una tasa invisible diferente. En su lugar, la serie extrae el valor bruto, Monto(valor=124, moneda=”USD”, unidad=”mes”), y permite que Python haga la comparación con una tasa que se encuentra en el registro de auditoría, 1 USD = 0,92 EUR. Eso da 114 euros, por lo que la respuesta es Verdadera, y cada paso, la extracción, la tasa y la comparación, se puede reproducir y comprobar manualmente.
→ El artículo 8A (el contrato de respuesta) cubre los valores tipificados y la disciplina de no cálculo.
Patrón 3: Completitud a partir de la estructura, no de autoevaluación
El LLM dentro del alcance de recuperación no puede ver si la página siguiente continúa una lista; la recuperación extrae una página adicional y la tubería busca un límite de sección, por lo que la integridad es determinista y se basa en la estructura. Un modelo que sólo puede ver lo que se le envió no puede juzgar lo que falta.
Tome “enumerar todas las exclusiones”. La sección de exclusiones comienza en la página 7, y la siguiente sección, “Limitaciones”, comienza en la página 10, por lo que la respuesta se encuentra en las páginas 7 a 9. Naive RAG entrega esas páginas al LLM y pregunta “¿está completa la lista?”. El modelo solo puede ver lo que se le dio, por lo que lee las páginas 7 a 9 y dice que sí, sin forma de saber si alguna vez se recuperó una décima exclusión. En cambio, la serie comprueba la estructura en el momento de la recuperación: ¿la página siguiente todavía pertenece a la sección de exclusiones? Si es así, tráigalo; una vez que cruce a “Limitaciones”, deténgase. La integridad se convierte en un hecho acerca de dónde termina la sección, no en una suposición que el modelo hace sobre el texto que no puede ver.
→ El Artículo 8A (contrato de respuesta) y el Artículo 8C (validación) crean integridad programática.
Patrón 4: dos valores booleanos, ni un flotador de confianza
Fuera del corpus, parcial y completo cada ruta hacia una siguiente acción diferente, y dos banderas obligan a tomar decisiones más claras que una sola escala. El marco de flotación-confianza colapsa tres resultados diferentes en un solo número.
Tome “enumerar todas las exclusiones” nuevamente, pero esta vez la recuperación encontró la página 7 y omitió la página 8. Una confianza única = 0,6 no le dice al orquestador casi nada: no puede decir si dos de las tres exclusiones regresaron o si la respuesta completa fue inventada. La serie lo divide en dos booleanos. answer_found = True dice que la pregunta se puede responder desde este documento y complete_answer_found = False dice que la lista que regresó es parcial. Esas dos banderas se asignan a tres siguientes movimientos claros: seguir recuperando cuando se encuentre la respuesta pero esté incompleta, enviar cuando se encuentre y esté completa, y rechazar cuando no se encuentre en absoluto. Un solo flotador colapsa esos tres resultados en un solo número y pierde la decisión.
→ El artículo 8A (el contrato de respuesta) explica la división en dos booleanos.
Patrón 5: un mensaje por forma, enviado en tiempo de ejecución
Un despachador compone BASE + un fragmento de forma + restricciones opcionales y registra qué fragmentos se aplicaron, por lo que se puede rastrear un formato incorrecto seis meses después, a diferencia de un mega mensaje que genera cláusulas sin comentar. Un único mensaje al que todo el mundo sigue atendiendo es un olor común a la base del código RAG; componerlo a partir de fragmentos nombrados es lo que mantiene reconstruible el mensaje de cada respuesta.
Tomemos como ejemplo “¿fecha de entrada en vigor?”, cuya forma de respuesta es Fecha. Una línea de base ingenua ejecuta un mensaje genérico que siempre pide “una respuesta”, sea cual sea la pregunta. En su lugar, la serie compone el mensaje a partir de partes: el mensaje BASE, más un fragmento de forma de Fecha que dice “devolver AAAA-MM-DD”, más el esquema DateAnswer. El registro de auditoría registra exactamente qué piezas se utilizaron, Prompt_id=BASE@v3 + shape=date_v2. Entonces, cuando el modelo regresa “1 de julio de 2026” seis meses después y alguien tiene que explicar el formato incorrecto, el equipo puede reconstruir ese mensaje exacto a partir del registro y reproducir el error, en lugar de adivinar qué cláusula de un mega mensaje de mil líneas se disparó.
→ El artículo 8B (montaje rápido) diseña el despachador rápido.
Patrón 6: modelos sin razonamiento en la extracción JSON
El esquema ya limita el trabajo, por lo que el “pensamiento” adicional agrega latencia y se sale del esquema sin agregar precisión. Los modelos de razonamiento ganan su lugar en tareas abiertas; en la extracción restringida por esquemas, están sobrediseñados.
Tome “¿cuál es el monto del deducible?”. Un equipo que espera lograr una extracción más limpia cambia a un modelo de razonamiento. Piensa durante ocho segundos y devuelve el mismo número que devolvió un modelo simple en uno, porque el esquema ya había fijado la salida en un solo campo escrito. Los tokens de razonamiento costaban latencia y dinero y no compraban nada, ya que no había ningún juicio abierto que hacer. La postura que sigue es simple: use el modelo más pequeño que llene el esquema de manera confiable y guarde el razonamiento para los pasos que realmente lo necesitan, como el árbitro LLM al final de la recuperación.
→ El artículo 8A (el contrato de respuesta) y el artículo 8B (pronta asamblea) funcionan a través de las compensaciones.
Patrón 7: descomponer para modelos pequeños, una llamada para los grandes
Un modelo de frontera puede completar un esquema compuesto (extraer + convertir + formatear) en una sola llamada; un modelo pequeño no puede, y al solicitarlo inventa los campos derivados en silencio. El tamaño del modelo establece la granularidad del contrato, no su forma.
Tomemos como ejemplo “¿la prima es superior a 100 euros al mes?” con un esquema compuesto, PremiumComparison(raw_amount: Monto, convert_eur: float, exchange_rate: float, over_100_eur: bool). GPT-4.1 completa todos los campos correctamente en una sola llamada: extrae $124/mes en raw_amount, convierte a 114,08 EUR con una tasa visible y devuelve over_100_eur=True. Entregue el mismo esquema a llama-3.2-3B y el modelo devuelve cantidad_bruta poblada, euro_convertido inventado a 117,6 (de una tasa imaginaria de 0,95 que el registro nunca lleva) y over_100_eur=True derivado de esa tasa inventada. El modelo pequeño no falla la validación JSON. Llena todos los campos. Tres de los cuatro son inventados.
La solución es descomponer el contrato en etapas que el modelo pequeño pueda manejar de forma aislada. Primera llamada: extraer Monto(valor=124, moneda=”USD”, unidad=”mes”). Python se hace cargo: búsqueda de tarifas (registrada, 1 USD = 0,92 EUR), conversión (124 * 0,92 = 114,08 EUR), umbral (114,08 > 100 = Verdadero). Segunda llamada opcional si se necesita un resumen en lenguaje natural: devuelva la fila compuesta completa con un mensaje en formato sencillo. Misma fila final, misma precisión, sin intermedio fabricado.
La regla: el tamaño del modelo determina el número de llamadas de extracción, no la forma del esquema. Modelo grande = una llamada densa. Modelo pequeño = una cadena de extractos escritos con computación Python en el medio y una llamada de formato opcional al final. El contrato mecanografiado sobrevive de cualquier manera; sólo cambia la granularidad.
El artículo B05 (elegir un modelo) compara la compensación de granularidad en una flota de trece modelos (enlace a continuación).
Los siete patrones comparten un movimiento: rechazar el marco del LLM como oráculo y tratar a la generación como si se cumpliera un contrato mecanografiado. El esquema es el contrato; las citas y los campos de autoevaluación son resultados de primera clase; el validador se ejecuta antes de que el usuario vea algo. El patrón 7 añade el matiz operativo: el mismo contrato se mantiene en todos los tamaños de modelo, pero un modelo pequeño necesita dividirlo en etapas que el modelo pueda completar sin inventar valores derivados. Las inmersiones profundas (8A, 8B, 8C) incluyen código ejecutable en documentos reales; esta pieza es el catálogo que nombra cada patrón y apunta al código que lo implementa.
En todos los sectores y profesiones
La disciplina del contrato mecanografiado (esquema Pydantic + citas + campos de autoevaluación) se cumple en todos los dominios. Lo que cambia por pregunta es la forma del esquema. El patrón de contrato sigue siendo el mismo. Cinco sectores debajo, cinco formas de respuesta, un validador ejecuta las mismas comprobaciones en todos ellos.
El validador ejecuta las mismas comprobaciones en las cinco filas: espacios de línea dentro de los límites del documento, citas textuales que coinciden con las líneas citadas, restricciones de formato respetadas (una Duración en realidad se analiza como una duración, una Cantidad lleva moneda y unidad). La fila legal demuestra la división en dos booleanos (Patrón 4): la respuesta se encontró en este documento pero no está completa sin una referencia cruzada, por lo que el orquestador continúa con la recuperación en lugar de enviar una respuesta parcial. La fila médica muestra el rastro de auditoría (Patrón 1): la advertencia captura un conocimiento desconocido que el LLM no pudo resolver.
Dónde aterrizan estos patrones en la serie
Los artículos numerados desarrollan cada patrón en código, con cuadernos ejecutables:
Fuentes y lecturas adicionales
La mayor parte de los escritos sobre la generación LLM provienen de chatbots y textos abiertos. La serie supone algo diferente: la respuesta debe ser auditable y el LLM debe negarse a inventar.