StockSense AI: The Open-Source Retail Analytics Assistant That Computes First, Explains Later

StockSense AI computes evidence with deterministic Python and uses an optional local model only to explain it, giving small retailers an auditable analytics tool.
StockSense AI is an open-source retail analytics MVP built on a compute-first, explain-later architecture: deterministic Python code handles all metric calculations, while an optional local Gemma model only interprets the evidence. It distinguishes answers from core analytics, the Gemma model, or a labeled fallback, and shows supporting metrics and inventory evidence. The AI path is fully optional via Ollama—the dashboard keeps working when the model is offline. The project is an MVP foundation, not a finished SaaS.
When a Chatbot Can't Count Inventory
At closing time, a shop owner faces a spreadsheet hundreds of rows deep: sales records are complete, but inventory status sits somewhere between "probably fine" and "should have restocked yesterday." Dashboards can show totals, but they can't explain why a particular product ranks first, whether the profit numbers are trustworthy, or what information is still missing.
This is exactly the question StockSense AI tries to answer: can small retailers get useful answers from sales and inventory data without handing arithmetic over to a chatbot?
Developer sleepyaishik69 open-sourced this retail analytics MVP on GitHub (repository). Its core idea: a traditional analytics backend generates the evidence, and an optional local language model only explains the evidence. If the model is unavailable, the core dashboard keeps working as usual.

