Ingeniería de bucles para generación RAG: itere top-k uno a la vez

El usuario pregunta “¿cuál es la fecha de vigencia de esta póliza?”. La recuperación devuelve cinco ventanas de línea candidatas y las pasa todas al LLM en un solo mensaje. El LLM lee los cinco para extraer la misma fecha que ya tenía el primer candidato. Los fragmentos del dos al cinco eran firmas, notas a pie de página y un párrafo sobre fechas históricas. Pagado por nada. Envíe primero el top-1, pregúntele al LLM si eso es suficiente y deténgase cuando diga que sí: la alimentación secuencial reduce el costo del token en un 80 % en este tipo de preguntas. El resto del artículo cataloga dónde se obtienen victorias secuenciales, dónde una sola llamada sobre todos los K es el valor predeterminado correcto y cómo el analizador de preguntas distribuye entre los dos.

Este artículo complementa Enterprise Document Intelligence, la serie cuya filosofía se establece en Amplify the Expert, la serie que construye RAG empresarial a partir de cuatro ladrillos (análisis de documentos, análisis de preguntas, recuperación, generación). Se encuentra entre el Artículo 8 (generación) y el Artículo 9 (actualización del mini-RAG) y desarrolla una decisión específica: ¿cómo se introducen los candidatos top-K recuperados en el bloque de generación? La respuesta que tienen la mayoría de los oleoductos es “todo K a la vez”. Este artículo cataloga el segundo régimen (secuencial, top-1 primero) y muestra cuándo gana cada uno.

La ingenua línea de base que este artículo rechaza

Los dos regímenes para alimentar el top-K al ladrillo de generación – Imagen del autor

Naive RAG envía lotes de forma predeterminada. La recuperación arroja el top 5, el LLM obtiene los 5, la respuesta regresa. Funciona y en cuestiones difíciles (comparación, listado) es la elección correcta. Pero el costo silencioso se paga en todas las demás preguntas: las fáciles y fácticas en las que el primero ya tenía la respuesta. Este artículo recorre el segundo régimen y el despacho que elige por pregunta.

Dónde se ubica este artículo en la serie: ladrillo 8 (generación) resaltado – Imagen del autor

📓 El cuaderno ejecutable para este artículo está en GitHub: doc-intel/notebooks-vol1. Envía las mismas preguntas a través de generación secuencial y por lotes, imprime el costo del token por pregunta y los dos valores booleanos de suficiencia (answer_found, complete_answer_found) que detienen el ciclo y reproduce la tabla de despacho en su propia máquina.

El repositorio público de códigos complementarios en doc-intel/notebooks-vol1 – Imagen del autor

1. Dos regímenes para alimentar a los mejores K a la generación

Las manos de recuperación generan un top-K ordenado. Hay dos formas de alimentarlo y cuestan muy diferentes.

1.1 El oleoducto fijo top-K y lo que desperdicia

El patrón predeterminado en la mayoría de los tutoriales de RAG se ve así:

top_k = recuperación(pregunta, k=5) respuesta = generación(pregunta, top_k)

Se ejecuta en dos pasos para cada pregunta. El costo del token es aproximadamente costo_generación (pregunta + 5 fragmentos de contexto). La latencia es aproximadamente recuperación + una llamada LLM. Y el LLM procesa felizmente los 5 fragmentos incluso cuando el top 1 ya era suficiente y los fragmentos 2..5 no agregaron información.

Concretamente: el usuario pregunta “¿cuál es la fecha de vigencia de esta política?”. La recuperación devuelve 5 ventanas de línea donde aparece la palabra clave “efectivo”. La primera es la respuesta (“vigente a partir del 1 de enero de 2026”). Los fragmentos 2 a 5 son firmas, notas a pie de página y un párrafo sobre las fechas históricas de vigencia de políticas pasadas. El LLM lee los 5 para extraer la misma fecha que ya tenía el primero. En un corpus de un documento, el costo es un error de redondeo. En un corpus de 50.000 pólizas, esto es dinero real por mes.

1.2 Secuencial: primero el primero, predicado de suficiencia, escalar si es necesario

El régimen secuencial trata a los candidatos K como una lista ordenada y pide al bloque generacional que valide la suficiencia en cada paso:

para i, candidato en enumerar(top_k): respuesta = generación(pregunta, [candidate]) si respuesta.answer_found y respuesta.complete_answer_found: descanso

La señal de suficiencia se encuentra dentro del contrato mecanografiado que introdujo el artículo 8A. El esquema AnswerWithEvidence expone answer_found (¿estaba la información de la pregunta presente en este candidato?) y complete_answer_found (¿estaba presente la respuesta completa, no un fragmento?). El bucle lee esos campos, no una heurística personalizada.

En el ejemplo anterior de fecha de vigencia: la generación se ejecuta una vez en el candidato principal, el LLM devuelve respuesta_encontrada = Verdadero, respuesta_completa = Verdadero, el ciclo sale. Tokens gastados: coste_generación (pregunta + 1 parte de contexto). Eso es 1/5 del costo del lote para esta pregunta, en un proceso que maneja miles de búsquedas similares por día.

1.3 Lote: envíe todos los K a la vez, deje que el LLM arbitre

El modo por lotes mantiene el comportamiento predeterminado: una llamada de LLM ve a todos los K candidatos y produce una respuesta escrita. Su caso se basa en tres tipos de preguntas donde la secuencial se descompone:

Preguntas de listado: “enumere todas las exclusiones de este contrato”. La respuesta es cada candidato coincidente, no el primero. Sequential se detendría en el top 1 (se encontró una exclusión) y perdería las otras cuatro. Lote es el único modo correcto. Preguntas comparativas: “¿la prima es más alta que la del año anterior?”. La respuesta requiere que ambos candidatos (este año + el año pasado) estén en la misma convocatoria para que el LLM pueda compararlos. Secuencial extraería cada uno de forma independiente y perdería la unión. Recuperación de puntajes ajustados: cuando los puntajes de relevancia de los candidatos top-K están dentro del 5% entre sí, la recuperación no puede promover de manera confiable a los primeros 1 a la cima. Batch permite al LLM arbitrar con toda la evidencia visible.

Análisis de costos: el lote siempre paga el costo_generación (pregunta + K fragmentos de contexto) una vez. Secuencial paga costo_generación (pregunta + 1 parte de contexto) en el caso fácil (el 1 superior es suficiente) y costo_generación (pregunta + 1 parte) × K en el peor de los casos (cada candidato es insuficiente). En un corpus empresarial típico con K = 5, el secuencial es más barato en promedio para búsquedas objetivas (~80% del tráfico típico) y más caro para listado/comparación (~20%).

2. La decisión de envío: por pregunta, no por canalización

La arquitectura limpia no selecciona lotes o secuenciales globalmente. Selecciona por pregunta, utilizando la fila question_df analizada del bloque 2. La forma de la pregunta, el patrón de descomposición y la intención impulsan la elección:

Cuatro formas de preguntas, cuatro decisiones de ruta; el analizador llena dos columnas, el despachador las lee – Imagen del autor

El despachador lee question_df.answer_shape y question_df.decomposition y rutas. Naive RAG no tiene forma de hacer esta distinción porque no tiene una pregunta analizada para leer.

La misma tabla de enrutamiento se aplica en todos los sectores y profesiones. Diferentes dominios tienen los mismos patrones de forma y de ellos fluye la misma decisión secuencial/por lotes:

La lógica de despacho se aplica ya sea que el corpus sea de seguros, legal, médico, financiero o de cumplimiento – Imagen del autor

En cada fila, la columna secuencial es un valor escrito único (Cantidad, Fecha, Booleano) y se beneficia de la primera parada. La columna de lote es una lista o una comparación y necesita que todos los K candidatos estén visibles a la vez. La mesa del despachador cubre los cinco sectores con la misma lógica.

3. La señal de suficiencia

El modo secuencial se apoya en una cosa: el bloque de generación que informa si el candidato que acaba de leer fue suficiente. Esa señal y las reglas que detienen el ciclo viven aquí.

3.1 Dónde reside la señal de suficiencia en el contrato mecanografiado

El modo secuencial solo funciona si el bloque de generación puede autoinformar si el candidato que acaba de ver contenía la respuesta. El contrato mecanografiado del artículo 8A es lo que hace esto posible:

clase AnswerWithEvidence(BaseModel): valor: Cualquier evidencia: lista[Span]
respuesta_encontrada: bool respuesta_completa: bool confianza: flotador = Campo(ge=0, le=1) advertencias: lista[str] = []

