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:
- Tokens: el modelo no ve palabras sino tokens (~¾ de palabra). Costo y límites se miden en tokens.
- Context window: cuántos tokens entran (prompt + respuesta). Excederlo = truncamiento/error → por eso RAG (traer solo lo relevante).
- Structured output: forzar que la respuesta cumpla un schema (JSON/pydantic) en vez de texto libre — clave para integrar en código.
- Function/tool calling: el modelo pide ejecutar una función (con args tipados) y vos la corrés; base de los agentes.
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:
- Front: ¿por qué structured output es clave en backend con LLMs?
- Back: porque el texto libre no es parseable de forma confiable; forzar un schema (JSON/pydantic) hace la salida determinista de forma, integrable en código y validable — convierte al LLM en un componente, no en una caja de texto.
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
- Más contexto no es mejor: cuesta más, agrega latencia y puede “perderse en el medio”. Contexto relevante > contexto largo.
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:
- Front: ¿qué problema resuelve RAG frente a meter todo en el prompt o reentrenar?
- Back: el context window es limitado y reentrenar es caro/lento. RAG trae solo los chunks relevantes en runtime → respuestas fundadas en datos propios/actualizados, barato, sin tocar el modelo. El chunking y el retrieval son donde se gana o se pierde calidad.
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
- Garbage in, garbage out: mal chunking (muy grande/chico) o embeddings pobres = retrieval malo = respuesta mala. El LLM no arregla un mal retrieval.
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):
- pgvector: extensión de Postgres — vectores en tu DB relacional. Ideal si ya usás Postgres (una sola DB, menos infra).
- Pinecone / Weaviate: vector DBs dedicadas, gestionadas, para escala grande.
- Chroma: liviana, buena para prototipos/local.
- Búsqueda = distancia (coseno/euclidiana) entre el vector de la query y los almacenados; índices ANN (HNSW) para que sea rápido a escala. Video: Vector Search in PostgreSQL Using pgvector: A Complete Tutorial — InterviewBuddies Nota atómica: Front: ¿cuándo pgvector y cuándo una vector DB dedicada? Back: pgvector si ya usás Postgres y el volumen es moderado (una sola DB, menos operación). Dedicada (Pinecone/Weaviate) cuando el volumen/latencia a escala lo justifica. Empezar por pgvector suele ser lo pragmático. Feynman: “Una DB normal busca coincidencias exactas (‘dame el usuario con id 7’). Un vector store busca lo más parecido (‘dame los 5 textos que significan algo similar a esto’), aunque no compartan ni una palabra.” Aplicar: guardá embeddings en pgvector y hacé una búsqueda top-k por similitud coseno. Límites: la calidad depende del modelo de embeddings; cambiar de modelo obliga a re-embeber todo.
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:
- Front: ¿qué ventaja da LangGraph sobre un loop de agente casero?
- Back: modela el flujo como grafo explícito con estado (nodos/edges/condiciones), lo que hace el comportamiento controlable, inspeccionable, reanudable y testeable — en vez de un while-loop implícito con prompts, difícil de debuggear y con riesgo de loops infinitos.
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
- Los agentes multiplican costo/latencia (varias llamadas) y pueden loopear; límites de pasos + observabilidad (M5) son obligatorios.
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):
- Un servidor MCP expone herramientas y datos con un contrato estándar; cualquier cliente/agente compatible las consume.
- Desacopla las tools del agente: escribís la tool una vez, la usan varios agentes/clientes.
Nota atómica: Front: ¿qué problema resuelve MCP? Back: estandariza cómo un modelo/agente accede a tools y datos externos; en vez de integraciones ad-hoc por proveedor, exponés un servidor MCP y cualquier cliente compatible lo usa. Interoperabilidad y reuso de tools.
Feynman: “MCP es el USB de las herramientas de IA: en vez de un cable propietario por cada aparato, un puerto estándar donde enchufás cualquier tool.”
Aplicar: exponé una tool simple vía un servidor MCP y consumila desde un cliente compatible.
Límites: ecosistema joven y en movimiento —
[verificar]estado/versiones antes de fijarlo como estándar de producción.
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:
- Front: ¿por qué las evals son lo que separa un demo de un producto en IA?
- Back: porque sin medición repetible no sabés si un cambio (de prompt/modelo/chunking) mejora o empeora, ni podés detectar alucinaciones/regresiones. La eval convierte “parece que anda” en un número con umbral que gatea el deploy — igual que los tests en código.
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
- LLM-as-judge tiene sesgo y costo; combiná con métricas automáticas y revisión humana en los casos límite.
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):
- Elección de modelo: el más grande no siempre; modelos chicos/rápidos para tareas simples, grandes solo donde hace falta (routing).
- Prompt caching: cachear prefijos/contexto repetido para no pagarlo cada vez.
- Batching: agrupar requests cuando el caso lo permite.
- Medir: tokens y latencia por request (cruza con M5 — observabilidad del pipeline LLM). Nota atómica: Front: ¿cómo se baja el costo/latencia de un feature LLM sin perder calidad? Back: routing de modelos (chico para lo simple, grande para lo difícil), prompt caching del contexto repetido, batching donde se pueda, y reducir contexto al relevante (mejor retrieval). Todo se decide midiendo tokens/latencia, no a ojo. Feynman: “Usar el modelo más grande para todo es contratar a un cirujano para poner una curita. Enrutás: la curita la pone la enfermera (modelo chico), el cirujano solo opera lo grave.” Aplicar: medí tokens y latencia de tu RAG; probá un modelo más chico para la parte simple y compará costo/calidad. Límites: optimizar de más antes de tener el caso andando = premature optimization; primero que funcione y tenga evals, después optimizás con datos.
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:
- Scaffolding con IA: generar la estructura repetitiva (endpoints CRUD, tests boilerplate, configs) a partir de un patrón existente en el repo — la IA copia convenciones, vos definís el contrato.
- Refactor asistido: renombrar/mover/extraer con contexto de todo el repo (no solo regex) — útil para refactors grandes que a mano tomarían horas.
- Schemas y migraciones: generar el modelo (pydantic/SQLAlchemy) y la migración (Alembic) a partir de una descripción o de un schema existente — reduce el trabajo mecánico, no la responsabilidad de revisar la migración antes de correrla en producción.
- Agentes internos: además de usar la IA como asistente interactivo, el salto senior es construir agentes que corren solos y automatizan tareas repetitivas de ingeniería del propio equipo — ej: un agente que lee un PR, corre linters/tests, resume el diff y comenta hallazgos; uno que triagea issues y les pone labels; uno que genera el changelog desde los commits. Son “pegamento” entre sistemas ya existentes (CI, tracker, repo), no productos nuevos.
- Criterio “velocidad real vs juguete”: velocidad real = el output se integra directo (pasa tests/lint/review) y el tiempo total (generar + verificar) es menor que hacerlo a mano. Juguete = generar código vistoso que igual hay que reescribir, o automatizar algo que raramente se repite (el costo de mantener el agente supera el ahorro).
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:
- Front: ¿qué separa usar IA como “velocidad real” de usarla como “juguete” en ingeniería?
- Back: que el output se verifique con el mismo rigor que código escrito a mano (tests, lint, review) y que la tarea automatizada sea lo bastante repetitiva/mecánica como para que el ahorro supere el costo de generar + verificar + mantener. Generar código sin verificar, o automatizar algo que casi no se repite, no es velocidad — es deuda técnica disfrazada de productividad.
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
- Nunca confiar ciego en schemas/migraciones generados: correrlos primero contra una DB de staging, revisar el SQL generado antes de aplicar en producción — una migración mal generada puede ser destructiva.
- Refactors grandes generados por IA necesitan test suite sólida como red de seguridad; sin tests, el refactor “silencioso” puede romper comportamiento no cubierto.
- Un agente interno mal alcanzado (sin límite de acciones, sin revisión humana en el punto correcto) puede propagar errores más rápido de lo que un humano los detecta — aplican los mismos límites de pasos/observabilidad que en agentes de producto (Concepto 4).
- No automatizar tareas de baja frecuencia: el costo de construir y mantener el agente puede superar el ahorro; medir antes de invertir.
Checklist de dominio M6
Marcás cuando podés explicar (Feynman) + aplicar:
- Fundamentos LLM (tokens, context, structured output, tool calling)
- RAG (chunking, embeddings, retrieval, reranking)
- Vector stores (pgvector vs dedicadas)
- Agentes (LangGraph, tool-calling, estado, límites de pasos)
- MCP
- Evals (dataset, fidelidad/relevancia, LLM-as-judge)
- Costo y latencia (routing, caching, batching, medición)
- AI-native development workflow (scaffolding/refactor/schemas asistidos, agentes internos, verificación de output, velocidad real vs juguete)
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.