import json import re from llm import generate_vision_pass VISION_PROMPT = """Analyze this image and return ONLY a JSON object, no other text: { "scene": "one sentence describing the setting", "mood": "one word emotional tone", "objects": ["key", "objects", "in", "scene"], "style": "visual style (cinematic, documentary, candid, etc)", "possible_interpretations": ["2-3 thematic meanings a debater could argue"] }""" def run_vision_pass(image_path: str) -> dict: """ Extract structured scene context from image. Runs once per debate — result is passed to all persona turns as text. Sends image via local transformers ZeroGPU pipeline. """ text = generate_vision_pass(image_path, VISION_PROMPT) match = re.search(r"\{.*\}", text, re.DOTALL) if not match: raise ValueError(f"Vision pass returned no JSON:\n{text}") return json.loads(match.group()) def build_context_block(scene: dict) -> str: """ Format scene dict into a readable text block injected into every persona and judge prompt. """ objects = ", ".join(scene["objects"]) if scene.get("objects") else "none" interpretations = ( "; ".join(scene["possible_interpretations"]) if scene.get("possible_interpretations") else "none" ) return ( f"IMAGE CONTEXT (factual, do not dispute this):\n" f"- Scene: {scene['scene']}\n" f"- Mood: {scene['mood']}\n" f"- Objects: {objects}\n" f"- Style: {scene['style']}\n" f"- Possible interpretations: {interpretations}" )