El bucle secuencial lee respuesta_encontrada y respuesta_completa_encontrada, no un flotador de confianza ni una heurística personalizada. La clara separación entre los dos valores booleanos (del Patrón 4 del Artículo 8ter) es lo que hace que el bucle sea determinista. Encontrado + incompleto dice “continuar con el siguiente candidato”; encontrado + completo dice “detener”; no encontrado dice “continuar o darse por vencido en K”.

Una flotación de confianza forzaría un umbral (por ejemplo, “detenerse en 0,8”), y ese umbral deriva de un modelo a otro. Dos valores booleanos no se desvían.

Dos valores booleanos conducen a tres salidas; la salida del medio regresa a la generación con el siguiente candidato – Imagen del autor

3.2 Iteración limitada: incluso la secuencial debe detenerse

El bucle secuencial tiene tres salidas, no una:

Suficiencia: respuesta_encontrada y respuesta_completa_encontrada en un candidato. Detente, envía la respuesta. Agotamiento: todos los candidatos K vistos, ninguno suficiente. Detener, devolver respuesta_encontrada = False (una respuesta de primera clase por la que pasa el validador). Presupuesto: un token o presupuesto de tiempo establecido por el despachador. Útil cuando el corpus es grande y un bucle secuencial fuera de control arruinaría el límite. La misma forma que los nombres de la iteración limitada M4 (ingeniería de bucle).

Las implementaciones secuenciales ingenuas se saltan la tercera salida y queman tokens para siempre en los casos extremos. La versión en serie establece un presupuesto por adelantado y el despachador lo registra en cada llamada.

4. Costo y dónde termina la serie

Dos regímenes, dos perfiles de costos y un límite que la serie no cruza.

4.1 Una comparación de costes concreta en un lote de cien preguntas

Para que la compensación sea real, aquí hay un resumen de una carga de trabajo de preguntas y respuestas sobre seguros empresariales:

100 preguntas por día, K = 5, tamaño promedio del fragmento = 600 tokens. Línea de base del lote: 100 × costo_generación (pregunta + 5 × 600 tokens) = ~330 000 tokens de entrada por día para la generación. Secuencial (80 % del top-1 suficiente): 80 × costo_generación (pregunta + 600) + 20 × costo_generación (pregunta + 5 × 600) (peor caso para el 20 % de preguntas complejas) = ​​~115 000 tokens de entrada por día.

La proporción es un ahorro del 65 % en tokens de entrada para la generación en esta carga de trabajo. La proporción exacta depende de la proporción de preguntas fáciles y del tamaño del fragmento; El principio es que el secuencial es el valor predeterminado barato una vez que el contrato mecanografiado está vigente. El lote está reservado para los tipos de preguntas que lo necesitan.

4.2 La tentación agente y dónde se detiene la serie

Un siguiente paso natural es dejar que el LLM decida entre lote y secuencial por pregunta (despacho agente). La serie no llega a esto. El despachador en la Sección 2 es determinista-despachador (uno de los tres enfoques catalogados en el Artículo 6C), no LLM-decide. La razón es la misma que se repite en toda la serie: auditoría. La misma pregunta el mismo día debe encaminarse en el mismo sentido; un LLM que replanifica el despacho por llamada no puede dar esa garantía.

Si necesita un bucle agente más sólido (el LLM elige qué candidatos examinar, en qué orden y con qué alcance), el artículo más amplio sobre bucles RAG adaptativos es el lugar correcto. Este artículo mantiene el alcance de la decisión determinista secuencial versus por lotes impulsada por la pregunta analizada.

5. La decisión pertenece al analizador, no al LLM.

El proceso por lotes fijo top-K + es el valor predeterminado correcto para los tipos de preguntas en las que cada candidato es importante. Es un valor predeterminado incorrecto para las búsquedas factuales que constituyen la mayor parte del tráfico empresarial. La serie agrega dos piezas: la señal de suficiencia escrita (respuesta_encontrada, respuesta_completa_encontrada) del Artículo 8A y la tabla de despacho de la Sección 2. Juntos dejan que el bloque de generación se detenga después del primer candidato cuando es suficiente, y procesan todos los K cuando el tipo de pregunta lo requiere. La decisión la toma el analizador, no el LLM, que mantiene intacto el rastro de auditoría.

6. Lecturas adicionales y fuentes

La decisión secuencial/por lotes se sitúa en el límite entre la recuperación y la generación. Los artículos que enmarcan cada lado: