18 Min. Lesezeit

Lernziele

Am Ende dieses Moduls werden Sie in der Lage sein:

  • Sich gegen den AI Model Hub-Inferenz-Endpunkt mit einem Bearer-Token zu authentifizieren und Chat-Vervollständigungen von Python und curl auszuführen
  • AI Model Hub in Anwendungscode zu integrieren, indem Sie den OpenAI-kompatiblen API und den offiziellen OpenAI-Python-Client verwenden, der auf die IONOS-Grund-URL zeigt
  • Mit `BAAI/bge-m3`-Einbettungen zu generieren und das richtige Modell nach Kontextfenster und pro-Token-Preis auszuwählen
  • Eine Produktionsfehlerbehandlung für HTTP-Rate-Limits, Timeouts und fehlerhafte Antworten mit exponentiellem Backoff zu implementieren
  • Ein synchrones und ein asynchrones (Kafka-gesteuertes) Inferenzmuster zu erstellen und Ergebnisse in Redis zu cachen, um die Tokenkosten zu kontrollieren

Einheit 4.4: AI Model Hub-Integration

Einführung

Sie fügen eine KI-Funktion zu TaskBoard hinzu: Wenn ein Benutzer eine lange Aufgabenbeschreibung einreicht, ruft das API ein großes Sprachmodell auf, um eine einzeilige Zusammenfassung zu erstellen, und speichert diese Zusammenfassung dann in PostgreSQL. Das AI Model Hub stellt gehostete Modelle hinter einem OpenAI-kompatiblen REST API bereit, sodass Sie keine GPUs ausführen und keine Modellgewichte verwalten. Sie senden einen Prompt an einen Inferenz-Endpunkt, erhalten Token zurück und zahlen pro Token.

Diese Einheit beginnt beim HTTP-Aufruf. Sie werden die exakten Anforderungs- und Antwortformen sehen, diese in Python mit beiden requests und dem OpenAI-Client verbinden, die Wiederholungs- und Zeitüberschreitungslogik hinzufügen, die die Produktionsinferenz benötigt, und dann die Funktion mit dem REST von TaskBoard über synchrone Aufrufe und einen Kafka-gesteuerten asynchronen Pfad verbinden. Jedes Code-Block zielt auf den realen IONOS-Endpunkt und reale Modell-Identifikatoren ab, sodass Sie kopieren, Ihr Token einstellen 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-Tooling und SDKs durch Ändern nur der Basis-URL und der Anmeldedaten wiederverwenden können. Für die Anwendungsintegration ist dies der gewünschte Pfad, da die Anfrage- und Antwortformen bereits vertraut sind und die offiziellen OpenAI-Client-Bibliotheken unverändert funktionieren.

Die OpenAI-kompatible Basis-URL ist https://openai.inference.de-txl.ionos.com/v1. Die Authentifizierung verwendet ein Bearer-Token, das ein JSON-Web-Token (JWT) mit einem Ablaufdatum ist. Die AI Model Hub-Anleitungen gehen davon aus, dass das Token in der IONOS_API_TOKEN-Umgebungsvariable gespeichert ist. Da das Token ein JWT mit einem exp-Anspruch ist, bedeutet ein Request, der plötzlich einen Authentifizierungsfehler zurückgibt, normalerweise, dass das Token abgelaufen ist und nicht, dass der Aufruf falsch ist. Überprüfen Sie den exp-Anspruch und erzeugen Sie das Token neu, wenn es abgelaufen ist.

1.1 Erster Aufruf mit curl

Senden Sie eine Chat-Vervollständigung, um Ihr Token und die Konnektivität zu bestätigen, bevor Sie Anwendungscode schreiben. Der Endpunkt ist POST /v1/chat/completions und der Anforderungstext enthält eine model-Identifikator 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-Stil-Vervollständigungsobjekt. Der generierte Text ist in choices[0].message.content, und usage berichtet 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 Auflisten verfügbarer Modelle

Die OpenAI-kompatible API stellt einen Modelle-Endpunkt bereit, um die Liste der verfügbaren Modelle und deren Details abzurufen. Verwenden Sie ihn, um die exakten Modell-Identifikator-Zeichenfolgen zu entdecken, anstatt eine Vermutung hart zu codieren, da die Identifikator die model-Feld erfordert.

