Configuration¶
The two sides¶
lazycontroller's OpenAI and AsyncOpenAI take every argument of openai.OpenAI /
openai.AsyncOpenAI, which configure the slow side, plus fast=FastConfig(...) for the
fast side: which decision model to ask, and when to trust its answer.
from lazycontroller import FastConfig, OpenAI
client = OpenAI(
api_key="...", # slow side: any openai.OpenAI argument (base_url, timeout, ...)
fast=FastConfig( # fast side: same names as openai.OpenAI, for the decision model
base_url="http://localhost:11434",
model="kev:0.8b-q8_0",
min_confidence=0.8,
),
)
The model in each call (model="gpt-6-luna") is the slow model: the one your code already uses.
FastConfig¶
| Setting | Default | Meaning |
|---|---|---|
base_url |
None |
The System One server. Without it (or client) the fast side is off. |
api_key |
None |
Key for base_url. See keys below. |
model |
None |
The decision model. None uses the server's default. |
min_confidence |
0.9 |
The fast model's answer is used only if every field's confidence reaches this; otherwise the call goes on to the slow model. See choosing it. |
enabled |
True |
False sends every call straight to the slow model. |
shadow |
False |
Ask both models, always return the slow answer, report disagreements. See shadow mode. |
on_route |
None |
Called with a Route after every intercepted call. |
client |
None |
A ready typesafe_sdk.TypeSafeClient (or AsyncTypeSafeClient) to use instead of creating one. |
FastConfig is immutable; an unknown setting raises TypeError and a min_confidence
outside 0–1 raises ValueError.
Fast model servers¶
The fast model is any server speaking the System One API:
| Server | base_url |
api_key |
Example model |
|---|---|---|---|
| TypeSafe | "https://api.typesafe.ai" |
your TypeSafe key | "jev-latest" |
| OpenRouter | "https://openrouter.ai/api" |
your OpenRouter key | "typesafe/jev-1.14" |
| Ollama (local) | "http://localhost:11434" |
none | "kev:0.8b-q8_0" |
Every server is configured the same way: there is no default, and nothing is read from the
environment, so without base_url every call goes to the slow model
(reason="disabled").
Decision models don't all support the same question types; check yours (see schemas). The state is sent as structured JSON, so servers that accept only a string state can't serve as the fast model.
Keys¶
- Fast side:
FastConfig.api_keyis sent toFastConfig.base_urland nowhere else. Environment variables such asTYPESAFE_API_KEYare not read. Local servers need no key. - Slow side: as in
openai.OpenAI(api_keyorOPENAI_API_KEY), except that a localbase_url(localhost,127.0.0.1,::1,*.localhost) needs no key. A remote server without a key raises the SDK's usual error.
Varying settings with with_fast¶
Settings live on the client, so call sites stay as they are. To change them for part of your
code, derive a copy, as with_options does for the SDK's own options:
refunds = client.with_fast(min_confidence=0.97) # a wrong answer costs more here
tagging = client.with_fast(min_confidence=0.6)
plain = client.with_fast(enabled=False) # this code path always uses the slow model
Copies share the connection to the fast model when its server and key are unchanged, and the
original client keeps its settings. with_options on a copy keeps the copy's FastConfig.
What stays the stock SDK¶
Only chat.completions.create / parse and responses.create / parse are intercepted.
Everything else (embeddings, files, models, with_raw_response, streaming, ...) is
openai itself, and an isinstance(client, openai.OpenAI) check still passes.