Connect to WiFi. Train large language models.
A clean Python SDK for model training, inference, and post-training experiments.
✨ What is PyTRIO?
PyTRIO lets you focus on the parts of post-training that matter—your data and algorithms—while the engine handles distributed execution, scheduling, fault tolerance, and GPU infrastructure.
Write your training loop on a CPU machine, choose a base model with one string, and keep full control of your loss function, optimizer, rollout strategy, and experiment logic.
- 🧪 Built for post-training: Run SFT, RL, preference optimization, and custom objectives
- ⚡ Async research: Keep working locally while training runs remotely
- 🚀 Managed scale: Train across GPUs without managing CUDA or clusters
- 🔁 Fast iteration: Sample fresh weights, checkpoint, and resume anytime
- 🔌 Application ready: Serve trained weights through OpenAI-compatible APIs
🚀 Train, then sample
Install the SDK and sign in with an API key from the Trio console:
pip install pytrio
trio login
The same training client can update LoRA weights and turn the latest policy into a sampler immediately:
import pytrio as trio
# Connect to the PyTRIO training engine.
service = trio.ServiceClient()
trainer = service.create_lora_training_client(
base_model="Qwen/Qwen3.5-4B",
rank=32,
)
tokenizer = trainer.get_tokenizer()
# Prepare one supervised training example.
tokens = tokenizer.encode(
"Question: what is Trio?\nAnswer: a model training platform."
)
batch = [
trio.Datum(
model_input=trio.ModelInput.from_ints(tokens[:-1]),
loss_fn_inputs={
"target_tokens": tokens[1:],
"weights": [1.0] * (len(tokens) - 1),
},
)
]
# Every step of the training loop stays in your hands.
for step in range(10):
trainer.forward_backward(batch, "cross_entropy").result()
trainer.optim_step(trio.AdamParams(learning_rate=1e-4)).result()
# Save the latest policy and sample from it immediately.
sampler = trainer.save_weights_and_get_sampling_client()
prompt_tokens = tokenizer.encode("Question: what is Trio?\nAnswer:")
result = sampler.sample(
prompt=trio.ModelInput.from_ints(prompt_tokens),
sampling_params=trio.SamplingParams(max_tokens=32, temperature=0.0),
num_samples=1,
).result()
print(result.sequences[0].text)
🎲 Rollouts in, policy updates out
PyTRIO keeps rollout generation and policy updates in one workflow. Sample multiple trajectories from the latest policy, score them with your reward function, then train directly from their tokens and logprobs:
question = "What is 6 * 8?"
prompt_tokens = tokenizer.encode(
f"Question: {question}\nReturn only the final numeric answer.\nAnswer:"
)
# Generate a group of rollouts from the latest policy.
rollouts = sampler.sample(
prompt=trio.ModelInput.from_ints(prompt_tokens),
sampling_params=trio.SamplingParams(max_tokens=8, temperature=0.7),
num_samples=4,
).result()
training_data = []
for sequence in rollouts.sequences:
reward = 2.0 if sequence.text.strip() == "48" else -1.0
completion_tokens = list(sequence.tokens)
tokens = prompt_tokens + completion_tokens
old_logprobs = (
[0.0] * len(prompt_tokens)
+ [0.0 if value is None else float(value) for value in sequence.logprobs]
)
advantages = [0.0] * len(prompt_tokens) + [reward] * len(completion_tokens)
training_data.append(
trio.Datum(
model_input=trio.ModelInput.from_ints(tokens[:-1]),
loss_fn_inputs={
"target_tokens": tokens[1:],
"logprobs": old_logprobs[1:],
"advantages": advantages[1:],
},
)
)
# Update the policy from rewarded rollouts.
trainer.forward_backward(
training_data,
loss_fn="importance_sampling",
).result()
trainer.optim_step(
trio.AdamParams(learning_rate=1e-5),
).result()
Refresh the sampler from the latest weights on every iteration to build an on-policy loop. The same primitives support SFT, PPO-style objectives, custom losses, checkpointing, and evaluation without hiding the algorithm behind a black box.
🧭 API primitives
| Goal | Start here |
|---|---|
| Connect to the training engine | trio.ServiceClient |
| Create and update a LoRA policy | trio.TrainingClient |
| Generate rollouts or compute logprobs | trio.SamplingClient |
| Define token, text, or image input | trio.ModelInput |
| Control rollout generation | trio.SamplingParams |
| Save, resume, and download checkpoints | trio.RestClient |
🔌 OpenAI-compatible inference
Move a trained policy into an application with a model identifier and the standard OpenAI client:
from openai import OpenAI
client = OpenAI(
base_url="https://pytrio.com/api/openai/v1",
api_key="TRIO_API_KEY",
)
response = client.chat.completions.create(
model="trio://your-model/your-version",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytrio-0.2.9.tar.gz.
File metadata
- Download URL: pytrio-0.2.9.tar.gz
- Upload date:
- Size: 136.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
109cfd84b2becb72ac358ef5d498c5084917f252f1889362b2d5e74f13b2d88a
|
|
| MD5 |
9569c1478f66e05dc2a36a688560ce58
|
|
| BLAKE2b-256 |
e3f9d433947fd980dd50288982f9ae9313f8833634ce68c24be49d5c5218c860
|
Provenance
The following attestation bundles were made for pytrio-0.2.9.tar.gz:
Publisher:
release.yml on SwanHubX/Trio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytrio-0.2.9.tar.gz -
Subject digest:
109cfd84b2becb72ac358ef5d498c5084917f252f1889362b2d5e74f13b2d88a - Sigstore transparency entry: 2595966348
- Sigstore integration time:
-
Permalink:
SwanHubX/Trio@eaa250d51385a1c835ac96a8c19aaa300783759e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SwanHubX
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eaa250d51385a1c835ac96a8c19aaa300783759e -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file pytrio-0.2.9-py3-none-any.whl.
File metadata
- Download URL: pytrio-0.2.9-py3-none-any.whl
- Upload date:
- Size: 200.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09eb49535afd3fcf16b25643896224b77ca291e80552275c6693e348e4be3737
|
|
| MD5 |
de0a6b5ce0a527804baae471d510a5a9
|
|
| BLAKE2b-256 |
a2327a319f0c826a83c4663b6c834f0543835b3c1c88d32b38c6b7274f8345eb
|
Provenance
The following attestation bundles were made for pytrio-0.2.9-py3-none-any.whl:
Publisher:
release.yml on SwanHubX/Trio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytrio-0.2.9-py3-none-any.whl -
Subject digest:
09eb49535afd3fcf16b25643896224b77ca291e80552275c6693e348e4be3737 - Sigstore transparency entry: 2595966502
- Sigstore integration time:
-
Permalink:
SwanHubX/Trio@eaa250d51385a1c835ac96a8c19aaa300783759e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SwanHubX
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eaa250d51385a1c835ac96a8c19aaa300783759e -
Trigger Event:
pull_request
-
Statement type: