Zum Hauptinhalt springen

Kimi K2 Thinking: Open-Source-LLM-Guide, Benchmarks und Tools

Praxisnahes Tutorial: Kimi K2 Thinking ausführen, Tool-Workflows bauen, transparentes Reasoning einsehen und gegen GPT-5 und Claude 4.5 benchmarken.
· 15 Min. lesen

Entdecke KI

Ein Open-Source-Modell übertrifft GPT-5 und Claude Sonnet 4.5 in wichtigen Benchmarks – bei einem Bruchteil der Kosten. Das Modell heißt Kimi K2 Thinking, die Reasoning-Variante von Moonshot AI, veröffentlicht im November 2025.

Kimi K2 Thinking kann 200–300 Toolaufrufe in Folge eigenständig ausführen – ideal für komplexe agentische Workflows. Zudem legt es seinen Denkprozess über ein eigenes API-Feld offen – du siehst also genau, wie es Probleme durchdenkt.

Dieses Tutorial zeigt dir, wie du die Kimi K2 Thinking API für Reasoning-Aufgaben nutzt. Du implementierst Tool-Workflows, baust eine Vergleichs-Chat-App, um K2 gegen GPT-5 und Claude zu testen, und lernst, wann K2 dank seiner Stärken die bessere Wahl ist. Wenn du tiefer in das Bauen von LLM-Apps einsteigen willst, empfehle ich den Kurs Developing LLM Applications with LangChain. Schau dir außerdem unsere Projekte zu GPT-5.1-Codex und Qwen3-Max-Thinking an. Empfehlenswert ist auch unser Guide zu Kimi K2.5 mit Agent Swarm.

Hier ist eine Vorschau der App:

Bevor wir in die Praxis einsteigen, schauen wir uns an, was K2 Thinking von herkömmlichen Sprachmodellen unterscheidet.

Was ist Kimi K2 Thinking?

Die meisten Sprachmodelle generieren Antworten sofort. K2 Thinking funktioniert anders. Es ist für mehrstufige Probleme gebaut, bei denen das Modell selbstständig planen, schlussfolgern und handeln muss.

Architektur und Design

Das Modell nutzt eine Mixture-of-Experts (MoE)-Architektur mit insgesamt 1 Billion Parametern. Pro Eingabe werden jedoch nur 32 Milliarden aktiviert. So erhält K2 die Power eines riesigen Modells ohne hohe Inferenzkosten. Das Kontextfenster mit 256.000 Tokens erlaubt dir, komplette Codebasen, lange Dokumente oder umfangreiche Chat-Verläufe ohne Chunking zu verarbeiten.

Moonshot AI hat zwei Versionen veröffentlicht. K2 Instruct übernimmt direkte Aufgaben wie Textgenerierung, Klassifikation und einfache Q&A, bei denen Geschwindigkeit zählt. K2 Thinking ist für komplexe Reasoning-Aufgaben gedacht.

Zwei herausragende Fähigkeiten

Erstens: Transparentes Reasoning. Du siehst, wie K2 Probleme zerlegt, Optionen bewertet und zu Schlussfolgerungen kommt.

Zweitens: Tool-Orchestrierung. K2 beherrscht lange Sequenzen an Toolaufrufen – weit über das hinaus, was die meisten Modelle leisten. Es entscheidet, welche Tools wann und wie kombiniert werden – ohne dass du in jeder Stufe eingreifen musst.

Weitere Features

K2 bringt Features für unterschiedliche Deployments mit. Für produktive Szenarien, in denen Genauigkeit entscheidend ist, führt der Heavy Mode acht Reasoning-Pfade parallel aus und wählt die beste Antwort – bei höheren Rechenkosten. 

Für latenzkritische Anwendungen verdoppelt INT4-Quantisierung die Inferenzgeschwindigkeit bei minimalem Genauigkeitsverlust – ideal für High-Throughput-Umgebungen.

Kimi K2 Thinking vs. GPT-5 vs. Claude Sonnet 4.5 vs. DeepSeek

So schneidet K2 im Vergleich zu GPT-5, Claude Sonnet 4.5 und DeepSeek V3.2 ab.

Messgröße

Kimi K2 Thinking

GPT-5 (High)

Claude Sonnet 4.5

DeepSeek-V3.2

HLE (mit Tools)

44.9

41.7

32

20.3

HLE Heavy Mode

51

42

—

—

AIME25 (mit Python)

99,1 %

99,6 %

100 %

58,1 %

GPQA

84.5

85.7

83.4

79.9

BrowseComp

60.2

54.9

24.1

40.1

Frames

87

86

85

80.2

SWE-bench Verified

71,3 %

74,9 %

77,2 %

67,8 %

LiveCodeBench

83,1 %

87,0 %

64,0 %

74,1 %

Kontextfenster

256 k Tokens

400 k Tokens

200 k Tokens

128 k Tokens

Input-Preise

$0,60 / 1 Mio.

$1,25 / 1 Mio.

$3,00 / 1 Mio.

$0,55 / 1 Mio.

Output-Preise

$2,50 / 1 Mio.

$10,00 / 1 Mio.

$15,00 / 1 Mio.

$2,19 / 1 Mio.

Max. Toolaufrufe

200–300

Dutzende +

Dutzende +

Nicht angegeben

Kurze Benchmark-Definitionen: HLE prüft Wissen auf Master-Niveau, AIME25 nutzt Wettbewerbs-Matheaufgaben, BrowseComp und Frames testen Web-Navigation und Synthese, SWE-bench Verified misst Bugfixes in Open-Source-Code, LiveCodeBench testet Codegenerierung, und GPQA umfasst naturwissenschaftliche Fragen auf Graduierten-Niveau.

K2s Tool-Training zeigt sich besonders deutlich in agentischen Benchmarks. Heavy Mode schlägt GPT-5 in HLE um 9 Punkte, weil acht Reasoning-Pfade parallel laufen. Claudes Code-Training verschafft ihm bei SWE-bench Verified den Vorsprung – die beste Wahl für Software-Engineering-Projekte.

Bei reinem Reasoning liegen alle drei Modelle nah beieinander. Unterschiede entstehen, sobald Tools im Spiel sind. K2s Kapazität von 200–300 Toolaufrufen ermöglicht autonome Research-Workflows, Debugging-Pipelines und mehrstufige Datenanalysen – ohne manuelles Eingreifen in jeder Phase.

Welches Modell wofür?

  • Wähle K2 Thinking für agentische Workflows mit intensiver Tool-Orchestrierung, Web-Recherche und Informationssynthese – oder wenn du transparente Reasoning-Ketten für Debugging oder Compliance brauchst.
  • Wähle GPT-5 für das größte Kontextfenster mit 400k Tokens oder wenn du ausgewogene Leistung über viele Aufgaben mit ausgereiftem Ökosystem willst.
  • Wähle Claude Sonnet 4.5 für Software-Engineering-Projekte, bei denen Debugging und Codefixes im Vordergrund stehen.
  • Wähle DeepSeek, wenn Budget Priorität hat und du Open Source unter MIT-Lizenz benötigst.

Kimi K2 Thinking API-Zugang einrichten

Du hast zwei Möglichkeiten, auf K2 Thinking zuzugreifen: direkt über Moonshot AIs platform.moonshot.ai oder über OpenRouter, ein einheitliches API-Gateway. Wir nutzen OpenRouter, weil du damit K2, GPT-5, Claude und Dutzende weitere Modelle mit einem einzigen API-Schlüssel nutzen kannst. Dieser einheitliche Zugang ist später für die Vergleichs-Chat-App essenziell. OpenRouter übernimmt zudem automatisch Rate-Limits und Failover – du musst keine mehreren Provider-Konten managen.

Erstelle zunächst auf openrouter.ai ein Konto. Anmelden geht per Google oder GitHub. Wechsel danach im Dashboard in den Bereich „Keys“ und generiere einen neuen API-Schlüssel. 

OpenRouter schenkt dir bei der Anmeldung $5 Guthaben – genug, um K2 Thinking mit mehreren Abfragen zu testen. Falls du mehr brauchst, kannst du im Bereich „Credits“ eine Zahlungsmethode hinterlegen.

Kopiere deinen API-Schlüssel und bewahre ihn sicher auf. Du brauchst ihn gleich. Committe ihn nicht in die Versionskontrolle und teile ihn nicht öffentlich – jeder mit deinem Schlüssel kann API-Aufrufe über dein Konto ausführen.

Jetzt richten wir deine Python-Umgebung ein. Du brauchst das OpenAI Python SDK, das mit OpenRouters API funktioniert, da diese OpenAI-kompatibel ist. Außerdem empfiehlt sich python-dotenv, um den API-Schlüssel sicher zu verwalten. Installiere beide Pakete:

!pip install openai python-dotenv

Erstelle in deinem Projektverzeichnis eine .env-Datei und füge deinen OpenRouter-API-Schlüssel ein:

OPENROUTER_API_KEY=your_key_here

Wenn du git verwendest, füge .env zu deiner .gitignore-Datei hinzu, damit du deine Zugangsdaten nicht versehentlich commitest.

Hier ein schneller Test, um alles zu verifizieren:

import os
from openai import OpenAI
from dotenv import load_dotenv

# Load API key from .env file
load_dotenv()

# Configure client for OpenRouter
client = OpenAI(
   base_url="https://openrouter.ai/api/v1",
   api_key=os.getenv("OPENROUTER_API_KEY")
)

# Test call to K2 Thinking
response = client.chat.completions.create(
   model="moonshotai/kimi-k2-thinking",
   messages=[
       {"role": "user", "content": "What is 15 * 24?"}
   ]
)

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

Ausgabe:

15 * 24 = **360**

Wenn du die Antwort siehst, ist alles bereit.

Den Thinking Mode von Kimi K2 verstehen

Wir haben vorhin K2s transparentes Reasoning erwähnt. Jetzt schauen wir uns an, wie du es im Code abrufst. K2 Thinking legt seinen Denkprozess automatisch über ein eigenes API-Feld offen. 

Anders als bei manchen Modellen musst du den Thinking Mode nicht manuell aktivieren – K2 liefert standardmäßig Reasoning-Inhalte in jeder Antwort mit.

So greifst du auf Reasoning-Inhalte zu

Bei einem API-Call an K2 Thinking enthält die Antwort zwei Felder. Das content-Feld enthält die finale Antwort, und das reasoning-Feld zeigt den schrittweisen Denkprozess. Hier ein Praxisbeispiel mit einer Rabattberechnung in mehreren Schritten:

