Skip to main content

Python

Because Serenity* Star exposes OpenAI-compatible endpoints for its self-hosted inference models, you can drive them with the official openai Python package. There is no Serenity-specific SDK to install, and once the client is configured everything else (streaming, client tools) works exactly as it does against OpenAI.

For more information about request and response shapes for the inference OpenAI-compatible endpoints, see the REST API reference.

Install

pip install openai

Configure the client

Two things differ from a plain OpenAI setup:

  • base_url must point at the inference path, including the model (for example .../inference/qwen/qwen3.6). With it set, the SDK appends /chat/completions and /responses for you. Because the model lives in the URL, a client instance talks to a single model. To call a different model, create another client with that model's path.
  • A User-Agent header is required by the Serenity* Star API, and the OpenAI SDK does not send one. Set it yourself via default_headers, otherwise the request fails with a 403 Forbidden.

Your Serenity API key goes in api_key; the bearer form is accepted, so it is sent as Authorization: Bearer YOUR_API_KEY.

from openai import OpenAI

client = OpenAI(
base_url="https://api.serenitystar.ai/api/v2/inference/qwen/qwen3.6",
api_key="YOUR_API_KEY",
default_headers={"User-Agent": "mySerenityClient/1.0"}, # required
)

Selecting the model

Unlike AIProxy, inference selects the model through the URL path, not through the model field in the request body:

/api/v2/inference/{model}/chat/completions
/api/v2/inference/{model}/responses

{model} must be one of the inference models enabled on your instance (for example qwen/qwen3.6, qwen/qwen3.6-35b-a3b, or qwen/qwen3.6-27b). The OpenAI SDK still requires a model argument on each call, but it is ignored — the path always wins. Set it to the same value to keep things clear.

See the REST API reference for the full rules.

Examples

Simple request

response = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=5000,
messages=[
{"role": "user", "content": "Hello! Tell me a fun fact about Valencia."},
],
)

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

Function calling

Inference supports client tools — standard OpenAI function calling: the model asks for a function, you run it, and you send the result back for the model to finish its answer. (Server tools such as web search or image generation are not available, because there is no agent in front of the model.)

tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "The city name"},
},
"required": ["city"],
},
},
}
]

messages = [
{"role": "user", "content": "What is the weather like in Paris right now? Use the tool."},
]

# Step 1 — the model requests the tool.
first = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=512,
messages=messages,
tools=tools,
)

tool_call = first.choices[0].message.tool_calls[0]

# Step 2 — run the function and send the result back.
messages.append(first.choices[0].message)
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": '{"city":"Paris","temperature_c":18,"condition":"light rain","humidity":72}',
}
)

second = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=512,
messages=messages,
tools=tools,
)

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