# Chat Completions (/api/chat-completions) ```http POST https://api.promodelhub.de/v1/chat/completions ``` Erzeugt die Antwort des Modells auf einen Gesprächsverlauf. Derselbe Endpunkt deckt [Streaming](/funktionen/streaming), [Reasoning](/funktionen/reasoning), [Tool-Calling](/funktionen/tool-calling), [strukturierte Ausgaben](/funktionen/strukturierte-ausgaben) und [Bildeingabe](/funktionen/bildeingabe) ab. ## Beispiel [#beispiel] ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gemma-4-31b", "messages": [ {"role": "system", "content": "Antworte kurz und auf Deutsch."}, {"role": "user", "content": "Was ist der Unterschied zwischen RAM und Festplatte?"} ], "temperature": 0.3, "max_tokens": 300 }' ``` ## Parameter [#parameter] | Parameter | Typ | Beschreibung | | --------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------ | | `model` | string, **Pflicht** | API-ID des Modells, siehe [Modelle](/modelle) | | `messages` | array, **Pflicht** | Gesprächsverlauf, siehe unten | | `max_tokens` | integer | maximale Länge der Antwort in Token (inklusive Reasoning). `max_completion_tokens` wird ebenfalls akzeptiert | | `temperature` | number | Zufälligkeit, 0 bis 2. Niedrig (0–0,3) für Fakten und Extraktion, höher für kreative Texte | | `top_p` | number | Nucleus Sampling, Alternative zu `temperature` | | `stop` | string oder array | Die Ausgabe endet vor dieser Zeichenfolge | | `n` | integer | Anzahl alternativer Antworten (jede wird als Output berechnet) | | `seed` | integer | Startwert für den Zufall, macht Antworten besser reproduzierbar (nicht garantiert) | | `presence_penalty`, `frequency_penalty` | number | verringern Wiederholungen, -2 bis 2 | | `logprobs`, `top_logprobs` | boolean, integer | Wahrscheinlichkeiten der erzeugten Token zurückgeben | | `stream` | boolean | Antwort als Server-Sent Events, siehe [Streaming](/funktionen/streaming) | | `stream_options` | object | `{"include_usage": true}` liefert beim Streaming die Token-Zahlen mit | | `tools`, `tool_choice` | array, string/object | [Tool-Calling](/funktionen/tool-calling) | | `response_format` | object | JSON-Ausgabe, optional nach Schema, siehe [Strukturierte Ausgaben](/funktionen/strukturierte-ausgaben) | | `reasoning_effort` | string | Denkmodus steuern, siehe [Reasoning](/funktionen/reasoning) | | `chat_template_kwargs` | object | modellspezifische Optionen, z. B. `{"enable_thinking": true}` ([Reasoning](/funktionen/reasoning)) | ## Nachrichten [#nachrichten] Jede Nachricht hat eine `role` und einen `content`: | Rolle | Zweck | | ----------- | ---------------------------------------------------------------- | | `system` | Anweisungen an das Modell (Rolle, Stil, Regeln). Steht am Anfang | | `user` | Eingaben des Nutzers | | `assistant` | frühere Antworten des Modells, inklusive `tool_calls` | | `tool` | Ergebnis eines Tool-Aufrufs, mit `tool_call_id` | Die API speichert keinen Gesprächszustand. Für einen Chat schickst du bei jedem Request den kompletten bisherigen Verlauf mit – und er zählt jedes Mal als Input ([Abrechnung](/grundlagen/abrechnung)). `content` ist ein String oder – für [Bilder](/funktionen/bildeingabe) – ein Array aus Teilen: ```json { "role": "user", "content": [ {"type": "text", "text": "Was steht auf dem Schild?"}, {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AAQ..."}} ] } ``` ## Antwort [#antwort] ```json { "id": "chatcmpl-a76caf6b4319df57", "object": "chat.completion", "created": 1790777031, "model": "gemma-4-31b", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "RAM ist der schnelle Arbeitsspeicher ...", "reasoning_content": null, "tool_calls": null }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 41, "completion_tokens": 120, "total_tokens": 161, "completion_tokens_details": { "reasoning_tokens": 0 } } } ``` | Feld | Bedeutung | | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `choices[].message.content` | die Antwort. Kann `null` sein, wenn das Modell nur Tools aufruft oder `max_tokens` schon beim Reasoning erreicht war | | `choices[].message.reasoning_content` | Gedankengang bei eingeschaltetem [Reasoning](/funktionen/reasoning), sonst nicht vorhanden | | `choices[].message.tool_calls` | angeforderte [Tool-Aufrufe](/funktionen/tool-calling) | | `choices[].finish_reason` | `stop` (fertig), `length` (`max_tokens` oder Kontextfenster erreicht), `tool_calls` (Modell wartet auf Tool-Ergebnisse) | | `usage` | abgerechnete Token, siehe [Abrechnung](/grundlagen/abrechnung) | Die Antwort kann weitere Felder enthalten (z. B. `provider_specific_fields`). Ignoriere unbekannte Felder – wir ergänzen gelegentlich neue. # Embeddings (/api/embeddings) ```http POST https://api.promodelhub.de/v1/embeddings ``` Ein Embedding ist ein Zahlenvektor, der die Bedeutung eines Textes abbildet: Texte mit ähnlicher Bedeutung haben ähnliche Vektoren. Damit baust du semantische Suche, RAG (Retrieval Augmented Generation), Duplikaterkennung oder Klassifikation über Ähnlichkeit. Welche Embedding-Modelle es gibt, steht unter [Modelle](/modelle). ## Beispiel [#beispiel] ```python import os from openai import OpenAI client = OpenAI(base_url="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"]) result = client.embeddings.create( model="qwen3-vl-embedding-2b", input=["Wie kündige ich meinen Vertrag?", "Die Kündigung ist jederzeit zum Monatsende möglich."], dimensions=1024, ) vectors = [item.embedding for item in result.data] print(len(vectors), len(vectors[0])) # 2 1024 ``` ## Parameter [#parameter] | Parameter | Typ | Beschreibung | | ----------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `model` | string, **Pflicht** | API-ID des Embedding-Modells | | `input` | string oder array, **Pflicht** | ein Text oder eine Liste von Texten, höchstens 8.192 Token pro Text | | `dimensions` | integer | Länge des Vektors (bei `qwen3-vl-embedding-2b` 64 bis 2048, Standard 2048). Kürzere Vektoren sparen Speicher im Vektorindex bei etwas geringerer Genauigkeit | | `encoding_format` | string | `float` (Standard) oder `base64` | | `instruction` | string | **Erweiterung:** Aufgabenbeschreibung für das Modell, siehe unten | Mehrere Texte in einem Request sind schneller als einzelne Requests. Die Reihenfolge in `data` entspricht der in `input`. ## Antwort [#antwort] ```json { "object": "list", "model": "qwen3-vl-embedding-2b", "data": [ { "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456, ...] }, { "object": "embedding", "index": 1, "embedding": [0.0789, 0.0012, ...] } ], "usage": { "prompt_tokens": 42, "total_tokens": 42 } } ``` Berechnet werden nur Input-Token. ## Instruction: Fragen und Dokumente [#instruction-fragen-und-dokumente] Das Modell erzeugt bessere Suchergebnisse, wenn es weiß, wofür ein Text steht. Mit dem Feld `instruction` gibst du eine kurze Aufgabenbeschreibung auf Englisch mit. Ohne Feld gilt `Represent the user's input.` – das ist gut für Dokumente und allgemeine Ähnlichkeit. Für Suchanfragen in einem RAG-System lohnt sich eine eigene Anweisung, während die Dokumente ohne `instruction` eingebettet werden: ```python # Dokumente einmalig einbetten (ohne instruction) docs = client.embeddings.create(model="qwen3-vl-embedding-2b", input=chunks) # Suchanfrage mit Aufgabenbeschreibung query = client.embeddings.create( model="qwen3-vl-embedding-2b", input="Wie kündige ich?", extra_body={"instruction": "Given a customer question, retrieve relevant help-center passages."}, ) ``` `instruction` ist kein Feld der OpenAI-API. Im Python-SDK übergibst du es mit `extra_body`, in Node.js direkt im Request-Objekt (bei TypeScript mit Typ-Cast). ## Ähnlichkeit berechnen [#ähnlichkeit-berechnen] Vergleiche Vektoren über die Kosinus-Ähnlichkeit (bei normierten Vektoren gleich dem Skalarprodukt). Wichtig: Alle Vektoren eines Index müssen mit demselben Modell und derselben `dimensions` erzeugt sein. ```python import math def cosine(a, b): dot = sum(x * y for x, y in zip(a, b)) return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b))) print(cosine(vectors[0], vectors[1])) ``` # Fehler (/api/fehler) ## Fehlerformat [#fehlerformat] Fehler kommen als JSON mit einem HTTP-Statuscode ungleich 2xx: ```json { "error": { "message": "key not allowed to access model. This key can only access models=['mistral-small-24b']. Tried to access gemma-4-31b", "type": "key_model_access_denied", "param": "model", "code": "403" } } ``` Werte `message` nur zur Anzeige und Fehlersuche aus – der Text kann sich ändern. Für die Programmlogik zählt der HTTP-Status. Die OpenAI-SDKs werfen passende Exceptions (z. B. `openai.RateLimitError` bei `429`). Einige Fehler (`403` für nicht unterstützte Pfade, `413`, `503` beim IP-Limit) kommen direkt von unserem Gateway und haben eine HTML-Seite statt JSON als Body. ## Statuscodes [#statuscodes] | Status | Bedeutung | Typische Ursache | Wiederholen? | | ------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | `400` | ungültiger Request | Kontextfenster überschritten, unbekanntes Modell, ungültiger Parameter, Bild als URL statt Data-URI | nein | | `401` | nicht authentifiziert | Key fehlt, falsch, widerrufen, abgelaufen oder wegen seines Credit-Limits bzw. des Nutzerlimits gesperrt | nein | | `403` | nicht erlaubt | Account hat kein aktives Paket (`no_package`); Key oder Nutzer darf dieses Modell nicht nutzen; nicht unterstützter Endpunkt | nein | | `413` | Request zu groß | Body größer als 20 MB, meist wegen großer Bilder | nein | | `429` | Paket verbraucht | Credits des Abrechnungszeitraums aufgebraucht (`insufficient_quota`) | nein, erst nach Upgrade oder im nächsten Zeitraum | | `429` | Rate-Limit | Requests pro Minute oder parallele Requests deines Pakets erreicht, gilt für den ganzen Account (`rate_limit_exceeded`) | ja, nach `retry-after` bzw. wenn laufende Requests fertig sind | | `500` | interner Fehler | unerwarteter Fehler | ja, mit Backoff | | `503` | vorübergehend nicht verfügbar | Modell wird gewechselt oder gewartet; zu viele Requests von deiner IP-Adresse | ja, mit Backoff | Wie du Retries einbaust, steht unter [Wartezeiten und Retries](/grundlagen/verfuegbarkeit#wann-du-einen-retry-brauchst). ## Paket verbraucht [#paket-verbraucht] Sind die Credits deines Pakets für den laufenden Abrechnungszeitraum aufgebraucht, antwortet die API mit `429` und diesem Body: ```json { "error": { "message": "The credits of your package for the current billing period are used up. Upgrade your package in the portal to continue right away: https://app.promodelhub.de", "type": "insufficient_quota", "param": null, "code": "insufficient_quota" } } ``` Das ist kein normales Rate-Limit: Ein Retry hilft nicht. Die Sperre gilt, bis der nächste Abrechnungszeitraum beginnt oder der Owner ein größeres Paket bucht – dann ist die API sofort wieder frei ([Abrechnung](/grundlagen/abrechnung#wenn-das-kontingent-aufgebraucht-ist)). Ein bereits laufender Request wird nicht abgebrochen. Die OpenAI-SDKs werfen für beide Fälle `RateLimitError`. Ein Rate-Limit wiederholen sie vorher automatisch (standardmäßig zweimal), `insufficient_quota` nicht: Die API schickt dabei `x-should-retry: false`, die Exception kommt sofort. Unterscheide die Fälle am Fehlercode: ```python import time import openai try: response = client.chat.completions.create( model="qwen3.8-27b", messages=[{"role": "user", "content": "Hallo!"}], ) except openai.RateLimitError as e: if e.code == "insufficient_quota": # Paket verbraucht: nicht wiederholen, Job anhalten und Bescheid geben raise # Rate-Limit: warten, dann erneut senden time.sleep(int(e.response.headers.get("retry-after", "5"))) ``` ```ts import OpenAI from "openai"; try { const response = await client.chat.completions.create({ model: "qwen3.8-27b", messages: [{ role: "user", content: "Hallo!" }], }); } catch (err) { if (err instanceof OpenAI.RateLimitError && err.code === "insufficient_quota") { // Paket verbraucht: nicht wiederholen, Job anhalten und Bescheid geben } throw err; } ``` Den Fehlercode findest du auch im Body unter `error.code` (in Python `e.body["code"]`). ## Häufige Fehler [#häufige-fehler] **`401` nach einiger Zeit, vorher lief alles:** Der Key hat sein Credit-Limit oder das Limit des Nutzers für den laufenden Abrechnungszeitraum erreicht, ist abgelaufen oder wurde widerrufen bzw. der Nutzer gesperrt. Den Status jedes Keys siehst du im Portal unter **API-Keys**. **`403` mit `no_package`:** Dein Account hat kein aktives Paket – entweder wurde noch keins aktiviert oder es ist nach einer Kündigung abgelaufen. Der Owner aktiviert oder bestellt ein Paket im [Portal](https://app.promodelhub.de), danach funktionieren die Keys sofort ([Abrechnung](/grundlagen/abrechnung#testphase)). **`429` mit `insufficient_quota`:** Die Credits deines Pakets sind verbraucht, siehe [Paket verbraucht](#paket-verbraucht). **`429` mit `rate_limit_exceeded`:** Dein Account hat das Limit für Requests pro Minute oder für parallele Requests seines Pakets erreicht. Die Limits gelten für alle Keys zusammen. Warte die Zeit aus `retry-after` ab bzw. bis laufende Requests fertig sind, begrenze die Parallelität in deiner Anwendung oder buche ein größeres Paket ([Limits](/grundlagen/limits#paketlimits)). **`403` mit `key_model_access_denied`:** Die Meldung nennt die Modelle, die der Key nutzen darf. Prüfe die API-ID auf Tippfehler und die Modellbeschränkung von Key und Nutzer. **`400` mit `ContextWindowExceededError`:** Eingabe plus `max_tokens` sind größer als das Kontextfenster des Modells. Kürze den Verlauf oder setze `max_tokens` kleiner ([Limits](/grundlagen/limits#kontextfenster)). **Leere Antwort mit `finish_reason: "length"`:** `max_tokens` war schon aufgebraucht, bevor die eigentliche Antwort begann – meist wegen eingeschaltetem [Reasoning](/funktionen/reasoning). Erhöhe `max_tokens`. # API-Überblick (/api) Die API folgt der [OpenAI-API](https://platform.openai.com/docs/api-reference). Die offiziellen OpenAI-SDKs und alle Tools, die einen „OpenAI-kompatiblen“ Endpunkt unterstützen, funktionieren ohne Anpassung. ## Basis-URL [#basis-url] ```text https://api.promodelhub.de/v1 ``` ## Authentifizierung [#authentifizierung] Jeder Request braucht einen [API-Key](/grundlagen/konto-und-keys) im Header `Authorization`: ```http Authorization: Bearer sk-... Content-Type: application/json ``` ## Endpunkte [#endpunkte] | Methode | Pfad | Zweck | | ------- | ----------------------------------------------- | ----------------------------------------------------------- | | `POST` | [`/v1/chat/completions`](/api/chat-completions) | Chat, Textgenerierung, Tool-Calling, Bildeingabe, Reasoning | | `POST` | [`/v1/embeddings`](/api/embeddings) | Vektoren für semantische Suche und RAG | | `GET` | [`/v1/models`](/api/modelle) | Modelle, die dein Key nutzen darf | | `POST` | `/v1/completions` | klassische Text-Completions ohne Chat-Format (Legacy) | Jeder Pfad funktioniert auch ohne `/v1`, z. B. `/chat/completions`. ## Nicht unterstützt [#nicht-unterstützt] Folgende Teile der OpenAI-API gibt es bei uns (noch) nicht: Responses API (`/v1/responses`), Assistants, Files, Batch, Fine-Tuning, Moderation, Bild- und Audioerzeugung, Spracherkennung. Anfragen daran beantwortet die API mit `403`. Bilder als Eingabe gehen nur als Base64-Data-URI, nicht als Link ([Bildeingabe](/funktionen/bildeingabe)). ## Text-Completions (Legacy) [#text-completions-legacy] `POST /v1/completions` setzt einen Text fort, ohne Chat-Vorlage des Modells: ```bash curl https://api.promodelhub.de/v1/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "mistral-small-24b", "prompt": "Die Hauptstadt von Frankreich ist", "max_tokens": 10}' ``` Für neue Anwendungen empfehlen wir Chat Completions: Die Modelle sind auf das Chat-Format trainiert und liefern damit deutlich bessere Ergebnisse. # Modelle abfragen (/api/modelle) ```http GET https://api.promodelhub.de/v1/models ``` Liefert die Modelle, die **dein API-Key** aufrufen darf. Ist der Key oder sein Nutzer auf bestimmte Modelle beschränkt ([Konto und API-Keys](/grundlagen/konto-und-keys)), enthält die Liste nur diese. ```bash curl https://api.promodelhub.de/v1/models \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" ``` ```json { "object": "list", "data": [ { "id": "mistral-small-24b", "object": "model", "created": 1677610602, "owned_by": "openai" }, { "id": "gemma-4-31b", "object": "model", "created": 1677610602, "owned_by": "openai" } ] } ``` `id` ist die API-ID, die du als `model` verwendest. Die Felder `created` und `owned_by` haben keine Bedeutung. Beschreibungen, Credit-Faktoren und Fähigkeiten der Modelle stehen unter [Modelle](/modelle). # Changelog (/changelog) ## 05.10.2026 [#05102026] * **Neu:** Credit-Pakete ersetzen Grundgebühr und Abrechnung nach Verbrauch. Du buchst ein Monatspaket (Starter, Pro, Business oder Business Plus) mit festem Kontingent an Credits, siehe [Abrechnung](/grundlagen/abrechnung). * Jedes Modell hat einen Credit-Faktor (Credits pro Token) statt Euro-Preisen für Input und Output. Die Faktoren stehen in der [Modellübersicht](/modelle). * Das Starter-Paket ist 30 Tage kostenlos testbar. * Der Abrechnungszeitraum beginnt mit der Bestellung statt mit dem Kalendermonat. * Requests pro Minute und parallele Requests richten sich nach dem Paket und gelten für den ganzen Account statt 60 Requests pro Minute pro Key ([Limits](/grundlagen/limits)). * Ist das Paket verbraucht, antwortet die API mit `429` und `insufficient_quota`, ohne Paket mit `403` und `no_package` ([Fehler](/api/fehler)). * Limits pro Key und Nutzer werden in Credits pro Abrechnungszeitraum statt in Euro pro Monat festgelegt. ## 30.09.2026 [#30092026] * Diese Dokumentation ist online: Anleitungen, API-Referenz und eine eigene Seite pro Modell. * Reasoning, Tool-Calling und Bildeingabe sind pro Modell dokumentiert. ## 28.09.2026 [#28092026] * **Neu:** Gemma 4 31B (`gemma-4-31b`) als großes Allround-Modell, mit Bildeingabe und optionalem Reasoning. Ersetzt Llama 3.3 70B. * **Neu:** Qwen3-Coder-Next (`qwen3-coder-next`) für Programmierung und Coding-Agenten. * **Neu:** Qwen3.8 27B (`qwen3.8-27b`) mit Reasoning. * **Neu:** Embedding-Modell Qwen3-VL-Embedding 2B (`qwen3-vl-embedding-2b`) für semantische Suche und RAG. * **Entfernt:** Llama 3.3 70B. * Tool-Calling funktioniert bei allen Chat-Modellen. ## 26.09.2026 [#26092026] * Mehrere API-Keys pro Nutzer, mit Modellbeschränkung, Monatslimit und Ablaufdatum. * Kontextfenster auf 32.768 Token erhöht. ## 25.09.2026 [#25092026] * Beta-Start mit Llama 3.3 70B und Mistral Small 24B (`mistral-small-24b`). * Preise pro Modell statt Preisstufen. # Bildeingabe (/funktionen/bildeingabe) Modelle mit Bildeingabe verstehen Bilder im Chat: Fotos beschreiben, Text aus Screenshots und Dokumenten auslesen, Diagramme erklären oder Produktbilder einordnen. Die Antwort ist immer Text – Bilder erzeugen können die Modelle nicht. Bildeingabe unterstützen: ## Bild senden [#bild-senden] Bilder schickst du als Teil einer `user`-Nachricht, **als Base64-Data-URI**: ```python import base64 with open("rechnung.jpg", "rb") as f: image = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="gemma-4-31b", messages=[{ "role": "user", "content": [ {"type": "text", "text": "Lies Rechnungsnummer, Datum und Gesamtbetrag aus."}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image}"}}, ], }], ) print(response.choices[0].message.content) ``` Links auf Bilder (`https://…`) lehnt die API mit `400` ab. Lade das Bild in deiner Anwendung und schicke es als Data-URI (`data:image/png;base64,…`). ## Limits [#limits] | | | | ------------------ | ---------------------------------------------------------------------------------- | | Bilder pro Request | höchstens 4 | | Formate | PNG, JPEG, WebP, GIF | | Größe des Requests | höchstens 20 MB inklusive Base64-Aufschlag von etwa 33 % | | Verbrauch | ein Bild entspricht je nach Modell einigen hundert Input-Token (Gemma 4: etwa 280) | ## Tipps [#tipps] * **Verkleinern spart Übertragungszeit:** Eine lange Kante von 1.000 bis 1.600 Pixeln reicht meist. Für kleine Schrift in Screenshots nicht zu stark verkleinern und PNG statt stark komprimiertem JPEG nutzen. * **Konkret fragen:** „Lies den Gesamtbetrag aus“ funktioniert besser als „Was siehst du?“. Kombiniere Bildeingabe mit [strukturierten Ausgaben](/funktionen/strukturierte-ausgaben), um Felder direkt als JSON zu bekommen. * **Mehrere Seiten:** Schicke bis zu vier Bilder in einer Nachricht, z. B. Vorder- und Rückseite eines Dokuments. * **Ausprobieren:** Im Test-Chat des Portals kannst du Bilder hochladen oder Screenshots einfügen. # Reasoning (/funktionen/reasoning) Einige Modelle können vor der Antwort „nachdenken“: Sie erzeugen zuerst einen Gedankengang und dann die eigentliche Antwort. Das verbessert die Ergebnisse bei Mathematik, Logik, Planung und kniffligen Analysen, kostet aber Zeit und Output-Token. Bei einfachen Aufgaben wie Zusammenfassungen, Übersetzungen oder Klassifikation lohnt es sich meist nicht. ## Welches Modell kann was [#welches-modell-kann-was] * **Optional (standardmäßig aus):** Ohne Parameter antwortet das Modell direkt. Reasoning schaltest du pro Request ein. * **Standardmäßig an:** Das Modell denkt immer nach, außer du schaltest es pro Request aus. * **Nicht verfügbar:** Das Modell hat keinen Denkmodus, auch `reasoning_effort` erzeugt keinen Gedankengang. Modellspezifische Details, z. B. welche Stufen von `reasoning_effort` ein Modell kennt, stehen auf der jeweiligen Modellseite unter **API-Hinweise**. ## Ein- und ausschalten [#ein--und-ausschalten] Es gibt zwei gleichwertige Wege: | Weg | Einschalten | Ausschalten | | ------------------------------------ | --------------------------------------------------- | ---------------------------- | | `reasoning_effort` (OpenAI-Standard) | `"low"`, `"medium"` (je nach Modell weitere Stufen) | `"none"` | | `chat_template_kwargs` | `{"enable_thinking": true}` | `{"enable_thinking": false}` | `reasoning_effort` funktioniert mit allen OpenAI-SDKs ohne Tricks und ist unsere Empfehlung. `chat_template_kwargs` ist kein Feld der OpenAI-API und muss im Python-SDK über `extra_body` übergeben werden. Modelle ohne Denkmodus lehnen es teilweise mit `400` ab. ```python response = client.chat.completions.create( model="gemma-4-31b", messages=[{"role": "user", "content": "Ein Zug fährt um 9:40 los, braucht 2 h 35 min und hat 17 min Verspätung. Wann kommt er an?"}], reasoning_effort="low", # Denkmodus an max_tokens=4000, # Platz für Gedankengang und Antwort ) message = response.choices[0].message print(message.reasoning_content) # Gedankengang print(message.content) # Antwort: 12:32 print(response.usage.completion_tokens_details.reasoning_tokens) # Alternative über chat_template_kwargs: response = client.chat.completions.create( model="qwen3.8-27b", messages=[{"role": "user", "content": "Übersetze ins Englische: Guten Morgen!"}], extra_body={"chat_template_kwargs": {"enable_thinking": False}}, # Denkmodus aus ) ``` ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3.8-27b", "messages": [{"role": "user", "content": "Übersetze ins Englische: Guten Morgen!"}], "reasoning_effort": "none" }' ``` ## Gedankengang auslesen [#gedankengang-auslesen] Der Gedankengang steht getrennt von der Antwort im Feld `reasoning_content` der Nachricht, beim [Streaming](/funktionen/streaming) in `delta.reasoning_content` (vor den `content`-Stücken). Die eigentliche Antwort in `content` enthält keinen Gedankengang. * Zeige den Gedankengang höchstens als aufklappbares Detail an. Er ist ein Arbeitsstand, keine geprüfte Aussage. * Schicke ihn im Gesprächsverlauf **nicht** zurück: Frühere `assistant`-Nachrichten brauchen nur `content`. * Beim Python-SDK ist `reasoning_content` kein offizielles Feld. Lies es mit `getattr(message, "reasoning_content", None)`, wenn du nicht sicher bist, dass Reasoning an war. ## Verbrauch und `max_tokens` [#verbrauch-und-max_tokens] Die Denk-Token zählen zu den `completion_tokens` und verbrauchen Credits wie jeder andere Output. Wie viele es waren, steht in `usage.completion_tokens_details.reasoning_tokens`. Der Gedankengang ist oft mehrere hundert bis einige tausend Token lang. `max_tokens` begrenzt Gedankengang und Antwort **zusammen**. Ist es zu klein, endet die Ausgabe schon während des Nachdenkens: `content` ist dann `null` und `finish_reason` ist `length`. Setze `max_tokens` bei eingeschaltetem Reasoning großzügig oder lass es weg. ## Kombination mit anderen Funktionen [#kombination-mit-anderen-funktionen] Reasoning funktioniert zusammen mit [Tool-Calling](/funktionen/tool-calling), [strukturierten Ausgaben](/funktionen/strukturierte-ausgaben) und Streaming. Bei strukturierten Ausgaben gilt das Schema nur für `content`, nicht für den Gedankengang. # Streaming (/funktionen/streaming) Mit `"stream": true` schickt die API die Antwort als [Server-Sent Events](https://developer.mozilla.org/de/docs/Web/API/Server-sent_events), während das Modell sie erzeugt. Nutzer sehen die ersten Wörter nach Sekundenbruchteilen statt erst nach der ganzen Antwort. Streaming kostet dasselbe wie ein normaler Request. ```python stream = client.chat.completions.create( model="mistral-small-24b", messages=[{"role": "user", "content": "Schreibe ein Haiku über Rechenzentren."}], stream=True, stream_options={"include_usage": True}, ) for chunk in stream: if chunk.choices and chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end="", flush=True) if chunk.usage: print("\n", chunk.usage) ``` ```ts const stream = await client.chat.completions.create({ model: "mistral-small-24b", messages: [{ role: "user", content: "Schreibe ein Haiku über Rechenzentren." }], stream: true, stream_options: { include_usage: true }, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); if (chunk.usage) console.log("\n", chunk.usage); } ``` ```bash curl -N https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "mistral-small-24b", "stream": true, "messages": [{"role": "user", "content": "Schreibe ein Haiku über Rechenzentren."}]}' ``` ## Format [#format] Jedes Event ist eine Zeile `data: {...}` mit einem `chat.completion.chunk`. Die neuen Teile stehen in `choices[0].delta`: | Feld in `delta` | Inhalt | | ------------------- | ------------------------------------------------------------------------------------------------------------- | | `role` | im ersten Chunk: `assistant` | | `content` | nächstes Stück der Antwort | | `reasoning_content` | nächstes Stück des Gedankengangs bei eingeschaltetem [Reasoning](/funktionen/reasoning) – kommt vor `content` | | `tool_calls` | Tool-Aufrufe, in Stücken (Argumente müssen zusammengesetzt werden) | Das Ende markiert `data: [DONE]`. Mit `"stream_options": {"include_usage": true}` kommt davor ein letzter Chunk mit leerem `choices` und den Token-Zahlen in `usage` – ohne diese Option liefert der Stream keine Token-Zahlen. ## Tipp [#tipp] Setze Proxys und Webserver zwischen deiner Anwendung und dem Browser so, dass sie Antworten nicht puffern (bei nginx z. B. `proxy_buffering off`). # Strukturierte Ausgaben (/funktionen/strukturierte-ausgaben) Mit `response_format` erzwingst du, dass die Antwort gültiges JSON ist. Das ist die Grundlage für Extraktion, Klassifikation und alles, was dein Code weiterverarbeitet. Alle aktuellen Chat-Modelle unterstützen beide Varianten. ## JSON nach Schema (empfohlen) [#json-nach-schema-empfohlen] Mit `json_schema` hält sich die Antwort an dein [JSON Schema](https://json-schema.org/) – Feldnamen, Typen und Pflichtfelder stimmen garantiert. ```python import json schema = { "type": "object", "properties": { "kategorie": {"type": "string", "enum": ["Rechnung", "Technik", "Vertrag", "Sonstiges"]}, "dringend": {"type": "boolean"}, "zusammenfassung": {"type": "string"}, }, "required": ["kategorie", "dringend", "zusammenfassung"], "additionalProperties": False, } response = client.chat.completions.create( model="mistral-small-24b", messages=[ {"role": "system", "content": "Ordne Support-Anfragen ein."}, {"role": "user", "content": "Seit heute früh ist unser Shop offline, bitte sofort melden!"}, ], response_format={"type": "json_schema", "json_schema": {"name": "ticket", "schema": schema, "strict": True}}, ) ticket = json.loads(response.choices[0].message.content) print(ticket["kategorie"], ticket["dringend"]) ``` Das Schema kannst du auch aus einer [Pydantic](https://docs.pydantic.dev/)-Klasse erzeugen: `Ticket.model_json_schema()`. ## Beliebiges JSON [#beliebiges-json] `{"type": "json_object"}` erzwingt gültiges JSON ohne festes Schema. Beschreibe die gewünschten Felder dann im Prompt – ohne Schema wählt das Modell Feldnamen teils selbst (z. B. `einwohnerzahl` statt `einwohner`). ```python response = client.chat.completions.create( model="gemma-4-31b", messages=[{"role": "user", "content": "Nenne die größte Stadt Bayerns als JSON mit den Feldern stadt und einwohner."}], response_format={"type": "json_object"}, ) ``` ## Tipps [#tipps] * Erwähne im Prompt, dass JSON erwartet wird, und beschreibe die Bedeutung der Felder – das Schema legt nur die Form fest, nicht den Inhalt. * Setze `max_tokens` großzügig genug. Wird die Ausgabe abgeschnitten (`finish_reason: "length"`), ist das JSON unvollständig. * Bei eingeschaltetem [Reasoning](/funktionen/reasoning) gilt das Schema für `content`, der Gedankengang steht wie immer in `reasoning_content`. # Tool-Calling (/funktionen/tool-calling) Beim Tool-Calling beschreibst du dem Modell Funktionen deiner Anwendung – z. B. „Wetter abfragen“ oder „Bestellung suchen“. Das Modell entscheidet, ob und mit welchen Argumenten es eine Funktion braucht, und antwortet dann mit einem strukturierten Aufruf statt mit Text. **Ausführen musst du die Funktion selbst**; das Ergebnis schickst du zurück, und das Modell formuliert daraus die Antwort. Tool-Calling unterstützen: ## Ablauf [#ablauf] ```python import json tools = [{ "type": "function", "function": { "name": "get_order_status", "description": "Liefert den Status einer Bestellung anhand der Bestellnummer.", "parameters": { "type": "object", "properties": {"order_id": {"type": "string", "description": "Bestellnummer, z. B. A-1042"}}, "required": ["order_id"], }, }, }] def get_order_status(order_id: str) -> dict: return {"order_id": order_id, "status": "versendet", "carrier": "DHL"} # deine Logik messages = [{"role": "user", "content": "Wo ist meine Bestellung A-1042?"}] response = client.chat.completions.create(model="mistral-small-24b", messages=messages, tools=tools) message = response.choices[0].message # 1. Das Modell fordert Tool-Aufrufe an (finish_reason == "tool_calls") while message.tool_calls: messages.append(message) # Aufruf in den Verlauf übernehmen for call in message.tool_calls: args = json.loads(call.function.arguments) result = get_order_status(**args) # 2. Ergebnis mit der passenden tool_call_id zurückgeben messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)}) # 3. Das Modell formuliert die Antwort (oder ruft weitere Tools auf) response = client.chat.completions.create(model="mistral-small-24b", messages=messages, tools=tools) message = response.choices[0].message print(message.content) ``` ## Parameter [#parameter] | Parameter | Beschreibung | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `tools` | Liste der Funktionen mit `name`, `description` und `parameters` (JSON Schema) | | `tool_choice` | `"auto"` (Standard): Modell entscheidet. `"none"`: keine Tools. `"required"`: mindestens ein Tool-Aufruf. `{"type": "function", "function": {"name": "..."}}`: genau diese Funktion | Das Modell kann mehrere Tools in einer Antwort aufrufen (z. B. das Wetter für zwei Städte). Führe dann alle aus und gib jedes Ergebnis als eigene `tool`-Nachricht zurück. `tool_choice: "required"` und das Erzwingen einer bestimmten Funktion setzen nicht alle Modelle um. Wo es nicht funktioniert, steht es auf der Modellseite unter **API-Hinweise**. Mit `"auto"` und einer klaren Beschreibung der Funktion rufen alle Modelle zuverlässig Tools auf. ## Tipps [#tipps] * **Beschreibungen sind der Prompt:** Das Modell entscheidet anhand von `description` der Funktion und der Parameter. Schreibe dort, wann die Funktion passt und in welchem Format die Werte sein müssen. * **Argumente prüfen:** `arguments` ist ein JSON-String, den das Modell erzeugt hat. Validiere ihn, bevor du damit etwas ausführst – besonders bei schreibenden Aktionen. * **Wenige Tools:** Jede Funktionsbeschreibung kostet bei jedem Request Input-Token. Gib nur die Tools mit, die im jeweiligen Schritt sinnvoll sind. * **Fehler zurückgeben:** Schlägt eine Funktion fehl, gib die Fehlermeldung als Ergebnis zurück. Das Modell kann dann nachfragen oder es anders versuchen. # Abrechnung (/grundlagen/abrechnung) Du buchst ein Monatspaket mit einem festen Kontingent an **Credits**. Jedes Modell verbraucht Credits mit einem eigenen **Credit-Faktor**: Kleine, effiziente Modelle verbrauchen weniger, größere mehr. Eine Abrechnung nach Verbrauch gibt es nicht. Alle Preise sind Nettopreise zzgl. USt. ## So funktionieren Credits [#so-funktionieren-credits] * **1 Credit = 1 Token bei Credit-Faktor 1×.** Der Faktor gibt an, wie viele Credits ein Token kostet (Credits pro Token). * Verbrauch pro Request: `(Input-Token + Output-Token) × Credit-Faktor` * Token sind das, was das Modell zählt. Die Zahlen stehen in jeder Antwort im Feld `usage`. **Beispiel:** Ein Request mit 2.000 Input- und 500 Output-Token an Qwen3.8 27B (Faktor 1,5×) verbraucht 2.500 × 1,5 = **3.750 Credits**. Den aktuellen Credit-Faktor jedes Modells findest du in der [Modellübersicht](/modelle) und auf der Seite des Modells. Ändert sich ein Faktor, gilt für jeden Request der Faktor zum Zeitpunkt des Requests. ## Pakete [#pakete] | | Starter | Pro | Business | Business Plus | | ------------------------ | ------------ | ------------- | -------------- | -------------- | | **Preis/Monat** | **7 €** | **35 €** | **129 €** | **249 €** | | Credits/Monat | 5 Mio. | 80 Mio. | 320 Mio. | 650 Mio. | | entspricht bei Faktor 1× | 5 Mio. Token | 80 Mio. Token | 320 Mio. Token | 650 Mio. Token | | Requests pro Minute | 30 | 60 | 150 | 150 | | parallele Requests | 5 | 10 | 20 | 20 | | Support per E-Mail | – | ✓ | ✓ | ✓ | Alle Pakete enthalten alle Modelle, Hosting in Deutschland und einen AVV. Ein Paket mit eigener GPU (Dedicated) gibt es auf Anfrage, sobald der zweite GPU-Server in Betrieb ist. Requests pro Minute und parallele Requests gelten für deinen ganzen Account, siehe [Limits](/grundlagen/limits). Das Angebot richtet sich an Geschäftskunden. ### Was ein Paket hergibt [#was-ein-paket-hergibt] Token, wenn alle Credits auf ein Modell gehen: | Paket | Qwen3-Coder-Next (1×) | Qwen3.8 27B / Gemma 4 31B (1,5×) | Mistral Small 24B (2×) | Qwen3-VL-Embedding 2B (0,25×) | | ------------- | --------------------- | -------------------------------- | ---------------------- | ----------------------------- | | Starter | 5 Mio. | 3,3 Mio. | 2,5 Mio. | 20 Mio. | | Pro | 80 Mio. | 53 Mio. | 40 Mio. | 320 Mio. | | Business | 320 Mio. | 213 Mio. | 160 Mio. | 1,28 Mrd. | | Business Plus | 650 Mio. | 433 Mio. | 325 Mio. | 2,6 Mrd. | Die Faktoren für Gemma 4 31B und Mistral Small 24B sind vorläufig. ## Was als Input und Output zählt [#was-als-input-und-output-zählt] | Token | Enthält | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Input** (`prompt_tokens`) | alle Nachrichten des Requests inklusive System-Prompt und bisherigem Gesprächsverlauf, Tool-Definitionen, Bilder | | **Output** (`completion_tokens`) | die Antwort des Modells inklusive Tool-Aufrufen und – falls eingeschaltet – des Gedankengangs beim [Reasoning](/funktionen/reasoning) | Input- und Output-Token werden mit demselben Credit-Faktor verrechnet. Die genauen Zahlen stehen in jeder Antwort im Feld `usage`: ```json "usage": { "prompt_tokens": 57, "completion_tokens": 253, "total_tokens": 310, "completion_tokens_details": { "reasoning_tokens": 245 } } ``` Bei einem Modell mit Faktor 1,5× verbraucht dieser Request 310 × 1,5 = 465 Credits. Hinweise: * **Gesprächsverlauf:** Die API ist zustandslos. Bei einem Chat schickst du den bisherigen Verlauf bei jedem Request erneut mit, er zählt also jedes Mal als Input. Lange Verläufe lohnen sich zu kürzen oder zusammenzufassen. * **Reasoning:** Die Denk-Token (`reasoning_tokens`) sind Teil der `completion_tokens` und zählen als Output. * **Bilder:** Ein Bild zählt je nach Modell als einige hundert Input-Token (bei Gemma 4 etwa 280). * **Embeddings:** Es fallen nur Input-Token an. * **Streaming:** verbraucht dasselbe wie ein normaler Request. Die Token-Zahlen bekommst du mit `stream_options.include_usage` ([Streaming](/funktionen/streaming)). ## Abrechnungszeitraum [#abrechnungszeitraum] Die Laufzeit ist monatlich und beginnt mit deiner Bestellung. Jeder Account hat damit seinen eigenen Monatsrhythmus, z. B. vom 12. eines Monats bis zum 12. des Folgemonats. Die Grenze ist jeweils Mitternacht deutscher Zeit. Gibt es den Tag in einem Monat nicht (z. B. den 31.), endet der Zeitraum am letzten Tag des Monats. Zu Beginn jedes Zeitraums wird dein Kontingent wieder voll aufgefüllt. Nicht verbrauchte Credits verfallen am Ende des Zeitraums. ## Testphase [#testphase] Das Starter-Paket kannst du **30 Tage kostenlos** testen, einmal pro Account. Du aktivierst es im Portal unter **Paket**. Die Aktivierung ist bereits die Bestellung: Kündigst du nicht vor Testende, läuft Starter danach für 7 €/Monat (netto) weiter. * Bestellst du gleich ein größeres Paket, ist die Testphase damit verbraucht. * Ein Upgrade während der Testphase beendet den Test. Das neue Paket wird sofort zum vollen Preis berechnet, mit vollem Kontingent. ## Paket wechseln und kündigen [#paket-wechseln-und-kündigen] Das Paket bestellt und ändert nur der Owner des Accounts, im Portal unter **Paket**. | Änderung | Wirkung | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Upgrade** | sofort. Die Preisdifferenz wird anteilig für die restlichen Tage des Zeitraums berechnet, der Tag des Upgrades zählt mit. Dein Kontingent steigt auf das des neuen Pakets, bereits verbrauchte Credits bleiben verbraucht. War die API wegen eines verbrauchten Pakets gesperrt, ist sie sofort wieder frei. | | **Downgrade** | zum Ende des laufenden Zeitraums. Bis dahin gilt das bisherige Paket. | | **Kündigung** | zum Ende des laufenden Zeitraums, in der Testphase zum Testende. | Downgrade und Kündigung kannst du bis zum Ende des Zeitraums zurücknehmen. Ein Upgrade hebt einen vorgemerkten Downgrade oder eine Kündigung auf. ## Wenn das Kontingent aufgebraucht ist [#wenn-das-kontingent-aufgebraucht-ist] * Bei **75 %** und **90 %** Verbrauch siehst du einen Hinweis im Portal. * Bei **100 %** nimmt die API keine neuen Requests mehr an. Sie antwortet mit `429` und dem Fehlercode `insufficient_quota` ([Fehler](/api/fehler#paket-verbraucht)). Das gilt, bis der nächste Zeitraum beginnt oder du ein größeres Paket buchst. * Ein Request, der schon angenommen wurde, läuft immer bis zum Ende, auch beim Streaming. Erst der nächste Request wird abgelehnt. * Der Verbrauch wird etwa einmal pro Minute ausgewertet. Bis der Stopp greift, können deshalb noch einzelne Requests über 100 % hinaus durchgehen. Sie zählen zum Verbrauch, kosten aber nichts extra. Es entstehen keine unerwarteten Zusatzkosten. ## Verbrauch einsehen [#verbrauch-einsehen] Im Portal unter **Kosten & Verbrauch** siehst du Token und Credits pro Modell für den laufenden und die vergangenen Zeiträume samt Abrechnungen, unter **API-Keys** den Verbrauch jedes Keys im laufenden Zeitraum. Neue Requests erscheinen dort nach etwa ein bis zwei Minuten. ## Verbrauch steuern [#verbrauch-steuern] Mit Limits pro Key und pro Nutzer (in Credits pro Abrechnungszeitraum) teilst du das Kontingent im Team auf ([Konto und API-Keys](/grundlagen/konto-und-keys#was-bei-einem-limit-passiert)). Weitere Stellschrauben: * `max_tokens` begrenzt die Länge der Antwort. * Ein Modell mit kleinerem Credit-Faktor für einfache Aufgaben wie Klassifikation oder Extraktion (siehe [Welches Modell passt?](/modelle#welches-modell-passt)). * Reasoning nur einschalten, wo es die Qualität wirklich verbessert. # Konto und API-Keys (/grundlagen/konto-und-keys) ## Account und Nutzer [#account-und-nutzer] Ein **Account** ist dein Kundenkonto: Er hat ein gemeinsames Paket und bekommt eine gemeinsame Rechnung. Im Account kann es mehrere **Nutzer** geben, jeder mit eigenem Login und eigenen API-Keys. ### Paket aktivieren [#paket-aktivieren] Bevor API-Keys funktionieren, braucht dein Account ein aktives Paket. Nach der Freischaltung deines Accounts aktiviert der Owner im Portal unter **Paket** das Starter-Paket für 30 Tage kostenlos oder bestellt gleich ein größeres Paket. Ohne aktives Paket antwortet die API mit `403` und dem Code `no_package` ([Fehler](/api/fehler)). Das Paket bestellt und ändert nur der **Owner**. Credits, Requests pro Minute und parallele Requests des Pakets teilen sich alle Nutzer und Keys des Accounts. Details zu Paketen, Testphase und Wechsel stehen unter [Abrechnung](/grundlagen/abrechnung). | Rolle | Darf | | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- | | Owner | alles, auch Nutzer anlegen und verwalten und das Paket bestellen, wechseln oder kündigen; wird bei der Registrierung automatisch angelegt | | Admin | Nutzer anlegen, bearbeiten, sperren und löschen; alle Keys im Account sehen und widerrufen | | Member | eigene API-Keys verwalten, Test-Chat und Verbrauch nutzen | Nutzer verwaltest du im Portal unter **Team**. Pro Nutzer lassen sich festlegen: * **Erlaubte Modelle** – der Nutzer und alle seine Keys können nur diese Modelle aufrufen. * **Credit-Limit** – Credits pro Abrechnungszeitraum, gilt für alle Keys des Nutzers zusammen. * **Sperren** – alle Keys des Nutzers werden sofort gesperrt; beim Entsperren funktionieren sie wieder. ## API-Keys [#api-keys] Jeder Nutzer kann bis zu 25 aktive API-Keys anlegen, z. B. einen pro Anwendung oder Umgebung. Einstellungen pro Key: | Einstellung | Wirkung | | ------------------ | ------------------------------------------------------------------------------------------------------------ | | Name | nur zur Unterscheidung im Portal | | Modellbeschränkung | der Key kann nur diese Modelle aufrufen – zusätzlich zur Beschränkung des Nutzers (es gilt die Schnittmenge) | | Credit-Limit | Credits, die dieser Key im laufenden Abrechnungszeitraum verbrauchen darf | | Ablaufdatum | danach lehnt die API den Key ab; ohne Datum gilt er unbegrenzt | Wir speichern nur einen Hash des Keys. Nach dem Anlegen kann ihn niemand mehr anzeigen, auch der Support nicht. Wenn du ihn verlierst, erzeuge ihn neu. ### Neu erzeugen und widerrufen [#neu-erzeugen-und-widerrufen] * **Neu erzeugen** (Rotation): Du bekommst einen neuen Key mit denselben Einstellungen, der alte wird sofort ungültig. Der Verbrauch des neuen Keys für sein Credit-Limit beginnt bei 0. * **Widerrufen**: Der Key wird sofort ungültig. Sein bisheriger Verbrauch bleibt in der Abrechnung sichtbar. ### Was bei einem Limit passiert [#was-bei-einem-limit-passiert] Mit Credit-Limits teilst du das Kontingent deines Pakets im Team auf. Überschreitet ein Key sein Credit-Limit oder der Nutzer das Nutzerlimit, wird der Key gesperrt und die API antwortet mit `401` ([Fehler](/api/fehler)). Die Sperre hebt sich automatisch auf, wenn du das Limit erhöhst oder ein neuer Abrechnungszeitraum beginnt. Ist dagegen das Kontingent des ganzen Pakets verbraucht, antwortet die API für alle Keys mit `429` und dem Code `insufficient_quota` ([Abrechnung](/grundlagen/abrechnung#wenn-das-kontingent-aufgebraucht-ist)). Der Verbrauch wird etwa einmal pro Minute ausgewertet. Bis die Sperre greift, können deshalb noch einzelne Requests über das Limit hinaus durchgehen – plane das Limit mit etwas Puffer. ## Sicherheit [#sicherheit] * Setze den Key als Umgebungsvariable oder in einem Secret-Store, nie im Quellcode oder im Frontend. * Verwende getrennte Keys pro Anwendung. Dann kannst du einen einzelnen Key widerrufen, ohne alle anderen zu tauschen. * Beschränke Keys auf die Modelle, die die Anwendung braucht, und setze ein Credit-Limit. * Schicke den Key nur an `https://api.promodelhub.de` – im Header `Authorization: Bearer `. # Limits (/grundlagen/limits) | Limit | Wert | Bei Überschreitung | | ------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------ | | Credits pro Abrechnungszeitraum | je Paket, siehe [unten](#paketlimits) | `429` mit Code `insufficient_quota` | | Requests pro Minute (Account) | je Paket | `429` mit Code `rate_limit_exceeded`, Header `retry-after` | | Parallele Requests (Account) | je Paket | `429` mit Code `rate_limit_exceeded` | | Requests pro IP-Adresse | etwa 10 pro Sekunde | `503` | | Kontextfenster | je Modell, siehe [Modelle](/modelle) | `400` | | Größe eines Requests | 20 MB | `413` | | Bilder pro Request | 4 | `400` | | Eingabe pro Embedding | 8.192 Token | `400` | | Dauer eines Requests | 600 Sekunden | Abbruch | | Limits pro Key und Nutzer | selbst festgelegt, in Credits pro Abrechnungszeitraum | `401`, siehe [Konto und API-Keys](/grundlagen/konto-und-keys#was-bei-einem-limit-passiert) | | Kein aktives Paket | – | `403` mit Code `no_package` | Die Fehler und was du jeweils tun kannst, stehen unter [Fehler](/api/fehler). ## Paketlimits [#paketlimits] | Paket | Credits/Monat | Requests pro Minute | parallele Requests | | ------------- | ------------- | ------------------- | ------------------ | | Starter | 5 Mio. | 30 | 5 | | Pro | 80 Mio. | 60 | 10 | | Business | 320 Mio. | 150 | 20 | | Business Plus | 650 Mio. | 150 | 20 | Alle Paketlimits gelten **pro Account**, also für alle API-Keys und Nutzer zusammen. Mehrere Keys erhöhen die Limits nicht. Wie Credits verbraucht werden, steht unter [Abrechnung](/grundlagen/abrechnung). ### Credits [#credits] Sind die Credits des laufenden Abrechnungszeitraums verbraucht, antwortet die API mit `429` und dem Code `insufficient_quota`. Ein Retry hilft hier nicht: Die Sperre gilt bis zum nächsten Zeitraum oder bis du ein größeres Paket buchst. Der Verbrauch wird etwa einmal pro Minute ausgewertet, deshalb können bis zur Sperre noch einzelne Requests über 100 % hinaus durchgehen. ### Requests pro Minute [#requests-pro-minute] Gezählt werden die Requests deines Accounts in den letzten 60 Sekunden. Ist das Limit erreicht, antwortet die API mit `429`, Code `rate_limit_exceeded` und dem Header `retry-after` (Sekunden bis zum nächsten freien Platz). ### Parallele Requests [#parallele-requests] So viele Requests darf dein Account gleichzeitig offen haben. Ein Request belegt seinen Platz, bis die Antwort vollständig ist, beim Streaming also bis zum letzten Chunk. Ist das Limit erreicht, antwortet die API mit `429` und dem Code `rate_limit_exceeded`, die Meldung nennt die parallelen Requests. Warte, bis laufende Requests fertig sind, oder begrenze die Parallelität in deiner Anwendung (z. B. mit einem Semaphore oder einer Worker-Queue). Brauchst du dauerhaft mehr, buche ein größeres Paket. ## Kontextfenster [#kontextfenster] Das Kontextfenster umfasst **Eingabe und Ausgabe zusammen**: Die Input-Token plus `max_tokens` dürfen es nicht überschreiten. Sonst lehnt die API den Request mit `400` ab, die Fehlermeldung nennt die Token-Zahlen: ```text This model's maximum context length is 32768 tokens. However, you requested 10 output tokens and your prompt contains 80003 input tokens, for a total of 80013 tokens. ... ``` Ohne `max_tokens` darf die Antwort den gesamten restlichen Platz im Kontextfenster nutzen. ## Lange Antworten [#lange-antworten] Ein Request darf höchstens 600 Sekunden dauern. Für lange Antworten empfehlen wir [Streaming](/funktionen/streaming): Die ersten Token kommen nach wenigen Sekunden, und Verbindungen über Proxys oder Load Balancer brechen seltener ab. # Wartezeiten und Retries (/grundlagen/verfuegbarkeit) ## Modellwechsel [#modellwechsel] Einige Modelle teilen sich Rechenkapazität. Wird ein Modell gerade nicht genutzt, wird es bei der ersten Anfrage aktiviert. Das dauert meist nur wenige Sekunden. Laufen auf dem geteilten Platz noch Anfragen an ein anderes Modell, werden diese zuerst fertig bearbeitet. Spätestens nach 10 Sekunden nimmt das andere Modell keine neuen Anfragen mehr an. Eine lange laufende Generierung wird aber nicht abgebrochen, in dem Fall kann die Wartezeit länger sein. Ein aktives Modell bleibt aktiv, bis ein anderes Modell auf demselben Platz angefragt wird. Im Alltag merkst du davon meist nur eine etwas längere Zeit bis zum ersten Token. ## Wann du einen Retry brauchst [#wann-du-einen-retry-brauchst] Kann ein Modell vorübergehend nicht antworten (z. B. während eines Wechsels unter hoher Last oder bei Wartung), antwortet die API mit `503`. Solche Fehler sind vorübergehend: Wiederhole den Request nach einer kurzen Pause mit wachsendem Abstand (exponentielles Backoff). | Status | Wiederholen? | | ---------------------------------------- | --------------------------------------------------------------------------------- | | `429` mit `rate_limit_exceeded` | ja, nach der Zeit im Header `retry-after` bzw. wenn laufende Requests fertig sind | | `429` mit `insufficient_quota` | nein – das Paket ist verbraucht ([Fehler](/api/fehler#paket-verbraucht)) | | `500`, `502`, `503`, `504` | ja, mit Backoff (z. B. 1, 2, 4, 8 Sekunden) | | `400`, `401`, `403`, `404`, `413`, `422` | nein – der Request muss geändert werden | Die offiziellen OpenAI-SDKs wiederholen `429` und `5xx` bereits automatisch (standardmäßig zweimal). Ausgenommen ist `429` mit `insufficient_quota`: Die API schickt dabei den Header `x-should-retry: false`, die SDKs werfen dann sofort `RateLimitError`. Frag den Fehlercode ab, statt selbst zu wiederholen ([Fehler](/api/fehler#paket-verbraucht)). Eigene Retry-Logik ohne SDK sollte `insufficient_quota` genauso auslassen. Für Hintergrundjobs lohnt es sich, die Zahl der Retries zu erhöhen: ```python client = OpenAI( base_url="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"], max_retries=5, timeout=600, ) ``` ```ts const client = new OpenAI({ baseURL: "https://api.promodelhub.de/v1", apiKey: process.env.PRO_MODEL_HUB_API_KEY, maxRetries: 5, timeout: 600_000, }); ``` Mehr zu Fehlercodes und dem Fehlerformat unter [Fehler](/api/fehler). # Übersicht (/) Der pro Model Hub stellt dir leistungsfähige offene Sprach-, Coding- und Embedding-Modelle über eine einzige API bereit. Die API ist **kompatibel zur OpenAI-API**: Bestehende Anwendungen, SDKs und Tools funktionieren, wenn du Basis-URL, API-Key und Modellnamen austauschst. * **Basis-URL:** `https://api.promodelhub.de/v1` * **Hosting:** Die Modelle laufen auf dedizierten Servern in Deutschland. * **Abrechnung:** Monatspakete mit festem Kontingent an Credits. Jedes Modell verbraucht Credits mit einem eigenen Credit-Faktor ([Abrechnung](/grundlagen/abrechnung)). Der pro Model Hub befindet sich in der Beta. Modelle, Pakete, Credit-Faktoren und Limits können sich noch ändern – Änderungen stehen im [Changelog](/changelog). ## Loslegen [#loslegen] ## Was die API kann [#was-die-api-kann] | Funktion | Endpunkt | Anleitung | | -------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | Chat und Textgenerierung | `POST /v1/chat/completions` | [Chat Completions](/api/chat-completions) | | Streaming | `POST /v1/chat/completions` mit `"stream": true` | [Streaming](/funktionen/streaming) | | Reasoning (Denkmodus) | `POST /v1/chat/completions` | [Reasoning](/funktionen/reasoning) | | Tool-Calling (Function Calling) | `POST /v1/chat/completions` mit `tools` | [Tool-Calling](/funktionen/tool-calling) | | JSON-Ausgaben nach Schema | `POST /v1/chat/completions` mit `response_format` | [Strukturierte Ausgaben](/funktionen/strukturierte-ausgaben) | | Bilder verstehen (Image-to-Text) | `POST /v1/chat/completions` mit Bildern | [Bildeingabe](/funktionen/bildeingabe) | | Embeddings für Suche und RAG | `POST /v1/embeddings` | [Embeddings](/api/embeddings) | | Verfügbare Modelle abfragen | `GET /v1/models` | [Modelle abfragen](/api/modelle) | ## Für KI-Assistenten [#für-ki-assistenten] Jede Seite dieser Dokumentation gibt es auch als Markdown: Hänge `.md` an die URL an (z. B. [/schnellstart.md](/schnellstart.md)). Eine Übersicht aller Seiten liefert [/llms.txt](/llms.txt), die komplette Dokumentation in einer Datei [/llms-full.txt](/llms-full.txt). # Integrationen (/integrationen) Überall, wo du einen „OpenAI-kompatiblen“ Anbieter eintragen kannst, funktioniert der pro Model Hub. Du brauchst immer dieselben drei Angaben: | Einstellung | Wert | | ---------------------------------------- | -------------------------------------------------------------------------- | | Basis-URL (Base URL, API Base, Endpoint) | `https://api.promodelhub.de/v1` | | API-Key | dein [API-Key](/grundlagen/konto-und-keys) | | Modell | eine API-ID aus der [Modellübersicht](/modelle), z. B. `mistral-small-24b` | Für Werkzeuge, die mehrere Anbieter verwalten, lohnt sich ein eigener Key pro Werkzeug mit Credit-Limit. ## OpenAI-SDKs [#openai-sdks] Python und Node.js: siehe [Schnellstart](/schnellstart). Bei anderen Sprachen (Go, Java, .NET, PHP …) setzt du im OpenAI-Client die Basis-URL und den Key, der Rest bleibt gleich. ## LangChain [#langchain] ```python import os from langchain_openai import ChatOpenAI, OpenAIEmbeddings llm = ChatOpenAI( model="gemma-4-31b", base_url="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"], ) print(llm.invoke("Was ist RAG? Ein Satz.").content) embeddings = OpenAIEmbeddings( model="qwen3-vl-embedding-2b", base_url="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"], check_embedding_ctx_length=False, # sonst schickt LangChain Token-IDs statt Text ) ``` ## LlamaIndex [#llamaindex] ```python import os from llama_index.llms.openai_like import OpenAILike llm = OpenAILike( model="gemma-4-31b", api_base="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"], is_chat_model=True, is_function_calling_model=True, context_window=32768, ) ``` Das Paket heißt `llama-index-llms-openai-like`. Das Kontextfenster des Modells steht auf der jeweiligen Modellseite. ## Open WebUI [#open-webui] Eine eigene Chat-Oberfläche für dein Team: In Open WebUI unter **Admin-Einstellungen → Verbindungen → OpenAI API** eine Verbindung hinzufügen, Basis-URL und API-Key eintragen. Die Modelle erscheinen danach in der Modellauswahl (Open WebUI liest sie über `/v1/models`). ## Coding-Assistenten [#coding-assistenten] Für Programmieraufgaben eignen sich die Modelle der Kategorie Coding (siehe [Modelle](/modelle)). **Continue** (VS Code, JetBrains) – in der `config.yaml`: ```yaml models: - name: Qwen3 Coder Next (pro Model Hub) provider: openai model: qwen3-coder-next apiBase: https://api.promodelhub.de/v1 apiKey: roles: [chat, edit, apply] ``` **Cline** (VS Code) – in den Einstellungen als API-Provider **OpenAI Compatible** wählen, Basis-URL, API-Key und Modell-ID eintragen. Coding-Agenten schicken viel Kontext (Dateien, Tool-Definitionen) und viele Requests hintereinander. Behalte den Credit-Verbrauch und die [Limits deines Pakets](/grundlagen/limits#paketlimits) im Blick, vor allem die parallelen Requests. ## n8n und andere Automatisierungs-Tools [#n8n-und-andere-automatisierungs-tools] In n8n die Zugangsdaten vom Typ **OpenAI** anlegen und die Basis-URL auf `https://api.promodelhub.de/v1` ändern. Danach funktionieren die OpenAI-Knoten und der „OpenAI Chat Model“-Knoten für AI-Agenten mit den Modellen des pro Model Hub. In anderen Tools (Make, Zapier, Flowise …) funktioniert es genauso, sofern sie eine eigene Basis-URL erlauben. # Modelle (/modelle) Die Liste wird live aus unserem Modellkatalog erzeugt und ist immer aktuell. Die **API-ID** setzt du im Request als `model`. Ein Klick auf den Modellnamen führt zu Beschreibung, Stärken, API-Hinweisen und Beispielen. Der **Credit-Faktor** gibt an, wie viele Credits ein Token des Modells verbraucht: `(Input-Token + Output-Token) × Credit-Faktor`. Wie Token gezählt werden und welche Pakete es gibt, steht unter [Abrechnung](/grundlagen/abrechnung). Welche Modelle dein API-Key nutzen darf, liefert [`GET /v1/models`](/api/modelle). ## Welches Modell passt? [#welches-modell-passt] * **Hohes Anfragevolumen und klar umrissene Aufgaben** (Chatbots, Klassifikation, Extraktion): ein kleineres, schnelles Modell mit niedrigem Credit-Faktor. * **Komplexe Texte, Analysen und anspruchsvolle Kundenkommunikation:** ein großes Allround-Modell, bei kniffligen Aufgaben mit [Reasoning](/funktionen/reasoning). * **Programmierung, Code-Review und Coding-Agenten:** ein Coding-Modell. * **Semantische Suche, RAG und Klassifikation über Ähnlichkeit:** ein [Embedding-Modell](/api/embeddings). Am schnellsten findest du das passende Modell, indem du dieselben Prompts im **Test-Chat** des Portals mit mehreren Modellen ausprobierst. ## Status und Lebenszyklus [#status-und-lebenszyklus] | Status | Bedeutung | | ---------- | ------------------------------------------------------------ | | Beta | nutzbar, Verhalten und Credit-Faktor können sich noch ändern | | Verfügbar | stabil für den produktiven Einsatz | | Auslaufend | wird abgekündigt – bitte auf ein anderes Modell umsteigen | | Demnächst | angekündigt, noch nicht über die API nutzbar | Neue, geänderte und entfernte Modelle stehen im [Changelog](/changelog). # Schnellstart (/schnellstart) ### API-Key anlegen [#api-key-anlegen] Melde dich im [Portal](https://app.promodelhub.de) an. Hat dein Account noch kein Paket, aktiviert der Owner zuerst das Starter-Paket (30 Tage kostenlos) oder bestellt ein größeres ([Abrechnung](/grundlagen/abrechnung#testphase)). Ohne aktives Paket lehnt die API Requests ab. Öffne dann **API-Keys** → **Neuer Key**. Optional kannst du den Key auf bestimmte Modelle beschränken, ein Credit-Limit pro Abrechnungszeitraum oder ein Ablaufdatum setzen ([Konto und API-Keys](/grundlagen/konto-und-keys)). Der Key wird **nur einmal angezeigt**. Kopiere ihn direkt und speichere ihn sicher, z. B. in einem Passwort-Manager oder Secret-Store. ### Key als Umgebungsvariable setzen [#key-als-umgebungsvariable-setzen] Lege den Key nie im Quellcode ab. Alle Beispiele in dieser Dokumentation lesen ihn aus der Umgebungsvariable `PRO_MODEL_HUB_API_KEY`: ```bash export PRO_MODEL_HUB_API_KEY="sk-..." ``` ### Ersten Request senden [#ersten-request-senden] Wähle ein Modell aus der [Modellübersicht](/modelle) und setze seine API-ID als `model`. ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "mistral-small-24b", "messages": [ {"role": "system", "content": "Du bist ein hilfreicher Assistent."}, {"role": "user", "content": "Nenne drei Einsatzideen für Sprachmodelle im Kundenservice."} ] }' ``` Mit dem offiziellen OpenAI-SDK (`pip install openai`) – nur `base_url` und `api_key` ändern sich: ```python import os from openai import OpenAI client = OpenAI( base_url="https://api.promodelhub.de/v1", api_key=os.environ["PRO_MODEL_HUB_API_KEY"], ) response = client.chat.completions.create( model="mistral-small-24b", messages=[ {"role": "system", "content": "Du bist ein hilfreicher Assistent."}, {"role": "user", "content": "Nenne drei Einsatzideen für Sprachmodelle im Kundenservice."}, ], ) print(response.choices[0].message.content) print(response.usage) # abgerechnete Token ``` Mit dem offiziellen OpenAI-SDK (`npm install openai`): ```ts import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.promodelhub.de/v1", apiKey: process.env.PRO_MODEL_HUB_API_KEY, }); const response = await client.chat.completions.create({ model: "mistral-small-24b", messages: [ { role: "system", content: "Du bist ein hilfreicher Assistent." }, { role: "user", content: "Nenne drei Einsatzideen für Sprachmodelle im Kundenservice." }, ], }); console.log(response.choices[0].message.content); ``` ### Verbrauch prüfen [#verbrauch-prüfen] Jede Antwort enthält im Feld `usage` die verarbeiteten Token. Daraus ergeben sich mit dem Credit-Faktor des Modells die verbrauchten Credits. Den Verbrauch pro Modell und Key siehst du im Portal unter **Kosten & Verbrauch** – mit etwa ein bis zwei Minuten Verzögerung ([Abrechnung](/grundlagen/abrechnung)). ## Ohne Programmierung ausprobieren [#ohne-programmierung-ausprobieren] Im Portal gibt es unter **Test-Chat** einen Chat, mit dem du alle Modelle direkt im Browser testen kannst – auch mit Bildern bei Modellen mit Bildeingabe. Er verbraucht Credits wie API-Aufrufe. ## Nächste Schritte [#nächste-schritte] # Mistral Small 24B Kompaktes, schnelles Modell von Mistral AI mit 24 Mrd. Parametern – ideal für klar umrissene Aufgaben und Anwendungen mit hohem Anfragevolumen. | Eigenschaft | Wert | |---|---| | API-ID (`model`) | `mistral-small-24b` | | Anbieter | Mistral AI | | Kategorie | Sprachmodelle | | Status | Beta | | Kontextfenster | 32.768 Token | | Credit-Faktor | 2× (Credits pro Token) | | Bildeingabe | nein | | Tool-Calling | ja | | Reasoning | Nicht verfügbar | Verbrauch pro Request: (Input-Token + Output-Token) × Credit-Faktor, siehe Abrechnung. ## Stärken - Schnell und effizient - Gute Leistung in europäischen Sprachen - Solides Function Calling ## Schwächen - Schwächer bei komplexem, mehrstufigem Schlussfolgern als große Modelle ## Empfohlene Einsatzbereiche - Chatbots - Klassifikation - Datenextraktion - Kurze Zusammenfassungen - Anwendungen mit hohem Anfragevolumen ## API-Hinweise - `chat_template_kwargs` lehnt das Modell mit `400` ab – nicht mitschicken. ## Beispiel ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "mistral-small-24b", "messages": [{"role": "user", "content": "Erkläre in zwei Sätzen, was ein Sprachmodell ist."}] }' ``` # Qwen 3.8 27B Aktuelles Allround-Modell von Alibaba/Qwen mit 27 Mrd. Parametern und Reasoning-Modus – für Aufgaben, bei denen das Modell erst nachdenken und dann antworten soll. | Eigenschaft | Wert | |---|---| | API-ID (`model`) | `qwen3.8-27b` | | Anbieter | Alibaba/Qwen | | Kategorie | Sprachmodelle | | Status | Beta | | Kontextfenster | 32.768 Token | | Credit-Faktor | 1,5× (Credits pro Token) | | Bildeingabe | nein | | Tool-Calling | ja | | Reasoning | Standardmäßig an | Verbrauch pro Request: (Input-Token + Output-Token) × Credit-Faktor, siehe Abrechnung. ## Stärken - Reasoning-Modus für mehrstufige Analysen und Schlussfolgerungen - Zuverlässiges Tool Calling für Agenten-Workflows - Stark bei Programmier-, Recherche- und Fachaufgaben - Großes Kontextfenster (32.768 Token) ## Schwächen - Das Nachdenken kostet Zeit und erzeugt zusätzliche Output-Token (höhere Kosten pro Anfrage) - Bei uns nur Text – kein Bild- oder Videoverständnis ## Empfohlene Einsatzbereiche - Komplexe Analysen und mehrstufiges Schlussfolgern - Agenten mit Tool-Nutzung - Auswertung längerer Dokumente - Recherche- und Fachaufgaben ## API-Hinweise - `reasoning_effort` kennt `low`, `medium` und `xhigh` (Standard, wenn nichts gesetzt ist). `high` lehnt das Modell mit `400` ab. - Für einfache Aufgaben den Denkmodus mit `reasoning_effort: "none"` ausschalten – das spart Zeit und Output-Token. - Nur Text, keine Bildeingabe. ## Beispiel ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3.8-27b", "messages": [{"role": "user", "content": "Erkläre in zwei Sätzen, was ein Sprachmodell ist."}] }' ``` ## Reasoning ```python # Denkmodus ausschalten (standardmäßig an) response = client.chat.completions.create( model="qwen3.8-27b", messages=[{"role": "user", "content": "Wie viele Montage hat der März 2027?"}], reasoning_effort="none", ) message = response.choices[0].message print(getattr(message, "reasoning_content", None)) # Gedankengang, falls eingeschaltet print(message.content) # eigentliche Antwort ``` # Gemma 4 31B Leistungsstarkes Allround-Modell von Google mit 31 Mrd. Parametern, das neben Text auch Bilder versteht: Es liest Screenshots, Fotos und gescannte Dokumente und antwortet in Text. | Eigenschaft | Wert | |---|---| | API-ID (`model`) | `gemma-4-31b` | | Anbieter | Google | | Kategorie | Sprachmodelle | | Status | Beta | | Kontextfenster | 32.768 Token | | Credit-Faktor | 1,5× (Credits pro Token) | | Bildeingabe | ja | | Tool-Calling | ja | | Reasoning | Optional (standardmäßig aus) | Verbrauch pro Request: (Input-Token + Output-Token) × Credit-Faktor, siehe Abrechnung. ## Stärken - Bildverständnis (Image-to-Text): bis zu 4 Bilder pro Anfrage - Sehr gute Ergebnisse bei Wissens- und Reasoning-Benchmarks für seine Größe - Optionaler Reasoning-Modus (Thinking) für mehrstufige Aufgaben - Zuverlässiges Tool Calling - Großes Kontextfenster (32.768 Token) ## Schwächen - Erzeugt keine Bilder, antwortet nur in Text - Bilder nur als Base64 im Request, Bild-URLs werden nicht abgerufen - Jedes Bild zählt als Input-Token (ca. 280 Token pro Bild) - Das Nachdenken im Reasoning-Modus erzeugt zusätzliche Output-Token ## Empfohlene Einsatzbereiche - Dokumente, Belege und Formulare auslesen - Screenshots und Diagramme erklären - Bildbeschreibungen und Alt-Texte - Anspruchsvolle Texterstellung und Analyse - Agenten mit Tool-Nutzung ## API-Hinweise - Reasoning: Jeder Wert von `reasoning_effort` außer `none` (`low`, `medium`, `high`) schaltet den Denkmodus ein. Die Stufe ändert die Länge des Gedankengangs nicht. - `tool_choice: "required"` und das Erzwingen einer bestimmten Funktion setzt das Modell nicht um, es entscheidet wie bei `auto` selbst. Bei `required` kommt trotzdem `finish_reason: "tool_calls"` zurück, auch wenn kein Aufruf enthalten ist – prüfe `tool_calls` statt `finish_reason`. - Bilder nur als Base64-Data-URI, höchstens 4 pro Request, jedes etwa 280 Input-Token. ## Beispiel ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gemma-4-31b", "messages": [{"role": "user", "content": "Erkläre in zwei Sätzen, was ein Sprachmodell ist."}] }' ``` ## Reasoning ```python # Denkmodus einschalten (standardmäßig aus) response = client.chat.completions.create( model="gemma-4-31b", messages=[{"role": "user", "content": "Wie viele Montage hat der März 2027?"}], reasoning_effort="low", ) message = response.choices[0].message print(getattr(message, "reasoning_content", None)) # Gedankengang, falls eingeschaltet print(message.content) # eigentliche Antwort ``` # Qwen3-Coder-Next Auf Programmierung spezialisiertes Modell von Alibaba/Qwen (80 Mrd. Parameter, davon je Anfrage nur 3 Mrd. aktiv) – schnell und für agentische Coding-Workflows mit Tool-Nutzung ausgelegt. | Eigenschaft | Wert | |---|---| | API-ID (`model`) | `qwen3-coder-next` | | Anbieter | Alibaba/Qwen | | Kategorie | Coding | | Status | Beta | | Kontextfenster | 32.768 Token | | Credit-Faktor | 1× (Credits pro Token) | | Bildeingabe | nein | | Tool-Calling | ja | | Reasoning | Nicht verfügbar | Verbrauch pro Request: (Input-Token + Output-Token) × Credit-Faktor, siehe Abrechnung. ## Stärken - Auf Programmierung spezialisiert: Code-Generierung und -Verständnis - Schnell dank nur 3 Mrd. aktiver Parameter - Stark in agentischen Workflows: Tool-Nutzung und Umgang mit Fehlern bei der Ausführung - Großes Kontextfenster (32.768 Token) ## Schwächen - Kein Reasoning-Modus – bei kniffligen Analysen außerhalb von Code schwächer - Für allgemeine Texte und Kundenkommunikation weniger geeignet als Allround-Modelle - Kontextfenster reicht für einzelne Dateien und Module, nicht für ganze große Codebasen ## Empfohlene Einsatzbereiche - Code-Generierung - Code-Review - Refactoring - Erklärung von Code - Coding-Assistenten und -Agenten ## Beispiel ```bash curl https://api.promodelhub.de/v1/chat/completions \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3-coder-next", "messages": [{"role": "user", "content": "Erkläre in zwei Sätzen, was ein Sprachmodell ist."}] }' ``` # Qwen3-VL Embedding 2B | Eigenschaft | Wert | |---|---| | API-ID (`model`) | `qwen3-vl-embedding-2b` | | Anbieter | Alibaba/Qwen | | Kategorie | Embeddings | | Status | Beta | | Kontextfenster | 8.192 Token | | Credit-Faktor | 0,25× (Credits pro Token) | Verbrauch pro Request: (Input-Token + Output-Token) × Credit-Faktor, siehe Abrechnung. ## API-Hinweise - `dimensions` von 64 bis 2048 (Standard 2048). - Höchstens 8.192 Token pro Text. - Zusätzliches Feld `instruction` für eine aufgabenspezifische Anweisung, z. B. für Suchanfragen in RAG-Systemen (siehe API-Referenz Embeddings). ## Beispiel ```bash curl https://api.promodelhub.de/v1/embeddings \ -H "Authorization: Bearer $PRO_MODEL_HUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3-vl-embedding-2b", "input": ["Wie kündige ich meinen Vertrag?", "Die Kündigung ist jederzeit zum Monatsende möglich."] }' ```