Design wechseln

Ollama-API-Aufrufe: Von curl bis zur OpenAI-SDK-kompatiblen Schnittstelle

Der curl-Befehl im Terminal – und im JSON steckt nur ein halbes Wort. Zwei Stunden später war klar: Streaming-Antwort. Ollama liefert standardmäßig Inhalt stückweise aus, jedes JSON-Objekt enthält nur wenige Zeichen.

Beim lokalen LLM-Deployment senkt Ollama die Hürde: Herunterladen, installieren, starten – drei Schritte. Bei der API wird es unübersichtlich: Was unterscheidet native REST-API und OpenAI-SDK-Kompatibilität? Wie verarbeitet man Streaming?

Dieser Artikel fasst die Stolpersteine zusammen – von curl bis zur OpenAI-SDK-Migration ohne Codeänderung, plus Details, die in der Doku leicht übersehen werden.


Zwei Ollama-API-Schnittstellen

Das hat mich eine Weile verwirrt: Ollama bietet zwei grundverschiedene API-Varianten:

Native REST-API: http://localhost:11434/api/*

  • Endpunkte: /api/generate (Textgenerierung), /api/chat (Dialog), /api/tags (Modellliste)
  • Standardmäßig Streaming (genau das Problem um drei Uhr nachts)
  • Direkter HTTP-Aufruf, kein SDK nötig

OpenAI-kompatible Schnittstelle: http://localhost:11434/v1/*

  • Endpunkte: /v1/chat/completions, /v1/completions, /v1/models
  • Voll kompatibel mit OpenAI SDK (Python, JavaScript)
  • Bestehendes OpenAI-Tool-Ökosystem nutzbar

Warum zwei Varianten? Beide haben ihren Platz. Die native API ist leichter und direkter – ideal für eigene HTTP-Clients. Die OpenAI-Kompatibilität lässt bestehenden OpenAI-SDK-Code unverändert laufen – nur base_url anpassen.

Dieses Design ist durchdacht: einfache Aufrufe für Einsteiger, nahtlose Integration für Teams mit OpenAI-Codebasis.


Native REST-API: Mit curl starten

Die native API ist schlicht: ein standardmäßiger REST-Endpunkt.

Einfacher curl-Aufruf

Minimalbeispiel – Textgenerierung:

curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "Why is the sky blue?",
  "stream": false
}'

Achten Sie auf stream: false. Standardmäßig streamt Ollama – für eine vollständige JSON-Antwort Streaming explizit deaktivieren. Sonst erscheint eine Ausgabe wie:

{"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}

Jedes JSON-Objekt enthält nur wenige Zeichen – tokenweise Ausgabe. Das ist NDJSON (Newline-Delimited JSON): eine Zeile pro JSON-Objekt. Beim ersten Versuch wurde nur das erste Objekt mit „That“ geparst – weil es wie normales JSON behandelt wurde.

Dialogmodus ist praxisnäher

Einmalige Generierung für einfache Aufgaben; im Alltag zählt der Dialogmodus:

curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [
    { "role": "user", "content": "Hello!" }
  ],
  "stream": false
}'

Ein messages-Array hält den Verlauf – so behält das Modell Kontext. Entscheidend für Chat-Anwendungen.

Installierte Modelle anzeigen

Welche Modelle lokal verfügbar sind:

curl http://localhost:11434/api/tags

Die JSON-Antwort listet alle heruntergeladenen Modelle inklusive Größe, Änderungszeit und Quantisierungsstufe.


Streaming-Antworten verarbeiten

Ollama streamt nicht in einem Stück, sondern tokenweise.

Streaming in Python

Mit der requests-Bibliothek:

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)

Der Schlüssel ist response.iter_lines() – zeilenweises Lesen des NDJSON-Streams. Jeder Chunk kann nur wenige Zeichen enthalten; erst die Akkumulation ergibt die vollständige Antwort.

Streaming in JavaScript

Mit der fetch-API ähnlich:

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);
  // Jeden Chunk verarbeiten...
}

Streaming ist aufwändiger als Nicht-Streaming – die UX ist besser: Ausgabe in Echtzeit statt langer Wartezeit und plötzlichem Textblock.


OpenAI-SDK-Kompatibilität: Migration ohne Codeänderung

Ollama bietet eine vollständige OpenAI-API-kompatible Schnittstelle – bestehender Code lässt sich nahezu nahtlos übernehmen.

Beispiel mit Python OpenAI SDK

Offizielles OpenAI SDK direkt nutzen:

from openai import OpenAI

client = OpenAI(
    base_url='http://localhost:11434/v1/',
    api_key='ollama'  # lokal keine Validierung, beliebiger Wert
)

response = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Hello!"}]
)

print(response.choices[0].message.content)

Die einzige Anpassung: base_url setzen und beliebigen api_key übergeben. Restlicher Code bleibt gleich.

Wechsel zwischen Entwicklung und Produktion

Praktisch: lokal Ollama, in Produktion OpenAI:

# Entwicklung .env
OPENAI_API_KEY=anyrandomtext
LLM_ENDPOINT="http://localhost:11434/v1"
MODEL=llama3.2

# Produktion .env
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXX
LLM_ENDPOINT="https://api.openai.com/v1"
MODEL=gpt-3.5-turbo

Im Code aus Umgebungsvariablen lesen:

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.getenv('LLM_ENDPOINT'),
    api_key=os.getenv('OPENAI_API_KEY')
)

In der Entwicklung entfallen OpenAI-Kosten – lokale Tests reichen. Beim Go-Live reicht ein Wechsel der Umgebungsvariablen.

Unterstützte Endpunkte

Die OpenAI-kompatible Ollama-Schnittstelle unterstützt:

EndpunktFunktionUnterstützung
/v1/chat/completionsDialoggenerierungVollständig
/v1/completionsTextvervollständigungVollständig
/v1/modelsModelllisteVollständig
/v1/embeddingsText-EmbeddingsVollständig
/v1/responsesNeue Responses-APIVollständig

Experimentell gibt es /v1/images/generations – Stabilität noch eingeschränkt.

Modell-Aliase

Kleiner Trick: Modellen Aliase geben. Code soll wie GPT-3.5 aussehen:

ollama cp llama3.2 gpt-3.5-turbo

Dann verwendet model="gpt-3.5-turbo" im Code lokal llama3.2 – hilfreich bei der Migration.


Welche Variante wählen?

Native REST-API

Passend wenn:

  • Sie den leichtesten Aufruf wollen
  • Sie kein OpenAI-SDK-Ökosystem brauchen
  • Sie einen eigenen HTTP-Client schreiben (Embedded, Spezialumgebung)
  • Sie Streaming-Details präzise steuern müssen

Die native API ist direkter und näher am Protokoll – wer HTTP kennt, kommt schnell zurecht.

OpenAI-SDK-kompatible Schnittstelle

Passend wenn:

  • Sie bereits OpenAI-SDK-Code haben
  • Sie schnell auf lokales Deployment wechseln wollen
  • Sie OpenAI-Toolchains nutzen (LangChain, LlamaIndex)
  • Sie zwischen Entwicklung und Produktion wechseln müssen

Wer wenig am Code ändern will, greift zur OpenAI-Kompatibilität.

Empfehlung

In der Entwicklung meist OpenAI-SDK-Kompatibilität – wenig Codeänderung, Toolchains funktionieren, Debugging einfacher. Die native API passt für minimale CLI-Tools oder Umgebungen ohne OpenAI SDK.


Praxis-Code-Snippets

Python-Streaming-Chat (OpenAI SDK)

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)

JavaScript-Vollständiger Dialog (native API)

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();
}

// Dialogverlauf pflegen
let conversation = [
  { role: 'user', content: 'Hello!' }
];

const result = await chat(conversation);
conversation.push({
  role: 'assistant',
  content: result.message.content
});

console.log(result.message.content);

Beispiel mit Tool Calling

Ollama unterstützt Function Calling:

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)

Kurz zusammengefasst

Ollamas API-Design ist ausgewogen: native REST-API für Direktheit und Leichtgewicht, OpenAI-SDK für Bequemlichkeit und Ökosystem-Kompatibilität. Beide Varianten haben klare Einsatzgebiete – die Wahl hängt vom Bedarf ab.

Beim Einstieg empfiehlt sich die OpenAI-SDK-Kompatibilität – schneller Start, wenig Anpassung. Später können Sie bei Bedarf zur nativen API wechseln.

Wichtig beim Streaming: Standard ist Streaming aktiv. Bei Bedarf an vollständigem JSON stream: false setzen – sonst droht das Erlebnis mit einem halben Wort um drei Uhr nachts.


Referenzen

Zwei Wege, die Ollama-API aufzurufen

Vollständiger Ablauf von curl über die native API bis zur OpenAI-SDK-kompatiblen Schnittstelle

⏱️ Estimated time: 10 min

  1. 1

    Step 1: Prüfen, ob Ollama installiert und aktiv ist

    Zuerst kontrollieren, ob Ollama läuft:

    • Im Terminal: ollama list (heruntergeladene Modelle anzeigen)
    • Oder aufrufen: http://localhost:11434 (sollte Ollama is running zurückgeben)
    • Standardport: 11434
  2. 2

    Step 2: Aufrufvariante wählen

    Je nach Szenario:

    • Native REST-API: für leichte Aufrufe und eigene Clients
    • OpenAI-SDK-Kompatibilität: für bestehenden OpenAI-Code und schnelle Migration
  3. 3

    Step 3: Native REST-API nutzen (curl)

    Einfachster curl-Aufruf:

    • Textgenerierung: curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "prompt": "...", "stream": false}'
    • Dialogmodus: curl http://localhost:11434/api/chat -d '{"model": "llama3.2", "messages": [...], "stream": false}'
    • Hinweis: Standard ist Streaming – stream: false setzen zum Deaktivieren
  4. 4

    Step 4: OpenAI-SDK-kompatible Schnittstelle nutzen

    Aufruf mit Python OpenAI SDK:

    • base_url='http://localhost:11434/v1/' setzen
    • api_key beliebig (lokal keine Validierung)
    • Restlicher Code identisch zu OpenAI
    • Umgebungswechsel: nur base_url anpassen (lokal vs. OpenAI in Produktion)
  5. 5

    Step 5: Streaming-Antworten verarbeiten

    Wichtige Punkte beim Streaming:

    • Python: response.iter_lines() liest NDJSON zeilenweise
    • JavaScript: response.body.getReader() für Stream-Lesen
    • Jeder Chunk enthält nur wenige Zeichen – Inhalt akkumulieren
    • Nicht-Streaming: stream: false liefert vollständiges JSON

FAQ

Was ist der Unterschied zwischen Ollamas nativer API und der OpenAI-SDK-kompatiblen Schnittstelle?
Die native API ist schlanker und direkter, streamt standardmäßig (NDJSON) und eignet sich für eigene HTTP-Clients. Die OpenAI-SDK-kompatible Schnittstelle ist vollständig kompatibel – nur base_url ändern, ideal für schnelle Migration bestehenden OpenAI-Codes.
Warum liefert mein Ollama-API-Aufruf nur ein halbes Wort zurück?
Das ist das Standardverhalten beim Streaming. Ollama gibt im NDJSON-Format tokenweise aus – jedes JSON-Objekt enthält nur wenige Zeichen. Lösungen:

• stream: false setzen für vollständiges JSON
• Oder NDJSON-Stream korrekt verarbeiten: zeilenweise lesen und Inhalt akkumulieren
Wie nutze ich lokal Ollama in der Entwicklung und OpenAI in der Produktion?
Per Umgebungsvariable wechseln: In der Entwicklung LLM_ENDPOINT="http://localhost:11434/v1", in der Produktion "https://api.openai.com/v1". Im Code base_url aus der Umgebungsvariable lesen – sonst bleibt alles gleich.
Welche OpenAI-Endpunkte unterstützt Ollama?
Voll unterstützt: /v1/chat/completions, /v1/completions, /v1/models, /v1/embeddings, /v1/responses. Experimentell: /v1/images/generations (Stabilität noch eingeschränkt).
Kann ich Ollama-Modellen Aliase geben?
Ja. Befehl: ollama cp llama3.2 gpt-3.5-turbo – dann verwendet model="gpt-3.5-turbo" im Code lokal llama3.2. Praktischer Trick bei der Code-Migration.
Unterstützt Ollama Tool Calling (Function Calling)?
Ja. Über die OpenAI-SDK-kompatible Schnittstelle mit dem tools-Parameter: Funktionsschema definieren, das Modell liefert tool_calls mit dem aufzurufenden Funktionsnamen.

6 Min. Lesezeit · Veröffentlicht am: 3. Apr. 2026 · Aktualisiert am: 9. Juli 2026

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog