xr-ai-models#
xr-ai-models defines typed LLM, VLM, STT, TTS, and embedding protocols and
constructs concrete clients from deployment profiles. Workers depend on those
protocols instead of hand-written HTTP or vendor SDK calls. Refer to
API Reference for exact classes, methods, fields, and defaults. Refer to
AI inference servers for server operation.
Construct a model client#
from xr_ai_models import ChatMessage, load_models_config, make_llm
config = load_models_config("yaml/models.json")
async with make_llm(config, "agent_llm") as llm:
response = await llm.chat(
[ChatMessage(role="user", content="hello")],
max_tokens=128,
enable_thinking=True,
)
print(response.content, response.reasoning)
A profile names logical roles and separates three concerns:
{
"models": {
"agent_llm": {
"category": "llm",
"adapter": {"preset": "nemotron_omni"},
"endpoint": {
"base_url": "http://localhost:8108",
"timeout": 60.0,
"readiness": "health"
},
"deployment": {"ownership": "reused", "service": "omni"}
}
}
}
adapterowns the model name, wire quirks, capabilities, default request extras, and reasoning-field normalization.endpointowns connectivity, readiness, timeouts, and environment-variable credentials.deploymenttells an orchestrator whether the process is managed, reused, or external.
Workers may load JSON or YAML. For compatibility, the loader accepts a direct
role mapping, legacy flat entries, health_check: true or health_check: false,
and kind: preset:<name>. The public role-spec classes also retain their legacy
flat constructors and read-only flat properties. Profiles shared with the
stdlib-only launcher must use the wrapped nested JSON form. Launcher credentials
are explicit: endpoint credentials use api_key_env, while credentials needed
by a managed service itself use deployment.credentials.
Built-in adapters#
Preset |
Target |
Important behavior |
|---|---|---|
|
Cosmos3 Nano VLM |
Image; video requires |
|
Cosmos-Reason1 compatibility |
Image; video requires |
|
Llama Nemotron LLM |
Server-side |
|
Nemotron 3 Nano LLM |
Normalizes the |
|
Nemotron Omni |
Tool calls, image and video, |
|
Embedding server |
OpenAI-compatible dense vectors |
|
STT server |
OpenAI-compatible transcription |
|
Pocket TTS |
OpenAI-compatible speech synthesis |
|
Magpie TTS |
OpenAI-compatible speech synthesis |
The Cosmos adapter capability describes the supported request shape, but the
server controls whether video input is enabled. Every checked-in vlm-server
profile sets max_videos_per_prompt: 0 to avoid reserving unused activation
memory. Set it to at least 1 and restart the persistent VLM server before
sending a video request.
ChatResponse.reasoning is the canonical post-normalization field. Model
adapters absorb whether the provider calls it reasoning or
reasoning_content. LLM and VLM calls accept controlled per-request headers for
Relay lineage, but callers cannot replace the profile’s Authorization header.
Single-image ask_image() and stream() calls are wrappers over the ordered
multi-image methods. All images are placed in one user message in caller order.
Hosted endpoints#
A hosted OpenAI-compatible endpoint changes only the profile:
{
"models": {
"vlm": {
"category": "vlm",
"adapter": {
"kind": "openai_compat",
"model_name": "nvidia/cosmos3-nano-reasoner"
},
"endpoint": {
"base_url": "https://integrate.api.nvidia.com",
"api_key_env": "NGC_API_KEY",
"readiness": "none"
},
"deployment": {"ownership": "external"}
}
}
}
Use readiness: none only when the remote provider has no compatible health
route. It makes health() succeed without a request, preventing an impossible
local readiness gate.
Riva speech over gRPC#
Riva speech NIMs use kind: riva_grpc, not OpenAI /v1/audio. Install the
riva extra; its nvidia-riva-client import is deferred until make_stt() or
make_tts() selects that kind.
stt:
kind: riva_grpc
category: stt
base_url: localhost:50051
language: en-US
STT accepts 16-bit PCM WAV or raw int16 PCM with an explicit sample rate. TTS
also accepts voice and sample_rate. A hosted NVCF endpoint uses TLS,
api_key_env, its function_id, and health_check: false because it has no
Riva channel-ready health surface.
Tests#
The CPU-only tests/test_models_*.py modules exercise model wire formats with
the tests/_stub_openai.StubOpenAI httpx mock transport. Run them from the
repository root:
uv run --project tests pytest -q tests/test_models_*.py