Text Generation
Transformers
PEFT
English
gravityllm
spatial-audio
immersive-audio
spatial9
iamf
instruction-tuning
json
lora
qlora
Instructions to use Spatial9/GravityLLM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Spatial9/GravityLLM with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Spatial9/GravityLLM")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Spatial9/GravityLLM", dtype="auto") - PEFT
How to use Spatial9/GravityLLM with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Spatial9/GravityLLM with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Spatial9/GravityLLM" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Spatial9/GravityLLM", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Spatial9/GravityLLM
- SGLang
How to use Spatial9/GravityLLM 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 "Spatial9/GravityLLM" \ --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": "Spatial9/GravityLLM", "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 "Spatial9/GravityLLM" \ --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": "Spatial9/GravityLLM", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Spatial9/GravityLLM with Docker Model Runner:
docker model run hf.co/Spatial9/GravityLLM
| from __future__ import annotations | |
| import json | |
| import math | |
| import re | |
| from pathlib import Path | |
| from typing import Any, Dict, List, Tuple | |
| import matplotlib.pyplot as plt | |
| from jsonschema import Draft7Validator | |
| SCHEMA_PATH = Path(__file__).resolve().parents[1] / "schemas" / "scene.schema.json" | |
| SCHEMA: Dict[str, Any] = json.loads(SCHEMA_PATH.read_text(encoding="utf-8")) | |
| VALIDATOR = Draft7Validator(SCHEMA) | |
| CLASS_DEFAULTS = { | |
| "lead_vocal": {"az": 0, "el": 10, "dist": 1.6, "width": 0.15, "gain": 0.0, "rev": 0.18, "er": 0.22}, | |
| "dialogue": {"az": 0, "el": 5, "dist": 1.5, "width": 0.10, "gain": 0.0, "rev": 0.08, "er": 0.18}, | |
| "back_vocal": {"az": -18, "el": 8, "dist": 1.9, "width": 0.25, "gain": -1.2, "rev": 0.16, "er": 0.16}, | |
| "kick": {"az": 0, "el": 0, "dist": 2.2, "width": 0.0, "gain": 0.0, "rev": 0.02, "er": 0.05}, | |
| "snare": {"az": 8, "el": 4, "dist": 2.4, "width": 0.1, "gain": -0.3, "rev": 0.05, "er": 0.07}, | |
| "hihat": {"az": 22, "el": 7, "dist": 2.7, "width": 0.18, "gain": -1.0, "rev": 0.06, "er": 0.08}, | |
| "bass": {"az": 0, "el": -5, "dist": 2.6, "width": 0.05, "gain": -0.5, "rev": 0.03, "er": 0.06}, | |
| "drums_bus": {"az": 0, "el": 2, "dist": 2.8, "width": 0.25, "gain": -0.6, "rev": 0.08, "er": 0.10}, | |
| "pad": {"az": -70, "el": 18, "dist": 4.8, "width": 0.82, "gain": -4.0, "rev": 0.28, "er": 0.12}, | |
| "synth_lead": {"az": 24, "el": 15, "dist": 2.0, "width": 0.35, "gain": -1.0, "rev": 0.12, "er": 0.10}, | |
| "guitar": {"az": -28, "el": 10, "dist": 2.8, "width": 0.28, "gain": -1.5, "rev": 0.09, "er": 0.11}, | |
| "piano": {"az": -14, "el": 8, "dist": 2.6, "width": 0.34, "gain": -1.5, "rev": 0.09, "er": 0.10}, | |
| "fx": {"az": 105, "el": 28, "dist": 6.2, "width": 0.66, "gain": -7.0, "rev": 0.42, "er": 0.08}, | |
| "ambience": {"az": -120, "el": 15, "dist": 8.0, "width": 0.90, "gain": -8.0, "rev": 0.55, "er": 0.10}, | |
| "other": {"az": 0, "el": 8, "dist": 3.0, "width": 0.25, "gain": -2.0, "rev": 0.10, "er": 0.10}, | |
| } | |
| SPATIAL_CLASSES = list(CLASS_DEFAULTS) | |
| def clip(value: float, lo: float, hi: float) -> float: | |
| return max(lo, min(hi, value)) | |
| def extract_first_json_block(text: str) -> str: | |
| match = re.search(r"\{.*\}", text, flags=re.DOTALL) | |
| return match.group(0).strip() if match else text.strip() | |
| def parse_json_text(text: str) -> Dict[str, Any]: | |
| return json.loads(extract_first_json_block(text)) | |
| def validate_scene(scene: Dict[str, Any]) -> Tuple[bool, List[str]]: | |
| errors = sorted(VALIDATOR.iter_errors(scene), key=lambda e: list(e.path)) | |
| if not errors: | |
| return True, [] | |
| messages = [] | |
| for err in errors[:50]: | |
| path = ".".join(str(x) for x in err.path) | |
| messages.append(f"{path or '<root>'}: {err.message}") | |
| return False, messages | |
| def make_motion(az: float, el: float, dist: float, sweep: float = 0.0) -> List[Dict[str, float]]: | |
| if abs(sweep) < 0.001: | |
| return [ | |
| {"t": 0.0, "az_deg": round(az, 2), "el_deg": round(el, 2), "dist_m": round(dist, 2)}, | |
| {"t": 1.0, "az_deg": round(az, 2), "el_deg": round(el, 2), "dist_m": round(dist, 2)}, | |
| ] | |
| return [ | |
| {"t": 0.0, "az_deg": round(az - sweep / 2, 2), "el_deg": round(el, 2), "dist_m": round(dist, 2)}, | |
| {"t": 1.0, "az_deg": round(az + sweep / 2, 2), "el_deg": round(el, 2), "dist_m": round(dist, 2)}, | |
| ] | |
| def find_anchor_rules(payload: Dict[str, Any]) -> Dict[str, Dict[str, float]]: | |
| anchors: Dict[str, Dict[str, float]] = {} | |
| for rule in payload.get("rules", []): | |
| if rule.get("type") == "anchor": | |
| key = rule.get("track_class") | |
| if key: | |
| anchors[key] = { | |
| "az": float(rule.get("az_deg", 0.0)), | |
| "el": float(rule.get("el_deg", 0.0)), | |
| "dist": float(rule.get("dist_m", 1.6)), | |
| } | |
| return anchors | |
| def width_preference(payload: Dict[str, Any], track_class: str) -> float | None: | |
| for rule in payload.get("rules", []): | |
| if rule.get("type") == "width_pref" and rule.get("track_class") == track_class: | |
| value = rule.get("min_width") | |
| if value is not None: | |
| return float(value) | |
| return None | |
| def target_layout(payload: Dict[str, Any]) -> str: | |
| fmt = str(payload.get("target_format", "iamf")).lower() | |
| if fmt in {"binaural", "iamf", "5.1.4", "7.1.4"}: | |
| return fmt | |
| return "iamf" | |
| def room_preset(payload: Dict[str, Any]) -> str: | |
| style = str(payload.get("style", "neutral")).lower() | |
| mapping = { | |
| "club": "club_medium", | |
| "cinematic": "cinema_large", | |
| "film": "cinema_large", | |
| "podcast": "studio_dry", | |
| "live": "stage_wide", | |
| "intimate": "studio_small", | |
| } | |
| return mapping.get(style, "studio_neutral") | |
| def heuristic_scene(payload: Dict[str, Any]) -> Dict[str, Any]: | |
| anchors = find_anchor_rules(payload) | |
| objects: List[Dict[str, Any]] = [] | |
| constraints_applied: List[str] = [] | |
| max_objects = int(payload.get("max_objects", 10)) | |
| style = str(payload.get("style", "neutral")).lower() | |
| for rule in payload.get("rules", []): | |
| rtype = rule.get("type") | |
| if rtype == "anchor": | |
| constraints_applied.append( | |
| f"anchor:{rule.get('track_class')}@{rule.get('az_deg')}/{rule.get('el_deg')}/{rule.get('dist_m')}" | |
| ) | |
| elif rtype == "mono_low_end": | |
| constraints_applied.append(f"mono_low_end<{rule.get('hz_below', 120)}Hz") | |
| elif rtype == "width_pref": | |
| constraints_applied.append(f"{rule.get('track_class')}_width>={rule.get('min_width')}") | |
| elif rtype == "keep_dialogue_clear": | |
| band = rule.get("band_hz", [1000, 4000]) | |
| constraints_applied.append(f"keep_dialogue_clear_{band[0]}-{band[1]}Hz") | |
| elif rtype == "avoid_band_masking": | |
| band = rule.get("band_hz", [1500, 4500]) | |
| constraints_applied.append(f"avoid_masking_{rule.get('mask_target')}_{band[0]}-{band[1]}Hz") | |
| for idx, stem in enumerate(payload.get("stems", [])[:max_objects]): | |
| cls = stem.get("class", "other") | |
| defaults = dict(CLASS_DEFAULTS.get(cls, CLASS_DEFAULTS["other"])) | |
| if cls in anchors: | |
| defaults["az"] = anchors[cls]["az"] | |
| defaults["el"] = anchors[cls]["el"] | |
| defaults["dist"] = anchors[cls]["dist"] | |
| width_min = width_preference(payload, cls) | |
| if width_min is not None: | |
| defaults["width"] = max(defaults["width"], width_min) | |
| leadness = float(stem.get("leadness", 0.0)) | |
| transient = float(stem.get("transient", 0.0)) | |
| lufs = float(stem.get("lufs", -20.0)) | |
| if leadness > 0.8 and cls not in {"kick", "bass", "dialogue", "lead_vocal"}: | |
| defaults["dist"] = clip(defaults["dist"] - 0.35, 0.8, 15.0) | |
| defaults["gain"] = clip(defaults["gain"] + 0.8, -60.0, 12.0) | |
| if transient > 0.7 and cls in {"fx", "synth_lead"}: | |
| defaults["az"] += 12.0 | |
| if lufs < -24 and cls in {"fx", "ambience", "pad"}: | |
| defaults["dist"] = clip(defaults["dist"] + 0.5, 0.5, 15.0) | |
| # Add style-specific touch | |
| sweep = 0.0 | |
| if style == "club" and cls in {"fx", "synth_lead"}: | |
| sweep = 28.0 if cls == "fx" else 10.0 | |
| elif style in {"cinematic", "film"} and cls in {"fx", "ambience"}: | |
| sweep = 18.0 | |
| elif style == "podcast" and cls in {"dialogue", "back_vocal"}: | |
| sweep = 0.0 | |
| obj = { | |
| "id": str(stem.get("id", f"obj_{idx+1}")), | |
| "class": cls if cls in SPATIAL_CLASSES else "other", | |
| "az_deg": round(clip(defaults["az"], -180, 180), 2), | |
| "el_deg": round(clip(defaults["el"], -45, 90), 2), | |
| "dist_m": round(clip(defaults["dist"], 0.5, 15.0), 2), | |
| "width": round(clip(defaults["width"], 0.0, 1.0), 2), | |
| "gain_db": round(clip(defaults["gain"], -60, 12), 2), | |
| "reverb_send": round(clip(defaults["rev"], 0.0, 1.0), 2), | |
| "early_reflections": round(clip(defaults["er"], 0.0, 1.0), 2), | |
| "motion": make_motion(defaults["az"], defaults["el"], defaults["dist"], sweep=sweep), | |
| } | |
| # Low-end mono safety | |
| if cls in {"kick", "bass"}: | |
| obj["az_deg"] = 0.0 | |
| obj["width"] = 0.0 if cls == "kick" else min(obj["width"], 0.08) | |
| obj["motion"] = make_motion(0.0, obj["el_deg"], obj["dist_m"], sweep=0.0) | |
| objects.append(obj) | |
| scene = { | |
| "version": "1.0", | |
| "bed": { | |
| "layout": target_layout(payload), | |
| "loudness_target_lufs": -16.0 if payload.get("style") == "cinematic" else -14.0, | |
| "room_preset": room_preset(payload), | |
| }, | |
| "objects": objects or [ | |
| { | |
| "id": "placeholder", | |
| "class": "other", | |
| "az_deg": 0.0, | |
| "el_deg": 0.0, | |
| "dist_m": 2.0, | |
| "width": 0.2, | |
| "gain_db": 0.0, | |
| "reverb_send": 0.1, | |
| "early_reflections": 0.1, | |
| "motion": make_motion(0.0, 0.0, 2.0), | |
| } | |
| ], | |
| "constraints_applied": constraints_applied, | |
| } | |
| return scene | |
| def scene_stats(scene: Dict[str, Any]) -> Dict[str, Any]: | |
| objects = scene.get("objects", []) | |
| dominant = sorted(objects, key=lambda o: float(o.get("gain_db", -99.0)), reverse=True)[:3] | |
| return { | |
| "layout": scene.get("bed", {}).get("layout", "unknown"), | |
| "room_preset": scene.get("bed", {}).get("room_preset", "unknown"), | |
| "object_count": len(objects), | |
| "dominant": ", ".join(f"{o.get('id')} ({o.get('class')})" for o in dominant) or "n/a", | |
| } | |
| def scene_table(scene: Dict[str, Any]) -> List[List[Any]]: | |
| rows = [] | |
| for obj in scene.get("objects", []): | |
| rows.append([ | |
| obj.get("id"), | |
| obj.get("class"), | |
| obj.get("az_deg"), | |
| obj.get("el_deg"), | |
| obj.get("dist_m"), | |
| obj.get("width"), | |
| obj.get("gain_db"), | |
| ]) | |
| return rows | |
| def scene_markdown(scene: Dict[str, Any], valid: bool, errors: List[str], backend_used: str) -> str: | |
| stats = scene_stats(scene) | |
| badge = "✅ Schema valid" if valid else "⚠️ Validation issues" | |
| lines = [ | |
| f"### {badge}", | |
| "", | |
| f"- **Backend:** {backend_used}", | |
| f"- **Layout:** `{stats['layout']}`", | |
| f"- **Room preset:** `{stats['room_preset']}`", | |
| f"- **Objects:** `{stats['object_count']}`", | |
| f"- **Top objects:** {stats['dominant']}", | |
| ] | |
| if errors: | |
| lines.append("") | |
| lines.append("**Validation messages**") | |
| for err in errors[:8]: | |
| lines.append(f"- {err}") | |
| return "\n".join(lines) | |
| def plot_scene(scene: Dict[str, Any]): | |
| fig = plt.figure(figsize=(7.0, 7.0)) | |
| ax = fig.add_subplot(111) | |
| ax.set_facecolor("#f8fbff") | |
| fig.patch.set_facecolor("#f8fbff") | |
| # rings | |
| for r in [2, 4, 6, 8, 10]: | |
| circle = plt.Circle((0, 0), r, color="#d9e5f7", fill=False, linewidth=1) | |
| ax.add_artist(circle) | |
| # axes | |
| ax.axhline(0, color="#d9e5f7", linewidth=1) | |
| ax.axvline(0, color="#d9e5f7", linewidth=1) | |
| # labels | |
| ax.text(0, 10.7, "Front", ha="center", va="bottom", fontsize=11, color="#4a5b77") | |
| ax.text(10.7, 0, "Right", ha="left", va="center", fontsize=11, color="#4a5b77") | |
| ax.text(-10.7, 0, "Left", ha="right", va="center", fontsize=11, color="#4a5b77") | |
| ax.text(0, -10.7, "Rear", ha="center", va="top", fontsize=11, color="#4a5b77") | |
| palette = ["#1d4ed8", "#0891b2", "#7c3aed", "#ea580c", "#0f766e", "#be123c", "#0369a1", "#4d7c0f"] | |
| for idx, obj in enumerate(scene.get("objects", [])): | |
| az = math.radians(float(obj.get("az_deg", 0.0))) | |
| dist = float(obj.get("dist_m", 1.0)) | |
| x = dist * math.sin(az) | |
| y = dist * math.cos(az) | |
| size = 120 + 220 * float(obj.get("width", 0.2)) | |
| color = palette[idx % len(palette)] | |
| ax.scatter([x], [y], s=size, c=color, alpha=0.85, edgecolors="white", linewidths=1.5, zorder=3) | |
| ax.text(x, y + 0.42, f"{obj.get('id')}\n{obj.get('class')}", ha="center", va="bottom", fontsize=9, color="#1f2937") | |
| ax.set_xlim(-11, 11) | |
| ax.set_ylim(-11, 11) | |
| ax.set_xticks([]) | |
| ax.set_yticks([]) | |
| ax.set_title("Spatial Scene Preview", fontsize=15, color="#15233d", pad=12) | |
| return fig | |