Appels API Ollama : de curl à l'interface compatible OpenAI SDK

La commande curl dans le terminal ne renvoie qu’un demi-mot dans le JSON — deux heures perdues avant de comprendre que c’était le streaming. Ollama crache le contenu petit à petit par défaut ; chaque objet JSON ne contient que quelques caractères.
Pour déployer un LLM en local, Ollama abaisse la barrière : télécharger, installer, lancer, trois étapes. En revanche, les appels API prêtent à confusion : quelle différence entre l’API REST native et l’interface compatible OpenAI SDK ? Comment gérer le streaming ?
Cet article rassemble les pièges que j’ai rencontrés, de la commande curl à la migration zero-code vers le SDK OpenAI, plus quelques détails que la doc ne mentionne pas clairement.
Ollama propose deux interfaces API
Franchement, ça m’a embrouillé un moment. Ollama offre en réalité deux interfaces API complètement distinctes :
API REST native : http://localhost:11434/api/*
- Endpoints :
/api/generate(génération de texte),/api/chat(dialogue),/api/tags(liste des modèles) - Réponse en streaming par défaut (c’est le piège que j’ai rencontré à trois heures du matin)
- Appel HTTP direct, sans SDK
Interface compatible OpenAI : http://localhost:11434/v1/*
- Endpoints :
/v1/chat/completions,/v1/completions,/v1/models - Entièrement compatible avec le SDK OpenAI (Python, JavaScript)
- Compatible avec l’écosystème d’outils OpenAI existant
Pourquoi deux interfaces ? Chacune a son utilité. L’API native est plus légère et directe, idéale pour écrire son propre client HTTP ; l’interface compatible OpenAI permet d’utiliser le code SDK OpenAI existant sans modification — il suffit de changer base_url.
Honnêtement, c’est une conception maline. Elle s’adresse aux développeurs qui veulent un appel simple, comme aux équipes qui ont déjà du code dans l’écosystème OpenAI.
API REST native : commencer avec curl
Commençons par l’API native. C’est assez direct : une interface REST standard.
Appel curl de base
L’exemple le plus simple — génération de texte :
curl http://localhost:11434/api/generate -d '{
"model": "llama3.2",
"prompt": "Why is the sky blue?",
"stream": false
}'
Notez le stream: false. Par défaut, Ollama renvoie le contenu en streaming. Pour obtenir une réponse JSON complète, il faut désactiver explicitement le streaming. Sinon, vous verrez une série de sorties comme celle-ci :
{"model":"llama3.2","response":"That","done":false}
{"model":"llama3.2","response":"'","done":false}
{"model":"llama3.2","response":"s","done":false}
{"model":"llama3.2","response":" a","done":false}
...
{"model":"llama3.2","response":"!","done":true}
Chaque objet JSON ne contient que quelques caractères, token par token. C’est le format NDJSON (Newline-Delimited JSON) — un objet JSON par ligne. Cette nuit-là à trois heures, je n’avais pas remarqué ça et j’avais parsé comme un JSON classique ; je n’avais récupéré que « That » du premier objet.
Le mode dialogue est plus pratique
La génération unique convient aux tâches simples, mais le mode dialogue est celui qu’on utilise vraiment :
curl http://localhost:11434/api/chat -d '{
"model": "llama3.2",
"messages": [
{ "role": "user", "content": "Hello!" }
],
"stream": false
}'
Vous pouvez maintenir un tableau messages avec l’historique de la conversation, pour que le modèle garde le contexte. Essentiel pour construire une application de chat.
Voir les modèles installés
Parfois, vous voulez savoir quels modèles sont disponibles en local :
curl http://localhost:11434/api/tags
Le JSON renvoyé liste tous les modèles téléchargés, avec taille, date de modification, niveau de quantification, etc. Pratique.
Gestion des réponses en streaming
Ce point mérite une section dédiée. Le streaming Ollama a une particularité : il ne renvoie pas le contenu d’un coup, mais token par token.
Streaming en Python
Avec la bibliothèque requests en Python :
import requests
import json
url = "http://localhost:11434/api/chat"
payload = {
"model": "llama3.2",
"messages": [{"role": "user", "content": "Write a short poem"}],
"stream": True
}
response = requests.post(url, json=payload, stream=True)
for line in response.iter_lines():
if line:
chunk = json.loads(line)
print(chunk.get("message", {}).get("content", ""), end="", flush=True)
Le point clé est response.iter_lines() — il permet de lire le flux NDJSON ligne par ligne. Chaque chunk ne contient peut-être que quelques caractères ; il faut les accumuler pour obtenir la réponse complète.
Streaming en JavaScript
Côté frontend, avec l’API fetch, c’est similaire :
const response = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
body: JSON.stringify({
model: 'llama3.2',
messages: [{ role: 'user', content: 'Hello!' }],
stream: true
})
});
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
// Traiter chaque chunk...
}
Le streaming est un peu plus complexe que le mode non streamé, mais l’expérience utilisateur est bien meilleure — vous voyez le modèle « réfléchir » et produire sa sortie en temps réel, au lieu d’attendre longtemps avant qu’un gros bloc de texte apparaisse.
Interface compatible OpenAI SDK : migration zero-code
C’est la partie que je préfère. Ollama fournit une interface API entièrement compatible OpenAI ; vous pouvez migrer votre code existant quasi sans friction.
Exemple avec le SDK Python OpenAI
Utilisez directement le SDK officiel OpenAI :
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1/',
api_key='ollama' # Non vérifiée en local, valeur quelconque
)
response = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
La seule modification : définir base_url et une api_key quelconque. Le reste du code reste identique.
Bascule développement / production
Cette fonctionnalité est particulièrement utile. En développement, utilisez Ollama en local ; en production, OpenAI :
# .env développement
OPENAI_API_KEY=anyrandomtext
LLM_ENDPOINT="http://localhost:11434/v1"
MODEL=llama3.2
# .env production
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXX
LLM_ENDPOINT="https://api.openai.com/v1"
MODEL=gpt-3.5-turbo
Le code lit simplement les variables d’environnement :
import os
from openai import OpenAI
client = OpenAI(
base_url=os.getenv('LLM_ENDPOINT'),
api_key=os.getenv('OPENAI_API_KEY')
)
En développement, pas besoin de payer l’API OpenAI — les tests locaux suffisent. En production, changez les variables d’environnement pour basculer vers OpenAI.
Endpoints pris en charge
L’interface compatible OpenAI d’Ollama prend en charge ces endpoints :
| Endpoint | Fonction | Niveau de support |
|---|---|---|
/v1/chat/completions | Génération de dialogue | Prise en charge complète |
/v1/completions | Complétion de texte | Prise en charge complète |
/v1/models | Liste des modèles | Prise en charge complète |
/v1/embeddings | Embeddings de texte | Prise en charge complète |
/v1/responses | Nouvelle API de réponses | Prise en charge complète |
Il existe aussi un endpoint expérimental /v1/images/generations, mais sa stabilité n’est pas encore suffisante.
Alias de modèles
Petite astuce : vous pouvez créer des alias pour vos modèles. Par exemple, pour que le code ressemble à un appel GPT-3.5 :
ollama cp llama3.2 gpt-3.5-turbo
Ainsi, model="gpt-3.5-turbo" dans votre code utilisera en réalité llama3.2 en local. Utile lors de la migration de code.
Quelle approche choisir ?
Après tout ça, vous vous demandez peut-être : laquelle utiliser ?
Cas d’usage de l’API REST native
Convient dans ces situations :
- Vous voulez l’appel le plus léger possible
- Vous n’avez pas besoin de l’écosystème OpenAI SDK
- Vous écrivez votre propre client HTTP (appareils embarqués, environnements spéciaux)
- Vous devez contrôler finement les détails du streaming
L’API native est plus directe, plus bas niveau. Si vous maîtrisez HTTP, vous serez à l’aise.
Cas d’usage de l’interface compatible OpenAI SDK
Convient dans ces situations :
- Vous avez déjà du code basé sur le SDK OpenAI
- Vous devez migrer rapidement vers un déploiement local
- Vous utilisez la chaîne d’outils OpenAI (LangChain, LlamaIndex, etc.)
- Vous devez basculer entre environnements dev et prod
En bref, si vous voulez réutiliser du code existant sans le modifier, prenez l’interface compatible OpenAI.
Mon conseil
Franchement, en développement je préfère l’interface compatible OpenAI SDK — peu de modifications, la chaîne d’outils fonctionne, le débogage est simple. Mais l’API native convient mieux dans certains cas, par exemple pour un outil CLI minimaliste ou un environnement qui ne supporte pas le SDK OpenAI.
Extraits de code pratiques
Quelques extraits que j’utilise souvent.
Chat en streaming Python (SDK OpenAI)
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1/',
api_key='ollama'
)
stream = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Write a poem"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Dialogue complet JavaScript (API native)
async function chat(messages) {
const response = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'llama3.2',
messages: messages,
stream: false
})
});
return await response.json();
}
// Maintenir l'historique de conversation
let conversation = [
{ role: 'user', content: 'Hello!' }
];
const result = await chat(conversation);
conversation.push({
role: 'assistant',
content: result.message.content
});
console.log(result.message.content);
Exemple avec appel d’outils
Ollama prend aussi en charge le Function Calling (appel d’outils) :
from openai import OpenAI
client = OpenAI(base_url='http://localhost:11434/v1/', api_key='ollama')
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
tools=tools
)
if response.choices[0].message.tool_calls:
print("Model wants to call:", response.choices[0].message.tool_calls[0].function.name)
En résumé
Le design de l’API Ollama est équilibré — l’API REST native pour la légèreté et la simplicité, le SDK OpenAI pour la commodité et la compatibilité écosystème. Chaque approche a ses cas d’usage ; tout dépend de vos besoins.
Si vous débutez avec Ollama, je recommande de commencer par l’interface compatible OpenAI SDK — prise en main rapide, peu de modifications. Une fois à l’aise, choisissez l’API native selon vos besoins concrets.
Et un dernier point : le streaming est un piège classique. Par défaut, c’est activé ; si vous n’en avez pas besoin, définissez explicitement stream: false, sinon vous risquez de rester fixé sur un demi-mot à trois heures du matin, comme moi.
Références
- Ollama API Introduction
- Ollama OpenAI Compatibility
- Ollama Streaming Guide
- KodeKloud OpenAI Compatibility Guide
Deux façons d'appeler l'API Ollama
Flux complet d'appel, de l'API native curl à l'interface compatible OpenAI SDK
⏱️ Estimated time: 10 min
- 1
Step 1: Vérifier qu'Ollama est installé et en cours d'exécution
Commencez par vérifier qu'Ollama fonctionne correctement :
• Dans le terminal : ollama list (pour voir les modèles téléchargés)
• Ou visitez : http://localhost:11434 (doit afficher Ollama is running)
• Port par défaut : 11434 - 2
Step 2: Choisir la méthode d'appel
Selon votre cas d'usage :
• API REST native : adaptée aux appels légers et aux clients personnalisés
• Compatible OpenAI SDK : idéale si vous avez déjà du code OpenAI, migration rapide - 3
Step 3: Utiliser l'API REST native (via curl)
Appel curl de base :
• Génération de texte : curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "prompt": "...", "stream": false}'
• Mode dialogue : curl http://localhost:11434/api/chat -d '{"model": "llama3.2", "messages": [...], "stream": false}'
• Attention : le streaming est activé par défaut ; définissez stream: false pour le désactiver - 4
Step 4: Utiliser l'interface compatible OpenAI SDK
Appel avec le SDK Python OpenAI :
• Définissez base_url='http://localhost:11434/v1/'
• api_key peut être n'importe quelle valeur (non vérifiée en local)
• Le reste du code est identique à OpenAI
• Changement d'environnement : modifiez base_url (local en dev, OpenAI en prod) - 5
Step 5: Gérer les réponses en streaming
Points clés pour le streaming :
• Python : response.iter_lines() pour lire le NDJSON ligne par ligne
• JavaScript : response.body.getReader() pour lire le flux
• Chaque chunk ne contient que quelques caractères ; il faut accumuler la réponse complète
• Mode non streamé : définissez stream: false pour obtenir un JSON complet
FAQ
Quelle est la différence entre l'API native Ollama et l'interface compatible OpenAI SDK ?
Pourquoi mon appel API Ollama ne renvoie qu'un demi-mot ?
• Définissez stream: false pour obtenir un JSON complet
• Ou traitez correctement le flux NDJSON : lisez ligne par ligne et accumulez le contenu
Comment utiliser Ollama en local en développement et OpenAI en production ?
Quels endpoints OpenAI Ollama prend-il en charge ?
Peut-on créer des alias pour les modèles Ollama ?
Ollama prend-il en charge l'appel d'outils (Function Calling) ?
8 min de lecture · Publié le: 3 avr. 2026 · Mis à jour le: 27 juil. 2026
Guide Ollama LLM local
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Ollama + Open WebUI : créer une interface ChatGPT locale (guide complet)
Guide pas à pas pour déployer une interface de dialogue IA style ChatGPT en local avec Ollama et Open WebUI : installation, choix de modèles, base de connaissances RAG, intégration API et optimisation des performances — en 30 minutes.
Partie 11 sur 18
Suivant
Pratique Ollama API : guide de développement client Python et Node.js
Guide complet d'appel à l'API Ollama : SDK Python et Node.js, réponses en streaming, boucle Agent Loop pour l'appel d'outils, mode thinking et comparaison avec la compatibilité OpenAI
Partie 13 sur 18



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire