← Todas las recetasReceta · 13 de septiembre de 2025

RAG casero: que tu IA responda con TUS documentos

Monta un asistente que conoce tus PDFs, notas y documentos, usando embeddings + un LLM local. Privado, gratis y sin límites de upload.

Dificultadmedia
Tiempo1 hora
IngredientesOllama · Nomic-Embed · Python · ChromaDB

La pregunta más repetida del IA local: “¿Puedo darle mis documentos a ChatGPT?” Sí, pero ¿y si no quieres subir tus documentos a la nube? RAG en local es la respuesta.

¿Qué es RAG en 20 segundos?

  1. Cortas tus documentos en trozos y los conviertes en vectores (embeddings).
  2. Cuando preguntas algo, se buscan los trozos más parecidos a tu pregunta.
  3. Se le dan esos trozos al LLM como contexto: responde basándose en TUS documentos.

Ingredientes

  • Ollama instalado (receta 1 de este blog)
  • pip install chromadb ollama

Pasos

  1. Descarga los modelos:

    ollama pull nomic-embed-text   # embeddings
    ollama pull qwen2.5:7b         # el cerebro
  2. Indexa tus documentos:

    import chromadb, ollama, pathlib
    
    client = chromadb.PersistentClient("mi-base")
    col = client.get_or_create_collection("docs")
    
    for archivo in pathlib.Path("mis-documentos").glob("*.txt"):
        texto = archivo.read_text(encoding="utf-8")
        # trocea en párrafos de ~500 caracteres
        trozos = [texto[i:i+500] for i in range(0, len(texto), 500)]
        for n, trozo in enumerate(trozos):
            emb = ollama.embed(model="nomic-embed-text", input=trozo)["embeddings"][0]
            col.add(ids=[f"{archivo.name}-{n}"], documents=[trozo], embeddings=[emb])
  3. Pregunta con contexto:

    pregunta = "¿Qué decidimos sobre el presupuesto?"
    emb = ollama.embed(model="nomic-embed-text", input=pregunta)["embeddings"][0]
    resultados = col.query(query_embeddings=[emb], n_results=3)
    
    contexto = "\n---\n".join(resultados["documents"][0])
    respuesta = ollama.chat(model="qwen2.5:7b", messages=[
        {"role": "system", "content": "Responde SOLO con el contexto dado. Si no está, dilo."},
        {"role": "user", "content": f"Contexto:\n{contexto}\n\nPregunta: {pregunta}"},
    ])
    print(respuesta["message"]["content"])

Resultado esperado

Respuestas que citan TU información. Con los modelos pequeños hay que exigirles en el system prompt que no inventen — y aun así, revisa las citas.

Trucos

  • El tamaño de trozo importa: 300-800 caracteres suele ir bien. Demasiado grande = contexto diluido; demasiado pequeño = sin contexto.
  • Para PDFs: pymupdf extrae texto en 3 líneas.
  • Si las respuestas son malas, el 90% de las veces el problema es el retrieval (los trozos recuperados), no el modelo. Depura mirando qué contexto se está pasando.
  • ChromaDB guarda todo en local y persiste. Tus documentos no salen de tu disco. 🔒