import os
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

client = OpenAI(
   base_url="https://openrouter.ai/api/v1",
   api_key=os.getenv("OPENROUTER_API_KEY")
)

response = client.chat.completions.create(
   model="moonshotai/kimi-k2-thinking",
   messages=[
       {"role": "user", "content": "A laptop costs $850. There's a 20% discount today, then 8% sales tax applies to the discounted price. What's the final amount I pay?"}
   ],
   temperature=1.0
)

print("Final answer:")
print(response.choices[0].message.content)
print("\nReasoning process:")
print(response.choices[0].message.reasoning)

Ausgabe:

Final answer:
The final amount you pay is **$734.40**.

Here's the breakdown:

1. **Discount:** 20% of $850 = $170
2. **Discounted price:** $850 - $170 = $680
3. **Sales tax:** 8% of $680 = $54.40
4. **Final amount:** $680 + $54.40 = **$734.40**

Reasoning-Prozess (gekürzt für bessere Lesbarkeit):

The user wants to know the final amount they will pay for a laptop with a discount and then sales tax applied.

Step 1: Calculate the discount amount.
Discount amount = $850 * 0.20 = $170

Step 2: Calculate the discounted price.
Discounted price = $850 - $170 = $680

Step 3: Calculate the sales tax amount.
Sales tax amount = $680 * 0.08 = $54.40

Step 4: Calculate the final amount to pay.
Final amount = $680 + $54.40 = $734.40

Let me double-check the calculations...
[verification steps omitted]

The final amount is $734.40

Das content-Feld liefert die saubere Antwort für deine Nutzerinnen und Nutzer. Das reasoning-Feld zeigt, wie K2 gearbeitet hat – so erkennst du, ob das Modell wirklich korrekt geschlussfolgert hat oder nur Glück hatte.

K2 generiert Reasoning-Tokens während der Inferenz, nicht nachträglich. Das heißt, das Modell denkt die Aufgabe durch, bevor es sich auf eine Antwort festlegt – so wie du eine Matheaufgabe erst auf Schmierpapier löst, bevor du das Ergebnis notierst. Das Reasoning passiert in Echtzeit als Teil der Generierung.

Empfohlene Parameter für den Thinking Mode

Setze temperature=1.0, wenn du K2 Thinking nutzt. Niedrigere Temperaturen schränken die Explorationsfähigkeit des Modells ein – das konterkariert den Thinking Mode. Außerdem solltest du max_tokens=4096 oder höher wählen, da Reasoning-Ketten Tokens verbrauchen, noch bevor die finale Antwort beginnt.

response = client.chat.completions.create(
   model="moonshotai/kimi-k2-thinking",
   messages=[{"role": "user", "content": "Your question here"}],
   temperature=1.0,
   max_tokens=4096
)

Jetzt, da du den Thinking Mode kennst, schauen wir uns K2s nächste Schlüsselkompetenz an: Tool Calling. Viele Modelle unterstützen grundlegende Tools – K2 setzt sich in Umfang und Autonomie ab.

Kimi K2s Tool-Calling-Fähigkeiten

Mit Tool Calling kann K2 während des Reasonings Funktionen ausführen. Du definierst Tools als JSON-Schemata: was die Funktion macht und welche Parameter sie braucht. Wenn K2 externe Daten oder Rechenoperationen benötigt, ruft es das passende Tool auf und wartet auf Ergebnisse.

So entsteht ein Hin-und-her: K2 liest deinen Prompt und denkt darüber nach. Falls es ein Tool braucht, liefert es finish_reason: "tool_calls" zurück. Du führst die Funktion aus, übergibst die Ergebnisse mit role: "tool", und K2 macht weiter. Das wiederholt sich, bis K2 mit finish_reason: "stop" die finale Antwort liefert.

Das Schema folgt dem OpenAI-Format mit Name, Beschreibung und Parametern. K2 liest diese, um zu verstehen, wann welches Tool sinnvoll ist. Klare Beschreibungen sind wichtig – sie steuern die Entscheidungen des Modells.

Den CSV-Analyzer bauen

Wir bauen nun ein praktisches Tool zur Analyse von CSV-Dateien – eine häufige Aufgabe in der Data Science. Das Tool liest eine CSV, extrahiert Spalteninfos und gibt Zusammenfassungsstatistiken zurück. Es zeigt, wie K2 während des Reasonings auf externe Daten zugreift – essenziell für datengetriebene Anwendungen.

Hier ist die vollständige Implementierung:

import csv
import os
import json

# Define the tool schema
tools = [
   {
       "type": "function",
       "function": {
           "name": "analyze_csv",
           "description": "Read and analyze the first few rows of a CSV file. Returns columns, sample rows, total row count, and file size.",
           "parameters": {
               "type": "object",
               "properties": {
                   "filepath": {
                       "type": "string",
                       "description": "Path to the CSV file"
                   },
                   "num_rows": {
                       "type": "integer",
                       "description": "Number of rows to read",
                       "default": 10
                   }
               },
               "required": ["filepath"]
           }
       }
   }
]

Das Schema definiert ein Function-Tool im OpenAI-Format. Das description-Feld erklärt K2, was das Tool macht, und hilft zu entscheiden, wann es zum Einsatz kommen soll. 

Das parameters-Objekt spezifiziert die Inputs: filepath ist Pflicht, num_rows optional (Default 10). Aussagekräftige Beschreibungen helfen K2 zu erkennen, wann dieses Tool den Bedarf der Nutzer deckt.

Die Implementierung übernimmt die eigentliche Dateiverarbeitung:

# Implement the function
def analyze_csv(filepath: str, num_rows: int = 10) -> dict:
   if not os.path.exists(filepath):
       return {"error": f"File not found: {filepath}"}

   try:
       with open(filepath, 'r') as f:
           reader = csv.DictReader(f)
           columns = reader.fieldnames
           sample_rows = [dict(row) for i, row in enumerate(reader) if i < num_rows]
           f.seek(0)
           total_rows = sum(1 for _ in f) - 1

       return {
           "columns": list(columns),
           "sample_rows": sample_rows,
           "total_rows": total_rows,
           "file_size_kb": round(os.path.getsize(filepath) / 1024, 2)
       }
   except Exception as e:
       return {"error": str(e)}

Die Funktion prüft den Pfad und nutzt csv.DictReader, um CSV-Daten als Dictionaries mit Spaltennamen als Keys zu parsen. Sie liest die ersten num_rows Einträge, setzt mit seek(0) den Zeiger zurück und zählt die Gesamtzeilen. 

Das Rückgabe-Dictionary enthält Spaltennamen, Beispieldaten, Zeilenzahl und Dateigröße in KB. Fehlerbehandlung sorgt für hilfreiches Feedback bei Problemen.

Die Tool-Execution-Schleife implementieren

Mit definiertem Tool brauchst du eine Schleife, die das Gespräch zwischen K2 und deinen Funktionen steuert. Tool Calling ist kein Einmalvorgang. K2 kann mehrere Iterationen benötigen: Tool aufrufen, Ergebnis analysieren, entscheiden, ob ein weiteres Tool nötig ist, und wiederholen. Dafür brauchst du eine Schleife, die dieses Ping-Pong fortsetzt, bis K2 seine finale Antwort liefert.

Hier die komplette Implementierung mit einem realen Beispiel:

from openai import OpenAI

client = OpenAI(
   base_url="https://openrouter.ai/api/v1",
   api_key=os.getenv("OPENROUTER_API_KEY")
)

messages = [
   {"role": "user", "content": "Analyze sample_employees.csv and tell me the average salary for Engineering department employees."}
]

Das initialisiert den OpenAI-Client für OpenRouter und erstellt die erste User-Nachricht zur Analyse der Mitarbeitergehälter.

while True:
   response = client.chat.completions.create(
       model="moonshotai/kimi-k2-thinking",
       messages=messages,
       tools=tools,
       temperature=1.0
   )

   message = response.choices[0].message
   finish_reason = response.choices[0].finish_reason

   messages.append({
       "role": "assistant",
       "content": message.content,
       "tool_calls": message.tool_calls
   })

Die Hauptschleife sendet den Gesprächsverlauf mit verfügbaren Tools an K2. Nach dem Auslesen von Antwort und Finish-Reason wird alles angehängt, um den Kontext zu erhalten.

  if finish_reason == "tool_calls":
       for tool_call in message.tool_calls:
           function_name = tool_call.function.name
           arguments = json.loads(tool_call.function.arguments)

           if function_name == "analyze_csv":
               result = analyze_csv(**arguments)

           messages.append({
               "role": "tool",
               "content": json.dumps(result),
               "tool_call_id": tool_call.id
           })

   elif finish_reason == "stop":
       print(message.content)
       break

Fordert K2 Toolaufrufe an, führen wir die Funktionen mit den Argumenten aus und hängen die Ergebnisse mit passender tool_call_id an. Gibt K2 „stop“ zurück, drucken wir die finale Antwort und beenden die Schleife.

Lege für dieses Beispiel eine Datei sample_employees.csv an – mit Name, Abteilung und Gehalt für ca. 12 Mitarbeitende aus Engineering, Marketing, Sales und HR. Beim Ausführen ruft K2 typischerweise analyze_csv() mit num_rows ≥ 12 auf, um vollständige Daten abzudecken, identifiziert dann Engineering-Mitarbeitende und berechnet deren Durchschnittsgehalt.

Ausgabe:

Based on the CSV data, I found 5 Engineering employees in the sample:
- Alice Johnson: $95,000
- Carol White: $110,000
- Eve Davis: $88,000
- Iris Martinez: $102,000
- Kate Thomas: $92,000

The average salary for Engineering department employees is $97,400.

Die tool_call_id in jeder Antwort verknüpft Ergebnisse mit ihren Funktionsaufrufen. K2 kann mehrere Tools in einer Antwort anfordern, daher braucht jedes seine ID. Der vollständige Verlauf gibt K2 den nötigen Kontext für konsistentes Reasoning über Toolaufrufe hinweg.

K2s eigenständige Orchestrierung verstehen

Sobald du mit einfachem Tool Calling vertraut bist, zeigt sich K2s wahre Stärke: erweiterte Orchestrierung. K2 wurde von Anfang an auf Tool-Orchestrierung trainiert – nicht als Add-on. Das verändert, wie es mehrstufige Aufgaben abarbeitet. Die meisten Modelle schaffen 20–50 Toolaufrufe in Folge, bevor die Leistung abfällt. K2 bewältigt 200–300 bei konsistentem Reasoning.

