All work

Tender Radar

AI that reads every EU IT tender and says which ones to bid on, and at what price.

An AI pipeline on Databricks: an LLM translates and classifies every EU IT tender from 24 languages, an ML model predicts the winning price, and RAG answers questions with cited sources. Every open tender gets a score with three reasons, every morning.

Role
Personal project · AI, data engineering & ML
Period
11/2026

Built end to end on Databricks

On Free Edition: serverless only, one SQL warehouse, one AI Search endpoint and a daily compute quota. Those limits shaped the design.

  • Lakeflow Jobs
  • Unity Catalog
  • Auto Loader
  • Delta Lake
  • Databricks SQL
  • ai_query
  • MLflow
  • AI Search
  • AI/BI Dashboards
  • Declarative Automation Bundles

The question

Which EU IT tenders should a mid-size IT firm bid on this week, and at what price?

Every year the EU publishes about 80,000 IT, software and consulting tenders on TED, in 24 languages. A mid-size IT firm can bid on a few a month, and every bid costs days of work.

What I asked myself first

Can we predict who wins?

No. Award notices name only the winner, never the other bidders. And 94% of winners come from the buyer's own country, so always guessing “domestic” is already 94% right, and useless.

94%of winners are domestic

What can the data predict?

The price. The award value is filled in for 77% of EU awards. So a model predicts award ÷ estimate, and similar past tenders show who won them.

77%of awards carry a price

Is bidding even worth it?

Often, yes. 40.4% of awarded IT tenders had only one bidder, 72.8% in Croatia. And winning prices land at a median 0.83× the estimate.

40.4%had only one bid

What the data can't tell

  • Who else bid, and at what price
  • Why the winner won
  • What the contract really costs in the end

Consulting case

What this is worth to a bid team

Tender Radar is built like a client project: a real decision (bid or no bid), the firm's profile as configuration, and numbers a bid manager can check. For a mid-size IT firm in DACH it changes four things.

Focus

1,778 instead of 7,918

The score narrows the open calls to those that fit the firm's services, size and markets, each with its reasons. Today that is 77.5% fewer to read.

Price

0.83×

Winning prices land at a median 0.83× the buyer's estimate. The model gives a likely price per tender: a starting point for the bid instead of a gut feeling.

Where to compete

66% vs. 16%

Single-bid share in software maintenance vs. procurement consulting. Topics and buyers show where few firms bid, and point sales effort there.

Cost to run

≈ 10 min

Of serverless compute per day on Free Edition. At a client, the same bundle deploys from git into their own workspace.

How I would roll it out at a client

  1. 1Set the profileThe firm's services, home markets and size range as dbt variables. The score recalculates right away.
  2. 2Pilot with the bid teamFour weeks of putting the shortlist next to the team's real decisions, and tuning the weights on them.
  3. 3Hand overThe job, tests and dashboard run from git in the client's Databricks workspace. The team owns it, not me.

The pipeline

From 24 languages to one recommendation

Every morning at 06:00 a Lakeflow Job runs on Databricks Free Edition, deployed from git. Click a step.

  1. The last 3 days from the TED Search API and the ECB rates land as files in a Unity Catalog volume, so a missed day catches up by itself.

    • Python
    • TED API
    • Unity Catalog

    3 yearsof history since eForms (10/2023)

One run takes about 10 minutes of serverless compute. Every step is rerunnable: the fix for a failure is to rerun.

Live dashboard

The Databricks dashboard, live

This is the AI/BI dashboard I built in Databricks, taken over 1:1: the same content, the same 7 SQL queries on the same gold tables. A GitHub Action runs them every morning after the pipeline and the page is rebuilt from the result, so the numbers match the original.

  1. Databricks gold tables
  2. 7 SQL queries
  3. JSON snapshot
  4. Static site
The original in Databricks
The original in Databricks

Tender Radar

Data as of (Berlin time)

This week's bids

Every open EU IT tender, scored 0–100 for a mid-size IT firm in the DACH region. The reasons say why. Likely winning price = estimate × the model's predicted award ÷ estimate.

Open tenders scored
7,918
Score 70 or more
1,778
AITypical award ÷ estimate (model)
0.88×

300 matches · the top 300 of 7,918 open tenders

1–10 of 300

AI, ML & RAG

Where the AI works, and how I tested it

Every AI part is tested against something simple: a hand check, a baseline, or a test set with known answers.

LLM

Translate and classify

20/20

summaries right, checked by hand

Llama 3.3 70B turns every notice in 24 languages into an English title, a summary, technologies and a service type.

ai_query right in the warehouse, a fixed JSON schema (every answer parses), each notice sent only once, open tenders first.

Hand check: 20 tenders in 8 languages
  • Title19/20
  • Summary20/20
  • Technologies19/20
  • Service type17/20
ML

Predict the winning price

−19%

error (MAE) vs. the median baseline

Gradient boosting predicts award ÷ estimate. Times the estimate, that is the likely winning price in the dashboard.

Time split: trained on Oct 2023 – Sep 2026, tested on October 2026. Logged in MLflow, registered in Unity Catalog only if it beats the baseline.

Mean error on unseen months (lower is better)
  • Baseline (median)0.299
  • Model0.242
RAG

Answer questions with sources

80%

recall@6: the right source among the top 6

A question like “cloud migration Germany” finds matching tenders by vector search, and the LLM answers only from those sources, with a TED link for every claim.

Embeddings (gte-large-en) in dbt, an AI Search index, hybrid retrieval (top 6), answers with [n] citations and a check that every cited source exists.

20 test questions with a known answer
  • Recall@680%
  • Cites the right notice80%
  • Grounded answers100%
Clustering

Find the topics

66%

single-bid share in software maintenance

k-means on the same embeddings groups the tenders into 15 topics that the LLM names. That shows where competition is low.

Tried k = 10 to 30; 15 had the best silhouette score. Fit once, assigned daily: stable topics and a cheap daily step.

Only one bid: least vs. most contested
  • Software maintenance66.3%
  • Procurement consulting16.4%

And why the bid score is not a model

There is no data on which tenders a firm should have bid on, so a model would only pretend to know. The score is an open formula from five signals instead, and every tender shows its top three reasons.

  • Fits our services30 points
  • Low competition25 points
  • Right size20 points
  • Home market (DACH)15 points
  • Known buyer10 points

What I built

  • LLM enrichment with Llama 3.3 70B via ai_query: English title, summary, technologies and service type from 24 languages, as schema-checked JSON, hand-checked on 20 tenders.
  • A price model (gradient boosting, time-based split) in MLflow that predicts award ÷ estimate and beats the median baseline by 19% MAE.
  • A RAG chat with sources: embeddings, a vector index of 29,373 documents, hybrid retrieval, citation checks, recall@6 of 80%. Plus 15 topics from k-means on the embeddings.
  • A daily lakehouse pipeline as a Lakeflow Job: the TED API, Auto Loader into bronze, PySpark silver in EUR, dbt gold with 6 models and 18 tests, including a leak test.
  • A transparent bid score from five signals with the top three reasons in words, as an AI/BI dashboard deployed from git and rebuilt here from a daily snapshot.

Results

  • Every open tender scored, with three reasons in plain words and a model-predicted winning price.
  • Questions about tenders in any language, answered with TED sources instead of made-up answers.
  • Facts a bid manager can use: 40.4% of IT awards had only one bid.
  • Runs every morning without me, deployed from git, on Databricks Free Edition.

Tech stack

AI & ML

LLM translation, the price model, topics and RAG search with sources.

  • ai_query
  • Llama 3.3 70B
  • scikit-learn
  • MLflow
  • AI Search
  • gte-large-en

Ingest & lakehouse

New notices every morning from bronze to silver, converted to EUR.

  • Python
  • Auto Loader
  • Delta Lake
  • PySpark
  • Unity Catalog

Gold & quality

Tested gold tables for the model, search, score and dashboard.

  • dbt
  • SQL
  • Databricks SQL

Run & serve

The daily job from git, the dashboard and this snapshot export.

  • Lakeflow Jobs
  • Declarative Automation Bundles
  • AI/BI Dashboards
  • GitHub Actions
  • Next.js
Next projectTrain&Track