Text Generation
Safetensors
GGUF
English
dory
decision-making
lora
eider
bf16
nvfp4
llama-cpp
conversational
decision-model
Instructions to use rdaum/decisive-dory with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use rdaum/decisive-dory with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf rdaum/decisive-dory:Q8_0 # Run inference directly in the terminal: llama cli -hf rdaum/decisive-dory:Q8_0
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf rdaum/decisive-dory:Q8_0 # Run inference directly in the terminal: llama cli -hf rdaum/decisive-dory:Q8_0
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf rdaum/decisive-dory:Q8_0 # Run inference directly in the terminal: ./llama-cli -hf rdaum/decisive-dory:Q8_0
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf rdaum/decisive-dory:Q8_0 # Run inference directly in the terminal: ./build/bin/llama-cli -hf rdaum/decisive-dory:Q8_0
Use Docker
docker model run hf.co/rdaum/decisive-dory:Q8_0
- Llama new
- LM Studio
- Jan
- vLLM
How to use rdaum/decisive-dory with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "rdaum/decisive-dory" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "rdaum/decisive-dory", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/rdaum/decisive-dory:Q8_0
- Ollama
How to use rdaum/decisive-dory with Ollama:
ollama run hf.co/rdaum/decisive-dory:Q8_0
- Unsloth Desktop
- Pi
How to use rdaum/decisive-dory with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf rdaum/decisive-dory:Q8_0
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "rdaum/decisive-dory:Q8_0" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use rdaum/decisive-dory with Docker Model Runner:
docker model run hf.co/rdaum/decisive-dory:Q8_0
- Lemonade
How to use rdaum/decisive-dory with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull rdaum/decisive-dory:Q8_0
Run and chat with the model
lemonade run user.decisive-dory-Q8_0
List all available models
lemonade list
- Hermes Agent
How to use rdaum/decisive-dory with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf rdaum/decisive-dory:Q8_0
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default rdaum/decisive-dory:Q8_0
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use rdaum/decisive-dory with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf rdaum/decisive-dory:Q8_0
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "rdaum/decisive-dory:Q8_0" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Download adapter/dory_lora.py from rdaum/decisive-dory: direct link, hf CLI and curl.
- Browser
- Download file 11.5 kB
-
https://huggingface.co/rdaum/decisive-dory/resolve/main/adapter/dory_lora.py
- Command line
-
hf download hf://rdaum/decisive-dory/adapter/dory_lora.py
-
curl -L -o dory_lora.py https://huggingface.co/rdaum/decisive-dory/resolve/main/adapter/dory_lora.py
11.5 kB
| """BF16 Dory with frozen checkpoint weights and trainable linear LoRA adapters. | |
| The nGPT equations follow the independent dory-checkpoint-reference.py oracle | |
| and vLLM revision 55076950b6c155f384d6766d63563c3bc20a0e3f. This is a training | |
| experiment, not a replacement for Eider's CUDA serving implementation. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import math | |
| from pathlib import Path | |
| import torch | |
| from safetensors import safe_open | |
| from safetensors.torch import load_file, save_file | |
| from torch import nn | |
| from torch.nn import functional as F | |
| from torch.utils.checkpoint import checkpoint | |
| def norm(x): | |
| value = x.float() | |
| return (value * torch.rsqrt(value.square().sum(-1, keepdim=True) + 1e-6)).to( | |
| x.dtype | |
| ) | |
| class Linear(nn.Module): | |
| def __init__(self, weight, rank, alpha): | |
| super().__init__() | |
| self.register_buffer("weight", weight) | |
| self.scale = alpha / rank if rank else 0 | |
| if rank: | |
| self.lora_a = nn.Parameter( | |
| torch.empty(rank, weight.shape[1], device=weight.device) | |
| ) | |
| self.lora_b = nn.Parameter( | |
| torch.zeros(weight.shape[0], rank, device=weight.device) | |
| ) | |
| nn.init.kaiming_uniform_(self.lora_a, a=math.sqrt(5)) | |
| else: | |
| self.register_parameter("lora_a", None) | |
| self.register_parameter("lora_b", None) | |
| def forward(self, x): | |
| base = F.linear(x, self.weight) | |
| if self.lora_a is None: | |
| return base | |
| delta = F.linear(F.linear(x, self.lora_a.to(x.dtype)), self.lora_b.to(x.dtype)) | |
| return (base.float() + self.scale * delta.float()).to(x.dtype) | |
| class Layer(nn.Module): | |
| def __init__(self, config, index, read, rank, alpha): | |
| super().__init__() | |
| self.config = config | |
| self.kind = config["layer_types"][index] | |
| prefix = f"backbone.layers.{index}" | |
| mixer = prefix + ".mixer" | |
| std = config["initializer_range"] | |
| if self.kind == "mlp": | |
| names = ("gate_proj", "up_proj", "down_proj") | |
| scale = math.sqrt(config["hidden_size"]) | |
| self.register_buffer("suv_gate", read(mixer + ".suv_gate").float() * scale) | |
| self.register_buffer("suv_up", read(mixer + ".suv_up").float() * scale) | |
| rate = read(prefix + ".mlp_alpha") | |
| else: | |
| names = ("q_proj", "k_proj", "v_proj", "g_proj", "o_proj") | |
| dim = config["head_dim"] | |
| self.register_buffer( | |
| "sqk", (read(mixer + ".sqk").float() * (math.sqrt(dim) / std)).square() | |
| ) | |
| g0 = config.get("attention_output_gate_logit_scale_init") or math.sqrt( | |
| config["hidden_size"] | |
| ) | |
| self.register_buffer( | |
| "s_gate", | |
| (read(mixer + ".s_gate").float() * (math.sqrt(g0) / std)).square(), | |
| ) | |
| rate = read(prefix + ".attn_alpha") | |
| self.register_buffer( | |
| "rate", (rate.float() * config["ngpt_alpha_init"] / std).abs() | |
| ) | |
| self.projections = nn.ModuleDict( | |
| { | |
| name: Linear(read(mixer + "." + name + ".weight"), rank, alpha) | |
| for name in names | |
| } | |
| ) | |
| def forward(self, h, rotary, sliding_mask, reference=False): | |
| p, c, dtype = self.projections, self.config, h.dtype | |
| if self.kind == "mlp": | |
| gate = (p["gate_proj"](h).float() * self.suv_gate).to(dtype) | |
| up = (p["up_proj"](h).float() * self.suv_up).to(dtype) | |
| out = p["down_proj"](norm((F.silu(gate.float()) * up.float()).to(dtype))) | |
| else: | |
| nq, nk, dim = ( | |
| c["num_attention_heads"], | |
| c["num_key_value_heads"], | |
| c["head_dim"], | |
| ) | |
| cos, sin = rotary[self.kind] | |
| def rope(x): | |
| a, b = x.float().chunk(2, -1) | |
| return torch.cat((a * cos - b * sin, b * cos + a * sin), -1).to(dtype) | |
| q = norm(rope(p["q_proj"](h).reshape(*h.shape[:-1], nq, dim))) | |
| k = norm(rope(p["k_proj"](h).reshape(*h.shape[:-1], nk, dim))) | |
| q = (q.float() * self.sqk.reshape(nq, dim)).to(dtype) | |
| v = p["v_proj"](h).reshape(*h.shape[:-1], nk, dim) | |
| # Repeat GQA heads explicitly so both SDPA backends and the oracle | |
| # use the same layout. Batch rows retain independent attention. | |
| q = q.transpose(1, 2) | |
| k = k.repeat_interleave(nq // nk, 2).transpose(1, 2) | |
| v = v.repeat_interleave(nq // nk, 2).transpose(1, 2) | |
| mask = sliding_mask if self.kind == "sliding_attention" else None | |
| if reference: | |
| if mask is None: | |
| mask = torch.ones( | |
| h.shape[1], h.shape[1], device=h.device, dtype=torch.bool | |
| ).tril() | |
| scores = (q.float() @ k.float().transpose(-1, -2)) / math.sqrt(dim) | |
| out = ( | |
| scores.masked_fill(~mask, -torch.inf).softmax(-1) @ v.float() | |
| ).to(dtype) | |
| else: | |
| out = F.scaled_dot_product_attention( | |
| q, k, v, attn_mask=mask, is_causal=mask is None | |
| ) | |
| out = out.transpose(1, 2).reshape(*h.shape[:-1], nq * dim) | |
| gate = p["g_proj"](h) | |
| out = norm( | |
| (out.float() * torch.sigmoid(gate.float() * self.s_gate)).to(dtype) | |
| ) | |
| out = p["o_proj"](out) | |
| a, b = norm(h).float(), norm(out).float() | |
| return norm(a + self.rate * (b - a)).to(dtype) | |
| class Dory(nn.Module): | |
| def __init__(self, config, read, *, rank=8, alpha=16, loops=2, checkpointing=False): | |
| super().__init__() | |
| if config.get("model_type") != "dory" or config.get("quantization_config"): | |
| raise ValueError("requires an unquantized Dory checkpoint") | |
| if loops < 1 or rank < 0 or alpha <= 0: | |
| raise ValueError("invalid loop count or adapter dimensions") | |
| self.config, self.loops, self.checkpointing = config, loops, checkpointing | |
| self.register_buffer("embedding", read("backbone.embeddings.weight")) | |
| self.register_buffer("head", read("lm_head.weight")) | |
| self.register_buffer( | |
| "head_scale", | |
| read("lm_head.logit_scale").float() / config["initializer_range"], | |
| ) | |
| self.layers = nn.ModuleList( | |
| Layer(config, i, read, rank, alpha) | |
| for i in range(config["num_hidden_layers"]) | |
| ) | |
| def load(cls, path: Path, *, device="cuda", **kwargs): | |
| config = json.loads((path / "config.json").read_text()) | |
| with safe_open( | |
| path / "model.safetensors", framework="pt", device="cpu" | |
| ) as weights: | |
| consumed = set() | |
| def read(name): | |
| value = weights.get_tensor(name) | |
| if value.dtype != torch.bfloat16: | |
| raise ValueError(f"expected BF16 weight: {name}") | |
| consumed.add(name) | |
| return value.to(device) | |
| model = cls(config, read, **kwargs) | |
| if consumed != set(weights.keys()): | |
| raise ValueError( | |
| f"unconsumed checkpoint tensors: {set(weights.keys()) - consumed}" | |
| ) | |
| return model | |
| def forward(self, ids, labels=None, *, lengths=None, reference=False): | |
| c = self.config | |
| single = ids.ndim == 1 | |
| if single: | |
| ids = ids.unsqueeze(0) | |
| positions = torch.arange(ids.shape[1], device=ids.device) | |
| dim = c["head_dim"] | |
| rotary = {} | |
| for kind, params in c["rope_parameters"].items(): | |
| angles = positions.float()[:, None] * params["rope_theta"] ** ( | |
| -torch.arange(dim // 2, device=ids.device).float() / (dim // 2) | |
| ) | |
| rotary[kind] = (angles.cos()[:, None, :], angles.sin()[:, None, :]) | |
| # For short training rows the sliding mask equals the causal mask. | |
| sliding_mask = None | |
| if ids.shape[1] > c["sliding_window"]: | |
| distance = positions[:, None] - positions[None, :] | |
| sliding_mask = (distance >= 0) & (distance < c["sliding_window"]) | |
| def apply(h, start, end): | |
| for layer in self.layers[start:end]: | |
| if self.training and self.checkpointing and not reference: | |
| h = checkpoint(layer, h, rotary, sliding_mask, use_reentrant=False) | |
| else: | |
| # Keep the serial evaluator and oracle eager. Their batch-one, | |
| # inference-only graphs otherwise compete with training graphs. | |
| forward = ( | |
| layer if self.training and not reference else layer.forward | |
| ) | |
| h = forward(h, rotary, sliding_mask, reference) | |
| return h | |
| ni, nr = c["n_input_layers"], c["n_recurrent_layers"] | |
| h = apply(F.embedding(ids, self.embedding), 0, ni) | |
| input_h = h | |
| for _ in range(self.loops): | |
| h = norm(h + input_h) | |
| h = norm(apply(h, ni, ni + nr)) | |
| h = apply(h, ni + nr, len(self.layers)) | |
| # Right-padding is always after each real query, so causal attention | |
| # excludes it without a padding mask. Read only each row's final token. | |
| last = ( | |
| h[:, -1] | |
| if lengths is None | |
| else h[torch.arange(ids.shape[0], device=ids.device), lengths - 1] | |
| ) | |
| weight = self.head if labels is None else self.head[labels] | |
| scale = self.head_scale if labels is None else self.head_scale[labels] | |
| logits = ( | |
| torch.bmm(weight, last.unsqueeze(-1)).squeeze(-1) | |
| if labels is not None and labels.ndim == 2 | |
| else F.linear(last, weight) | |
| ).float() * scale | |
| return logits.squeeze(0) if single else logits | |
| def compile_layers(self): | |
| # Compile individual layers so recurrent traversals reuse their graphs. | |
| # Keep the BF16 rounding points used by the eager nGPT equations. | |
| # All layer kinds share Layer.forward's code cache. Attention masks, | |
| # input gradients and shape guards produce more than eight variants when | |
| # training batches cross the sliding-window boundary. Keep a bounded | |
| # cache large enough for those variants; fullgraph raises on overflow. | |
| torch._dynamo.config.recompile_limit = max( | |
| torch._dynamo.config.recompile_limit, 32 | |
| ) | |
| for layer in self.layers: | |
| layer.compile( | |
| fullgraph=True, | |
| dynamic=True, | |
| options={"emulate_precision_casts": True}, | |
| ) | |
| def save_adapter(self, path): | |
| save_file( | |
| { | |
| name: p.detach().cpu().contiguous() | |
| for name, p in self.named_parameters() | |
| }, | |
| str(path), | |
| ) | |
| def load_adapter(self, path): | |
| values = load_file(str(path)) | |
| params = dict(self.named_parameters()) | |
| if values.keys() != params.keys(): | |
| raise ValueError("adapter does not match the model's projection modules") | |
| with torch.no_grad(): | |
| for name, p in params.items(): | |
| if p.shape != values[name].shape: | |
| raise ValueError(f"adapter shape mismatch: {name}") | |
| p.copy_(values[name]) | |