
Vous savez déjà utiliser Ollama en ligne de commande et en Python. Mais saviez-vous qu'Ollama dispose d'un SDK Python natif avec des fonctionnalités exclusives ? Ce guide vous montre comment exploiter les Structured Outputs (sorties JSON typées), les embeddings pour la recherche sémantique, et comment construire un assistant DevOps complet en local.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- SDK natif vs LiteLLM : quand utiliser chaque approche
- Streaming : afficher les réponses en temps réel
- Structured Output : obtenir du JSON typé avec Pydantic
- Embeddings : générer des vecteurs pour la recherche sémantique
- Conversation multi-turn : maintenir le contexte entre les échanges
- TP fil rouge : construire DevOps Buddy, un assistant DevOps local
Prérequis
Section intitulée « Prérequis »Avant de commencer, assurez-vous d'avoir :
- Ollama installé (guide d'installation)
- Un modèle téléchargé :
ollama pull llama3.2:3b- Le SDK Python, avec des versions figées pour que les exemples se comportent à l'identique chez vous :
pip install ollama==0.6.2 pydantic==2.12.3Vérifiez les versions :
ollama --version # 0.16.x ou supérieurpip show ollama # 0.6.x ou supérieurSDK natif vs LiteLLM : quelle différence ?
Section intitulée « SDK natif vs LiteLLM : quelle différence ? »Les deux bibliothèques parlent au même serveur Ollama, la question n'est donc pas laquelle « marche » mais laquelle vous enferme. Le SDK natif expose l'API d'Ollama telle quelle, y compris les paramètres qui n'ont pas d'équivalent chez les autres fournisseurs. LiteLLM normalise les appels sur le format OpenAI, ce qui rend le code portable au prix du plus petit dénominateur commun. Dans le tableau ci-dessous, la ligne décisive est Structured Output : le SDK natif contraint la génération avec un schéma JSON côté serveur, là où LiteLLM passe par le mécanisme d'appel de fonctions, moins strict.
| Aspect | SDK ollama | LiteLLM |
|---|---|---|
| Installation | pip install ollama | pip install litellm |
| Scope | Ollama uniquement | 100+ providers (OpenAI, Anthropic...) |
| Structured Output | ✅ Natif avec format= | Via function calling |
| Embeddings | ✅ embed() intégré | ✅ embedding() |
| Pensée (Thinking) | ✅ think=True | ❌ |
| Cas d'usage | Scripts dédiés Ollama | Code portable multi-providers |
Recommandation : Utilisez le SDK natif si vous ciblez uniquement Ollama et voulez exploiter ses fonctionnalités spécifiques. Utilisez LiteLLM si vous voulez pouvoir basculer vers d'autres providers.
TP fil rouge : DevOps Buddy
Section intitulée « TP fil rouge : DevOps Buddy »Tout au long de ce guide, nous construisons DevOps Buddy, un assistant DevOps local qui :
- Répond aux questions DevOps en streaming
- Utilise une base de connaissances avec embeddings (mini-RAG)
- Retourne des commandes structurées avec Pydantic
Créez le répertoire de travail :
mkdir -p ~/lab-ollama && cd ~/lab-ollamapython3 -m venv .venv && source .venv/bin/activatepip install ollama==0.6.2 pydantic==2.12.3Chat basique avec le SDK natif
Section intitulée « Chat basique avec le SDK natif »La fonction chat() du SDK est l'équivalent de litellm.completion(), mais
avec une API légèrement différente.
Script 01 : Premier appel
Section intitulée « Script 01 : Premier appel »Ce premier script sert surtout à découvrir la forme de l'objet de réponse.
Regardez la partie « Métadonnées » plutôt que le texte généré : prompt_eval_count
et eval_count comptent les tokens en entrée et en sortie, total_duration
s'exprime en nanosecondes, d'où la division par 1e9. Ces trois valeurs sont
votre seul moyen de mesurer le coût réel d'un appel local, puisqu'aucune
facturation ne vient vous le rappeler.
#!/usr/bin/env python3"""TP 01 : Appel basique avec le SDK Ollama natifObjectif : Comprendre la différence avec litellm"""
from ollama import chat
# Appel simple avec le SDK natifresponse = chat( model='llama3.2:3b', messages=[ {'role': 'user', 'content': 'Explique Docker en une phrase pour un débutant.'} ])
print("=== Réponse du modèle ===")print(response.message.content)
print("\n=== Métadonnées ===")print(f"Modèle utilisé : {response.model}")print(f"Tokens prompt : {response.prompt_eval_count}")print(f"Tokens réponse : {response.eval_count}")print(f"Durée totale : {response.total_duration / 1e9:.2f}s")Exécutez le script :
python 01_chat_basique.pySortie attendue :
=== Réponse du modèle ===Docker est une technologie qui permet de créer des conteneurs virtuels, qui sontdes environnements isolés et sécurisés où les applications peuvent être exécutéessans nécessiter d'installations supplémentaires sur l'hôte.
=== Métadonnées ===Modèle utilisé : llama3.2:3bTokens prompt : 36Tokens réponse : 54Durée totale : 5.88sStreaming : réponses en temps réel
Section intitulée « Streaming : réponses en temps réel »Le streaming affiche la réponse mot par mot au fur et à mesure de la génération. C'est essentiel pour une bonne expérience utilisateur.
Script 02 : Streaming
Section intitulée « Script 02 : Streaming »Avec stream=True, chat() ne renvoie plus un objet mais un générateur :
la boucle for consomme les fragments au rythme de la génération. Deux
conséquences pratiques. Les métadonnées de fin (eval_count, total_duration)
n'arrivent que dans le dernier fragment, pas au début. Et si vous avez besoin
du texte complet ensuite, il faut le concaténer vous-même pendant la boucle,
comme le fait DevOps Buddy plus bas.
#!/usr/bin/env python3"""TP 02 : Streaming avec le SDK OllamaObjectif : Afficher la réponse en temps réel, mot par mot"""
from ollama import chat
# Streaming : la réponse arrive progressivementprint("=== Réponse en streaming ===")stream = chat( model='llama3.2:3b', messages=[ {'role': 'user', 'content': 'Donne 5 bonnes pratiques Dockerfile, très bref.'} ], stream=True # Active le streaming)
# Afficher chaque chunk au fur et à mesurefor chunk in stream: print(chunk.message.content, end='', flush=True)
print("\n\n=== Fin du streaming ===")Le paramètre flush=True force l'affichage immédiat de chaque caractère.
Structured Output avec Pydantic
Section intitulée « Structured Output avec Pydantic »C'est la fonctionnalité la plus puissante du SDK Ollama. Au lieu d'obtenir du texte libre, vous obtenez du JSON typé qui correspond exactement à un schéma Pydantic.
Pourquoi c'est important ?
Section intitulée « Pourquoi c'est important ? »Sans schéma, un modèle à qui l'on demande « réponds en JSON » produit un JSON
valide la plupart du temps, et du texte accompagné de trois backticks le reste du
temps. Ce taux d'échec résiduel suffit à casser un script en production. Avec
format=, Ollama contraint le décodage token par token : la sortie ne peut
pas dévier du schéma. Les quatre bénéfices ci-dessous découlent tous de cette
garantie côté serveur, pas d'une consigne dans le prompt.
- Parsing fiable : plus besoin de regex ou de parsing manuel
- Validation automatique : Pydantic vérifie que la réponse est conforme
- Typage : votre IDE connaît les types des champs
- Intégration : les données sont directement utilisables dans votre code
Script 03 : Structured Output basique
Section intitulée « Script 03 : Structured Output basique »Deux appels font tout le travail, et il ne faut pas les confondre.
DockerCommand.model_json_schema() convertit la classe Pydantic en schéma JSON
transmis au serveur, qui s'en sert pour brider la génération.
DockerCommand.model_validate_json() relit la réponse et instancie l'objet Python.
Le schéma contraint la forme, pas le contenu : le champ level sera bien
une chaîne, mais rien n'empêche le modèle d'y écrire intermédiaire au lieu des
trois valeurs attendues. Pour verrouiller aussi les valeurs, déclarez un
Literal["debutant", "intermediaire", "avance"] plutôt qu'un str.
#!/usr/bin/env python3"""TP 03 : Structured Output avec PydanticObjectif : Obtenir des réponses JSON typées et validées automatiquementFeature : Disponible depuis Ollama 0.5.0+"""
from ollama import chatfrom pydantic import BaseModel
# Définir le schéma de sortie avec Pydanticclass DockerCommand(BaseModel): """Une commande Docker expliquée""" command: str # La commande complète description: str # Explication en une phrase example: str # Un exemple concret level: str # "debutant", "intermediaire", "avance"
# Appeler le modèle avec le schémaresponse = chat( model='llama3.2:3b', messages=[ { 'role': 'user', 'content': 'Explique la commande docker build' } ], format=DockerCommand.model_json_schema() # Forcer le format JSON)
# Valider et parser la réponse avec Pydanticresult = DockerCommand.model_validate_json(response.message.content)
# Afficher le résultat structuréprint("=== Sortie structurée (Pydantic) ===")print(f"Commande : {result.command}")print(f"Description : {result.description}")print(f"Exemple : {result.example}")print(f"Niveau : {result.level}")
print("\n=== JSON brut ===")print(response.message.content)Sortie attendue :
=== Sortie structurée (Pydantic) ===Commande : docker buildDescription : Crée une image Docker à partir d'un fichier Dockerfile.Exemple : docker build -t mon-image .Niveau : debutant
=== JSON brut ==={"command": "docker build", "description": "Crée une image Docker...", ...}Script 04 : Listes et objets imbriqués
Section intitulée « Script 04 : Listes et objets imbriqués »Un schéma Pydantic peut contenir d'autres schémas : Tutorial référence une
liste de Step, et Pydantic génère un schéma JSON imbriqué qu'Ollama sait
respecter. Deux options méritent attention dans l'appel. temperature: 0 rend la
sortie déterministe, ce qui compte quand on extrait des données plutôt qu'on ne
rédige. num_predict: 500 plafonne le nombre de tokens générés : une structure
imbriquée coupée en plein milieu produit un JSON invalide et fait échouer la
validation, c'est la panne la plus fréquente sur ce type de schéma.
#!/usr/bin/env python3"""TP 04 : Structured Output avancé (listes et objets imbriqués)Objectif : Extraire plusieurs éléments structurés en une seule requête"""
from ollama import chatfrom pydantic import BaseModel
class Step(BaseModel): """Une étape d'un processus""" number: int action: str command: str
class Tutorial(BaseModel): """Un tutoriel complet""" title: str steps: list[Step] total_time: str
print("🔧 Définition du schéma Pydantic...")
print("\n📤 Envoi de la requête à Ollama (llama3.2:3b)...")
# Demander un tutoriel structuréresponse = chat( model='llama3.2:3b', messages=[ { 'role': 'user', 'content': 'Donne un tutoriel Docker en 2 étapes avec titre, steps (number, action, command) et total_time' } ], format=Tutorial.model_json_schema(), options={'temperature': 0, 'num_predict': 500})
print("✅ Réponse reçue!")print(f" Durée: {response.total_duration / 1e9:.2f}s")
# Parser la réponsetutorial = Tutorial.model_validate_json(response.message.content)
# Afficher le tutoriel formatéprint(f"\n📚 {tutorial.title}")print(f"⏱️ {tutorial.total_time}")for step in tutorial.steps: print(f" {step.number}. {step.action} → {step.command}")Sortie attendue :
📚 Tutoriel Docker en 2 étapes⏱️ > 30 minutes 1. Créer un nouveau projet Docker → docker run -it ubuntu /bin/bash 2. Créer une image personnalisée → docker build -t mon-image .Conversation multi-turn avec historique
Section intitulée « Conversation multi-turn avec historique »Pour maintenir le contexte entre plusieurs échanges, vous devez gérer l'historique des messages.
Script 05 : Conversation
Section intitulée « Script 05 : Conversation »Le serveur Ollama ne mémorise rien entre deux appels : la mémoire de la
conversation, c'est votre liste messages. À chaque tour, vous renvoyez tout
l'historique, question et réponse comprises. Cela a un coût qui grandit
linéairement, visible dans prompt_eval_count qui augmente à chaque échange
jusqu'à saturer la fenêtre de contexte du modèle. Sur un assistant destiné à
durer, il faut donc prévoir une troncature de l'historique ou un résumé des
tours anciens ; le script ci-dessous, limité à quatre échanges, n'en a pas besoin.
#!/usr/bin/env python3"""TP 05 : Conversation multi-turn avec historiqueObjectif : Maintenir le contexte entre plusieurs échanges"""
from ollama import chat
# Historique de la conversationmessages = []
# Contexte systèmesystem_message = { 'role': 'system', 'content': '''Tu es DevOps Buddy, un assistant spécialisé DevOps.Tu réponds de manière concise et technique.Tu donnes des exemples de commandes quand c'est pertinent.'''}messages.append(system_message)
print("🤖 DevOps Buddy initialisé")print("=" * 50)
def ask(question: str) -> str: """Pose une question et met à jour l'historique""" print(f"\n👤 {question}")
# Ajouter la question à l'historique messages.append({'role': 'user', 'content': question})
# Appeler le modèle avec tout l'historique response = chat( model='llama3.2:3b', messages=messages, options={'temperature': 0.3} )
# Ajouter la réponse à l'historique assistant_message = response.message.content messages.append({'role': 'assistant', 'content': assistant_message})
print(f"🤖 {assistant_message}") return assistant_message
# Simulation d'une conversationask("C'est quoi un Pod Kubernetes en une phrase ?")ask("Et un Deployment, c'est quoi par rapport à un Pod ?")ask("Donne-moi la commande pour créer un Deployment avec 3 réplicas")ask("Comment je scale à 5 réplicas maintenant ?")
print("\n" + "=" * 50)print(f"📊 Total messages dans l'historique : {len(messages)}")Le modèle se souvient du contexte : la 4e question "Comment je scale à 5 réplicas" fait référence au Deployment mentionné précédemment.
Embeddings pour la recherche sémantique
Section intitulée « Embeddings pour la recherche sémantique »Les embeddings transforment du texte en vecteurs numériques. Deux textes similaires auront des vecteurs proches. C'est la base du RAG.
Script 06 : Embeddings et similarité
Section intitulée « Script 06 : Embeddings et similarité »La fonction embed() renvoie toujours une liste de vecteurs, même pour une
seule chaîne en entrée, d'où le response.embeddings[0] répété dans le script.
La similarité cosinus mesure l'angle entre deux vecteurs et non leur
distance : elle vaut 1 pour deux textes de sens identique et tend vers 0 pour
deux textes sans rapport. Ne comparez jamais un score dans l'absolu, seul le
classement relatif entre documents a un sens, et ce classement dépend
entièrement du modèle utilisé.
#!/usr/bin/env python3"""TP 06 : Embeddings avec OllamaObjectif : Générer des vecteurs pour la recherche sémantiqueFeature : Disponible depuis Ollama 0.3+"""
from ollama import embedimport math
def cosine_similarity(vec1: list[float], vec2: list[float]) -> float: """Calcule la similarité cosinus entre deux vecteurs""" dot_product = sum(a * b for a, b in zip(vec1, vec2)) norm1 = math.sqrt(sum(a ** 2 for a in vec1)) norm2 = math.sqrt(sum(b ** 2 for b in vec2)) return dot_product / (norm1 * norm2)
# Base de connaissances DevOpsdocuments = [ "Docker est une plateforme de conteneurisation qui permet de packager des applications", "Kubernetes orchestre les conteneurs à grande échelle dans un cluster", "Ansible automatise la configuration des serveurs et le déploiement", "Terraform gère l'infrastructure as code pour le cloud", "GitLab CI/CD permet l'intégration et le déploiement continus"]
print("📦 Génération des embeddings pour 5 documents...")
# Générer les embeddings pour chaque documentdoc_embeddings = []for i, doc in enumerate(documents): response = embed(model='llama3.2:3b', input=doc) doc_embeddings.append(response.embeddings[0]) print(f" ✅ Doc {i+1} : {len(response.embeddings[0])} dimensions")
print(f"\n📊 Dimension des vecteurs : {len(doc_embeddings[0])}")
# Question de testquery = "Comment déployer des conteneurs en production ?"print(f"\n🔍 Requête : {query}")
# Générer l'embedding de la requêtequery_response = embed(model='llama3.2:3b', input=query)query_embedding = query_response.embeddings[0]
# Calculer la similarité avec chaque documentprint("\n📈 Scores de similarité :")scores = []for i, doc_emb in enumerate(doc_embeddings): score = cosine_similarity(query_embedding, doc_emb) scores.append((score, documents[i])) print(f" {score:.4f} → {documents[i][:50]}...")
# Trier par score décroissantscores.sort(reverse=True)print(f"\n🏆 Document le plus pertinent :")print(f" Score: {scores[0][0]:.4f}")print(f" {scores[0][1]}")Sortie attendue :
📦 Génération des embeddings pour 5 documents... ✅ Doc 1 : 3072 dimensions ✅ Doc 2 : 3072 dimensions ...
📈 Scores de similarité : 0.3004 → Docker est une plateforme de conteneurisation... 0.3473 → Kubernetes orchestre les conteneurs à grande... ...
🏆 Document le plus pertinent : Score: 0.4581 Ansible automatise la configuration des serveurs et le déploiementCe résultat est mauvais, et c'est l'enseignement principal du script : à la
question « comment déployer des conteneurs en production », le document Ansible
arrive devant Docker et Kubernetes. llama3.2 est un modèle de conversation,
ses vecteurs internes ne sont pas entraînés pour la recherche sémantique. Le
classement obtenu reflète surtout la proximité lexicale du mot « déploiement ».
Reproduisez l'expérience avec nomic-embed-text et l'ordre se corrige : c'est la
démonstration qu'un modèle d'embedding dédié n'est pas une optimisation mais une
condition de fonctionnement.
DevOps Buddy : l'assistant complet
Section intitulée « DevOps Buddy : l'assistant complet »Combinons toutes les fonctionnalités dans un assistant DevOps interactif.
Script 07 : DevOps Buddy
Section intitulée « Script 07 : DevOps Buddy »Le script est long, lisez-le par blocs plutôt que ligne à ligne. Trois parties
portent la logique. find_relevant_context() réalise la récupération : elle
compare l'embedding de la question à ceux de la base et renvoie les deux
documents les plus proches. chat_with_rag() réalise l'augmentation : elle
colle ce contexte devant la question avant de l'envoyer au modèle. Le reste est
de l'habillage de terminal.
Deux limites assumées, qui distinguent ce prototype d'un vrai système RAG. Les embeddings sont recalculés à chaque démarrage et vivent en mémoire : aucune persistance, aucune base vectorielle. Et la recherche est linéaire, elle compare la question à tous les documents. Sur six entrées c'est instantané, sur dix mille il faut un index dédié.
#!/usr/bin/env python3"""TP 07 : DevOps Buddy - Assistant local completObjectif : Combiner toutes les fonctionnalités Ollama dans un assistant interactifFeatures utilisées : chat, streaming, structured output, embeddings"""
from ollama import chat, embedfrom pydantic import BaseModelimport math
# === Configuration ===MODEL = 'llama3.2:3b'SYSTEM_PROMPT = '''Tu es DevOps Buddy, un assistant expert DevOps/DevSecOps.Tu réponds en français de manière concise et technique.Tu donnes des exemples de commandes quand c'est pertinent.Tu structures tes réponses avec des listes à puces.'''
# === Base de connaissances embarquée ===KNOWLEDGE_BASE = [ {"topic": "docker", "content": "Docker utilise des conteneurs pour isoler les applications. Commandes: docker build, docker run, docker compose"}, {"topic": "kubernetes", "content": "Kubernetes orchestre les conteneurs. Concepts: Pod, Deployment, Service, Ingress. Commandes: kubectl get, kubectl apply"}, {"topic": "ansible", "content": "Ansible automatise la configuration. Concepts: playbook, inventory, role, task. Commande: ansible-playbook"}, {"topic": "terraform", "content": "Terraform gère l'infrastructure as code. Concepts: provider, resource, module, state. Commandes: terraform init, plan, apply"}, {"topic": "gitlab", "content": "GitLab CI/CD pipeline avec .gitlab-ci.yml. Concepts: stages, jobs, artifacts, cache, runners"}, {"topic": "prometheus", "content": "Prometheus collecte les métriques. Concepts: scraping, PromQL, alertmanager, exporters"},]
# Pré-calculer les embeddings de la base de connaissancesprint("🔄 Chargement de la base de connaissances...")knowledge_embeddings = []for item in KNOWLEDGE_BASE: response = embed(model=MODEL, input=item["content"]) knowledge_embeddings.append(response.embeddings[0])print(f"✅ {len(KNOWLEDGE_BASE)} documents indexés\n")
# === Fonctions utilitaires ===def cosine_similarity(vec1: list[float], vec2: list[float]) -> float: dot = sum(a * b for a, b in zip(vec1, vec2)) norm1 = math.sqrt(sum(a ** 2 for a in vec1)) norm2 = math.sqrt(sum(b ** 2 for b in vec2)) return dot / (norm1 * norm2) if norm1 and norm2 else 0
def find_relevant_context(query: str, top_k: int = 2) -> str: """Recherche les documents pertinents pour enrichir le contexte""" query_emb = embed(model=MODEL, input=query).embeddings[0]
scores = [] for i, doc_emb in enumerate(knowledge_embeddings): score = cosine_similarity(query_emb, doc_emb) scores.append((score, KNOWLEDGE_BASE[i]))
scores.sort(reverse=True) top_docs = scores[:top_k]
context = "\n".join([f"- {doc['content']}" for _, doc in top_docs]) return context
# === Schéma pour les commandes structurées ===class CommandSuggestion(BaseModel): command: str description: str warning: str | None = None
def get_structured_command(query: str) -> CommandSuggestion | None: """Obtenir une suggestion de commande structurée""" try: response = chat( model=MODEL, messages=[ {'role': 'system', 'content': 'Tu suggères des commandes DevOps. Réponds uniquement en JSON.'}, {'role': 'user', 'content': f'Suggère une commande pour: {query}'} ], format=CommandSuggestion.model_json_schema(), options={'temperature': 0, 'num_predict': 200} ) return CommandSuggestion.model_validate_json(response.message.content) except Exception as e: print(f"⚠️ Erreur structured output: {e}") return None
# === Chat avec RAG ===def chat_with_rag(question: str, history: list) -> str: """Répond à une question avec contexte enrichi""" # Trouver le contexte pertinent context = find_relevant_context(question)
# Construire le prompt enrichi augmented_question = f"""Contexte (base de connaissances):{context}
Question de l'utilisateur: {question}"""
# Ajouter au historique history.append({'role': 'user', 'content': augmented_question})
# Appeler le modèle avec streaming response_text = "" stream = chat( model=MODEL, messages=history, stream=True, options={'temperature': 0.3} )
for chunk in stream: content = chunk.message.content print(content, end='', flush=True) response_text += content
print() # Nouvelle ligne après le streaming
# Ajouter la réponse à l'historique history.append({'role': 'assistant', 'content': response_text})
return response_text
# === Main ===def main(): print("=" * 60) print("🤖 DevOps Buddy - Assistant DevOps Local (Ollama)") print("=" * 60) print(f"Modèle: {MODEL}") print("Commandes spéciales:") print(" /cmd <action> : Obtenir une commande structurée") print(" /quit : Quitter") print("-" * 60)
history = [{'role': 'system', 'content': SYSTEM_PROMPT}]
while True: try: user_input = input("\n👤 Vous: ").strip()
if not user_input: continue
if user_input.lower() == '/quit': print("👋 À bientôt!") break
if user_input.startswith('/cmd '): # Mode commande structurée query = user_input[5:] print("\n🔧 Recherche de commande...") result = get_structured_command(query) if result: print(f"\n📋 Commande: {result.command}") print(f"📝 Description: {result.description}") if result.warning: print(f"⚠️ Attention: {result.warning}") else: print("❌ Impossible de générer la commande") else: # Mode conversation avec RAG print("\n🤖 DevOps Buddy: ", end='') chat_with_rag(user_input, history)
except EOFError: print("\n👋 À bientôt!") break except KeyboardInterrupt: print("\n👋 Interruption - À bientôt!") break
if __name__ == "__main__": main()Utilisation de DevOps Buddy
Section intitulée « Utilisation de DevOps Buddy »Le démarrage prend quelques secondes, le temps de calculer les six embeddings de
la base. L'assistant propose ensuite deux modes qu'il est utile de comparer :
une question libre passe par le RAG en streaming, tandis que le préfixe
/cmd bascule sur la sortie structurée et affiche une commande, sa
description et un avertissement facultatif. La différence se sent à l'usage : le
mode conversation affiche les premiers mots presque tout de suite, alors que le
mode /cmd reste muet jusqu'à ce que le JSON complet soit généré et validé,
puisqu'un JSON partiel serait inutilisable.
python 07_devops_buddy.pyExemple de session :
🔄 Chargement de la base de connaissances...✅ 6 documents indexés
============================================================🤖 DevOps Buddy - Assistant DevOps Local (Ollama)============================================================Modèle: llama3.2:3bCommandes spéciales: /cmd <action> : Obtenir une commande structurée /quit : Quitter------------------------------------------------------------
👤 Vous: C'est quoi un Pod ?
🤖 DevOps Buddy: Un Pod est l'unité de base dans Kubernetes...
👤 Vous: /cmd lister les pods kubernetes
🔧 Recherche de commande...
📋 Commande: kubectl get pods📝 Description: Liste tous les pods dans le namespace courant⚠️ Attention: Ajoutez -A pour lister tous les namespacesContrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- SDK natif vs LiteLLM : Le SDK ollama offre des fonctionnalités exclusives (structured output, thinking) mais ne supporte que Ollama
format=: Passez un schéma Pydantic pour obtenir du JSON typéstream=True: Affiche la réponse en temps réelembed(): Génère des embeddings pour la recherche sémantique- Historique : Passez tous les messages pour maintenir le contexte
options: Contrôlez la température, le nombre de tokens, etc.- RAG local : Combinez embeddings + contexte pour enrichir les réponses
Checklist
Section intitulée « Checklist »Passez cette liste avant d'aller plus loin : chaque script isole une capacité du
SDK, et les suivants s'appuient sur les précédents. Si 03_structured_output.py
échoue, inutile de lancer DevOps Buddy, il utilise le même mécanisme.
Installation
Section intitulée « Installation »Ces trois vérifications éliminent la cause la plus fréquente d'échec, un serveur et un SDK qui ne parlent pas de la même version d'API.
- SDK ollama installé (
pip show ollama) - Pydantic installé (
pip show pydantic) - Modèle téléchargé (
ollama list)
Scripts testés
Section intitulée « Scripts testés »Exécutez-les dans l'ordre. Le seul qui peut échouer pour une raison de fond est
06_embeddings.py : si les scores sont tous proches les uns des autres, c'est le
modèle d'embedding qu'il faut changer, pas le code.
-
01_chat_basique.py: réponse + métadonnées -
02_streaming.py: affichage temps réel -
03_structured_output.py: JSON validé par Pydantic -
04_structured_avance.py: listes d'objets -
05_conversation.py: historique multi-turn -
06_embeddings.py: similarité cosinus -
07_devops_buddy.py: assistant complet