KPIAssembler: stop hand-picking KPIs, let AI propose them Developer Akshat Srivastava released KPIAssembler, an open-source Ruby gem that uses an LLM to propose KPI metric SQL recipes while deterministic Ruby code certifies which ones are safe to publish. The tool inspects a live database schema, runs candidates through EXPLAIN and sample-period replay checks, and flags failures such as unconstrained joins or unsafe division, with heuristic candidates as a fallback when no model is available. "The LLM proposes. Code certifies," the project states. Text-to-SQL looks great in a demo. Then someone ships a conversion rate that JOIN s without ON , a revenue figure that double-counts through a fan-out, or a "tenant-safe" query that forgot account id . The chart library was never the hard part. Metric definition is. I built KPIAssembler for that gap: inspect the live schema, let a model propose KPI recipes, and let deterministic Ruby decide what is certified. The model never gets a vote on publication. Gem: kpi assembler https://rubygems.org/gems/kpi assembler Source: github.com/Akshatsrivastava700/kpi assembler https://github.com/Akshatsrivastava700/kpi assembler The LLM proposes. Code certifies. Certification is boring on purpose. Each accepted candidate must: SELECT or WITH … JOIN without ON NULLIF / CASE EXPLAIN and a sample-period replay Fail any check and the KPI is draft , with reasons. Draft is not "you rejected it in the UI." Rejected candidates never reach this step. Draft means you accepted it and the engine still refused to publish the number. That distinction is the whole product. Heuristics still run as a backfill. If Gemini is down or Ollama has the wrong model pulled, you get schema-driven candidates instead of an empty screen. The UI says whether the proposer was llm or heuristics . Gemfile gem "kpi assembler", "~ 0.5" bundle install bin/rails generate kpi assembler:install config/routes.rb — inside the same auth scope as the rest of the app mount KPIAssembler::Engine = "/kpi-assembler" Point the initializer at a read-only pool. Certification executes candidate SQL. Do not hang this off the write primary. KPIAssembler.configure do |config| config.connection provider = lambda do | controller| ApplicationRecord.connected to role: :reading do ApplicationRecord.connection pool end end config.tenant column = "account id" config.tenant id resolver = - controller { controller.send :current account .id } config.authorize with = lambda do |controller| controller.send :authenticate user controller.send :current account .present? end config.llm provider = :gemini config.gemini api key = ENV "GEMINI API KEY" end In .env : KPI LLM PROVIDER=gemini GEMINI API KEY=your-key KPI GEMINI MODEL=gemini-2.0-flash No Gemini URL to set. Restart, sign in, open /kpi-assembler , click Discover metrics . Prefer local models? KPI LLM PROVIDER=ollama and a running ollama serve . Prefer no model? KPI USE LLM=false . Walkthrough and troubleshooting: setup guide https://github.com/Akshatsrivastava700/kpi assembler/blob/main/docs/setup.md . The sample catalog includes a metric that is supposed to fail: revenue per lead via an unconstrained join. It is accepted on purpose so you can watch certification refuse it. You should see reasons like: JOIN without ON — unconstrained join / cartesian risk Unsafe division without NULLIF or CASE That is the demo I care about — not a green dashboard. Other drafts you will hit with a real LLM: missing account id = 123 , invented table names, or Sample-period replay returned NULL when NULLIF did its job on an empty window. Those are honest failures. Empty last-30-days is not the same as bad SQL, but the engine currently treats a NULL replay as unpublished. Read the reasons array before you rewrite the query. It is not Looker, Metabase, or a warehouse. It does not persist packs to your database yet: the engine keeps the latest pack in memory per tenant . Restart the process and it is gone. GET /kpi-assembler/api/v1/pack is the JSON to save yourself if you need it durable. It is not "AI analytics." It is a gated compiler for metric SQL. gem "kpi assembler", "~ 0.5" Issues and PRs: Akshatsrivastava700/kpi assembler https://github.com/Akshatsrivastava700/kpi assembler . If you already generate KPIs with a chatbot, run one of those queries through a join-without- ON check before you put it on a slide. That is the same instinct this gem encodes.