Einheit 4.4: Integration des AI Model Hub
Einführung
Sie fügen TaskBoard eine KI-Funktion hinzu: Wenn ein Benutzer eine lange Aufgabenbeschreibung übermittelt, ruft die API ein großes Sprachmodell auf, um eine einzeilige Zusammenfassung zu erstellen, und speichert diese Zusammenfassung anschließend in PostgreSQL. AI Model Hub stellt gehostete Modelle über eine OpenAI-kompatible REST API bereit, sodass Sie keine GPUs betreiben und keine Modellgewichte verwalten müssen. Sie senden einen Prompt an einen Inferenz-Endpunkt, erhalten Tokens zurück und zahlen pro Token.
Diese Einheit beginnt mit dem HTTP-Aufruf. Sie sehen die genauen Strukturen von Anfrage und Antwort, binden diese in Python sowohl mit requests als auch mit dem OpenAI-Client ein, ergänzen die Wiederholungs- und Timeout-Logik, die für Produktionsinferenz erforderlich ist, und verbinden die Funktion anschließend mit dem Rest von TaskBoard über synchrone Aufrufe und einen asynchronen Pfad mit Kafka-Warteschlange. Jeder Codeblock richtet sich an den echten IONOS CLOUD-Endpunkt und echte Modellkennungen, sodass Sie ihn kopieren, Ihr Token eintragen und ausführen können.
1. Der Inferenz-Endpunkt und die Authentifizierung
AI Model Hub bietet zwei API-Optionen: eine native AI Model Hub API und eine OpenAI-kompatible API. Die OpenAI-kompatible API spiegelt die OpenAI-Anfrage- und Antwortstruktur wider, sodass Sie bestehende OpenAI-Tools und SDKs wiederverwenden können, indem Sie nur die Basis-URL und die Zugangsdaten ändern. Für die Anwendungsentegration ist dies der empfohlene Weg, da die Struktur von Anfragen und Antworten bereits vertraut ist und die offiziellen OpenAI-Client-Bibliotheken ohne Änderungen funktionieren.
Die OpenAI-kompatible Basis-URL lautet https://openai.inference.de-txl.ionos.com/v1. Die Authentifizierung erfolgt über ein Bearer-Token, das ein JSON Web Token (JWT) mit Ablaufdatum ist. Die AI Model Hub-Anleitungen gehen davon aus, dass das Token in der Umgebungsvariable IONOS_API_TOKEN gespeichert ist. Da das Token ein JWT mit einem exp-Anspruch ist, bedeutet ein plötzlicher Authentifizierungsfehler in der Regel, dass das Token abgelaufen ist, nicht dass der Aufruf fehlerhaft ist. Prüfen Sie den exp-Anspruch und generieren Sie das Token neu, falls das Ablaufdatum überschritten wurde.
1.1 Erster Aufruf mit curl
Senden Sie eine Chat-Vervollständigung, um Ihr Token und die Konnektivität zu überprüfen, bevor Sie Anwendungscode schreiben. Der Endpunkt lautet POST /v1/chat/completions und der Anfragekörper enthält eine model-Kennung und ein messages-Array.
export IONOS_API_TOKEN="your-jwt-token"
curl -s https://openai.inference.de-txl.ionos.com/v1/chat/completions \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-3.3-70B-Instruct",
"messages": [
{"role": "user", "content": "Summarize in one sentence: the deploy pipeline failed because the registry token expired."}
],
"temperature": 0.2,
"max_tokens": 60
}'
Die Antwort ist ein OpenAI-artiges Completion-Objekt. Der generierte Text befindet sich in choices[0].message.content, und usage meldet prompt_tokens, completion_tokens und total_tokens, die Sie für die Kostenverfolgung benötigen.
{
"id": "chatcmpl-123",
"object": "chat.completion",
"model": "meta-llama/Llama-3.3-70B-Instruct",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "The deploy pipeline failed because the container registry token had expired."},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 28, "completion_tokens": 14, "total_tokens": 42}
}
1.2 Verfügbare Modelle auflisten
Die OpenAI-kompatible API stellt einen models-Endpunkt bereit, mit dem die Liste der verfügbaren Modelle und deren Details abgerufen werden kann. Verwenden Sie diesen Endpunkt, um die genauen Modellkennzeichner als Zeichenketten zu ermitteln, anstatt eine Vermutung hart zu codieren, da das Feld model genau diesen Kennzeichner erfordert.
curl -s https://openai.inference.de-txl.ionos.com/v1/models \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" | python3 -m json.tool
Die übergebene Modellkennung muss exakt mit dem Katalog übereinstimmen. Für die in dieser Einheit verwendeten Chatmodelle lauten die Kennungen meta-llama/Llama-3.3-70B-Instruct, openai/gpt-oss-120b und mistralai/Mistral-Small-24B-Instruct. Ein Tippfehler in der Kennung ist einer der häufigsten Fehler bei der ersten Inanspruchnahme.
2. Aufruf von Model Hub aus Anwendungscode
Im API-Dienst von TaskBoard rufen Sie Inference aus Python heraus auf. Sie haben zwei saubere Optionen: Sie nutzen die HTTP-API direkt mit requests, oder Sie verwenden den offiziellen openai-Client, der auf die Basis-URL von IONOS CLOUD zeigt. Beide Optionen treffen auf denselben Endpunkt zu. Der Pfad über requests hält die Abhängigkeiten minimal; der OpenAI-Client bietet Ihnen zusätzlich typisierte Helfer, Streaming-Iteratoren und Retry-Hooks.
2.1 Direktes HTTP mit requests
Dies ist die Integration mit den geringsten Abhängigkeiten. Sie ist auch die klarste Möglichkeit, genau zu sehen, was über die Leitung übertragen wird, was bei der Fehlersuche hilfreich ist.
import os
import requests
BASE_URL = "https://openai.inference.de-txl.ionos.com/v1"
TOKEN = os.environ["IONOS_API_TOKEN"]
def summarize(description: str) -> str:
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"model": "meta-llama/Llama-3.3-70B-Instruct",
"messages": [
{"role": "system", "content": "You write one-sentence task summaries."},
{"role": "user", "content": description},
],
"temperature": 0.2,
"max_tokens": 60,
},
timeout=30,
)
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"].strip()
Setzen Sie immer ein explizites timeout fest. Die Inferenzlatenz variiert je nach Promptlänge und Modellgröße, und ein Socket ohne Timeout, der hängen bleibt, blockiert einen Worker-Thread in Ihrer API.
2.2 Der OpenAI-Client, der auf IONOS CLOUD zeigt
Da die API OpenAI-kompatibel ist, funktioniert das offizielle openai-Python-Paket, wenn Sie base_url und api_key überschreiben. Dies ist die ergonomischste Option für Anwendungscode.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openai.inference.de-txl.ionos.com/v1",
api_key=os.environ["IONOS_API_TOKEN"],
)
def summarize(description: str) -> str:
completion = client.chat.completions.create(
model="meta-llama/Llama-3.3-70B-Instruct",
messages=[
{"role": "system", "content": "You write one-sentence task summaries."},
{"role": "user", "content": description},
],
temperature=0.2,
max_tokens=60,
)
return completion.choices[0].message.content.strip()
2.3 Streaming-Antworten
Für interaktive Benutzeroberflächen können Sie Token streamen, während sie generiert werden, indem Sie stream auf true setzen. Beim Streaming sind Nutzungsstatistiken standardmäßig nicht enthalten. Um die Nutzungsdaten im letzten Chunk zu erhalten, müssen Sie stream_options explizit mit aktiviertem include_usage setzen.
stream = client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=[{"role": "user", "content": "Explain what a poison message is."}],
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)
Der Stream endet mit einer letzten Datenzeile, die usage gefolgt von einem [DONE]-Marker enthält. Wenn Sie stream_options überspringen, verlieren Sie die Token-Anzahlen, die Sie für die Kostenabrechnung benötigen.
3. Modellauswahl: Kontextfenster und Preis
Die Modellauswahl ist eine Codeentscheidung, die von zwei Zahlen gesteuert wird: wie viele Tokens das Modell akzeptiert (Kontextfenster) und was eine Million Tokens kostet. Die Zusammenfassungen von TaskBoard sind kurz, daher ist das günstigste leistungsfähige Modell der richtige Standardwert; größere Modelle sollten nur für Aufgaben reserviert werden, die sie tatsächlich benötigen.
Die folgende Tabelle vergleicht die in dieser Einheit verwendeten Chat-Modelle. Die Preise sind in EUR pro Million Tokens angegeben.
| Modellkennung | Kontextfenster (Tokens) | Eingabepreis (EUR / 1M) | Ausgabepreis (EUR / 1M) |
|---|---|---|---|
mistralai/Mistral-Small-24B-Instruct |
128000 | 0.10 | 0.30 |
openai/gpt-oss-120b |
128000 | 0.15 | 0.65 |
meta-llama/Llama-3.3-70B-Instruct |
128000 | 0.65 | 0.65 |
Wie oben gezeigt, akzeptieren alle drei Modelle ein Kontextfenster von 128000 Tokens, daher ist der Preis bei einer kurzen Zusammenfassungsanfrage der entscheidende Faktor. mistralai/Mistral-Small-24B-Instruct ist sowohl bei der Eingabe als auch bei der Ausgabe am günstigsten und ist ein sinnvoller Standardwert für TaskBoard-Zusammenfassungen. Wechseln Sie nur dann zu einem größeren Modell, wenn die Qualität der Zusammenfassung bei echten Aufgabenbeschreibungen nachweislich besser ist und den Aufpreis pro Token rechtfertigt.
3.1 Kostenbewusste Modellkonfiguration
Machen Sie das Modell zu einem Konfigurationswert, nicht zu einem in dem Code verstreuten Literal, damit Sie je nach Umgebung wechseln können, ohne die Logik neu bereitzustellen.
import os
SUMMARY_MODEL = os.environ.get("SUMMARY_MODEL", "mistralai/Mistral-Small-24B-Instruct")
def estimate_cost_eur(prompt_tokens: int, completion_tokens: int,
in_price: float, out_price: float) -> float:
return (prompt_tokens / 1_000_000) * in_price + (completion_tokens / 1_000_000) * out_price
print(estimate_cost_eur(28, 14, 0.10, 0.30)) # 28 prompt + 14 completion tokens, Mistral-Small pricing
3.2 Embeddings für semantische Merkmale
Wenn TaskBoard eine semantische Suche über Aufgaben erfordert, generieren Sie Vektoren mit einem Embedding-Modell, nicht mit einem Chat-Modell. Der Endpunkt ist POST /v1/embeddings. Das BAAI/bge-m3-Modell gibt 1024-dimensionale Vektoren zurück und wird mit 0,02 EUR pro Million Tokens berechnet.
def embed(text: str) -> list[float]:
resp = client.embeddings.create(model="BAAI/bge-m3", input=text)
return resp.data[0].embedding # 1024 floats
vec = embed("Fix the expired registry token in the deploy pipeline")
assert len(vec) == 1024
Speichern Sie die resultierenden Vektoren dort, wo Ihre Suchschicht hostet. Die Embedding-Erzeugung ist für eine gegebene Eingabe und ein gegebenes Modell deterministisch, sodass identischer Text immer denselben Vektor erzeugt. Dadurch sind Embeddings ein starker Kandidat für das Caching.
4. Fehlerbehandlung im Produktivbetrieb
Inference-Aufrufe scheitern auf Arten, die bei Ihren CRUD-Endpunkten nicht vorkommen: Das Modell wird durch Rate Limiting gedrosselt, die Anfrage läuft unter Last in ein Timeout, oder die Antwort ist zwar gut formatiertes JSON, der Inhalt ist jedoch leer oder nicht dem erwarteten Format entsprechend. Produktionscode muss alle drei Fälle behandeln. Der wichtigste Fall auf IONOS CLOUD ist das Rate Limiting.
4.1 Rate Limits und 429-Backoff
Das allgemeine API-Rate Limit beträgt 5 Anfragen pro Sekunde (Basis) mit einer Burst-Genehmigung von 10. Wenn Sie das Limit überschreiten, gibt der Dienst HTTP 429 Too Many Requests zurück. Behandeln Sie 429 als Signal zum Zurückfahren und erneuten Versuch, nicht als harten Fehler. Verwenden Sie exponentielles Backoff, damit ein Burst an TaskBoard-Aktivität den Endpunkt nicht überlastet.
import time
import requests
def chat_with_retry(payload: dict, max_attempts: int = 5) -> dict:
delay = 1.0
for attempt in range(max_attempts):
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers={"Authorization": f"Bearer {TOKEN}"},
json=payload,
timeout=30,
)
if resp.status_code == 429:
retry_after = float(resp.headers.get("Retry-After", delay))
time.sleep(retry_after)
delay *= 2
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("inference rate-limited after retries")
Respektieren Sie den Retry-After-Header, wenn der Dienst diesen bereitstellt, und greifen Sie andernfalls auf Ihre eigene exponentielle Verzögerung zurück. Beschränken Sie die Anzahl der Versuche, damit ein anhaltender Ausfall als Fehler gemeldet wird und nicht als Endlosschleife.
4.2 Timeouts and response validation
Eine Antwort mit dem Status 200 ist keine Garantie für verwertbare Inhalte. Das Modell kann eine leere Zeichenfolge oder Text zurückgeben, der Ihre nachgelagerten Annahmen verletzt. Validieren Sie, bevor Sie Daten speichern.
def safe_summary(description: str) -> str:
payload = {
"model": SUMMARY_MODEL,
"messages": [
{"role": "system", "content": "Reply with exactly one sentence."},
{"role": "user", "content": description},
],
"max_tokens": 60,
}
data = chat_with_retry(payload)
choices = data.get("choices") or []
if not choices:
raise ValueError("no choices in inference response")
content = (choices[0]["message"]["content"] or "").strip()
if not content:
raise ValueError("empty summary returned")
return content
Für strukturierte Extraktion unterstützt die Chat-Completions-API ein response_format mit einem JSON-Schema und aktiviertem strict, das das Modell dazu zwingt, gültiges JSON auszugeben, das Ihrem Schema entspricht. Das ist der zuverlässige Weg, maschinenlesbare Ausgaben zu erhalten, anstatt freien Text, den Sie defensiv parsen müssen.
5. Integrationsmuster und Kostenkontrolle
Sie können Inference auf zwei Arten in TaskBoard aufrufen. Synchrones Inference wird innerhalb der Anfrage ausgeführt, die das Ergebnis benötigt. Asynchrones Inference stellt die Arbeit in eine Warteschlange und verarbeitet sie außerhalb des Bandes. Die richtige Wahl hängt davon ab, ob der Benutzer auf die Antwort wartet.
5.1 Synchron: Zusammenfassung bei der Erstellung
Wenn der Benutzer eine Aufgabe einreicht und die Zusammenfassung sofort zurück erwartet, rufen Sie Inference im Anfrage-Handler auf und schreiben Sie die Zusammenfassung in derselben Transaktion in PostgreSQL.
def create_task(db, description: str) -> int:
summary = safe_summary(description)
row = db.execute(
"INSERT INTO tasks (description, summary) VALUES (%s, %s) RETURNING id",
(description, summary),
).fetchone()
db.commit()
return row[0]
Halten Sie den synchronen Pfad hinter einem Timeout und einem Wiederholungsbudget, damit ein langsames Modell die nutzerseitige Anfrage nicht endlos blockiert.
5.2 Asynchron: Inferenz über Kafka in die Warteschleife stellen
Wenn die Zusammenfassung nicht sofort benötigt wird, entkoppeln Sie sie. Die API schreibt die Aufgabe sofort und erzeugt ein Aufgabenänderungsereignis in Kafka (siehe Einheit 4.3); ein Worker konsumiert das Ereignis, ruft die Inferenz auf und aktualisiert die Zeile. Dadurch bleibt die Erstellungsanfrage schnell und trennt die Inferenzlatenz sowie die Ratenbeschränkungen vom Nutzerpfad.
def handle_event(event: dict, db): # worker side: consume task event, summarize, persist
task_id = event["task_id"]
description = event["description"]
try:
summary = safe_summary(description)
except (ValueError, RuntimeError):
# route to a dead-letter topic; do not block the consumer group
produce_dead_letter(event)
return
db.execute("UPDATE tasks SET summary = %s WHERE id = %s", (summary, task_id))
db.commit()
Das asynchrone Muster glättet auch Lastspitzen: Die Beschränkung auf 5 Anfragen pro Sekunde ist deutlich leichter einzuhalten, wenn ein einzelner Verbraucher eine Warteschlange mit einer kontrollierten Rate abarbeitet, als wenn viele Web-Worker Inference-Aufrufe gleichzeitig ausführen.
5.3 Zwischenspeichern von Ergebnissen in Redis
Inference ist der aufwendigste Aufruf in dieser Funktion, daher sollten Sie nicht zweimal dafür bezahlen. Zwischenspeichern Sie die Ergebnisse anhand eines Hashes aus dem Modell und der Eingabe. Identische Beschreibungen verursachen nach dem ersten Aufruf keine weiteren Kosten. Dies passt nahtlos zu der bestehenden In-Memory DB (Redis)-Zwischenspeicher von TaskBoard aus Einheit 4.1.
import hashlib
import redis
r = redis.Redis(host="taskboard-redis", port=6379, ssl=True)
def cached_summary(description: str) -> str:
key = "sum:" + hashlib.sha256(
(SUMMARY_MODEL + "|" + description).encode()
).hexdigest()
hit = r.get(key)
if hit:
return hit.decode()
summary = safe_summary(description)
r.set(key, summary, ex=86400) # 24h TTL
return summary
Da die Inferenz zustandslos ist und Prompts sowie Ausgaben am Ende jeder Sitzung verworfen werden, ist die einzige dauerhafte Aufzeichnung eines Ergebnisses diejenige, die Sie bewusst aufbewahren. Caching ist daher sowohl ein Kostentreiber als auch Ihr Speicher für berechnete Ergebnisse.
5.4 Datenresidenz und Datenschutz
AI Model Hub funktioniert als zustandsloser Dienst: Prompts und Ausgaben werden am Ende jeder Sitzung verworfen, nicht protokolliert oder aufgezeichnet und nicht für das Training von Modellen wiederverwendet. Kundendaten werden unter keinen Umständen für das Training verwendet. Alle AI Model Hub-Dienste, einschließlich der Modell-Inferenz-Endpunkte und der verwalteten Vektordatenbanken, werden in ISO 27001-zertifizierten Rechenzentren in Deutschland gehostet, und die Verarbeitung ist vollständig DSGVO-konform. Für TaskBoard bedeutet dies, dass für die Zusammenfassung gesendete Aufgabenbeschreibungen innerhalb der deutschen Rechenzentrumsgrenze verbleiben und niemals in einen Trainingsdatensatz einfließen.
5.5 Nur-Lese-Agenten-Zugriff mit dem IONOS CLOUD MCP Server
Wenn die benötigte Integration nicht darin besteht, ein Modell aufzurufen, sondern einen KI-Agenten die IONOS CLOUD-Infrastruktur inspizieren zu lassen, ist der IONOS CLOUD MCP Server der für Entwickler vorgesehene Weg. Es handelt sich um ein lokales Binary, das das Model Context Protocol (MCP) implementiert und JSON-RPC über stdio mit einem KI-Client oder autonomen Agenten spricht. Es gewährt diesem Client nur-Lese-Zugriff auf über 100 Tools in sechs Produkten: Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Billing und Activity Log. Die Tools sind nach dem Entwurf ausschließlich zur Inspektion bestimmt, sodass das Binary keine Ressourcen erstellen, aktualisieren oder löschen kann.
Der MCP Server ist eine Alternative zum manuellen Aufbau eigener direkter API- oder SDK-Aufrufe für agentische und automatisierte Lese-Szenarien. Anstatt Client-Code für jede Produkt-API zu schreiben, führen Sie das Binary als lokalen Unterprozess aus; der KI-Client erkennt die Tools und ruft sie in einer agentischen Schleife auf, und das Binary ruft die IONOS CLOUD API direkt über HTTPS mit Ihrem API-Token auf. Für vollständig souveräne Workflows wird er mit AI Model Hub kombiniert, sodass sowohl der Inferenzschritt als auch der Infrastruktur-Inspektionschritt innerhalb des IONOS CLOUD-Umfangs verbleiben. Behandeln Sie die Tool-Ausgaben als Daten, die den Umfang verlassen, sobald der KI-Client sie liest.
Schnellreferenz für die API
Wichtige API-Endpunkte für die Integration mit AI Model Hub:
| Methode | Endpunkt | Beschreibung |
|---|---|---|
GET |
/v1/models |
Verfügbare Modelle und deren Details auflisten |
POST |
/v1/chat/completions |
Chat-Vervollständigung generieren (stream für Streaming festlegen) |
POST |
/v1/embeddings |
Embedding-Vektoren für Eingabetext generieren |
POST |
/v1/images/generations |
Bilder aus einem Textprompt generieren |
Basis-URL (OpenAI-kompatibel): https://openai.inference.de-txl.ionos.com/v1
Natives API-Dokumentation: https://api.ionos.com/docs/inference-modelhub/v1
Authentifizierung: Authorization: Bearer <IONOS_API_TOKEN> (JWT mit exp-Anspruch)
Code-Labor
Ziel: Fügen Sie TaskBoard eine KI-gestützte Zusammenfassungsfunktion hinzu. Rufen Sie AI Model Hub auf, um eine Aufgabenbeschreibung zusammenzufassen, behandeln Sie einen 429-Fehler mit Backoff und cachen Sie das Ergebnis in Redis, damit eine wiederholte Zusammenfassung keine Token kostet.
Voraussetzungen:
- IONOS CLOUD-Konto mit einem API-Token (JWT) in
IONOS_API_TOKEN - Python 3.10+ mit
pip install openai requests redis - Eine erreichbare Redis-Instanz (oder ein lokales
redisfür das Labor)
Schritt 1: Token exportieren und Konnektivität bestätigen
export IONOS_API_TOKEN="your-jwt-token"
curl -s https://openai.inference.de-txl.ionos.com/v1/models \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" | python3 -m json.tool | head
Erwartete Ausgabe:
{
"object": "list",
"data": [
{ "id": "meta-llama/Llama-3.3-70B-Instruct", ... }
Schritt 2: Ersten Zusammenfassungsaufruf ausführen
from openai import OpenAI
import os
client = OpenAI(base_url="https://openai.inference.de-txl.ionos.com/v1",
api_key=os.environ["IONOS_API_TOKEN"])
c = client.chat.completions.create(
model="mistralai/Mistral-Small-24B-Instruct",
messages=[{"role": "user", "content": "Summarize in one sentence: registry token expired so the deploy failed."}],
max_tokens=60, temperature=0.2)
print(c.choices[0].message.content)
print("tokens:", c.usage.total_tokens)
Erwartete Ausgabe:
The deployment failed because the container registry token had expired.
tokens: 41
Schritt 3: Retry-on-429 mit exponentiellem Backoff hinzufügen
import time, requests, os
BASE="https://openai.inference.de-txl.ionos.com/v1"
def call(payload, attempts=5):
delay=1.0
for _ in range(attempts):
r=requests.post(f"{BASE}/chat/completions",
headers={"Authorization":f"Bearer {os.environ['IONOS_API_TOKEN']}"},
json=payload, timeout=30)
if r.status_code==429:
time.sleep(float(r.headers.get("Retry-After", delay))); delay*=2; continue
r.raise_for_status(); return r.json()
raise RuntimeError("rate-limited")
Erwartete Ausgabe: Bei einem normalen Aufruf tritt kein Fehler auf; ein 429 löst ein Warten und einen erneuten Versuch aus, anstatt eines Absturzes.
Schritt 4: Die Antwort vor der Verwendung validieren
def summary(text):
data=call({"model":"mistralai/Mistral-Small-24B-Instruct",
"messages":[{"role":"user","content":text}],"max_tokens":60})
out=(data["choices"][0]["message"]["content"] or "").strip()
if not out: raise ValueError("empty summary")
return out
print(summary("The CI job failed on the embeddings step."))
Erwartete Ausgabe:
The CI job failed during the embeddings step.
Schritt 5: Ergebnisse in Redis zwischenspeichern
import hashlib, redis
r=redis.Redis(host="localhost", port=6379)
MODEL="mistralai/Mistral-Small-24B-Instruct"
def cached(text):
k="sum:"+hashlib.sha256((MODEL+"|"+text).encode()).hexdigest()
hit=r.get(k)
if hit: return hit.decode()
s=summary(text); r.set(k, s, ex=86400); return s
Schritt 6: Überprüfen, ob der Cache die Kosten des zweiten Aufrufs eliminiert
import time
t=time.time(); cached("Same description here."); print("miss", round(time.time()-t,2))
t=time.time(); cached("Same description here."); print("hit ", round(time.time()-t,2))
Erwartete Ausgabe:
miss 0.9
hit 0.0
Schritt 7: Ein Embedding für die semantische Suche generieren
e=client.embeddings.create(model="BAAI/bge-m3", input="Fix the expired registry token")
print(len(e.data[0].embedding))
Erwartete Ausgabe:
1024
Prüfliste:
- [ ]
/v1/modelsgibt eine Modellliste mit Ihrem Token zurück - [ ] Eine Chat-Antwort gibt Inhalte und eine
usageToken-Anzahl zurück - [ ] Ein 429-Code löst Backoff und erneuten Versuch aus, statt einer Ausnahme
- [ ] Eine wiederholte Zusammenfassung wird aus Redis bereitgestellt, ohne Token-Kosten
- [ ]
BAAI/bge-m3gibt einen Vektor mit 1024 Dimensionen zurück
Aufräumen:
redis-cli --scan --pattern 'sum:*' | xargs -r redis-cli del
Häufige Fehler
Fehler von Entwicklerinnen und Entwicklern, die bei der Integration von AI Model Hub vermieden werden sollten:
-
429 als schwerwiegender Fehler behandeln
- Problem: Ein Anstieg der TaskBoard-Aktivität führt zu
HTTP 429 Too Many Requests, und Ihr Handler bricht ab, wodurch Benutzeranfragen fehlschlagen. - Ursache: Das allgemeine API-Ratenlimit beträgt 5 Anfragen pro Sekunde (Basis) mit einem Burst von 10; parallele Web-Worker überschreiten diesen Wert leicht.
- Lösung: 429 abfangen,
Retry-Aftereinhalten und mit exponentiellem Backoff erneut versuchen. Inference auf einen Worker verschieben, der von Kafka entleert wird, um die Parallelität zu steuern.
- Problem: Ein Anstieg der TaskBoard-Aktivität führt zu
-
Abgelaufenes JWT als Codefehler missverstehen
- Problem: Aufrufe, die gestern noch funktioniert haben, geben heute einen Authentifizierungsfehler zurück, und Sie beginnen, Header und Payloads zu debuggen.
- Ursache: Das Bearer-Token ist ein JWT mit einem
exp-Claim und einem festen Ablaufdatum. Nach Ablauf schlägt jeder Aufruf bei der Authentifizierung fehl. - Lösung: Den
exp-Claim des Tokens dekodieren und das Token bei Ablauf neu generieren. Authentifizierungsfehler zunächst als Token-Lebenszyklus-Prüfung behandeln, nicht als Fehler im Anfrageformat.
-
Inference synchron aufrufen und für Duplikate bezahlen
- Problem: Latenzspitzen bei der Task-Erstellung und steigende Token-Kosten, weil identische Beschreibungen wiederholt zusammengefasst werden.
- Ursache: Inference läuft im Anfragepfad ohne Caching ab, sodass dieselbe Eingabe jedes Mal Token-Kosten verursacht.
- Lösung: Nach einem Hash aus Modell plus Eingabe in Redis mit TTL cachen und nicht dringende Zusammenfassungen an einen asynchronen Kafka-Worker verschieben, damit die Erstellungsanfrage schnell bleibt.
Zusammenfassung
Sie können AI Model Hub nun in Anwendungscode integrieren. Sie rufen den OpenAI-kompatiblen Endpunkt unter https://openai.inference.de-txl.ionos.com/v1 mit einem Bearer JWT auf, steuern ihn aus requests oder dem offiziellen OpenAI-Client, streamen, wenn die UI es benötigt, und generieren Embeddings mit BAAI/bge-m3. Sie wählen Modelle anhand des Kontextfensters und des Preises pro Token aus, und Sie kapseln jeden Aufruf mit Timeout, 429-Backoff und Antwortvalidierung. Sie haben die Funktion in TaskBoard sowohl synchron als auch über einen Kafka-gepufferten Worker eingebunden, und Sie cachen Ergebnisse in Redis, damit wiederholte Eingaben nichts kosten.
Wichtige Punkte:
- Die OpenAI-kompatible API unter
/v1/chat/completions,/v1/embeddings,/v1/modelsund/v1/images/generationsermöglicht es dem offiziellen OpenAI-Client zu funktionieren, indembase_urlundapi_keyüberschrieben werden - Die Authentifizierung erfolgt über ein Bearer JWT in
IONOS_API_TOKEN; ein abgelaufenerexp-Claim ist die häufigste Ursache für plötzliche Authentifizierungsfehler - Das allgemeine Ratenlimit beträgt 5 Anfragen pro Sekunde Basis, 10 Burst; bei Überschreitung wird HTTP 429 zurückgegeben, was Sie mit
Retry-Afterund exponentiellem Backoff behandeln - Die Modellwahl ist eine Kostenentscheidung: Alle drei Chat-Modelle teilen ein 128000-Token-Kontextfenster, daher unterscheidet sich der Preis, wobei
mistralai/Mistral-Small-24B-Instructdas günstigste ist - Der Dienst ist zustandslos und in Deutschland gehostet; Prompts und Ausgaben werden pro Sitzung verworfen und nie für das Training verwendet, daher ist Redis-Caching sowohl Ihr Kostentreiber als auch Ihr einziger dauerhafter Speicher für Ergebnisse
- Der IONOS CLOUD MCP Server ist ein lokales Binary, das KI-Agenten read-only-Zugriff auf über 100 Tools in Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Billing und Activity Log über MCP (JSON-RPC auf stdio) gewährt; er ist eine Alternative zu direkten API- oder SDK-Aufrufen für agentische Lese-Szenarien und wird mit AI Model Hub für souveräne Workflows kombiniert
Wichtige Begriffe:
- OpenAI-kompatible API: Ein Endpunkt, der die Anfrage- und Antwortstruktur von OpenAI spiegelt, sodass OpenAI-SDKs gegen IONOS CLOUD funktionieren, indem die Basis-URL und der Schlüssel geändert werden
- Kontextfenster: Die maximale Anzahl an Tokens (Prompt plus Vollendung), die ein Modell in einer Anfrage akzeptiert; 128000 für die Chat-Modelle in dieser Einheit
- Token-basierte Preisgestaltung: Kosten, die pro Million Eingabe- und Ausgabetoken berechnet werden; verfolgt über das
usage-Objekt in jeder Antwort - Exponentielles Backoff: Eine Wiederholstrategie, die die Wartezeit zwischen Versuchen nach einem 429 verdoppelt, um einen thundering-herd-Wiederholungssturm zu verhindern
- Zustandslose Inferenz: Jede Anfrage steht für sich; AI Model Hub verwirft Prompts und Ausgaben am Ende der Sitzung und protokolliert, speichert oder trainiert nicht darauf
- IONOS CLOUD MCP Server: Ein lokales Binary, das das Model Context Protocol (JSON-RPC über stdio) implementiert und read-only-Inspektionstools über sechs IONOS CLOUD-Produkte für einen KI-Client bereitstellt, wobei die IONOS CLOUD API direkt aufgerufen wird, ohne einen Drittanbieter-KI-Anbieter im Datenpfad
Nächste Schritte
Weiter lernen: Einheit 4.5: Wissensprüfung - Service Integration
Verwandte Themen: