Spaces:
Sleeping
Sleeping
Download models.py from RaoAditya/StoreManager: direct link, hf CLI and curl.
- Browser
- Download file 8.95 kB
-
https://huggingface.co/spaces/RaoAditya/StoreManager/resolve/main/models.py
- Command line
-
hf download hf://spaces/RaoAditya/StoreManager/models.py
-
curl -L -o models.py https://huggingface.co/spaces/RaoAditya/StoreManager/resolve/main/models.py
8.95 kB
| # Copyright (c) Meta Platforms, Inc. and affiliates. | |
| # All rights reserved. | |
| # | |
| # This source code is licensed under the BSD-style license found in the | |
| # LICENSE file in the root directory of this source tree. | |
| """ | |
| Data models for the Store Manager Environment. | |
| The Store Manager environment simulates a retail store where an LLM agent | |
| acts as the store manager, applying discounts to products to maximize profit | |
| while managing inventory and handling product expiry. | |
| """ | |
| from __future__ import annotations | |
| from typing import Dict, List, Literal, Optional | |
| from openenv.core.env_server.types import Action, Observation, State | |
| from pydantic import BaseModel, Field | |
| class ProductState(BaseModel): | |
| """State of a single product in the store inventory.""" | |
| product_id: int = Field(..., description="Unique integer identifier for the product") | |
| name: str = Field(..., description="Human-readable product name") | |
| cost_price: float = Field(..., description="Cost to the store per unit") | |
| selling_price: float = Field(..., description="Current selling price (after discount)") | |
| base_selling_price: float = Field(..., description="Original selling price before any discount") | |
| quantity: int = Field(..., description="Units currently in stock") | |
| expiry_step: int = Field( | |
| ..., description="Episode step number at which this product expires" | |
| ) | |
| base_probability: float = Field( | |
| ..., description="Base pick-probability weight before discount" | |
| ) | |
| current_discount_pct: float = Field( | |
| default=0.0, description="Active discount percentage this step (0/10/20/50)" | |
| ) | |
| effective_pick_prob: float = Field( | |
| default=0.0, | |
| description="Normalised pick probability this step after applying discount (sums to 1 across all active products)", | |
| ) | |
| is_active: bool = Field( | |
| default=True, description="False if the product is sold out or expired" | |
| ) | |
| sales_history: List[Dict] = Field( | |
| default_factory=list, | |
| description="List of {step, discount_pct, units_sold} records", | |
| ) | |
| # Zone / Shelf Placement fields | |
| zone: int = Field( | |
| default=2, description="Current shelf zone (1=premium/high-traffic, 2=standard, 3=back/low-traffic)" | |
| ) | |
| # Restocking / Procurement fields | |
| holding_cost_rate: float = Field( | |
| default=0.02, description="Holding cost per unit per step as a fraction of cost_price" | |
| ) | |
| restock_cost_per_unit: float = Field( | |
| default=0.0, description="Cost per unit when reordering (may exceed cost_price due to rush ordering)" | |
| ) | |
| restock_lead_time: int = Field( | |
| default=2, description="Number of steps until a restock order is delivered" | |
| ) | |
| pending_restock_quantity: int = Field( | |
| default=0, description="Units currently on order (not yet delivered)" | |
| ) | |
| pending_restock_arrives_at_step: Optional[int] = Field( | |
| default=None, description="Step number when the pending restock order will arrive" | |
| ) | |
| # Compounding popularity effect | |
| popularity_multiplier: float = Field( | |
| default=1.0, | |
| description=( | |
| "Cumulative pick-probability multiplier earned through repeated discounting. " | |
| "Starts at 1.0 and compounds up each time a discount action is applied: " | |
| "popularity_multiplier *= (1 + discount_pct / 100). " | |
| "Persists across steps within an episode; resets to 1.0 on reset()." | |
| ), | |
| ) | |
| # Derived signal fields (recomputed each step — do not set manually) | |
| steps_until_expiry: int = Field( | |
| default=0, | |
| description=( | |
| "Steps remaining before this product expires (expiry_step - current_step). " | |
| "Near-expiry threshold: <= 3 steps. Below-cost discounting is permitted " | |
| "when steps_until_expiry <= 3; the price floor loosens progressively." | |
| ), | |
| ) | |
| margin_per_unit: float = Field( | |
| default=0.0, | |
| description=( | |
| "Current per-unit profit margin: selling_price - cost_price. " | |
| "Positive = profitable. Zero = break-even. " | |
| "Negative = selling at a loss (only possible when steps_until_expiry <= 3)." | |
| ), | |
| ) | |
| class StoremanagerAction(Action): | |
| """Agent action: discount a product, restock inventory, or move a product to a different zone.""" | |
| action_type: Literal["discount", "restock", "place"] = Field( | |
| default="discount", | |
| description="Type of action: 'discount' to apply a price discount, 'restock' to order more inventory, 'place' to move product to a different shelf zone", | |
| ) | |
| product_id: int = Field(..., description="ID of the product to act on") | |
| discount_pct: Literal[0, 10, 20, 50] = Field( | |
| default=0, description="Discount percentage (used when action_type='discount'): 0, 10, 20, or 50" | |
| ) | |
| restock_quantity: Optional[int] = Field( | |
| default=None, description="Number of units to order (used when action_type='restock'); must be > 0" | |
| ) | |
| target_zone: Optional[Literal[1, 2, 3]] = Field( | |
| default=None, description="Destination zone (used when action_type='place'): 1=premium, 2=standard, 3=back" | |
| ) | |
| class StoremanagerObservation(Observation): | |
| """Full observation returned to the agent after each step.""" | |
| inventory: List[ProductState] = Field( | |
| default_factory=list, | |
| description="Current state of all products (including inactive ones)", | |
| ) | |
| current_step: int = Field(default=0, description="Current step number (0-indexed)") | |
| max_steps: int = Field(default=30, description="Total steps in this episode") | |
| steps_remaining: int = Field( | |
| default=30, description="Steps remaining in the episode" | |
| ) | |
| cumulative_profit: float = Field( | |
| default=0.0, description="Total profit accumulated so far in the episode" | |
| ) | |
| last_step_profit: float = Field( | |
| default=0.0, description="Net profit from the most recent step" | |
| ) | |
| last_step_units_sold: int = Field( | |
| default=0, description="Total units sold across all products in the last step" | |
| ) | |
| last_expired_products: List[str] = Field( | |
| default_factory=list, | |
| description="Names of products that expired at the end of the last step", | |
| ) | |
| num_customers_per_step: int = Field( | |
| default=10, description="Fixed number of customers simulated per step" | |
| ) | |
| task_name: str = Field( | |
| default="custom", | |
| description="Active difficulty task: easy / medium / hard / expert / custom", | |
| ) | |
| error: Optional[str] = Field( | |
| default=None, description="Error message if the last action was invalid" | |
| ) | |
| # Zone information | |
| zone_capacity: Dict[int, int] = Field( | |
| default_factory=lambda: {1: 2, 2: 4, 3: 99}, | |
| description="Maximum number of products allowed per zone", | |
| ) | |
| zone_occupancy: Dict[int, int] = Field( | |
| default_factory=lambda: {1: 0, 2: 0, 3: 0}, | |
| description="Current number of active products in each zone", | |
| ) | |
| zone_multipliers: Dict[int, float] = Field( | |
| default_factory=lambda: {1: 1.5, 2: 1.0, 3: 0.6}, | |
| description="Pick-probability multiplier per zone", | |
| ) | |
| # Step cost breakdown | |
| holding_cost_this_step: float = Field( | |
| default=0.0, description="Total holding cost charged this step across all products" | |
| ) | |
| placement_cost_this_step: float = Field( | |
| default=0.0, description="Labor cost charged this step if a zone placement was made" | |
| ) | |
| restock_cost_this_step: float = Field( | |
| default=0.0, description="Ordering cost charged this step if a restock order was placed" | |
| ) | |
| unjustified_discount_penalty: float = Field( | |
| default=0.0, | |
| description=( | |
| "Extra penalty this step for selling below cost_price when steps_until_expiry >= 4. " | |
| "Equals the total per-unit loss on unjustified below-cost units sold. " | |
| "Zero when below-cost selling is justified by near-expiry urgency." | |
| ), | |
| ) | |
| class StoremanagerState(State): | |
| """Internal state snapshot for debugging and orchestration.""" | |
| num_products: int = Field(default=8, description="Number of products in this episode") | |
| max_steps: int = Field(default=30, description="Episode length in steps") | |
| cumulative_profit: float = Field(default=0.0, description="Total episode profit so far") | |
| last_reward: float = Field(default=0.0, description="Reward from the last step") | |
| active_product_count: int = Field( | |
| default=0, description="Number of currently active (non-expired, in-stock) products" | |
| ) | |
| inventory_snapshot: List[Dict] = Field( | |
| default_factory=list, | |
| description="Serialised inventory for state introspection", | |
| ) | |