{"id":671,"date":"2026-06-20T16:58:46","date_gmt":"2026-06-20T14:58:46","guid":{"rendered":"https:\/\/atlaszn.com\/blog\/?p=671"},"modified":"2026-06-20T16:58:46","modified_gmt":"2026-06-20T14:58:46","slug":"reflection-con-llms-auto-correccion-y-mejora-iterativa","status":"publish","type":"post","link":"https:\/\/atlaszn.com\/blog\/2026\/06\/20\/reflection-con-llms-auto-correccion-y-mejora-iterativa\/","title":{"rendered":"Reflection con LLMs: Auto-correcci\u00f3n y mejora iterativa"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">El problema que Reflection resuelve<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Un modelo de lenguaje produce su mejor output en el primer intento. La mayoria de las veces es suficiente. Pero hay tareas donde el primer intento falla de forma predecible: C\u00f3digo con edge cases olvidados, an\u00e1lisis que omite perspectivas clave, contenido que no cumple restricciones espec\u00edficas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un humano escribe, lee, corrige. Un LLM escribe y se queda en silencio. Reflection cierra esa brecha introduciendo un bucle de feedback: Genera output, eval\u00faa contra criterios, mejora.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que esto no hace es convertir un modelo incapaz en uno competente. Si el modelo no puede generar c\u00f3digo correcto la primera vez, probablemente tampoco pueda corregirlo la segunda. Reflection estabiliza la calidad de un modelo que ya funciona, no lo repara.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arquitectura b\u00e1sica<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El patr\u00f3n tiene cuatro fases:<\/p>\n\n\n\n<ul class=\"wp-block-list\" class=\"wp-block-list\">\n<li><strong>Generaci\u00f3n<\/strong>: El agente produce el output inicial.<\/li>\n\n\n\n<li><strong>Cr\u00edtica<\/strong>: Una evaluaci\u00f3n independiente analiza el output contra criterios espec\u00edficos.<\/li>\n\n\n\n<li><strong>Refinamiento<\/strong>: El agente genera una versi\u00f3n mejorada bas\u00e1ndose en la cr\u00edtica.<\/li>\n\n\n\n<li><strong>Iteracion<\/strong>: El ciclo se repite hasta cumplir una condici\u00f3n de parada.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"683\" height=\"1024\" src=\"https:\/\/atlaszn.com\/blog\/wp-content\/uploads\/2026\/06\/diagrama_reflection-683x1024.webp\" alt=\"\" class=\"wp-image-694\" style=\"width:730px;height:auto\" srcset=\"https:\/\/atlaszn.com\/blog\/wp-content\/uploads\/2026\/06\/diagrama_reflection-683x1024.webp 683w, https:\/\/atlaszn.com\/blog\/wp-content\/uploads\/2026\/06\/diagrama_reflection-200x300.webp 200w, https:\/\/atlaszn.com\/blog\/wp-content\/uploads\/2026\/06\/diagrama_reflection-768x1152.webp 768w, https:\/\/atlaszn.com\/blog\/wp-content\/uploads\/2026\/06\/diagrama_reflection.webp 1024w\" sizes=\"auto, (max-width: 683px) 100vw, 683px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Usar dos agentes distintos: Un Generator enfocado en producci\u00f3n y un Critic con instrucciones de \u00abingeniero senior\u00bb o \u00abrevisor exhaustivo\u00bb previene el sesgo de confirmaci\u00f3n. Un modelo que acaba de generar codigo tiende a excusar sus propios errores. Un agente separado no tiene esa inercia.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ejemplo: Bucle de reflection funcional<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import asyncio\nimport json\nfrom dataclasses import dataclass\n\n@dataclass\nclass ReflectionResult:\n    output: str\n    iterations: int\n    accepted: bool\n    total_tokens: int\n\nasync def reflect(\n    task: str,\n    criteria: dict,\n    max_iter: int = 3,\n    generate_fn=None,\n    critique_fn=None,\n) -&gt; ReflectionResult:\n    \"\"\"Bucle de reflection con control de contexto y parada temprana.\"\"\"\n    output = await generate_fn(task, &#91;])\n    context = &#91;task]\n    total_tokens = 0\n\n    for i in range(max_iter):\n        feedback = await critique_fn(task, output, criteria)\n        total_tokens += len(feedback)  # proxy de tokens\n\n        if \"OUTPUT_ACCEPTABLE\" in feedback:\n            return ReflectionResult(output, i + 1, True, total_tokens)\n\n        # Truncar contexto: mantener solo las 2 criticas mas recientes\n        context = &#91;task] + context&#91;-2:]\n        context.append(f\"Critique {i+1}: {feedback}\")\n        output = await generate_fn(\"Refine based on critiques.\", context)\n\n    return ReflectionResult(output, max_iter, False, total_tokens)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Tres iteraciones m\u00e1ximo. Condici\u00f3n de parada expl\u00edcita. Contexto truncado a las dos cr\u00edticas m\u00e1s recientes para evitar que el historial inunde la ventana del modelo. Es la estructura que he usado en sistemas reales porque equilibra calidad y coste de forma predecible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lo que aprendimos a mal<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La primera vez que implementamos Reflection, lo hicimos con 5 iteraciones y el mismo modelo para Generator y Critic. Parec\u00eda buena idea: Un solo modelo, menos infraestructura, y \u00absi 3 iteraciones ayudan, 5 ayudaran el doble\u00bb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fue un desastre. El modelo entraba en bucles donde el Critic se\u00f1alaba un problema, el Generator lo \u00abarreglaba\u00bb introduciendo otro, y el Critic se\u00f1alaba el nuevo problema. En la iteraci\u00f3n 4, el output era peor que el original. Y como us\u00e1bamos el mismo modelo, el Critic tendia a aceptar sus propias correcciones anteriores en lugar de evaluar el resultado final.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que hicimos: Bajamos a 3 iteraciones, separamos Generator y Critic, y a\u00f1adimos la condici\u00f3n de parada temprana. El resultado fue mejor y m\u00e1s barato. La lecci\u00f3n: M\u00e1s iteraciones no es m\u00e1s calidad. Es mas ruido.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Y eso no fue el peor problema. Lo que realmente nos cost\u00f3 tiempo fue el overflow de contexto. Cada iteraci\u00f3n a\u00f1ad\u00eda el output anterior m\u00e1s la cr\u00edtica al historial, y en tareas con outputs largos (generaci\u00f3n de c\u00f3digo de 200 lineas), la ventana de contexto se llenaba en la segunda iteraci\u00f3n. El modelo empezaba a alucinar porque perd\u00eda el contexto original de la tarea. Lo que hicimos; truncar el historial a las dos cr\u00edticas m\u00e1s recientes y mantener solo la tarea original. Funcion\u00f3, pero fue una correcci\u00f3n que deber\u00edamos haber hecho desde el principio.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Los dos enfoques de Reflection<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En la literatura sobre sistemas LLM, se distinguen dos formas de implementar la reflexion. Cada una tiene un perfil de objetividad y costo distinto.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Auto-reflexi\u00f3n<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">El mismo modelo genera y revisa su output. Una sola llamada, un prompt que incluye tanto la tarea como la instrucci\u00f3n de auto-revisi\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Funciona para errores obvios (sintaxis, formato, ortograf\u00eda), pero se rompe cuando el fallo es conceptual. Pedirle a un modelo que encuentre sus propios errores de l\u00f3gica es como pedirle a alguien que revise su propio trabajo despu\u00e9s de tres horas seguidas, pasa por alto lo que acaba de escribir.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En LangChain se implementa con una cadena secuencial, generaci\u00f3n seguida de auto-evaluaci\u00f3n. Es barato y rapido, pero la calidad de la revisi\u00f3n tiene un techo bajo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Critic separado<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Un agente distinto, con instrucciones diferentes, evalua el output. El Generator se enfoca en producci\u00f3n. El Critic se enfoca en hallar fallos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esta separaci\u00f3n es lo que hace efectivo al patr\u00f3n. El Critic no invirti\u00f3 tokens en el output original. Puede ser mas severo porque no tiene apego al resultado. En nuestros tests, la diferencia en calidad de revisi\u00f3n entre un Critic separado y la auto-reflexion era clara, el Critic independiente detectaba errores conceptuales que la auto-reflexi\u00f3n pasaba por alto consistentemente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pero tiene un precio, duplica las llamadas al modelo. Si el Generator ya usa un modelo grande, el Critic a\u00f1ade latencia y coste. Si no compensa el overhead, la auto-reflexi\u00f3n suele ser suficiente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Comparativa<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Enfoque<\/th><th>Coste<\/th><th>Objetividad<\/th><th>Complejidad<\/th><th>Mejora t\u00edpica<\/th><\/tr><\/thead><tbody><tr><td>Auto-reflexi\u00f3n<\/td><td>Bajo (1 modelo)<\/td><td>Baja (sesgo de confirmaci\u00f3n)<\/td><td>Baja<\/td><td>Errores superficiales<\/td><\/tr><tr><td>Critic separado<\/td><td>Medio (2 modelos)<\/td><td>Alta<\/td><td>Media<\/td><td>Errores conceptuales y superficiales<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Reflection en la pr\u00e1ctica: d\u00f3nde colocarlo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La posici\u00f3n del bucle de reflection en el flujo determina su impacto. Hay tres ubicaciones comunes:<\/p>\n\n\n\n<ul class=\"wp-block-list\" class=\"wp-block-list\">\n<li><strong>Reflection en la salida<\/strong>: El punto mas natural. El pipeline genera un output y un critic lo revisa antes de entregarlo al usuario. Es el uso m\u00e1s directo, c\u00f3digo generado, contenido escrito, an\u00e1lisis completado. Aqu\u00ed es donde Reflection ofrece el retorno mas claro porque la revisi\u00f3n ocurre justo antes de la entrega.<\/li>\n\n\n\n<li><strong>Reflection intermedia<\/strong>: aparece dentro de un pipeline m\u00e1s largo. Un sistema de an\u00e1lisis genera datos intermedios, los revisa, y los usa como input para el siguiente paso. Es menos com\u00fan pero m\u00e1s efectivo cuando los errores tempranos se amplifican en pasos posteriores. Corregir en el paso 2 es mas barato que corregir en el paso 5.<\/li>\n\n\n\n<li><strong>Reflection como puerta de calidad<\/strong>: un critic actua como gatekeeper antes de que el output avance. Si no pasa la revisi\u00f3n, se rechaza y se regenera. Esencialmente es un filtro de calidad con bucle de reintento. Funciona bien en sistemas donde la consistencia es prioritaria sobre la velocidad.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Ejemplo de c\u00f3digo: Reflection con LangChain<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El ejemplo anterior era un bucle m\u00ednimo. En produccion, necesitas manejo de errores, parsing robusto, y control de retries. As\u00ed es como se ve una implementacion funcional:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import asyncio\nimport json\nfrom typing import Optional\nfrom langchain_core.language_models import BaseChatModel\nfrom langchain_core.messages import HumanMessage, SystemMessage\n\nCRITIC_PROMPT = \"\"\"You are a senior reviewer. Evaluate this output against the criteria.\nIf it passes all criteria, respond with exactly: OUTPUT_ACCEPTABLE\nOtherwise, list specific issues with line references.\n\nTask: {task}\nOutput: {output}\nCriteria: {criteria}\n\"\"\"\n\nGENERATOR_PROMPT = \"\"\"Generate the requested output.\nTask: {task}\n\"\"\"\n\nasync def production_reflect(\n    task: str,\n    criteria: dict,\n    generator: BaseChatModel,\n    critic: BaseChatModel,\n    max_iter: int = 3,\n    temperature: float = 0.3,\n) -&gt; dict:\n    \"\"\"Reflection con control de errores y parsing estructurado.\"\"\"\n    history = &#91;SystemMessage(content=GENERATOR_PROMPT.format(task=task))]\n    output = \"\"\n    iterations_used = 0\n    accepted = False\n\n    for i in range(max_iter):\n        try:\n            # Generar\n            resp = await generator.ainvoke(history, temperature=temperature)\n            output = resp.content.strip()\n            iterations_used = i + 1\n\n            # Criticar\n            critic_msg = HumanMessage(\n                content=CRITIC_PROMPT.format(\n                    task=task, output=output, criteria=json.dumps(criteria)\n                )\n            )\n            critique_resp = await critic.ainvoke(&#91;critic_msg], temperature=0.1)\n            feedback = critique_resp.content.strip()\n\n            if \"OUTPUT_ACCEPTABLE\" in feedback:\n                accepted = True\n                break\n\n            # Refinar: a\u00f1adir critica al historial y regenerar\n            history.append(HumanMessage(content=f\"Review feedback: {feedback}\"))\n            history.append(HumanMessage(content=\"Refine the output addressing all issues.\"))\n\n        except Exception as e:\n            # Si falla, devolver el output actual con bandera de error\n            return {\n                \"output\": output,\n                \"iterations\": iterations_used,\n                \"accepted\": False,\n                \"error\": str(e),\n            }\n\n    return {\n        \"output\": output,\n        \"iterations\": iterations_used,\n        \"accepted\": accepted,\n    }<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nota las decisiones de dise\u00f1o: temperatura baja en el Critic (0.1) para consistencia, parsing por string literal en lugar de JSON para evitar que el modelo rompa el formato, y un try\/externo que captura fallos de red o timeouts sin colgar el pipeline. Sin estas protecciones, un timeout del Critic bloquea toda la petici\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El parsing por string literal es una decisi\u00f3n fea pero funcional. Probamos con JSON estructurado primero, el Critic respond\u00eda con objetos JSON, y el modelo romp\u00eda el formato en el 10% de los casos. Un try-except alrededor del json.loads() ayudaba, pero a\u00f1adir una capa de parsing que fallaba regularmente era m\u00e1s ruido que se\u00f1al. El string literal es m\u00e1s sucio, pero funciona.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Como medir si tu reflection funciona<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Un bucle de reflection sin metricas es un gasto justificado por fe. Estos son los indicadores m\u00ednimos:<\/p>\n\n\n\n<ul class=\"wp-block-list\" class=\"wp-block-list\">\n<li><strong>Tasa de aceptaci\u00f3n por iteraci\u00f3n<\/strong>: En que iteraci\u00f3n el critic declara el output aceptable. Si el 60% pasa en la primera iteraci\u00f3n, el bucle es innecesario para esos casos. Si el 80% llega a la ultima iteraci\u00f3n, las instrucciones del critic son demasiado estrictas o el generator necesita mejora.<\/li>\n\n\n\n<li><strong>Mejora marginal por iteraci\u00f3n<\/strong>: Cuanto mejora el output entre iteraciones. Si la iteracion 3 aporta menos del 5% de mejora sobre la 2, el costo adicional no se justifica. El retorno decreciente es real y medible.<\/li>\n\n\n\n<li><strong>Coste por output aceptable<\/strong>: Tokens totales divididos por outputs que pasaron la revisi\u00f3n. Si el costo se triplica con una mejora del 10%, la relaci\u00f3n es negativa.<\/li>\n\n\n\n<li><strong>Crecimiento del contexto<\/strong>: tokens acumulados en el historial de conversaci\u00f3n. Cada iteraci\u00f3n a\u00f1ade output + cr\u00edtica. Sin control, el contexto crece linealmente y alcanza el l\u00edmite del modelo. Truncamos el historial despu\u00e9s de la tercera iteracion, manten\u00eda la calidad sin inflar el contexto.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">No necesitas un dashboard completo. Un log con <code>{iteracion, tokens, feedback_length, accepted}<\/code> y un resumen semanal es suficiente para mantener el bucle bajo control.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Anti-patrones que rompen reflection<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Los errores aqu\u00ed no son t\u00e9cnicos. Son de dise\u00f1o. El c\u00f3digo de reflection rara vez falla. Falla la decisi\u00f3n de que revisar y cuantas veces.<\/p>\n\n\n\n<ul class=\"wp-block-list\" class=\"wp-block-list\">\n<li><strong>Bucles sin l\u00edmite<\/strong>: Sin m\u00e1ximo de iteraciones o condici\u00f3n de parada, el agente se ejecuta hasta agotar el contexto o el rate limit. En producci\u00f3n, esto se traduce en facturas inesperadas y timeouts en cascada.<\/li>\n\n\n\n<li><strong>Criterios vagos<\/strong>: Pedir al critic que \u00abverifique la calidad\u00bb sin dimensiones espec\u00edficas produce feedback in\u00fatil. \u00abEl codigo es bueno\u00bb no ayuda. \u00abFalta manejo de ValueError para n &lt; 0\u00bb si ayuda.<\/li>\n\n\n\n<li><strong>Reflection en tareas simples<\/strong>: Si un solo prompt produce resultados aceptables, a\u00f1adir un bucle de revisi\u00f3n desperdicia recursos. La reflection vale la pena cuando el costo del error supera el costo de la revisi\u00f3n.<\/li>\n\n\n\n<li><strong>Ignorar el crecimiento del contexto<\/strong>: Cada ciclo a\u00f1ade el output anterior m\u00e1s la critica al historial. Conversaciones largas agotan la ventana de contexto rapidamente. El error t\u00edpico es acumular historial sin truncar.<\/li>\n\n\n\n<li><strong>Critic demasiado permisivo<\/strong>: Un critic que acepta todo convierte la reflection en un pasarela cosm\u00e9tica. El Critic debe tener criterios mas estrictos que el Generator. Si el Critic acepta lo que el Generator considera bueno, no hay revisi\u00f3n real.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">El anti-patron mas peligroso es el Critic que empeora el output. Hemos visto casos donde el Critic senalaba \u00aberrores\u00bb que no eran errores, estilo de codificaci\u00f3n preferido, estructura alternativa, y el Generator los \u00abcorreg\u00eda\u00bb introduciendo bugs reales. Lo que funcion\u00f3: El Critic evaluando contra criterios objetivos (funcionalidad, seguridad, rendimiento), no contra preferencias subjetivas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cu\u00e1ndo NO usar Reflection<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Reflection es una soluci\u00f3n a un problema espec\u00edfico, output de primer intento insuficiente para el caso de uso. Si un solo prompt produce resultados aceptables, Reflection a\u00f1ade costo sin retorno.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ejemplos concretos donde Reflection sobra:<\/p>\n\n\n\n<ul class=\"wp-block-list\" class=\"wp-block-list\">\n<li>Clasificaci\u00f3n de texto en categor\u00edas predefinidas: Un solo paso es suficiente.<\/li>\n\n\n\n<li>Extracci\u00f3n de datos estructurados con schema claro: El modelo cumple o no cumple, no hay espacio para iteraci\u00f3n \u00fatil.<\/li>\n\n\n\n<li>Generaci\u00f3n de contenido simple (t\u00edtulos, descripciones cortas): La revisi\u00f3n no aporta valor medible.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Si el costo del error es bajo y la tarea es predecible, un solo prompt es m\u00e1s eficiente. Usa Reflection cuando la calidad del output es prioritaria y el primer intento falla de forma predecible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reflection y los demas patrones<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La combinaci\u00f3n m\u00e1s com\u00fan en producci\u00f3n es <strong>Chaining \u2192 Reflection<\/strong>. Un pipeline genera output paso a paso, y un critic revisa el resultado final. En LangChain, una cadena secuencial puede terminar con un nodo de reflection opcional.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Reflection tambien se combina con Routing. Un router clasifica la tarea y decide si merece revisi\u00f3n. Tareas cr\u00edticas (c\u00f3digo de producci\u00f3n, an\u00e1lisis financiero) pasan por reflection. Tareas rutinarias (resumir, clasificar) no. La decisi\u00f3n de aplicar reflection es una forma de routing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con Parallelization, la combinacion es <strong>Parallelization \u2192 Reflection<\/strong>. M\u00faltiples ramas generan candidatos simultaneamente, y un critic selecciona el mejor. Esencialmente es A\/B testing automatizado con revisi\u00f3n inteligente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfCu\u00e1ndo debo usar Reflection en lugar de un solo prompt?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando la calidad del output importa mas que la velocidad. Generacion de codigo, contenido largo, analisis complejo. La prueba es simple: ejecuta el prompt una vez y mide la tasa de errores. Si supera el 15%, Reflection vale la pena. Si esta por debajo, un solo prompt es mas eficiente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfEs mejor un Critic separado o auto-reflexi\u00f3n?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Un Critic separado es m\u00e1s objetivo. La auto-reflexi\u00f3n sufre de sesgo de confirmaci\u00f3n, el modelo tiende a validar su propio trabajo en lugar de encontrar fallos reales. El costo es una llamada adicional al modelo, pero la calidad de la cr\u00edtica mejora significativamente. En producci\u00f3n, la diferencia es medible.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfCu\u00e1ntas iteraciones de Reflection?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Depende del caso, pero la mayor\u00eda de sistemas en producci\u00f3n se benefician de 2-3 iteraciones m\u00e1ximo. Despues de eso, la mejora marginal disminuye rapidamente y el costo crece linealmente. Siempre define una condici\u00f3n de parada expl\u00edcita. Un bucle sin l\u00edmite es una bomba de tiempo financiera.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfQu\u00e9 es una condici\u00f3n de parada en Reflection?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Es el criterio que termina el bucle de reflection. Puede ser un m\u00e1ximo de iteraciones (ej: 3 intentos), una se\u00f1al explicita del critic (ej: \u00abOUTPUT_ACCEPTABLE\u00bb), o un umbral de confianza. Sin condici\u00f3n de parada, el bucle se ejecuta hasta agotar el contexto o el rate limit.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfReflection funciona con modelos locales peque\u00f1os?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">S\u00ed, pero el beneficio depende de la capacidad del modelo. Un modelo de 7B puede mejorar c\u00f3digo simple con Reflection, pero para tareas complejas necesitas al menos 13B. La reflexi\u00f3n amplifica las capacidades del modelo, no las crea. Un modelo incapaz de generar c\u00f3digo correcto en el primer intento probablemente tampoco ser\u00e1 capaz de corregirlo en el segundo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfC\u00f3mo evito que el bucle de Reflection crezca indefinidamente en contexto?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Limita el historial de conversaci\u00f3n a las iteraciones relevantes. En lugar de acumular todo el historial, pasa solo el output actual y la cr\u00edtica m\u00e1s reciente. O usa res\u00famenes compresivos de iteraciones anteriores. Lo que vimos fue que truncar despu\u00e9s de la tercera iteraci\u00f3n manten\u00eda la calidad sin inflar el contexto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusi\u00f3n<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Reflection funciona. Pero no es bonito. Cuesta m\u00e1s de lo que parece, requiere m\u00e9tricas que nadie quiere mantener, y siempre hay ese caso donde el Critic se vuelve demasiado permisivo o demasiado severo y tienes que reescribir sus criterios.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que hace en la pr\u00e1ctica es reducir la variabilidad del output. Un modelo competente produce buenos resultados la mayor\u00eda de las veces. Reflection hace que esos buenos resultados sean consistentes, incluso en los d\u00edas en que el modelo tiene un mal d\u00eda.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La implementaci\u00f3n que funciona no es la mas elegante. Es la que tiene un Critic con criterios claros, un m\u00e1ximo de iteraciones razonable, y un plan B cuando el bucle falla. Todo lo dem\u00e1s es optimizacion.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Patr\u00f3n Reflection para LLMs: Generator-Critic, bucles de feedback, condiciones de parada. Cu\u00e1ndo usarlo, anti-patrones y ejemplos.<\/p>\n","protected":false},"author":1,"featured_media":672,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[135,6],"tags":[125,121,133,134,123,82,86,85,131,132],"class_list":["post-671","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-agentes","category-ia-automatizacion","tag-agentes-ia","tag-agentic-patterns","tag-feedback-loop","tag-generator-critic","tag-google-adk","tag-langchain","tag-langgraph","tag-llm","tag-reflection","tag-self-correction"],"_links":{"self":[{"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/posts\/671","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/comments?post=671"}],"version-history":[{"count":5,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions"}],"predecessor-version":[{"id":695,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions\/695"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/media\/672"}],"wp:attachment":[{"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/media?parent=671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/categories?post=671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/atlaszn.com\/blog\/wp-json\/wp\/v2\/tags?post=671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}