The control plane could not be reached.
Retry
My projects — Sign in to load
My trainings — Sign in to load
Running now —
Failed · need attention —
Projects will appear after connecting.
Failed runs and their cause will appear here.
A project is one model line: a single Hugging Face repository whose trainings publish as numbered versions, plus the jobs, RL objectives and datasets behind them. Promote a version to make it the model other work can start from.
New project
Judge and version
Holdout configuration
Choose a configuration to evaluate and compare models.
Select models to evaluate or compare their results.
Run history
Comparison Shared configuration
Model A Model B
Differences use examples scored for both models. Missing scores are shown as —.
Criterion · shared scored examples Model A Model B Difference B − A
Shared evaluation configuration All runs use this snapshot. Create a new evaluation to change the dataset or judge.
Back to models
Model / revision Inference / Judge Scored / failures Mean score Approval Actions
Close
For Judge access or connection errors, check the VPN on the Mission Control server and LiteLLM credentials. Once access is restored, use Judge saved responses to retry without running inference again.
Saved run
Outcome All responses Inference failures Judge execution failures Errors reported by Judge Rejected by Judge
Error type All error types
Copy all
Example Input Response / inference Judge Gold
Close
Close
Runs inference locally on CPU and calls the frozen Judge via LiteLLM. This may download model weights and incur Judge API costs.
Model / revision
Cancel Start CPU run
Overview & history
Runs
Metrics
Config & parameters
Loading run configuration…
Favorite models, shared with every project for demos and as training sources. Every other model stays inside its project — open the project and use “Favorite” to list it here.
Manage catalog
Clean completed
Create job
Queued jobs —
Requested GPUs —
Ready definitions —
Assigned users —
Edit the draft, then publish an immutable version for evaluations. Changes leave all previously published versions and results intact.
Published version history
Published version (read only)
Saved configuration
1. Identification
Name Required
Description
2. Evaluator model
Evaluator model Optional Choose at evaluation time Select a model made available by LiteLLM for the configured credential.
Reasoning effort Model default
Advanced inference parameters
Blank fields are omitted from the provider request. Parameter availability depends on the model.
Temperature Between 0 and 2. Controls response variability.
Top P Greater than 0 and up to 1. An alternative to temperature.
Maximum output tokens Token budget for the evaluator response.
Seed Helps reproducibility when supported; identical results are not guaranteed.
3. Evaluation instructions
Judge prompt Required Place {criteria_block} where the criteria should appear; if omitted, they are appended.
The result includes criterion scores, feedback and errors with evidence. The structured response contract is generated automatically.
4. Criteria
Define a scale for each criterion and explain what each score means. At least one criterion is required.
Add criterion
5. Approval
Minimum passing score Between 0 and 1. The score is rounded to four decimal places before comparison.
Final score = sum(score × weight) ÷ sum(maximum allowed score × weight). Zero on any critical criterion sets the final score to zero and fails the response.
TOML
TOML Generated automatically from the settings.
Final prompt
Teacher LLM prompt Instructions, criteria and response format sent in the system message.
During evaluation, the original text, model response and optional reference are sent in a separate message.
Cancel Save draft Save and publish version
Delete ? Associated versions and tests will also be deleted. This cannot be undone.
Cancel Delete judge
Each objective is one reward program for small-model RL: name it, prepare the required thinking bootstrap and independent GRPO data, write and test the Python reward, certify it on the pinned data, then launch GRPO.
New objective
1 Objective Name, project and status
2 Bootstrap Teach thinking with supervised data
3 GRPO data Prompts and gold answers
4 Reward code Program and test the reward
5 Certify Prove it on the pinned dataset
6 Launch Training recipe and GRPO job
Step 1 · Objective
Name the objective and choose where it belongs
An objective is one reward program together with its pinned dataset, certification evidence and training recipe. Attach it to a project so the GRPO job publishes its model there.
Unsaved draft
Objective name Required
Project No project
Status Draft Ready Archived
Description
Start from an example Production examples pin a thinking dataset, token budgets and a starter reward. Applying one fills the next steps; everything stays editable.
potelo/kimi-bit-rl-catchup-thinking-v1
Catch up · thinking + GRPO
Bootstrap chronological, source-linked legal catch-up reasoning before optimizing the grounded digest reward.
Rows 300
Prompt budget 8192 tokens
Use this example
Details
potelo/kimi-bit-rl-movement-thinking-v1
Movement explanation · thinking + GRPO
Teach a small model to reason over one court movement before optimizing a grounded, plain-Portuguese explanation.
Rows 300
Prompt budget 4096 tokens
Use this example
Details
potelo/kimi-bit-rl-toy-thinking-500
Toy thinking bootstrap · 500 rows
Private 500-example mixed reasoning fixture (250 rows per task) for a bounded two-stage smoke test.
Rows 250
Prompt budget 512 tokens
Use this example
Details
Loading example…
Continue to bootstrap
Step 2 · Bootstrap Teach the model to think before RL Choose supervised examples with a non-empty thinking column and a final answer. This dataset has its own split, revision and column mapping, independent of the RL data in step 3.
Thinking bootstrap dataset · required Supervised rows with a literal thinking column and a final answer. Cold Start finetunes the source model on them before RL so it learns the reasoning envelope. Every RL objective includes this supervised stage before RL.
Use the training dataset
Not inspected
Open Settings › Datasets
Pinned revision
Not resolved yet
Inspecting resolves the branch to its current commit and pins it.
Pin a specific commit
Commit SHA Branches and tags are never stored; inspect again after changing the commit.
Inspect the thinking bootstrap dataset to see its columns, sample rows and task values.
2 Thinking columns
Map dataset columns to the reasoning contract. The thinking role is locked to the literal thinking column and every selected row must fill it.
Instruction source Fixed instruction Dataset column
Fixed instruction Required Preserves line breaks. Use the teacher’s task policy, including what to preserve or remove. Choose a dataset column when instructions vary by row. The token profile includes this instruction.
Instruction
Input
Thinking Locked
Final answer
Task Optional When unmapped, every row uses the objective task.
Back to objective Continue to RL data
Step 3 · RL data
Choose the prompts and gold answers for RL
RL generates answers for each prompt and scores them with your reward. Choose this dataset independently of the supervised bootstrap. Gold answers are available to the reward only; the model sees the instruction and input.
Not inspected
Training dataset · RL prompts Usually the larger task dataset. Instruction and input become the prompt; an optional task column keeps only rows of this objective; a reference answer supplies the gold text for rewards that compare predictions.
Not inspected
Open Settings › Datasets
Pinned revision
Not resolved yet
Inspecting resolves the branch to its current commit and pins it.
Pin a specific commit
Commit SHA Branches and tags are never stored; inspect again after changing the commit.
Inspect the training dataset to see its columns, sample rows and task values.
1 Prompt columns
Map the training dataset onto the prompt contract. Roles are guessed from column names after an inspection; adjust them here.
Instruction source Fixed instruction Dataset column
Fixed instruction Required Preserves line breaks. Use the teacher’s task policy, including what to preserve or remove. Choose a dataset column when instructions vary by row. The token profile includes this instruction.
Instruction Required
Input Optional
Task Optional When unmapped, every row uses the objective task.
Reference answer Optional Available to reward code as source.reference_text during RL. Never included in the model prompt.
Back to bootstrap
Save objective
Continue to reward code
Step 4 · Reward code
Python reward studio
Write reward(sample) with the RL Lab helpers, run it instantly on hand-written probes or on rows sampled from the dataset, and inspect every score, component and trace. Prefer an IDE or an LLM? Download the bundle and run the same samples locally. The exact certified code is embedded into RL.
Unsaved draft
LLM judge
Compare gold and predicted answers with Qwen3.8-27B
Judge reasoning effort Low Medium Extra high Choose the judge's reasoning depth independently of its token limits. Low remains the default; changing effort leaves the output budget unchanged.
Judge context tokens Prompt plus judge output. Leave room for gold, prediction and rubric as well as the output budget. GPU preflight checks whether the allocation fits.
Judge output tokens · thinking + final score Total budget for reasoning and the final scalar. Must be smaller than its context. Truncated responses are rejected and retained in the audit. The accepted answer remains one number in [0, 1].
Judge thinking token cap (optional) Leave blank to let thinking finish naturally within the total output limit. An explicit cap can interrupt thinking; responses that hit the cap are rejected and retained in the audit. If set, reserve at least 32 output tokens for the scalar score.
Judge timeout (seconds) Allow time for reasoning before the scalar score, especially with a large output budget.
Concurrent judge requests Default 8; configurable from 1 to 64. Using 32 needs at least 32 eligible B×G candidates (prompts per round × completions per prompt) and enough judge GPU capacity for their context and output. This is a request limit, not a throughput guarantee.
vLLM serves Qwen/Qwen3.8-27B with FP8 weights on one dedicated GPU. Select at least 2 GPUs at launch: one for the judge and the rest for training.
Use Certify to validate the dataset and code here. Judge probes require the allocated GPU and run before bootstrap; a failed preflight stops training.
Judge prompt template (Jinja2) Required Include gold and predicted below. The runtime substitutes the full texts. The rl_judge_prompt() helper retains this exact template.
{{ gold }} · required
{{ predicted }} · required
{{ input }} · optional
{{ thinking }} · optional
Templates support text and the four field substitutions only; loops, conditions, filters and attribute access are not supported.
Return a single number in [0, 1]: 0, 0.75 or 1.0. Decimals use a point. JSON objects such as {"score": 0.75}, quoted numbers, extra text, nonfinite values and out-of-range scores are rejected.
Preview substituted prompt
Uses a sampled row if available, with gold copied as an illustrative prediction; otherwise uses a small OCR example. This renders the template only. It does not call the judge or measure a score.
Render preview
Preview has not been rendered.
Replace reward with judge example
The example rejects incomplete thinking, then calls the judge with gold and predicted final text. Keep the helper call when this option is enabled. Disabling requires removing the helper call from your code.
Starter example
Catch up example
Movement explanation example
Load a saved reward function
Load from library…
Reset starter
Save to library
Download bundle
Validate
Run probes
Run on sample rows
Choose source model
Ready · Ctrl/⌘+Enter runs the probes
Ln 1, Col 1
Unsaved code
Ctrl/⌘ +Enter run · Ctrl/⌘ +S save · Ctrl +Space complete
Runtime API
Define reward(sample)
The sample is read-only and identical in simulation and RL. Split logic into top-level helper functions and import re, math, string or unicodedata when you need them. Autocomplete offers only the RL Lab helpers and snippets; click a helper or snippet to insert it.
Sample
Helpers
Snippets
Return
Rules
{
"task": str,
"prompt": str,
"completion": str,
"thinking": str,
"thinking_tokens": int | None,
"thinking_soft_limit_tokens": int,
"final": str,
"reasoning_valid": bool,
"reasoning_error": str | None,
"source": {"source_text": str, "reference_text"?: str},
"stop_reason": str,
"words": int,
}
taskstr Objective slug the program is certified for (for example catchup_digest).
promptstr Raw task input without chat-template markup: the instruction plus the input field of the dataset row.
completionstr Complete model output including the <think>…</think><answer>…</answer> envelope.
thinkingstr Parsed reasoning text; empty when the envelope is missing.
thinking_tokensint | None Exact parsed thinking token count using the pinned student tokenizer, without special tokens or envelope. Unavailable is None, never a word/character estimate. Programs referencing this field require the tokenizer before any judge call.
thinking_soft_limit_tokensint Trusted root GRPO configuration value (default 8192, integer >= 1000), not dataset-supplied metadata. The visible OCR reward uses 0.01/500 * (max(0, thinking_tokens - 1000) + max(0, thinking_tokens - thinking_soft_limit_tokens)). This soft threshold increases marginal penalty; it does not stop generation. Custom programs must use it explicitly.
finalstr Parsed final answer; empty when the envelope is invalid.
reasoning_validbool True when the envelope parsed cleanly. Gate on this first.
reasoning_errorstr | None Parser error message when reasoning_valid is False.
source{"source_text": str, "reference_text"?: str} Grounding text equals prompt. Optional reference_text is the mapped gold answer, available only to the reward and never to the model prompt.
stop_reasonstr eos, length or stop_sequence. length means the generation hit max_new_tokens and is probably truncated.
wordsint Deterministic word count of final.
sample["thinking_tokens"] counts the parsed thinking with the pinned student tokenizer, without special tokens. It is not a word count, character estimate or judge token count. Select the registered source model in Launch for probe evaluation and bundle export. When unavailable, the value is None; rewards requiring it cannot be scored.
Filter helpers
llm_judge(gold, predicted, prompt) -> float
Compare gold and predicted text with the configured Qwen judge on its exclusive runtime GPU. The prompt must exactly match the saved Jinja2 template, including gold and predicted substitutions. Use {{ gold | tojson }} and {{ predicted | tojson }} for lossless JSON string framing; only this filter on a bare field is allowed, without arguments or filter chains. Plain {{ gold }} and {{ predicted }} remain available for custom templates; {{ input }} and {{ thinking }} are optional for custom rubrics. The OCR outcome rubric uses only gold and predicted to judge final-answer semantic transcription fidelity. Source input and student thinking remain in separate audit fields; retaining them does not include them in the rendered judge prompt. The judge's own reasoning is a separate audit trace, not the student's thinking. Envelope checks and the configured student-token penalty remain separate reward terms. Returns any single finite number in [0, 1], without category rounding (for example 0.75); JSON objects, quoted numbers and extra text are rejected. There are at most four calls per sample. Infrastructure errors fail the run rather than becoming scores. Controller validation checks code and dataset only; judge execution requires GPU allocation and real preflight before bootstrap.
score = llm_judge(sample["source"]["reference_text"], sample["final"], rl_judge_prompt())
clamp(value, minimum=0.0, maximum=1.0) -> float
Bound a number inside [minimum, maximum]. Bounds must be finite and ordered.
quality = clamp(words / 120.0)
safe_divide(numerator, denominator, default=0.0) -> float
Divide two finite numbers and return default when the denominator is zero.
precision = safe_divide(matched, len(answer_links))
mean(values) -> float
Arithmetic mean of finite numbers; 0.0 for an empty input. Bounded to 10,000 items.
score = mean(components.values())
words(text) -> tuple[str, ...]
Lower-cased alphanumeric tokens (Unicode letters and digits).
first_words = words(final)[:20]
word_count(text) -> int
Number of tokens returned by words(text).
final_words = word_count(final)
contains(text, needle, case_sensitive=False) -> bool
Case-insensitive substring test by default.
has_date = contains(final, "13/07/2023")
count_occurrences(text, needle, case_sensitive=False) -> int
Number of non-overlapping needle occurrences; 0 for an empty needle.
paragraph_breaks = count_occurrences(final, "\n\n")
links(text) -> tuple[str, ...]
Every http(s) URL in text with trailing punctuation removed.
source_links = links(source)
fraction_present(values, text) -> float
Share of non-empty values found in text (case-insensitive). 1.0 when there is nothing to find.
link_recall = fraction_present(source_links, final)
ordered_fraction(values, text) -> float
Share of values that appear in text in the same order as given; rewards chronology.
chronology = ordered_fraction(source_links, final)
token_overlap(left, right) -> float
Jaccard overlap of the word sets of two texts, from 0.0 to 1.0.
grounding = clamp(token_overlap(final, source) * 3.0)
Plain Python the sandbox also accepts
Builtins: abs() all() any() bool() enumerate() float() int() len() max() min() range() round() sorted() str() sum() zip()
Methods: .capitalize() .casefold() .count() .endswith() .find() .isalnum() .isalpha() .isdigit() .isspace() .join() .lower() .lstrip() .partition() .removeprefix() .removesuffix() .replace() .rsplit() .rstrip() .split() .splitlines() .startswith() .strip() .title() .upper() .get() .items() .keys() .values() .search() .match() .fullmatch() .findall() .finditer() .sub() .subn() .group() .groups() .groupdict() .start() .end() .span()
Imports (top of the program): import re import math import string import unicodedata
Return a floor reward when the thinking envelope is broken.
if not sample.get("reasoning_valid", False):
return {
"score": -1.0,
"components": {"reasoning_format": -1.0},
"trace": {"reasoning_error": sample.get("reasoning_error")},
}
Penalize generations that exhausted the token budget.
if sample.get("stop_reason") == "length":
return {
"score": -1.0,
"components": {"incomplete_generation": -1.0},
"trace": {"stop_reason": "length"},
}
Reward answers inside a word-count window.
final_words = word_count(final)
length_quality = clamp(min(final_words / 30.0, 160.0 / max(final_words, 1)))
Precision, recall and chronology of source links.
source_links = links(source)
answer_links = links(final)
link_precision = fraction_present(answer_links, source) if answer_links else 0.0
link_recall = fraction_present(source_links, final)
chronology = ordered_fraction(source_links, final)
Weighted components Insert
Combine named components whose sum is the score.
components = {
"grounding": 0.5 * clamp(token_overlap(final, source) * 3.0),
"length_quality": 0.3 * length_quality,
"clean_ending": 0.2 * (1.0 if final.strip().endswith((".", "!", "?")) else 0.0),
}
return {"score": sum(components.values()), "components": components, "trace": {}}
Test the answer against a regular expression. Add "import re" at the top of the program.
cites_article = re.search(r"art\.\s*\d+", final, re.IGNORECASE) is not None
date_count = len(re.findall(r"\b\d{2}/\d{2}/\d{4}\b", final))
# Simple
return 0.75
# Auditable
return {
"score": 0.75,
"components": {"grounding": 0.5, "format": 0.25},
"trace": {"matched": 3},
}
Component names are lowercase slugs (a-z, 0-9, _). Component values must sum exactly to score. Trace values must be JSON-safe and stay under 16 KiB per example. GRPO only uses the ranking inside a group of completions, so the order your score induces matters more than absolute totals.
Allowed
Exactly one top-level def reward(sample), plus any number of top-level helper functions with plain positional parameters (literal defaults allowed). Helpers may call each other but never recursively. import re, math, string and unicodedata at the top of the program (also "import re as regex" or "from math import sqrt"); only the documented members of each module are available. Assignments, if/elif/else, for loops (nested at most twice), break, continue and return. Numbers, strings, f-strings, lists, tuples, sets and dicts, comprehensions and generator expressions. Arithmetic, comparisons, boolean logic, | for regex flags, slicing and mapping lookups. The documented helpers, builtins, string/dict/regex methods and module members.
Not available
Any other module, imports inside functions, module-level assignments, nested functions, class, while, try/except, lambda, global, async, yield, assert and del. Attribute access other than the documented methods and module members; use sample["key"] or sample.get("key"). Names that start with an underscore, exec/eval/open and every other ambient builtin; helpers and imports may not shadow the documented helper names. Power exponents that are not numeric literals of magnitude 8 or less.
Limits
Code up to 32768 bytes and 2500 syntax nodes.
At most 64 components; trace up to 16384 bytes per example.
Scores between -10.0 and 10.0; loops nested at most 2 deep; iterables bounded to 10000 items.
Simulations run in a separate interpreter with no ambient builtins, an empty working directory, no network, and CPU, memory, output and wall-time limits.
Saved functions Reusable reward(sample) programs · 0 in the library
Search reward functions
Load one into this objective, clone it, or delete it. Certification always binds to the objective, never to the library.
No saved functions yet. Save one with “Save to library”.
Probes Hand-written thinking / final pairs for fast good-vs-broken checks
Probe examples Edit thinking and final output together; both fields are available to your reward function. Dataset rows can be copied in as probes.
From dataset row
Add probe
Scratch runs are instant and never persisted. Record a run to keep an exploratory snapshot in the objective history.
Record probes in history
Back to RL data
Continue to certification
Step 6 · Launch
Training recipe and RL handoff
Set the input and output limits for your model. The advisor suggests budgets from a separate dataset profile; it never changes your token limits. Review the remaining training settings before certifying this recipe.
Draft
Datasets Choose the training dataset
Thinking contract Literal thinking → canonical envelope
Reward evidence Run a successful simulation
Source model Choose a registered model
Source model Required before launch Choose before launch… The model commit is resolved automatically. Its size template and context length drive the recipe below; the job form performs the final artifact checks.
Inspect RL train metadata for a step-budget estimate. Steps remain editable.
Recovery defaults: local checkpoints target every 300 seconds at a completed round boundary (or sooner by the step interval); remote recovery targets at most 600 seconds of lost progress. Incomplete uploads are ignored; recovery continues after the saved rollout round. Long rounds, save/upload time or upload outages can exceed this budget: review recovery budget warnings before trusting the target. These are automatic defaults, not a guarantee or a required form setting.
Input and output token limits · set manually
Profile 10% of the dataset, up to 1,000 rows, separately from the reading preview. Recommendations are estimates, not a guarantee that every row fits. Output includes THINKING + FINAL answer + reasoning envelope tokens.
Bootstrap input tokens Set the maximum supervised prompt size.
Bootstrap output tokens · thinking + final + envelope Allow enough room for the full supervised response; oversized rows are rejected.
Bootstrap maximum thinking tokens Default 16,384. Discard the whole training example above this thinking limit; never shorten its original thinking or answer.
RL input tokens Whole prompts above this limit are rejected, never sliced.
RL output tokens · thinking + final + envelope Shared generation limit for the complete response.
RL maximum thinking tokens Default 16,384. Hard limit on generated thinking; a smaller total output budget takes precedence and may leave no room for the answer and envelope.
Thinking penalty soft threshold Default 8,192. Passed to the visible reward code as sample["thinking_soft_limit_tokens"]. The OCR reward charges 0.01 per 500 thinking tokens above 1,000, with double marginal cost above this threshold. This threshold does not stop generation.
1 Cold Start bootstrap recipe
Advanced Cold Start settings
Learning rate auto
Batch size auto
Validation fraction auto
2 Policy optimization · GRPO by default
Optimization method GRPO (default · at least 2 completions per prompt) KLPO (one completion per prompt) GRPO compares several completions of each prompt (measured catch-up recipe: 4 prompts × 8, held-out reward 0.833 at ~24 s/step). KLPO samples one completion per prompt with a leave-one-out reward baseline (32 × 1: 0.826 at ~55 s/step).
Advanced RL settings and token budgets
Prompts / step auto
Prompt rows auto
Checkpoint every auto Part of the certified objective; use 1 for replay capture.
KLPO reward baseline Leave-one-out (recommended) None · raw rewards Compares each reward with the other samples of its group, or of the step batch at one completion per prompt. Without it KLPO reinforces every sample when the mean reward is positive.
Truncated responses Drop them from the loss (GRPO) Train them with their reward (KLPO) The starter rewards score stop_reason == "length" as -1. GRPO's group mean still sees that penalty when the response is dropped; KLPO only trains it when truncated responses stay in the loss.
Temperature auto
The handoff preserves the objective’s exact dataset revision and reward code. The job form enforces source-artifact compatibility, judge GPU capacity, controller secrets, W&B and target-model validation. RL supports spot compute with automatic recovery of durable checkpoints.
Back to certification
Save & open RL job
Checking gateway connection…
Endpoints Deploy, test and monitor your model APIs.
+ New endpoint
Model Provider Capacity Review
Set your capacity Endpoints scale to zero by default: the first request rents a GPU, and idle workers are released after the idle shutdown delay. Set a minimum above zero to keep GPUs warm for immediate responses.
GPU classes Select compatible hardware. Classes are preferred in the order shown.
Use spot instances Storage and network charges are additional to compute ceilings.
Ready to deploy Review your endpoint. We will reserve GPUs, load the model and enable its route when ready.
Your endpoint gets its own access token, available on the Overview tab. The gateway token also works.
Models
Datasets
Prepared data
Tokenizers
Users
Training
Rewards
Integration
Advanced
Servers —
Providers —
Advanced: registered fixed servers and the temporary cloud machines the controller provisions for jobs. Most operators only need to pick compute inside the job builder.
Add server
Fixed servers —
Temporary servers —
GPUs available —
GPUs allocated —
Search servers
Filter servers by lifecycle Fixed and temporary Fixed servers Temporary servers
Filter servers by status All statuses Available capacity Fully allocated Provisioning Cleanup required Offline
0 resources
Advanced: cloud provider accounts (Runpod, Vast.ai) whose balance, GPU catalog and prices feed the temporary-compute picker.
Add provider account
Register Hugging Face artifacts available as finetuning sources.
Add model
Synchronized datasets become available in job creation.
Sync datasets
Manage the private tokenizer artifacts offered to pretraining jobs.
Add tokenizer
Review Google access requests, approve operators, and delegate administrator access. Only administrators can open this section.
Add user
Models —
Datasets —
Last sync Never
Dataset owners Required One Hugging Face owner per line. No access token is exposed to the browser.
Checkpoint bucket Required Checkpoints, logs, and run status are kept here; final model artifacts go only to their model repository.
Sync now Save integration