Majen's picture
Fix README config + add all project files
5eb405c
"""
RecallTrace OpenEnv β€” Hugging Face Spaces Entry Point
Space: https://huggingface.co/spaces/Majen/recalltrace-openenv
Team: Shamanth MS | P G Ayush Rai | Shreya B J
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
import gradio as gr
from recall_env.env import RecallTraceEnv
from grader.grader import grade, compute_reward
from scenario.scenario import get_scenario, list_levels
# ── helpers ──────────────────────────────────────────────────────────────────
def run_episode(level: str) -> str:
scenario = get_scenario(level)
env = RecallTraceEnv(level=level)
obs = env.reset()
lot_catalog = scenario.get("lot_catalog", {})
transformations = scenario.get("transformations", {})
contaminated_lot = scenario.get("contaminated_lot", "")
contaminated_lots = {l for l, m in lot_catalog.items() if m.get("contaminated", False)}
contaminated_lots.add(contaminated_lot)
if contaminated_lot in transformations:
contaminated_lots.add(transformations[contaminated_lot])
actions = []
for node_id in scenario["nodes"]:
actions.append({"type": "inspect_node", "node_id": node_id})
for lot_id in sorted(contaminated_lots):
actions.append({"type": "trace_lot", "lot_id": lot_id})
for node_id, node_data in scenario["nodes"].items():
for lot_id, qty in node_data["inventory"].items():
if lot_id in contaminated_lots and qty > 0:
actions.append({"type": "quarantine", "node_id": node_id, "lot_id": lot_id, "quantity": qty})
notified = set()
for node_id, node_data in scenario["nodes"].items():
if any(l in contaminated_lots for l in node_data["inventory"]):
if node_id not in notified:
actions.append({"type": "notify", "node_id": node_id})
notified.add(node_id)
actions.append({"type": "finalize"})
lines = []
lines.append(f"πŸ“‹ Recall Notice: {obs['recall_notice']}\n")
lines.append(f"πŸ—ΊοΈ Nodes: {list(scenario['nodes'].keys())}\n")
lines.append("─" * 55)
final_info = {}
env2 = RecallTraceEnv(level=level)
env2.reset()
for action in actions:
obs, reward, done, info = env2.step(action)
lines.append(f"β–Ά {action['type']:15s} β†’ reward={reward:+.2f} done={done}")
if done:
final_info = info
break
score = final_info.get("score", 0.0)
bd = final_info.get("breakdown", {})
lines.append("─" * 55)
lines.append(f"βœ… Final Score : {score:.4f}")
lines.append(f" Quarantine Score : {bd.get('quarantine_score', '-')}")
lines.append(f" Notification Score: {bd.get('notification_score', '-')}")
lines.append(f" All Stock Clear : {bd.get('all_stock_quarantined', '-')}")
lines.append(f" All Nodes Notified: {bd.get('all_affected_notified', '-')}")
return "\n".join(lines)
def run_all():
results = []
for level in list_levels():
results.append(f"{'='*55}")
results.append(f" LEVEL: {level.upper()}")
results.append(f"{'='*55}")
results.append(run_episode(level))
results.append("")
return "\n".join(results)
# ── Gradio UI ─────────────────────────────────────────────────────────────────
with gr.Blocks(title="RecallTrace OpenEnv") as demo:
gr.Markdown("""
# πŸ” RecallTrace OpenEnv
**Supply-chain recall traceability β€” OpenEnv compliant**
An AI agent traces contaminated lots through a shipment graph,
quarantines affected inventory, and notifies relevant nodes.
**Team:** Shamanth MS Β· P G Ayush Rai Β· Shreya B J
""")
with gr.Row():
level_dropdown = gr.Dropdown(
choices=["easy", "medium", "hard"],
value="easy",
label="Select Task Level"
)
run_btn = gr.Button("β–Ά Run Episode", variant="primary")
run_all_btn = gr.Button("⚑ Run All Levels")
output = gr.Textbox(label="Episode Output", lines=30, max_lines=50)
run_btn.click(fn=run_episode, inputs=level_dropdown, outputs=output)
run_all_btn.click(fn=run_all, inputs=None, outputs=output)
gr.Markdown("""
---
### Action Space
| Action | Description |
|--------|-------------|
| `inspect_node` | Reveal inventory at a node |
| `trace_lot` | Trace a lot across the network |
| `quarantine` | Isolate contaminated stock |
| `notify` | Send recall alert to a node |
| `finalize` | Submit plan β†’ get final score |
### Scoring: 0.0 β†’ 1.0
- Quarantine accuracy + notification coverage
- Penalised for unnecessary quarantines
""")
if __name__ == "__main__":
demo.launch()