Cookbook
Migrate from OpenAI in 3 lines
Change base_url + api_key. Keep the rest. Done.
Last updated: 2026-05-19
Migrate from OpenAI in 3 lines
If your code calls the OpenAI API today, swapping it for siati.ai is a base_url change and an API key change. The rest of your code stays as-is.
Python (openai package)
from openai import OpenAI
# Before:
# client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
# After:
client = OpenAI(
base_url="https://api.siati.ai/v1",
api_key=os.environ["SIATI_API_KEY"],
)
resp = client.chat.completions.create(
model="apertus-70b-instruct", # change the model id
messages=[{"role": "user", "content": "Ciao"}],
)
That's it. chat.completions.create, embeddings.create, streaming, function calling — all work.
JavaScript / TypeScript (openai package)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.siati.ai/v1",
apiKey: process.env.SIATI_API_KEY,
});
const resp = await client.chat.completions.create({
model: "apertus-70b-instruct",
messages: [{ role: "user", content: "Ciao" }],
});
LangChain
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="https://api.siati.ai/v1",
api_key=os.environ["SIATI_API_KEY"],
model="apertus-70b-instruct",
)
llm.invoke("Tell me a Swiss joke.")
Works with langchain-openai >= 0.2. For embeddings:
from langchain_openai import OpenAIEmbeddings
emb = OpenAIEmbeddings(
base_url="https://api.siati.ai/v1",
api_key=os.environ["SIATI_API_KEY"],
model="bge-m3",
)
LlamaIndex
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
api_base="https://api.siati.ai/v1",
api_key=os.environ["SIATI_API_KEY"],
model="apertus-70b-instruct",
is_chat_model=True,
)
OpenAILike is the recommended class for any OpenAI-compatible third-party endpoint — that's us.
Model-name mapping
We do not silently rewrite model names. If your code says gpt-4o, it will fail with 404 model_not_found. The intentional substitutions you might want:
| OpenAI model | siati alternative | Notes |
|---|---|---|
gpt-4o, gpt-4-turbo |
apertus-70b-instruct or deepseek-r1-distill-70b or mistral-large-2 |
Apertus for IT-CH default; DeepSeek-R1 for visible reasoning; Mistral Large 2 for top quality general |
gpt-4o-mini |
qwen2.5:7b-instruct-q4_K_M |
Compact, fast, multilingual |
text-embedding-3-small/large |
bge-m3 |
1024-dim, multilingual |
whisper-1 |
(roadmap) | Coming Q2 2026 |
dall-e-3 |
(out of scope) | Not a focus area |
Tool calling (function calling)
Same shape as OpenAI. Apertus, Mistral Large 2, Qwen 72B and DeepSeek-R1 Distill all support it.
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
resp = client.chat.completions.create(
model="apertus-70b-instruct",
messages=[{"role": "user", "content": "Che tempo fa a Lugano?"}],
tools=tools,
tool_choice="auto",
)
What we don't support (yet)
- Assistants API — use our RAG endpoints instead, simpler shape.
- Batch API — coming Q2.
- Realtime / voice — roadmap, not committed.
- Image generation — out of scope (we focus on language).
Should you fully migrate or split traffic?
Mixed deployments are easy. Use OpenAI for cases that need their specific models (vision, voice) and siati.ai for everything text — same SDK, two base_url. We see customers route 70–90% of text traffic to siati once they verify quality + sovereignty.