curl -s https://openai.inference.de-txl.ionos.com/v1/models \
  -H "Authorization: Bearer ${IONOS_API_TOKEN}" | python3 -m json.tool

Der Modell-Identifikator, den Sie übergeben, muss dem Katalog genau entsprechen. Für die Chat-Modelle, die in dieser Einheit verwendet werden, sind die Identifikatoren meta-llama/Llama-3.3-70B-Instruct, openai/gpt-oss-120b und mistralai/Mistral-Small-24B-Instruct. Ein Tippfehler in der Identifikator ist einer der häufigsten ersten Aufruf-Fehler.

2. Aufruf des Model Hub aus Anwendungscode

In TaskBoards API-Dienst rufen Sie die Inferenz aus Python auf. Sie haben zwei saubere Optionen: Steuern Sie den HTTP API direkt mit requests oder verwenden Sie den offiziellen openai-Client, der auf die IONOS-Base-URL zeigt. Beide treffen den gleichen Endpunkt. Der requests-Pfad hält die Abhängigkeiten minimal; der OpenAI-Client bietet Ihnen typisierte Helfer, Streaming-Iteratoren und Wiederholungshooks kostenlos.

2.1 Direkter HTTP mit Anfragen

Dies ist die Integration mit den geringsten Abhängigkeiten. Es ist auch die klarste Möglichkeit, genau zu sehen, was über das Netzwerk übertragen wird, was hilft, wenn Sie debuggen.

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 eine explizite timeout. Die Inferenzlatenz variiert mit der Länge des Prompts und der Größe des Modells, und ein hängender Socket ohne Timeout wird einen Worker-Thread in Ihrem API blockieren.

2.2 Der OpenAI-Client, der auf IONOS zeigt

Da der 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 als sie generiert werden streamen, indem Sie stream auf true setzen. Wenn Sie streamen, sind die Nutzungsstatistiken standardmäßig nicht enthalten. Um die Nutzungsstatistiken im letzten Chunk zu erhalten, müssen Sie stream_options mit include_usage aktiviert explizit 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 Tokenzahlen, die Sie für die Kostenrechnung benötigen.

3. Auswahl eines Modells: Kontextfenster und Preis

Die Modellauswahl ist eine Entscheidung, die von zwei Zahlen getrieben wird: wie viele Token das Modell akzeptiert (Kontextfenster) und was jedes Million Token kostet. TaskBoard-Zusammenfassungen sind kurz, daher ist das günstigste geeignete Modell die richtige Voreinstellung. Größere Modelle sollten für Aufgaben reserviert werden, die sie tatsächlich benötigen.

Die folgende Tabelle vergleicht die Chat-Modelle, die in dieser Einheit verwendet werden. Die Preise sind in EUR pro Million Token.

