Zum Hauptinhalt springen

Chat, Streaming, Tool Calling

Chat geht über zwei Endpunkte: /v1/chat/completions im OpenAI-Format und /v1/messages im Anthropic-Format. Beide nehmen dieselben Modelle aus der Modellliste (Kategorie Chat).

Streaming​

Beide Endpunkte streamen per Server-Sent Events, wenn du "stream": true setzt.

curl -N https://api.openhippo.io/v1/chat/completions \
-H "Authorization: Bearer $OPENHIPPO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openhippo/gpt-oss-120b",
"stream": true,
"messages": [{"role": "user", "content": "Explain SSE in two sentences."}]
}'

Tool Calling​

Tool Calling (Function Calling) im OpenAI-Format ist in unseren Tests abgedeckt für:

  • selbst gehostet: openhippo/Qwen3-VL-30B-A3B-Instruct (hippo-vision), openhippo/Qwen3.8-27B (hippo-coding), openhippo/gpt-oss-120b (hippo-chat-large),
  • Partner: aki-io/glm5.3-754b, aki-io/qwen3.6-35b, aki-io/deepseek-v4.1-flash-552b, mistral/mistral-large-4, mistral/glm-5.3, telekom/glm-5.2, telekom/qwen3.6-35b, tensorx/glm-5.3-flash, tensorx/kimi-k3, tensorx/deepseek-v4-pro.

Getestet sind einfache Aufrufe, mehrere Tools zur Auswahl und Streaming mit Tools, jeweils mit tool_choice: "auto".

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.openhippo.io/v1", api_key=os.environ["OPENHIPPO_API_KEY"])

tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]

messages = [{"role": "user", "content": "What is the weather in Augsburg?"}]
response = client.chat.completions.create(model="openhippo/gpt-oss-120b", messages=messages, tools=tools)
message = response.choices[0].message

if not message.tool_calls:
print(message.content) # answered without a tool
else:
messages.append(message)
for call in message.tool_calls:
args = json.loads(call.function.arguments)
print(call.function.name, args)
result = {"city": args.get("city"), "temp_c": 14} # your tool's result
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
final = client.chat.completions.create(model="openhippo/gpt-oss-120b", messages=messages, tools=tools)
print(final.choices[0].message.content)

Ob das Modell ein Tool aufruft, entscheidet es selbst; das Beispiel prüft deshalb tool_calls, bevor es darauf zugreift.

Noch nicht dokumentiert: andere tool_choice-Werte als "auto" (z. B. ein erzwungenes Tool oder "none") und parallele Tool-Aufrufe (parallel_tool_calls). Fragen: support@openhippo.io.

Bilder​

Bilder verstehen nur Modelle der Kategorie Vision (siehe Modelle). Das Bild geht als image_url mit, entweder als URL oder als Data-URI (data:image/png;base64,...):

import base64, os
from openai import OpenAI

client = OpenAI(base_url="https://api.openhippo.io/v1", api_key=os.environ["OPENHIPPO_API_KEY"])

with open("photo.jpg", "rb") as f:
image = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
model="hippo-vision",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "What is in this picture?"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image}"}},
],
}],
)
print(response.choices[0].message.content)

Einige Modelle ohne eigenes Bildverständnis haben einen Alias mit der Endung -vision. Dort beschreibt ein Vision-Modell desselben Anbieters das Bild zuerst; dieser Beschreibungsschritt wird zusätzlich abgerechnet. Welches Modell beschreibt: Vision-Aliase.

OCR​

Texterkennung läuft über Chat Completions mit dem Modell openhippo/GLM-OCR und einem Bild pro Request. Das Bild geht als URL oder als Data-URI mit:

import base64, os
from openai import OpenAI

client = OpenAI(base_url="https://api.openhippo.io/v1", api_key=os.environ["OPENHIPPO_API_KEY"])

with open("invoice.png", "rb") as f:
image = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
model="openhippo/GLM-OCR",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Output the text of this document."},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image}"}},
],
}],
)
print(response.choices[0].message.content)

Reasoning​

reasoning_effort (OpenAI-Format) und thinking (Anthropic-Format) werden auf die Stufen des jeweiligen Modells abgebildet.

Für hippo-coding gilt:

  • Stufen low, medium, xhigh; Standard ist xhigh.
  • Andere Werte werden auf die nächsthöhere Stufe gerundet (z. B. high → xhigh).
  • "none" schaltet das Reasoning aus.
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.openhippo.io/v1", api_key=os.environ["OPENHIPPO_API_KEY"])

response = client.chat.completions.create(
model="hippo-coding",
reasoning_effort="low",
messages=[{"role": "user", "content": "Write a Python function that checks for primes."}],
)
print(response.choices[0].message.content)

Bekannte Grenzen​

  • Unbekannte Parameter werden stillschweigend verworfen, statt einen Fehler zu erzeugen.
  • Tool Calling ist nur für die oben genannten Modelle getestet.
  • OCR mit openhippo/GLM-OCR: ein Bild pro Request, siehe OCR.
  • /v1/responses unterstützt nur das Anlegen einer Antwort, kein Abrufen oder Löschen.