Módulo 5: Modos de fallo y resiliencia para IA

Fallback y degradación elegante

Descripción

Ya tienes el timeout que convierte un cuelgue en una excepción atrapable (lección 4). Ahora la pregunta es: cuando el modelo falla —caído, lento, rate-limited—, ¿qué respondes? Hay dos respuestas posibles y una es mucho mejor que la otra. La mala es nada: el request se cae, el cliente ve un error, la feature no funciona. La buena es una respuesta peor pero válida: en vez de la búsqueda semántica que entiende la intención, una búsqueda por keywords que al menos encuentra productos relevantes; en vez del dato fresco del modelo, la última respuesta cacheada. Esta lección instala la mitigación central del módulo: el fallback —degradar a una ruta más simple cuando el modelo falla— y la degradación elegante —dar una respuesta parcial o peor, marcada como tal, en vez de caerse—.

En la lección 1 mediste el efecto de un fallback binario (modelo o keywords). Aquí lo desarrollas en su forma completa: una cascada de fallback con varios niveles —semántica → cache → keywords—, donde cada nivel es peor que el anterior pero mejor que caerse, y donde la respuesta degradada se marca para que el sistema (y a veces el usuario) sepa que no es la óptima. Vas a ver, ejecutado, la búsqueda de Mercado atravesando esa cascada durante una caída del modelo, con la disponibilidad subiendo de 70% a 100% y las respuestas etiquetadas por su nivel de calidad.

Conexión con el módulo. La lección 4 te dio el timeout, que habilita el fallback (sin cortar la espera, no hay a qué degradar). Esta lección construye el fallback encima. Y prepara la 6: el circuit breaker decide cuándo saltarse el modelo e ir directo al fallback, pero el fallback en sí —a dónde vas cuando te saltas el modelo— es lo de aquí. La frontera con la guía de resiliencia es dura: la degradación elegante y el load shedding como patrones generales se enseñan en resilience-and-reliability-patterns-guide M7; aquí los aplicamos al componente de IA —qué significa "degradar" cuando la ruta preferida es un LLM— y remitimos allá para el patrón completo.

Una analogía: el elevador, las escaleras y la escalera de mano

Vuelve al edificio de la lección 1, pero mira que no tiene una ruta de respaldo, sino varias, ordenadas de mejor a peor. La ruta preferida es el elevador: rápido, cómodo, llega a todos los pisos. Si el elevador falla, está la escalera principal: más lenta y cansada, pero segura, amplia, con barandal, te lleva a cualquier piso. Y si por alguna razón la escalera principal está bloqueada (una obra, un incendio en ese tramo), está la escalera de emergencia: incómoda, estrecha, la usas solo si no hay de otra, pero existe y te saca del edificio. Un edificio bien diseñado tiene esta cascada: la ruta óptima, la buena, y la de último recurso. Nunca te quedas sin ninguna forma de subir o bajar.

Fíjate en dos cosas. Primero, cada nivel es peor que el anterior pero infinitamente mejor que "nada": la escalera de emergencia es incómoda, pero comparada con quedarte atrapado, es excelente. Segundo, y esto es clave, cuando usas la escalera, sabes que estás usando la escalera: no te engañas pensando que vas en elevador. La degradación es honesta —te subes las escaleras conscientemente, aceptando que tardarás más—. Un edificio que te hiciera creer que vas en elevador mientras subes a pie sería peor que uno que te dijera la verdad, porque planearías mal tu tiempo.

Aquí está el punto: el fallback de un sistema de IA es una cascada de rutas, ordenadas de mejor a peor, donde la respuesta degradada se sirve honestamente marcada como degradada. La búsqueda semántica es el elevador (entiende la intención); la respuesta cacheada es la escalera principal (buena, pero puede estar un poco vieja); la búsqueda por keywords es la escalera de emergencia (no entiende la intención, pero encuentra productos que contienen esas palabras). Cuando el modelo cae, el sistema baja por la cascada hasta el primer nivel que funcione, sirve esa respuesta, y la marca como degradada —para el monitoreo, y a veces para el usuario ("resultados aproximados; la búsqueda inteligente no está disponible ahora")—. El usuario nunca se queda atrapado; recibe la mejor ruta disponible en ese momento, sabiendo que no es la óptima.

Ejemplo trabajado: la cascada de fallback

Vamos a construir la cascada. La búsqueda de Mercado tiene tres niveles:

  • semantic (óptimo): el LLM entiende la intención de la query. Es la ruta preferida. Puede fallar (modelo caído).
  • cache (degradado): respuestas recientes guardadas para queries populares. No depende del modelo. Cubre las queries que ya se vieron.
  • keyword (degradado): búsqueda literal por palabras sobre el catálogo. No depende del modelo, no entiende intención, pero siempre devuelve algo relevante. Es la red de seguridad final.

resilient_search implementa la cascada: intenta semantic; si falla, busca en cache; si no está en cache, cae a keyword. Nunca se queda sin respuesta. Cada resultado se etiqueta con su tier y un flag degraded. Simulamos una caída del modelo en los índices 4, 5 y 6 (3 de 10 requests → modelo 70% disponible) y medimos la disponibilidad con y sin la cascada.

# Leccion 5: FALLBACK y DEGRADACION. La busqueda semantica cae a una ruta
# mas simple cuando el modelo falla: primero una respuesta cacheada, luego
# busqueda por keywords. El usuario SIEMPRE recibe algo (peor, pero no un
# error). Medimos disponibilidad CON vs SIN fallback y que TIER sirvio cada
# request. Degradacion elegante a fondo: resilience-and-reliability M7.

CATALOG = [
    (1, "audifonos inalambricos con cancelacion de ruido"),
    (2, "cafetera de goteo programable"),
    (3, "mochila impermeable para laptop"),
    (4, "teclado mecanico retroiluminado"),
    (5, "audifonos deportivos resistentes al agua"),
]


class ModelError(Exception):
    pass


# El modelo semantico esta caido en una ventana (indices 4..6).
OUTAGE = set(range(4, 7))

QUERIES = ["audifonos", "cafetera", "mochila laptop", "teclado",
           "audifonos", "cafetera", "audifonos agua", "mochila",
           "teclado luz", "cafetera"]

# Respuestas recientes cacheadas (una ruta de fallback sin modelo).
CACHE = {"audifonos": [1, 5], "cafetera": [2]}


def semantic_search(i, query):
    if i in OUTAGE:
        raise ModelError("modelo semantico caido")
    words = query.split()
    return [pid for pid, name in CATALOG if any(w in name for w in words)]


def keyword_search(query):
    words = query.split()
    return [pid for pid, name in CATALOG if any(w in name for w in words)]


def resilient_search(i, query):
    # Cascada de fallback: semantic -> cache -> keyword. Nunca se cae.
    try:
        return ("semantic", semantic_search(i, query), False)   # tier, hits, degradado
    except ModelError:
        pass
    if query in CACHE:
        return ("cache", CACHE[query], True)
    return ("keyword", keyword_search(query), True)


# --- Modo A: SIN fallback (solo semantica) ---
responded_A = 0
for i, q in enumerate(QUERIES):
    try:
        semantic_search(i, q)
        responded_A += 1
    except ModelError:
        pass   # sin fallback: el usuario ve un error
avail_A = responded_A / len(QUERIES) * 100

# --- Modo B: CON cascada de fallback ---
tiers = {"semantic": 0, "cache": 0, "keyword": 0}
print(f"{'req':<5}{'query':<16}{'tier':<10}{'resultados':<14}calidad")
print("-" * 58)
for i, q in enumerate(QUERIES):
    tier, hits, degraded = resilient_search(i, q)
    tiers[tier] += 1
    quality = "degradado" if degraded else "optimo"
    print(f"{i:<5}{q:<16}{tier:<10}{str(hits):<14}{quality}")
responded_B = len(QUERIES)
avail_B = responded_B / len(QUERIES) * 100

print("-" * 58)
print(f"Disponibilidad:  SIN fallback {responded_A}/{len(QUERIES)} = {avail_A:.0f}%   "
      f"|   CON fallback {responded_B}/{len(QUERIES)} = {avail_B:.0f}%")
print(f"Tiers servidos:  semantic={tiers['semantic']}  "
      f"cache={tiers['cache']}  keyword={tiers['keyword']}")
print(f"Respuestas degradadas (peores, pero validas): "
      f"{tiers['cache'] + tiers['keyword']}")

Qué esperar. Al correr el archivo, la salida es exactamente esta:

