ruta backend / módulo 6

M6 — AI / Agentic

Outcome del módulo: un mini-RAG o agente demostrable, con evals, integrado como feature real (no demo aislada). Explicar por qué cada decisión (chunking, modelo, retrieval) y probarlo con una eval.

Regla del módulo: cualquiera llama a un LLM; el valor está en lo que lo rodea — retrieval, evals, control de costo/latencia y confiabilidad. Ahí está el diferenciador de backend, no en el prompt.


Concepto 1 — Fundamentos LLM (tokens, context, structured output, tool calling)

Idea núcleo: un LLM predice tokens dado un contexto acotado. Para backend, lo que importa es controlar entrada/salida: límites de contexto, salida estructurada y llamadas a funciones.

Entender (capa 1)

Texto:

Visual:

flowchart LR
    P[prompt + contexto] --> LLM[LLM]
    LLM -->|texto| T[respuesta libre]
    LLM -->|schema| S[JSON/pydantic validado]
    LLM -->|tool call| F[pide ejecutar función args]

Video: How LLMs Work - Tokens, Context Windows, and API Costs Explained — Data Whisperer Academy

Ejemplo (structured output):

from pydantic import BaseModel
class Extraction(BaseModel):
    name: str
    amount: float
    currency: str
# pedir al LLM que devuelva EXACTA esta estructura → parseable, integrable
result: Extraction = llm.extract(text, schema=Extraction)

Fijar (capa 2)

Nota atómica:

Feynman: “Texto libre es pedirle a alguien que te cuente algo y transcribirlo a mano. Structured output es darle un formulario: llena los campos exactos que tu sistema espera.”

Aplicar (capa 3)

Hacé una extracción con structured output (pydantic) sobre un texto. Contá los tokens de entrada/salida. Definí una tool y hacé que el modelo la invoque.

Límites


Concepto 2 — RAG (Retrieval-Augmented Generation)

Idea núcleo: en vez de meter todo al prompt, recuperás solo los fragmentos relevantes de tu base de conocimiento y se los das al modelo. Respuestas fundadas en tus datos, sin reentrenar.

Entender (capa 1)

Texto: pipeline: (1) chunking — partir documentos en fragmentos; (2) embeddings — convertir cada chunk en un vector; (3) guardarlos en un vector store; (4) en la query, embeber la pregunta y traer los chunks más cercanos (retrieval); (5) opcional reranking para ordenar mejor; (6) pasar esos chunks como contexto al LLM.

Visual:

flowchart LR
    subgraph Ingesta
      D[docs] --> CH[chunking] --> EMB[embeddings] --> VS[(vector store)]
    end
    subgraph Query
      Q[pregunta] --> QE[embedding] --> RET[retrieve top-k] --> RR[rerank] --> CTX[contexto] --> LLM[LLM] --> A[respuesta fundada]
    end
    VS --> RET

Video: What is Retrieval-Augmented Generation (RAG)? — IBM Technology

Ejemplo (conceptual):

# ingesta
for chunk in chunk_document(doc, size=500, overlap=50):
    store.add(embed(chunk), metadata={"source": doc.id})
# query
hits = store.search(embed(pregunta), top_k=5)
contexto = "\n".join(h.text for h in hits)
respuesta = llm.answer(pregunta, context=contexto)   # fundada en TUS datos

Fijar (capa 2)

Nota atómica:

Feynman: “RAG es un examen a libro abierto: no memorizás toda la enciclopedia (reentrenar) ni la cargás entera al escritorio (prompt gigante). Buscás las 3 páginas que necesitás y respondés con eso a la vista.”

Aplicar (capa 3)

Armá un mini-RAG sobre un set de docs público: chunking + embeddings + pgvector + retrieval top-k. Probá con 5 preguntas y observá qué chunks trae.

Límites


Concepto 3 — Vector stores

Idea núcleo: una DB especializada en búsqueda por similitud de vectores (nearest neighbor), no por igualdad exacta.

Entender (compacto):


Concepto 4 — Agentes (LangGraph, tool-calling, estado)

Idea núcleo: un agente es un LLM en un loop que decide acciones (llamar tools), observa resultados y sigue, hasta cumplir un objetivo. LangGraph modela ese loop como un grafo de estados.

Entender (capa 1)

Texto: a diferencia de una llamada única, el agente itera: piensa → elige una tool → ejecuta → observa → decide el siguiente paso. LangGraph te da un grafo explícito (nodos = pasos, edges = transiciones) con estado compartido, en vez de un loop implícito difícil de controlar/debuggear.

Visual:

flowchart TD
    START[objetivo] --> THINK[LLM decide]
    THINK -->|usar tool| TOOL[ejecuta tool] --> OBS[observa resultado] --> THINK
    THINK -->|listo| END[respuesta final]

Video: Introduction to LangGraph — LangChain (oficial)

Ejemplo (conceptual):

# nodos con estado compartido; el grafo controla el flujo
from langgraph.graph import END        # sentinel real del nodo terminal (no el string "END")
graph.add_node("plan", plan_step)
graph.add_node("act", call_tool)
graph.add_edge("plan", "act")
graph.add_conditional_edges("act", lambda s: "plan" if not s.done else END)

Fijar (capa 2)

Nota atómica:

Feynman: “Una llamada al LLM es preguntarle algo una vez. Un agente es un empleado con tareas: prueba una herramienta, ve el resultado, decide el siguiente paso. LangGraph es el organigrama que define qué puede hacer y cuándo parar, para que no se quede dando vueltas.”

