Text Classification
Transformers
Safetensors
English
nli
cross-encoder
qwen3.5
reranker
image-text-to-text
Instructions to use AlexWortega/openjev with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use AlexWortega/openjev with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="AlexWortega/openjev")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("AlexWortega/openjev", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 6,187 Bytes
26de23c | 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 | """Image JevBench bridge and reproducible public-example runner.
The published benchmark runner/sealed corpus are not in the public repository.
This bridge consumes its public example schema without passing alt text or gold
to inference. Output probabilities are explicitly normalized NLI entailment,
not calibrated forecasts. No temperature is fitted on benchmark examples.
"""
from __future__ import annotations
import argparse
import base64
import hashlib
import json
import math
from pathlib import Path
import time
import httpx
import numpy as np
class OpenJevImageAdapter:
def __init__(self, endpoint, model, timeout=180):
self.endpoint = endpoint.rstrip("/")
self.model = model
self.client = httpx.Client(timeout=timeout)
def close(self):
self.client.close()
def build_request(self, item, image_bytes):
options = item["options"]
criteria = {o["label"]: o["text"] for o in options}
if not criteria or len(criteria) != len(options):
raise ValueError("Options must have unique labels")
return {"model": self.model, "state": "An image: <<IMG>>",
"image_data": base64.b64encode(image_bytes).decode("ascii"),
"questions": {"decision": {"type": "choice", "instructions": item["question"],
"criteria": criteria}}}
def run(self, item, image_bytes):
body = self.build_request(item, image_bytes)
start = time.perf_counter()
r = self.client.post(self.endpoint + "/v1/systemone", json=body)
latency = time.perf_counter() - start
r.raise_for_status()
raw = r.json()
answer = raw["answers"]["decision"]
p = answer["probabilities"]
labels = list(body["questions"]["decision"]["criteria"])
if set(p) != set(labels) or any(isinstance(v, bool) or not isinstance(v, (int, float))
or not math.isfinite(v) or not 0 <= v <= 1 for v in p.values()):
raise ValueError("Invalid categorical probabilities")
total = sum(p.values())
if abs(total - 1) > 0.005:
raise ValueError("Probabilities do not sum to one")
# Remove API decimal rounding error, preserving score order.
p = {label: p[label] / total for label in labels}
choice = answer["choice"]
if choice not in p or p[choice] < max(p.values()):
raise ValueError("Choice disagrees with distribution")
return {"id": item.get("sourceItemId", item.get("key")), "choice": choice,
"probabilities": p, "probability_method": raw.get("probability_method", "unknown"),
"latency_s": latency, "image_sha256": hashlib.sha256(image_bytes).hexdigest(),
"request_sha256": hashlib.sha256(json.dumps(body, sort_keys=True).encode()).hexdigest(),
"raw": raw}
def summarize(rows):
good = [r for r in rows if "probabilities" in r]
labelled = [r for r in good if r.get("gold") is not None]
result = {"attempted": len(rows), "completed": len(good), "errors": len(rows)-len(good),
"scope": "published resized public examples only; not the full benchmark",
"probability_method": "normalized_entailment_v1; no fitted calibration",
"cost": None}
if good:
result.update({"p50_s": float(np.percentile([r["latency_s"] for r in good], 50)),
"p95_s": float(np.percentile([r["latency_s"] for r in good], 95))})
if labelled:
correct = [r["choice"] == r["gold"] for r in labelled]
conf = [r["probabilities"][r["choice"]] for r in labelled]
ece = 0.0
for i in range(10):
indices = [j for j, c in enumerate(conf) if min(int(c*10), 9) == i]
if indices:
ece += abs(sum(conf[j] - correct[j] for j in indices)) / len(labelled)
result.update({"scored": len(labelled), "correct": sum(correct), "accuracy": sum(correct)/len(labelled),
"top_label_ece_10_bins": ece,
"brier_multiclass": float(np.mean([sum((p-(k==r["gold"]))**2
for k, p in r["probabilities"].items()) for r in labelled]))})
return result
def main():
ap = argparse.ArgumentParser(__doc__)
ap.add_argument("--items", type=Path, required=True, help="JSON array exported from PUBLIC_IMAGE_JEV_EXAMPLES")
ap.add_argument("--assets-root", type=Path, required=True, help="Repository public/ directory")
ap.add_argument("--endpoint", required=True)
ap.add_argument("--model", required=True)
ap.add_argument("--output", type=Path, required=True)
args = ap.parse_args()
items = json.loads(args.items.read_text())
args.output.mkdir(parents=True, exist_ok=True)
adapter = OpenJevImageAdapter(args.endpoint, args.model)
rows = []
try:
with (args.output / "predictions.jsonl").open("x") as f:
for item in items:
try:
root = args.assets_root.resolve()
path = (root / item["image"].lstrip("/")).resolve()
if not path.is_relative_to(root):
raise ValueError("Image escapes assets root")
row = adapter.run(item, path.read_bytes())
row["gold"] = item.get("correctLabel")
if row["gold"] is not None and row["gold"] not in row["probabilities"]:
raise ValueError("Gold is not an option")
except Exception as e:
row = {"id": item.get("sourceItemId", item.get("key")), "error": str(e)}
rows.append(row)
f.write(json.dumps(row) + "\n")
f.flush()
print(json.dumps({k: v for k, v in row.items() if k != "raw"}), flush=True)
finally:
adapter.close()
report = summarize(rows)
(args.output / "summary.json").write_text(json.dumps(report, indent=2) + "\n")
print(json.dumps(report, indent=2))
if report["errors"]:
raise SystemExit(1)
if __name__ == "__main__":
main()
|