Image-Text-to-Text
Transformers
Safetensors
English
qwen3_5
decision-model
system-one
calibrated-probabilities
typed-decisions
ainode
merged-lora
conversational
Eval Results (legacy)
Instructions to use frontier-infra/jebadiah-9b-v2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use frontier-infra/jebadiah-9b-v2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="frontier-infra/jebadiah-9b-v2") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("frontier-infra/jebadiah-9b-v2") model = AutoModelForMultimodalLM.from_pretrained("frontier-infra/jebadiah-9b-v2", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use frontier-infra/jebadiah-9b-v2 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "frontier-infra/jebadiah-9b-v2" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "frontier-infra/jebadiah-9b-v2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/frontier-infra/jebadiah-9b-v2
- SGLang
How to use frontier-infra/jebadiah-9b-v2 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "frontier-infra/jebadiah-9b-v2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "frontier-infra/jebadiah-9b-v2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "frontier-infra/jebadiah-9b-v2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "frontier-infra/jebadiah-9b-v2", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use frontier-infra/jebadiah-9b-v2 with Docker Model Runner:
docker model run hf.co/frontier-infra/jebadiah-9b-v2
File size: 6,384 Bytes
b1d222a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | """Loading a base model (plus an optional adapter) and reading option probabilities off its logits.
Shared by the trainer, the evaluator and the /v1/systemone server: one code path from a
rendered prompt to a probability per option key. No generation anywhere.
"""
from __future__ import annotations
import json
import os
import torch
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
from jebadiah_prompt import Renderer, Rendered
def load_tokenizer(base: str, revision: str | None = None):
tok = AutoTokenizer.from_pretrained(base, revision=revision)
if tok.pad_token_id is None:
tok.pad_token = tok.eos_token
tok.padding_side = "right"
return tok
def model_class(base: str, revision: str | None = None):
cfg = AutoConfig.from_pretrained(base, revision=revision)
if getattr(cfg, "model_type", "") == "qwen3_5":
# The text-only class: the multimodal ConditionalGeneration class would load a vision
# tower nothing here uses.
from transformers import Qwen3_5ForCausalLM
return Qwen3_5ForCausalLM
return AutoModelForCausalLM
def load_base(base: str, revision: str | None = None, attn_implementation: str = "sdpa",
dtype=torch.bfloat16, device: str = "cuda"):
cls = model_class(base, revision)
model = cls.from_pretrained(base, revision=revision, dtype=dtype, device_map=device,
attn_implementation=attn_implementation)
model.config.use_cache = False
return model
def load_adapter(model, adapter_dir: str):
from peft import PeftModel
return PeftModel.from_pretrained(model, adapter_dir)
def core_of(model):
"""The CausalLM underneath a PEFT wrapper (LoRA layers stay injected in place)."""
return model.get_base_model() if hasattr(model, "get_base_model") else model
# v1: the candidate-token logits are computed in fp32 from the last hidden state, W[cand].float()
# @ h.float(), the fix the v0 report asks for. The bf16 lm_head put two option tokens on the same
# bf16 logit often enough that ties decided 0.4 to 3 percent of picks between identical repeats.
# JEB_FP32_HEAD=0 restores the v0 read (bf16 lm_head, then cast).
FP32_CANDIDATE_LOGITS = os.environ.get("JEB_FP32_HEAD", "1") != "0"
def option_logits(model, input_ids: torch.Tensor, attention_mask: torch.Tensor,
cand_ids: torch.Tensor) -> torch.Tensor:
"""Logits over each row's candidate tokens at its answer position (the last real token).
cand_ids is [B, Kmax] padded with -1; padded slots come back as -inf. Only the answer
position goes through the head, so memory does not scale with vocab x sequence."""
core = core_of(model)
hidden = core.model(input_ids=input_ids, attention_mask=attention_mask).last_hidden_state
last = attention_mask.sum(dim=1) - 1
h_last = hidden[torch.arange(hidden.shape[0], device=hidden.device), last]
safe = cand_ids.clamp(min=0)
if FP32_CANDIDATE_LOGITS:
head = core.lm_head
w = head.weight[safe].float() # [B, K, H], a few KB per row
cand = torch.einsum("bkh,bh->bk", w, h_last.float())
if getattr(head, "bias", None) is not None:
cand = cand + head.bias[safe].float()
else:
cand = core.lm_head(h_last).float().gather(1, safe)
return cand.masked_fill(cand_ids < 0, float("-inf"))
class Scorer:
"""Batches of (state, question) -> probabilities over the option keys, with an optional
temperature per question type applied to the candidate logits before the softmax."""
def __init__(self, model, tokenizer, max_tokens: int = 2048, temperatures: dict | None = None,
device: str = "cuda", renderer: Renderer | None = None):
self.model = model
self.tok = tokenizer
self.renderer = renderer or Renderer(tokenizer, max_tokens)
self.max_tokens = max_tokens
self.temperatures = temperatures or {}
self.device = device
self.model.eval()
@property
def max_options(self) -> int:
return self.renderer.max_options
def render(self, state, q: dict, order: list | None = None) -> Rendered:
return self.renderer.render(state, q, order)
@torch.no_grad()
def score_rendered(self, items: list[tuple[Rendered, str]]) -> list[list[float]]:
"""items: (rendered, question type). Returns one probability list per item, in the
rendered key order, after that type's temperature (1.0 when unset)."""
enc = self.tok([r.prompt for r, _ in items], return_tensors="pt", padding=True,
add_special_tokens=False).to(self.device)
kmax = max(len(r.cand_ids) for r, _ in items)
cand = torch.full((len(items), kmax), -1, dtype=torch.long, device=self.device)
for i, (r, _) in enumerate(items):
cand[i, :len(r.cand_ids)] = torch.tensor(r.cand_ids, device=self.device)
logits = option_logits(self.model, enc.input_ids, enc.attention_mask, cand)
out = []
for i, (r, qtype) in enumerate(items):
t = float(self.temperatures.get(qtype, 1.0))
p = torch.softmax(logits[i, :len(r.cand_ids)] / t, dim=-1)
out.append(p.tolist())
return out
def score(self, state, questions: dict, orders: dict | None = None, batch_size: int = 8):
"""All questions of one request, each over the same state. Returns {qid: (keys, probs)}."""
rendered = {qid: self.render(state, q, (orders or {}).get(qid)) for qid, q in questions.items()}
qids = list(rendered)
result = {}
for i in range(0, len(qids), batch_size):
chunk = qids[i:i + batch_size]
probs = self.score_rendered([(rendered[qid], questions[qid]["type"]) for qid in chunk])
for qid, p in zip(chunk, probs):
result[qid] = (rendered[qid].keys, p)
return result
def read_temperatures(adapter_dir: str | None) -> dict:
if not adapter_dir:
return {}
path = os.path.join(adapter_dir, "temperatures.json")
if os.path.exists(path):
return {k: float(v) for k, v in json.load(open(path))["temperatures"].items()}
return {}
def template_sha256(tokenizer) -> str:
import hashlib
return hashlib.sha256((tokenizer.chat_template or "").encode("utf-8")).hexdigest()
|