Conceptos básicos de RAG
10 ejemplos para empezar con Agentes de IA y RAG: 7 básicos y 3 intermedios.
Prerrequisitos
uv venv && source .venv/bin/activate
uv pip install "openai>=1.60" "chromadb>=0.5" "tiktoken>=0.8"
export OPENAI_API_KEY="sk-..."Ejemplos básicos
1. Dividir un documento
Divide texto largo en fragmentos del tamaño adecuado para la recuperación.
def chunk_text(text: str, size: int = 500, overlap: int = 50) -> list[str]:
chunks = []
start = 0
while start < len(text):
chunks.append(text[start:start + size])
start += size - overlap
return chunks- 500 caracteres con 50 de superposición es un punto de partida para prosa.
- La superposición preserva el contexto entre los límites de los fragmentos.
Relacionado: División e ingesta
2. Incrustar y almacenar fragmentos
Crea vectores y guárdalos en una colección.
import chromadb
from openai import OpenAI
client = OpenAI()
chroma = chromadb.Client()
collection = chroma.create_collection("docs")
texts = ["FastAPI es un framework web de Python.", "pytest ejecuta pruebas de Python."]
emb = client.embeddings.create(model="text-embedding-3-small", input=texts)
collection.add(ids=["1","2"], documents=texts, embeddings=[e.embedding for e in emb.data])3. Recuperar fragmentos relevantes
Consulta por similitud semántica.
query = "¿Cómo pruebo Python?"
q_emb = client.embeddings.create(model="text-embedding-3-small", input=[query])
results = collection.query(query_embeddings=[q_emb.data[0].embedding], n_results=2)
print(results["documents"])4. Construir un prompt fundamentado
Inyecta el contexto recuperado en el prompt del LLM.
context = "\n".join(results["documents"][0])
prompt = f"Responde ÚNICAMENTE usando este contexto:\n{context}\n\nPregunta: {query}"5. Generar una respuesta
Envía el prompt fundamentado al LLM.
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0,
)
print(response.choices[0].message.content)6. Función RAG de extremo a extremo
Combina recuperación + generación.
def rag_answer(query: str, collection, k: int = 3) -> str:
q_emb = client.embeddings.create(model="text-embedding-3-small", input=[query])
hits = collection.query(query_embeddings=[q_emb.data[0].embedding], n_results=k)
context = "\n---\n".join(hits["documents"][0])
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Responde solo del contexto. Di 'No lo sé' si no se encuentra."},
{"role": "user", "content": f"Contexto:\n{context}\n\nPregunta: {query}"},
],
temperature=0,
)
return resp.choices[0].message.content or ""7. Citar fuentes
Incluye los IDs de los fragmentos en la respuesta.
for i, (doc, meta) in enumerate(zip(hits["documents"][0], hits["metadatas"][0])):
print(f"[{i+1}] {doc[:80]}...")Ejemplos intermedios
8. Filtrado de metadatos
Filtra la recuperación por tipo de documento o fecha.
collection.query(
query_embeddings=[q_emb.data[0].embedding],
n_results=3,
where={"source": "docs"},
)9. Concepto de búsqueda híbrida
Combina puntuaciones de palabras clave y semánticas.
- BM25 captura términos exactos; los embeddings capturan paráfrasis.
- Ver Recuperación y reordenación.
10. Evaluar la calidad de la recuperación
Comprueba si el fragmento correcto aparece en el top-k.
def recall_at_k(query: str, expected_text: str, k: int = 5) -> bool:
hits = collection.query(query_embeddings=[embed(query)], n_results=k)
return any(expected_text in doc for doc in hits["documents"][0])Versiones de la pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.