So verwenden Sie Ollama für Streaming-Antworten und Tool-Aufrufe

Dieser Leitfaden zeigt, wie man Ollamas neue Funktionen nutzt: Streaming & Tool-Aufrufe in Echtzeit. Ideal für lebendige Chat-Apps.

Leo Schulz

Leo Schulz

5 June 2025

So verwenden Sie Ollama für Streaming-Antworten und Tool-Aufrufe

Dieser Leitfaden führt Sie durch die Verwendung einer der neuen leistungsstarken Funktionen von Ollama: die Fähigkeit, Antworten zu streamen und Tools (wie Funktionen oder APIs) in Echtzeit aufzurufen. Dies ist ein Game-Changer für die Entwicklung von Chat-Anwendungen, die sich lebendig anfühlen und mit der Welt um sie herum interagieren können.

Was Sie in diesem Tutorial lernen werden:

💡
Benötigen Sie ein großartiges API-Testtool, das wunderschöne API-Dokumentation generiert?

Benötigen Sie eine integrierte All-in-One-Plattform, damit Ihr Entwicklerteam mit maximaler Produktivität zusammenarbeiten kann?

Apidog liefert alle Ihre Anforderungen und ersetzt Postman zu einem viel günstigeren Preis!
button

Erste Schritte: Was Sie benötigen

Um mitzumachen, benötigen Sie ein paar Dinge:

Grundlegendes zu Schlüsselideen: Streaming und Tool-Aufrufe

Lassen Sie uns aufschlüsseln, was wir mit "Streaming-Antworten" und "Tool-Aufrufen" meinen.

Was ist Response Streaming?

Stellen Sie sich vor, Sie chatten mit einer KI. Anstatt darauf zu warten, dass sie nachdenkt und ihre gesamte Antwort eintippt, bevor Sie etwas sehen, bedeutet Streaming, dass die KI ihre Antwort Stück für Stück, Wort für Wort, sendet, während sie sie generiert. Dies lässt die Interaktion viel schneller und natürlicher erscheinen, wie eine echte Konversation.

Wenn Sie in Ollama Streaming aktivieren ("stream": true), erhalten Sie diese inkrementellen Updates.

Wie funktioniert Tool-Aufruf?

Tool-Aufrufe ermöglichen es Ihren KI-Modellen, mehr zu tun, als nur Text zu generieren. Sie können "Tools" definieren – im Wesentlichen Funktionen oder externe APIs –, die die KI verwenden kann, um Informationen zu erhalten oder Aktionen auszuführen.

Ein Tool könnte beispielsweise sein:

Sie beschreiben diese Tools für Ollama, und wenn die KI feststellt, dass die Verwendung eines Tools bei der Beantwortung der Abfrage des Benutzers hilfreich wäre, signalisiert sie ihre Absicht, dieses Tool mit bestimmten Argumenten aufzurufen. Ihre Anwendung führt dann das Tool aus und kann die Ergebnisse zurück an die KI senden, um die Konversation fortzusetzen.

Warum Streaming mit Tool-Aufrufen kombinieren?

Ollamas großes Upgrade ist, dass es jetzt Tool-Aufrufe während des Streamings von Antworten verarbeiten kann. Dies bedeutet, dass Ihre Anwendung Folgendes kann:

  1. Erhalten Sie anfänglichen Text vom Modell (gestreamt).
  2. Plötzlich könnte der Stream anzeigen, dass ein Tool-Aufruf benötigt wird.
  3. Ihre App verarbeitet den Tool-Aufruf.
  4. In der Zwischenzeit könnte das Modell sogar mehr Text streamen (z. B. "Okay, ich hole das Wetter für Sie...").
  5. Sobald Ihre App das Ergebnis des Tools erhält, können Sie es zurück an das Modell senden, und es wird seine Antwort weiter streamen, jetzt informiert durch die Ausgabe des Tools.

Dies erzeugt hochgradig reaktionsfähige und leistungsfähige KI-Anwendungen.

