Skip to navigation

Demand Forecasting Solution

View as Markdown

Forecast how much demand each item will see so the business can plan inventory, replenishment, and procurement. This example predicts a numeric total for each item over the next 30 days, so the task is a regression forecast rather than a ranking or a yes or no classification. Kumo Engine learns the forecast from historical sales and from the item and category structure of the graph.

Data and relationships

The example assumes a prepared Kumo Engine graph, a matching snapshot, and these tables:

TableRequired columnsPurpose
salesorder_id, item_id, group_id, timestamp, quantityRecords each sale, the item and category it belongs to, when it happened, and how many units it moved.
itemsitem_id as the primary keyDefines the items to forecast.
groupsgroup_id as the primary keyDefines the item categories for aggregated forecasts.

Connect sales.item_id to items.item_id and sales.group_id to groups.group_id. Mark sales.timestamp as the time column and sales.order_id as the primary key of the sales table. Each predictive query below aggregates the sales table over a future window measured from the prediction time.

Forecast item demand

This query asks Kumo Engine to forecast the total units sold for each item during the 30 days after the prediction time. The 0 and 30 offsets define that window, SUM(sales.quantity, ...) totals the units, and FOR EACH items.item_id produces one forecast per item.

from kumo.engine import PredictiveQuery
query_text = (
"PREDICT SUM(sales.quantity, 0, 30, days) "
"FOR EACH items.item_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type()) # regression

To forecast how many separate orders each item will see instead of the unit total, count sales rows over the same window. COUNT(sales.*, ...) counts qualifying sales, which is useful when order frequency matters more than the units per order.

query_text = (
"PREDICT COUNT(sales.*, 0, 30, days) "
"FOR EACH items.item_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type()) # regression

Forecast category demand

To plan at the category level, change the entity to groups.group_id. This query totals the units sold across every item in a category during the next 30 days, which smooths the noise of individual items and supports category buying decisions.

query_text = (
"PREDICT SUM(sales.quantity, 0, 30, days) "
"FOR EACH groups.group_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type()) # regression

Procurement often needs lead time, so the window can start in the future rather than at the prediction time. Here the offsets 35 and 42 select the week that runs from 35 to 42 days ahead, roughly the sixth week out, for each category.

query_text = (
"PREDICT SUM(sales.quantity, 35, 42, days) "
"FOR EACH groups.group_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type()) # regression

Reading the forecast

Each of these queries is a regression task, so a trained model returns one numeric value for every entity in the prediction population: the forecast total of units or orders for that item or category over the requested window. A forecast of zero means the model expects no demand in the window, and every forecast is an estimate from past behavior, not a guarantee of future sales.

Use the per item forecasts to set reorder points and safety stock, the order count forecasts to size fulfillment and staffing, and the category forecasts for aggregate procurement and budgeting. The future window horizon lets a planner order ahead of the demand it covers. Refresh the forecast as new sales arrive so each decision uses the latest history.