Vercel AI SDK — el minimalista
Filosofía
Sección titulada «Filosofía»Vercel AI SDK no es “un framework de RAG”. Es una capa provider-agnostic sobre LLMs y embedders, con utilidades chiquitas (embed, embedMany, generateText, streamText). Para hacer RAG, vos componés: vos llamás embed(), vos llamás qdrant.query(...), vos armás el prompt, vos llamás generateText().
Cero abstracción de alto nivel. El framework ni siquiera sabe que estás haciendo RAG. Te da las cuatro piezas y vos las cosés.
Tradeoff: más LOC, más control. Si necesitás meter mano en cualquier paso (un retriever propio, una métrica custom, un wrapper de logging), no hay capa que romper — el código ya es vos.
Cómo se hace ingest
Sección titulada «Cómo se hace ingest»packages/01-vercel-ai-sdk/src/ingest.ts — 76 líneas. Mostramos los 3 stages clave:
const docs = await loadMarkdownDir(DATA_DIR);const chunks = chunkDocs(docs);
await recreateCollection();
const embeddingModel = ollama.embeddingModel(OLLAMA_EMBED);const { embeddings } = await embedMany({ model: embeddingModel, values: chunks.map((c) => c.content),});embedMany es la primitiva del SDK: le pasás un array de strings, te devuelve un array paralelo de vectores. Internamente puede paralelizar/batchear; vos no te enterás. Sin estado, sin clases, sin builder pattern.
Cómo se hace query
Sección titulada «Cómo se hace query»packages/01-vercel-ai-sdk/src/query.ts — 96 líneas. El stage de retrieve + generate:
const { embedding } = await embed({ model: ollama.embeddingModel(OLLAMA_EMBED), value: question,});
const results = await qdrant.query(COLLECTION, { query: embedding, limit: TOP_K, with_payload: true,});
const prompt = `You are a helpful assistant. Answer the question using ONLY the context below.If the context does not contain enough information, say so.
Context:${contextBlocks.join('\n\n---\n\n')}
Question: ${question}`;
const { text } = await generateText({ model: ollama(OLLAMA_LLM), prompt,});Mirá lo que NO hay:
- No hay
retriever.search(...). Vos llamás directo a Qdrant. - No hay
chain.invoke(...). Vos armás el prompt y llamásgenerateText. - No hay magic state global.
Settings.llm = ...no existe.
Cada paso es explícito. Si querés cambiar el prompt, cambiás un string. Si querés cambiar el retriever, cambiás un await qdrant.query(...) por otra cosa.
A — el más estricto de los 4. Funciones del SDK son full generic:
const { embedding } = await embed({ model, value });// ^^^^^^^^^ inferido como number[]
const { embeddings } = await embedMany({ model, values });// ^^^^^^^^^^^ inferido como number[][]
const { text } = await generateText({ model, prompt });// ^^^^ inferido como stringSin any, sin as unknown as .... Funciona limpio con tsconfig.strict = true y noUncheckedIndexedAccess. El único cast que hace falta en el query.ts del repo es para validar el payload de Qdrant (que viene tipado unknown por diseño), y para eso hay un type guard isChunkPayload explícito.
Cuándo brilla
Sección titulada «Cuándo brilla»- Equipos TS-strict que valoran tipos limpios y errores en compile-time.
- Implementar técnicas avanzadas (Nivel 3): hybrid retrievers, rerankers, multi-query, citations. Cuando vos sos el que escribe el retriever, no hay framework que pelear.
- Edge runtime (Cloudflare Workers, Vercel Edge): el SDK se reduce a
fetch()calls. Elquery.tslo movés a edge cambiando 4 líneas (Nivel 4 / cap 04). - Provider-agnóstico: cambiar de Ollama a OpenAI a Anthropic es cambiar 1 import. La API del SDK es la misma.
Cuándo sufre
Sección titulada «Cuándo sufre»- Si querés “todo incluido”: integraciones con vector stores raros, document loaders para 30 formatos, retrievers con 15 estrategias preparadas — Vercel no te da nada de eso. Tenés que escribir o instalar piezas separadas.
- Para experimentar con agentes y tools: Vercel tiene
toolcalling pero no abstracciones de high-level agents. Si querés un agent con memory, planning, retries — Mastra te ahorra trabajo. - Si tu equipo viene de LangChain Python: la mental model es distinta. No hay Chain, no hay Runnable. Es un cambio de paradigma.
El número honesto
Sección titulada «El número honesto»LOC mínimo del query end-to-end (sin imports ni comments): 21 líneas. Latencia base: ~1842 ms sobre el corpus del curso. Las dos métricas son las más altas del nivel — Vercel paga el costo de “vos componés cada paso” pero no paga ningún costo de overhead de framework.
Lo que viene
Sección titulada «Lo que viene»LangChain.js — el opuesto de Vercel. Mismo problema, otra filosofía: “abstracciones reutilizables sobre LLMs” + ecosistema gigante. Más compacto en LOC, más conceptos para aprender.