YADRO bans its LLM from touching numbers and ships 10+ reports a day with no humans in the loop

Egor Shlyupikov, a senior business analyst at YADRO, and his colleague Egor Kataev spent three months building an IT analytics service in which the LLM never sees a single number in a report. Every morning, more than a dozen HTML reports for five departments go out with no human involved: a Python script computes the metrics, the model writes the conclusions, and code fills in the values. The design came out of a failure. Given a summary, the model copied numbers into the text itself, and at one point it began producing stale figures from a snapshot sitting in the Dify knowledge base. Now it receives only a few dozen key indicators and returns text with placeholders instead of values. • Trino joins a replica of Naumen.ITAM and daily snapshots in ClickHouse into a single table with history, along with data from NetBox, 1C and Jira. • If the model is unavailable, the report still goes out, just without the text conclusions. • Missing equipment prices are estimated by cohort imputation and shown separately from actual prices.

AI-processed from Habr AI; edited by Hamidun News
YADRO bans its LLM from touching numbers and ships 10+ reports a day with no humans in the loop
Source: Habr AI. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceHabr AI ↗
Editor-in-Chief
Key metric #1Trino joins a replica of Naumen.ITAM and daily snapshots in ClickHouse into a single table with history, along with data from NetBox, 1C and Jira.
Key metric #2If the model is unavailable, the report still goes out, just without the text conclusions.
Key metric #3Missing equipment prices are estimated by cohort imputation and shown separately from actual prices.

At YADRO, the team that manages the company's IT equipment fleet spent three months building a service that publishes more than a dozen analytical reports a day for five departments. No humans are involved in the process. The central engineering rule: code computes every number, and the language model writes only the text commentary and never sees a single indicator in raw form. The project was built by senior business analyst Egor Shlyupikov and his colleague Egor Kataev, and nobody on the GRID team had done production development before.

From a data-export experiment to a standalone service

It began with a task in April: assess the inventory at one of the warehouses and suggest how to clear out equipment that had been sitting unused. At the time, the company was tracking a metric called aged, the share of assets that have been in storage for more than one to two years. Shlyupikov took an export from Naumen.ITAM, stripped out sensitive data (legal entities, warehouse names) and asked a neural network to build an HTML report. It produced many cross-sections. Each was of little value on its own, but together they answered a large number of questions. His manager approved developing the idea inside the company's perimeter.

The first version ran on the low-code platform Dify. The team connected business context as a knowledge base and, because of context limits, started passing in not raw data but a summary prepared by a Python script. Even with a summary, though, the model made mistakes. It copied numbers into the text following the prompt's rules, and the same figures kept surfacing in the comments where they didn't belong. It turned out these were values from a snapshot of assets taken on the day the knowledge base was connected, not current data.

Placeholders instead of numbers

This led to a hard separation. The script prepares two datasets: a full one, from which the charts and template are built, and a compact one containing a few dozen key numbers. The model sees only the compact one. It returns observations, interpretations and red flags, and puts placeholders in place of figures. The values are filled in when the report is assembled, using the same rules as the template. Distorting a metric through the model is physically impossible.

There is a token-economy benefit too: the context holds dozens of numbers rather than arrays of rows. The model call is isolated in a separate client, so the model can be swapped without touching the pipeline. The look of the reports lives in templates. If the model is unavailable or returns an invalid response, the report still goes out on time with correct numbers, just without the text conclusions.

The team had to move off Dify because of access-control limits, because database connection parameters were stored in the pipeline settings, and because it lacked scheduling, statistics and notifications.

Trino as glue across time and across systems

As the number of sources grew, the entire data layer moved to a separate VM running Trino. The authors admit that at the time this was overkill, but they built in a safety margin. Trino solves two problems.

  • Joining across time. In Naumen.ITAM, the current state sits in a replica of the production database, while history arrives in ClickHouse as daily snapshots. A single federated query takes today's data point from the replica, and yesterday and all earlier history from ClickHouse. The limitation: the history step is one day, so statuses that changed during the day are not visible, which is why the team calculates process speed cautiously.
  • Joining across systems. Naumen.ITAM knows which team a server is assigned to, and NetBox knows its rack in the data center. A query joins the two and shows how rack costs are distributed across teams.

The report generators don't know where the data comes from, so connecting a new source doesn't require rewriting the reports. The current sources are Naumen.ITAM, ClickHouse DWH, 1C, a BI/CPM platform (number of new hires and budget), Jira (equipment requests) and NetBox.

The pipeline and protection against its own errors

The chain works like this: Airflow (which replaced cron) launches a DAG, data is read through Trino, Python computes the indicators, Dify returns the comments, a template renders the HTML, the report is saved with a timestamp, and the link to the latest version is updated. Access goes through the corporate Keycloak and a permissions check in a validator, with roles for owners, administrators, users and superusers. Through Mattermost, users can request access, refresh reports and view statistics.

The code lives in the corporate GitLab, and changes are accepted only through a merge request that is not approved by the author. Each update runs on a separate staging environment for a day, and if it fails acceptance, it rolls back automatically.

Data that didn't exist

The service exposed gaps in the data. Nobody had previously calculated the operational value of warehouse inventory, and the price field in Naumen.ITAM is not filled in for every item. The solution is cohort imputation (equipment type, model, manufacturer, year of manufacture). The average price across items that have a price is applied to the rest. The report shows actual cost and the estimate separately. If a cohort has no prices at all, it is either merged into a broader cohort or left without an estimate and flagged. Reconciliation with accounting produced comparable figures.

What you can take away

The pattern carries over to any reporting: deterministic code does the calculating, and the model receives aggregates and returns text with placeholders. This is cheaper in tokens, easier to audit and doesn't break the report when the model fails. The team's next step is a report builder in which the user describes a cross-section in words, the model generates a description of the metrics, and the Cube semantic layer generates the SQL from predefined measures. Here too, the model touches neither the queries nor the numbers.

Key Questions Answered

What are the key details on From a data-export experiment to a standalone service?

It began with a task in April: assess the inventory at one of the warehouses and suggest how to clear out equipment that had been sitting unused. At the time, the company was tracking a metric called aged, the share of assets that have been in storage for more than one to two years. Shlyupikov took an export from Naumen.ITAM, stripped out sensitive data (legal entities, warehouse names) and asked a neural network to build an HTML report. It produced many cross-sections. Each was of little value on its own, but together they answered a large number of questions. His manager

What are the key details on Placeholders instead of numbers?

This led to a hard separation. The script prepares two datasets: a full one, from which the charts and template are built, and a compact one containing a few dozen key numbers. The model sees only the compact one. It returns observations, interpretations and red flags, and puts placeholders in place of figures. The values are filled in when the report is assembled, using the same rules as the template. Distorting a metric through the model is physically impossible. There is a token-economy benefit too: the context holds dozens of numbers rather than arrays of rows. The mode

What are the key details on Trino as glue across time and across systems?

As the number of sources grew, the entire data layer moved to a separate VM running Trino. The authors admit that at the time this was overkill, but they built in a safety margin. Trino solves two problems. Joining across time. In Naumen.ITAM, the current state sits in a replica of the production database, while history arrives in ClickHouse as daily snapshots. A single federated query takes today's data point from the replica, and yesterday and all earlier history from ClickHouse. The limitation: the history step is one day, so statuses that changed during the day are not

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Hands-On AI Engineering · Hamidun Academy

Build & Ship Production AI Agents Without Boilerplate Code

Start your free 72-hour trial at Hamidun Academy (academy.hamidun.com) — interactive lessons on Claude Code & Cursor, live Tech Radar, and production agent templates.

Start 72h Free Trial →Vibe-Coding Intensive
What do you think?
Loading comments…