Diese Kapazität ist entscheidend für eigenständige Workflows, bei denen das Modell entscheidet, Informationen sammelt, Ergebnisse validiert und iteriert, bis das Problem gelöst ist. Denk an Research-Aufgaben: K2 durchsucht Datenbanken, führt Cross-Checks durch, erkennt Lücken, verfeinert Queries und synthetisiert alles. Oder Datenpipelines mit Validierung in jedem Schritt. Oder Debugging-Workflows mit mehreren Hypothesen.

Geht es um „Führe diese eine Aktion aus“, reichen die meisten Modelle. Geht es um „Arbeite weiter, bis es gelöst ist“, wird K2s erweiterte Tool-Kapazität zum entscheidenden Faktor.

Eine Multi-Model-Vergleichs-Chat-App bauen

Du hast gesehen, wie K2 Thinking einzelne Aufgaben mit Tools und transparentem Reasoning löst. Jetzt testen wir es gegen die Konkurrenz. Du baust eine Streamlit-App, die Kimi K2 Thinking, GPT-5 und Claude Sonnet 4.5 gleichzeitig mit demselben Prompt abfragt. Die Oberfläche zeigt alle drei Antworten nebeneinander – so siehst du direkt, wie jedes Modell das Problem angeht.

Das vollständige Skript findest du in diesem GitHub Gist. Willst du nur die Testergebnisse, kannst du diesen Abschnitt überspringen. Die folgenden Schritte enthalten eine detaillierte Aufschlüsselung des über 200 Zeilen langen Skripts – hebe dir die Lektüre auf, wenn du Zeit hast, mitzuklicken. Los geht’s.

Schritt 1: Projekt-Setup und Abhängigkeiten

Für diese Vergleichs-App brauchst du API-Zugänge zu allen drei Modellen. Du benötigst dein OpenRouter-Konto (mit den $5 Startguthaben) und optional OpenAI- und Anthropic-API-Keys. Die $5 sollten reichen, um alle drei Modelle mehrfach zu testen. Mit reinem OpenRouter-Zugang kannst du K2 auch gegen andere über OpenRouter verfügbare Modelle vergleichen.

Installiere Streamlit für das Web-Interface und das Anthropic-SDK für Claude:

pip install streamlit anthropic

Erstelle die Datei model_comparison_chat.py. Die App lebt komplett in dieser Datei. Beginne mit den Imports:

import os
import time
from typing import Dict, List
from concurrent.futures import ThreadPoolExecutor, as_completed
from dotenv import load_dotenv
import streamlit as st
from openai import OpenAI
from anthropic import Anthropic

load_dotenv()

Schritt 2: API-Verbindungen konfigurieren

Du hast OPENROUTER_API_KEY bereits in deiner .env. Ergänze die Keys für GPT-5 und Claude:

OPENROUTER_API_KEY=your_openrouter_key  # Already set up
OPENAI_API_KEY=your_openai_key           # Add this
ANTHROPIC_API_KEY=your_anthropic_key     # Add this

Deinen OpenAI-API-Key bekommst du unter platform.openai.com, den Anthropic-Key unter console.anthropic.com. Mehr Details zu GPT-5 findest du im GPT-5-Guide. Für Claude Sonnet 4.5 lies die Übersicht zu Claude Sonnet 4.5.

Initialisiere die drei Clients:

KIMI_CLIENT = OpenAI(
   api_key=os.getenv("OPENROUTER_API_KEY"),
   base_url="https://openrouter.ai/api/v1"
)
GPT_CLIENT = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
CLAUDE_CLIENT = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

Schritt 3: Helferfunktionen pro Modell

Baue eine einheitliche Funktion, die je nach Name an das richtige Modell routet. Das hält den Code sauber und macht spätere Erweiterungen einfach.

Beginne mit dem Aufruf von Kimi K2:

def call_model(model_name: str, messages: List[Dict], **kwargs) -> Dict:
   """Call any model with unified interface."""
   try:
       start_time = time.time()

       if model_name == "Kimi K2 Thinking":
           enable_thinking = kwargs.get("enable_thinking", True)

           completion = KIMI_CLIENT.chat.completions.create(
               model="moonshotai/kimi-k2-thinking",
               messages=messages,
               temperature=1.0,
               extra_body={"include_reasoning": True}
           )

           message = completion.choices[0].message
           content = message.content

           # Extract reasoning from the dedicated field
           reasoning_content = None
           if enable_thinking and hasattr(message, 'reasoning') and message.reasoning:
               reasoning_content = message.reasoning

           return {
               "content": content,
               "reasoning_content": reasoning_content,
               "response_time": time.time() - start_time,
               "tokens_used": {
                   "input": completion.usage.prompt_tokens,
                   "output": completion.usage.completion_tokens,
                   "total": completion.usage.total_tokens
               },
               "error": None
           }