Aplicar (capa 3)

Armá un agente mínimo con 1-2 tools (ej: buscar en tu RAG + una calculadora) usando LangGraph. Ponele un límite de pasos para evitar loops.

Límites


Concepto 5 — MCP (Model Context Protocol)

Idea núcleo: estándar para exponer tools/recursos a modelos/agentes de forma interoperable, en vez de integrar cada tool a mano por proveedor.

Entender (compacto):


Concepto 6 — Evals (medir que no alucina)

Idea núcleo: sin evals, “funciona” es una opinión. Las evals miden la calidad de las respuestas de forma repetible — el paso que separa un demo de un producto.

Entender (capa 1)

Texto: una eval = un dataset de casos (pregunta → respuesta esperada / criterios) + una métrica. Para RAG: relevancia del contexto recuperado, fidelidad (la respuesta se apoya en el contexto, no inventa), correctitud. La técnica central es LLM-as-judge (otro modelo puntúa) — y frameworks como RAGAS la automatizan (faithfulness, answer relevancy, context precision/recall son LLM-as-judge por dentro). Combinalo con métricas deterministas (exact match, similitud de embeddings) donde apliquen.

Visual:

flowchart LR
    DS[dataset de casos] --> RUN[correr el sistema] --> SCORE[métricas: relevancia / fidelidad / correctitud] --> GATE{¿supera umbral?}
    GATE -->|sí| SHIP[deploy]
    GATE -->|no| FIX[mejorar chunking/prompt/modelo]

Video: AI Agent Evaluation with RAGAS — James Briggs

Fijar (capa 2)

Nota atómica:

Feynman: “Sin evals, evaluás tu IA como quien prueba la sopa una vez y dice ‘buena’. Las evals son la receta con medidas: probás 50 platos con criterio y sabés si esta tanda salió peor que la anterior.”

Aplicar (capa 3)

Armá un dataset chico (10 preguntas con respuesta esperada) para tu mini-RAG y corré una eval de fidelidad/relevancia. Cambiá el chunk size y volvé a medir para ver el efecto.

Límites


Concepto 7 — Costo y latencia

Idea núcleo: en producción, un LLM es un componente con costo por token y latencia real que hay que gestionar y defender ante el negocio.

Entender (compacto):


Concepto 8 — AI-native development workflow

Idea núcleo: las herramientas de IA asistida (Cursor, Copilot, Claude Code, Devin, agent frameworks) son velocidad real de ingeniería cuando reemplazan trabajo mecánico verificable — scaffolding, refactors, schemas, migraciones — y cuando además se usan para construir agentes internos que automatizan tareas repetitivas del propio equipo; son un juguete cuando se usan para generar código que nadie revisa o para tareas donde el costo de un error supera el tiempo ahorrado.

Entender (capa 1)

Texto:

Visual:

flowchart TD
    T[tarea repetitiva de eng] --> D{es scaffolding/refactor/schema puntual, o se repite seguido?}
    D -->|puntual| A[asistente interactivo: Cursor/Copilot/Claude Code]
    D -->|se repite seguido| B[agente interno: corre solo, pega sistemas]
    A --> V[verificar output: tests + lint + review humano]
    B --> V
    V -->|pasa| M[merge / velocidad real]
    V -->|falla| F[descartar o corregir manual]

Video: Coding Agents Explained: How Claude Code, Codex & Cursor Actually Work — ByteByteAI

Ejemplo (agente interno mínimo — bot de revisión de PR):

# agente que corre en CI: lee el diff, corre checks, comenta resumen en el PR
def review_pr(pr_number: int) -> None:
    diff = github.get_diff(pr_number)
    lint_result = run_linter(diff.changed_files)
    test_result = run_tests(diff.changed_files)
    summary = llm.summarize(
        diff=diff,
        context={"lint": lint_result, "tests": test_result},
        schema=PRReviewSummary,   # structured output (Concepto 1)
    )
    github.comment(pr_number, summary.to_markdown())
    # el humano decide el merge; el agente solo acelera el triage

Fijar (capa 2)

Nota atómica:

Feynman: “Un asistente de IA es un aprendiz muy rápido: le das la tarea repetitiva (armar el CRUD, mover el schema) y la entrega en minutos, pero un ingeniero senior sigue revisando el trabajo antes de firmarlo. Un agente interno es contratar a ese aprendiz de planta para una tarea que se repite todos los días — solo tiene sentido si esa tarea realmente se repite lo suficiente como para justificar el sueldo.”

Aplicar (capa 3)

Elegí una tarea repetitiva real de tu flujo (ej: generar el boilerplate de un endpoint nuevo siguiendo el patrón del repo, o resumir diffs de PR). Hacela una vez con un asistente IA (Cursor/Copilot/Claude Code) midiendo tiempo total (generar + verificar) contra hacerla a mano. Si se repite seguido, prototipá un agente interno simple (script + LLM call) que la automatice y corré structured output para que el resultado sea consumible por otro sistema (Concepto 1).

Límites


Checklist de dominio M6

Marcás cuando podés explicar (Feynman) + aplicar:

Salida verificable del módulo: un mini-RAG sobre docs públicos (pgvector) con structured output, un dataset de eval (10 casos) que mide fidelidad/relevancia, y medición de tokens/latencia. Bonus: un agente con 1-2 tools y límite de pasos.