Ir al contenido

Lab: query

Tenés el corpus indexado en Qdrant. Ahora vamos a usarlo. El comando es uno solo:

Ventana de terminal
pnpm vercel:query "¿Qué es la regla de dependencia en Clean Architecture?"

Si todo está bien, en unos segundos el LLM te va a responder citando los archivos del corpus. Vamos a ver exactamente qué pasa entre que tipeás eso y aparece la respuesta.

El código vive en packages/01-vercel-ai-sdk/src/query.ts — 96 líneas. Cuatro stages, igual que la ingestión pero al revés.

packages/01-vercel-ai-sdk/src/query.ts
const { embedding } = await embed({
model: ollama.embeddingModel(OLLAMA_EMBED),
value: question,
});

embed (singular, no embedMany) toma la pregunta y devuelve un solo vector. Lo crítico:

query.ts
const TOP_K = 4;
const results = await qdrant.query(COLLECTION, {
query: embedding,
limit: TOP_K,
with_payload: true,
});
const hits = results.points;

Le mandás el vector de la pregunta a Qdrant y le decís “dame los 4 chunks más parecidos”. with_payload: true hace que vuelva la metadata original (filename, content, índice) — sin eso solo recibís IDs y scores.

TOP_K = 4 es el default razonable para un corpus chico como el del curso. En tu propio dataset, ajustalo midiendo (vamos a ver cómo en la próxima página).

Stage 3 — Construir el prompt con contexto

Sección titulada «Stage 3 — Construir el prompt con contexto»
query.ts: prompt
const contextBlocks = hits
.map((hit) => {
const payload = hit.payload;
if (!isChunkPayload(payload)) return null;
return `[${payload.filename}]\n${payload.content}`;
})
.filter((b): b is string => b !== null);
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}`;

Tres cosas notables del prompt:

  • ONLY the context below — instrucción explícita para que no invente. Es la frase más importante del prompt entero.
  • If the context does not contain enough information, say so — habilita al modelo a admitir ignorancia. Un RAG decente prefiere “no sé” antes que alucinar.
  • [${filename}] prefix — le da al modelo señales para que pueda citar fuentes en la respuesta.
query.ts: generate
const { text } = await generateText({
model: ollama(OLLAMA_LLM),
prompt,
});
console.log('\n=== Answer ===');
console.log(text);

generateText es la función gemela de embedMany que ya viste. Le mandás el prompt completo y devuelve la respuesta. OLLAMA_LLM apunta a llama3.2:3b.

Después del texto, el script imprime las fuentes con sus scores:

query.ts: sources
hits.forEach((hit) => {
const payload = hit.payload;
if (!isChunkPayload(payload)) return;
console.log(` - ${payload.filename} (score: ${hit.score?.toFixed(4) ?? 'n/a'})`);
});
Ventana de terminal
pnpm vercel:query "¿Cuál es la regla de dependencia en Clean Architecture?"

packages/01-vercel-ai-sdk/src/query.ts en GitHub →

Si todavía no levantaste el stack local, igual querés ver lo que produce el pipeline. Este widget muestra el output real que pnpm vercel:query generó sobre el corpus del curso para 5 preguntas distintas — desde la pregunta ideal hasta la out-of-corpus que el RAG debería rechazar.

Probá con una pregunta capturada
Pregunta puntual sobre un solo doc — caso ideal
Respuesta del LLM
La regla de dependencia en Clean Architecture establece que el código fuente solo puede depender de cosas que estén más adentro. En otras palabras, nada en una capa interior puede saber absolutamente nada sobre algo en una capa exterior.
Sources (top-K) — 4 chunks
  1. [1] clean-architecture.md score 0.8170

    # Clean Architecture Clean Architecture es un enfoque arquitectónico propuesto por Robert C. Martin (Uncle Bob) que organiza el código en capas concéntricas con una regla de dependencia estricta: **las dependencias del c…

  2. [2] clean-architecture.md score 0.7574

    cíficas de la aplicación. Por ejemplo: "registrar un usuario", "transferir dinero entre cuentas". 3. **Interface Adapters (Adaptadores)**: convierten datos del formato más conveniente para los casos de uso al formato más…

  3. [3] hexagonal-architecture.md score 0.7526

    éntricas** (Entities, Use Cases, Interface Adapters, Frameworks) y la regla de dependencia entre ellas. En la práctica, muchos equipos combinan: usan el modelo de puertos/adaptadores de Hexagonal con la organización en c…

  4. [4] solid-principles.md score 0.7467

    ementan. La dirección de la dependencia se invierte: la infraestructura depende del dominio, no al revés. **Ejemplo**: en vez de que `OrderService` importe `PostgresOrderRepository` directamente, define una interfaz `Ord…

Captura: 2026-05-03 · 6990 ms · llama3.2:3b + nomic-embed-text

Cuando corrás pnpm vercel:query con tu instalación, los textos van a variar (llama3.2:3b no es determinista al 100%), pero la forma del output — chunks, scores, latencia, respuesta anclada al contexto — es exactamente esta.

Funciona — pero ¿cómo sabés si está funcionando bien? Los scores son una pista, pero no alcanzan. En la próxima página vamos a aprender a inspeccionar qué chunks recuperó el retriever y por qué, paso a paso.