Spaces:
Running on Zero
Running on Zero
Sync Capability Decision Lab from GitHub
Browse files
app.py
CHANGED
|
@@ -22,7 +22,6 @@ import torch
|
|
| 22 |
import laya
|
| 23 |
from kev.api import SystemOneRequest, output_tokens, to_answers, to_record
|
| 24 |
from kev.checkpoint import Checkpoint, LoadOptions
|
| 25 |
-
from transformers import AutoModelForMultimodalLM, AutoProcessor
|
| 26 |
|
| 27 |
NONE_ID = "__none__"
|
| 28 |
INFER_MAX_STATE = 8192
|
|
@@ -32,7 +31,6 @@ MODEL_IDS = {
|
|
| 32 |
"kev-0.8b": "jaredpalmer/kev-0.8b",
|
| 33 |
"kev-4b": "jaredpalmer/kev-4b",
|
| 34 |
"laya": "convaiinnovations/laya-typed-decisions",
|
| 35 |
-
"gemma-4-e4b": "google/gemma-4-E4B",
|
| 36 |
}
|
| 37 |
|
| 38 |
|
|
@@ -54,12 +52,6 @@ def _load_kev(repo_id: str):
|
|
| 54 |
KEV_08_CK, KEV_08_TOK, KEV_08 = _load_kev(MODEL_IDS["kev-0.8b"])
|
| 55 |
KEV_4_CK, KEV_4_TOK, KEV_4 = _load_kev(MODEL_IDS["kev-4b"])
|
| 56 |
LAYA = laya.load(MODEL_IDS["laya"], device="cuda")
|
| 57 |
-
GEMMA4_PROCESSOR = AutoProcessor.from_pretrained(MODEL_IDS["gemma-4-e4b"])
|
| 58 |
-
GEMMA4 = AutoModelForMultimodalLM.from_pretrained(
|
| 59 |
-
MODEL_IDS["gemma-4-e4b"],
|
| 60 |
-
torch_dtype=torch.bfloat16,
|
| 61 |
-
).to("cuda").eval()
|
| 62 |
-
|
| 63 |
KEV_MODELS = {
|
| 64 |
"kev-0.8b": (KEV_08_CK, KEV_08_TOK, KEV_08),
|
| 65 |
"kev-4b": (KEV_4_CK, KEV_4_TOK, KEV_4),
|
|
@@ -212,97 +204,6 @@ def _laya_predict(
|
|
| 212 |
}
|
| 213 |
|
| 214 |
|
| 215 |
-
def _extract_json_object(text: str) -> dict[str, Any]:
|
| 216 |
-
stripped = (text or "").strip()
|
| 217 |
-
try:
|
| 218 |
-
value = json.loads(stripped)
|
| 219 |
-
if isinstance(value, dict):
|
| 220 |
-
return value
|
| 221 |
-
except Exception:
|
| 222 |
-
pass
|
| 223 |
-
start = stripped.find("{")
|
| 224 |
-
end = stripped.rfind("}")
|
| 225 |
-
if start >= 0 and end > start:
|
| 226 |
-
return json.loads(stripped[start:end + 1])
|
| 227 |
-
raise ValueError(f"Gemma 4 response did not contain a JSON object: {stripped[:500]}")
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
def _gemma4_predict(case: dict[str, Any], reverse: bool = False):
|
| 231 |
-
candidates = list(case["candidates"])
|
| 232 |
-
if reverse:
|
| 233 |
-
candidates.reverse()
|
| 234 |
-
system = (
|
| 235 |
-
"You are a strict capability resolver. "
|
| 236 |
-
"Choose one supplied candidate only if using it exactly as described would fully satisfy the user's original intent. "
|
| 237 |
-
"Semantic relatedness is not enough and a nearby substitute does not count. "
|
| 238 |
-
"If none of the candidates fully satisfies the intent, choose null. "
|
| 239 |
-
"Do not consider permission or authorization. "
|
| 240 |
-
"Return JSON only with selected and reason. "
|
| 241 |
-
"selected must be one supplied candidate id or null. "
|
| 242 |
-
"Keep reason to one short sentence."
|
| 243 |
-
)
|
| 244 |
-
user_payload = {
|
| 245 |
-
"original_intent": case["intent"],
|
| 246 |
-
"requested_signature": case["signature"],
|
| 247 |
-
"candidates": [
|
| 248 |
-
{
|
| 249 |
-
"id": candidate["id"],
|
| 250 |
-
"name": candidate.get("name"),
|
| 251 |
-
"summary": candidate.get("summary"),
|
| 252 |
-
"provides": candidate.get("provides") or [],
|
| 253 |
-
"matching_operation_signatures": candidate.get("matching_operation_signatures") or [],
|
| 254 |
-
}
|
| 255 |
-
for candidate in candidates
|
| 256 |
-
],
|
| 257 |
-
"question": "Which candidate, if any, fully satisfies the original intent?",
|
| 258 |
-
}
|
| 259 |
-
messages = [
|
| 260 |
-
{"role": "system", "content": [{"type": "text", "text": system}]},
|
| 261 |
-
{"role": "user", "content": [{"type": "text", "text": json.dumps(user_payload)}]},
|
| 262 |
-
]
|
| 263 |
-
inputs = GEMMA4_PROCESSOR.apply_chat_template(
|
| 264 |
-
messages,
|
| 265 |
-
add_generation_prompt=True,
|
| 266 |
-
tokenize=True,
|
| 267 |
-
return_dict=True,
|
| 268 |
-
return_tensors="pt",
|
| 269 |
-
)
|
| 270 |
-
inputs = {k: v.to("cuda") if hasattr(v, "to") else v for k, v in inputs.items()}
|
| 271 |
-
torch.cuda.synchronize()
|
| 272 |
-
started = time.perf_counter()
|
| 273 |
-
with torch.inference_mode():
|
| 274 |
-
generated = GEMMA4.generate(
|
| 275 |
-
**inputs,
|
| 276 |
-
max_new_tokens=96,
|
| 277 |
-
do_sample=False,
|
| 278 |
-
)
|
| 279 |
-
torch.cuda.synchronize()
|
| 280 |
-
elapsed_ms = (time.perf_counter() - started) * 1000
|
| 281 |
-
input_len = inputs["input_ids"].shape[-1]
|
| 282 |
-
text = GEMMA4_PROCESSOR.decode(generated[0][input_len:], skip_special_tokens=True)
|
| 283 |
-
parsed = _extract_json_object(text)
|
| 284 |
-
selected = parsed.get("selected")
|
| 285 |
-
if selected is None or str(selected).strip().upper() == "NONE":
|
| 286 |
-
selected = None
|
| 287 |
-
else:
|
| 288 |
-
selected = str(selected).strip()
|
| 289 |
-
allowed = {candidate["id"] for candidate in candidates}
|
| 290 |
-
if selected not in allowed:
|
| 291 |
-
raise ValueError(f"Gemma 4 selected unknown candidate: {selected}")
|
| 292 |
-
return {
|
| 293 |
-
"order": [candidate["id"] for candidate in candidates],
|
| 294 |
-
"answer": {
|
| 295 |
-
"selected": selected,
|
| 296 |
-
"confidence": None,
|
| 297 |
-
"probabilities": {},
|
| 298 |
-
"probability_margin": None,
|
| 299 |
-
},
|
| 300 |
-
"elapsed_ms": round(elapsed_ms, 3),
|
| 301 |
-
"raw_text": text,
|
| 302 |
-
"reason": str(parsed.get("reason") or "").strip(),
|
| 303 |
-
}
|
| 304 |
-
|
| 305 |
-
|
| 306 |
def _score_case(case: dict[str, Any], selected: str | None) -> bool:
|
| 307 |
expected = set(case.get("expected") or [])
|
| 308 |
return selected in expected if expected else selected is None
|
|
@@ -367,11 +268,6 @@ def _run_model(
|
|
| 367 |
answer = raw.pop("answer")
|
| 368 |
answer["correct"] = _score_case(case, answer["selected"])
|
| 369 |
runs[label] = {"order": order, **answer, **raw}
|
| 370 |
-
elif model_name == "gemma-4-e4b":
|
| 371 |
-
raw = _gemma4_predict(case, reverse=reverse)
|
| 372 |
-
answer = raw.pop("answer")
|
| 373 |
-
answer["correct"] = _score_case(case, answer["selected"])
|
| 374 |
-
runs[label] = {**answer, **raw}
|
| 375 |
else:
|
| 376 |
raw = _laya_predict(state, questions, stream=stream)
|
| 377 |
answer = raw.pop("answer")
|
|
@@ -440,8 +336,6 @@ def _run_suite_impl(payload_json: str, parallel: bool = True, batch_size: int =
|
|
| 440 |
if parallel and len(requested) > 1:
|
| 441 |
# Give each resident model its own CUDA stream so independent kernels can
|
| 442 |
# overlap on the same ZeroGPU allocation where the GPU scheduler permits.
|
| 443 |
-
if "gemma-4-e4b" in requested:
|
| 444 |
-
raise ValueError("gemma-4-e4b is benchmarked in serial mode; do not mix it into the CUDA-stream stress test")
|
| 445 |
streams = {name: torch.cuda.Stream() for name in requested}
|
| 446 |
with ThreadPoolExecutor(max_workers=len(requested)) as pool:
|
| 447 |
futures = {
|
|
@@ -482,7 +376,7 @@ def run_suite_api(payload_json: str, parallel: bool = True, batch_size: int = 1)
|
|
| 482 |
with gr.Blocks(title="Capability Decision Lab") as demo:
|
| 483 |
gr.Markdown(
|
| 484 |
"# Capability Decision Lab\n"
|
| 485 |
-
"ZeroGPU benchmark service for Kev-0.8B, Kev-4B, Laya typed-decisions
|
| 486 |
)
|
| 487 |
payload_box = gr.Textbox(
|
| 488 |
label="Benchmark payload (JSON)",
|
|
|
|
| 22 |
import laya
|
| 23 |
from kev.api import SystemOneRequest, output_tokens, to_answers, to_record
|
| 24 |
from kev.checkpoint import Checkpoint, LoadOptions
|
|
|
|
| 25 |
|
| 26 |
NONE_ID = "__none__"
|
| 27 |
INFER_MAX_STATE = 8192
|
|
|
|
| 31 |
"kev-0.8b": "jaredpalmer/kev-0.8b",
|
| 32 |
"kev-4b": "jaredpalmer/kev-4b",
|
| 33 |
"laya": "convaiinnovations/laya-typed-decisions",
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
|
|
|
|
| 52 |
KEV_08_CK, KEV_08_TOK, KEV_08 = _load_kev(MODEL_IDS["kev-0.8b"])
|
| 53 |
KEV_4_CK, KEV_4_TOK, KEV_4 = _load_kev(MODEL_IDS["kev-4b"])
|
| 54 |
LAYA = laya.load(MODEL_IDS["laya"], device="cuda")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
KEV_MODELS = {
|
| 56 |
"kev-0.8b": (KEV_08_CK, KEV_08_TOK, KEV_08),
|
| 57 |
"kev-4b": (KEV_4_CK, KEV_4_TOK, KEV_4),
|
|
|
|
| 204 |
}
|
| 205 |
|
| 206 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
def _score_case(case: dict[str, Any], selected: str | None) -> bool:
|
| 208 |
expected = set(case.get("expected") or [])
|
| 209 |
return selected in expected if expected else selected is None
|
|
|
|
| 268 |
answer = raw.pop("answer")
|
| 269 |
answer["correct"] = _score_case(case, answer["selected"])
|
| 270 |
runs[label] = {"order": order, **answer, **raw}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
else:
|
| 272 |
raw = _laya_predict(state, questions, stream=stream)
|
| 273 |
answer = raw.pop("answer")
|
|
|
|
| 336 |
if parallel and len(requested) > 1:
|
| 337 |
# Give each resident model its own CUDA stream so independent kernels can
|
| 338 |
# overlap on the same ZeroGPU allocation where the GPU scheduler permits.
|
|
|
|
|
|
|
| 339 |
streams = {name: torch.cuda.Stream() for name in requested}
|
| 340 |
with ThreadPoolExecutor(max_workers=len(requested)) as pool:
|
| 341 |
futures = {
|
|
|
|
| 376 |
with gr.Blocks(title="Capability Decision Lab") as demo:
|
| 377 |
gr.Markdown(
|
| 378 |
"# Capability Decision Lab\n"
|
| 379 |
+
"ZeroGPU benchmark service for Kev-0.8B, Kev-4B, and Laya typed-decisions."
|
| 380 |
)
|
| 381 |
payload_box = gr.Textbox(
|
| 382 |
label="Benchmark payload (JSON)",
|