Image-Text-to-Text
Transformers
English
Chinese
eviscene
multimodal
image-factuality
agent
sft
distillation
Instructions to use ZiAnwang/EviScene with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ZiAnwang/EviScene with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="ZiAnwang/EviScene")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("ZiAnwang/EviScene", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use ZiAnwang/EviScene with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ZiAnwang/EviScene" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ZiAnwang/EviScene", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/ZiAnwang/EviScene
- SGLang
How to use ZiAnwang/EviScene 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 "ZiAnwang/EviScene" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ZiAnwang/EviScene", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "ZiAnwang/EviScene" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ZiAnwang/EviScene", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use ZiAnwang/EviScene with Docker Model Runner:
docker model run hf.co/ZiAnwang/EviScene
Download scripts/trajectory/build_sft_case_split.py from ZiAnwang/EviScene: direct link, hf CLI and curl.
- Browser
- Download file 10.7 kB
-
https://huggingface.co/ZiAnwang/EviScene/resolve/main/scripts/trajectory/build_sft_case_split.py
- Command line
-
hf download hf://ZiAnwang/EviScene/scripts/trajectory/build_sft_case_split.py
-
curl -L -o build_sft_case_split.py https://huggingface.co/ZiAnwang/EviScene/resolve/main/scripts/trajectory/build_sft_case_split.py
10.7 kB
| #!/usr/bin/env python3 | |
| """Freeze a leakage-safe train/validation split for reviewed SFT cases.""" | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| from collections import Counter, defaultdict | |
| from pathlib import Path | |
| from typing import Any, Dict, Iterable, Mapping, Sequence | |
| SCHEMA_VERSION = "ifv-sft-case-split-v1" | |
| def _load_jsonl(path: Path) -> list[Dict[str, Any]]: | |
| rows: list[Dict[str, Any]] = [] | |
| for line_number, line in enumerate( | |
| path.read_text(encoding="utf-8").split("\n"), start=1 | |
| ): | |
| if not line.strip(): | |
| continue | |
| value = json.loads(line) | |
| if not isinstance(value, dict): | |
| raise ValueError(f"{path}:{line_number} must be a JSON object") | |
| rows.append(value) | |
| return rows | |
| def _index(rows: Sequence[Mapping[str, Any]], *, name: str) -> Dict[str, Mapping[str, Any]]: | |
| result: Dict[str, Mapping[str, Any]] = {} | |
| for row in rows: | |
| case_id = str(row.get("case_id") or "").strip() | |
| if not case_id: | |
| raise ValueError(f"{name} row lacks case_id") | |
| if case_id in result: | |
| raise ValueError(f"duplicate {name} case_id: {case_id}") | |
| result[case_id] = row | |
| return result | |
| def _label(row: Mapping[str, Any]) -> str: | |
| label = str(row.get("label") or row.get("factual_status") or "").strip().lower() | |
| if label in {"supported", "refuted"}: | |
| return label | |
| verdict = str( | |
| row.get("expected_verdict") or row.get("gold_verdict") or "" | |
| ).strip().lower() | |
| mapping = {"real": "supported", "fake": "refuted"} | |
| if verdict in mapping: | |
| return mapping[verdict] | |
| raise ValueError("gold labels must be supported/refuted or real/fake") | |
| class _UnionFind: | |
| def __init__(self, values: Iterable[str]) -> None: | |
| self.parent = {value: value for value in values} | |
| def find(self, value: str) -> str: | |
| parent = self.parent[value] | |
| if parent != value: | |
| self.parent[value] = self.find(parent) | |
| return self.parent[value] | |
| def union(self, left: str, right: str) -> None: | |
| left_root = self.find(left) | |
| right_root = self.find(right) | |
| if left_root != right_root: | |
| self.parent[max(left_root, right_root)] = min(left_root, right_root) | |
| def _group_keys( | |
| runtime: Mapping[str, Any], | |
| gold: Mapping[str, Any], | |
| ) -> set[str]: | |
| keys = {f"image:{str(runtime.get('image_sha256') or '').casefold()}"} | |
| claim_atom = gold.get("claim_atom") | |
| if isinstance(claim_atom, Mapping): | |
| subject = str(claim_atom.get("subject") or "").strip().casefold() | |
| event = str(claim_atom.get("event") or "").strip().casefold() | |
| if subject and event: | |
| keys.add(f"subject-event:{subject}|{event}") | |
| evidence = gold.get("certifying_evidence") | |
| if isinstance(evidence, list): | |
| for row in evidence: | |
| if not isinstance(row, Mapping): | |
| continue | |
| for field in ("source_id", "snapshot_sha256"): | |
| value = str(row.get(field) or "").strip().casefold() | |
| if value: | |
| keys.add(f"{field}:{value}") | |
| return keys | |
| def build_split( | |
| runtime_rows: Sequence[Mapping[str, Any]], | |
| gold_rows: Sequence[Mapping[str, Any]], | |
| *, | |
| validation_count: int, | |
| validation_supported: int, | |
| seed: str, | |
| prohibited_case_ids: set[str] | None = None, | |
| prohibited_image_hashes: set[str] | None = None, | |
| ) -> tuple[list[Dict[str, Any]], Dict[str, Any]]: | |
| runtime = _index(runtime_rows, name="runtime") | |
| gold = _index(gold_rows, name="gold") | |
| if set(runtime) != set(gold): | |
| raise ValueError("runtime and gold case IDs must match exactly") | |
| if validation_count < 1 or validation_count >= len(runtime): | |
| raise ValueError("validation_count must leave non-empty train and validation") | |
| if validation_supported < 0 or validation_supported > validation_count: | |
| raise ValueError("validation_supported is outside validation_count") | |
| blocked_ids = prohibited_case_ids or set() | |
| blocked_hashes = {value.casefold() for value in (prohibited_image_hashes or set())} | |
| overlap_ids = sorted(set(runtime) & blocked_ids) | |
| overlap_hashes = sorted( | |
| { | |
| str(row.get("image_sha256") or "").casefold() | |
| for row in runtime.values() | |
| } | |
| & blocked_hashes | |
| ) | |
| if overlap_ids or overlap_hashes: | |
| raise ValueError( | |
| "training candidates overlap prohibited evaluation data: " | |
| f"case_ids={overlap_ids[:5]}, image_hashes={overlap_hashes[:5]}" | |
| ) | |
| labels = {case_id: _label(gold[case_id]) for case_id in gold} | |
| union = _UnionFind(runtime) | |
| members_by_key: Dict[str, list[str]] = defaultdict(list) | |
| for case_id in runtime: | |
| for key in _group_keys(runtime[case_id], gold[case_id]): | |
| members_by_key[key].append(case_id) | |
| for members in members_by_key.values(): | |
| for member in members[1:]: | |
| union.union(members[0], member) | |
| components: Dict[str, list[str]] = defaultdict(list) | |
| for case_id in runtime: | |
| components[union.find(case_id)].append(case_id) | |
| groups: list[Dict[str, Any]] = [] | |
| for members in components.values(): | |
| ordered = sorted(members) | |
| group_id = hashlib.sha256( | |
| json.dumps(ordered, separators=(",", ":")).encode("utf-8") | |
| ).hexdigest()[:20] | |
| groups.append( | |
| { | |
| "group_id": group_id, | |
| "members": ordered, | |
| "count": len(ordered), | |
| "supported": sum(labels[item] == "supported" for item in ordered), | |
| } | |
| ) | |
| groups.sort( | |
| key=lambda group: hashlib.sha256( | |
| f"{seed}:{group['group_id']}".encode("utf-8") | |
| ).hexdigest() | |
| ) | |
| target = (validation_count, validation_supported) | |
| choices: Dict[tuple[int, int], tuple[int, ...]] = {(0, 0): ()} | |
| for index, group in enumerate(groups): | |
| next_choices = dict(choices) | |
| for (count, supported), selected in choices.items(): | |
| state = ( | |
| count + int(group["count"]), | |
| supported + int(group["supported"]), | |
| ) | |
| if state[0] > target[0] or state[1] > target[1]: | |
| continue | |
| next_choices.setdefault(state, selected + (index,)) | |
| choices = next_choices | |
| if target not in choices: | |
| raise ValueError( | |
| "group constraints cannot satisfy requested validation count/labels" | |
| ) | |
| validation_groups = {groups[index]["group_id"] for index in choices[target]} | |
| group_by_case = { | |
| case_id: str(group["group_id"]) | |
| for group in groups | |
| for case_id in group["members"] | |
| } | |
| rows = [ | |
| { | |
| "schema_version": SCHEMA_VERSION, | |
| "case_id": case_id, | |
| "image_sha256": str(runtime[case_id].get("image_sha256") or ""), | |
| "split_group_id": group_by_case[case_id], | |
| "split": ( | |
| "validation" | |
| if group_by_case[case_id] in validation_groups | |
| else "train" | |
| ), | |
| } | |
| for case_id in sorted(runtime) | |
| ] | |
| split_labels = { | |
| split: Counter(labels[row["case_id"]] for row in rows if row["split"] == split) | |
| for split in ("train", "validation") | |
| } | |
| summary = { | |
| "schema_version": SCHEMA_VERSION, | |
| "seed": seed, | |
| "case_count": len(rows), | |
| "group_count": len(groups), | |
| "split_counts": dict(Counter(row["split"] for row in rows)), | |
| "split_label_counts": { | |
| split: dict(sorted(counts.items())) | |
| for split, counts in split_labels.items() | |
| }, | |
| "validation_group_ids": sorted(validation_groups), | |
| } | |
| return rows, summary | |
| def _sha256(path: Path) -> str: | |
| digest = hashlib.sha256() | |
| with path.open("rb") as handle: | |
| for chunk in iter(lambda: handle.read(1024 * 1024), b""): | |
| digest.update(chunk) | |
| return digest.hexdigest() | |
| def _args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--runtime", required=True, type=Path) | |
| parser.add_argument("--gold", required=True, type=Path) | |
| parser.add_argument("--prohibited-runtime", type=Path) | |
| parser.add_argument("--output-dir", required=True, type=Path) | |
| parser.add_argument("--validation-count", type=int, default=8) | |
| parser.add_argument("--validation-supported", type=int, default=2) | |
| parser.add_argument("--seed", default="ifv-qwen35-sft-v1") | |
| return parser.parse_args() | |
| def main() -> int: | |
| args = _args() | |
| output_dir = args.output_dir.expanduser().resolve() | |
| if output_dir.exists() and any(output_dir.iterdir()): | |
| raise FileExistsError(f"output directory must be new or empty: {output_dir}") | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| runtime_rows = _load_jsonl(args.runtime) | |
| gold_rows = _load_jsonl(args.gold) | |
| prohibited_rows = ( | |
| _load_jsonl(args.prohibited_runtime) | |
| if args.prohibited_runtime is not None | |
| else [] | |
| ) | |
| rows, summary = build_split( | |
| runtime_rows, | |
| gold_rows, | |
| validation_count=args.validation_count, | |
| validation_supported=args.validation_supported, | |
| seed=args.seed, | |
| prohibited_case_ids={str(row.get("case_id") or "") for row in prohibited_rows}, | |
| prohibited_image_hashes={ | |
| str(row.get("image_sha256") or "") for row in prohibited_rows | |
| }, | |
| ) | |
| split_path = output_dir / "case_split.jsonl" | |
| split_path.write_text( | |
| "\n".join(json.dumps(row, sort_keys=True) for row in rows) + "\n", | |
| encoding="utf-8", | |
| ) | |
| manifest = { | |
| **summary, | |
| "inputs": { | |
| "runtime": {"path": str(args.runtime.resolve()), "sha256": _sha256(args.runtime)}, | |
| "gold": {"path": str(args.gold.resolve()), "sha256": _sha256(args.gold)}, | |
| "prohibited_runtime": ( | |
| { | |
| "path": str(args.prohibited_runtime.resolve()), | |
| "sha256": _sha256(args.prohibited_runtime), | |
| } | |
| if args.prohibited_runtime is not None | |
| else None | |
| ), | |
| }, | |
| "artifacts": { | |
| "case_split": "case_split.jsonl", | |
| "case_split_sha256": _sha256(split_path), | |
| }, | |
| } | |
| (output_dir / "manifest.json").write_text( | |
| json.dumps(manifest, ensure_ascii=False, indent=2) + "\n", | |
| encoding="utf-8", | |
| ) | |
| print(json.dumps(manifest, ensure_ascii=False, indent=2)) | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |