23f2002275 commited on
Commit
889dea9
Β·
1 Parent(s): f01e48a

docs(readme): add demo links, honest fallback, create demo space

Browse files
scripts/deploy_demo_space.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Deploy FATHOM demo server to HuggingFace Streamlit Space.
2
+
3
+ Run: python scripts/deploy_demo_space.py
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ # Force UTF-8 output on Windows
12
+ if sys.platform == "win32":
13
+ import io
14
+ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
15
+
16
+ HF_TOKEN = os.getenv("HF_TOKEN")
17
+ SPACE_NAME = "Pratham-math/fathom-demo"
18
+ REPO_ROOT = Path(__file__).parent.parent
19
+
20
+
21
+ def deploy():
22
+ from huggingface_hub import HfApi
23
+
24
+ api = HfApi(token=HF_TOKEN)
25
+ me = api.whoami()
26
+ print(f"Logged in as: {me['name']}")
27
+
28
+ # 1. Create Space (Streamlit SDK)
29
+ print(f"Ensuring Space exists: {SPACE_NAME} ...")
30
+ api.create_repo(
31
+ repo_id=SPACE_NAME,
32
+ repo_type="space",
33
+ space_sdk="streamlit",
34
+ private=False,
35
+ exist_ok=True,
36
+ )
37
+ print("Space ready.")
38
+
39
+ # 2. Collect files to upload
40
+ uploads = [
41
+ (REPO_ROOT / "space_demo" / "app.py", "app.py"),
42
+ (REPO_ROOT / "space_demo" / "README.md", "README.md"),
43
+ (REPO_ROOT / "space_demo" / "requirements.txt", "requirements.txt"),
44
+ ]
45
+
46
+ print(f"Uploading {len(uploads)} files...")
47
+ for local, remote in uploads:
48
+ if local.exists():
49
+ api.upload_file(
50
+ path_or_fileobj=str(local),
51
+ path_in_repo=remote,
52
+ repo_id=SPACE_NAME,
53
+ repo_type="space",
54
+ commit_message=f"Deploy demo: {remote}",
55
+ )
56
+ print(f" OK {remote}")
57
+ else:
58
+ print(f" SKIP (missing): {local}")
59
+
60
+ hf_url = f"https://huggingface.co/spaces/{SPACE_NAME}"
61
+ space_url = f"https://Pratham-math-fathom-demo.hf.space"
62
+
63
+ print("=" * 60)
64
+ print("Deploy complete!")
65
+ print(f" HF Space : {hf_url}")
66
+ print(f" App URL : {space_url}")
67
+ print("=" * 60)
68
+
69
+ if __name__ == "__main__":
70
+ deploy()
space_demo/README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: FATHOM Demo
3
+ emoji: 🧠
4
+ colorFrom: indigo
5
+ colorTo: purple
6
+ sdk: streamlit
7
+ sdk_version: 1.39.0
8
+ app_file: app.py
9
+ pinned: true
10
+ license: apache-2.0
11
+ ---
12
+
13
+ # FATHOM Demo
14
+
15
+ Interactive UI for the FATHOM recursive-LM environment. Backed by [Pratham-math/fathom-env](https://huggingface.co/spaces/Pratham-math/fathom-env).
space_demo/app.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FATHOM Streamlit Demo β€” DEM-03.
2
+
3
+ 2-panel layout:
4
+ Left: Recursion tree visualization (D3 or plotly sunburst)
5
+ Right: W&B training curves embed (live iframe)
6
+
7
+ Run: streamlit run space_demo/app.py
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import os
13
+
14
+ import streamlit as st
15
+
16
+ st.set_page_config(
17
+ page_title="FATHOM β€” RL-Trained Recursive Language Model",
18
+ page_icon="🧠",
19
+ layout="wide",
20
+ )
21
+
22
+ st.markdown(
23
+ f"**Live env:** [Pratham-math/fathom-env]({os.environ.get('FATHOM_SPACE_URL','https://Pratham-math-fathom-env.hf.space')}) "
24
+ f"Β· **Trained model:** [Pratham-math/fathom-1.5b-grpo](https://huggingface.co/Pratham-math/fathom-1.5b-grpo) "
25
+ f"Β· **W&B:** [run sy1tqun0](https://wandb.ai/pratham-alwar05-indian-institute-of-information-technolo/huggingface/runs/sy1tqun0)"
26
+ )
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Header
30
+ # ---------------------------------------------------------------------------
31
+ st.markdown("## 🧠 FATHOM Demo")
32
+ st.markdown(
33
+ "_First RL-Trained Recursive Language Model β€” Meta Γ— PyTorch Γ— HF Hackathon_"
34
+ )
35
+ st.divider()
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Reward composition badge (DEM-03 C.4: visible-to-judges reward overview)
39
+ # ---------------------------------------------------------------------------
40
+ with st.expander("Reward composition (4 components, deterministic verifier)", expanded=True):
41
+ cb1, cb2 = st.columns([1, 2], gap="medium")
42
+ with cb1:
43
+ st.markdown("**Format gate** (multiplier)")
44
+ st.success("`<answer>...</answer>` required \u2014 if missing, soft bonus + cap applies")
45
+ st.caption("Source: `rewards/compose.py` \u2014 audited in REWARD_AUDIT.md")
46
+ with cb2:
47
+ try:
48
+ import plotly.graph_objects as go # type: ignore
49
+ labels = ["correctness", "token_budget", "recursion_efficiency"]
50
+ weights = [0.70, 0.15, 0.15]
51
+ colors = ["#2ca02c", "#1f77b4", "#ff7f0e"]
52
+ fig0 = go.Figure(go.Pie(
53
+ labels=labels, values=weights, marker=dict(colors=colors),
54
+ hole=0.4, textinfo="label+percent",
55
+ ))
56
+ fig0.update_layout(margin=dict(l=10, r=10, t=10, b=10), height=200, showlegend=False)
57
+ st.plotly_chart(fig0, use_container_width=True)
58
+ except ImportError:
59
+ st.metric("correctness", 0.70)
60
+ st.metric("token_budget", 0.15)
61
+ st.metric("recursion_efficiency", 0.15)
62
+
63
+ st.divider()
64
+
65
+ # ---------------------------------------------------------------------------
66
+ # Sidebar: controls
67
+ # ---------------------------------------------------------------------------
68
+ with st.sidebar:
69
+ st.header("Controls")
70
+ env_url = st.text_input(
71
+ "Env server URL",
72
+ value=os.environ.get("FATHOM_SPACE_URL", "https://Pratham-math-fathom-env.hf.space"),
73
+ key="env_url",
74
+ )
75
+ st.divider()
76
+ st.caption("Source: [github.com/Pratham-math/fathom](https://github.com/Pratham-math/fathom)")
77
+
78
+ @st.cache_data(ttl=3600)
79
+ def fetch_trace(url: str) -> dict:
80
+ import httpx
81
+ try:
82
+ # Provide a quick dummy trace by interacting with the env.
83
+ # Note: the real recursive model is not loaded in Streamlit,
84
+ # so this just grabs the reset observation and submits a dummy answer.
85
+ r = httpx.post(f"{url}/reset", json={"seed": 42}, timeout=10)
86
+ r.raise_for_status()
87
+ obs = r.json()
88
+ q = obs.get("question", "Question")
89
+
90
+ s = httpx.post(f"{url}/step", json={"action_type": "answer", "answer": "simulated"}, timeout=10)
91
+ s.raise_for_status()
92
+
93
+ return {
94
+ "name": f"Live init: {q[:30]}...",
95
+ "children": [
96
+ {"name": "REPL: simulated step"},
97
+ {"name": "β†’ <answer>simulated</answer>"}
98
+ ]
99
+ }
100
+ except Exception as e:
101
+ return {
102
+ "name": "[Example Trace] root: 200K doc",
103
+ "children": [
104
+ {
105
+ "name": "llm(chunk_0-50K)",
106
+ "children": [{"name": "REPL: grep β†’ 'azure'"}],
107
+ },
108
+ {"name": "REPL: count_tokens β†’ 200K"},
109
+ {"name": "β†’ <answer>azure</answer>"},
110
+ ],
111
+ }
112
+
113
+ # ---------------------------------------------------------------------------
114
+ # 2 columns
115
+ # ---------------------------------------------------------------------------
116
+ col_tree, col_wb = st.columns([1.5, 1.5], gap="medium")
117
+
118
+ # ── Column 1: Recursion tree ────────────────────────────────────────────────
119
+ with col_tree:
120
+ st.subheader("Recursion Tree")
121
+ st.caption("Sample episode trace")
122
+
123
+ sample_tree = fetch_trace(env_url)
124
+ tree_json = json.dumps(sample_tree)
125
+ d3_html = f"""
126
+ <html>
127
+ <head>
128
+ <script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
129
+ <style>
130
+ body {{ font-family: monospace; font-size: 12px; }}
131
+ .node circle {{ fill: #6366f1; stroke: #312e81; stroke-width: 1.5px; }}
132
+ .node text {{ fill: #1e1b4b; }}
133
+ .link {{ fill: none; stroke: #a5b4fc; stroke-width: 1.5px; }}
134
+ </style>
135
+ </head>
136
+ <body>
137
+ <div id="tree"></div>
138
+ <script>
139
+ const data = {tree_json};
140
+ const width = 400, height = 240;
141
+ const svg = d3.select("#tree").append("svg").attr("width", width).attr("height", height);
142
+ const g = svg.append("g").attr("transform", "translate(40,20)");
143
+ const tree = d3.tree().size([height-40, width-120]);
144
+ const root = d3.hierarchy(data);
145
+ tree(root);
146
+ g.selectAll(".link").data(root.links()).enter().append("path")
147
+ .attr("class","link")
148
+ .attr("d", d3.linkHorizontal().x(d=>d.y).y(d=>d.x));
149
+ const node = g.selectAll(".node").data(root.descendants()).enter()
150
+ .append("g").attr("class","node")
151
+ .attr("transform", d=>`translate(${{d.y}},${{d.x}})`);
152
+ node.append("circle").attr("r", 5);
153
+ node.append("text").attr("dy","0.35em").attr("x", d=>d.children?-8:8)
154
+ .attr("text-anchor", d=>d.children?"end":"start")
155
+ .text(d=>d.data.name.slice(0,35));
156
+ </script>
157
+ </body></html>
158
+ """
159
+ st.components.v1.html(d3_html, height=280)
160
+
161
+ # ── Column 3: W&B training curves ────────────────────────────────────────────
162
+ with col_wb:
163
+ st.subheader("Training Curves")
164
+ wb_url = os.environ.get("WANDB_RUN_URL", "https://wandb.ai/pratham-alwar05-indian-institute-of-information-technolo/huggingface/runs/sy1tqun0")
165
+ if wb_url:
166
+ st.components.v1.iframe(wb_url, height=260, scrolling=True)
167
+ else:
168
+ st.info("Set `WANDB_RUN_URL` env var to embed live training curves.")
169
+
170
+ st.divider()
171
+ st.caption("FATHOM Demo Space")
space_demo/requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit>=1.39,<2.0
2
+ plotly>=5.24,<6.0
3
+ httpx>=0.27,<1.0
4
+ huggingface_hub>=0.28
5
+ pandas>=2.0