GPT-5 nutzt einen anderen Ansatz mit Responses-Endpoint und konfigurierbarem Reasoning-Effort:

      elif model_name == "GPT-5":
           reasoning_effort = kwargs.get("reasoning_effort", "medium")
           input_messages = [
               {"role": m["role"], "content": m["content"]}
               for m in messages
           ]

           response = GPT_CLIENT.responses.create(
               model="gpt-5",
               input=input_messages,
               reasoning={
                   "effort": reasoning_effort,
                   "summary": "auto"
               }
           )

           # Parse response structure
           reasoning_text = None
           content_text = ""

           for item in response.output:
               if item.type == "reasoning" and hasattr(item, "summary"):
                   summaries = [s.text for s in item.summary if hasattr(s, "text")]
                   reasoning_text = "\n\n".join(summaries) if summaries else None
               elif item.type == "message" and hasattr(item, "content"):
                   content_text += "".join(c.text for c in item.content if hasattr(c, "text"))

           return {
               "content": content_text,
               "reasoning_content": reasoning_text,
               "response_time": time.time() - start_time,
               "tokens_used": {
                   "input": getattr(response.usage, "input_tokens", 0),
                   "output": getattr(response.usage, "output_tokens", 0),
                   "total": getattr(response.usage, "total_tokens", 0)
               },
               "error": None
           }

GPT-5 bietet vier Reasoning-Stufen: minimal, low, medium, high. Die Antwortstruktur trennt Reasoning in Summary-Blöcke und Inhalte in Message-Blöcke – du parsest beides separat und gibst ein einheitliches Dictionary wie bei Kimi K2 zurück.

Claude Sonnet 4.5 setzt auf erweitertes Thinking mit Token-Budget:

    else:  # Claude Sonnet 4.5
           enable_thinking = kwargs.get("enable_thinking", True)
           params = {
               "model": "claude-sonnet-4-5",
               "max_tokens": 10000,
               "messages": messages
           }
           if enable_thinking:
               params["thinking"] = {
                   "type": "enabled",
                   "budget_tokens": 5000
               }

           message = CLAUDE_CLIENT.messages.create(**params)

           # Extract content and thinking blocks
           content_text = ""
           thinking_text = None

           for block in message.content:
               if block.type == "thinking":
                   thinking_text = block.thinking
               elif block.type == "text":
                   content_text += block.text

           return {
               "content": content_text,
               "reasoning_content": thinking_text,
               "response_time": time.time() - start_time,
               "tokens_used": {
                   "input": message.usage.input_tokens,
                   "output": message.usage.output_tokens,
                   "total": message.usage.input_tokens + message.usage.output_tokens
               },
               "error": None
           }

   except Exception as e:
       return {
           "content": None,
           "reasoning_content": None,
           "response_time": 0,
           "tokens_used": {"input": 0, "output": 0, "total": 0},
           "error": f"{model_name} Error: {str(e)}"
       }

Claude reserviert ein Token-Budget für internes Reasoning, bevor die finale Antwort generiert wird. Die Antwort enthält mehrere Content-Blöcke, die du durchläufst und Thinking- von Text-Blöcken trennst. Das Error-Handling liefert stets die gleiche Dictionary-Struktur mit Fehlermeldung – so bricht die Oberfläche bei API-Fehlern nicht.

Schritt 4: Streamlit-Interface bauen

Mit der API-Schicht fertig, baust du das Web-Interface. Konfiguriere zuerst die Streamlit-Seite:

def main():
   st.set_page_config(
       page_title="Multi-Model Comparison Chat",
       page_icon="🤖",
       layout="wide",
       initial_sidebar_state="expanded"
   )

   st.session_state.setdefault("messages", [])
   st.session_state.setdefault("model_responses", [])

Das Wide-Layout schafft Platz für drei Spalten. Die Session State hält Chat-Verlauf und Modellantworten trotz Streamlit-Reruns vor.

Füge Titel und Sidebar-Controls hinzu:

st.title("🤖 Multi-Model Comparison Chat")
   st.markdown("""
   Compare **Kimi K2 Thinking**, **GPT-5**, and **Claude Sonnet 4.5** side-by-side.
   All three models support reasoning modes - see how they approach problems differently.
   """)

   with st.sidebar:
       st.header("⚙️ Settings")

       st.subheader("Thinking Mode")
       kimi_thinking = st.checkbox("Enable Kimi K2 Thinking", value=True)
       gpt5_reasoning = st.selectbox(
           "GPT-5 Reasoning Effort",
           options=["minimal", "low", "medium", "high"],
           index=2
       )
       claude_thinking = st.checkbox("Enable Claude Thinking", value=True)

Die Sidebar gibt Kontrolle über die Thinking-Modi. Kimi K2 und Claude haben Schalter, GPT-5 bietet vier Stufen, da die API diese Granularität erlaubt.

Darunter ein API-Status, damit klar ist, welche Dienste verbunden sind:

st.subheader("API Status")
       st.markdown(f"""
       - Kimi K2: {"✅" if os.getenv("OPENROUTER_API_KEY") else "❌"}
       - GPT-5: {"✅" if os.getenv("OPENAI_API_KEY") else "❌"}
       - Claude: {"✅" if os.getenv("ANTHROPIC_API_KEY") else "❌"}
       """)

Die Häkchen erscheinen, wenn die Environment-Variablen gesetzt sind. Ein rotes X bedeutet: Key in der .env ergänzen.

Schritt 5: Vergleichslogik implementieren

Jetzt zum Kern. Wenn Nutzer eine Nachricht senden, rufst du alle drei Modelle parallel auf und zeigst die Ergebnisse nebeneinander an.

def call_models_parallel(messages: List[Dict], selected_models: List[str],
                       kimi_thinking: bool, gpt5_reasoning: str,
                       claude_thinking: bool) -> Dict[str, Dict]:
   """Call multiple models in parallel."""
   model_kwargs = {
       "Kimi K2 Thinking": {"enable_thinking": kimi_thinking},
       "GPT-5": {"reasoning_effort": gpt5_reasoning},
       "Claude Sonnet 4.5": {"enable_thinking": claude_thinking}
   }

   with ThreadPoolExecutor(max_workers=3) as executor:
       futures = {
           executor.submit(call_model, m, messages, **model_kwargs[m]): m
           for m in selected_models if m in model_kwargs
       }
       return {futures[f]: f.result() for f in as_completed(futures)}

Diese Funktion stößt drei API-Calls gleichzeitig an und sammelt die Ergebnisse bei Abschluss. Sequenziell würde das 15–30 Sekunden dauern, parallel 5–10 Sekunden – du wartest nur auf das langsamste Modell statt auf die Summe.

Integriere die Parallelisierung in die Chat-Oberfläche:

   if prompt := st.chat_input("Ask a question to all models..."):
       st.session_state.messages.append({"role": "user", "content": prompt})

       with st.chat_message("user"):
           st.markdown(prompt)

       api_messages = [
           {"role": m["role"], "content": m["content"]}
           for m in st.session_state.messages
       ]

       with st.spinner("🤔 Models are thinking..."):
           responses = call_models_parallel(
               api_messages,
               ["Kimi K2 Thinking", "GPT-5", "Claude Sonnet 4.5"],
               kimi_thinking,
               gpt5_reasoning,
               claude_thinking
           )

       cols = st.columns(3)
       for idx, (model_name, response_data) in enumerate(responses.items()):
           with cols[idx]:
               st.markdown(f"### {model_name}")
               if response_data["reasoning_content"]:
                   with st.expander("🧠 Thinking Process", expanded=False):
                       st.markdown(response_data["reasoning_content"])
               st.markdown(response_data["content"])

So entstehen drei Spalten mit je einer Modellantwort. Der Thinking-Prozess ist zunächst eingeklappt – Nutzer sehen erst die finalen Antworten und können das Reasoning bei Bedarf ausklappen.

Schritt 6: Testen und verfeinern

Starte die App mit:

streamlit run model_comparison_chat.py

Beginne mit einem einfachen Test:

What is 2+2?

Alle drei Modelle sollten binnen Sekunden antworten. Das bestätigt die API-Verbindungen und die parallele Ausführung. Die App läuft lokal – du bestimmst also, wann Kosten anfallen. Pro Abfrage zahlst du ca. $0,01–0,05 für den Drei-Modell-Vergleich (je nach Länge).

Die App mit komplexen Prompts testen

Du hast die Vergleichs-App gebaut und mit einfachen Fragen getestet. Die wahren Unterschiede zeigen sich jedoch, wenn du die Modelle forderst. Dafür habe ich alle drei Modelle mit komplexen Prompts getestet. Du kannst die gleichen Tests in deiner App laufen lassen. Hier sind die wichtigsten Erkenntnisse.

Die Testprompts

Wir haben drei Herausforderungen gewählt, die unterschiedliche Reasoning-Fähigkeiten prüfen.

Test 1: Fortgeschrittenes mathematisches Reasoning

Ein rechteckiger Garten ist 24 Fuß lang und 18 Fuß breit. Ein 2 Fuß breiter Weg verläuft um den äußeren Rand des Gartens. Sarah pflanzt Blumen mit einer Dichte von 4 Blumen pro Quadratfuß. Danach ersetzt sie auf 30 % der bepflanzten Fläche die Blumen durch Ziersteine. Wie viele Blumen bleiben? Und wie groß ist die Fläche des Wegs (in Quadratfuß)?

Test 2: Mehrstufiges logisches Reasoning

Vier Freunde – Alice, Bob, Carol und David – sollen sich für ein Foto in einer Reihe aufstellen. Folgende Regeln gelten:

1. Alice muss neben Bob stehen

2. Carol darf nicht an einem Ende stehen

3. David muss links von Alice stehen

Liste alle gültigen Anordnungen von links nach rechts auf.

Test 3: Codegenerierung mit Constraints

Schreibe eine Python-Funktion, die prüft, ob ein String eine gültige IPv4-Adresse ist, mit folgenden Anforderungen:

1. Format validieren (vier Oktette, durch Punkte getrennt)

2. Jedes Oktett muss 0–255 sein (keine führenden Nullen außer „0“ selbst)

3. Ungültige Formate abweisen (leere Strings, zu viele/zu wenige Oktette, nichtnumerische Zeichen)

4. Zeitkomplexität O(n), wobei n die String-Länge ist

5. Vollständige Docstring mit Beispielen

6. Type Hints für alle Parameter und Rückgabewerte

7. Edge Cases behandeln (leer, None, Sonderzeichen)

Erkläre außerdem deinen Validierungsansatz und warum er O(n) ist.

Ergebnisse

Alle drei Modelle haben jede Aufgabe korrekt gelöst – aber auf sehr unterschiedlichen Wegen. Hier die Performance-Zusammenfassung:

Test

Modell

Zeit (Sek.)

Tokens

Ergebnis

Gartenproblem

Kimi K2

28,5

3.420

✓ Korrekt (1.209,6 Blumen, 184 sq ft)

 

GPT-5

44,6

1.476

✓ Korrekt (1.209,6 Blumen, 184 sq ft)

 

Claude

19,7

1.386

✓ Korrekt (1.210 Blumen, 184 sq ft)

Foto-Anordnung

Kimi K2

50,5

6.249

✓ Alle 2 gültigen Anordnungen gefunden

 

GPT-5

39,4

1.914

✓ Alle 2 gültigen Anordnungen gefunden

 

Claude

31,3

2.310

✓ Alle 2 gültigen Anordnungen gefunden

IPv4-Validator

Kimi K2

192,6

5.245

✓ Funktionierende O(n)-Lösung

 

GPT-5

73,7

4.233

✓ Funktionierende O(n)-Lösung

 

Claude

43,1

3.330

✓ Funktionierende O(n)-Lösung

Was macht jedes Modell in dieser Zeit konkret?

Kimi K2s Ansatz

Es exploriert und hinterfragt sich ständig. Beim Gartenproblem visualisierte es den Aufbau, rechnete durch und hielt inne: „Moment, lass mich das kurz prüfen …“, bevor es fortfuhr. Bei der Foto-Aufgabe testete es jede Bedingung einzeln und zeigte jeden Schritt.

Der IPv4-Validator dauerte über 3 Minuten, weil Edge Cases einzeln betrachtet, der O(n)-Beweis durchlaufen und die Logik mehrfach verifiziert wurde. Du beobachtest gewissermaßen Denken laut Protokoll – inklusive Selbstkontrolle und Verifikation.

GPT-5s Ansatz

Methodisch und geordnet. Das Gartenproblem wurde klar strukturiert, Schritte nummeriert und der Reihe nach abgearbeitet. Die Foto-Anordnung erhielt einen strukturierten Walkthrough: Position für Position mit Regelprüfung.

Der Code kam mit klaren Erklärungen und guter Dokumentation. Es zweifelt seltener an sich als K2 und agiert weniger hastig als Claude. Du bekommst eine ausgewogene Darstellung des Denkens – ohne Übermaß.

Claudes Ansatz

Schnell. Es identifiziert den Lösungsweg flott und setzt sauber um. Beim Foto-Problem strukturierte es nach Fällen und arbeitete sie ohne Umschweife durch. Der IPv4-Code war sauber und gut dokumentiert – aber zügig auf den Punkt.

Claude zeigt sein Denken, verweilt aber nicht bei Verifikationsschritten. Geschwindigkeit entsteht durch Vertrauen in den Ansatz und minimales Zurückspringen.

Diese Ansätze erzeugen klare Trade-offs. Wähle K2, wenn du detailliertes Reasoning für Lernen, Debugging oder Audits brauchst. Wähle Claude, wenn Tempo zählt und du den Ergebnissen ohne Einsicht in Reasoning-Ketten vertraust. Wähle GPT-5, wenn du die Balance zwischen K2s Ausführlichkeit und Claudes Tempo möchtest.

Hinweis: Nimm die Ergebnisse mit Vorsicht – ein einzelner Test kann nicht alle Fähigkeiten der drei Modelle umfassend abbilden.

Fazit

Du hast Kimi K2 Thinking über OpenRouter eingerichtet, seine Reasoning-Fähigkeiten erkundet, Tool-Workflows gebaut und eine Vergleichs-App erstellt, um es gegen GPT-5 und Claude zu testen. K2s Stärken sind eigenständige Tool-Orchestrierung und transparentes Reasoning – ideal für komplexe Workflows, in denen du die Entscheidungen des Modells nachvollziehen willst.

K2s Kapazität und Preis machen das praktikabel. Es führt lange Sequenzen von Toolaufrufen aus – während die meisten Wettbewerber nur ein paar Dutzend schaffen – und das Feld reasoning_content legt jeden Denkschritt offen. Bei etwa einem Viertel der GPT-5-Kosten und einem Sechstel der Claude-Kosten für Output-Tokens kannst du umfangreich experimentieren, ohne das Budget zu sprengen.

Die von dir gebaute Vergleichs-App liefert dir harte Evidenz für diese Trade-offs. Teste sie mit deinen eigenen Problemen und Workflows, um ein Gefühl dafür zu entwickeln, ob K2s detailliertes Reasoning die längeren Antwortzeiten rechtfertigt. Praxistests in deinen Use Cases zeigen Muster, die generische Benchmarks nicht erfassen.

Wenn du tiefer einsteigen willst, sieh dir DataCamps OpenRouter-Tutorial zum Management mehrerer LLM-Provider an, den GPT-5-Guide zu Reasoning-Stufen und den Claude Sonnet 4-Guide für den erweiterten Thinking Mode.

Bexruz (Bex) Tuychiev

Autor

Bexruz (Bex) Tuychiev

Ich bin Content-Creator im Bereich Data Science mit über zwei Jahren Erfahrung und zähle zu den größten Stimmen auf Medium. Ich schreibe gern ausführliche Artikel über KI und ML – mit einer Prise Sarkasmus, damit das Ganze nicht zu trocken wird. Bisher habe ich über 130 Artikel veröffentlicht und einen DataCamp-Kurs produziert, ein weiterer ist in Arbeit. Meine Inhalte wurden von über 5 Millionen Menschen gelesen, 20.000 davon folgen mir auf Medium und LinkedIn. 

Themen

Ähnlich