Sunstead trust scoring project
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.9 kB View raw
1"""M7 voice briefing (PRD: an ElevenLabs voice briefing on the API). 2 3The explanation `summary` is already "suitable to read aloud" (6.6/6.9), so this 4just composes a short spoken script from an assessment and pipes it to ElevenLabs. 5No SDK — one POST with httpx. 6 7Env (only ELEVENLABS_API_KEY touches the network): 8 ELEVENLABS_API_KEY your key; absent -> the API returns the brief text instead of audio 9 ELEVENLABS_VOICE_ID voice (default: a public ElevenLabs voice) 10""" 11 12from __future__ import annotations 13 14import os 15 16URL = "https://api.elevenlabs.io/v1/text-to-speech/{voice}" 17DEFAULT_VOICE = os.environ.get("ELEVENLABS_VOICE_ID", "21m00Tcm4TlvDq8ikWAM") # "Rachel" (public) 18DECISION_PHRASE = { 19 "fast_lane": "safe to fast-lane", 20 "normal_queue": "for the normal review queue", 21 "needs_human": "routed to a human reviewer", 22} 23 24 25def brief_text(score: dict) -> str: 26 """2-3 sentence spoken script from an assessment. Skips raw DIDs (unspeakable).""" 27 who = score.get("handle") or score["did"] 28 pct = round((score.get("calibrated_prob") or 0) * 100) 29 decision = DECISION_PHRASE.get(score["decision"], score["decision"]) 30 reason = score.get("explanation") or {} 31 out = [f"{who}: {decision}. Calibrated trust {pct} percent."] 32 if reason.get("compliance_block"): 33 out.append(reason["compliance_block"]) 34 else: 35 factor = next((f for f in reason.get("top_factors", []) 36 if "did:" not in f and "trust reaches" not in f), None) 37 if factor: 38 out.append(factor.rstrip(".") + ".") 39 if reason.get("content_summary"): 40 out.append("Claude notes: " + reason["content_summary"]) 41 return " ".join(out) 42 43 44def synthesize(text: str) -> bytes | None: 45 """ElevenLabs TTS -> mp3 bytes, or None when no API key is configured.""" 46 key = os.environ.get("ELEVENLABS_API_KEY") 47 if not key: 48 return None 49 import httpx 50 51 r = httpx.post(URL.format(voice=DEFAULT_VOICE), 52 headers={"xi-api-key": key, "accept": "audio/mpeg"}, 53 json={"text": text, "model_id": "eleven_turbo_v2_5"}, timeout=60) 54 r.raise_for_status() 55 return r.content 56 57 58def demo() -> None: 59 """Self-check: build a sensible script; synth is a no-op without a key.""" 60 script = brief_text({ 61 "did": "did:plc:alice", "handle": "alice.dev", "calibrated_prob": 1.0, 62 "decision": "needs_human", 63 "explanation": {"compliance_block": "sensitive-tier repo: a valid jurisdiction " 64 "attestation is required before fast-lane/merge (6.13)", 65 "top_factors": ["trust reaches did:plc:alice via maintainer", "8 merged PRs"]}, 66 }) 67 print(script) 68 assert "alice.dev" in script and "human reviewer" in script and "did:" not in script 69 assert synthesize(script) is None or isinstance(synthesize(script), bytes) 70 print("ok") 71 72 73if __name__ == "__main__": 74 demo()