Console

Python API reference

Reference for the river_client Python package, generated from river-client 0.6.1. The guide covers the same API as a walkthrough; this page lists every public class, method, and type.


pip install river-client
import river_client as river

Client

River API client.

Connects to the River API server over gRPC with automatic retry on transient failures and connection keepalive.

Client(
    api_key: str,
    endpoint: str = 'api.river.ai',
    port: int = 443,
    timeout: float = 86400.0,
    use_ssl: bool = True,
    enable_retries: bool = True,
)
ParameterTypeDefaultDescription
api_keystrAPI key for authentication
endpointstr'api.river.ai'API endpoint hostname
portint443API port
timeoutfloat86400.0Default timeout for operations
use_sslboolTrueWhether to use SSL
enable_retriesboolTrueWhether submit RPCs and gRPC transport may retry transient failures. Disable this for fail-closed evaluation protocols that require one server submission per model turn.

Methods: session, sample, health_check, get_capabilities, get_streaming_replica, promote_streaming_replica, chat_complete_stream, chat_complete, chat_complete_from_checkpoint, chat_complete_from_training, close

Client.session

Client.session(*, timeout: float = 86400.0, **tags: str) -> SessionContext

Create a session context manager.

Returns: SessionContext — Context manager that yields a Session

ParameterTypeDefaultDescription
timeoutfloat86400.0End-to-end session-creation timeout in seconds.
tagsstr

Client.sample

Client.sample(
    prompts: str | list[str] | None = None,
    *,
    base_model: str,
    num_samples: int = 1,
    max_tokens: int = 256,
    temperature: float = 1.0,
    top_p: float = 1.0,
    top_k: int = -1,
    stop: list[str] | None = None,
    seed: int | None = None,
    return_prompt_logprobs: bool = False,
    logprobs: int | None = None,
    images: list[bytes] | list[list[bytes]] | None = None,
    prompt_token_ids: list[int] | list[list[int]] | None = None,
    model_input: list[dict] | list[list[dict]] | None = None,
    tokenizer: Any | None = None,
    metrics_type: str = '',
    timeout: float | None = None,
) -> list[Sample]

Sample from a base model (no session required).

Returns: list[Sample] — Flat list[Sample] — all samples across all prompts. For a single prompt with num_samples=1 (the default), this is a list with one element: result[0].text.

ParameterTypeDefaultDescription
promptsstr | list[str] | NoneNoneSingle prompt string or list of prompts. Mutually exclusive with prompt_token_ids.
base_modelstrBase model name (e.g. "Qwen/Qwen3.6-35B-A3B-FP8").
num_samplesint1Number of independent samples per prompt.
max_tokensint256Maximum tokens to generate per sample.
temperaturefloat1.0Sampling temperature.
top_pfloat1.0Nucleus sampling threshold.
top_kint-1Top-k sampling (-1 = disabled).
stoplist[str] | NoneNoneStop sequences.
seedint | NoneNoneRandom seed (varied per sample automatically).
return_prompt_logprobsboolFalseWhether to return prompt token logprobs.
logprobsint | NoneNoneIf set to K > 0, request the top-K alternative logprobs at each position. Off by default — enabling it roughly halves server throughput.
imageslist[bytes] | list[list[bytes]] | NoneNoneOptional raw image bytes for multimodal sampling. See sample for the per-prompt vs. broadcast semantics.
prompt_token_idslist[int] | list[list[int]] | NoneNonePre-tokenized prompt(s); mutually exclusive with prompts. See sample for details.
model_inputlist[dict] | list[list[dict]] | NoneNoneTraining-style chunk list(s); mutually exclusive with prompts / prompt_token_ids / images. See sample for details.
tokenizerAny | NoneNoneOptional tokenizer name or already-loaded tokenizer. Defaults to base_model after applying River model-alias resolution.
metrics_typestr''Opaque server-interpreted token enabling extra scalar metrics on the response. Unrecognized values are silently ignored; when recognized, per-result metrics appear on Sample.metrics.
timeoutfloat | NoneNoneTimeout in seconds.

Client.health_check

Client.health_check() -> bool

Check API health.

Returns: bool — True if healthy

Client.get_capabilities

Client.get_capabilities() -> list[str]

Get supported models.

Returns: list[str] — List of supported model names

Client.get_streaming_replica

Client.get_streaming_replica(
    model: str,
    *,
    timeout: float | None = None,
) -> PromotedStreamingReplica | None

Return promoted streaming metadata for model when available.

This reads server-owned routing metadata from the control plane. Missing metadata returns None; other HTTP/auth failures raise a River client exception.

ParameterTypeDefault
modelstr
timeoutfloat | NoneNone

Client.promote_streaming_replica

Client.promote_streaming_replica(
    checkpoint: str | Checkpoint,
    model: str,
    *,
    timeout: float | None = None,
) -> PromotedStreamingReplica

Request beta promotion of a checkpoint to a streaming model alias.

The request is asynchronous: the returned metadata is usually status="provisioning". Poll get_streaming_replica until the status is "ready" or "degraded" before using chat_complete_stream.

ParameterTypeDefault
checkpointstr | Checkpoint
modelstr
timeoutfloat | NoneNone

Client.chat_complete_stream

Client.chat_complete_stream(
    messages: list[dict],
    *,
    model: str,
    timeout: float | None = None,
    on_not_ready: str = 'raise',
    **kwargs,
) -> Iterator[dict[str, Any]]

Stream OpenAI-compatible chat chunks from a promoted replica.

timeout is the socket read timeout for each blocking read, not an end-to-end generation deadline. Let the iterator finish, or call close() on it when breaking early, so the HTTP connection is closed.

Returns: Iterator[dict[str, Any]] — Iterator of decoded OpenAI streaming chunk dictionaries.

ParameterTypeDefaultDescription
messageslist[dict]OpenAI-format messages list.
modelstrProduct-facing promoted model alias.
timeoutfloat | NoneNonePer-read HTTP timeout. Defaults to 60 seconds.
on_not_readystr'raise'"raise" (default) or "blocking". The blocking fallback returns one stream-shaped chunk converted from the existing blocking control-plane chat path when promoted metadata is missing, unreachable, or not ready.
kwargs

Client.chat_complete

Client.chat_complete(
    messages: list[dict],
    *,
    base_model: str,
    timeout: float | None = None,
    **kwargs,
) -> ChatCompleteResult | Iterator[dict[str, Any]]

Chat completion from a base model (no LoRA).

Builds an OpenAI-format request body and sends it through the gRPC ChatCompleteFromBase RPC.

Returns: ChatCompleteResult | Iterator[dict[str, Any]] — ChatCompleteResult with response_json and status_code.

ParameterTypeDefaultDescription
messageslist[dict]OpenAI-format messages list.
base_modelstrBase model name for routing.
timeoutfloat | NoneNoneTimeout in seconds.
kwargs

Client.chat_complete_from_checkpoint

Client.chat_complete_from_checkpoint(
    messages: list[dict],
    *,
    checkpoint_path: str,
    base_model: str = '',
    timeout: float | None = None,
    **kwargs,
) -> ChatCompleteResult

Chat completion from a saved checkpoint.

Returns: ChatCompleteResult — ChatCompleteResult with response_json and status_code.

ParameterTypeDefaultDescription
messageslist[dict]OpenAI-format messages list.
checkpoint_pathstrriver:// checkpoint path.
base_modelstr''Base model name (optional; resolved from DB if empty).
timeoutfloat | NoneNoneTimeout in seconds.
kwargs

Client.chat_complete_from_training

Client.chat_complete_from_training(
    messages: list[dict],
    *,
    model_id: str,
    timeout: float | None = None,
    **kwargs,
) -> ChatCompleteResult

Chat completion from in-memory training weights.

Returns: ChatCompleteResult — ChatCompleteResult with response_json and status_code.

ParameterTypeDefaultDescription
messageslist[dict]OpenAI-format messages list.
model_idstrTraining model ID (e.g. session_id:model:seq).
timeoutfloat | NoneNoneTimeout in seconds.
kwargs

Client.close

Client.close() -> None

Close the client connection.


Session

A training session with GPU allocation.

Entered through Client.session; it owns the models you train.

Methods: attest_training_data, create_model, sample, submit_sample

Session.attest_training_data

Session.attest_training_data(
    artifacts: list[TrainingDataArtifact],
    timeout: float = 86400.0,
) -> TrainingDataAttestation

Ask the API to hash source artifacts and retain their manifest.

The source bytes are discarded by the API after hashing. Pass the result to create_model to make the server fail closed before every forward/backward request if that manifest disappears or no longer belongs to the model's session.

ParameterTypeDefault
artifactslist[TrainingDataArtifact]
timeoutfloat86400.0

Session.create_model

Session.create_model(
    base_model: str,
    lora: LoraConfig | None = None,
    tokenizer: str | Any | None = None,
    checkpoint: str | Checkpoint | None = None,
    timeout: float = 86400.0,
    training_data_attestation: TrainingDataAttestation | str | None = None,
) -> Model

Create a new model for training.

Returns: Model — Model object for training

ParameterTypeDefaultDescription
base_modelstrBase model name (e.g., "Qwen/Qwen3.6-35B-A3B-FP8")
loraLoraConfig | NoneNoneOptional LoRA configuration
tokenizerstr | Any | NoneNoneTokenizer name (defaults to base_model) or an already-loaded tokenizer object
checkpointstr | Checkpoint | NoneNoneOptional checkpoint to load after creation. Can be a river:// path string or a Checkpoint object. If a Checkpoint is passed, its step is restored and load_optimizer is set automatically based on checkpoint type.
timeoutfloat86400.0Timeout in seconds
training_data_attestationTrainingDataAttestation | str | NoneNoneOptional server-verified source-artifact manifest. When supplied, the API rejects forward/backward requests if its manifest is missing or no longer belongs to this session.

Session.sample

Session.sample(
    prompts: str | list[str] | None = None,
    *,
    base_model: str,
    checkpoint: str | Checkpoint | None = None,
    num_samples: int = 1,
    max_tokens: int = 256,
    temperature: float = 1.0,
    top_p: float = 1.0,
    top_k: int = -1,
    stop: list[str] | None = None,
    seed: int | None = None,
    return_prompt_logprobs: bool = False,
    logprobs: int | None = None,
    return_expert_routing: bool = False,
    images: list[bytes] | list[list[bytes]] | None = None,
    prompt_token_ids: list[int] | list[list[int]] | None = None,
    model_input: list[dict] | list[list[dict]] | None = None,
    tokenizer: Any | None = None,
    metrics_type: str = '',
    timeout: float = 86400.0,
) -> list[list[Sample]]

Sample from a base model or checkpoint.

When checkpoint is provided, the server loads the LoRA from the saved checkpoint, generates text, then unloads.

Returns: list[list[Sample]]list[list[Sample]] — outer list is per-prompt, inner list is per-sample.

ParameterTypeDefaultDescription
promptsstr | list[str] | NoneNoneSingle prompt string or list of prompts. Mutually exclusive with prompt_token_ids.
base_modelstrBase model name (e.g. "Qwen/Qwen3.6-35B-A3B-FP8").
checkpointstr | Checkpoint | NoneNoneOptional river:// path or Checkpoint object. If provided, samples from that checkpoint's LoRA weights.
num_samplesint1Number of independent samples per prompt.
max_tokensint256Maximum tokens to generate per sample.
temperaturefloat1.0Sampling temperature.
top_pfloat1.0Nucleus sampling threshold.
top_kint-1Top-k sampling (-1 = disabled).
stoplist[str] | NoneNoneStop sequences.
seedint | NoneNoneRandom seed (varied per sample automatically).
return_prompt_logprobsboolFalseWhether to return prompt token logprobs.
logprobsint | NoneNoneIf set to K > 0, request the top-K alternative logprobs at each position. Off by default — enabling it roughly halves server throughput.
return_expert_routingboolFalse
imageslist[bytes] | list[list[bytes]] | NoneNoneOptional raw image bytes for multimodal sampling. See sample for the per-prompt vs. broadcast semantics.
prompt_token_idslist[int] | list[list[int]] | NoneNonePre-tokenized prompt(s); mutually exclusive with prompts. See sample for details.
model_inputlist[dict] | list[list[dict]] | NoneNoneTraining-style chunk list(s); mutually exclusive with prompts / prompt_token_ids / images. See sample for details.
tokenizerAny | NoneNoneOptional already-loaded tokenizer. Passing this avoids repeated Hugging Face cache/network resolution in tight loops.
metrics_typestr''Opaque server-interpreted token enabling extra scalar metrics on the response. Unrecognized values are silently ignored; when recognized, per-result metrics appear on Sample.metrics.
timeoutfloat86400.0Timeout in seconds.

Session.submit_sample

Session.submit_sample(
    prompts: str | list[str] | None = None,
    *,
    base_model: str,
    checkpoint: str | Checkpoint | None = None,
    num_samples: int = 1,
    max_tokens: int = 256,
    temperature: float = 1.0,
    top_p: float = 1.0,
    top_k: int = -1,
    stop: list[str] | None = None,
    seed: int | None = None,
    return_prompt_logprobs: bool = False,
    logprobs: int | None = None,
    return_expert_routing: bool = False,
    images: list[bytes] | list[list[bytes]] | None = None,
    prompt_token_ids: list[int] | list[list[int]] | None = None,
    model_input: list[dict] | list[list[dict]] | None = None,
    tokenizer: Any | None = None,
    metrics_type: str = '',
    timeout: float = 86400.0,
) -> PendingSample

Submit sampling from a base model or checkpoint without waiting.

See sample for the full kwarg reference.

ParameterTypeDefault
promptsstr | list[str] | NoneNone
base_modelstr
checkpointstr | Checkpoint | NoneNone
num_samplesint1
max_tokensint256
temperaturefloat1.0
top_pfloat1.0
top_kint-1
stoplist[str] | NoneNone
seedint | NoneNone
return_prompt_logprobsboolFalse
logprobsint | NoneNone
return_expert_routingboolFalse
imageslist[bytes] | list[list[bytes]] | NoneNone
prompt_token_idslist[int] | list[list[int]] | NoneNone
model_inputlist[dict] | list[list[dict]] | NoneNone
tokenizerAny | NoneNone
metrics_typestr''
timeoutfloat86400.0

Session.session_id

Session.session_id: str

SessionContext

Context manager for Session with auto-heartbeat.

The context manager returned by Client.session.


Model

A training model with mutable in-memory weights.

Created by Session.create_model.

Methods: forward, forward_backward, optim_step, train_step, submit_forward_backward, submit_optim_step, submit_train_step, sample, submit_sample, chat_complete, save_weights, promote_to_streaming, load_weights

Model.forward

Model.forward(
    data: list[dict],
    loss_fn: str = 'cross_entropy',
    timeout: float = 86400.0,
    **loss_config: float,
) -> ForwardResult

Forward pass only (compute loss, no gradients).

Returns: ForwardResult — ForwardResult with metrics

ParameterTypeDefaultDescription
datalist[dict]List of training samples, each with "input_ids" and "labels"
loss_fnstr'cross_entropy'Loss function name
timeoutfloat86400.0Timeout in seconds
loss_configfloat

Model.forward_backward

Model.forward_backward(
    data: list[dict],
    loss_fn: str = 'cross_entropy',
    timeout: float = 86400.0,
    return_logprobs: bool = False,
    zero_out: bool = True,
    compute_expert_flip_metric: bool = False,
    force_routing_replay: bool = False,
    **loss_config: float,
) -> ForwardResult

Forward + backward pass (compute gradients).

Returns: ForwardResult — ForwardResult with metrics and logprobs when returned by the worker.

ParameterTypeDefaultDescription
datalist[dict]List of training samples, each with "input_ids" and "labels"
loss_fnstr'cross_entropy'Loss function name
timeoutfloat86400.0Timeout in seconds
return_logprobsboolFalseDeprecated no-op. Training losses return per-token logprobs when the worker includes them in the result; this argument is accepted for older callers but is not sent to the server as a loss configuration key.
zero_outboolTrueWhen gradient_accumulation is enabled, clear existing gradients before this call. Use True for the first micro-batch and False for subsequent micro-batches.
compute_expert_flip_metricboolFalseWhen True, compares sampled expert routing against the training-time routing per token and MoE layer, then emits one scalar into ForwardResult.metrics: * expert_flip/per_token_expert_rate ∈ [0, 1] — the fraction of individual top-k expert slots that differ, (top_k − |intersection|) / top_k over (token, layer). Independent of force_routing_replay. Requires per-datum routing keys from Sample.routing_datum_keys(required=True).
force_routing_replayboolFalseWhen true, replay the sampled expert selection while recomputing routing weights at those experts with the trainer's live gate. Every datum in data must include the keys returned by Sample.routing_datum_keys(required=True).
loss_configfloat

Model.optim_step

Model.optim_step(
    lr: float,
    beta1: float = 0.9,
    beta2: float = 0.999,
    eps: float = 1e-08,
    weight_decay: float = 0.0,
    grad_clip_norm: float | None = None,
    timeout: float = 86400.0,
) -> OptimStepResult

Apply gradients with Adam optimizer.

Returns: OptimStepResult — OptimStepResult with metrics (step, lr, grad_norm, grad_norm_finite)

ParameterTypeDefaultDescription
lrfloatLearning rate
beta1float0.9Adam beta1
beta2float0.999Adam beta2
epsfloat1e-08Adam epsilon
weight_decayfloat0.0Weight decay
grad_clip_normfloat | NoneNoneGradient clipping norm (None to disable)
timeoutfloat86400.0Timeout in seconds

Model.train_step

Model.train_step(
    data: list[dict],
    lr: float,
    *,
    loss_fn: str = 'cross_entropy',
    beta1: float = 0.9,
    beta2: float = 0.999,
    eps: float = 1e-08,
    weight_decay: float = 0.0,
    grad_clip_norm: float | None = None,
    compute_expert_flip_metric: bool = False,
    force_routing_replay: bool = False,
    timeout: float = 86400.0,
    **loss_config: float,
) -> tuple[ForwardResult, OptimStepResult]

Complete training step: forward+backward plus optimizer update.

Submits forward+backward and the optimizer step back-to-back — the server runs them in order as one pipelined unit, without a client round trip in between — then waits for both results. See forward_backward and optim_step for the full parameter reference.

The error path differs from calling forward_backward() then optim_step(): the optimizer step is already submitted when forward-backward resolves, so if forward-backward fails, this call raises its error while the optimizer step still runs server-side and Model.step has already advanced. Callers that need to inspect both outcomes should use submit_train_step.

A train step is a complete step: gradients are always cleared first. For micro-batch gradient accumulation, use submit_forward_backward(zero_out=...) and submit_optim_step directly.

Returns: tuple[ForwardResult, OptimStepResult] — Tuple of (ForwardResult, OptimStepResult).

ParameterTypeDefaultDescription
datalist[dict]List of training samples, each with "input_ids" and "labels"
lrfloatLearning rate
loss_fnstr'cross_entropy'
beta1float0.9
beta2float0.999
epsfloat1e-08
weight_decayfloat0.0
grad_clip_normfloat | NoneNone
compute_expert_flip_metricboolFalse
force_routing_replayboolFalse
timeoutfloat86400.0
loss_configfloat

Model.submit_forward_backward

Model.submit_forward_backward(
    data: list[dict],
    loss_fn: str = 'cross_entropy',
    timeout: float = 86400.0,
    return_logprobs: bool = False,
    zero_out: bool = True,
    compute_expert_flip_metric: bool = False,
    force_routing_replay: bool = False,
    **loss_config: float,
) -> PendingOp

Submit forward+backward without blocking. Returns a PendingOp.

Call pending.result() later to get the ForwardResult. This enables pipelining: submit step N+1 while step N is still running. See forward_backward for the full kwarg reference.

When submitting multiple micro-batches before submit_optim_step, use zero_out=True for the first one and False for later submissions.

timeout bounds the submit RPC and, separately, the wait inside pending.result().

ParameterTypeDefault
datalist[dict]
loss_fnstr'cross_entropy'
timeoutfloat86400.0
return_logprobsboolFalse
zero_outboolTrue
compute_expert_flip_metricboolFalse
force_routing_replayboolFalse
loss_configfloat

Model.submit_optim_step

Model.submit_optim_step(
    lr: float,
    beta1: float = 0.9,
    beta2: float = 0.999,
    eps: float = 1e-08,
    weight_decay: float = 0.0,
    grad_clip_norm: float | None = None,
    timeout: float = 86400.0,
) -> PendingOp

Submit optimizer step without blocking. Returns a PendingOp.

Call pending.result() later to get the OptimStepResult. Model.step advances at submit time, even if the operation later fails.

ParameterTypeDefault
lrfloat
beta1float0.9
beta2float0.999
epsfloat1e-08
weight_decayfloat0.0
grad_clip_normfloat | NoneNone
timeoutfloat86400.0

Model.submit_train_step

Model.submit_train_step(
    data: list[dict],
    lr: float,
    *,
    loss_fn: str = 'cross_entropy',
    beta1: float = 0.9,
    beta2: float = 0.999,
    eps: float = 1e-08,
    weight_decay: float = 0.0,
    grad_clip_norm: float | None = None,
    compute_expert_flip_metric: bool = False,
    force_routing_replay: bool = False,
    timeout: float = 86400.0,
    **loss_config: float,
) -> tuple[PendingOp, PendingOp]

Submit a complete training step without blocking.

Fires forward+backward and the optimizer step back-to-back; the server runs them in submission order per model. Returns the two PendingOps as (forward_backward, optim_step).

Because both are submitted up front, a failed forward-backward does not cancel the already-submitted optimizer step. Model.step advances at submit time. See train_step for the full kwarg reference.

ParameterTypeDefault
datalist[dict]
lrfloat
loss_fnstr'cross_entropy'
beta1float0.9
beta2float0.999
epsfloat1e-08
weight_decayfloat0.0
grad_clip_normfloat | NoneNone
compute_expert_flip_metricboolFalse
force_routing_replayboolFalse
timeoutfloat86400.0
loss_configfloat

Model.sample

Model.sample(
    prompts: str | list[str] | None = None,
    *,
    num_samples: int = 1,
    max_tokens: int = 256,
    temperature: float = 1.0,
    top_p: float = 1.0,
    top_k: int = -1,
    stop: list[str] | None = None,
    seed: int | None = None,
    return_prompt_logprobs: bool = False,
    logprobs: int | None = None,
    images: list[bytes] | list[list[bytes]] | None = None,
    return_expert_routing: bool = False,
    prompt_token_ids: list[int] | list[list[int]] | None = None,
    model_input: list[dict] | list[list[dict]] | None = None,
    metrics_type: str = '',
    timeout: float = 86400.0,
    poll_interval: float = 1.0,
) -> list[list[Sample]]

Sample from the current in-memory training weights.

Generates text using the model's current weights, without needing to save a checkpoint first. Per-token logprobs are always returned.

Returns: list[list[Sample]]list[list[Sample]] — outer list is per-prompt, inner list is per-sample. Each Sample has .tokens, .text, .logprobs, and .stop_reason.

ParameterTypeDefaultDescription
promptsstr | list[str] | NoneNoneSingle prompt string or list of prompts. Mutually exclusive with prompt_token_ids.
num_samplesint1Number of independent samples per prompt.
max_tokensint256Maximum tokens to generate per sample.
temperaturefloat1.0Sampling temperature.
top_pfloat1.0Nucleus sampling threshold.
top_kint-1Top-k sampling (-1 = disabled).
stoplist[str] | NoneNoneStop sequences.
seedint | NoneNoneRandom seed (varied per sample automatically).
return_prompt_logprobsboolFalseWhether to return prompt token logprobs.
logprobsint | NoneNoneIf set to K > 0, request the top-K alternative logprobs at each output position (and, when return_prompt_logprobs=True, at each prompt position). Off by default — enabling it roughly halves server throughput for small serialization gain, so it's opt-in.
imageslist[bytes] | list[list[bytes]] | NoneNoneOptional raw image bytes (PNG / JPEG) for multimodal sampling. Accepts list[bytes] (broadcast the same image set to every prompt) or list[list[bytes]] (per-prompt explicit). Bytes are sent to the inference backend as image data. Most ergonomic source: **Qwen35VLRenderer.build_sample_prompt(messages).to_kwargs(), which emits {"prompt", "images"}. The image format is inferred from the bytes' magic header, so no separate format hint is sent over the wire.
return_expert_routingboolFalseCapture per-token MoE expert routing during this sampling call. When available, each Sample exposes an .expert_routing object that can be round-tripped into training data with sample.routing_datum_keys(required=True) before calling forward_backward(force_routing_replay=...) or forward_backward(compute_expert_flip_metric=True).
prompt_token_idslist[int] | list[list[int]] | NoneNonePre-tokenized prompt(s) — a flat list[int] (one prompt) or list[list[int]] (one entry per prompt). Mutually exclusive with prompts. Ids are forwarded verbatim for sampling, bypassing server-side tokenization, so the sampled continuation is conditioned on exactly these ids (no training/sampling tokenization skew). Ids must be valid for this model's vocabulary. May be combined with images using the same single-placeholder convention as text prompts: one un-expanded <|image_pad|>-style token id per image, in images order — the placeholder count must match the image count exactly (a surplus of images is silently dropped by the backend otherwise).
model_inputlist[dict] | list[list[dict]] | NoneNoneTraining-style chunk list(s) — the same [{"type": "text", "tokens": [...]}, {"type": "image", "data": bytes, ...}, ...] shape forward_backward accepts, for one prompt (list[dict]) or a batch (list[list[dict]]). Lowered client-side to prompt_token_ids + images (each image chunk becomes one un-expanded placeholder token). Mutually exclusive with prompts / prompt_token_ids / images. expected_tokens and format on image chunks are accepted and ignored; to validate the backend's image expansion against expected_tokens, pass return_prompt_logprobs=True and count placeholder ids in the echoed Sample.prompt_token_ids.
metrics_typestr''Opaque server-interpreted token enabling extra scalar metrics on the response. Unrecognized values are silently ignored; when recognized, per-result metrics appear on Sample.metrics.
timeoutfloat86400.0Timeout in seconds for the entire operation (includes server-side wait for LoRA slot availability).
poll_intervalfloat1.0Seconds between completion polls once the request is in flight. The default (1s) suits ad-hoc sampling; tight RL loops that immediately consume the results can lower it to shave the post-completion notice lag off every step.

Model.submit_sample

Model.submit_sample(
    prompts: str | list[str] | None = None,
    *,
    num_samples: int = 1,
    max_tokens: int = 256,
    temperature: float = 1.0,
    top_p: float = 1.0,
    top_k: int = -1,
    stop: list[str] | None = None,
    seed: int | None = None,
    return_prompt_logprobs: bool = False,
    logprobs: int | None = None,
    images: list[bytes] | list[list[bytes]] | None = None,
    return_expert_routing: bool = False,
    prompt_token_ids: list[int] | list[list[int]] | None = None,
    model_input: list[dict] | list[list[dict]] | None = None,
    metrics_type: str = '',
    timeout: float = 86400.0,
    poll_interval: float = 1.0,
) -> PendingSample

Submit sampling from current training weights without waiting.

See sample for the full kwarg reference.

ParameterTypeDefault
promptsstr | list[str] | NoneNone
num_samplesint1
max_tokensint256
temperaturefloat1.0
top_pfloat1.0
top_kint-1
stoplist[str] | NoneNone
seedint | NoneNone
return_prompt_logprobsboolFalse
logprobsint | NoneNone
imageslist[bytes] | list[list[bytes]] | NoneNone
return_expert_routingboolFalse
prompt_token_idslist[int] | list[list[int]] | NoneNone
model_inputlist[dict] | list[list[dict]] | NoneNone
metrics_typestr''
timeoutfloat86400.0
poll_intervalfloat1.0

Model.chat_complete

Model.chat_complete(
    messages: list[dict],
    *,
    timeout: float | None = None,
    **kwargs,
) -> ChatCompleteResult

OpenAI-compatible chat completion from current training weights.

Like model.sample() but using the OpenAI chat-completions format instead of raw prompts.

Returns: ChatCompleteResult — ChatCompleteResult with response_json (full OpenAI-format JSON string) and status_code.

ParameterTypeDefaultDescription
messageslist[dict]OpenAI-format messages list (e.g. [{"role": "user", "content": "Hello"}]).
timeoutfloat | NoneNoneTimeout in seconds.
kwargs

Model.save_weights

Model.save_weights(
    name: str,
    mode: str = 'training',
    timeout: float = 86400.0,
    ttl: datetime.timedelta | None = None,
) -> Checkpoint

Save a checkpoint of the current model weights.

Returns: Checkpoint — Checkpoint object with river:// path.

ParameterTypeDefaultDescription
namestrCheckpoint name (e.g. "final" or "step_000100").
modestr'training'"training" saves optimizer state (for training continuation), "inference" saves PEFT format only (for sampling/inference).
timeoutfloat86400.0Timeout in seconds.
ttldatetime.timedelta | NoneNoneLifetime before the checkpoint is reaped. Applies to explicit user-saved checkpoints in both modes; when omitted, the server default is 1 year. 1 year is also the maximum — the server rejects a longer ttl.

Model.promote_to_streaming

Model.promote_to_streaming(
    model: str,
    checkpoint: str | Checkpoint | None = None,
    checkpoint_name: str | None = None,
    timeout: float | None = 86400.0,
) -> PromotedStreamingReplica

Promote this model's current or saved checkpoint to a stream alias.

When checkpoint is omitted, this saves the current weights with mode="inference" using checkpoint_name or a generated name, then asks the control plane to promote that checkpoint asynchronously. The timeout is applied separately to the save and promotion calls, not as one end-to-end deadline. Omitted checkpoint_name values create a new server-side inference checkpoint for each call.

ParameterTypeDefault
modelstr
checkpointstr | Checkpoint | NoneNone
checkpoint_namestr | NoneNone
timeoutfloat | None86400.0

Model.load_weights

Model.load_weights(
    checkpoint: str | Checkpoint,
    load_optimizer: bool = True,
    timeout: float = 86400.0,
) -> None

Load weights from a checkpoint.

ParameterTypeDefaultDescription
checkpointstr | CheckpointA river:// path string or a Checkpoint object. If a Checkpoint is passed, its step is restored on the model.
load_optimizerboolTrueWhether to load optimizer state.
timeoutfloat86400.0Timeout in seconds.

Model.model_id

Model.model_id: str

Model.training_run_id

Model.training_run_id: str

Model.step

Model.step: int

Current training step.

Advances when an optimizer step is submitted (so pipelined submissions observe a consistent value), not when it resolves — a failed or timed-out optimizer step leaves it advanced.


Data types

Values returned by the client and the configuration objects you pass to it.

LoraConfig

LoRA adapter configuration.

FieldTypeDefault
rankint16
train_attnboolTrue
train_mlpboolTrue
train_unembedboolFalse
seedint | NoneNone

Sample

A generated sample.

tokens contains generated token IDs when the response includes them; older responses may fall back to retokenizing text client-side.

prompt_token_ids / top_logprobs / prompt_top_logprobs are None when the server did not provide them or the feature was not requested.

expert_routing is populated when return_expert_routing=True was passed on the request.

metrics carries per-result scalar metrics; empty unless the originating request passed a recognized metrics_type token.

FieldTypeDefault
tokenslist[int]
textstr
logprobslist[float]
stop_reasonstr
model_stepint
prompt_logprobslist[float] | NoneNone
request_idstr''
prompt_token_idslist[int] | NoneNone
top_logprobslist[list[TopLogprob]] | NoneNone
prompt_top_logprobslist[list[TopLogprob]] | NoneNone
expert_routingExpertRouting | NoneNone
metricsdict[str, float]{}

Sample.routing_datum_keys

Sample.routing_datum_keys(*, required: bool = False) -> dict[str, bytes | str]

Return the per-datum keys to splat into a forward_backward datum when enabling force_routing_replay or compute_expert_flip_metric.

Returns an empty dict when this sample carries no routing capture and required is false. Raises ValueError when required is true and no routing handle is available.

Example:

data = []
for sample in samples:
    datum = {
        "input_ids": ...,
        "advantages": ...,
        **sample.routing_datum_keys(required=True),
    }
    data.append(datum)
ParameterTypeDefault
requiredboolFalse

ChatCompleteResult

Result of a chat completion request.

FieldType
response_jsonstr
status_codeint

ForwardResult

Result of forward or forward_backward pass.

FieldTypeDefault
metricsdict[str, float]
logprobslist | NoneNone

OptimStepResult

Result of an optimizer step.

FieldType
metricsdict[str, float]

Checkpoint

A saved model checkpoint.

FieldType
pathstr
stepint
checkpoint_typestr

TopLogprob

One top-K candidate token at a single position.

FieldTypeDefault
logprobfloat
token_idint
tokenstr''

PendingOp

A submitted but not-yet-resolved async operation.

Returned by Model.submit_forward_backward() and Model.submit_optim_step(). Call .result() to block until complete.

FieldType
request_idstr

PendingOp.result

PendingOp.result() -> ForwardResult | OptimStepResult

Block until the operation completes and return the result.

PendingSample

A submitted but not-yet-resolved sampling operation.

FieldType
request_idstr

PendingSample.result

PendingSample.result() -> list[list[Sample]]

Block until sampling completes and return grouped samples.

ExpertRouting

Captured MoE expert routing for one sample.

Populated when the caller passed return_expert_routing=True on the sample request and routing capture was available.

To enable router replay / flip-rate metrics, splat the canonical per-datum keys via Sample.routing_datum_keys() rather than building them by hand:

datum = {..., **sample.routing_datum_keys(required=True)}

Current servers return routing captures as an opaque handle; the splat yields expert_routing_handle. topk_ids is retained for inspection and proto round-trip compatibility only; replay always recomputes the routing weights in the trainer.

The shape header fields (num_decoder_layers / top_k / layer_indices) are informational only and let the user inspect capture metadata.

Byte layout (when ids are present): [num_tokens, num_decoder_layers, top_k] row-major int16 little-endian. num_tokens = seqlen - 1 because routing capture omits the trailing position.

FieldTypeDefault
topk_idsbytesb''
num_tokensint0
num_decoder_layersint0
top_kint0
layer_indiceslist[int][]
handlestr''

PromotedStreamingReplica

Server-owned routing metadata for a promoted streaming replica.

FieldTypeDefault
checkpointstr
statusstr
base_urlstr | None
replica_idstr | None
modelstr
base_modelstr
updated_atstr
status_reasonstr | NoneNone

TrainingDataArtifact

Source bytes and expected digest for server-side integrity verification.

The API hashes content itself and retains only the resulting manifest. Callers should verify their source files locally before constructing these objects, then bind the returned TrainingDataAttestation to the model they create.

FieldType
namestr
expected_sha256str
contentbytes

AttestedTrainingDataArtifact

Server-observed source-artifact digest and size.

FieldType
namestr
sha256str
size_bytesint

TrainingDataAttestation

A server-verified source-artifact manifest bound to one session.

FieldType
training_data_attestation_idstr
artifactslist[AttestedTrainingDataArtifact]

Errors

Every server and transport failure derives from RiverError, so a single except river.RiverError catches all of them. Invalid arguments still raise the standard ValueError and TypeError.

RiverError

Inherits Exception.

Base exception for River client errors.

AuthenticationError

Inherits RiverError.

Authentication failed.

CapacityError

Inherits RiverError.

No capacity available for the operation.

ModelNotFoundError

Inherits RiverError.

Model not found.

RiverConnectionError

Inherits RiverError.

Connection or communication error with the River API server.

This wraps gRPC errors with a more user-friendly message while preserving the original error details for debugging.

FieldDescription
messageHuman-readable error message
status_codegRPC status code name (e.g., "UNAVAILABLE", "DEADLINE_EXCEEDED")
detailsAdditional error details from the server
original_errorThe original gRPC RpcError for debugging

RiverConnectionError.from_grpc_error

RiverConnectionError.from_grpc_error(
    error: Exception,
    context: str = 'API call',
) -> 'RiverConnectionError'

Create a RiverConnectionError from a gRPC RpcError.

ParameterTypeDefault
errorException
contextstr'API call'

RiverTimeoutError

Inherits RiverError.

Operation timed out while retaining its recoverable future ID.

Field
request_id

SessionHeartbeatError

Inherits RiverConnectionError.

Session heartbeat was lost or rejected while a session was active.


Tokenizers

Helpers for tokenizing prompts yourself, for example when you build prompt_token_ids for training data.

load_tokenizer

load_tokenizer(
    tokenizer: str | Any | None = None,
    *,
    base_model: str | None = None,
    revision: str | None = None,
    local_files_only: bool = False,
    resolve_aliases: bool = True,
)

Load or return a tokenizer for River client result parsing.

base_model remains the public River model name used for routing. When it is a hyphen-suffixed deployment alias of a known canonical model, this helper resolves it to the underlying Hugging Face tokenizer id before loading. local_files_only keeps sealed jobs from reaching Hugging Face after their tokenizer revision has been frozen. resolve_aliases=False retains a deployment's own tokenizer source for unpinned compatibility paths.

ParameterTypeDefault
tokenizerstr | Any | NoneNone
base_modelstr | NoneNone
revisionstr | NoneNone
local_files_onlyboolFalse
resolve_aliasesboolTrue

resolve_tokenizer_name

resolve_tokenizer_name(model_name: str) -> str

Return the tokenizer for a canonical River model or one of its aliases.

Deployment aliases must append a hyphen-delimited suffix to a canonical model name. Longest-root matching keeps the result deterministic if a future canonical model name extends another root.

ParameterType
model_namestr

MODEL_TOKENIZER_ALIASES

MODEL_TOKENIZER_ALIASES: dict[str, str]
KeyValue
Qwen/Qwen3.6-35B-A3B-FP8Qwen/Qwen3.6-35B-A3B
Qwen/Qwen3.5-397B-A17B-FP8Qwen/Qwen3.5-397B-A17B-FP8
nvidia/Kimi-K2.6-NVFP4nvidia/Kimi-K2.6-NVFP4
nvidia/GLM-5.1-NVFP4nvidia/GLM-5.1-NVFP4
nvidia/GLM-5.2-NVFP4nvidia/GLM-5.2-NVFP4