eventhorizon28 commited on
Commit
2968362
·
verified ·
1 Parent(s): 623e126

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +1 -1
  2. server/app.py +3 -0
  3. server/gradio_app.py +195 -0
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: Bridge Forge Environment Server
3
- emoji: 🌉
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
 
1
  ---
2
  title: Bridge Forge Environment Server
3
+ emoji: "\U0001F309"
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
server/app.py CHANGED
@@ -16,9 +16,11 @@ except Exception as e:
16
  try:
17
  from ..models import BridgeForgeAction, BridgeForgeObservation
18
  from .bridge_forge_environment import BridgeForgeEnvironment
 
19
  except (ImportError, ValueError):
20
  from models import BridgeForgeAction, BridgeForgeObservation
21
  from server.bridge_forge_environment import BridgeForgeEnvironment
 
22
 
23
  app = create_app(
24
  BridgeForgeEnvironment,
@@ -26,6 +28,7 @@ app = create_app(
26
  BridgeForgeObservation,
27
  env_name="bridge_forge",
28
  max_concurrent_envs=4,
 
29
  )
30
 
31
  STATIC_DIR = "/tmp/bridge_forge_static"
 
16
  try:
17
  from ..models import BridgeForgeAction, BridgeForgeObservation
18
  from .bridge_forge_environment import BridgeForgeEnvironment
19
+ from .gradio_app import build_bridge_forge_ui
20
  except (ImportError, ValueError):
21
  from models import BridgeForgeAction, BridgeForgeObservation
22
  from server.bridge_forge_environment import BridgeForgeEnvironment
23
+ from server.gradio_app import build_bridge_forge_ui
24
 
25
  app = create_app(
26
  BridgeForgeEnvironment,
 
28
  BridgeForgeObservation,
29
  env_name="bridge_forge",
30
  max_concurrent_envs=4,
31
+ gradio_builder=build_bridge_forge_ui,
32
  )
33
 
34
  STATIC_DIR = "/tmp/bridge_forge_static"
server/gradio_app.py ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import gradio as gr
7
+
8
+ PARAM_EXAMPLES = {
9
+ "select_type": '{"bridge_type": "warren_truss"}',
10
+ "add_node": '{"node_id": "n1", "x": 0.0, "y": 0.0}',
11
+ "add_member": '{"member_id": "m1", "node_start": "n1", "node_end": "n2", "material": "steel", "section_area": 0.01}',
12
+ "add_support": '{"node_id": "n1", "support_type": "pin"}',
13
+ "add_load": '{"node_id": "n2", "Fx": 0.0, "Fy": -50.0}',
14
+ "simulate": "{}",
15
+ "submit": "{}",
16
+ }
17
+
18
+ ACTION_TYPES = list(PARAM_EXAMPLES.keys())
19
+
20
+ SCENARIO_IDS = ["easy", "medium", "hard"]
21
+
22
+
23
+ def _format_obs(data: Dict[str, Any]) -> str:
24
+ obs = data.get("observation", {})
25
+ lines: List[str] = []
26
+
27
+ if obs.get("message"):
28
+ lines.append(f"**Message:** {obs['message']}")
29
+ if obs.get("scenario"):
30
+ lines.append(f"\n**Scenario:** {obs['scenario'][:200]}...")
31
+ if obs.get("bridge_type"):
32
+ lines.append(f"**Bridge type:** `{obs['bridge_type']}`")
33
+ if obs.get("constraints"):
34
+ lines.append(f"**Constraints:** `{obs['constraints']}`")
35
+
36
+ nodes = obs.get("nodes", [])
37
+ members = obs.get("members", [])
38
+ supports = obs.get("supports", [])
39
+ loads = obs.get("loads", [])
40
+ if nodes:
41
+ lines.append(f"\n**Nodes ({len(nodes)}):** {', '.join(n.get('node_id','?') for n in nodes)}")
42
+ if members:
43
+ lines.append(f"**Members ({len(members)}):** {', '.join(m.get('member_id','?') for m in members)}")
44
+ if supports:
45
+ lines.append(f"**Supports ({len(supports)}):** {', '.join(s.get('node_id','?')+' ('+s.get('support_type','?')+')' for s in supports)}")
46
+ if loads:
47
+ lines.append(f"**Loads ({len(loads)}):** {', '.join(l.get('node_id','?') for l in loads)}")
48
+
49
+ sim = obs.get("simulation_result")
50
+ if sim:
51
+ lines.append("\n### Simulation Results")
52
+ lines.append(f"- **Status:** `{sim.get('structural_status', '?')}`")
53
+ lines.append(f"- **Max deflection:** `{sim.get('max_deflection_mm', 0):.4f} mm`")
54
+ lines.append(f"- **Max stress ratio:** `{sim.get('max_stress_ratio', 0):.4f}`")
55
+ lines.append(f"- **Total mass:** `{sim.get('total_mass_kg', 0):.2f} kg`")
56
+ lines.append(f"- **Cost:** `{sim.get('cost_inr', 0):,.0f} INR`")
57
+ lines.append(f"- **Members:** `{sim.get('member_count', 0)}`")
58
+ if sim.get("failed_members"):
59
+ lines.append(f"- **Failed:** `{sim['failed_members']}`")
60
+
61
+ reward = data.get("reward")
62
+ done = data.get("done")
63
+ if reward is not None:
64
+ lines.append(f"\n**Reward:** `{reward}`")
65
+ if done is not None:
66
+ lines.append(f"**Done:** `{done}`")
67
+
68
+ return "\n".join(lines) if lines else "*No observation data*"
69
+
70
+
71
+ def _get_viz_url(data: Dict[str, Any]) -> Optional[str]:
72
+ sim = data.get("observation", {}).get("simulation_result")
73
+ if sim and sim.get("visualization_url"):
74
+ return sim["visualization_url"]
75
+ return None
76
+
77
+
78
+ def build_bridge_forge_ui(
79
+ web_manager: Any,
80
+ action_fields: List[Dict[str, Any]],
81
+ metadata: Any,
82
+ is_chat_env: bool,
83
+ title: str,
84
+ quick_start_md: Optional[str],
85
+ ) -> gr.Blocks:
86
+ async def reset_env(scenario_id: str):
87
+ try:
88
+ data = await web_manager.reset_environment(
89
+ {"scenario_id": scenario_id or "easy"}
90
+ )
91
+ obs_md = _format_obs(data)
92
+ return (
93
+ obs_md,
94
+ json.dumps(data, indent=2),
95
+ f"Reset with scenario: {scenario_id}",
96
+ None,
97
+ )
98
+ except Exception as e:
99
+ return ("", "", f"Error: {e}", None)
100
+
101
+ async def step_env(action_type: str, params_json: str):
102
+ if not action_type:
103
+ return ("", "", "Select an action type first.", None)
104
+ try:
105
+ params = json.loads(params_json) if params_json.strip() else {}
106
+ except json.JSONDecodeError as e:
107
+ return ("", "", f"Invalid JSON in params: {e}", None)
108
+
109
+ action_data = {"action_type": action_type, "params": params}
110
+ try:
111
+ data = await web_manager.step_environment(action_data)
112
+ obs_md = _format_obs(data)
113
+ viz_url = _get_viz_url(data)
114
+ viz_img = None
115
+ if viz_url:
116
+ import os
117
+ local_path = os.path.join("/tmp/bridge_forge_static", os.path.basename(viz_url))
118
+ if os.path.exists(local_path):
119
+ viz_img = local_path
120
+ return (
121
+ obs_md,
122
+ json.dumps(data, indent=2),
123
+ "Step complete.",
124
+ viz_img,
125
+ )
126
+ except Exception as e:
127
+ return ("", "", f"Error: {e}", None)
128
+
129
+ def update_placeholder(action_type: str):
130
+ return gr.update(value=PARAM_EXAMPLES.get(action_type, "{}"))
131
+
132
+ with gr.Blocks(title=f"BridgeForge: {title}") as demo:
133
+ gr.Markdown("## BridgeForge Playground")
134
+
135
+ with gr.Row():
136
+ with gr.Column(scale=1):
137
+ scenario_dd = gr.Dropdown(
138
+ choices=SCENARIO_IDS,
139
+ value="easy",
140
+ label="Scenario",
141
+ )
142
+ reset_btn = gr.Button("Reset", variant="secondary")
143
+
144
+ gr.Markdown("---")
145
+
146
+ action_dd = gr.Dropdown(
147
+ choices=ACTION_TYPES,
148
+ value="select_type",
149
+ label="Action Type",
150
+ )
151
+ params_box = gr.Textbox(
152
+ label="Params (JSON)",
153
+ value=PARAM_EXAMPLES["select_type"],
154
+ lines=3,
155
+ placeholder='e.g. {"bridge_type": "warren_truss"}',
156
+ )
157
+ step_btn = gr.Button("Step", variant="primary")
158
+
159
+ status_box = gr.Textbox(label="Status", interactive=False)
160
+
161
+ with gr.Column(scale=2):
162
+ obs_display = gr.Markdown(
163
+ value="Click **Reset** to start a new episode."
164
+ )
165
+ viz_image = gr.Image(
166
+ label="Bridge Visualization",
167
+ type="filepath",
168
+ interactive=False,
169
+ )
170
+ with gr.Accordion("Raw JSON", open=False):
171
+ raw_json = gr.Code(
172
+ label="Response",
173
+ language="json",
174
+ interactive=False,
175
+ )
176
+
177
+ action_dd.change(
178
+ fn=update_placeholder,
179
+ inputs=[action_dd],
180
+ outputs=[params_box],
181
+ )
182
+
183
+ reset_btn.click(
184
+ fn=reset_env,
185
+ inputs=[scenario_dd],
186
+ outputs=[obs_display, raw_json, status_box, viz_image],
187
+ )
188
+
189
+ step_btn.click(
190
+ fn=step_env,
191
+ inputs=[action_dd, params_box],
192
+ outputs=[obs_display, raw_json, status_box, viz_image],
193
+ )
194
+
195
+ return demo