req  query           tier      resultados    calidad
----------------------------------------------------------
0    audifonos       semantic  [1, 5]        optimo
1    cafetera        semantic  [2]           optimo
2    mochila laptop  semantic  [3]           optimo
3    teclado         semantic  [4]           optimo
4    audifonos       cache     [1, 5]        degradado
5    cafetera        cache     [2]           degradado
6    audifonos agua  keyword   [1, 5]        degradado
7    mochila         semantic  [3]           optimo
8    teclado luz     semantic  [4]           optimo
9    cafetera        semantic  [2]           optimo
----------------------------------------------------------
Disponibilidad:  SIN fallback 7/10 = 70%   |   CON fallback 10/10 = 100%
Tiers servidos:  semantic=7  cache=2  keyword=1
Respuestas degradadas (peores, pero validas): 3

Lee la tabla, porque muestra la cascada bajando nivel por nivel.

Fuera de la caída, todo va por el nivel óptimo. Los requests 0-3 y 7-9 se sirvieron por semantic: el modelo estaba sano, entendió la intención, dio la mejor respuesta. La cascada no cobra ningún costo cuando la ruta preferida funciona; solo entra en acción cuando hace falta.

Durante la caída (requests 4, 5, 6), la cascada baja de nivel. Mira lo que pasó cuando el modelo estaba caído:

  • Request 4 ("audifonos"): falló semantic, pero "audifonos" está en el CACHE, así que se sirvió del cache —los productos [1, 5], la última respuesta buena guardada—. Degradado, pero relevante y rápido.
  • Request 5 ("cafetera"): igual, falló semantic, "cafetera" está en cache, se sirvió del cache [2].
  • Request 6 ("audifonos agua"): falló semantic, y "audifonos agua" no está en el cache (es una query que no se había visto), así que la cascada bajó un nivel más, a keyword —búsqueda literal—, que encontró [1, 5] (los dos productos con "audifonos" en el nombre, uno de ellos con "agua"). El último recurso, y aun así devolvió resultados relevantes.

Los tres se sirvieron degradados —marcados como tal en la columna "calidad"—, pero los tres devolvieron productos. El usuario que buscó durante la caída no vio un error ni una página vacía; vio resultados un poco peores (sin la comprensión semántica de la intención), etiquetables como aproximados.

La disponibilidad: de 70% a 100%. Sin fallback, el sistema respondió 7 de 10 (falló en los 3 requests de la caída) = 70%. Con la cascada, respondió 10 de 10 = 100%. Como en la lección 1, el modelo tiene la misma disponibilidad (70% en este experimento); lo que cambió es que el sistema dejó de depender del modelo para responder. Y el desglose por tier cuenta la historia completa: 7 óptimos, 2 por cache, 1 por keyword —3 respuestas degradadas pero válidas que, sin la cascada, habrían sido 3 errores—.

La implicación arquitectónica: degradar es cualitativamente distinto de caerse. Un sistema que se cae le dice al usuario "no puedo ayudarte"; un sistema que degrada le dice "puedo ayudarte un poco peor". La diferencia, a escala de Mercado, es enorme: durante una caída del modelo de veinte minutos, el sistema sin fallback pierde todo el tráfico de búsqueda (y las ventas que venían de ahí), mientras el sistema con cascada sigue vendiendo, con una búsqueda menos inteligente pero funcional. La resiliencia no es evitar la degradación; es elegir degradar en vez de caer.

Profundización: cómo se diseña una buena cascada de fallback

La regla de oro: el fallback no debe compartir la dependencia frágil. Esto es lo que hace que la disponibilidad se multiplique a tu favor (lo calculaste en el ejercicio 2 de la lección 1). Si tu fallback también llamara al modelo —por ejemplo, "si el modelo grande falla, intenta el modelo pequeño"— y la caída fuera del proveedor entero (no de un modelo específico), el fallback caería junto con la ruta preferida y no ganarías nada. Por eso el último nivel de la cascada debe ser determinista y local: la búsqueda por keywords corre en tu propio proceso, sin red, sin API externa. Es la escalera de emergencia que funciona aunque se corte la luz de todo el edificio. Un fallback que depende de lo mismo que la ruta preferida es un fallback de mentira.

La cascada se ordena de mejor calidad a mayor independencia. Fíjate en el orden: semantic (mejor calidad, pero depende del modelo) → cache (buena calidad, independiente del modelo pero limitada a lo ya visto) → keyword (peor calidad, totalmente independiente y siempre disponible). El principio: arriba pones lo mejor aunque sea frágil, abajo pones lo más robusto aunque sea peor, y el sistema baja hasta el primer nivel que funcione. El nivel de más abajo debe ser el más robusto de todos —tu red de seguridad final— porque es el que atrapa todo lo que los de arriba dejan caer. Si el nivel más bajo pudiera fallar, tendrías un agujero.