Modellkennung Kontextfenster (Token) Eingabe-Preis (EUR / 1M) Ausgabe-Preis (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 ein Kontextfenster von 128000 Token, sodass für eine kurze Zusammenfassungsanfrage der entscheidende Faktor der Preis ist. mistralai/Mistral-Small-24B-Instruct ist am günstigsten bei Eingabe und Ausgabe und ist eine vernünftige Voreinstellung für TaskBoard-Zusammenfassungen. Wechseln Sie nur zu einem größeren Modell, wenn die Zusammenfassungsqualität bei realen Aufgabenbeschreibungen nachweislich besser ist und den pro-Token-Preis wert ist.

3.1 Kostenaufwandsbewusste Modellkonfiguration

Machen Sie das Modell zu einem Konfigurationswert und nicht zu einem wörtlichen Wert, der im Code verteilt ist, damit Sie ihn ohne Neudeployment der Logik je nach Umgebung umschalten können.

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 Einbettungen für semantische Merkmale

Wenn TaskBoard eine semantische Suche über Aufgaben benötigt, generieren Sie Vektoren mit einem Einbettungsmodell anstelle eines Chat-Modells. Der Endpunkt ist POST /v1/embeddings. Das BAAI/bge-m3-Modell gibt 1024-dimensionale Vektoren zurück und kostet 0,02 EUR pro Million Token.

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 an dem Ort, an dem Ihre Suchschicht lebt. Die Einbettung ist deterministisch für eine gegebene Eingabe und ein Modell, sodass identischer Text immer den gleichen Vektor erzeugt, was Einbettungen zu einem starken Kandidaten für die Zwischenspeicherung macht.

4. Fehlerbehandlung in der Produktion

Schlussfolgerungsanrufe scheitern auf Arten, die Ihre CRUD-Endpunkte nicht tun: Das Modell ist ratenbegrenzt, die Anforderung läuft unter Last aus, oder die Antwort ist wohlgeformt JSON, aber der Inhalt ist leer oder im falschen Format. Produktionscode muss alle drei Fälle behandeln. Der wichtigste Fall bei IONOS ist die Rate-Begrenzung.

4.1 Rate-Begrenzungen und 429-Rücknahmen

Die allgemeine API-Rate-Begrenzung beträgt 5 Anfragen pro Sekunde (Basis) mit einer Burst-Erlaubnis von 10. Wenn Sie die Begrenzung überschreiten, gibt der Dienst HTTP 429 Too Many Requests zurück. Behandeln Sie 429 als Signal, um zurückzutreten und erneut zu versuchen, und nicht als harten Fehler. Verwenden Sie exponentielles Zurücktreten, damit ein Burst von TaskBoard-Aktivitäten den Endpunkt nicht belastet.

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 ihn bereitstellt, und fallen Sie auf Ihre eigene exponentielle Verzögerung zurück, wenn er nicht bereitgestellt wird. Begrenzen Sie die Anzahl der Versuche, damit ein anhaltender Ausfall als Fehler und nicht als unendliche Schleife auftritt.

4.2 Timeouts und Antwortvalidierung

Eine 200-Antwort ist keine Garantie für verwendbaren Inhalt. Das Modell kann eine leere Zeichenfolge oder Text zurückgeben, der Ihre nachgelagerten Annahmen bricht. Validieren Sie vor dem 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-Vervollständigung API ein response_format mit einem JSON-Schema und strict aktiviert, das das Modell dazu zwingt, gültige JSON-Daten auszugeben, die Ihrem Schema entsprechen. Das ist der zuverlässige Weg, um maschinenlesbare Ausgaben zu erhalten, anstatt freien Text, den Sie defensiv parsen müssen.

5. Integration Patterns und Kostenvorbehalt

Sie können die Inferenz auf zwei Arten innerhalb von TaskBoard aufrufen. Synchronisierte Inferenz läuft innerhalb der Anfrage, die das Ergebnis benötigt. Asynchrone Inferenz stellt die Arbeit in eine Warteschlange und verarbeitet sie außerhalb der Bandbreite. Die richtige Wahl hängt davon ab, ob der Benutzer auf die Antwort wartet.

5.1 Synchron: Zusammenfassung bei Erstellung

Wenn der Benutzer eine Aufgabe übermittelt und die Zusammenfassung sofort zurück erhält, rufen Sie die Inferenz innerhalb des Anfrage-Handlers auf und schreiben die Zusammenfassung in PostgreSQL in der gleichen Transaktion.

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 benutzerorientierte Anfrage nicht unbegrenzt blockiert.

5.2 Asynchron: Inferenz-Warteschlange durch Kafka

Wenn die Zusammenfassung nicht sofort benötigt wird, trennen Sie sie. Das API schreibt die Aufgabe sofort und erzeugt ein Aufgaben-Änderungsereignis zu Kafka (siehe Einheit 4.3); ein Worker verarbeitet das Ereignis, ruft die Inferenz auf und aktualisiert die Zeile. Dies hält die Erstellungsanfrage schnell und isoliert die Inferenz-Latenz und die Rate-Limits von der Benutzerpfad.

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 Spitzen: Die 5-Anfragen-pro-Sekunde-Grenze ist viel einfacher zu beachten, wenn ein einzelner Consumer eine Warteschlange mit einem kontrollierten Tempo entleert, als wenn viele Web-Worker die Inferenz gleichzeitig aufrufen.

5.3 Ergebnisse im Redis cachen

Die Inferenz ist der teuerste Aufruf in dieser Funktion, also zahlen Sie nicht zweimal dafür. Cachen Sie durch einen Hash des Modells plus der Eingabe. Identische Beschreibungen kosten dann nach dem ersten Aufruf nichts. Dies paart sich natürlich mit der bestehenden In-Memory DB-Cache (Redis) 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 die Eingaben und Ausgaben am Ende jeder Sitzung verworfen werden, ist die einzige dauerhafte Aufzeichnung eines Ergebnisses die, die Sie sich entscheiden zu speichern. Das Cachen ist daher sowohl ein Kostenvorteil als auch Ihr Speicher für berechnete Ergebnisse.

5.4 Datenresidenz und Datenschutz

AI Model Hub funktioniert als zustandsloser Dienst: Eingaben und Ausgaben werden am Ende jeder Sitzung verworfen, werden nicht protokolliert oder aufgezeichnet und werden nicht für die Modelltrainings verwendet. Kunden-Daten werden unter keinen Umständen für die Trainings verwendet. Alle AI Model Hub-Dienste, einschließlich Modell-Inferenz-Endpunkten und gemanagten Vektor-Datenbanken, werden in ISO 27001-zertifizierten Rechenzentren in Deutschland gehostet, und die Verarbeitung ist vollständig GDPR-konform. Für TaskBoard bedeutet dies, dass die Aufgabenbeschreibungen, die für die Zusammenfassung gesendet werden, innerhalb der deutschen Rechenzentrums-Grenze bleiben und nie in ein Trainingsset eingehen.

5.5 Schreibgeschützter Zugriff mit dem IONOS CLOUD MCP Server

Wenn die Integration, die Sie benötigen, nicht "ein Modell aufrufen" sondern "einen KI-Agenten auf Ihre IONOS-Infrastruktur zugreifen lassen" ist, ist der IONOS CLOUD MCP Server der Entwickler-orientierte Pfad. Es ist ein lokales Binärprogramm, das das Model-Context-Protokoll (MCP) implementiert, das JSON-RPC über stdio zu einem KI-Client oder einem autonomen Agenten spricht. Es gibt diesem Client schreibgeschützten Zugriff auf über 100 Tools in sechs Produkten: Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Billing und Activity Log. Die Tools sind von Natur aus nur für die Inspektion konzipiert, sodass das Binärprogramm keine Ressourcen erstellen, aktualisieren oder löschen kann.

Der MCP-Server ist eine Alternative zum direkten Aufruf von API- oder SDK-Aufrufen für agente- und Automatisierungs-Lese-Szenarien. Anstatt Client-Code für jedes Produkt API zu schreiben, führen Sie das Binärprogramm als lokales Unterprozess aus; der KI-Client entdeckt die Tools und ruft sie in einer agenbasierten Schleife auf, und das Binärprogramm ruft den IONOS Cloud API direkt über HTTPS mithilfe Ihres API-Tokens auf. Für vollständig souveräne Workflows paart es sich mit AI Model Hub, sodass sowohl der Inferenz-Schritt als auch der Infrastruktur-Inspektionsschritt innerhalb des IONOS-Perimeters bleiben. Behandeln Sie die Ausgaben der Tools als Daten, die den Perimeter verlassen, sobald der KI-Client sie liest.

API Referenz-Quick-Card

Wichtige API-Endpunkte für die AI Model Hub-Integration:

Methode Endpunkt Beschreibung
GET /v1/models Liste der verfügbaren Modelle und deren Details
POST /v1/chat/completions Erzeugen einer Chat-Vervollständigung (setzen von stream für Streaming)
POST /v1/embeddings Erzeugen von Einbettungsvektoren für den Eingabetext
POST /v1/images/generations Erzeugen von Bildern aus einem Text-Prompt

Basis-URL (OpenAI-kompatibel): https://openai.inference.de-txl.ionos.com/v1 Native 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 eine AI-Zusammenfassung zu TaskBoard hinzu. Rufen Sie AI Model Hub auf, um eine Aufgabenbeschreibung zusammenzufassen, behandeln Sie einen 429-Fehler mit einer Verzögerung und cachen Sie das Ergebnis in Redis, damit eine wiederholte Zusammenfassung keine Token kostet.

Voraussetzungen:

  • Ein 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 eine lokale redis für das Labor)

Schritt 1: Exportieren Sie Ihren Token und bestätigen Sie die Konnektivität

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: Führen Sie einen ersten Zusammenfassungsauftrag durch

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: Fügen Sie eine Wiederholung bei einem 429-Fehler mit exponentiellem Backoff hinzu

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: Kein Fehler bei einem normalen Aufruf; ein 429-Fehler löst eine Wartezeit und eine Wiederholung aus, anstatt zu einem Absturz zu führen.

Schritt 4: Überprüfen Sie die Antwort, bevor Sie sie verwenden

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: Cachen Sie die Ergebnisse in Redis

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 Sie, ob der Cache den zweiten Aufruf 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: Erstellen Sie eine Einbettung für die semantische Suche

e=client.embeddings.create(model="BAAI/bge-m3", input="Fix the expired registry token")
print(len(e.data[0].embedding))

Erwartete Ausgabe:

1024

Überprüfungsliste:

  • [ ] /v1/models gibt eine Modellliste mit Ihrem Token zurück
  • [ ] Eine Chat-Vervollständigung gibt Inhalt und eine usage-Tokenanzahl zurück
  • [ ] Ein 429-Fehler löst eine Verzögerung und eine Wiederholung aus, anstatt eine Ausnahme zu verursachen
  • [ ] Eine wiederholte Zusammenfassung wird aus Redis mit keinen Tokenkosten bereitgestellt
  • [ ] BAAI/bge-m3 gibt einen 1024-dimensionalen Vektor zurück

Aufräumen:

redis-cli --scan --pattern 'sum:*' | xargs -r redis-cli del

Häufige Fallstricke

Entwicklerfehler, die bei der Integration von AI Model Hub vermieden werden sollten:

  1. Ein 429-Fehler als fatalen Fehler behandeln

    • Problem: Ein Burst von TaskBoard-Aktivitäten gibt HTTP 429 Too Many Requests zurück und Ihr Handler löst aus, wodurch Benutzeranfragen fehlschlagen.
    • Warum es passiert: Die allgemeine API-Ratebegrenzung beträgt 5 Anfragen pro Sekunde (Basis) mit einem Burst von 10; gleichzeitige Web-Worker überschreiten diese leicht.
    • Lösung: Fangen Sie den 429-Fehler ab, berücksichtigen Sie Retry-After und wiederholen Sie den Versuch mit exponentiellem Backoff. Verschieben Sie die Inferenz auf einen Kafka-entlasteten Worker, um die Konkurrenz zu kontrollieren.
  2. Abgelaufenes JWT für einen Codefehler gehalten

    • Problem: Anrufe, die gestern funktioniert haben, geben heute einen Authentifizierungsfehler zurück, und Sie beginnen, Header und Payloads zu debuggen.
    • Warum es passiert: Der Bearer-Token ist ein JWT mit einem exp-Anspruch und einem festen Ablaufdatum. Wenn es verstrichen ist, schlägt jede Anrufauthentifizierung fehl.
    • Lösung: Dekodieren Sie den exp-Anspruch des Tokens und generieren Sie das Token erneut, wenn es abgelaufen ist. Behandeln Sie Authentifizierungsfehler als Token-Lebenszyklus-Prüfung zuerst, nicht als Anfrage-Formatfehler.
  3. Aufruf von Inferenz synchron und Bezahlung für Duplikate

    • Problem: Latenzsprünge bei der Aufgabenstellung und die Tokenrechnung steigt, weil identische Beschreibungen wiederholt zusammengefasst werden.
    • Warum es passiert: Die Inferenz läuft innerhalb des Anfragepfads mit keiner Zwischenspeicherung, sodass dieselbe Eingabe jedes Mal Token kostet.
    • Lösung: Zwischenspeichern Sie durch eine Hash-Funktion von Modell plus Eingabe in Redis mit einer TTL und verschieben Sie nicht dringende Zusammenfassungen auf einen asynchronen Kafka-Worker, damit die Erstellungsanfrage schnell bleibt.

Zusammenfassung

Sie können jetzt AI Model Hub in den Anwendungscode integrieren. Sie rufen den OpenAI-kompatiblen Endpunkt bei https://openai.inference.de-txl.ionos.com/v1 mit einem Bearer JWT auf, steuern ihn von requests oder dem offiziellen OpenAI-Client, streamen, wenn die Benutzeroberfläche es benötigt, und generieren Embeddings mit BAAI/bge-m3. Sie wählen Modelle nach Kontextfenster und pro-Token-Preis aus und umschließen jeden Aufruf mit Timeout, 429-Backoff und Antwortvalidierung. Sie haben die Funktion in TaskBoard sowohl synchron als auch über einen Kafka-gesteuerten Worker verdrahtet und cache Ergebnisse in Redis, sodass wiederholte Eingaben nichts kosten.

Wichtige Punkte:

  • Der OpenAI-kompatible API bei /v1/chat/completions, /v1/embeddings, /v1/models und /v1/images/generations ermöglicht es dem offiziellen OpenAI-Client zu funktionieren, indem er base_url und api_key überschreibt
  • Die Authentifizierung erfolgt durch einen Bearer JWT in IONOS_API_TOKEN; ein abgelaufener exp-Anspruch ist die häufigste Ursache für plötzliche Authentifizierungsfehler
  • Die allgemeine Rate-Limit-Begrenzung beträgt 5 Anfragen pro Sekunde Basis, 10 Burst; das Überschreiten davon gibt HTTP 429 zurück, das mit Retry-After und exponentiellem Backoff gehandhabt wird
  • Die Modellwahl ist eine Kostentscheidung: alle drei Chat-Modelle teilen ein Kontextfenster von 128000 Tokenn, sodass der Preis sie trennt, wobei mistralai/Mistral-Small-24B-Instruct der günstigste ist
  • Der Dienst ist zustandslos und in Deutschland gehostet; Prompts und Ausgaben werden pro Sitzung verworfen und nie für die Ausbildung verwendet, sodass Redis-Caching sowohl Ihr Kostenschalter als auch Ihr einziger dauerhafter Speicher für Ergebnisse ist
  • Der IONOS CLOUD MCP Server ist ein lokales Binärprogramm, das KI-Agents Lesezugriff auf über 100 Tools über Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Billing und Activity Log über MCP (JSON-RPC auf stdio) gewährt; es ist eine Alternative zu direkten API- oder SDK-Aufrufen für agente Lese-Szenarien und wird mit AI Model Hub für souveräne Workflows kombiniert

Wichtige Begriffe:

  • OpenAI-kompatibler API: Ein Endpunkt, der die Anfrage- und Antwortstruktur von OpenAI spiegelt, sodass OpenAI-SDKs gegen IONOS funktionieren, indem die Basis-URL und der Schlüssel geändert werden
  • Kontextfenster: Die maximale Anzahl von Tokenn (Prompt plus Vervollständigung), 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 Ausgabtoken berechnet werden; über das usage-Objekt in jeder Antwort nachverfolgt
  • Exponentielles Backoff: Eine Wiederholungsstrategie, die die Wartezeit zwischen den Versuchen nach einem 429 verdoppelt, um einen Thundering-Herd-Wiederholungssturm zu verhindern
  • Zustandslose Inferenz: Jede Anfrage steht allein; AI Model Hub verwirft Prompts und Ausgaben am Ende der Sitzung und loggt, speichert oder trainiert sie nicht
  • IONOS CLOUD MCP Server: Ein lokales Binärprogramm, das das Model-Context-Protokoll (JSON-RPC über stdio) implementiert und einen Lesezugriff auf sechs IONOS-Produkte für einen KI-Client ermöglicht, indem es den IONOS Cloud-API direkt ohne jeden Drittanbieter im Datenpfad aufruft

Nächste Schritte

Weiterlernen: Einheit 4.5: Wissensprüfung - Service-Integration

Verwandte Themen: