Files
ollama/create/laya.go
a00d083bb5 mlx: System one support (#18701)
* mlxrunner: restore System One scoring

Carry the MLX implementation and its tests from the original System One
commit. The API/compiler and llama-server implementation already exist on
the release branch, so retain those versions. Adapt the optional model test
to the renamed decision package and its explicit rendering/context setup.

(cherry picked from commit 26e546ddb3)

* Enable MLX System One and add regression coverage

* mlxrunner: add Laya support for System One

Import Laya checkpoints and implement bidirectional decision scoring.

* mlxrunner: release cached buffers after System One scoring

* decision: match Tev1 and Nimble publisher prompt formats

Select Tev1 prompts using renderer metadata and fix JSON formatting, with regression coverage for GGUF and MLX.

* mlx: support Clef and Clef Flash decision models

Add model import, quantization safeguards, and text/image scoring with the Clef joint decision head.

* support vision capabilities for decision models

* Make Clef scoring cancellable between prefill chunks

Preserve joint-head inputs and test cancellation, cleanup, and recovery.

* mlx: separate decision preparation and readout from forward

Let serial and batched scoring share model-owned preparation and readout
without duplicating architecture-specific logic in the runner.

* mlx: add Strands Decider support

* implement caching

---------

Co-authored-by: ParthSareen <parth.sareen@ollama.com>
2026-10-03 13:17:21 -07:00

51 lines
1.9 KiB
Go

package create
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
)
// Laya ships an encoder config and a decision config rather than a root HF
// config. Keep both verbatim and add only the descriptor Ollama uses to dispatch.
func readLayaConfig(dir string) (sourceModelConfig, json.RawMessage, error) {
var decision struct {
Encoder string `json:"encoder"`
MaxLen int `json:"max_len"`
HeadLayers *int `json:"head_layers"`
}
data, err := os.ReadFile(filepath.Join(dir, "rl_agent_config.json"))
if err != nil {
return sourceModelConfig{}, nil, err
}
if err := json.Unmarshal(data, &decision); err != nil {
return sourceModelConfig{}, nil, fmt.Errorf("parse rl_agent_config.json: %w", err)
}
var encoder struct {
ModelType string `json:"model_type"`
HiddenSize int `json:"hidden_size"`
NumHiddenLayers int `json:"num_hidden_layers"`
NumAttentionHeads int `json:"num_attention_heads"`
VocabSize int `json:"vocab_size"`
}
data, err = os.ReadFile(filepath.Join(dir, "encoder", "config.json"))
if err != nil {
return sourceModelConfig{}, nil, err
}
if err := json.Unmarshal(data, &encoder); err != nil {
return sourceModelConfig{}, nil, fmt.Errorf("parse encoder/config.json: %w", err)
}
if decision.Encoder == "" || decision.MaxLen <= 0 || decision.HeadLayers == nil || encoder.ModelType != "modernbert" {
return sourceModelConfig{}, nil, fmt.Errorf("unsupported Laya source configuration")
}
cfg := sourceModelConfig{ModelType: "laya", Architectures: []string{"LayaForDecision"}}
data, err = json.Marshal(map[string]any{
"architectures": cfg.Architectures, "model_type": cfg.ModelType,
"hidden_size": encoder.HiddenSize, "num_hidden_layers": encoder.NumHiddenLayers,
"num_attention_heads": encoder.NumAttentionHeads, "vocab_size": encoder.VocabSize,
"max_position_embeddings": decision.MaxLen,
})
return cfg, data, err
}