Los tipos de fallback, aplicados a IA. La cascada del ejemplo usa tres tipos, y vale nombrarlos porque los combinarás según la feature:

  • Ruta determinista alterna (keywords en vez de semántica): una implementación más simple y sin IA que resuelve el mismo problema peor. Es el fallback más robusto porque no comparte nada con la ruta de IA.
  • Respuesta cacheada (la última respuesta buena): sirves lo que ya tenías. Bueno para queries repetidas; inútil para queries nuevas. Es el GPS dándote la última ruta conocida.
  • Modelo más simple / más barato (un modelo pequeño en vez del grande): útil cuando el fallo es de capacidad (el modelo grande está saturado) pero no cuando el fallo es del proveedor entero (ambos modelos caen juntos). Úsalo con cuidado: comparte la dependencia de red con la ruta preferida.

Para el agente de soporte, la cascada sería distinta: modelo → respuesta de plantilla para preguntas comunes → escalar a un humano (la degradación final, del empleado que escala en vez de inventar, lección 3). El humano es el "keyword" del soporte: más lento y caro, pero siempre resuelve.

La degradación honesta: marca lo degradado. Volvamos a la lección de la analogía: cuando usas las escaleras, sabes que usas las escaleras. En el ejemplo, cada respuesta lleva un flag degraded. Ese flag tiene dos usos. Uno, para el monitoreo: si de repente el 80% de las respuestas son degradadas, tienes una caída del modelo en curso y quieres saberlo (conecta con el monitoreo de la lección 7). Dos, para el usuario, cuando aplica: una etiqueta discreta ("resultados aproximados; la búsqueda inteligente volverá pronto") gestiona la expectativa. No siempre expones el flag al usuario —para una búsqueda, quizás no—, pero siempre lo registras. Lo que nunca haces es servir una respuesta degradada fingiendo que es óptima, porque eso rompe la confianza cuando el usuario nota la diferencia y no entiende por qué.

Anatomía de la cascada:

   query del usuario
        │
        ▼
   ┌───────────┐  falla   ┌───────────┐  no esta  ┌───────────┐
   │ semantic  │─────────►│  cache    │──────────►│ keyword   │
   │ (optimo)  │          │(degradado)│           │(degradado)│
   └───────────┘          └───────────┘           └───────────┘
        │                      │                       │
      sirve                  sirve                   sirve
    (optimo)              (si hay hit)            (SIEMPRE: red final)
        │                      │                       │
        └──────────────────────┴───────────────────────┘
                               ▼
                    el usuario SIEMPRE recibe resultados

Errores comunes

No tener fallback y caer todo cuando el modelo cae. Qué pasa: la búsqueda es una llamada directa al modelo sin ninguna ruta alterna; el día de una caída del proveedor, la búsqueda de Mercado deja de funcionar por completo y se lleva consigo una parte del tráfico y las ventas. Por qué pasa: se diseñó el camino feliz, el fallo nunca se vio en desarrollo. Cómo detectarlo: traza qué pasa cuando la llamada al modelo lanza una excepción; si la respuesta es "el request falla", no tienes fallback. Cómo corregirlo: pon una cascada de fallback con un nivel final determinista y local. El ejemplo lo mide: sin fallback 70%, con cascada 100%.

Un fallback que depende de lo mismo que la ruta preferida. Qué pasa: el equipo pone como fallback "si el modelo grande falla, usa el modelo pequeño del mismo proveedor"; el día que el proveedor entero cae, ambos modelos caen juntos y el fallback no sirve de nada. Por qué pasa: se pensó el fallback como "otra forma de hacer IA" sin ver que comparte la dependencia frágil (la red al proveedor). Cómo detectarlo: tu último nivel de fallback llama a una API externa o al mismo proveedor que la ruta preferida. Cómo corregirlo: el nivel final de la cascada debe ser determinista y local, sin la dependencia frágil —keywords en memoria, una plantilla, una respuesta cacheada localmente—. El fallback debe sobrevivir a la caída que se supone que cubre.