Welche Modelle unterstützen diese Funktionen?

Ollama hat dies für mehrere beliebte Modelle aktiviert, darunter:

So tätigen Sie Ihren ersten Streaming-Tool-Aufruf mit cURL

cURL ist eine großartige Möglichkeit, die API von Ollama schnell zu testen. Fragen wir nach dem Wetter in Toronto.

Schritt 1: Konzeption Ihres Tools

Unser Tool wird get_current_weather sein. Es benötigt:

Schritt 2: Erstellen des cURL-Befehls

Öffnen Sie Ihr Terminal und bereiten Sie den folgenden Befehl vor. Wir werden ihn aufschlüsseln:

curl <http://localhost:11434/api/chat> -d '{
  "model": "qwen3",
  "messages": [
    {
      "role": "user",
      "content": "What is the weather today in Toronto?"
    }
  ],
  "stream": true,
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_current_weather",
        "description": "Get the current weather for a location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The location to get the weather for, e.g. San Francisco, CA"
            },
            "format": {
              "type": "string",
              "description": "The format to return the weather in, e.g. \\\\\\\\'celsius\\\\\\\\' or \\\\\\\\'fahrenheit\\\\\\\\'",
              "enum": ["celsius", "fahrenheit"]
            }
          },
          "required": ["location", "format"]
        }
      }
    }
  ]
}'

Aufschlüsselung:

Schritt 3: Ausführen und Beobachten der Ausgabe

Drücken Sie die Eingabetaste. Sie sehen eine Reihe von JSON-Objekten, die nacheinander erscheinen. Das ist der Stream!

Beispiel-Snippets aus dem Stream:

{
  "model": "qwen3", "created_at": "...",
  "message": { "role": "assistant", "content": "Okay, " }, "done": false
}

{
  "model": "qwen3", "created_at": "...",
  "message": { "role": "assistant", "content": "I will " }, "done": false
}

{
  "model": "qwen3", "created_at": "...",
  "message": { "role": "assistant", "content": "try to get that for you." }, "done": false
}

(Das Modell könnte je nach seinem internen Prozess einige "Denk"-Token wie <think>...celsius...</think> ausgeben, diese sind ebenfalls Teil des Streams)

Dann, entscheidend, könnten Sie so etwas sehen:

{
  "model": "qwen3",
  "created_at": "2025-05-27T22:54:58.100509Z",
  "message": {
    "role": "assistant",
    "content": "", // Content might be empty when a tool call is made
    "tool_calls": [
      {
        "function": {
          "name": "get_current_weather",
          "arguments": { // The arguments the model decided on!
            "format": "celsius",
            "location": "Toronto"
          }
        }
      }
    ]
  },
  "done": false // Still not done, awaiting tool result
}

Was zu beachten ist:

In einer realen Anwendung würde Ihr Code, wenn Sie einen tool_calls-Chunk sehen, Folgendes tun:

  1. Die Verarbeitung des Streams anhalten (oder ihn asynchron verarbeiten).
  2. Führen Sie die eigentliche get_current_weather-Funktion/API mit "Toronto" und "celsius" aus.
  3. Erhalten Sie das Ergebnis (z. B. "20 Grad Celsius").
  4. Senden Sie dieses Ergebnis in einer neuen Nachricht mit role: "tool" zurück an Ollama.
  5. Das Modell verwendet diese Informationen dann, um seine Antwort fortzusetzen, ebenfalls gestreamt.

So streamen Sie Tool-Aufrufe mit Python

Implementieren wir eine ähnliche Idee in Python mit der offiziellen Bibliothek von Ollama.

Schritt 1: Installieren der Ollama Python-Bibliothek

Installieren oder aktualisieren Sie die Bibliothek, falls noch nicht geschehen:

pip install -U ollama

Schritt 2: Definieren Ihres Tools und Programmieren in Python

