William McNulty

I build AI-enabled tools and check that they work.

I study Computer Science and Economics at the University of Virginia. My projects are software, data pipelines and workflow tools, and each one is measured against evidence before I trust it.

700+course documents converted into searchable notes
100%page-type accuracy on a hand-checked set
~200students I teach and review code for as a TA
3.6GPA, Computer Science and Economics

Projects

October 2026

Who Gets the Loan?

A fairness audit of the 1990 Boston mortgage-lending data, done two ways: the econometrics of the racial approval gap, and what a machine-learning model trained without race does by race. Results are associations after controlling for the variables recorded, with their limits stated first.

Pythonstatsmodelsscikit-learnEconometricsML fairnessGitHub Actions
Open the report  View the code
Read the brief

The problem

My econometrics course used this data for one problem set: a few regressions of loan approval on race and finances. I wanted to know how far the answer moves with what you control for, and whether a model that never sees race ends up treating applicants equally.

What I built

  • Linear probability, probit and logit models with marginal effects, a ladder of controls, race interactions and an Oaxaca-Blinder decomposition of the gap.
  • Approval models trained without race, measured for demographic parity, equalized odds and calibration by group, plus how much race the other inputs carry.
  • Mitigation trade-offs and a label-bias what-if, since the "approved" label is the decision being audited.

What it found

White applicants were approved 90.8% of the time and Black or Hispanic applicants 70.8%. About 63% of that gap isn't accounted for by the recorded finances and credit histories, which fits discrimination but also things the files don't record. A model trained without race kept a 21-point gap.

How I tested it

The course's models reproduce the instructor's Stata output to every printed digit (81 of 81 numbers), the fairness metrics are tested against hand-worked cases, and every push rebuilds the results and fails if they drift.

September 2026 · live, refreshed daily

Virginia Data Center Tracker

A statewide map of every data center Virginia's Department of Environmental Quality has on record, planned, under construction or operating. Search around a ZIP code, a school, or a pin on the map. Built from official records only, and every dot links back to its state record.

PythonJavaScriptMapLibreGeospatial dataGitHub Actions
Open the live map  View the code
Read the brief

The problem

My mom noticed three data centers going up within a mile of my little brother's middle school in about six months, and our family had no idea any of them were coming. The existing maps rely largely on community reports, so they aren't pulling from the best data.

What I built

  • A pipeline that pulls DEQ's daily air-permit records (every data center needs one for its backup generators), names each site's county or city, and adds permit dates.
  • Search by ZIP code, school (all 2,159 Virginia public schools, matching the names people actually use) or a pin, within 1 to 30 miles. It all runs in the browser, so nothing a visitor types leaves their device.
  • A daily automated refresh that refuses to publish if a source comes back broken.

What it found

Four data centers are within a mile of my brother's school, two of them still planned. Across Virginia, DEQ issued 44 data center air permits in 2026 through September, up from 34 in all of 2025.

How I tested it

Tests check that the browser's distance math matches the Python pipeline to a millionth of a mile, that "Rachel Carson" finds the school the federal data calls "Carson Middle", and that the build stops on bad data. Where two official sources disagree on a site's locality, the map shows both.

2026 to present · in progress

UVA Knowledge Network

A private, locally hosted pipeline that turns coursework (PDFs, slides, spreadsheets, class recordings) into structured, searchable notes, using local models so course material never leaves my machine.

PythonLocal vision-language modelsOCRBM25 searchEvaluation sets
Read the brief

The problem

Ten courses of material sat in scattered formats, so finding how one idea connected across classes meant re-reading everything.

What I built

  • Converters for PDFs, slide decks, spreadsheets and video transcripts into markdown with metadata (700+ documents across 10 courses).
  • An image workflow where a local vision-language model classifies each page as a graph, diagram, table or text and describes the figures.
  • Automated experiment loops that benchmark model, prompt and image-size variants against a hand-checked set and adopt a change only when it wins.
  • A keyword search prototype over 7,000+ text chunks, the foundation for question answering across courses.

How I tested it

I labelled a 19-page set by hand and scored every variant against it. Page-type accuracy rose from 71% to 100% once the prompt asked for the page type on its own line. The table shows the leaderboard from one report.

VariantQuality scoreRelative to 0.80 to 1.00
4B model, integrated GPU (adopted)0.947
9B model0.952
9B model, integrated GPU0.944
4B model, prompt v4 (baseline)0.932
Prompt v6 (handwriting line)0.929
Prompt v5 (adds text-page type)0.883

Bars are drawn from 0.80 to 1.00 so the differences are visible. Prompt v5 looked reasonable but lowered the score because it broke slides that mix figures and text, so I did not adopt it.

What I learned

Several apparent model failures were really bugs in my own scoring code. I now read the raw outputs before I trust a metric.

The code and data are private because they contain coursework. Next up: retrieval agents that answer questions across courses.

September 2026

UVA Capital Plan Tracker

An interactive look at six years of the University of Virginia's public capital plans: where the money comes from, how 94 projects' budgets changed from plan to plan, and what moves a project's net present value.

PythonJavaScriptData pipelineFinancial modelingGitHub Actions
Open the live site  View the code
Read the brief

The problem

UVA publishes its capital plan every year, but each year's tables use a different layout and projects change names between years, so following one project's budget over time is hard.

What I built

  • A parser that turns six years of plan PDFs into one table of 286 project rows, each reconciling to the dollar.
  • Linking that follows each project through renames: exact and fuzzy name matching plus hand-checked overrides.
  • The cash-flow model from my real estate course (NPV, IRR), with sliders for overruns, delays and growth rates.

What I found

State funding fell from 26% of the plan to about 10% while debt rose to a 58% peak. Of 64 projects with more than one budget, 23 grew, by a median of 17%.

How I tested it

The model reproduces my course's worked example to the dollar, the browser version matches the Python version on 26 cases, and every push retests the site before it deploys.

September 2026 to present

Job-Application Tracker

A local dashboard that tracks every application through defined statuses with deadlines, a follow-up queue and drafted follow-up emails. The demo runs entirely in your browser on made-up sample data.

Python standard libraryJavaScriptUnit testsVersion-controlled data
Open the live demo
Read the brief

The problem

I was managing more than 50 applications, each with its own deadline, requirements and follow-up date. Notes in scattered documents were not going to hold.

What I built

  • A Python API and a single-page front end that saves every change to a JSON file I can review in git.
  • Forms that reject invalid dates, scores and statuses.
  • Views for what needs attention now: submissions to confirm, follow-ups due and upcoming deadlines.
  • Controls against cross-site and DNS-rebinding requests: loopback-only binding, Host checks and JSON-only writes.

How I tested it

Automated unit tests cover validation, saving and the request checks. I built it with AI coding assistants and reviewed their work through the tests, which caught a date-validation bug that would have dropped connections.

The real tracker holds personal application data, so its repository is private. This demo uses invented companies.

June 2026 to present

Fraternity Operations Platform

One chat platform and membership database that replaced communication scattered across three apps, with workflows for reporting and approvals.

PythonFastAPIPostgreSQLDocker
Read the brief

The problem

Announcements were missed and there was no single, reliable record of members, because everything lived in Flare, Snapchat and GroupMe.

What I did

I gathered requirements from members, built the platform and released it in small steps. Members raised concerns about cost, time to adopt and design, and I addressed them by prioritizing their feedback.

The result

Other brothers now contribute to the project, it supports alumni connections, and the membership database is being extended to help manage house access.

The platform holds member data, so it is private and there are no screenshots here.

Background

University of Virginia

B.A. Computer Science and B.A. Economics, expected May 2028. Industrial Organization concentration, Real Estate minor. Dean's List, Spring and Fall 2025.

Teaching assistant

CS 3140, Software Development Essentials, since August 2026: design and programming reviews and teaching for about 200 students.

Associate Consultant

Aegis Cyber Solutions, since March 2023: comparative analyses of emerging AI technologies, turned into executive-facing recommendations.

Undergraduate researcher

Quantitative research with UVA faculty and World Bank researchers, supporting evidence-based policy analysis.

Beyond the code

Security Manager, Boylan Heights

Since March 2025, I lead daily operations for a team of 40+ at a bar: staffing, scheduling, communication and accountability, plus procedures that improve incident response.

Alpha Tau Omega, Delta Chapter

I joined the Delta Chapter of ATO at UVA in Spring 2025 and have served as philanthropy chair and membership educator. I also built the chapter's operations platform, one chat system and membership database that replaced three scattered apps (see the projects above).

Contact

Email me at willmcnultycontact@gmail.com, or find me on LinkedIn and GitHub. My resume is a one-page PDF.