Inspiration
Store managers at convenience chains lose money in three quiet ways: shelves go empty when demand spikes, perishables expire, and slow products sit unsold. Most forecasting tools stop at "you'll sell 40 units tomorrow." We wanted to answer the next question: what should I do about it right now, and how much will it earn me? That became StockCopilot, an AI copilot that turns a demand forecast into restock orders and smart promotions a manager can understand, simulate and approve.
What it does
- Forecasts demand per store × product with probabilistic bands (P50/P80/P90).
- Detects buying behaviors: demand peaks, waste risk and products bought together.
- Builds a commercial plan of up to 5 strategies per store (affinity combos, waste-rescue bundles, contextual offers) with start and end dates.
- Shows the trade-off: for every promotion, the manager sees "Si no aceptas / Si aceptas" (without vs. with accepting) and can move a discount slider to explore the curve.
- Suggests restock orders on a calendar, with suppliers ranked by on-time reliability.
- Keeps a human in the loop: the agent proposes, and nothing is sent or activated without explicit confirmation.
How we built it
Data. We generated a synthetic but causally plausible dataset of 25 convenience stores in Saltillo: daily sales, inventory, expiry, suppliers, weather, local events, paydays and ticket lines.
Model. A CatBoost quantile model, trained as a SageMaker Training Job, predicts baseline demand. It minimizes the pinball loss for each quantile $\tau \in {0.5, 0.8, 0.9}$:
$$ L_\tau(y, \hat{y}) = \max\big(\tau\,(y - \hat{y}),\ (\tau - 1)\,(y - \hat{y})\big) $$
We validated it with four fixed 14-day time-based backtests.
Decision engine. Every strategy is scored by its incremental impact, the expected outcome with it minus the baseline without it:
$$ \Delta_{\text{net}} = \big(\text{margin}{\text{treated}} - \text{margin}{\text{baseline}}\big) + \text{waste avoided} - \text{stockout cost} $$
A strategy is rejected if it breaks a minimum margin, exceeds available inventory or creates an unacceptable stockout risk. The plan's value is the portfolio impact, not a naive sum of cards that might cannibalize each other.
Agent. An orchestrator built with LangChain/LangGraph on Amazon Bedrock reads the model outputs and explains them in plain Spanish. The ML models produce the numbers; the LLM only interprets them.
Infrastructure. API Gateway + Lambda (Go), DynamoDB for current state, S3 + Athena for history, EventBridge for scheduled jobs.
Frontend. Next.js, TypeScript, Tailwind, Recharts and Leaflet (sales heatmap). A typed data layer validates every response with zod and can switch between mock, hybrid and live API modes, so the UI team never had to wait on the backend.
Challenges
- Parallel work in 24 hours. Five people were working on the model, the agent, the backend and the UI at once. We wrote an API contract first and built a deterministic mock backend with the same schemas, then switched endpoints to the real API one by one.
- Keeping math out of the client. It was tempting to compute impact in the browser. We made it a hard rule that every financial figure comes from the backend, so the numbers on screen always match the model's.
- Making AI trustworthy. An LLM that invents numbers is worse than none. We limited it to explaining engine outputs, made its chat responses a strict validated schema, and required human approval for every action.
- Simple but honest UX. Showing uncertainty bands, portfolio effects and discount curves to a store manager in under five minutes meant hiding the technical details behind "¿Cómo se calculó?" (how was this calculated?) without hiding the truth.
What we learned
- Forecasting is only half the product. The value is in turning a forecast into a decision with a price tag.
- Measuring incremental impact against a baseline changes which promotions look good.
- A typed contract plus a realistic mock is the best way to run a fast multi-team build.
- Human-in-the-loop design builds trust: managers accept AI suggestions more easily when they can see what happens if they say no.
Built With
- amazon-api-gateway
- amazon-athena
- amazon-bedrock
- amazon-dynamodb
- amazon-web-services
- aws-lambda
- catboost
- docker
- fastapi
- go
- langchain
- langgraph
- leaflet.js
- next.js
- pandas
- python
- react
- recharts
- sagemaker
- tailwind-css
- tanstack-query
- typescript
- zod
- zustand
Log in or sign up for Devpost to join the conversation.