Das Ollama Python SDK ermöglicht es Ihnen geschickt, Python-Funktionen direkt als Tools zu übergeben. Es untersucht die Funktionssignatur und den Docstring, um das Schema für die KI zu erstellen.

Erstellen wir ein einfaches Mathe-Tool-Beispiel (die Eingabe verwendet add_two_numbers, aber das Ausgabebispiel zeigt, dass subtract_two_numbers vom Modell aufgerufen wird. Wir halten uns an die bereitgestellte add_two_numbers für die Definition und lassen das Modell entscheiden, was basierend auf der Eingabeaufforderung zu tun ist.)

import ollama

# Definieren Sie die Python-Funktion, die als Tool verwendet werden kann
def add_two_numbers(a: int, b: int) -> int:
  """
  Addieren Sie zwei Zahlen.

  Argumente:
    a (int): Die erste Zahl als int.
    b (int): Die zweite Zahl als int.

  Gibt zurück:
    int: Die Summe der beiden Zahlen.
  """
  print(f"--- Tool 'add_two_numbers' called with a={a}, b={b} ---")
  return a + b

# --- Hauptlogik der Konversation ---
messages = [{'role': 'user', 'content': 'Was ist drei plus eins?'}]
# Oder, für das Subtraktionsbeispiel in der ursprünglichen Ausgabe:
# messages = [{'role': 'user', 'content': 'was ist drei minus eins?'}]

print(f"Benutzer: {messages[0]['content']}")

# Stellen Sie die Chat-Anfrage mit Streaming und dem Tool
# Hinweis: ChatResponse-Typ-Hinweis kann je nach Bibliotheksversion ollama.ChatResponse oder ähnlich sein
response_stream = ollama.chat(
  model='qwen3', # Oder ein anderes fähiges Modell
  messages=messages,
  tools=[
      { # Sie können das Tool auch explizit definieren, falls erforderlich, oder die Funktion direkt übergeben
          'type': 'function',
          'function': {
              'name': 'add_two_numbers', # Muss mit dem Python-Funktionsnamen übereinstimmen, wenn Sie möchten, dass er später direkt von Ihrem Code aufgerufen wird
              'description': 'Addieren Sie zwei ganze Zahlen.',
              'parameters': {
                  'type': 'object',
                  'properties': {
                      'a': {'type': 'integer', 'description': 'Die erste Zahl'},
                      'b': {'type': 'integer', 'description': 'Die zweite Zahl'}
                  },
                  'required': ['a', 'b']
              }
          }
      }
      # Einfachere Methode für Python: Übergeben Sie die Funktion direkt, wenn die Bibliothek eine einfache Schemaerstellung daraus unterstützt
      # tools=[add_two_numbers] # Das SDK kann das Schema oft daraus erstellen
  ],
  stream=True
)

print("Assistent (Streaming):")
full_response_content = ""
tool_call_info = None

for chunk in response_stream:
  # Drucken Sie den gestreamten Inhaltsteil
  if chunk['message']['content']:
    print(chunk['message']['content'], end='', flush=True)
    full_response_content += chunk['message']['content']

  # Suchen Sie nach Tool-Aufrufen im Chunk
  if 'tool_calls' in chunk['message'] and chunk['message']['tool_calls']:
    tool_call_info = chunk['message']['tool_calls'][0] # Unter der Annahme eines Tool-Aufrufs zur Vereinfachung
    print(f"\\\\n--- Tool-Aufruf erkannt: {tool_call_info['function']['name']} ---")
    break # Beenden Sie vorerst die Verarbeitung des Streams, verarbeiten Sie den Tool-Aufruf

  if chunk.get('done'):
      print("\\\\n--- Stream beendet ---")
      if not tool_call_info:
          print("Es wurde kein Tool-Aufruf getätigt.")