Design Principle: Compute First, Explain Later
Natural-language answers can sound beautiful yet be completely wrong. StockSense keeps business arithmetic firmly locked inside deterministic Python code. Based on the selected workspace, store, and date range, the backend computes totals, comparisons, product rankings, and inventory signals. Questions like "Which product sold the most?" or "What is net sales?" are answered directly from deterministic facts.
For broader questions, StockSense builds a bounded, structured analytics context that includes the current period compared with an equal-length prior period: sales and profit trends, product and category rankings, unit changes, inventory signals, basket patterns, and known data gaps. If a local Ollama and the configured Gemma model are available, the model writes an explanation grounded in this context. The model has no SQL tool access and cannot modify inventory or place orders.
The interface labels whether an answer comes from core analytics, the Gemma model, or a core analytics fallback, and shows the date range along with supporting metrics, products, and inventory evidence. When the selected period has no relevant data, the app says so explicitly instead of inventing a bestseller.
This separation is critical: the model can help interpret results, but it shouldn't quietly become the source of those results. Early versions had awkward moments—a user asked "Which product sold the most?" and the answer said it couldn't tell, even though the evidence panel clearly showed total sales; asking "How do I sell more?" returned broad marketing advice with no connection to products or data.
Deterministic computation refers to a process where the same set of inputs produces exactly the same output every time, no matter when or how many times it runs. StockSense uses Python's Decimal type rather than floats for monetary calculations precisely because binary floating point can't represent decimal fractions like 0.1 exactly; after accumulating hundreds of sales, this produces cent-level drift. A deterministic backend also brings reproducibility: when a user questions a net sales figure, it can be traced record by record back to the original imported rows, whereas the generation process of a language model has no such auditability. This is the fundamental reason for separating arithmetic from explanation—the model's natural-language output itself cannot be verified, but the factual context fed to the model can be.
What the App Currently Includes
Workspaces Start Empty
A new registration creates a workspace and a first store, but preloads no products or sales data. Products, stores, sales, and imports are all workspace-scoped, and the API applies the authenticated workspace to queries. This means demo datasets don't masquerade as a user's real business data—the included CSV is just an explicit synthetic test fixture that developers can import manually when exploring the product.
Import Existing Sales Data Instead of Re-entering It
The import flow accepts CSV and Excel files. The preview detects common column aliases, shows samples, and suggests mappings from source columns to StockSense fields—records are only written after the user confirms.
Date, quantity, and unit price are required; transaction ID, SKU, product name, category, discount, tax, unit cost, and return flag are optional. The backend validates dates and numbers, rejects non-positive quantities and duplicate rows, and can import only the valid rows while logging rejected rows and their reasons into import history. When a new SKU is encountered, the import flow can auto-create the product record. This makes data quality issues visible: a partially successful import isn't quietly treated as a perfect one.
Metrics Have Explicit Definitions
The analytics code uses Python Decimal values, with monetary amounts rounded to the cent. Core definitions include:
- Net sales = gross sales − discounts − refunds; tax is stored but excluded from net sales
- Gross profit = net sales − cost of goods sold, returned only when every relevant sales record has a unit cost
- Gross margin = gross profit ÷ net sales, unavailable when costs are incomplete or net sales is zero
- Transaction count counts deduplicated transaction IDs within the store scope
- Average order value = net sales ÷ transaction count
- Inventory value uses current product costs and current on-hand quantities—a present-day estimate, not a historical valuation
These rules prevent the dashboard from showing "0" where the honest answer is "unknown." Missing cost data is especially critical: a product's current catalog cost can't retroactively prove what a sales record actually cost at the time.
Sales and Product Analytics
The overview includes a snapshot of the selected period compared with an equal-length prior period, tracks sales and profit trends at weekly or monthly granularity, ranks products by units, sales, and gross profit, compares period-over-period unit changes, and groups by category.
The dashboard is split into practical views—Overview, Sales Analytics, Products, Inventory, Finance, Marketing, Ask StockSense, Reports, Imports, and Settings—letting shop owners drill from a metric down to the records and operational details behind it. Reports can be exported as CSV. The goal isn't to drown a small business in charts, but to let someone answer everyday questions, see the assumptions clearly, and get back to running the shop.
Inventory as a Series of Movements
StockSense uses an append-only inventory movement ledger that records opening counts, physical counts, receipts, damage, and corrections. Each record contains the product, store, workspace, movement type, quantity change, resulting quantity, notes, actor, and timestamp. Editing a product's stock also generates a movement record. Sales imports don't silently overwrite today's inventory.
This is a deliberate shift away from treating inventory as a mutable integer. Movement history gives operators a traceable trail when counts change. However, the ledger only records movements after the user starts entering data—it can't reconstruct inventory history that was never captured.
The daily action center in the overview flags unknown inventory, low-stock or stockout risks, suggested replenishments, and missing product costs. Replenishment estimates use the selected period's average daily units, lead time, and a configured reorder threshold. These are review prompts: they don't model seasonality, confirmed purchase orders, supplier pack sizes, or demand uncertainty, and they will never auto-generate purchase orders.
An append-only ledger is a data modeling approach where records are only added—never modified or deleted—and the current state is derived by accumulating all historical records. It contrasts sharply with directly updating a stock_quantity field. The advantage of the ledger pattern is traceability—when physical counts don't match system numbers, you can walk through every receipt, damage, and correction to locate the source of the discrepancy. The cost is that querying current inventory requires aggregating history, usually optimized with indexes or materialized views. Accounting's double-entry bookkeeping and version control's commit history use similar approaches. StockSense explicitly acknowledges the ledger's boundary: it can only record movements after the user starts entering data, and prior inventory history cannot be reconstructed from thin air.
Budget and Basket Signals
The purchasing budget planner allocates a specified budget across supported replenishment suggestions based on currently recorded costs and inventory. It only includes products with enough information to estimate cost, and it doesn't contact suppliers or place orders.
The marketing view can surface products that appear together in the same transaction basket, using support, confidence, and lift metrics, and only works when usable transaction IDs exist. These are descriptive co-purchase patterns—they can't prove that one product causes another's sales, nor measure promotion effectiveness. Promotional lift, price elasticity, and customer segmentation are outside the current data model's capabilities.
Support, confidence, and lift are the three standard metrics in association rule mining. Let A and B be two products: support = transactions containing both A and B ÷ total transactions, measuring how common the combination is; confidence = transactions containing both A and B ÷ transactions containing A, i.e., of those who bought A, how many also bought B; lift = confidence ÷ B's overall purchase rate—greater than 1 means A and B co-occur more often than random chance. Lift is the key metric, because high confidence between popular products may simply reflect that they already sell well. All three metrics are descriptive and can't rule out confounding factors, so StockSense emphasizes they can't prove causation or measure promotion effectiveness.
Optional Local Gemma via Ollama
The AI path is optional. StockSense can call a locally running Ollama service, configured for gemma2:2b. The dashboard shows model status; model-driven insight generation has timeouts and bounded concurrency. If Ollama is offline, deterministic analytics, reports, imports, and other dashboard features remain available, and natural-language chat falls back to a labeled summary of computed facts.
This is useful for local experimentation and keeps model dependencies separate from the data pipeline. But it doesn't mean the whole app is production-hardened: running a local model still requires suitable hardware and an operator-managed service.
Ollama is a local large-model runtime that downloads and loads model weights and serves inference over an HTTP interface, listening on port 11434 by default. Unlike calling a cloud API, Ollama runs the model entirely on the developer's own machine, so data never leaves the local environment—ideal for handling sensitive business records like sales details. The tradeoff is that inference speed depends on local hardware: a roughly 2-billion-parameter model like gemma2:2b can run on a laptop without a dedicated GPU, but response latency is noticeably higher than cloud services. StockSense therefore sets timeouts and bounded concurrency to prevent a stalled model from dragging down the whole dashboard. Switching models only requires changing the OLLAMA_MODEL config and re-pulling—no application code changes needed.
Tech Stack and Architecture
- Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS, Recharts
- API: Python, FastAPI, SQLAlchemy, Pydantic
- Persistence: SQLite for local development, PostgreSQL for the Docker Compose path
- Schema changes: Alembic migrations, with both the initial schema and inventory movement migrations in the repository
- Inference: Optional Gemma via Ollama HTTP; core metrics depend on no model
The request path roughly follows: CSV/Excel import → preview → map columns → validate → confirm → workspace-scoped relational records → Python Decimal analytics and inventory signals → dashboard and CSV reports, or → bounded factual context → optional Ollama/Gemma explanation.
In SQLite mode, the API creates an empty schema on startup; PostgreSQL deployments apply the Alembic migration chain. The schema.sql in the repository is a generated SQLite snapshot, and migrations are the true source of schema evolution.
How to Run It and Known Limitations
After cloning the repository, first create a virtual environment in the backend directory, install dependencies, run alembic upgrade head, then start the API with uvicorn app.main:app --reload --port 8000. In another terminal, go into frontend and run npm install and npm run dev. Open http://localhost:3000, create a workspace, and import your own sales file or the synthetic test CSV. API docs are at http://localhost:8000/docs.
To try the optional local model, install Ollama, then run ollama pull gemma2:2b and ollama serve. The API reads OLLAMA_BASE_URL, OLLAMA_MODEL, and OLLAMA_TIMEOUT_SECONDS from configuration.
StockSense is an MVP foundation, not a finished SaaS. Important gaps listed in the README include: PostgreSQL row-level security, workspace roles, password reset, CSRF protection, rate limiting, supplier records, confirmed purchase orders and partial receipts, historical cost snapshots, seasonal demand, promotion analytics, and browser end-to-end tests are all unimplemented. Session cookies currently only support local HTTP development; real deployments need HTTPS, production-grade cookie settings, secret management, database credential protection, backups, monitoring, and security review. Financial output is operational analytics and does not constitute accounting, tax, or professional financial advice.
Writing limitations into the product story is itself an advantage. Retailers should be able to tell which numbers are observed, which are estimated, and which questions the current data can't answer.
Engineering Decisions Worth Borrowing
The most useful engineering decision was to make the data path explicit before introducing natural language. This forces developers to define net sales, returns, missing costs, transaction identity, inventory history, and the boundary between measured facts and plausible explanations.
It also changes the understanding of "AI analytics." What's impressive isn't making a model summarize a table—it's preparing the right evidence, preserving metric semantics, showing provenance, and letting the system dare to say "not enough data." For inventory, this means recording movements rather than pretending the current count explains the past; for costs, it means making gaps visible rather than filling them with guesses.
One-line Summary
StockSense AI uses deterministic Python to compute evidence and an optional local model only to explain it, giving small retailers an auditable analytics tool.
Paragraph Summary
StockSense AI is an open-source retail analytics MVP whose core claim is locking business arithmetic inside deterministic Python code, with a language model only responsible for explaining established facts based on a bounded, structured context. It clearly distinguishes three answer sources—core analytics, the Gemma model, and the core fallback—and shows supporting evidence in the interface. Metric definitions are strict: net sales excludes tax, gross profit is only returned when costs are complete, and missing data is honestly shown as unknown rather than zero. Inventory uses an append-only movement ledger recording counts, receipts, damage, and corrections, and sales imports don't silently overwrite inventory. The AI path calls gemma2:2b via Ollama, fully optional, with everything else working normally when offline. The project is positioned as an MVP foundation rather than finished SaaS, and the README openly admits missing capabilities like row-level security, workspace roles, CSRF protection, historical cost snapshots, and seasonal demand.
Related articles

JobRunner MCP Server: AI Agents Can Now Fix Failed Java Jobs
JobRunner launches an open-source MCP server enabling AI agents to view cluster status, diagnose failures, and recover Java jobs—incident response from any cloud coding environment or existing agent.

MLAI Digital Launches 9 Security Agents: MCP Server Safeguards the Full Lifecycle of Agentic AI
MLAI Digital launches Security MCP Server with nine built-in specialized security agents covering vulnerability discovery, attack simulation, prompt injection detection, API and infrastructure assessment, and accelerated remediation—embedding security validation across the full Agentic AI lifecycle from development to production.

Running Isaac Lab on H100 GPUs: Exploring Better Approaches
Exploring optimization methods for running Isaac Lab on NVIDIA H100 GPUs, including MIG configuration, mixed precision, TensorRT acceleration, and community experience to improve robotics simulation and reinforcement learning efficiency.