Text Generation
Transformers
Safetensors
English
Chinese
Russian
yue2
music-generation
orbitquant
quantization
4-bit precision
custom-code
8-bit precision
Instructions to use WaveCut/YuE2-3B-OrbitQuant-W4A4 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use WaveCut/YuE2-3B-OrbitQuant-W4A4 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="WaveCut/YuE2-3B-OrbitQuant-W4A4")# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("WaveCut/YuE2-3B-OrbitQuant-W4A4", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use WaveCut/YuE2-3B-OrbitQuant-W4A4 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "WaveCut/YuE2-3B-OrbitQuant-W4A4" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "WaveCut/YuE2-3B-OrbitQuant-W4A4", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/WaveCut/YuE2-3B-OrbitQuant-W4A4
- SGLang
How to use WaveCut/YuE2-3B-OrbitQuant-W4A4 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 "WaveCut/YuE2-3B-OrbitQuant-W4A4" \ --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": "WaveCut/YuE2-3B-OrbitQuant-W4A4", "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 "WaveCut/YuE2-3B-OrbitQuant-W4A4" \ --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": "WaveCut/YuE2-3B-OrbitQuant-W4A4", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use WaveCut/YuE2-3B-OrbitQuant-W4A4 with Docker Model Runner:
docker model run hf.co/WaveCut/YuE2-3B-OrbitQuant-W4A4
Download src/runtime/yue2/cli.py from WaveCut/YuE2-3B-OrbitQuant-W4A4: direct link, hf CLI and curl.
- Browser
- Download file 12.2 kB
-
https://huggingface.co/WaveCut/YuE2-3B-OrbitQuant-W4A4/resolve/main/src/runtime/yue2/cli.py
- Command line
-
hf download hf://WaveCut/YuE2-3B-OrbitQuant-W4A4/src/runtime/yue2/cli.py
-
curl -L -o cli.py https://huggingface.co/WaveCut/YuE2-3B-OrbitQuant-W4A4/resolve/main/src/runtime/yue2/cli.py
12.2 kB
| """Small CLI sharing the Python pipeline's defaults and artifact protocol.""" | |
| from __future__ import annotations | |
| import argparse | |
| import importlib.metadata | |
| import json | |
| import os | |
| from pathlib import Path | |
| import sys | |
| import time | |
| from .storage import write_json, verify_result, identity | |
| def kit_root(): | |
| return Path(os.environ.get("YUE2_KIT", Path(__file__).resolve().parents[2])) | |
| def model_paths(args): | |
| root = kit_root() | |
| local_model = root / "models/YuE2-3B" | |
| local_vae = root / "models" / ("YuE2-Vae-legacy" if args.vae == "legacy" else "YuE2-Vae") | |
| model = args.model or (str(local_model) if local_model.exists() else "m-a-p/YuE2-3B") | |
| vae = args.vae if args.vae not in {"standard", "legacy"} else ( | |
| str(local_vae) if local_vae.exists() else "m-a-p/" + local_vae.name) | |
| return model, vae | |
| def get_pipe(args): | |
| from .pipeline import YuE2Pipeline | |
| from .protocol import GenerationConfig | |
| model, vae = model_paths(args) | |
| config = GenerationConfig.from_dict(json.loads(Path(args.config).read_text())) if args.config else None | |
| return YuE2Pipeline.from_pretrained(model, vae=vae, revision=args.revision, | |
| vae_revision=args.vae_revision, device=args.device, memory_budget_gib=args.budget, | |
| backend=args.backend, quantization=args.quantization, offload_ar=args.offload_ar, | |
| local_files_only=args.offline, generation_config=config, | |
| vae_core_frames=512 if args.budget <= 12 else 1024, | |
| progress=not getattr(args, "quiet", False)) | |
| def request_kwargs(data, base=Path.cwd()): | |
| allowed = {"style", "tags", "lyrics", "cot", "seed", "abc", "cfg_scale", "id", "abc_sampling", "semantic_sampling"} | |
| metadata = {"lang", "eval_index", "clip_id", "prompt"} | |
| unknown = set(data) - allowed - metadata - {"abc_path"} | |
| if unknown: | |
| raise ValueError(f"Unknown request fields: {sorted(unknown)}") | |
| result = {k: v for k, v in data.items() if k in allowed} | |
| if "abc_path" in data: | |
| if data.get("abc") is not None: | |
| raise ValueError("Pass abc or abc_path, not both") | |
| result["abc"] = (base / data["abc_path"]).read_bytes().decode("utf-8") | |
| if data.get("prompt") is not None: | |
| from .protocol import SongRequest | |
| request = SongRequest(style=result.get("style", result.get("tags")), lyrics=result["lyrics"], | |
| cot=result.get("cot", "full")) | |
| if data["prompt"] != request.text(): | |
| raise ValueError("Historical literal prompt does not match native instruction/style/lyrics") | |
| return result | |
| def doctor(args): | |
| import torch | |
| from .storage import model_identity | |
| model, vae = model_paths(args) | |
| versions = {} | |
| for package in ("torch", "transformers", "huggingface-hub", "safetensors", "tiktoken", "soundfile"): | |
| try: | |
| versions[package] = importlib.metadata.version(package) | |
| except importlib.metadata.PackageNotFoundError: | |
| versions[package] = None | |
| devices = [] | |
| for i in range(torch.cuda.device_count()): | |
| p = torch.cuda.get_device_properties(i) | |
| devices.append({"id": i, "name": p.name, "memory_gib": p.total_memory / 2**30, | |
| "compute_capability": [p.major, p.minor]}) | |
| report = {"dependencies_ready": all(versions.values()), "versions": versions, | |
| "cuda": devices, "mps_available": torch.backends.mps.is_available(), | |
| "model": model, "vae": vae, "default_cot": "full", "default_cfg": {"full": 1., "melody": 1., "off": 1.01}, | |
| "validated": False, "note": "Environment readiness is not quality or real-24GB acceptance."} | |
| if args.verify_hashes: | |
| from .storage import resolve_model | |
| report["weights"] = {"model": model_identity(resolve_model(model, local_files_only=args.offline)), | |
| "vae": model_identity(resolve_model(vae, local_files_only=args.offline))} | |
| if args.output: | |
| write_json(args.output, report) | |
| print(json.dumps(report, indent=2, ensure_ascii=False)) | |
| return 0 if report["dependencies_ready"] else 1 | |
| def generate(args): | |
| if args.request: | |
| path = Path(args.request) | |
| data = json.loads(path.read_text()) | |
| base = path.parent | |
| else: | |
| data, base = {}, Path.cwd() | |
| for key in ("id", "style", "cot", "seed", "cfg_scale"): | |
| value = getattr(args, key) | |
| if value is not None: | |
| data[key] = value | |
| if args.lyrics_file: | |
| data["lyrics"] = Path(args.lyrics_file).read_bytes().decode("utf-8") | |
| elif args.lyrics is not None: | |
| data["lyrics"] = args.lyrics | |
| if args.abc_file: | |
| data["abc"] = Path(args.abc_file).read_bytes().decode("utf-8") | |
| data.pop("abc_path", None) | |
| if not data: | |
| data = {"id": "first_song", "style": "Mandarin, warm piano, acoustic pop, female vocal", | |
| "lyrics": "[Verse]\n晚风轻轻吹过窗前\n你留下的笑还在昨天\n[Chorus]\n让这首歌陪你走远\n把所有想念唱成明天"} | |
| kwargs = request_kwargs(data, base) | |
| pipe = get_pipe(args) | |
| directory = Path(args.output or "runs/default") / kwargs.get("id", "song") | |
| if args.resume and (directory / "result.json").exists(): | |
| req_kwargs = {k: v for k, v in kwargs.items() if k not in {"abc_sampling", "semantic_sampling"}} | |
| request = pipe._request(**req_kwargs) | |
| config = pipe.effective_config(request, kwargs.get("abc_sampling"), kwargs.get("semantic_sampling")) | |
| expected = identity({"request": request.to_dict(), "config": config, "weights": pipe.weights}) | |
| result = verify_result(directory, expected) | |
| print(json.dumps({"resumed": True, "result": str(directory / "result.json"), "truncated": result["truncated"]})) | |
| return 0 | |
| if directory.exists() and any(directory.iterdir()): | |
| raise FileExistsError(f"Nonempty output {directory}; use --resume or a new output directory") | |
| directory.mkdir(parents=True, exist_ok=True) | |
| try: | |
| if args.stage == "plan": | |
| kwargs.pop("semantic_sampling", None) | |
| plan = pipe.plan(**kwargs) | |
| plan.save(directory) | |
| print(json.dumps({"stage": "plan", "output": str(directory), "truncated": plan.truncated})) | |
| else: | |
| result = pipe(**kwargs) | |
| result.save_artifacts(directory) | |
| print(json.dumps({"status": "complete", "output": str(directory), "truncated": result.truncated, | |
| "seconds": result.timing["e2e_seconds"]})) | |
| return 0 | |
| except BaseException as exc: | |
| write_json(directory / "failure.json", {"status": "failed", "type": type(exc).__name__, "reason": str(exc), | |
| "request": data}) | |
| raise | |
| finally: | |
| pipe.close() | |
| def batch(args): | |
| if args.concurrency != 1: | |
| raise ValueError("The minimal torch pipeline currently supports concurrency=1; do not share a pipeline concurrently") | |
| path = Path(args.input) | |
| rows = [json.loads(line) for line in path.read_text().splitlines() if line.strip()] | |
| ids = [r.get("id") for r in rows] | |
| if any(x is None for x in ids) or len(ids) != len(set(ids)): | |
| raise ValueError("Every batch request must have a unique id") | |
| pipe = get_pipe(args) | |
| output = Path(args.output or "runs/batch") | |
| receipts, failures = [], 0 | |
| try: | |
| for index, row in enumerate(rows, 1): | |
| if not args.quiet: | |
| print(f"Song {index}/{len(rows)}: {row['id']}", file=sys.stderr, flush=True) | |
| kwargs = request_kwargs(row, path.parent) | |
| if args.cot is not None: | |
| kwargs["cot"] = args.cot | |
| directory = output / row["id"] | |
| try: | |
| request = pipe._request(**{k:v for k,v in kwargs.items() if k not in {"abc_sampling", "semantic_sampling"}}) | |
| cfg = pipe.effective_config(request, kwargs.get("abc_sampling"), kwargs.get("semantic_sampling")) | |
| expected = identity({"request": request.to_dict(), "config": cfg, "weights": pipe.weights}) | |
| if args.resume and (directory / "result.json").exists(): | |
| receipt = verify_result(directory, expected) | |
| else: | |
| if directory.exists() and any(directory.iterdir()): | |
| raise FileExistsError("Nonempty request output; use --resume or a new run") | |
| receipt = pipe(**kwargs).save_artifacts(directory) | |
| receipts.append({"id": row["id"], "status": "complete", "identity": receipt["identity"]}) | |
| except Exception as exc: | |
| failures += 1 | |
| failure = {"id": row["id"], "status": "failed", "reason": str(exc), "type": type(exc).__name__} | |
| write_json(directory / "failure.json", failure) | |
| receipts.append(failure) | |
| write_json(output / "batch.json", {"complete": len(receipts) == len(rows) and not failures, | |
| "expected": len(rows), "failed": failures, "results": receipts}) | |
| finally: | |
| pipe.close() | |
| return int(failures > 0) | |
| def parser(): | |
| p = argparse.ArgumentParser(description="YuE2: style + lyrics → symbolic plan → song") | |
| sub = p.add_subparsers(dest="command", required=True) | |
| for name in ("doctor", "generate", "batch"): | |
| q = sub.add_parser(name) | |
| q.add_argument("--model") | |
| q.add_argument("--vae", default="standard", help="standard (old), YuE2-Vae-legacy, local path or HF repo") | |
| q.add_argument("--revision") | |
| q.add_argument("--vae-revision") | |
| q.add_argument("--device", default="auto") | |
| q.add_argument("--budget", type=float, default=24) | |
| q.add_argument("--backend", choices=("torch", "torch-eager", "vllm"), default="torch") | |
| q.add_argument("--quantization", choices=("none", "fp8"), default="none") | |
| q.add_argument("--offload-ar", action="store_true") | |
| q.add_argument("--offline", action="store_true") | |
| q.add_argument("--config") | |
| q.add_argument("--output") | |
| if name == "doctor": | |
| q.add_argument("--verify-hashes", action="store_true") | |
| else: | |
| q.add_argument("--cot", choices=("full", "melody", "off")) | |
| q.add_argument("--resume", action="store_true") | |
| q.add_argument("--quiet", "--no-progress", action="store_true", | |
| help="Hide YuE2 progress on stderr; keep result output on stdout") | |
| if name == "batch": | |
| q.add_argument("--input", required=True) | |
| q.add_argument("--concurrency", type=int, default=1) | |
| else: | |
| q.add_argument("--request") | |
| q.add_argument("--id") | |
| q.add_argument("--style") | |
| q.add_argument("--lyrics") | |
| q.add_argument("--lyrics-file") | |
| q.add_argument("--abc-file") | |
| q.add_argument("--seed", type=int) | |
| q.add_argument("--cfg-scale", type=float) | |
| q.add_argument("--stage", choices=("plan", "audio"), default="audio") | |
| for name in ("verify", "bench", "eval"): | |
| q = sub.add_parser(name, add_help=False) | |
| q.add_argument("arguments", nargs=argparse.REMAINDER) | |
| return p | |
| def main(argv=None): | |
| argv = sys.argv[1:] if argv is None else argv | |
| if argv and argv[0] in {"verify", "bench", "eval"}: | |
| import subprocess | |
| script = {"verify": "validate_release.py", "bench": "benchmark.py", "eval": "evaluate.py"}[argv[0]] | |
| target = kit_root() / "scripts" / script | |
| if not target.is_file(): | |
| raise FileNotFoundError("This command needs the complete minimal kit (scripts/data/evaluation_runtime). " | |
| "Set YUE2_KIT to its directory; the HF wheel supplies generation and the Python API.") | |
| return subprocess.call([sys.executable, str(target), *argv[1:]]) | |
| args = parser().parse_args(argv) | |
| return {"doctor": doctor, "generate": generate, "batch": batch}[args.command](args) | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |