← Retour au blog Technique IA

RAG avec Ollama : LLM Local, Données Privées, Zéro API Externe

2 juil. 20267 min

RAG (Retrieval-Augmented Generation) est la technique qui permet à un LLM de répondre à partir de vos propres documents. Mais la plupart des tutoriels envoient tout vers OpenAI ou Anthropic. Voici comment faire la même chose entièrement en local avec Ollama.

Pourquoi Local ?

Trois raisons pratiques :

  • RGPD : les données sensibles ne quittent jamais votre infrastructure
  • Coût : zéro API, zéro facture par token
  • Offline : fonctionne sans connexion internet

La contrepartie : il faut une machine suffisamment puissante (8 Go VRAM minimum pour des modèles 7B).

Stack

Ollama         → serveur LLM local (Llama 3.1, Mistral, Phi-3...)
nomic-embed    → modèle d'embedding local (via Ollama)
ChromaDB       → vector store en mémoire ou persistant
Python         → tout colle ensemble

Pipeline en 4 étapes

1. Installer Ollama et les modèles

# Installer Ollama (Linux/Mac)
curl -fsSL https://ollama.com/install.sh | sh

# Télécharger le LLM et le modèle d'embedding
ollama pull llama3.1:8b
ollama pull nomic-embed-text

2. Indexer les documents

import chromadb
import ollama

def embed(text: str) -> list[float]:
    resp = ollama.embeddings(model="nomic-embed-text", prompt=text)
    return resp["embedding"]

client = chromadb.Client()
collection = client.create_collection("docs")

documents = [
    {"id": "doc1", "text": "La politique RGPD de l'entreprise est..."},
    {"id": "doc2", "text": "Les données clients sont stockées dans..."},
]

for doc in documents:
    collection.add(
        ids=[doc["id"]],
        embeddings=[embed(doc["text"])],
        documents=[doc["text"]],
    )

3. Retrieval — trouver les passages pertinents

def retrieve(query: str, n: int = 3) -> list[str]:
    results = collection.query(
        query_embeddings=[embed(query)],
        n_results=n,
    )
    return results["documents"][0]

4. Génération avec contexte

def rag(question: str) -> str:
    passages = retrieve(question)
    context = "\n\n".join(passages)

    response = ollama.chat(
        model="llama3.1:8b",
        messages=[{
            "role": "user",
            "content": f"""Réponds à la question en te basant UNIQUEMENT sur le contexte fourni.
Si la réponse n'est pas dans le contexte, dis-le clairement.

Contexte :
{context}

Question : {question}"""
        }]
    )
    return response["message"]["content"]

Ce qui change par rapport au RAG cloud

Embedding local vs cloud : nomic-embed-text est nettement moins précis que text-embedding-3-large d’OpenAI sur des corpus complexes. Sur des documents métier en français, la différence est réelle — testez toujours sur vos données avant de choisir.

Latence : sur un Macbook M2 ou une machine Linux avec GPU mid-range, comptez 2–5 secondes pour une réponse 7B. Acceptable pour des outils internes, pas pour du temps réel.

ChromaDB en prod : pour la production, utilisez le mode persistant ou remplacez par pgvector (PostgreSQL) — plus robuste pour les volumes importants.

# ChromaDB persistant
client = chromadb.PersistentClient(path="/data/chroma")

Cas d’usage idéaux

  • Base de connaissances RH interne (contrats, politiques)
  • Support client sur documentation propriétaire
  • Assistant sur données médicales ou juridiques
  • Tout contexte où les données ne peuvent pas quitter le réseau interne
SC

Stéphanie Caumont

Product Owner IA · En savoir plus