Spaces:
Sleeping
Sleeping
File size: 3,822 Bytes
5459c43 | 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 | """Optional narration layer.
The rule engine already produces the diagnosis and the move. This turns that
into the way a good engineer would actually say it in the room, and catches
interactions between findings that per-rule logic cannot see.
Entirely optional: with no token configured the Space runs on the rule engine
alone and says so, rather than degrading silently.
"""
from __future__ import annotations
import json
import os
DEFAULT_MODEL = os.environ.get("EAR_LLM_MODEL", "Qwen/Qwen3-235B-A22B-Instruct-2507")
SYSTEM = """You are a senior sound designer and mix engineer sitting in on a session.
You have been handed measurements and a rule-based diagnosis of a piece of audio.
How you talk:
- Like an engineer in the room, not a manual. Short sentences. No hedging.
- Never repeat a number without saying what it means for the listener.
- Name the move, the device, and the value. "Cut 3 dB at 250" beats "consider EQ".
- If the measurements disagree with each other, say which one you trust and why.
- If nothing is wrong, say so in one line and talk about what to do next instead
of inventing problems.
- Never mention that you were given JSON or that you are an AI.
Structure your answer as exactly three short sections:
**What I'm hearing** β two or three sentences, the sound not the stats.
**The one thing to fix first** β a single highest-leverage move, with the reason.
**Then** β at most three more moves as a tight bulleted list.
"""
def _token() -> str | None:
return os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
def available() -> tuple[bool, str]:
if not _token():
return False, "no HF_TOKEN set β running on the rule engine only"
return True, f"ready ({DEFAULT_MODEL})"
def critique(
report: dict,
diagnoses: list[dict],
semantic_tags: dict,
genre: str,
source: str,
intent: str = "",
) -> str:
ok, _ = available()
if not ok:
return ""
from huggingface_hub import InferenceClient
payload = {
"genre": genre,
"listening_to": source,
"producer_intent": intent or "(not stated)",
"measurements": {
"lufs_integrated": round(report.get("lufs_i", -120), 1),
"true_peak_dbtp": round(report.get("true_peak", -120), 2),
"crest_db": round(report.get("crest", 0), 1),
"loudness_range_lu": round(report.get("lra", 0), 1),
"band_balance_db": {k: round(v, 1) for k, v in report.get("bands", {}).items()},
"ratios_db": {k: round(v, 1) for k, v in report.get("ratios", {}).items()},
"stereo": {k: round(v, 2) for k, v in report.get("stereo", {}).items()},
"tempo_bpm": round(report.get("rhythm", {}).get("bpm", 0), 1),
"key": report.get("key", {}).get("key", "β"),
},
"rule_findings": [
{"severity": d["severity"], "headline": d["headline"],
"evidence": d["evidence"], "suggested_move": d["move"]}
for d in diagnoses[:6]
],
"sounds_like": {g: [t for t, _ in v] for g, v in (semantic_tags or {}).items()},
}
try:
client = InferenceClient(api_key=_token(), provider="auto")
resp = client.chat_completion(
model=DEFAULT_MODEL,
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": json.dumps(payload, ensure_ascii=False)},
],
max_tokens=700,
temperature=0.6,
)
return (resp.choices[0].message.content or "").strip()
except Exception as exc: # noqa: BLE001 - narration is optional by design
return (f"_Narration unavailable ({type(exc).__name__}: {exc}). "
f"The analysis above stands on its own._")
|