AndrewRqy commited on
Commit ·
dd4200b
1
Parent(s): 7d8efb5
Add ORACLES_VISUAL_MODE toggle — lean default, full enabled via --full or env var
Browse files- Dockerfile +2 -1
- app.py +101 -49
- run.sh +21 -0
Dockerfile
CHANGED
|
@@ -29,6 +29,7 @@ EXPOSE 7860
|
|
| 29 |
ENV GRADIO_SERVER_NAME=0.0.0.0 \
|
| 30 |
GRADIO_SERVER_PORT=7860 \
|
| 31 |
GRADIO_ANALYTICS_ENABLED=False \
|
| 32 |
-
PYTHONUNBUFFERED=1
|
|
|
|
| 33 |
|
| 34 |
CMD ["python", "app.py"]
|
|
|
|
| 29 |
ENV GRADIO_SERVER_NAME=0.0.0.0 \
|
| 30 |
GRADIO_SERVER_PORT=7860 \
|
| 31 |
GRADIO_ANALYTICS_ENABLED=False \
|
| 32 |
+
PYTHONUNBUFFERED=1 \
|
| 33 |
+
ORACLES_VISUAL_MODE=lean
|
| 34 |
|
| 35 |
CMD ["python", "app.py"]
|
app.py
CHANGED
|
@@ -75,6 +75,23 @@ _PARALLAX_PNG = _HERE / "assets" / "parallax" / "banner_near.png"
|
|
| 75 |
_GRIMOIRE_TEXTURE_PNG = _HERE / "assets" / "sprites" / "grimoire_page_texture.png"
|
| 76 |
|
| 77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
# ---------------------------------------------------------------------------
|
| 79 |
# Pixel-art book frame: leather binding (via CSS border-image 9-slice), a
|
| 80 |
# vertical spine with raised bands and stitching, and a red ribbon bookmark.
|
|
@@ -298,13 +315,12 @@ def _grimoire_texture_css() -> str:
|
|
| 298 |
texture as a background-image on .grimoire-page, if the PNG exists.
|
| 299 |
Returns empty string otherwise (so the CSS-only gradients still apply).
|
| 300 |
|
| 301 |
-
|
| 302 |
-
base64-inlined into the initial CSS
|
| 303 |
-
|
| 304 |
-
just deleting the early return below.
|
| 305 |
"""
|
| 306 |
-
|
| 307 |
-
|
| 308 |
if not _GRIMOIRE_TEXTURE_PNG.exists():
|
| 309 |
return ""
|
| 310 |
try:
|
|
@@ -502,11 +518,19 @@ def _grimoire_summary_html(state: GameState) -> str:
|
|
| 502 |
for o in state.oracles:
|
| 503 |
text = (o.text or "").strip() or blank_label
|
| 504 |
items.append(f"<li><em>{_md_safe(text)}</em></li>")
|
| 505 |
-
#
|
| 506 |
-
#
|
| 507 |
-
#
|
| 508 |
-
|
| 509 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
header = _md_safe(_t("summary_five_sealed", lang))
|
| 511 |
return (
|
| 512 |
"<div class='grimoire-summary'>"
|
|
@@ -545,11 +569,14 @@ def _pipeline_demo_html(state: Optional[GameState] = None) -> str:
|
|
| 545 |
# Pixel-art sprites + backdrop pre-loaded as data URIs. The
|
| 546 |
# `_sprite_data_uri_app` helper caches per name, so reading the same
|
| 547 |
# sprite twice in this function only hits disk once.
|
| 548 |
-
#
|
| 549 |
-
#
|
| 550 |
-
#
|
| 551 |
-
|
| 552 |
-
|
|
|
|
|
|
|
|
|
|
| 553 |
tag_inscribes = _t("demo_tag_inscribes", lang)
|
| 554 |
tag_meets = _t("demo_tag_meets", lang)
|
| 555 |
tag_somehow = _t("demo_tag_somehow", lang)
|
|
@@ -693,10 +720,10 @@ def _inscribe_decoration_html(state: Optional[GameState] = None) -> str:
|
|
| 693 |
_sprite_data_uri_app(f"hero_{theme_key_for_sprites}")
|
| 694 |
or _sprite_data_uri_app("hero")
|
| 695 |
)
|
| 696 |
-
#
|
| 697 |
-
#
|
| 698 |
-
#
|
| 699 |
-
desk_uri = ""
|
| 700 |
if not wizard_uri or not hero_uri:
|
| 701 |
fallback = (
|
| 702 |
"<div class='oracle-inscribe-figs' style='text-align:center;"
|
|
@@ -819,19 +846,28 @@ def _banner_html(state: Optional[GameState] = None) -> str:
|
|
| 819 |
is_compact = mode in ("trial", "epilogue", "send_off")
|
| 820 |
extra_cls = " oracle-banner-compact" if is_compact else ""
|
| 821 |
|
| 822 |
-
#
|
| 823 |
-
#
|
| 824 |
-
#
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 835 |
_BANNER_HTML_CACHE[cache_key] = result
|
| 836 |
return result
|
| 837 |
|
|
@@ -912,14 +948,34 @@ def _global_sprite_vars_html() -> str:
|
|
| 912 |
|
| 913 |
|
| 914 |
def _phase_backdrop_styles_html() -> str:
|
| 915 |
-
"""One-time ``<style>`` block
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
|
| 920 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 921 |
"""
|
| 922 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 923 |
|
| 924 |
|
| 925 |
def _theme_style_overrides_html(state: Optional[GameState] = None) -> str:
|
|
@@ -3395,18 +3451,14 @@ def _composed_scene_html(state: GameState) -> str:
|
|
| 3395 |
return landscape
|
| 3396 |
return _sprite_data_uri_app(category) or ""
|
| 3397 |
|
| 3398 |
-
#
|
| 3399 |
-
# PNG is ~200-500 KB and
|
| 3400 |
-
#
|
| 3401 |
-
#
|
| 3402 |
-
env_uri = ""
|
| 3403 |
hero_uri = _theme_pick("hero")
|
| 3404 |
ob_uri = _theme_pick(ob_name) if ob_name else ""
|
| 3405 |
|
| 3406 |
-
# No early bailout — we now always render the composed scene with a
|
| 3407 |
-
# CSS-gradient backdrop, even with env_uri empty. Hero + obstacle
|
| 3408 |
-
# carry the visual load.
|
| 3409 |
-
|
| 3410 |
dragon_attr = ' data-dragon="true"' if is_dragon else ""
|
| 3411 |
hero_img = (
|
| 3412 |
f"<img class='scene-hero' src='{hero_uri}' alt='hero'/>"
|
|
|
|
| 75 |
_GRIMOIRE_TEXTURE_PNG = _HERE / "assets" / "sprites" / "grimoire_page_texture.png"
|
| 76 |
|
| 77 |
|
| 78 |
+
def _full_visual_mode() -> bool:
|
| 79 |
+
"""Visual-mode toggle. Read from $ORACLES_VISUAL_MODE on every call so
|
| 80 |
+
it stays accurate across reloads.
|
| 81 |
+
|
| 82 |
+
- ``lean`` (default, HF Space): skip heavy decorative PNGs — parallax
|
| 83 |
+
banner, grimoire parchment, the four phase backdrops, the scene
|
| 84 |
+
landscapes, the wizard-desk backdrop, the open-book illustration,
|
| 85 |
+
and the pipeline-demo card backdrop. Total saving: ~2-3 MB per
|
| 86 |
+
cold load on HF Space's slow egress bandwidth.
|
| 87 |
+
- ``full``: enable everything. Use locally where bandwidth is fast.
|
| 88 |
+
|
| 89 |
+
To run locally in full mode: ``ORACLES_VISUAL_MODE=full ./run.sh``
|
| 90 |
+
or pass ``--full`` to ``run.sh`` (which sets the env var).
|
| 91 |
+
"""
|
| 92 |
+
return os.environ.get("ORACLES_VISUAL_MODE", "lean").strip().lower() == "full"
|
| 93 |
+
|
| 94 |
+
|
| 95 |
# ---------------------------------------------------------------------------
|
| 96 |
# Pixel-art book frame: leather binding (via CSS border-image 9-slice), a
|
| 97 |
# vertical spine with raised bands and stitching, and a red ribbon bookmark.
|
|
|
|
| 315 |
texture as a background-image on .grimoire-page, if the PNG exists.
|
| 316 |
Returns empty string otherwise (so the CSS-only gradients still apply).
|
| 317 |
|
| 318 |
+
Skipped entirely in lean mode (default) — the texture is ~70 KB
|
| 319 |
+
base64-inlined into the initial CSS, which on HF Space's slow egress
|
| 320 |
+
adds noticeable cold-load time. Set ORACLES_VISUAL_MODE=full to enable.
|
|
|
|
| 321 |
"""
|
| 322 |
+
if not _full_visual_mode():
|
| 323 |
+
return ""
|
| 324 |
if not _GRIMOIRE_TEXTURE_PNG.exists():
|
| 325 |
return ""
|
| 326 |
try:
|
|
|
|
| 518 |
for o in state.oracles:
|
| 519 |
text = (o.text or "").strip() or blank_label
|
| 520 |
items.append(f"<li><em>{_md_safe(text)}</em></li>")
|
| 521 |
+
# Lean mode (default for HF Space): skip the open-book illustration —
|
| 522 |
+
# the PNG was ~200-300 KB. The heading + numbered list carry the
|
| 523 |
+
# meaning. Full mode restores the illustration above the list.
|
| 524 |
+
if _full_visual_mode():
|
| 525 |
+
book_uri = _sprite_data_uri_app("open_book_spread")
|
| 526 |
+
alt_text = _t("alt_sealed_grimoire", lang)
|
| 527 |
+
book_img = (
|
| 528 |
+
f"<img class='grimoire-summary-book' src='{book_uri}' "
|
| 529 |
+
f"alt='{_md_safe(alt_text)}'/>"
|
| 530 |
+
if book_uri else ""
|
| 531 |
+
)
|
| 532 |
+
else:
|
| 533 |
+
book_img = ""
|
| 534 |
header = _md_safe(_t("summary_five_sealed", lang))
|
| 535 |
return (
|
| 536 |
"<div class='grimoire-summary'>"
|
|
|
|
| 569 |
# Pixel-art sprites + backdrop pre-loaded as data URIs. The
|
| 570 |
# `_sprite_data_uri_app` helper caches per name, so reading the same
|
| 571 |
# sprite twice in this function only hits disk once.
|
| 572 |
+
# Lean mode (default for HF Space): skip the demo card painted
|
| 573 |
+
# backdrop (~200-400 KB). Panels still have CSS borders + shading.
|
| 574 |
+
# Full mode restores the painted background.
|
| 575 |
+
if _full_visual_mode():
|
| 576 |
+
bg = _sprite_data_uri_app("demo_card_backdrop")
|
| 577 |
+
bg_style = f"background-image:url('{bg}');" if bg else ""
|
| 578 |
+
else:
|
| 579 |
+
bg_style = ""
|
| 580 |
tag_inscribes = _t("demo_tag_inscribes", lang)
|
| 581 |
tag_meets = _t("demo_tag_meets", lang)
|
| 582 |
tag_somehow = _t("demo_tag_somehow", lang)
|
|
|
|
| 720 |
_sprite_data_uri_app(f"hero_{theme_key_for_sprites}")
|
| 721 |
or _sprite_data_uri_app("hero")
|
| 722 |
)
|
| 723 |
+
# Lean mode (default for HF Space): skip the wizard-desk backdrop —
|
| 724 |
+
# the PNG is ~200-400 KB. Full mode restores it as a fade-behind
|
| 725 |
+
# layer for the mentor/apprentice figures.
|
| 726 |
+
desk_uri = _sprite_data_uri_app("wizard_desk_scene") if _full_visual_mode() else ""
|
| 727 |
if not wizard_uri or not hero_uri:
|
| 728 |
fallback = (
|
| 729 |
"<div class='oracle-inscribe-figs' style='text-align:center;"
|
|
|
|
| 846 |
is_compact = mode in ("trial", "epilogue", "send_off")
|
| 847 |
extra_cls = " oracle-banner-compact" if is_compact else ""
|
| 848 |
|
| 849 |
+
# Lean mode (default for HF Space): use a CSS gradient instead of the
|
| 850 |
+
# ~455 KB parallax PNG. Full mode loads the PNG via Gradio's file
|
| 851 |
+
# route so the browser caches it after the first request.
|
| 852 |
+
if _full_visual_mode() and _PARALLAX_PNG.exists():
|
| 853 |
+
src = f"/gradio_api/file={_PARALLAX_PNG.as_posix()}"
|
| 854 |
+
result = (
|
| 855 |
+
f"<div class='oracle-banner{extra_cls}'>"
|
| 856 |
+
f"<img src='{src}' alt='banner'/>"
|
| 857 |
+
"<div class='oracle-banner-overlay'>"
|
| 858 |
+
f"<div class='oracle-banner-title'>{title}</div>"
|
| 859 |
+
f"<div class='oracle-banner-sub'>{subtitle}</div>"
|
| 860 |
+
"</div></div>"
|
| 861 |
+
)
|
| 862 |
+
else:
|
| 863 |
+
result = (
|
| 864 |
+
f"<div class='oracle-banner{extra_cls}' style='background:"
|
| 865 |
+
"linear-gradient(180deg,var(--w-panel) 0%, var(--w-night) 100%);'>"
|
| 866 |
+
"<div class='oracle-banner-overlay'>"
|
| 867 |
+
f"<div class='oracle-banner-title'>{title}</div>"
|
| 868 |
+
f"<div class='oracle-banner-sub'>{subtitle}</div>"
|
| 869 |
+
"</div></div>"
|
| 870 |
+
)
|
| 871 |
_BANNER_HTML_CACHE[cache_key] = result
|
| 872 |
return result
|
| 873 |
|
|
|
|
| 948 |
|
| 949 |
|
| 950 |
def _phase_backdrop_styles_html() -> str:
|
| 951 |
+
"""One-time ``<style>`` block (built at app startup) that wires the
|
| 952 |
+
per-phase pixel-art ambient textures onto the phase Group wrappers via
|
| 953 |
+
their ``elem_id`` attributes. Returns an empty string if any expected
|
| 954 |
+
texture is missing from disk OR if visual mode is lean.
|
| 955 |
+
|
| 956 |
+
Mapping:
|
| 957 |
+
#oracle-inscribe-grp ← grimoire_cover_texture
|
| 958 |
+
#oracle-send-off-grp ← stormy_plain_texture
|
| 959 |
+
#oracle-trial-grp ← night_sky_texture
|
| 960 |
+
#oracle-epilogue-grp ← forest_dusk_texture
|
| 961 |
"""
|
| 962 |
+
if not _full_visual_mode():
|
| 963 |
+
return ""
|
| 964 |
+
mapping = {
|
| 965 |
+
"oracle-inscribe-grp": "grimoire_cover_texture",
|
| 966 |
+
"oracle-send-off-grp": "stormy_plain_texture",
|
| 967 |
+
"oracle-trial-grp": "night_sky_texture",
|
| 968 |
+
"oracle-epilogue-grp": "forest_dusk_texture",
|
| 969 |
+
}
|
| 970 |
+
rules = []
|
| 971 |
+
for elem_id, sprite_name in mapping.items():
|
| 972 |
+
uri = _sprite_data_uri_app(sprite_name)
|
| 973 |
+
if not uri:
|
| 974 |
+
continue
|
| 975 |
+
rules.append(f"#{elem_id} {{ background-image: url('{uri}') !important; }}")
|
| 976 |
+
if not rules:
|
| 977 |
+
return ""
|
| 978 |
+
return "<style data-phase-backdrops>\n" + "\n".join(rules) + "\n</style>"
|
| 979 |
|
| 980 |
|
| 981 |
def _theme_style_overrides_html(state: Optional[GameState] = None) -> str:
|
|
|
|
| 3451 |
return landscape
|
| 3452 |
return _sprite_data_uri_app(category) or ""
|
| 3453 |
|
| 3454 |
+
# Lean mode (default for HF Space): skip the env (landscape) backdrop
|
| 3455 |
+
# — each scene_<theme>_landscape PNG is ~200-500 KB and slow over HF's
|
| 3456 |
+
# egress. The hero + obstacle sprites still load and the panel uses a
|
| 3457 |
+
# CSS gradient sky. Full mode restores the landscape.
|
| 3458 |
+
env_uri = _theme_pick(env_name, is_env=True) if _full_visual_mode() else ""
|
| 3459 |
hero_uri = _theme_pick("hero")
|
| 3460 |
ob_uri = _theme_pick(ob_name) if ob_name else ""
|
| 3461 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3462 |
dragon_attr = ' data-dragon="true"' if is_dragon else ""
|
| 3463 |
hero_img = (
|
| 3464 |
f"<img class='scene-hero' src='{hero_uri}' alt='hero'/>"
|
run.sh
CHANGED
|
@@ -19,10 +19,20 @@
|
|
| 19 |
# under DIR (default: ./traces/). Drop the file into
|
| 20 |
# an HF dataset repo for the Sharing-is-Caring badge.
|
| 21 |
# --self-test Pass-through to app.py for the scripted walkthrough.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
#
|
| 23 |
# Env vars:
|
| 24 |
# ORACLES_LLM_MODEL=llm request base model
|
| 25 |
# ORACLES_LLM_MODEL=oracle-wizard-lora (default) request fine-tune
|
|
|
|
|
|
|
| 26 |
# KEEP_LLM_WARM=1 keep Modal LLM running
|
| 27 |
# ORACLES_GGUF_PATH=/path/to/model.gguf used in --local-llama mode
|
| 28 |
# ORACLES_LOCAL_LLAMA_PORT=8080 (default) llama-server port
|
|
@@ -53,6 +63,8 @@ for arg in "$@"; do
|
|
| 53 |
--local-llama) USE_LOCAL_LLAMA="1" ;;
|
| 54 |
--save-trace) SAVE_TRACE_DIR="./traces" ;;
|
| 55 |
--save-trace=*) SAVE_TRACE_DIR="${arg#--save-trace=}" ;;
|
|
|
|
|
|
|
| 56 |
*) APP_ARGS+=("$arg") ;;
|
| 57 |
esac
|
| 58 |
done
|
|
@@ -63,6 +75,15 @@ if [ -n "$SAVE_TRACE_DIR" ]; then
|
|
| 63 |
echo "[run.sh] --save-trace: appending LLM exchanges to $SAVE_TRACE_DIR/oracles-trace-<session>.jsonl"
|
| 64 |
fi
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
# -----------------------------------------------------------------------------
|
| 67 |
# Load .env.local — look in both the project root and oracles_app/ so
|
| 68 |
# shared credentials are picked up.
|
|
|
|
| 19 |
# under DIR (default: ./traces/). Drop the file into
|
| 20 |
# an HF dataset repo for the Sharing-is-Caring badge.
|
| 21 |
# --self-test Pass-through to app.py for the scripted walkthrough.
|
| 22 |
+
# --full Enable ALL decorative PNGs (parallax banner,
|
| 23 |
+
# parchment, phase backdrops, scene landscapes,
|
| 24 |
+
# wizard-desk, open-book, demo-card backdrop).
|
| 25 |
+
# Recommended for local runs on fast connections.
|
| 26 |
+
# --lean (default) Skip the heavy decorative PNGs. Used by
|
| 27 |
+
# the HF Space deployment because its egress
|
| 28 |
+
# bandwidth (~15 KB/s) makes the full set add
|
| 29 |
+
# multi-megabytes to every cold load.
|
| 30 |
#
|
| 31 |
# Env vars:
|
| 32 |
# ORACLES_LLM_MODEL=llm request base model
|
| 33 |
# ORACLES_LLM_MODEL=oracle-wizard-lora (default) request fine-tune
|
| 34 |
+
# ORACLES_VISUAL_MODE=full same as --full
|
| 35 |
+
# ORACLES_VISUAL_MODE=lean (default) same as --lean
|
| 36 |
# KEEP_LLM_WARM=1 keep Modal LLM running
|
| 37 |
# ORACLES_GGUF_PATH=/path/to/model.gguf used in --local-llama mode
|
| 38 |
# ORACLES_LOCAL_LLAMA_PORT=8080 (default) llama-server port
|
|
|
|
| 63 |
--local-llama) USE_LOCAL_LLAMA="1" ;;
|
| 64 |
--save-trace) SAVE_TRACE_DIR="./traces" ;;
|
| 65 |
--save-trace=*) SAVE_TRACE_DIR="${arg#--save-trace=}" ;;
|
| 66 |
+
--full) export ORACLES_VISUAL_MODE="full" ;;
|
| 67 |
+
--lean) export ORACLES_VISUAL_MODE="lean" ;;
|
| 68 |
*) APP_ARGS+=("$arg") ;;
|
| 69 |
esac
|
| 70 |
done
|
|
|
|
| 75 |
echo "[run.sh] --save-trace: appending LLM exchanges to $SAVE_TRACE_DIR/oracles-trace-<session>.jsonl"
|
| 76 |
fi
|
| 77 |
|
| 78 |
+
# Visual-mode banner. The app defaults to lean; --full overrides for local
|
| 79 |
+
# bandwidth-rich runs that want the parallax banner, parchment texture,
|
| 80 |
+
# phase backdrops, scene landscapes, etc.
|
| 81 |
+
if [ "${ORACLES_VISUAL_MODE:-lean}" = "full" ]; then
|
| 82 |
+
echo "[run.sh] --full: ORACLES_VISUAL_MODE=full (all PNGs / textures / backdrops enabled)"
|
| 83 |
+
else
|
| 84 |
+
echo "[run.sh] lean mode (default) — pass --full to enable all visuals"
|
| 85 |
+
fi
|
| 86 |
+
|
| 87 |
# -----------------------------------------------------------------------------
|
| 88 |
# Load .env.local — look in both the project root and oracles_app/ so
|
| 89 |
# shared credentials are picked up.
|