""" Root-level Gradio app for WorldSmithAI. This file is intended to live directly beside callbacks.py in the repository root. It does not assume an app/ package or folder. The UI is intentionally thin: - app.py defines the Gradio interface. - callbacks.py runs generation, parsing, validation, world construction, simulation, visualization, metrics, and narration. - The simulation engine remains generic and DSL-driven. Environment variables: WORLDSMITHAI_MODEL_ID: Optional Hugging Face model id for model-generated DSL. HF_TOKEN: Optional Hugging Face token for private or gated models. WORLDSMITHAI_OUTPUT_DIR: Optional directory for generated GIFs, MP4s, charts, and images. WORLDSMITHAI_DEFAULT_STEPS: Optional default simulation step count. WORLDSMITHAI_MAX_FRAMES: Optional maximum animation frame count. WORLDSMITHAI_LOG_LEVEL: Optional logging level. Defaults to INFO. """ from __future__ import annotations import json import logging import os import traceback from collections.abc import Mapping from dataclasses import dataclass from pathlib import Path from typing import Any import gradio as gr from callbacks import ( CallbackConfig, CallbackResult, apply_step_override, callback_failure_result, generate_world_from_prompt, load_example_callback, parse_constraints, run_worldsmith_pipeline, simulate_dsl_pipeline, validate_dsl_callback, ) from dsl.validator import validate_world_spec APP_TITLE = "WorldSmithAI" APP_SUBTITLE = "Production-Level Agent-Based World Simulation Framework" APP_VERSION = "0.1.0" DEFAULT_PROMPT = ( "Create a compact research ecosystem where scientists, engineers, reviewers, " "and funding agents exchange knowledge, compete for attention, collaborate, " "and adapt their goals over time." ) PROMPT_EXAMPLES = [ [ "A medieval civilization with merchants, rulers, artisans, scholars, guards, " "taxes, trade, regulations, and resource pressure." ], [ "A startup economy with founders, investors, customers, operators, competitors, " "market bidding, adoption dynamics, and shifting goals." ], [ "A fantasy world with mages, dragons, healers, merchants, mana resources, " "alliances, communication, negotiation, and magical infrastructure." ], [ "A transport network with hubs, carriers, dispatchers, chargers, passengers, " "queues, routes, deliveries, and congestion." ], [ "A power grid world with generators, storage nodes, consumers, regulators, " "energy resources, subsidies, enforcement, and rebalancing." ], [ "A space colony with colonists, engineers, botanists, navigators, miners, " "oxygen resources, habitat expansion, and survival goals." ], ] CUSTOM_CSS = """ #worldsmith-header { padding: 1.1rem 1.25rem; border-radius: 1rem; background: linear-gradient(135deg, rgba(80, 80, 120, 0.12), rgba(120, 120, 160, 0.08)); border: 1px solid rgba(120, 120, 160, 0.18); } .worldsmith-small { font-size: 0.92rem; opacity: 0.82; } .worldsmith-status textarea { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; } """ logging.basicConfig( level=os.getenv("WORLDSMITHAI_LOG_LEVEL", "INFO").upper(), format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", ) logger = logging.getLogger(__name__) @dataclass(frozen=True) class AppModelStatus: """Status of the optional model client used by the UI.""" enabled: bool model_id: str | None message: str def to_markdown(self) -> str: """Return display Markdown for model status.""" if self.enabled: return f"**Model client:** configured with `{self.model_id}`." return f"**Model client:** not configured. {self.message}" class OptionalHFInferenceClient: """Small adapter around huggingface_hub.InferenceClient. This adapter tries both chat-completion and text-generation APIs and raises detailed errors instead of hiding provider/model failures. """ def __init__( self, model_id: str, token: str | None = None, provider: str | None = None, ) -> None: """Initialize the optional Hugging Face inference adapter.""" from huggingface_hub import InferenceClient self.model_id = model_id.strip().strip('"').strip("'").strip() self.provider = None if provider is None or not str(provider).strip() else str(provider).strip() api_key = ( token or os.getenv("HF_TOKEN") or os.getenv("HF_HUB_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN") ) if not api_key: raise RuntimeError( "HF_TOKEN is required for Hugging Face Inference Providers. " "Create a Hugging Face token with Inference Providers permission " "and add it as a Space secret named HF_TOKEN." ) if self.provider: self.client = InferenceClient( model=self.model_id, provider=self.provider, api_key=api_key, ) else: self.client = InferenceClient( model=self.model_id, api_key=api_key, ) def generate( self, prompt: str | None = None, messages: list[dict[str, str]] | None = None, max_new_tokens: int = 2048, temperature: float = 0.2, **_: Any, ) -> str: """Generate text using Hugging Face chat or text-generation APIs.""" errors: list[str] = [] if messages: text = self._try_chat_completion( messages, max_new_tokens=max_new_tokens, temperature=temperature, errors=errors, ) if text: return text text = self._try_openai_compatible_chat( messages, max_new_tokens=max_new_tokens, temperature=temperature, errors=errors, ) if text: return text if prompt: text = self._try_text_generation( prompt, max_new_tokens=max_new_tokens, temperature=temperature, errors=errors, ) if text: return text error_text = "\n".join(errors) if errors else "No inference method was attempted." raise RuntimeError( "InferenceClient did not return generated text.\n\n" f"Model id: {self.model_id}\n\n" f"Attempted methods and errors:\n{error_text}" ) def _try_chat_completion( self, messages: list[dict[str, str]], *, max_new_tokens: int, temperature: float, errors: list[str], ) -> str | None: """Try InferenceClient.chat_completion().""" chat_completion = getattr(self.client, "chat_completion", None) if not callable(chat_completion): errors.append("chat_completion: method not available on InferenceClient") return None try: response = chat_completion( messages=messages, max_tokens=max_new_tokens, temperature=temperature, ) text = _extract_model_text(response) if text: return text errors.append( "chat_completion: response had no extractable text. " f"response_type={response.__class__.__name__}, response={_short_repr(response)}" ) return None except Exception as exc: errors.append(f"chat_completion: {exc.__class__.__name__}: {exc}") return None def _try_openai_compatible_chat( self, messages: list[dict[str, str]], *, max_new_tokens: int, temperature: float, errors: list[str], ) -> str | None: """Try InferenceClient.chat.completions.create().""" chat = getattr(self.client, "chat", None) completions = getattr(chat, "completions", None) create = getattr(completions, "create", None) if not callable(create): errors.append("chat.completions.create: method not available on InferenceClient") return None call_variants = ( { "model": self.model_id, "messages": messages, "max_tokens": max_new_tokens, "temperature": temperature, }, { "messages": messages, "max_tokens": max_new_tokens, "temperature": temperature, }, ) for kwargs in call_variants: try: response = create(**kwargs) text = _extract_model_text(response) if text: return text errors.append( "chat.completions.create: response had no extractable text. " f"kwargs_keys={list(kwargs.keys())}, " f"response_type={response.__class__.__name__}, " f"response={_short_repr(response)}" ) except Exception as exc: errors.append( "chat.completions.create: " f"kwargs_keys={list(kwargs.keys())}, " f"{exc.__class__.__name__}: {exc}" ) return None def _try_text_generation( self, prompt: str, *, max_new_tokens: int, temperature: float, errors: list[str], ) -> str | None: """Try InferenceClient.text_generation().""" text_generation = getattr(self.client, "text_generation", None) if not callable(text_generation): errors.append("text_generation: method not available on InferenceClient") return None call_variants = ( { "prompt": prompt, "max_new_tokens": max_new_tokens, "temperature": temperature, "return_full_text": False, }, { "prompt": prompt, "max_new_tokens": max_new_tokens, "return_full_text": False, }, { "prompt": prompt, "max_new_tokens": max_new_tokens, }, ) for kwargs in call_variants: try: response = text_generation(**kwargs) text = _extract_model_text(response) if text: return text errors.append( "text_generation: response had no extractable text. " f"kwargs_keys={list(kwargs.keys())}, " f"response_type={response.__class__.__name__}, " f"response={_short_repr(response)}" ) except Exception as exc: errors.append( "text_generation: " f"kwargs_keys={list(kwargs.keys())}, " f"{exc.__class__.__name__}: {exc}" ) return None def build_optional_model_client() -> tuple[Any | None, AppModelStatus]: """Build the optional model client from environment variables.""" raw_model_id = ( os.getenv("WORLDSMITHAI_MODEL_ID") or os.getenv("WORLD_SMITH_MODEL_ID") or os.getenv("HF_MODEL_ID") ) token = ( os.getenv("HF_TOKEN") or os.getenv("HF_HUB_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN") ) provider = ( os.getenv("WORLDSMITHAI_PROVIDER") or os.getenv("HF_INFERENCE_PROVIDER") or None ) if not raw_model_id: return None, AppModelStatus( enabled=False, model_id=None, message="Set WORLDSMITHAI_MODEL_ID to enable model-generated DSL.", ) model_id = raw_model_id.strip().strip('"').strip("'").strip() logger.info( "WorldSmithAI model configuration: raw_model_id=%r sanitized_model_id=%r", raw_model_id, model_id, ) if not model_id: return None, AppModelStatus( enabled=False, model_id=None, message="WORLDSMITHAI_MODEL_ID was set but empty after sanitization.", ) try: client = OptionalHFInferenceClient( model_id=model_id, token=token, provider=provider, ) return client, AppModelStatus( enabled=True, model_id=model_id, message="Model client configured.", ) except Exception as exc: logger.warning("Optional model client could not be configured: %s", exc) return None, AppModelStatus( enabled=False, model_id=model_id, message=( f"WORLDSMITHAI_MODEL_ID={model_id} was found, but the client " f"could not be initialized: {exc}. The app will use deterministic fallback." ), ) MODEL_CLIENT, MODEL_STATUS = build_optional_model_client() def model_health_check_ui() -> str: """Return a quick model-client health check for the Gradio UI.""" if MODEL_CLIENT is None: return ( "Model client is NOT configured.\n\n" f"Runtime status: {MODEL_STATUS.message}\n\n" "Check that WORLDSMITHAI_MODEL_ID is set in Space settings." ) provider_label = ( getattr(MODEL_CLIENT, "provider", None) or os.getenv("WORLDSMITHAI_PROVIDER") or os.getenv("HF_INFERENCE_PROVIDER") or "auto" ) try: response = MODEL_CLIENT.generate( prompt='Return exactly this JSON object and nothing else: {"ok": true}', messages=[ { "role": "system", "content": "You return compact JSON only.", }, { "role": "user", "content": 'Return exactly this JSON object and nothing else: {"ok": true}', }, ], max_new_tokens=64, temperature=0.0, ) return ( "Model client is configured and returned text.\n\n" f"Model id: {MODEL_STATUS.model_id}\n\n" f"Provider: {provider_label}\n\n" f"Response:\n{response}" ) except Exception as exc: logger.exception("Model health check failed") return ( "Model client is configured but inference failed.\n\n" f"Model id: {MODEL_STATUS.model_id}\n\n" f"Provider: {provider_label}\n\n" f"Error type: {exc.__class__.__name__}\n" f"Error:\n{exc}" ) def app_callback_config( *, steps: int | float | str | None, animation_format: str, ) -> CallbackConfig: """Create callback configuration from UI values and environment defaults.""" default_steps = _env_int("WORLDSMITHAI_DEFAULT_STEPS", 60) max_frames = _env_int("WORLDSMITHAI_MAX_FRAMES", 80) output_dir = os.getenv("WORLDSMITHAI_OUTPUT_DIR") or None return CallbackConfig( output_dir=output_dir, steps=_coerce_optional_int(steps) if steps is not None else default_steps, max_animation_frames=max(1, max_frames), animation_format=animation_format, ) def run_from_prompt_ui( prompt: str, steps: int | float, constraints: str, animation_format: str, use_configured_model: bool, ) -> tuple[Any, ...]: """Run the full prompt-to-simulation pipeline for the main UI tab.""" client = MODEL_CLIENT if use_configured_model else None config = app_callback_config(steps=steps, animation_format=animation_format) try: result = run_worldsmith_pipeline( prompt=prompt, constraints=parse_constraints(constraints), client=client, config=config, ) return result_to_ui_tuple(result) except Exception as exc: logger.exception("Prompt simulation failed") return failure_to_ui_tuple(exc) def generate_dsl_only_ui( prompt: str, constraints: str, use_configured_model: bool, steps: int | float, ) -> tuple[str, str, str]: """Generate DSL only, without running simulation.""" client = MODEL_CLIENT if use_configured_model else None config = app_callback_config(steps=steps, animation_format="gif") try: generation = generate_world_from_prompt( prompt=prompt, constraints=parse_constraints(constraints), client=client, config=config, ) spec = apply_step_override(generation.spec, _coerce_optional_int(steps)) report = validate_world_spec( spec, config=config.resolved_validation_config(), ) status = ( f"Generated `{spec.id}` with {len(spec.agents)} agent(s), " f"{len(spec.resources)} resource(s), and " f"{len(spec.behavior_names)} behavior reference(s). " f"Validation: {len(report.errors)} error(s), {len(report.warnings)} warning(s)." ) return ( spec.to_json_string(indent=2, exclude_none=True), _safe_json_dumps(report.to_dict()), status, ) except Exception as exc: logger.exception("DSL generation failed") return "", "{}", f"DSL generation failed: {exc}" def simulate_dsl_ui( dsl_json: str, steps: int | float, animation_format: str, use_configured_model_for_narration: bool, ) -> tuple[Any, ...]: """Run simulation from user-supplied DSL JSON.""" client = MODEL_CLIENT if use_configured_model_for_narration else None config = app_callback_config(steps=steps, animation_format=animation_format) try: result = simulate_dsl_pipeline( dsl_json=dsl_json, client=client, config=config, ) return result_to_ui_tuple(result) except Exception as exc: logger.exception("DSL simulation failed") return failure_to_ui_tuple(exc, world_spec_json=dsl_json) def validate_dsl_ui(dsl_json: str) -> tuple[str, str]: """Validate DSL JSON in the validation tab.""" return validate_dsl_callback(dsl_json) def load_example_ui(example_name: str | None) -> tuple[str, str]: """Load an example JSON file into the DSL editor.""" if not example_name: return "", "Choose an example first." examples = discover_examples() path = examples.get(example_name) if path is None: return "", f"Unknown example: {example_name}" return load_example_callback(path) def clear_main_outputs() -> tuple[Any, ...]: """Clear main-tab outputs.""" return ( "", "", gr.update(value=None, visible=False), gr.update(value=None, visible=False), None, None, None, "", "", "", ) def result_to_ui_tuple(result: CallbackResult) -> tuple[Any, ...]: """Map CallbackResult to the app output component order.""" animation_image, animation_video = animation_path_updates(result.animation_path) return ( result.world_spec_json, result.validation_json, animation_image, animation_video, result.population_chart_path, result.resource_chart_path, result.final_image_path, _markdown_narrative(result.narrative), result.metrics_json, result.status_message, ) def failure_to_ui_tuple( error: BaseException, *, world_spec_json: str = "", ) -> tuple[Any, ...]: """Map an exception to a safe UI output tuple.""" result = callback_failure_result(error, world_spec_json=world_spec_json) details = { "success": False, "error_type": error.__class__.__name__, "error": str(error), "traceback": traceback.format_exc(), "callback_result": result.to_dict(), } return ( result.world_spec_json, result.validation_json, gr.update(value=None, visible=False), gr.update(value=None, visible=False), None, None, None, _markdown_narrative(result.narrative), _safe_json_dumps(details), result.status_message, ) def animation_path_updates(path: str | None) -> tuple[Any, Any]: """Return Gradio updates for GIF/image and MP4/video animation components.""" if not path: return gr.update(value=None, visible=False), gr.update(value=None, visible=False) suffix = Path(path).suffix.lower() if suffix in {".mp4", ".webm", ".mov", ".m4v"}: return gr.update(value=None, visible=False), gr.update(value=path, visible=True) return gr.update(value=path, visible=True), gr.update(value=None, visible=False) def discover_examples() -> dict[str, Path]: """Discover JSON example files in the root-level examples directory.""" examples_dir = Path(__file__).resolve().parent / "examples" if not examples_dir.exists(): return {} return { path.stem.replace("_", " ").title(): path for path in sorted(examples_dir.glob("*.json")) } def build_demo() -> gr.Blocks: """Build and return the Gradio Blocks demo.""" examples = discover_examples() example_names = list(examples.keys()) default_steps = _env_int("WORLDSMITHAI_DEFAULT_STEPS", 60) with gr.Blocks( title=f"{APP_TITLE} — Agent-Based World Simulation", css=CUSTOM_CSS, analytics_enabled=False, ) as demo: gr.Markdown( f"""
# {APP_TITLE} ### {APP_SUBTITLE} WorldSmithAI converts natural language into a validated JSON DSL, builds a deterministic Python agent-based world, simulates emergent behavior, and returns animation, charts, metrics, and narration. No species or domains are hardcoded. A farmer, dragon, scientist, vehicle, startup, power node, or civilization actor is a generic Agent with state, memory, behaviors, and policy.
""" ) with gr.Accordion("Runtime status", open=False): gr.Markdown(MODEL_STATUS.to_markdown()) gr.Markdown( "If no model client is configured, the app still runs with the deterministic fallback DSL generator. " "Set WORLDSMITHAI_MODEL_ID in the Space environment to enable model-generated DSL." ) model_health_button = gr.Button("Check model connection") model_health_output = gr.Textbox( label="Model health check", lines=8, interactive=False, ) model_health_button.click( fn=model_health_check_ui, inputs=[], outputs=[model_health_output], ) with gr.Tabs(): with gr.Tab("Generate + Simulate"): with gr.Row(): with gr.Column(scale=1): prompt = gr.Textbox( label="World prompt", value=DEFAULT_PROMPT, lines=8, placeholder=( "Describe any agent-based world: farm, civilization, research lab, " "startup economy, fantasy realm, transport system..." ), ) constraints = gr.Textbox( label="Optional constraints", value='{"max_agents": 6, "demo_size": "small"}', lines=4, placeholder='Example: {"max_agents": 6, "steps": 80}', ) with gr.Row(): steps = gr.Slider( minimum=1, maximum=250, value=default_steps, step=1, label="Simulation steps", ) animation_format = gr.Dropdown( choices=["gif", "mp4"], value="gif", label="Animation format", ) use_model = gr.Checkbox( label="Use configured model client when available", value=MODEL_CLIENT is not None, interactive=True, ) with gr.Row(): run_button = gr.Button("Generate world + run simulation", variant="primary") clear_button = gr.Button("Clear outputs") gr.Examples( examples=PROMPT_EXAMPLES, inputs=[prompt], label="Prompt examples", ) with gr.Column(scale=1): status = gr.Textbox( label="Status", lines=3, interactive=False, elem_classes=["worldsmith-status"], ) narrative = gr.Markdown(label="Narrative summary") with gr.Tab("Visual outputs"): with gr.Row(): animation_image = gr.Image( label="Simulation animation GIF", type="filepath", visible=True, ) animation_video = gr.Video( label="Simulation animation MP4", visible=False, ) with gr.Row(): final_image = gr.Image( label="Final world state", type="filepath", ) population_chart = gr.Image( label="Population chart", type="filepath", ) resource_chart = gr.Image( label="Resource chart", type="filepath", ) with gr.Tab("Generated DSL + diagnostics"): world_spec_json = gr.Code( label="Generated WorldSpec JSON", language="json", lines=24, ) validation_json = gr.Code( label="Validation report", language="json", lines=16, ) metrics_json = gr.Code( label="Metrics and run diagnostics", language="json", lines=24, ) main_outputs = [ world_spec_json, validation_json, animation_image, animation_video, population_chart, resource_chart, final_image, narrative, metrics_json, status, ] run_button.click( fn=run_from_prompt_ui, inputs=[prompt, steps, constraints, animation_format, use_model], outputs=main_outputs, show_progress=True, ) clear_button.click( fn=clear_main_outputs, inputs=[], outputs=main_outputs, ) with gr.Tab("Generate DSL only"): with gr.Row(): with gr.Column(scale=1): dsl_prompt = gr.Textbox( label="World prompt", value=DEFAULT_PROMPT, lines=8, ) dsl_constraints = gr.Textbox( label="Optional constraints", value='{"max_agents": 6}', lines=4, ) dsl_steps = gr.Slider( minimum=1, maximum=250, value=default_steps, step=1, label="Simulation steps to put in DSL", ) dsl_use_model = gr.Checkbox( label="Use configured model client when available", value=MODEL_CLIENT is not None, ) generate_dsl_button = gr.Button("Generate DSL", variant="primary") with gr.Column(scale=1): generated_dsl_status = gr.Textbox( label="Status", lines=3, interactive=False, ) generated_dsl_validation = gr.Code( label="Validation report", language="json", lines=16, ) generated_dsl = gr.Code( label="Generated WorldSpec JSON", language="json", lines=28, ) generate_dsl_button.click( fn=generate_dsl_only_ui, inputs=[dsl_prompt, dsl_constraints, dsl_use_model, dsl_steps], outputs=[generated_dsl, generated_dsl_validation, generated_dsl_status], show_progress=True, ) with gr.Tab("Simulate existing DSL"): with gr.Row(): with gr.Column(scale=1): example_dropdown = gr.Dropdown( choices=example_names, value=example_names[0] if example_names else None, label="Load example JSON", interactive=bool(example_names), ) load_example_button = gr.Button("Load selected example") example_status = gr.Textbox( label="Example status", lines=2, interactive=False, ) existing_dsl = gr.Code( label="WorldSpec JSON", language="json", lines=28, value="", ) with gr.Row(): existing_steps = gr.Slider( minimum=1, maximum=250, value=default_steps, step=1, label="Simulation steps override", ) existing_animation_format = gr.Dropdown( choices=["gif", "mp4"], value="gif", label="Animation format", ) existing_use_model = gr.Checkbox( label="Use configured model client for narration when available", value=False, ) simulate_dsl_button = gr.Button("Simulate DSL", variant="primary") with gr.Column(scale=1): existing_status = gr.Textbox( label="Status", lines=3, interactive=False, ) existing_narrative = gr.Markdown(label="Narrative summary") with gr.Tab("DSL simulation visuals"): with gr.Row(): existing_animation_image = gr.Image( label="Simulation animation GIF", type="filepath", visible=True, ) existing_animation_video = gr.Video( label="Simulation animation MP4", visible=False, ) with gr.Row(): existing_final_image = gr.Image( label="Final world state", type="filepath", ) existing_population_chart = gr.Image( label="Population chart", type="filepath", ) existing_resource_chart = gr.Image( label="Resource chart", type="filepath", ) with gr.Tab("DSL simulation diagnostics"): existing_validation = gr.Code( label="Validation report", language="json", lines=16, ) existing_metrics = gr.Code( label="Metrics and run diagnostics", language="json", lines=24, ) load_example_button.click( fn=load_example_ui, inputs=[example_dropdown], outputs=[existing_dsl, example_status], ) simulate_dsl_button.click( fn=simulate_dsl_ui, inputs=[ existing_dsl, existing_steps, existing_animation_format, existing_use_model, ], outputs=[ existing_dsl, existing_validation, existing_animation_image, existing_animation_video, existing_population_chart, existing_resource_chart, existing_final_image, existing_narrative, existing_metrics, existing_status, ], show_progress=True, ) with gr.Tab("Validate DSL"): validation_input = gr.Code( label="WorldSpec JSON to validate", language="json", lines=28, ) validate_button = gr.Button("Validate DSL", variant="primary") validation_output = gr.Code( label="Validation report", language="json", lines=24, ) validation_status = gr.Textbox( label="Status", lines=3, interactive=False, ) validate_button.click( fn=validate_dsl_ui, inputs=[validation_input], outputs=[validation_output, validation_status], ) with gr.Tab("About"): gr.Markdown( """ ## WorldSmithAI architecture WorldSmithAI follows this pipeline: Natural language prompt → SLM-generated JSON DSL → Pydantic schema validation → Semantic DSL validation → WorldFactory → World / Scheduler / Agents / Policies / Behaviors → Metrics / Visualization / Narration → Gradio UI ### Important design constraint The simulation engine is deterministic Python. The model generates JSON only, never Python code. ### UI outputs - Animation: GIF by default; MP4 if selected and ffmpeg is available. - Population chart: grouped by agent type. - Resource chart: grouped by resource type and weighted by amount. - Narrative: deterministic by default, optionally model-assisted if a client is configured. - Diagnostics: includes DSL validation, factory build report, metric history, artifact paths, and generation mode. ### Suggested root-level Space layout app.py callbacks.py requirements.txt core/ behaviors/ policies/ dsl/ factory/ metrics/ visualization/ llm/ examples/ """ ) return demo def _short_repr(value: Any, *, max_chars: int = 1200) -> str: """Return a bounded repr for diagnostics.""" text = repr(value) if len(text) <= max_chars: return text return text[: max_chars - 3] + "..." def _extract_model_text(response: Any) -> str | None: """Extract text from common model response shapes.""" if response is None: return None if isinstance(response, str): return response.strip() if isinstance(response, bytes): return response.decode("utf-8").strip() if isinstance(response, Mapping): for key in ("text", "content", "generated_text", "output", "response"): value = response.get(key) if value is not None: return _extract_model_text(value) choices = response.get("choices") if isinstance(choices, list) and choices: return _extract_model_text(choices[0]) message = response.get("message") if isinstance(message, Mapping): return _extract_model_text(message.get("content")) for attr in ("text", "content", "generated_text", "output", "response"): value = getattr(response, attr, None) if value is not None: return _extract_model_text(value) choices = getattr(response, "choices", None) if choices: return _extract_model_text(choices[0]) message = getattr(response, "message", None) if message is not None: return _extract_model_text(message) return None def _coerce_optional_int(value: int | float | str | None) -> int | None: """Coerce UI numeric values to optional int.""" if value is None or value == "": return None return int(float(value)) def _env_int(name: str, default: int) -> int: """Read an integer environment variable with a safe default.""" raw = os.getenv(name) if raw is None or raw == "": return default try: return int(float(raw)) except ValueError: logger.warning("Invalid integer environment variable %s=%r", name, raw) return default def _safe_json_dumps(value: Any) -> str: """Serialize values as pretty JSON for Gradio Code components.""" return json.dumps( _json_safe(value), indent=2, sort_keys=True, ensure_ascii=False, ) def _json_safe(value: Any) -> Any: """Return JSON-friendly representation of arbitrary values.""" if value is None or isinstance(value, (str, bool)): return value if isinstance(value, int) and not isinstance(value, bool): return value if isinstance(value, float): if value != value or value in {float("inf"), float("-inf")}: return None return value if isinstance(value, Mapping): return {str(key): _json_safe(nested) for key, nested in value.items()} if isinstance(value, (list, tuple)): return [_json_safe(item) for item in value] if hasattr(value, "to_dict") and callable(value.to_dict): return _json_safe(value.to_dict()) if hasattr(value, "model_dump") and callable(value.model_dump): return _json_safe(value.model_dump(mode="json")) return str(value) def _markdown_narrative(text: str) -> str: """Return narrative text formatted for Markdown display.""" cleaned = str(text or "").strip() if not cleaned: return "No narrative was generated." return cleaned demo = build_demo() app = demo if __name__ == "__main__": demo.queue().launch()