Aryanshh commited on
Commit
51cbaeb
·
1 Parent(s): eaea692

docs: Rewrite and finalize project README and fix ESG/production error feedbacks

Browse files
Files changed (3) hide show
  1. README.md +31 -15
  2. dashboard/app.js +5 -4
  3. netzero_nav/env.py +7 -1
README.md CHANGED
@@ -7,24 +7,40 @@ sdk: docker
7
  pinned: false
8
  ---
9
 
10
- # NetZero Nav (by Aryanshh)
11
 
12
  **Autonomous RL logistics agent navigating global disruptions with a Net-Zero carbon mandate.**
13
 
14
- **NetZero Nav** is an AI agentic environment where an autonomous logistics agent must navigate global supply chain disruptions while adhering to strict "Net Zero" carbon mandates.
 
 
 
15
 
16
  ## The Challenge
17
  Every logistical decision involves a strategic trade-off:
18
- - **Sea Freight**: Ultra-low carbon, low cost, but very slow (10+ days).
19
- - **Air Freight**: High speed, but massive CO2 emissions and 5x the cost.
20
- - **Rail/Road**: Hybrid options for balanced regional resilience.
21
-
22
- ## Core Tasks
23
- - **Task 1: The Sustainable Baseline**: Fulfill standard orders while selecting the most carbon-optimal routes.
24
- - **Task 2: Disruption Management**: A "Port Strike" or "Suez Blockade" occurs. The agent must solve the bottleneck without blowing its carbon quota.
25
- - **Task 3: The NetZero Crisis**: Manage a week of extreme chaos while minimizing the total CO2 footprint toward a zero-impact goal.
26
-
27
- ## Tech Specs
28
- - **Engine**: Custom Python RL Simulator.
29
- - **Interface**: FastAPI (OpenEnv Spec).
30
- - **Evaluation**: Programmatic ESG grading (Time/Cost/CO2).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  pinned: false
8
  ---
9
 
10
+ # NetZero Nav
11
 
12
  **Autonomous RL logistics agent navigating global disruptions with a Net-Zero carbon mandate.**
13
 
14
+ ## Overview
15
+ **NetZero Nav** is an AI agentic simulation environment built for logistics optimization. In modern supply chains, decision-making is a multi-objective problem: balancing financial costs, delivery speed, and environmental sustainability. This project simulates a supply chain command center where an agent (or human operator) manages electronic product manufacturing while adhering strictly to "Net-Zero" carbon quotas.
16
+
17
+ This interface serves as the visual playground and telemetry dashboard representing what an AI Reinforcement Learning (RL) agent interacts with behind the scenes via a custom FastAPI `/step` loop.
18
 
19
  ## The Challenge
20
  Every logistical decision involves a strategic trade-off:
21
+ - **Sea Freight ($10, 10 Days, 0.1kg CO2)**: Ultra-low carbon footprint and cheap, but extremely slow.
22
+ - **Air Freight ($50, 2 Days, 2.0kg CO2)**: High speed fulfillment, but massive CO2 emissions and 5x the cost.
23
+ - **Rail Freight ($25, 5 Days, 0.5kg CO2)**: The hybrid option for balanced regional resilience.
24
+
25
+ Operators must balance raw inventory against pending order fulfillment schedules to prevent bleeding capital, while ensuring they do not breach the 1,000kg Carbon Footprint limit.
26
+
27
+ ## Core Features
28
+ 1. **Real-time Telemetry Dashboard**: A high-fidelity, reactive command console providing live readouts on Capital Balance, Carbon Footprint, and Raw Inventory limitations.
29
+ 2. **Dynamic Order Routing & Cart Aggregation**: The environment automatically merges overlapping delivery constraints and cleanly manages multi-batch shipments in the `Your Orders` logistics stream.
30
+ 3. **Disruption Management ("The Suez Jam")**: Triggering real-world crises blocks optimal ocean routes (e.g., SEA mode) for 7 simulation days. The agent must rapidly recompute air and rail alternatives without bankrupting the system or violating carbon quotas.
31
+ 4. **ESG Strategic Offsetting**: Allows excess capital to be dynamically diverted into Carbon Offset programs, driving the footprint back down toward sustainable parameters.
32
+ 5. **Headless Python RL Engine**: Driven entirely by a custom `AtlasEcoEnv` state machine with a strict Pydantic ruleset, validating constraints prior to DOM interaction.
33
+
34
+ ## Tech Stack
35
+ - **Simulation Engine**: Custom Python RL Simulator (`env.py`)
36
+ - **Backend Infrastructure**: FastAPI (Handling continuous Step/Reset states)
37
+ - **Frontend Command Center**: Vanilla HTML/CSS/JS (Glassmorphic Enterprise aesthetic)
38
+ - **Deployment**: Fully dockerized & hosted on Hugging Face Spaces
39
+
40
+ ## Getting Started
41
+ To run locally:
42
+ ```bash
43
+ pip install fastapi uvicorn pydantic
44
+ uvicorn netzero_nav.server:app --host 0.0.0.0 --port 7860
45
+ ```
46
+ Navigate to `http://localhost:7860/` to launch the Command Console.
dashboard/app.js CHANGED
@@ -153,7 +153,6 @@ window.execute = async function(type, event, shipment_id = null) {
153
  if (type === 'order_parts') {
154
  const part = document.getElementById('part-select').value;
155
  const qty = parseInt(document.getElementById('qty-input').value) || 1;
156
- spawnFeedback(`+${qty} ${part} ordered`, event.clientX, event.clientY);
157
  actionObj.part_type = part;
158
  actionObj.mode = document.getElementById('mode-select').value;
159
  actionObj.quantity = qty;
@@ -161,11 +160,9 @@ window.execute = async function(type, event, shipment_id = null) {
161
  actionObj.product = document.getElementById('product-select').value;
162
  const qty = parseInt(document.getElementById('produce-qty-input').value) || 1;
163
  actionObj.quantity = qty;
164
- spawnFeedback(`Initiated x${qty} run`, event.clientX, event.clientY);
165
  } else if (type === 'offset') {
166
  const amt = parseFloat(document.getElementById('offset-qty-input').value) || 10;
167
  actionObj.offset_amount = amt;
168
- spawnFeedback(`Purchased ${amt} offsets`, event.clientX, event.clientY);
169
  } else if (type === 'skip') {
170
  actionObj.action_type = 'skip';
171
  } else if (type === 'cancel') {
@@ -183,8 +180,12 @@ window.execute = async function(type, event, shipment_id = null) {
183
 
184
  if (result.info && result.info.error) {
185
  log(`ERROR: ${result.info.error}`, 'error');
 
186
  } else {
187
- if (type === 'cancel') log(`SUCCESS: Canceled Shipment`, 'action');
 
 
 
188
  else log(`SUCCESS: ${type === 'skip' ? 'Skipped Day' : 'Executed ' + type}`, 'action');
189
  }
190
 
 
153
  if (type === 'order_parts') {
154
  const part = document.getElementById('part-select').value;
155
  const qty = parseInt(document.getElementById('qty-input').value) || 1;
 
156
  actionObj.part_type = part;
157
  actionObj.mode = document.getElementById('mode-select').value;
158
  actionObj.quantity = qty;
 
160
  actionObj.product = document.getElementById('product-select').value;
161
  const qty = parseInt(document.getElementById('produce-qty-input').value) || 1;
162
  actionObj.quantity = qty;
 
163
  } else if (type === 'offset') {
164
  const amt = parseFloat(document.getElementById('offset-qty-input').value) || 10;
165
  actionObj.offset_amount = amt;
 
166
  } else if (type === 'skip') {
167
  actionObj.action_type = 'skip';
168
  } else if (type === 'cancel') {
 
180
 
181
  if (result.info && result.info.error) {
182
  log(`ERROR: ${result.info.error}`, 'error');
183
+ spawnFeedback(`❌ ${result.info.error}`, event.clientX, event.clientY);
184
  } else {
185
+ if (type === 'order_parts') spawnFeedback(`+${actionObj.quantity} ordered`, event.clientX, event.clientY);
186
+ else if (type === 'produce') spawnFeedback(`Initiated x${actionObj.quantity} run`, event.clientX, event.clientY);
187
+ else if (type === 'offset') spawnFeedback(`Purchased ${actionObj.offset_amount} offsets`, event.clientX, event.clientY);
188
+ else if (type === 'cancel') log(`SUCCESS: Canceled Shipment`, 'action');
189
  else log(`SUCCESS: ${type === 'skip' ? 'Skipped Day' : 'Executed ' + type}`, 'action');
190
  }
191
 
netzero_nav/env.py CHANGED
@@ -187,12 +187,18 @@ class AtlasEcoEnv:
187
 
188
  def _handle_offset(self, action: Action, info: dict) -> float:
189
  if not action.offset_amount: return -5.0
 
 
 
 
190
  cost = action.offset_amount * 2.0
191
  if self.cash_balance >= cost:
192
  self.cash_balance -= cost
193
  self.carbon_total = max(0.0, self.carbon_total - action.offset_amount)
194
  return 5.0
195
- return -10.0
 
 
196
 
197
  def _handle_reroute(self, action: Action, info: dict) -> float:
198
  return 0.0
 
187
 
188
  def _handle_offset(self, action: Action, info: dict) -> float:
189
  if not action.offset_amount: return -5.0
190
+ if self.carbon_total <= 0:
191
+ info["error"] = "No carbon footprint to offset"
192
+ return -5.0
193
+
194
  cost = action.offset_amount * 2.0
195
  if self.cash_balance >= cost:
196
  self.cash_balance -= cost
197
  self.carbon_total = max(0.0, self.carbon_total - action.offset_amount)
198
  return 5.0
199
+ else:
200
+ info["error"] = "Insufficient funds for offset"
201
+ return -10.0
202
 
203
  def _handle_reroute(self, action: Action, info: dict) -> float:
204
  return 0.0