Zum Hauptinhalt springen

Python-Beispiele

Die Nutzung der Modelle innerhalb von Programmiersprachen kann komfortabel über bestehende Libraries stattfinden, welche die OpenAI-API unterstützen. Somit kann mittwalds AI-Hosting in vielen Fällen als Drop-In-Replacement genutzt werden.

Für die folgenden Beispiele müssen zunächst über einen Python-Paketmanager die Libraries installiert werden und der im mStudio generierte API-Key in einer .env-Datei hinterlegt werden:

pip install python-dotenv openai langchain-openai
echo 'OPENAI_API_KEY="sk-…"' > .env

Anschließend kann über das OpenAI-Paket ein Modell angesprochen werden:

from openai import OpenAI
from dotenv import load_dotenv

# Load .env file
load_dotenv()

# Initialize client with custom host and key from environment
client = OpenAI(
base_url="https://llm.aihosting.mittwald.de/v1"
)

# Make a simple call
response = client.chat.completions.create(
model="Ministral-3-14B-Instruct-2512",
temperature = 0.15,
messages=[
{"role": "user", "content": "Moin und hallo!"}
]
)

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

Alternativ kann auch langchain verwendet werden:

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

# Load .env file
load_dotenv()

# Initialize client with custom host and key from environment
chat = ChatOpenAI(
model="Ministral-3-14B-Instruct-2512",
base_url="https://llm.aihosting.mittwald.de/v1",
temperature = 0.15
)

# Get response
response = chat.invoke([
HumanMessage(content="Moin and hello!")
])

print(response.content)

Vision (Bild + Text)

Die Vision-Modelle auf mittwald AI Hosting akzeptieren Bilder ausschließlich als Base64-kodierte Data-URLs. Das Senden von Bild-URLs wird nicht unterstützt und führt zu einem Serverfehler.

Bilder kodieren und verkleinern

Installiere Pillow für die Bildverarbeitung:

pip install Pillow

Immer vor dem Senden verkleinern. Große Bilder erhöhen die Wartezeit bis zum ersten Token (TTFT) erheblich. Eine maximale Kantenlänge von 1024 px ist ein sicherer Standardwert, der für die meisten Aufgaben ausreichend Qualität liefert:

import base64
import io
from PIL import Image

def encode_image(path: str, max_px: int = 1024) -> str:
"""Bild auf max_px an der längsten Seite skalieren und als Base64-Data-URL zurückgeben."""
with Image.open(path) as img:
w, h = img.size
scale = min(1.0, max_px / max(w, h))
if scale < 1.0:
img = img.resize((int(w * scale), int(h * scale)), Image.LANCZOS)
buf = io.BytesIO()
img.save(buf, format="JPEG", quality=85)
b64 = base64.b64encode(buf.getvalue()).decode()
return f"data:image/jpeg;base64,{b64}"

Eine Vision-Anfrage stellen

from openai import OpenAI

client = OpenAI(base_url="https://llm.aihosting.mittwald.de/v1")

resp = client.chat.completions.create(
model="Ministral-3-14B-Instruct-2512",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Beschreibe dieses Bild detailliert."},
{"type": "image_url", "image_url": {"url": encode_image("foto.jpg")}},
]
}],
temperature=0.1,
max_tokens=512,
)
print(resp.choices[0].message.content)

Modell auswählen

ModellMax. BilderStärken
Qwen3.5-122B-A10B-FP820+Beste Genauigkeit, OCR, komplexe Szenen
Ministral-3-14B-Instruct-25124Ausgewogenes Verhältnis von Geschwindigkeit und Qualität
Qwen3.6-35B-A3B-FP85+Schnell bei wiederholten Anfragen
Devstral-Small-2-24B-Instruct-25124Code-Workflows mit Bildern

Bei Qwen-Modellen sollte der Thinking-Modus deaktiviert werden, um unnötigen Overhead zu vermeiden:

resp = client.chat.completions.create(
model="Qwen3.5-122B-A10B-FP8",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Extrahiere den gesamten Text aus diesem Dokument."},
{"type": "image_url", "image_url": {"url": encode_image("dokument.jpg")}},
]
}],
temperature=0.7,
max_tokens=1024,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
print(resp.choices[0].message.content)

Tool-Calling (Function Calling)

from openai import OpenAI
client = OpenAI(base_url="https://llm.aihosting.mittwald.de/v1")

tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Aktuelles Wetter abrufen",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}
]

resp = client.chat.completions.create(
model="Devstral-Small-2-24B-Instruct-2512",
messages=[{"role": "user", "content": "Wie ist das Wetter in Berlin?"}],
tools=tools,
tool_choice="auto"
)

# Prüfen, ob das Modell ein Tool aufgerufen hat
if resp.choices[0].message.tool_calls:
call = resp.choices[0].message.tool_calls[0]
print(f"Funktion: {call.function.name}")
print(f"Argumente: {call.function.arguments}")

Streaming-Antworten

from openai import OpenAI
client = OpenAI(base_url="https://llm.aihosting.mittwald.de/v1")

stream = client.chat.completions.create(
model="Devstral-Small-2-24B-Instruct-2512",
messages=[{"role": "user", "content": "Schreibe ein kurzes Gedicht über das Programmieren"}],
stream=True
)

for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)