# --- Wenn ein Tool-Aufruf erkannt wurde, verarbeiten Sie ihn ---
if tool_call_info:
  tool_name = tool_call_info['function']['name']
  tool_args = tool_call_info['function']['arguments']

  print(f"Argumente für das Tool: {tool_args}")

  # Hier würden Sie tatsächlich Ihre Python-Tool-Funktion aufrufen
  if tool_name == "add_two_numbers":
    # Stellen Sie zur Sicherheit sicher, dass die Argumente vom richtigen Typ sind, falls erforderlich
    try:
        arg_a = int(tool_args.get('a'))
        arg_b = int(tool_args.get('b'))
        tool_result = add_two_numbers(a=arg_a, b=arg_b)
        print(f"--- Tool-Ausführungsergebnis: {tool_result} ---")

        # Senden Sie dieses Ergebnis nun zurück an Ollama, um die Konversation fortzusetzen
        messages.append({'role': 'assistant', 'content': full_response_content, 'tool_calls': [tool_call_info]})
        messages.append({
            'role': 'tool',
            'content': str(tool_result), # Ergebnis muss ein String sein
            'tool_call_id': tool_call_info.get('id', '') # Wenn Ihre Bibliothek/Ihr Modell eine tool_call_id bereitstellt
        })

        print("\\\\n--- Senden des Tool-Ergebnisses zurück an das Modell ---")

        follow_up_response_stream = ollama.chat(
            model='qwen3',
            messages=messages,
            stream=True
            # Hier werden keine Tools benötigt, es sei denn, Sie erwarten einen weiteren Tool-Aufruf
        )

        print("Assistent (nach Tool-Aufruf):")
        for follow_up_chunk in follow_up_response_stream:
            if follow_up_chunk['message']['content']:
                print(follow_up_chunk['message']['content'], end='', flush=True)
            if follow_up_chunk.get('done'):
                print("\\\\n--- Follow-up-Stream beendet ---")
                break
    except ValueError:
        print("Fehler: Argumente des Tools konnten nicht als Ganzzahlen geparst werden.")
    except Exception as e:
        print(f"Während der Tool-Ausführung oder des Follow-ups ist ein Fehler aufgetreten: {e}")
  else:
    print(f"Fehler: Vom Modell wurde das unbekannte Tool '{tool_name}' angefordert.")

Erläuterung des Python-Codes:

  1. Importieren Sie ollama.
  2. add_two_numbers-Funktion: Dies ist unser Tool. Der Docstring und die Typ-Hinweise helfen Ollama, seinen Zweck und seine Parameter zu verstehen.
  3. messages: Wir beginnen die Konversation mit der Abfrage des Benutzers.
  4. ollama.chat(...):
  1. Schleife durch response_stream:
  1. Verarbeiten des Tool-Aufrufs:

Erwarteter Ausgabefluss: Sie sehen die ursprüngliche Benutzerfrage, dann die Antwort des Assistenten, die gestreamt wird. Wenn es sich entscheidet, add_two_numbers (oder subtract_two_numbers wie in der Beispielausgabe des ursprünglichen Materials, wenn die Eingabeaufforderung für die Subtraktion war) aufzurufen, sehen Sie die Meldung "Tool-Aufruf erkannt", die Argumente, das Ergebnis Ihrer Python-Funktion und dann den Assistenten, der seine Antwort unter Verwendung dieses Ergebnisses fortsetzt.

(Die ursprüngliche Beispielausgabe zeigte:

<think>
Okay, the user is asking ...
</think>

[ToolCall(function=Function(name='subtract_two_numbers', arguments={'a': 3, 'b': 1}))]

Dies zeigt den internen "Denk"-Prozess der KI und dann das strukturierte Tool-Aufrufobjekt, das das Python SDK bereitstellt.)

So streamen Sie Tool-Aufrufe mit JavaScript (Node.js)

Lassen Sie uns nun dasselbe mit JavaScript tun, typischerweise für ein Node.js-Backend oder eine Webanwendung.

Schritt 1: Installieren der Ollama JavaScript-Bibliothek

Führen Sie in Ihrem Projektverzeichnis Folgendes aus:

npm i ollama

Schritt 2: Definieren des Tool-Schemas und Programmieren in JavaScript

In JavaScript definieren Sie das Tool-Schema normalerweise als JSON-Objekt.

import ollama from 'ollama';

// Beschreiben Sie das Tool-Schema (z. B. zum Addieren von zwei Zahlen)
const addTool = {
    type: 'function',
    function: {
        name: 'addTwoNumbers',
        description: 'Addieren Sie zwei Zahlen',
        parameters: {
            type: 'object',
            required: ['a', 'b'],
            properties: {
                a: { type: 'number', description: 'Die erste Zahl' },
                b: { type: 'number', description: 'Die zweite Zahl' }
            }
        }
    }
};

// Ihre eigentliche JavaScript-Funktion, die das Tool implementiert
function executeAddTwoNumbers(a, b) {
    console.log(`--- Tool 'addTwoNumbers' called with a=${a}, b=${b} ---`);
    return a + b;
}

async function main() {
    const messages = [{ role: 'user', content: 'Was ist 2 plus 3?' }];
    console.log('Benutzer:', messages[0].content);

    console.log('Assistent (Streaming):');
    let assistantResponseContent = "";
    let toolToCallInfo = null;

    try {
        const responseStream = await ollama.chat({
            model: 'qwen3', // Oder ein anderes fähiges Modell
            messages: messages,
            tools: [addTool],
            stream: true
        });

        for await (const chunk of responseStream) {
            if (chunk.message.content) {
                process.stdout.write(chunk.message.content);
                assistantResponseContent += chunk.message.content;
            }
            if (chunk.message.tool_calls && chunk.message.tool_calls.length > 0) {
                toolToCallInfo = chunk.message.tool_calls[0]; // Unter der Annahme eines Tool-Aufrufs
                process.stdout.write(`\\\\n--- Tool-Aufruf erkannt: ${toolToCallInfo.function.name} ---\\\\n`);
                break; // Beenden Sie die Verarbeitung des Streams, um den Tool-Aufruf zu verarbeiten
            }
            if (chunk.done) {
                process.stdout.write('\\\\n--- Stream beendet ---\\\\n');
                if (!toolToCallInfo) {
                    console.log("Es wurde kein Tool-Aufruf getätigt.");
                }
                break;
            }
        }

        // --- Wenn ein Tool-Aufruf erkannt wurde, verarbeiten Sie ihn ---
        if (toolToCallInfo) {
            const toolName = toolToCallInfo.function.name;
            const toolArgs = toolToCallInfo.function.arguments;

            console.log(`Argumente für das Tool:`, toolArgs);

            let toolResult;
            if (toolName === 'addTwoNumbers') {
                toolResult = executeAddTwoNumbers(toolArgs.a, toolArgs.b);
                console.log(`--- Tool-Ausführungsergebnis: ${toolResult} ---`);

                // Hängen Sie die Teilausgabe des Assistenten und die Tool-Nachricht an
                messages.push({
                    role: 'assistant',
                    content: assistantResponseContent, // Fügen Sie den Inhalt vor dem Tool-Aufruf ein
                    tool_calls: [toolToCallInfo]
                });
                messages.push({
                    role: 'tool',
                    content: toolResult.toString(), // Ergebnis muss ein String sein
                    // tool_call_id: toolToCallInfo.id // Falls verfügbar und benötigt
                });

                console.log("\\\\n--- Senden des Tool-Ergebnisses zurück an das Modell ---");
                const followUpStream = await ollama.chat({
                    model: 'qwen3',
                    messages: messages,
                    stream: true
                });

                console.log("Assistent (nach Tool-Aufruf):");
                for await (const followUpChunk of followUpStream) {
                    if (followUpChunk.message.content) {
                        process.stdout.write(followUpChunk.message.content);
                    }
                     if (followUpChunk.done) {
                        process.stdout.write('\\\\n--- Follow-up-Stream beendet ---\\\\n');
                        break;
                    }
                }
            } else {
                console.error(`Fehler: Das unbekannte Tool '${toolName}' wurde angefordert.`);
            }
        }

    } catch (error) {
        console.error('Fehler während des Ollama-Chats:', error);
    }
}

main().catch(console.error);

Erläuterung des JavaScript-Codes:

  1. Importieren Sie ollama.
  2. addTool-Objekt: Dies ist das JSON-Schema, das unser Tool für Ollama beschreibt.
  3. executeAddTwoNumbers-Funktion: Unsere eigentliche JavaScript-Funktion für das Tool.
  4. main-Async-Funktion:
  1. Verarbeiten des Tool-Aufrufs: Ähnlich wie bei Python, wenn toolToCallInfo gesetzt ist:

Erwarteter Ausgabefluss (ähnlich den cURL- und Python-Beispielen): Sie sehen die Frage des Benutzers, dann die Antwort des Assistenten, die gestreamt wird. Wenn es sich entscheidet, addTwoNumbers aufzurufen, werden die Tool-Aufrufinformationen, das Ergebnis Ihrer JavaScript-Funktion ausgegeben und dann die Antwort der KI basierend auf diesem Ergebnis weiter gestreamt.

Die ursprüngliche Beispielausgabe für JS sah so aus:

Question: What is 2 plus 3?
<think>
Okay, the user is asking...
</think>
Tool call: {
  function: {
    name: "addTwoNumbers",
    arguments: { a: 2, b: 3 },
  },
}

Wie Ollama die Tool-Analyse während des Streamings handhabt

Sie fragen sich vielleicht, wie Ollama es schafft, Text zu streamen und Tool-Aufrufe so reibungslos zu identifizieren. Es verwendet einen cleveren neuen inkrementellen Parser.

Warum ist das besser?

Tipp: Verbesserung der Leistung mit dem Kontextfenster

Für komplexere Interaktionen, insbesondere mit Tool-Aufrufen, kann die Größe des "Kontextfensters", das das Modell verwendet, von Bedeutung sein. Ein größeres Kontextfenster bedeutet, dass sich das Modell mehr von der aktuellen Konversation merkt.

Beispiel: Festlegen des Kontextfensters mit cURL (Verwenden Sie ein Modell, das größere Kontexte unterstützt, wie z. B. llama3.1 oder llama4, wie im ursprünglichen Material vorgeschlagen – obwohl das Beispiel llama3.2 verwendet)

curl -X POST "<http://localhost:11434/api/chat>" -d '{
  "model": "llama3.1",
  "messages": [
    {
      "role": "user",
      "content": "why is the sky blue?"
    }
  ],
  "options": {
    "num_ctx": 32000
  }
}'

Experimentieren Sie mit dieser Einstellung, wenn Sie feststellen, dass Tool-Aufrufe nicht so zuverlässig sind, wie Sie es sich wünschen.

Explore more

Fathom-R1-14B: Fortschrittliches KI-Argumentationsmodell aus Indien

Fathom-R1-14B: Fortschrittliches KI-Argumentationsmodell aus Indien

Künstliche Intelligenz wächst rasant. FractalAIResearch/Fathom-R1-14B (14,8 Mrd. Parameter) glänzt in Mathe & Logik.

5 June 2025

Cursor 1.0 mit BugBot: KI-gestütztes Automatisierungstest-Tool ist da:

Cursor 1.0 mit BugBot: KI-gestütztes Automatisierungstest-Tool ist da:

Die Softwareentwicklung erlebt Innovationen durch KI. Cursor, ein KI-Editor, erreicht mit Version 1.0 einen Meilenstein.

5 June 2025

30+ öffentliche Web 3.0 APIs, die Sie jetzt nutzen können

30+ öffentliche Web 3.0 APIs, die Sie jetzt nutzen können

Der Aufstieg von Web 3.0: Dezentral, nutzerorientiert, transparent. APIs ermöglichen innovative dApps und Blockchain-Integration.

4 June 2025

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen