Repository navigation
v0.3.1a3 (beta)
Pre-release
Pre-release
This release fixes the router masks and the lazy-expert decode. It also adds a document-level cluster objective, MLX multimodal training in all six stages, tool-call SFT records and tool-call parsing in chronos serve, a kernel-level MLX cache limit and progress-based ETAs.
Added
cluster_locality_mode="segment": the cluster objective treats each document as one unit.- Documents are found from the tokens:
<|endoftext|>separators, and long documents are cut everycluster_locality_windowtokens. No labels or domain tags are used. - The loss is
1 − I(document; cluster) / log C, pooled over real tokens and all virtual layers. - The default stays
"window", the 0.3.1a2 objective. - Torch and MLX give the same value and gradient. The option is on the Web UI config page (advanced) in four languages.
- Documents are found from the tokens:
- MLX multimodal training.
chronos.mlx.multimodalports the image patch encoder, the audio conv encoder and the gated cross-attention fusion.- Pre-encoded
*_embedsinputs and the per-modality and per-token masks work as in Torch. - Logits match Torch within 2e-4 in FP32 tests.
- MLX checkpoints save and load the fusion weights, and
freeze_modality_encodersworks on MLX. run_mlx_stagetakes media in all six stages: pretrain, SFT, DPO, ORPO, GRPO and distill.- DPO and ORPO: the chosen and rejected answers condition on the prompt's media.
- GRPO: every rollout conditions on the prompt's media. The rollout encodes the media once and reuses it at every decode step, with identical logits. The policy update re-encodes the media, so the encoders get gradients.
- Distill: the student gets the media. A text-only teacher is accepted, as on PyTorch.
- Pre-encoded
- Multimodal preference and GRPO data.
MultimodalStreamingDPODatasetandpreference_collatereadchosen/rejectedrecords that carryimage,audioor*_embedsfields, the same fields SFT uses.load_grpo_prompt_recordskeeps each prompt's record so the media can be resolved per step.record_mediais the shared resolver.- The Web UI selects these automatically when the dataset contains media.
- The PyTorch DPO, ORPO and GRPO trainers are text-only. With media,
autopicks MLX, and an explicit PyTorch backend raises an error instead of dropping the media.
- Tool calls in the chat template.
toolsrender as one<tools>system block.- The assistant's
tool_callsrender as<tool_call>{json}</tool_call>lines, andtoolturns carry the results. - Conversations without tools render exactly as before.
chronos.data.chat_recordsprovidesrender_chat,encode_chatandwrite_sft_records.- Supervised tokens: the assistant text, its tool calls and
<|im_end|>. - Context tokens: system and user turns, tool definitions and tool results.
- Records are written as
.bin/.idx/.plen/.lmask.
- Supervised tokens: the assistant text, its tool calls and
SFTRecordsreads.lmask(one uint8 per token). When present it replaces the.plenprompt rule. Older readers still use.plen.chronos servesupports tool calls end to end.- It passes
toolsand the assistant'stool_callsfrom/api/chatand/v1/chat/completionsinto the template. - When the request has
tools, it parses<tool_call>blocks in the output into structured calls./api/chatreturns Ollamamessage.tool_calls./v1/chat/completionsreturns OpenAItool_callswith string arguments andfinish_reason: "tool_calls". - Streaming parses the calls as they are generated, and no client sees part of a tag.
- An invalid block stays in the content. Requests without
toolsare unchanged. chronos.serving.tool_callsholds the parser.
- It passes
chronos.mlx.memory: every MLX model sets the MLX buffer-cache limit before it allocates weights.- The limit is
min(RAM/8, 16 GiB). - A recipe (
extra.mlx_cache_limit_gb) orCHRONOS_MLX_CACHE_LIMIT_GBcan lower it. Larger values are clamped to the limit. LongRunlogs the limit and records it inruntime.json.- Only reclaimable cache is bounded. Weights, activations and gradients are not.
- The limit is
- Monitor and Web UI ETAs follow measured progress.
- A phase ends at the first of three points: the wall deadline, the step total, or
target_passes. - The pass rate comes from row timestamps over the last 30 minutes, so evaluation and checkpoint time count.
- Each phase shows its estimated end and which of the three points sets it.
- Later phases also get the current phase's unused time.
- A stopped or failed run shows its remaining work and its state, but no end time.
- A phase ends at the first of three points: the wall deadline, the step total, or
Fixed
- Router auxiliary losses and routing telemetry counted right-padding in SFT batches. Balance, entropy, lookahead and cluster terms now use only real tokens. Packed pretraining is unchanged.
- Training telemetry now sums every micro-batch of a step. Before, it sampled only the last one.
SFTRecordswith.lmask: under NumPy 2, the -100 context labels of uint16 shards wrapped to 65436. Labels are now built in int32.- MLX lazy-expert decode used the per-expert loop, which sums in a different order from the full-memory grouped kernel. In BF16 on the GPU this flipped near-tied greedy tokens: agreement was 31.25 % at every budget. The lazy path now runs the same grouped kernel over the live experts. Lazy and full greedy now agree at every budget (measured: 0.278, 0.5, 0.778 and 1.0 of experts, planned and window residency).
Pre-release. Install with pip install --pre Project_Chronos==0.3.1a3. Kernel only; chronos-translate stays a repo demo. Training-data licences are unknown, so no weights are published.