Image-Text-to-Text
Transformers
Safetensors
English
Chinese
sensenova_loop
text-generation
nvfp4
modelopt
quantized
multimodal
looped-transformer
mhc
mtp
custom_code
conversational
8-bit precision
Instructions to use gitcommit90/SenseNova-Loop-9B-Preview-NVFP4 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use gitcommit90/SenseNova-Loop-9B-Preview-NVFP4 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="gitcommit90/SenseNova-Loop-9B-Preview-NVFP4", trust_remote_code=True) 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 AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("gitcommit90/SenseNova-Loop-9B-Preview-NVFP4", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use gitcommit90/SenseNova-Loop-9B-Preview-NVFP4 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4", "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/gitcommit90/SenseNova-Loop-9B-Preview-NVFP4
- SGLang
How to use gitcommit90/SenseNova-Loop-9B-Preview-NVFP4 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 "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4" \ --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": "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4", "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 "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4" \ --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": "gitcommit90/SenseNova-Loop-9B-Preview-NVFP4", "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 gitcommit90/SenseNova-Loop-9B-Preview-NVFP4 with Docker Model Runner:
docker model run hf.co/gitcommit90/SenseNova-Loop-9B-Preview-NVFP4
Download runtime-v2/bench/screen.py from gitcommit90/SenseNova-Loop-9B-Preview-NVFP4: direct link, hf CLI and curl.
- Browser
- Download file 8.66 kB
-
https://huggingface.co/gitcommit90/SenseNova-Loop-9B-Preview-NVFP4/resolve/main/runtime-v2/bench/screen.py
- Command line
-
hf download hf://gitcommit90/SenseNova-Loop-9B-Preview-NVFP4/runtime-v2/bench/screen.py
-
curl -L -o screen.py https://huggingface.co/gitcommit90/SenseNova-Loop-9B-Preview-NVFP4/resolve/main/runtime-v2/bench/screen.py
8.66 kB
| #!/usr/bin/env python | |
| """Fast A/B screening benchmark for the SGLang server (OpenAI chat API, streaming). | |
| .venv-eval/bin/python runtime-v2/bench/screen.py --base-url http://127.0.0.1:30080 \ | |
| --model sensenova-loop-9b-nvfp4 --concurrency 1,4,8 --num-requests 4 --output-tokens 256 \ | |
| --prompt-kind synthetic --repeat 2 --out runtime-v2/runs/screen_baseline.json | |
| Prompts follow eval/perf_bench.py: unique per-request prefix (plus a per-run tag, so no prefix-cache | |
| hits even across runs), temperature 0, ignore_eos + min_tokens = max_tokens, thinking off. | |
| --prompt-kind: synthetic (perf_bench text, default 1024 tok), code (fixed coding prompt), doc (~4k-token | |
| document + summarization instruction). MTP acceptance: per-request `sglext.spec_tokens_details` | |
| (requested via return_spec_tokens_details) and the server's cumulative /server_info avg_spec_accept_length. | |
| """ | |
| from __future__ import annotations | |
| import argparse, json, statistics, sys, time, uuid | |
| from concurrent.futures import ThreadPoolExecutor | |
| from pathlib import Path | |
| import requests | |
| ROOT = Path(__file__).resolve().parents[2] | |
| sys.path.insert(0, str(ROOT / "evaluation" / "harness")) | |
| from perf_bench import DEFAULT_TOK, build_prompt_text, pct # noqa: E402 | |
| CODE_PROMPT = ("Implement an LRU cache in Python with O(1) get and put (no functools), explain the design " | |
| "and its complexity, then write a thorough pytest test suite covering eviction order, updates " | |
| "of existing keys, capacity 1 and invalid capacity. Finally discuss thread-safety trade-offs.") | |
| def make_prompt(args): | |
| if args.prompt_kind == "code": | |
| return CODE_PROMPT, "" | |
| n = args.input_tokens or (4096 if args.prompt_kind == "doc" else 1024) | |
| text, _, _ = build_prompt_text(n, args.tokenizer) | |
| if args.prompt_kind == "doc": | |
| return "Document:\n" + text, "\n\nSummarize the document above in five bullet points, then list its recurring themes." | |
| return text, "\n\nContinue this text." | |
| def one_request(args, s, body_text, suffix, tag): | |
| body = {"model": args.model, "stream": True, "stream_options": {"include_usage": True}, | |
| "messages": [{"role": "user", "content": f"[req {tag}] " + body_text + suffix}], | |
| "max_tokens": args.output_tokens, "temperature": 0.0, "ignore_eos": True, | |
| "min_tokens": args.output_tokens, "return_spec_tokens_details": True, | |
| "chat_template_kwargs": {"enable_thinking": False}} | |
| t0 = time.perf_counter() | |
| times, usage, spec = [], None, None | |
| try: | |
| with s.post(args.api + "/chat/completions", json=body, stream=True, timeout=args.timeout) as r: | |
| if r.status_code != 200: | |
| return {"ok": False, "error": f"HTTP {r.status_code}: {r.text[:300]}"} | |
| for line in r.iter_lines(): | |
| if not line.startswith(b"data:"): | |
| continue | |
| data = line[5:].strip() | |
| if data == b"[DONE]": | |
| break | |
| j = json.loads(data) | |
| usage = j.get("usage") or usage | |
| spec = ((j.get("sglext") or {}).get("spec_tokens_details")) or spec | |
| for ch in j.get("choices") or []: | |
| d = ch.get("delta") or {} | |
| if d.get("content") or d.get("reasoning_content") or d.get("reasoning"): | |
| times.append(time.perf_counter()) | |
| except Exception as e: # noqa: BLE001 | |
| return {"ok": False, "error": f"{type(e).__name__}: {e}"} | |
| if not times: | |
| return {"ok": False, "error": "no tokens received"} | |
| n_out = (usage or {}).get("completion_tokens") or len(times) | |
| dt = times[-1] - times[0] | |
| if isinstance(spec, list): | |
| spec = spec[0] if spec else None | |
| return {"ok": True, "ttft_s": times[0] - t0, "e2e_s": time.perf_counter() - t0, "out": n_out, | |
| "prompt_tokens": (usage or {}).get("prompt_tokens"), | |
| "decode_tok_s": (n_out - 1) / dt if dt > 0 and n_out > 1 else None, | |
| "itl_s": dt / (n_out - 1) if dt > 0 and n_out > 1 else None, | |
| "gaps": [b - a for a, b in zip(times, times[1:])], | |
| "accept_len": (spec or {}).get("spec_accept_length")} | |
| def server_accept(args): | |
| for path in ("/server_info", "/get_server_info"): | |
| try: | |
| j = requests.get(args.root + path, timeout=10).json() | |
| for st in j.get("internal_states") or []: | |
| if "avg_spec_accept_length" in st: | |
| return st["avg_spec_accept_length"] | |
| return None | |
| except Exception: # noqa: BLE001 | |
| continue | |
| return None | |
| def run_level(args, s, prompt, c, rep): | |
| n = args.num_requests or max(4, 2 * c) | |
| tags = [f"{args.run_tag}-c{c}-r{rep}-{i:05d}" for i in range(n)] | |
| acc0 = server_accept(args) | |
| t0 = time.perf_counter() | |
| with ThreadPoolExecutor(c) as ex: | |
| res = list(ex.map(lambda t: one_request(args, s, prompt[0], prompt[1], t), tags)) | |
| wall = time.perf_counter() - t0 | |
| ok = [r for r in res if r["ok"]] | |
| col = lambda k: [r[k] for r in ok if r.get(k) is not None] # noqa: E731 | |
| gaps = [g for r in ok for g in r["gaps"]] | |
| ms = lambda x: None if x is None else 1000 * x # noqa: E731 | |
| acc = col("accept_len") | |
| return {"concurrency": c, "repeat": rep, "n_requests": n, "n_ok": len(ok), "n_errors": n - len(ok), | |
| "errors": [r["error"] for r in res if not r["ok"]][:5], "wall_s": wall, | |
| "aggregate_output_tok_s": sum(col("out")) / wall if wall else None, | |
| "decode_tok_s_per_req_p50": pct(col("decode_tok_s"), 0.5), | |
| "ttft_ms_p50": ms(pct(col("ttft_s"), 0.5)), | |
| "itl_ms_p50": ms(pct(col("itl_s"), 0.5)), "itl_ms_p95": ms(pct(col("itl_s"), 0.95)), | |
| "chunk_gap_ms_p50": ms(pct(gaps, 0.5)), "chunk_gap_ms_p95": ms(pct(gaps, 0.95)), | |
| "out_tokens_mean": statistics.fmean(col("out")) if ok else None, | |
| "prompt_tokens_mean": statistics.fmean(col("prompt_tokens")) if col("prompt_tokens") else None, | |
| "spec_accept_len_req_mean": statistics.fmean(acc) if acc else None, | |
| "server_avg_accept_len_before": acc0, "server_avg_accept_len_after": server_accept(args)} | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--base-url", required=True, help="server root or .../v1") | |
| ap.add_argument("--model", required=True) | |
| ap.add_argument("--concurrency", default="1,4,8") | |
| ap.add_argument("--num-requests", type=int, default=0, help="per level; 0 => max(4, 2*c)") | |
| ap.add_argument("--input-tokens", type=int, default=0, help="0 => 1024 (synthetic) / 4096 (doc)") | |
| ap.add_argument("--output-tokens", type=int, default=256) | |
| ap.add_argument("--warmup", type=int, default=1) | |
| ap.add_argument("--repeat", type=int, default=1) | |
| ap.add_argument("--prompt-kind", choices=["synthetic", "code", "doc"], default="synthetic") | |
| ap.add_argument("--tokenizer", default=str(DEFAULT_TOK)) | |
| ap.add_argument("--timeout", type=float, default=600) | |
| ap.add_argument("--label", default="") | |
| ap.add_argument("--out", required=True) | |
| args = ap.parse_args() | |
| args.root = args.base_url.rstrip("/").removesuffix("/v1") | |
| args.api = args.root + "/v1" | |
| args.run_tag = uuid.uuid4().hex[:8] | |
| prompt = make_prompt(args) | |
| levels = [int(x) for x in args.concurrency.split(",")] | |
| s = requests.Session() | |
| s.mount("http://", requests.adapters.HTTPAdapter(pool_maxsize=max(levels) * 2 + 4)) | |
| for i in range(args.warmup): | |
| w = one_request(args, s, prompt[0], prompt[1], f"{args.run_tag}-warm{i}") | |
| if not w["ok"]: | |
| print("warmup error:", w["error"], file=sys.stderr) | |
| out = {"label": args.label, "time": time.strftime("%Y-%m-%dT%H:%M:%S%z"), | |
| "config": {k: v for k, v in vars(args).items()}, "levels": []} | |
| f = lambda x: " n/a" if x is None else f"{x:7.2f}" # noqa: E731 | |
| for c in levels: | |
| for rep in range(args.repeat): | |
| lv = run_level(args, s, prompt, c, rep) | |
| out["levels"].append(lv) | |
| print(f"c={c:2d} r={rep} ok={lv['n_ok']}/{lv['n_requests']} agg={f(lv['aggregate_output_tok_s'])} tok/s " | |
| f"dec/req={f(lv['decode_tok_s_per_req_p50'])} TTFT={f(lv['ttft_ms_p50'])}ms " | |
| f"ITL p50/p95={f(lv['itl_ms_p50'])}/{f(lv['itl_ms_p95'])}ms " | |
| f"accept={f(lv['spec_accept_len_req_mean'])} srv={f(lv['server_avg_accept_len_after'])}", | |
| flush=True) | |
| Path(args.out).parent.mkdir(parents=True, exist_ok=True) | |
| Path(args.out).write_text(json.dumps(out, indent=2)) | |
| print("wrote", args.out) | |
| if __name__ == "__main__": | |
| main() | |