Skip to content

Repository files navigation

SCAI — Signal & Cost engine for AI Infrastructure

SCAI

SCAI estimates a prospect's dedicated ML inference spend from public signals for AI infrastructure teams.

SCAI fixture-backed demo

Python 3.11+ Cost tests

The problem

I spent four months on an ML platform team whose GPU cluster sat at 5% utilisation. The instinct was to add nodes, but a 2-second feature query sat in front of a 1-millisecond inference: the hardware was starving, not saturated. That waste was invisible from the outside, and it has been invisible at every company I have looked at since. SCAI estimates it from public signals alone.

Demo

Landing state with company input and batch upload

Landing state: analyse one company or upload a CSV.

Grounded signal cards with evidence quotes and source links

Signal extraction: each claim retains its evidence quote, confidence, and source URL.

Deterministic cost estimate with the assumptions table expanded

Cost estimate: the full editable assumption set and unverified pricing row remain visible.

Constrained draft email with word counter and referenced signal

Email draft: validated cost figures, a linked signal, and a visible word count.

No public signal refusal state

Negative state: no grounded public signal means no estimate and no email.

These captures come from the recorded fixture in scripts/fixtures/capture.json; python scripts/capture.py reproduces them without an API key or model call.

How it works

flowchart LR
    A["1 · Signal extraction<br/>Gemini + Google Search grounding"] -->|"structured JSON<br/>source URL on every claim"| B["2 · Cost estimate<br/>pure Python + pricing.json"]
    B -->|"validated numbers only"| C["3 · Email draft<br/>Gemini constrained to Stage 2 output"]
Loading

Stage 1 retrieves public evidence and validates it into typed JSON. Stage 2 is a deterministic Python function with no model call. Stage 3 receives the validated signals and the completed cost object; its output is rejected if it introduces a dollar figure outside that object.

Why the model never produces a number

The LLM is used for retrieval and language, never for arithmetic. Every dollar figure is computed in app/cost.py from a hand-maintained pricing.json catalog whose rows carry source URLs and whose top-level as_of date records when the prices were checked.

Any pricing row that could not be verified is marked TODO_VERIFY. The cost engine rejects it, and the interface greys it out instead of guessing. A hallucinated price would make the entire tool worthless; separating probabilistic retrieval and drafting from deterministic cost math is the design decision SCAI is built around.

Cost model

Let q be peak queries per second, t throughput per instance, p hourly instance price, h hours per month, u utilisation as a percentage, and a API price per 1,000 inferences.

Assumption Default value Where it comes from How to override it
Scale band Signal result; unknown falls back to medium Stage 1 structured output; fallback in app/cost.py Select small, medium, or large in the cost table, or change inferred.scale_band in POST /api/estimate
Peak QPS (q) small: 5, medium: 50, large: 500, unknown: 50 DEFAULT_PEAK_QPS in app/cost.py Edit Peak QPS, or set overrides.peak_qps
Estimate range q_low = 0.5q; q_high = 1.5q Fixed range in app/cost.py Not exposed; change the two multipliers in app/cost.py
Utilisation (u) 15% DEFAULT_UTILISATION_PCT in app/cost.py Edit Assumed utilization, or set overrides.assumed_utilisation_pct
Hours per month (h) 730 DEFAULT_HOURS_PER_MONTH in app/cost.py Edit Hours per month, or set overrides.hours_per_month
Throughput per instance (t) small: 4, medium: 20, large: 100 inferences/s Planning bands in the selected pricing.json row; they are not benchmarks Edit Throughput / instance, set overrides.throughput_inferences_per_sec, or maintain the catalog
Dedicated instance (p) GCP g2-standard-4 with one NVIDIA L4 in us-central1, $0.706832276/hour Verified public list-rate row in pricing.json Select another verified row, set overrides.instance_id, or maintain the catalog
API comparison (a) $3.75 / 1,000 inferences pricing.json: 1,000 input and 250 output tokens at the catalogued public list rates Edit Per-call API / 1k, set overrides.api_price_per_1k_inferences_usd, or maintain the catalog
Seconds per hour 3,600 Unit conversion in app/cost.py Not configurable

The engine applies the same equations at q_low, q, and q_high where a range is required:

instances_needed(q) = ceil(q / t)
monthly_cost(q) = instances_needed(q) × p × h
idle_spend(q) = monthly_cost(q) × (1 − u / 100)

monthly_inferences(q) = q × h × 3,600 × (u / 100)
cost_per_1k(q) = monthly_cost(q) / monthly_inferences(q) × 1,000

api_cost_at_full_utilisation(q) = q × h × 3,600 / 1,000 × a
breakeven_utilisation(q) = min(100, monthly_cost(q) / api_cost_at_full_utilisation(q) × 100)

For the default medium band, for example, instances_needed(50) = ceil(50 / 20) = 3; the rest can be reproduced by substituting the table values above. Workload type and model-family guesses do not enter the cost equations.

Quickstart

Python 3.11 or later and Docker are required. Create .env from the tracked template and set GEMINI_API_KEY before starting the container.

git clone https://github.com/daetan999/SCAI.git
cd SCAI
cp .env.example .env
docker build -t scai .
docker run --rm --env-file .env -p 8080:8080 scai

Open http://localhost:8080.

The included deploy script builds from source and deploys the scai service to Cloud Run:

export GOOGLE_CLOUD_PROJECT="your-project-id"
bash scripts/deploy_cloud_run.sh

It defaults to asia-southeast1; set CLOUD_RUN_REGION to override the region. The deploying identity needs permission to build and deploy Cloud Run services and to use the configured Gemini endpoint.

Batch mode

Upload a UTF-8 CSV whose first column contains one company name or public careers-page URL per row. The optional header may be company, company_name, or url; a batch is limited to 50 rows and 1 MB.

company
Google Cloud
NVIDIA

The response columns are:

company,serves_models,idle_spend_low,idle_spend_high,top_signal_url,subject,email_body,no_signal_found

With the app running, submit the tracked example file and save the response:

curl -fsS -F 'file=@sample_companies.csv' http://localhost:8080/api/batch -o scai-batch-results.csv

Limitations

  • Estimates are ranges derived from public list rates. They ignore committed-use discounts, negotiated pricing, spot capacity, taxes, storage, networking, support, and engineering labour.
  • Throughput figures are coarse planning bands, not benchmarks. Model architecture, precision, batch size, sequence length, hardware, and latency targets can move the result materially.
  • Signal extraction depends on a company publishing something indexable. Absence of signal is not absence of workload.
  • SCAI does not detect batch versus real-time inference reliably. A wrong workload classification makes the chosen throughput band less useful.
  • The default assumes dedicated, continuously provisioned instances. Autoscaling, shared clusters, serverless endpoints, queues, and burst patterns are not modelled.
  • Source grounding constrains citations; it does not prove that a source is current, complete, or representative of the deployed system.
  • The API comparison uses a fixed token-shape assumption. It is not a quote for a prospect's actual traffic.

Disclaimer

SCAI is not affiliated with, endorsed by, or representing any cloud or GPU vendor. Pricing data is from public list pages and is accurate only as of the as_of date in pricing.json.

About

Estimates a company's ML inference spend from public hiring and engineering signals — cost math in Python, never from the model.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages