SPB Git

spb/airiskindex Public

The most methodologically rigorous, fully transparent AI job-exposure index.

TypeScript 88% Python 6.1% SQL 2.7% CSS 1.2% JavaScript 0.9% Shell 0.8%
21.5 KB · 458 lines tsx
Raw Blame History
1//  File:    page.tsx2//  Path:    apps/web/app/methodology/page.tsx3//  Project: AI Risk Index — airiskindex.io4//  Author:  Simon-Pierre Boucher5//  Contact: contact@spboucher.ai6//  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.7//8//  Description: Human-readable methodology documentation (weights pulled live from the engine).910import Link from "next/link";11import {12  DIMENSIONS,13  EXPOSURE_DIMENSIONS,14  HIGH_EXPOSURE_THRESHOLD,15  INDEX_VERSION,16  INVERTED_DIMENSIONS,17  WEIGHTS,18  type DimensionKey,19} from "@airiskindex/scoring";2021export const metadata = {22  title: "Methodology — AI Risk Index",23  description:24    "Full methodology of the AI Risk Index: task-based scoring, multi-model LLM rater panel, confidence intervals, weights, formulas, versioning and limitations.",25};2627const DIMENSION_DETAILS: Array<{28  key: DimensionKey;29  name: string;30  question: string;31  anchors: string;32}> = [33  {34    key: "automatability",35    name: "Task automatability",36    question:37      "Could current AI (including tool-using agents) perform this task end-to-end with at least 50% time saving at equal quality?",38    anchors:39      "1 = no meaningful part automatable today · 3 = roughly half automatable with significant setup · 5 = the full task meets the ≥50%-time-saving-at-equal-quality bar with off-the-shelf systems. The 50% threshold follows Eloundou et al. (2024), the citable standard.",40  },41  {42    key: "feasibility",43    name: "Current technical feasibility",44    question:45      "Do deployed products demonstrably perform this task reliably today — not merely in demos or benchmarks?",46    anchors:47      "1 = research-stage only · 3 = products exist with material error rates or narrow scope · 5 = mature products perform this reliably in production at scale. Separating conceivable from deployable is the failure that undid whole-occupation forecasts.",48  },49  {50    key: "cost_ratio",51    name: "Cost of substitution vs. wage",52    question:53      "How does the all-in AI cost per task-equivalent (inference, integration, oversight) compare to the loaded human wage for the same output?",54    anchors:55      "1 = AI is more expensive all-in · 3 = roughly comparable · 5 = AI is at least an order of magnitude cheaper.",56  },57  {58    key: "barriers",59    name: "Adoption barriers",60    question:61      "How strong are the real-world barriers to substitution: licensing and authorization requirements, liability and error-cost asymmetry, regulation of the automation itself, human-contact requirements, organizational friction?",62    anchors:63      "1 = nothing prevents substitution · 3 = some friction (oversight requirements, customer preference for humans) · 5 = hard barriers — a licensed human must legally perform or sign off on the task. This dimension is inverted in the composite: strong barriers lower the substitution score.",64  },65  {66    key: "adoption_velocity",67    name: "Sector adoption velocity",68    question:69      "How fast and deep are the sectors where this task occurs actually adopting AI — agents in production and measured displacement, not vendor announcements?",70    anchors:71      "1 = laggard sectors (small firms, physical work, low digitization) · 3 = pilots common, production rare · 5 = fast, deep adoption (information, finance, professional-services patterns).",72  },73];7475function Section({76  id,77  title,78  children,79}: {80  id: string;81  title: string;82  children: React.ReactNode;83}): JSX.Element {84  return (85    <section id={id} className="mt-12 scroll-mt-6">86      <h2 className="text-2xl font-semibold tracking-tight">{title}</h2>87      <div className="mt-4 space-y-4 leading-relaxed text-[var(--ink-2)]">{children}</div>88    </section>89  );90}9192export default function MethodologyPage(): JSX.Element {93  return (94    <main className="mx-auto max-w-3xl px-4 py-10 sm:px-6 sm:py-14">95      <p className="text-xs font-semibold uppercase tracking-[0.14em] text-[var(--muted)]">96        Methodology · version {INDEX_VERSION}97      </p>98      <h1 className="mt-3 text-4xl font-bold tracking-tight">99        How the AI Risk Index is computed100      </h1>101      <p className="mt-4 text-lg leading-relaxed text-[var(--ink-2)]">102        Every number on this site is reproducible: the weights, formulas, rater prompts and every103        individual model rating are public. This page is the human-readable specification; the104        machine-readable version is at{" "}105        <Link href="/api/v1/methodology" className="underline">106          /api/v1/methodology107        </Link>108        .109      </p>110111      <nav className="mt-8 card p-5 text-sm">112        <p className="font-medium text-[var(--ink)]">Contents</p>113        <ol className="mt-2 list-inside list-decimal space-y-1 text-[var(--ink-2)]">114          {[115            ["principles", "Principles"],116            ["three-scores", "The three scores"],117            ["data", "Data sources"],118            ["rating", "Task rating — the multi-model panel"],119            ["dimensions", "The five dimensions and their weights"],120            ["formulas", "Formulas"],121            ["aggregation", "From tasks to occupations"],122            ["uncertainty", "Confidence intervals"],123            ["versioning", "Versioning and immutable runs"],124            ["validation", "Validation and sensitivity"],125            ["limitations", "Known limitations"],126            ["citation", "Citation, license and contact"],127          ].map(([anchor, label]) => (128            <li key={anchor}>129              <a href={`#${anchor}`} className="hover:text-[var(--ink)] hover:underline">130                {label}131              </a>132            </li>133          ))}134        </ol>135      </nav>136137      <Section id="principles" title="1. Principles">138        <p>139          <strong className="text-[var(--ink)]">Task-based, not occupation-based.</strong>{" "}140          Occupations are bundles of tasks with very different AI exposure. Scoring whole141          occupations with a single judgment — the approach of the famous 2013 "47% of jobs"142          estimate — has a poor empirical track record. We score each of the ~18,800 O*NET task143          statements individually and derive occupation scores from them, weighted by how144          important each task is to the occupation.145        </p>146        <p>147          <strong className="text-[var(--ink)]">Uncertainty is part of the score.</strong> Large148          language models disagree with each other substantially when rating AI exposure —149          replications show the share of "highly exposed" occupations can vary by an order of150          magnitude depending on which frontier model does the rating. A single-model index is151          therefore an artifact. Every score we publish carries a confidence interval derived from152          disagreement across an independent multi-model panel.153        </p>154        <p>155          <strong className="text-[var(--ink)]">Fully reproducible.</strong> Weights live in one156          versioned source file, prompts are versioned, every rating stores the model, prompt157          version, raw response and parsed score, and every published number traces to a stored,158          immutable computation run.159        </p>160        <p>161          <strong className="text-[var(--ink)]">Adaptation, not doom.</strong> The evidence to162          date shows concentrated, cohort-specific effects — especially on entry-level hiring in163          automation-exposed occupations — rather than economy-wide job loss, while measured AI164          usage remains majority-augmentative. The index is designed to guide adaptation165          decisions, not to produce headlines.166        </p>167      </Section>168169      <Section id="three-scores" title="2. The three scores">170        <p>Every occupation gets three sub-scores on a 0–100 scale, never collapsed into one:</p>171        <ul className="list-inside list-disc space-y-2">172          <li>173            <strong className="text-[var(--ink)]">Exposure</strong> — AI is technically capable of174            performing the occupation's tasks. Computed from the capability dimensions only175            (automatability and feasibility).176          </li>177          <li>178            <strong className="text-[var(--ink)]">Substitution</strong> — the headline composite:179            AI actually replaces the human, once cost, adoption barriers and sector adoption180            velocity are accounted for. Exposure without adoption predicts nothing; this score is181            exposure discounted by the real world.182          </li>183          <li>184            <strong className="text-[var(--ink)]">Augmentation</strong> — AI assists the human on185            the task, raising productivity without replacing them. Rated separately per task; it186            is not part of the substitution composite. High augmentation alongside moderate187            substitution reads as a changing job, not a disappearing one.188          </li>189        </ul>190      </Section>191192      <Section id="data" title="3. Data sources">193        <div className="overflow-x-auto card">194          <table className="w-full text-left text-sm">195            <thead className="border-b border-[var(--grid)] text-xs uppercase tracking-wide text-[var(--muted)]">196              <tr>197                <th className="px-4 py-3 font-medium">Input</th>198                <th className="px-4 py-3 font-medium">Source</th>199                <th className="px-4 py-3 font-medium">Role</th>200              </tr>201            </thead>202            <tbody>203              {[204                [205                  "Occupations & task statements",206                  "O*NET 30.3 (U.S. Dept. of Labor, CC BY 4.0), O*NET-SOC 2019 taxonomy",207                  "Unit of analysis: 1,016 occupations, ~18,800 tasks",208                ],209                [210                  "Task importance weights",211                  "O*NET Task Ratings, importance scale (IM, 1–5)",212                  "Aggregation weights from tasks to occupations",213                ],214                [215                  "Wages & employment",216                  "BLS Occupational Employment and Wage Statistics, May 2025 national",217                  "Median wages (shown per occupation; cost-ratio context)",218                ],219                [220                  "EU/France crosswalk (planned)",221                  "ESCO v1.2 + official ESCO↔O*NET crosswalk; ROME 4.0",222                  "European occupation coverage in a future release",223                ],224                [225                  "Adoption evidence",226                  "Census BTOS, Anthropic Economic Index, sector deployment studies",227                  "Grounding for the adoption-velocity rubric anchors",228                ],229              ].map(([a, b, c]) => (230                <tr key={a as string} className="border-b border-[var(--grid)] last:border-b-0 align-top">231                  <td className="px-4 py-3 font-medium text-[var(--ink)]">{a}</td>232                  <td className="px-4 py-3">{b}</td>233                  <td className="px-4 py-3">{c}</td>234                </tr>235              ))}236            </tbody>237          </table>238        </div>239        <p>240          Raw source dumps are immutable and never edited in place; all transformations run241          through a pipeline that records manifests (hashes and row counts) for every derived242          artifact.243        </p>244      </Section>245246      <Section id="rating" title="4. Task rating — the multi-model panel">247        <p>248          Each task statement is rated on six dimensions (the five composite dimensions plus249          augmentation) on an integer 1–5 scale by{" "}250          <strong className="text-[var(--ink)]">at least two independent frontier language251          models</strong> using an identical, versioned rubric prompt. Ratings are requested with252          schema-constrained JSON output; each rating must include a written rationale grounded in253          the task statement.254        </p>255        <p>256          For every task × dimension, the panel produces a rating band:{" "}257          <code>low</code> = the panel minimum, <code>mid</code> = the panel mean,{" "}258          <code>high</code> = the panel maximum. Bands — not single numbers — flow into all259          downstream computation, which is how rater disagreement becomes a visible confidence260          interval instead of hidden noise.261        </p>262        <p>263          <strong className="text-[var(--ink)]">Audit trail.</strong> Every rating stores the264          model identifier, prompt version, raw API response, parsed score and rationale. On any265          occupation page, expanding a task shows every model's rating and rationale — nothing is266          asserted that cannot be inspected.267        </p>268        <p>269          <strong className="text-[var(--ink)]">Human validation.</strong> A sample of ratings is270          reviewed by humans; disagreements above one point on the 5-point scale route the task to271          an expert review queue whose overrides replace the model band and are flagged in the272          data. Prompt changes bump the prompt version and invalidate cached ratings.273        </p>274      </Section>275276      <Section id="dimensions" title="5. The five dimensions and their weights">277        <div className="overflow-x-auto card">278          <table className="w-full text-left text-sm">279            <thead className="border-b border-[var(--grid)] text-xs uppercase tracking-wide text-[var(--muted)]">280              <tr>281                <th className="px-4 py-3 font-medium">Dimension</th>282                <th className="px-4 py-3 font-medium">Weight</th>283                <th className="px-4 py-3 font-medium">Orientation</th>284              </tr>285            </thead>286            <tbody className="tabular-nums">287              {DIMENSIONS.map((key) => (288                <tr key={key} className="border-b border-[var(--grid)] last:border-b-0">289                  <td className="px-4 py-3 font-medium text-[var(--ink)]">290                    {DIMENSION_DETAILS.find((d) => d.key === key)?.name ?? key}291                  </td>292                  <td className="px-4 py-3">{(WEIGHTS[key] * 100).toFixed(0)}%</td>293                  <td className="px-4 py-3">294                    {INVERTED_DIMENSIONS.has(key)295                      ? "inverted — higher rating lowers substitution"296                      : "direct"}297                  </td>298                </tr>299              ))}300            </tbody>301          </table>302        </div>303        <div className="space-y-5">304          {DIMENSION_DETAILS.map((dim) => (305            <div key={dim.key}>306              <h3 className="font-semibold text-[var(--ink)]">307                {dim.name}{" "}308                <span className="text-sm font-normal text-[var(--muted)]">309                  · weight {(WEIGHTS[dim.key] * 100).toFixed(0)}%310                </span>311              </h3>312              <p className="mt-1">{dim.question}</p>313              <p className="mt-1 text-sm text-[var(--muted)]">{dim.anchors}</p>314            </div>315          ))}316        </div>317        <p>318          Weights are defined once, in a versioned source file, and served live at{" "}319          <Link href="/api/v1/methodology" className="underline">320            /api/v1/methodology321          </Link>{" "}322          — any change is a new index version with a changelog entry and regenerated sensitivity323          analyses.324        </p>325      </Section>326327      <Section id="formulas" title="6. Formulas">328        <p>329          A rating <em>r</em> ∈ [1, 5] normalizes to substitution pressure <em>p</em> ∈ [0, 1]:330        </p>331        <pre className="overflow-x-auto card p-4 text-sm text-[var(--ink)]">332          {`p = (r − 1) / 4            direct dimensions333p = 1 − (r − 1) / 4        inverted dimensions (barriers)334335substitution_task = 100 · Σ_d  w_d · p_d          over all five dimensions336exposure_task     = 100 · (w_auto·p_auto + w_feas·p_feas) / (w_auto + w_feas)337augmentation_task = 100 · p_augmentation`}338        </pre>339        <p>340          The exposure sub-score uses only {EXPOSURE_DIMENSIONS.join(" and ")}, renormalized. The341          scoring engine is a pure, deterministic library with no network, clock or randomness —342          identical inputs always produce identical scores, which is what makes runs auditable.343          Its behavior is pinned by property-based tests and by a published worked example that344          the test suite reproduces to three decimals.345        </p>346      </Section>347348      <Section id="aggregation" title="7. From tasks to occupations">349        <p>350          Occupation scores are the importance-weighted mean of task scores, using O*NET task351          importance ratings normalized within each occupation. Tasks without an importance rating352          receive the occupation's mean importance. The same aggregation applies to the low, mid353          and high bounds.354        </p>355        <p>356          We additionally report the <strong className="text-[var(--ink)]">highly exposed task357          share</strong>: the fraction of an occupation's tasks with a substitution score of{" "}358          {HIGH_EXPOSURE_THRESHOLD} or more. "X% of tasks in this occupation are highly exposed"359          is the preferred headline reading — more honest than a single composite.360        </p>361      </Section>362363      <Section id="uncertainty" title="8. Confidence intervals">364        <p>365          The low and high bounds are worst/best-case envelopes over the rater panel: the lower366          bound takes each dimension's pressure-minimizing rating bound (for the inverted barriers367          dimension, that is the <em>high</em> rating), the upper bound symmetrically. By368          construction low ≤ score ≤ high always holds. A wide interval means the models disagreed369          — treat that score as an open question, not a verdict. Occupations with the widest370          intervals are exactly where human expert review is prioritized.371        </p>372      </Section>373374      <Section id="versioning" title="9. Versioning and immutable runs">375        <p>376          The index version ({INDEX_VERSION}) follows semantic versioning: formula or weight377          changes are major; data-source refreshes are minor; recomputations with refreshed378          adoption inputs are patches. Every computation writes a run record with the index379          version, prompt version and rater models. Runs are immutable — recomputations create new380          runs and old runs remain queryable, so any historically published score can be381          reproduced and checked forever. Every API response carries the index version it was382          computed under.383        </p>384      </Section>385386      <Section id="validation" title="10. Validation and sensitivity">387        <p>Published alongside each major or minor release:</p>388        <ul className="list-inside list-disc space-y-2">389          <li>390            <strong className="text-[var(--ink)]">Convergent validity</strong> — rank correlation391            against independent published measures (Felten AIOE, "GPTs are GPTs" task scores, ILO392            exposure gradients).393          </li>394          <li>395            <strong className="text-[var(--ink)]">Rater stability</strong> — the distribution of396            cross-model agreement; the widest-band occupations are flagged in the product.397          </li>398          <li>399            <strong className="text-[var(--ink)]">Outcome tracking</strong> — correlation against400            realized labor-market indicators (entry-level employment in exposed occupations,401            measured usage data). Exposure indices individually explain little of realized402            unemployment risk, so we report outcome tracking honestly rather than claiming403            prediction.404          </li>405          <li>406            <strong className="text-[var(--ink)]">Weight sensitivity</strong> — rank stability of407            the composite under ±25% perturbation of each weight.408          </li>409        </ul>410      </Section>411412      <Section id="limitations" title="11. Known limitations">413        <ul className="list-inside list-disc space-y-2">414          <li>415            LLM raters co-evolve with the technology they measure; multi-model panels bound this416            "ruler problem" but do not eliminate it.417          </li>418          <li>419            Sector-level adoption evidence enters through rubric anchors rather than per-sector420            statistical joins in the current version.421          </li>422          <li>423            Scores describe tasks as currently constituted; occupations reorganize, and task mixes424            shift precisely when exposure is high.425          </li>426          <li>427            Wages shown are U.S. national medians; cross-country generalization awaits the428            ESCO/ROME release.429          </li>430          <li>431            This index measures pressure, not destiny. It cannot tell an individual whether their432            job is safe; it can tell them which of their tasks are changing and how confident the433            evidence is.434          </li>435        </ul>436      </Section>437438      <Section id="citation" title="12. Citation, license and contact">439        <p>440          Cite as: <em>AI Risk Index, version {INDEX_VERSION}, airiskindex.io, Simon-Pierre441          Boucher (2026)</em>. Scores and derived data are published under{" "}442          <strong className="text-[var(--ink)]">CC BY 4.0</strong> — reuse freely with443          attribution and the index version. Occupation and task data incorporate the O*NET444          database (U.S. Department of Labor, CC BY 4.0); wage data from BLS OEWS.445        </p>446        <p>447          Methodology questions, corrections, expert-panel participation, data licensing or448          anything else:{" "}449          <a href="mailto:contact@spboucher.ai" className="underline">450            contact@spboucher.ai451          </a>{" "}452          — Simon-Pierre Boucher.453        </p>454      </Section>455    </main>456  );457}458