AI-Verified Economic Analytics Pipeline


AI-Verified Economic Analytics Pipeline: Recession Risk and AI's Labor Market Impact

This project pulls 10 macroeconomic time series from the FRED API, loads them into a SQLite star schema, runs ARIMA-based COVID outlier adjustment, and surfaces the results through an interactive Streamlit dashboard. Every chart section includes an AI-generated narrative insight that was batch-generated by a local LLM, and every factual claim in those narratives is programmatically verified against the source database before it reaches the page.

The pipeline runs in two modes. Seed mode works immediately on clone: no API key, no LLM, just a pre-built database with 3,488 observations and 9 verified AI insights. Full mode pulls live data from FRED and rebuilds everything from scratch.

Article Source Code

Code for the project can be found here


Dashboard


Motivation

I wanted a portfolio project that shows SQL fluency, a real data pipeline, and business framing in one place. My resume has NLP and ML work, but no public SQL project and no public dashboard querying a database I built. Every DA/BI/analytics engineering job posting mentions SQL, and most want to see that you can pull data from an API, model it relationally, and present findings to a non-technical audience.

FRED was the obvious data source. I have an econometrics degree, FRED is the gold standard for U.S. macro data, and the API is free with generous rate limits. The business question came from watching two trends diverge in real time: information-sector employment flattening out while skilled trades keep growing. Add in yield curve inversions, a 37% cumulative CPI increase, and surging electricity demand from data centers, and there's a genuine macro story to tell.

The AI insight layer is what makes this project different from a standard dashboard. In 2026 every portfolio has charts. This one talks. Each chart section gets a batch-generated narrative that explains what the numbers mean in plain English, and every claim in that narrative is fact-checked against the database before it ships. That three-layer verification system (structured claims, programmatic checking, source display) is the feature I'd demo in an interview.


Design Decisions

I chose FRED over BLS or a multi-source ETL because it has 800,000+ series, updates reliably, and maps directly to my econometrics background. The API returns clean time series that model naturally into a star schema. BLS would have worked too, but FRED's single-endpoint design meant I could focus on the analysis and dashboard instead of fighting pagination across multiple endpoints.

SQLite is the right tool for this scale. No server to configure, the database is a single file you can inspect with any SQLite browser, and it ships with the repo so anyone can clone and run. For 3,488 observations across 10 series, PostgreSQL would add operational complexity without any analytical benefit.

AI insights are batch-generated rather than called live. Hitting an LLM on every page load or filter change is the expensive mistake people make. After the data pipeline runs, a script aggregates key metrics into structured payloads, sends them to a local LLM (Ollama llama3.1:8b), stores the responses in the database, and the dashboard reads from that table. Zero live API calls, no latency, no ongoing cost. Re-run the batch when you pull new data.

Every AI-generated claim gets verified programmatically because LLMs hallucinate. Not often on structured numeric data, but often enough that you can't ship unverified prose on a dashboard. Every narrative contains 3-4 specific, testable claims (percentage changes, averages, month counts). A separate verification script re-queries the database for each claim and checks it within tolerance: 5% relative or 0.5 absolute for values, +/- 2 for counts, sign-match for trends. If a claim fails, the insight gets flagged with a warning badge instead of a green checkmark.

The COVID ARIMA adjustment exists because COVID created a once-in-500-years shock that breaks rolling window calculations for 24 consecutive months. A 12-month YoY window touching April 2020 produces +300% and -58% swings that dominate every chart. The ARIMA counterfactual replaces the COVID window (March 2020 through January 2022) with "what would this series have looked like without the pandemic," then tapers back to actual values over 3 months. Raw data stays in the value column. The adjusted series goes in value_covid_adjusted. The dashboard defaults to January 2022 onward, where all adjusted values have fully tapered back.

This didn't change any conclusions. The same findings hold before and after. What it did was make the charts readable and the rolling calculations meaningful.


The AI Verification Pipeline

This is the core differentiator. Here's how it works end to end.

Step 1: Pre-compute claims in Python. The insight script queries the database for each of 9 analytical slices (yield curve vs unemployment, info vs trades divergence, GDP growth, etc.) and builds 3-4 verifiable claims per slice. Claims use change_pct, pct_of_start, average, and count_months aggregations. No trivial "latest value" claims.

Step 2: LLM writes narrative only. The pre-computed claims and their underlying data get passed to Ollama llama3.1:8b with a system prompt that enforces structured JSON output. The LLM's job is to write readable prose that weaves the claims into a coherent story. It doesn't compute anything.

Step 3: Independent verification. verify_insights.py re-queries the database for every claim, compares the expected value to the actual value, and records the result. Tolerances are intentionally generous (5% relative) because the point is catching hallucinations, not rounding differences.

What the dashboard shows:

Each chart section has an AI Insight expander (open by default) with a verification badge:

  • Verified (green) means all claims passed
  • Partially Verified (orange) means some claims passed, and shows "X of Y confirmed"
  • Unverified (red) means no claims passed

A "Show sources" expander inside each insight shows a table with the claim text, expected value, actual value, and color-coded status. You can see exactly what the AI said and whether the database agrees.

The seed database ships with 9 pre-computed, fully verified insights. The demo works out of the box with no Ollama install and no API calls.


Per-Capita Normalization

Raw employment numbers grow partly because the U.S. working-age population grows about 0.5% per year. Comparing specialty trades employment of 4,256k in 2016 to 5,244k in 2026 overstates the real sector expansion because some of that growth is just more people.

Employment series (USINFO and CES2023800001) are divided by CNP16OV (civilian noninstitutional population 16+) to produce "employees per 1,000 working-age persons." Both series are then indexed to 100 at the start date so they're visually comparable despite different absolute scales.

Before normalization, the information sector showed index 101 (barely grew). After per-capita normalization, it's index 93. That's a real decline of 7.2% relative to population. Trades went from index 123 raw to index 113 per capita. The info sector isn't just stagnating. It's shrinking per capita while trades are genuinely expanding.


Architecture

FRED API  -->  data_pull.py  -->  db_setup.py  -->  covid_adjustment.py  -->  export_csv.py
                                                            |
                                                   ai_insights.py  -->  verify_insights.py
                                                            |
                                                   Streamlit dashboard (app.py)

The database is a SQLite star schema with three tables:

TableContents
series_metadataDisplay names, categories, units for each FRED series
observationsRaw values plus ARIMA COVID-adjusted values side by side
ai_insightsBatch-generated narratives with pre-computed claims and verification results

The observations table carries both value (raw from FRED) and value_covid_adjusted (ARIMA counterfactual for the COVID window, raw value everywhere else). All trend queries use the adjusted column except Q5 (COVID recovery), which intentionally shows the real shock and rebound.


Analysis Queries

Eight SQL queries using CTEs, window functions, joins, and per-capita normalization:

QueryWhat it answers
Q1Yield curve inversions vs unemployment (T10Y2Y monthly avg + UNRATE 12-month lag)
Q2Info vs trades divergence, per-capita normalized, indexed to 100
Q3GDP annualized growth with NBER recession shading
Q4Rolling 12-month per-capita employment growth by sector
Q5COVID recovery comparison (raw values, the one exception)
Q6U6 vs U3 unemployment gap (hidden labor market slack)
Q7Electric power output vs info employment (AI energy paradox)
Q8CPI inflation MoM and YoY (exploratory context)

Technical Notes

Excluding the COVID window from rolling calculations leaves a gap in the charts and breaks any indexed series that starts before 2020. The ARIMA counterfactual is the better approach: fill the gap with a statistically defensible estimate and keep the raw data intact for queries that specifically need it (Q5).

Don't ask a language model to do math. Early iterations had the LLM compute values itself, and it got them wrong about 15% of the time. The right architecture has Python pre-compute all claims and hands the LLM finished numbers to weave into prose. That dropped verification failures to near zero.

Per-capita normalization had an outsized effect on the analysis. The raw data says the information sector barely moved. The per-capita data says it shrank 7.2%. That's the difference between "no story" and "AI is displacing white-collar workers." The methodology matters as much as the visualization.


Quick Start

git clone https://github.com/ShameekConyers/sql_python_dashboard.git cd sql_python_dashboard python3 -m venv .venv .venv/bin/pip install -r requirements-dev.txt .venv/bin/streamlit run dashboard/app.py

No API key needed. The repo ships with a seed database containing all 10 series, COVID-adjusted values, and 9 verified AI insights. Everything works out of the box.

Tools: Python, SQL/SQLite, pandas, Plotly, pmdarima/statsmodels, Streamlit, FRED API, Ollama (llama3.1:8b)