Degradar sin marcarlo (o sin monitorearlo). Qué pasa: el sistema cae a keywords silenciosamente y sirve resultados peores sin registrar que está degradado; una caída del modelo de horas pasa desapercibida porque "el sistema respondía" —peor, pero respondía—, y nadie se entera hasta que las métricas de conversión bajan. Por qué pasa: el fallback funcionó demasiado bien —tapó el problema en vez de degradar visiblemente—. Cómo detectarlo: no tienes una métrica de "% de respuestas degradadas"; no sabrías si estás sirviendo el 5% o el 95% por fallback. Cómo corregirlo: marca cada respuesta con su tier y monitorea la proporción degradada; un pico de degradación es una alarma de que la ruta preferida está fallando. El flag degraded del ejemplo existe justo para esto. Degradar es bueno; degradar a ciegas es esconder un incendio.

Ejercicios

Ejercicio 1 — Diseña la cascada del agente de soporte. La búsqueda tiene la cascada semántica → cache → keywords. Diseña la cascada de fallback equivalente para el agente de soporte de Mercado (que responde preguntas de clientes), con al menos tres niveles ordenados de mejor a peor, y di cuál es el nivel final que nunca falla y por qué.

Ver solución

Una cascada razonable para el agente de soporte, de mejor a peor:

  1. Agente LLM completo (óptimo): entiende la pregunta libre del cliente y responde con datos verificados contra la fuente de verdad (lección 3). Ruta preferida; depende del modelo.
  2. Respuestas de plantilla para preguntas frecuentes (degradado): para las preguntas más comunes ("¿dónde está mi pedido?", "¿cómo devuelvo un producto?"), una plantilla determinista que rellena datos de la base de datos. No entiende preguntas raras, pero cubre el grueso del volumen sin el modelo. Independiente del modelo.
  3. Escalar a un humano (degradado, último recurso): un agente humano recibe la conversación. Más lento y caro, pero resuelve cualquier cosa.

El nivel final que nunca falla es escalar a un humano. Nunca falla porque no depende de ninguna pieza técnica frágil (ni del modelo, ni de una plantilla que cubra el caso): un humano puede atender cualquier pregunta, incluso las que ninguna plantilla previó. Es el equivalente al keyword de la búsqueda —la red de seguridad final, más costosa pero universal—. La diferencia con la búsqueda es que aquí el último recurso es humano en vez de determinista, porque el soporte toca casos (dinero, reclamos) donde un humano es la única garantía. Es exactamente el empleado que escala al supervisor de la lección 1.

Ejercicio 2 — Por qué el orden de la cascada importa. En el ejemplo, la cascada es semántica → cache → keyword. Explica qué pasaría con la calidad de las respuestas si invirtieras el orden a keyword → cache → semántica, y por qué el orden correcto pone lo mejor arriba y lo más robusto abajo.

Ver solución

Si invirtieras el orden a keyword → cache → semántica, la cascada serviría siempre por keyword —el primer nivel—, porque keyword nunca falla (es determinista y local, siempre devuelve algo). La cascada nunca bajaría a los otros niveles, así que nunca usarías la búsqueda semántica ni el cache, aunque el modelo estuviera perfectamente sano. Servirías la peor calidad el 100% del tiempo, incluso cuando la mejor estaba disponible. Sería como usar siempre la escalera de emergencia teniendo el elevador funcionando.

El orden correcto pone lo mejor arriba (semántica) porque quieres servir la máxima calidad siempre que se pueda, e intentas ese nivel primero. Pone lo más robusto abajo (keyword) porque ese nivel es la red de seguridad: solo llegas a él cuando todos los de arriba fallaron, y necesitas que ese último nivel no pueda fallar. La cascada baja "buscando el primer nivel que funcione", así que el primero debe ser el de mejor calidad y el último el de mayor robustez. Invertir el orden convierte la red de seguridad en la ruta principal, tirando toda la calidad a la basura.

Ejercicio 3 — Degradación parcial dentro de una respuesta. La cascada del ejemplo degrada toda la respuesta a un nivel inferior. Pero a veces puedes degradar solo parte de una respuesta. Imagina la página de producto de Mercado, que muestra: (a) el precio y stock (de la base de datos), (b) la descripción generada por IA, y (c) recomendaciones "productos similares" generadas por IA. Si el modelo cae, ¿qué parte de la página degradas y cómo, y qué parte no se toca? ¿Por qué esto es mejor que caer la página entera?

Ver solución

Con el modelo caído, degradas solo las partes que dependen de la IA, y dejas intactas las que no:

  • (a) Precio y stock → NO se tocan. Vienen de la base de datos determinista, no del modelo. La caída del modelo no los afecta en absoluto; se muestran normales.
  • (b) Descripción generada por IA → degradar. Si la descripción se genera al vuelo con el modelo, cae a una descripción cacheada (la última generada, guardada) o a los atributos crudos del producto de la ficha ("Audífonos. Inalámbricos. 30 h batería."). Peor redactada, pero informativa.
  • (c) Recomendaciones por IA → degradar u ocultar. Cae a recomendaciones no personalizadas (los más vendidos de la categoría, calculados sin IA) o, si no hay buena alternativa, simplemente se oculta la sección —una página sin "productos similares" sigue siendo perfectamente usable—.

Esto es mejor que caer la página entera porque la mayor parte de la página no depende del modelo: el cliente todavía puede ver el precio, el stock, y comprar el producto. Caer la página completa por un fallo que solo afecta a dos secciones secundarias sería tirar la venta por un problema cosmético. La degradación parcial aísla el fallo a las partes afectadas y mantiene funcional el núcleo del negocio (poder comprar). Es la degradación elegante en su forma más fina: no todo o nada, sino "cada parte degrada a su propio fallback, y lo que no depende del modelo ni se entera". La guía de resiliencia (M7) trata este patrón a fondo.

Resumen y siguiente paso

En esta lección instalaste la mitigación central del módulo: el fallback —degradar a una ruta más simple cuando el modelo falla— y la degradación elegante —una respuesta peor pero válida, marcada como tal, en vez de caerse—. Lo viste con el edificio y su cascada de rutas (elevador → escalera principal → escalera de emergencia), y lo mediste: la búsqueda de Mercado bajó por la cascada semántica → cache → keyword durante una caída del modelo, la disponibilidad subió de 70% a 100%, y 3 de 10 respuestas se sirvieron degradadas pero válidas —2 por cache, 1 por keyword— en vez de fallar. Retuviste las reglas de una buena cascada: el nivel final debe ser determinista y local (no compartir la dependencia frágil), se ordena de mejor calidad arriba a mayor robustez abajo, y lo degradado se marca —para el monitoreo y a veces para el usuario— nunca se sirve fingiendo que es óptimo.

Antes de avanzar deberías poder: diseñar una cascada de fallback con niveles ordenados y un último recurso robusto; explicar por qué el fallback no debe compartir la dependencia frágil de la ruta preferida; argumentar por qué degradar es cualitativamente mejor que caer; y reconocer cuándo conviene una degradación parcial (por sección) en vez de total. La degradación como patrón general vive en resilience-and-reliability-patterns-guide M7; aquí la aplicamos a la IA.

La lección 6 responde una pregunta que el fallback deja abierta: durante una caída prolongada, ¿tiene sentido seguir intentando el modelo en cada request —pagando el timeout cada vez— antes de caer al fallback? No. El circuit breaker detecta que el modelo viene fallando y deja de llamarlo por un rato, yendo directo al fallback y ahorrando el timeout, el costo por llamada, y —clave en IA— la carga sobre un modelo que quizás está rate-limited justo por exceso de llamadas. Vas a medir cómo el breaker recorta las llamadas al modelo de 16 a 10 y el costo de $0.032 a $0.020 durante una caída.

Recursos

  • resilience-and-reliability-patterns-guide (este ecosistema), M7 "Degradación elegante y load shedding" — la referencia central para la mecánica de la degradación que aquí aplicamos: cómo degradar funcionalidad por prioridad, cómo hacer degradación parcial, cómo soltar carga bajo presión. En español.
  • Martin Fowler y Bharani Subramaniam, "Emerging Patterns in Building GenAI Apps" — martinfowler.com/articles/gen-ai-patterns. Trata los fallbacks y las rutas degradadas alrededor de un componente de IA como patrones de primera clase. En inglés.
  • Chip Huyen, AI Engineering (O'Reilly, 2024). Los capítulos sobre confiabilidad tratan las rutas de respaldo (modelo más simple, caché, respuesta por defecto) como parte del diseño de una aplicación con modelos. En inglés.
  • architecture-for-ai-native-systems-guide, Módulo 2 (caché de respuestas) — el cache que aquí usamos como nivel de fallback se diseñó allá como optimización de latencia/costo; aquí cumple doble función como ruta degradada. En español.