ML for Business · Proof of Skill

An AI agent that turns
raw business data into
clear decisions

Built by samuel harrington to show how a large language model can help a senior health insurer decide which members need care first, plus three other business tools. It runs on a free, open-source model behind a Flask backend.

Checking agent…
⚡ Simpson College · Indianola, IA
Ollama · open-source LLM
HTML · CSS · JS · Flask

🌩️

Simpson College — The Storm

Indianola, Iowa · Founded 1860 · CIS Program · Computer Information Systems

Businesses generate enormous volumes of unstructured data — customer reviews, meeting notes, KPI sheets, market reports. Traditional ML requires labeled datasets, compute infrastructure, and training time. The insight driving this project: a pre-trained large language model handles language understanding out of the box. The engineering work becomes task definition and prompt architecture, not model training.

This project demonstrates four core business ML capabilities that would otherwise require four separate models, four data pipelines, and months of labeled training data.

Selected an open-source model served by Ollama (Llama 3.2 by default) instead of a paid API. Three reasons: it costs nothing per request, anyone can run it on their own hardware, and sensitive inputs never leave the server. The trade-off is that smaller models follow instructions less reliably than frontier models, so the prompts are short, explicit, and structured, and the model can be swapped with one environment variable.

# Core model call: Flask streams Ollama's response to the browser
requests.post("http://localhost:11434/api/chat", stream=True, json={
    "model":    OLLAMA_MODEL,        # e.g. "llama3.2:3b"
    "stream":   True,
    "messages": [
        {"role": "system", "content": PROMPTS[module]},  # role + output format
        {"role": "user",   "content": user_input},
    ],
    "options":  {"temperature": 0.3, "num_predict": 800},
})

Each business capability is powered by a dedicated system prompt. This is the real engineering work in an LLM-based system: scoping the agent's role, defining input expectations, and specifying the output structure. A well-engineered prompt produces consistent, structured outputs without any model training or labeled data.

# Senior health risk scanner — system prompt architecture
"You are a senior-health risk analyst for a health insurer
covering members aged 65 and older.

RISK TIER: [Low / Moderate / High / Critical] - why.
TOP RISK DRIVERS: 4 drivers, each with likelihood and impact.
COST AND CLAIMS PAIN POINTS: where avoidable cost is likely.
CARE MANAGEMENT OPPORTUNITIES: 3 interventions and their benefit.
COMPLIANCE NOTE: supports outreach, not coverage or pricing.
NEXT STEPS: 3 actions for the care team this week.

Use only facts from the input. If not stated, say so."

Built four independent modules targeting the most common business ML use cases. Each module has its own system prompt, example inputs, and interface panel. They share one API integration layer — demonstrating that a single well-architected LLM integration can power multiple specialized business functions.

Sentiment Analysis — customer feedback → scored sentiment, themes, action items
Report Generator — raw data/notes → structured executive summary
Senior Health Risk Scanner — member profile or member group → risk tier, cost pain points, care-management moves (the featured demo)
KPI Narrativ e — raw metrics → plain-English story for stakeholders

Built zero-dependency — HTML, CSS, vanilla JavaScript. Tabbed navigation, streamed model responses with loading states, live error handling, and full mobile responsiveness. No framework needed at this scope. Styled in Simpson College's official Red and Gold to make it feel like a project that belongs here — the color palette reflects my school and my home.

State is managed in plain JS. Each capability runs independently, preserving inputs and outputs across tab switches.

The browser never talks to the model directly. It posts a module name and some text to Flask, which holds the prompts, validates the request, rate-limits each visitor, caps how many generations run at once, and streams the answer back from Ollama running on localhost. That keeps the model port private and the demo free for anyone to use.

Next steps for a real deployment: authentication, response caching, an audit log, and connecting the agent to claims and enrollment data instead of pasted text.

# Flask route: the only thing the browser can reach
@app.post("/api/analyze")
def analyze():
    body = request.get_json(silent=True) or {}
    if body.get("module") not in PROMPTS:       # known modules only
        return jsonify(error="Unknown module."), 400
    if rate_limited(request.remote_addr):        # 6 requests per IP per minute
        return jsonify(error="Too many requests."), 429
    if not _slots.acquire(blocking=False):      # cap simultaneous runs
        return jsonify(error="Agent is busy."), 503
    return Response(stream_with_context(stream_from_ollama(...)),
                    mimetype="text/plain")

Members 65 and older use more care than any other group, and a small share of them account for a large share of claims. Most of that cost builds up quietly before it becomes a crisis. These are the problems the risk scanner is built around.

Preventable readmissions

A hospital discharge without follow-up often ends in a return trip. Every avoidable readmission is a large claim and a worse outcome for the member.

Falls

One fall can mean surgery, rehab, and a long decline. Many are preventable with a medication review and a few changes at home.

Too many medications

Members on many drugs from several prescribers face interactions that nobody is watching across the whole list.

Chronic conditions slipping

Diabetes, heart failure, and COPD cost far less when managed steadily and far more after a crisis. Missed appointments are the early warning.

Isolation and access

Members who live alone, lose transportation, or stop going to appointments often show up in claims only after something goes wrong.

Too many members, too few nurses

Care teams can't call everyone. They need a ranked list of who to call first and why.

The scanner below turns a plain-language description into that ranked, explained starting point.


Describe one senior member or a group of members. The agent rates the risk, names the cost problems it expects, and suggests which care-management steps to take first.

Try an example:

Demo only. Use fictional scenarios and don't enter real member or patient information. Results are not medical advice and shouldn't drive coverage or pricing decisions.

Senior Health Risk Scan

Paste customer feedback, reviews, or survey responses. The agent identifies overall sentiment, key themes, pain points, and action items for the business team.

Sentiment Analysis

Enter raw data points, bullet notes, or meeting minutes. The agent produces a polished executive business report ready for stakeholder review.

Executive Report

Paste a list of KPIs and metrics. The agent writes a plain-English narrative explaining what the numbers mean and where leadership should focus.

KPI Narrative

⌨️

User Input

Business data — feedback, metrics, notes — entered via the browser. No preprocessing, database, or login required.

🧠

Prompt Layer

A task-specific system prompt defines the agent's role, output format, and tone. It lives on the server, so visitors can't change it.

🔌

Flask + Ollama

Flask validates the request and streams it to an open-source model running on the same server. No API key and no per-call cost.

📊

Structured Output

The response streams into the output panel as the model writes it. In production, this parses to JSON and feeds dashboards or downstream tools.

API Integration Prompt Engineering Agent Architecture JavaScript async/await HTML & CSS LLM System Design UI/UX Design Python / Flask Ollama / Open-Source LLMs Streaming Responses Rate Limiting Error Handling Business Intelligence