Skip to content

amois3/yield_monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Yield Monitor

A web-based Yield Monitor dashboard for manufacturing test data, built with FastAPI and SQLite. It shows live testing volume, part-number distribution and per-part yield, lets you enter test results manually, exposes a small natural-language chatbot, and ships with an end-to-end Selenium test.

Yield = (Passed Units / Total Tested Units) × 100 e.g. 3 passed out of 5 tested = 60%


Features

  • FastAPI backend with a clean REST API and auto-generated Swagger docs.
  • SQLite storage via the standard library (no DB server to install).
  • Single-page dashboard with three panels:
    • A – Daily Testing Volume — bar chart of units tested over the last 7 days.
    • B – Part Number Distribution — doughnut/pie chart; click a slice (or the legend row) to select a part number.
    • C – Yield Gauge — circular gauge for the selected part; colour-coded green ≥ 90%, yellow ≥ 80%, red < 80%.
  • Manual Testing form (modal) with serial number, part-number dropdown, a live timestamp clock and a Pass/Fail checkbox.
  • Header buttons: Manual Test, View API (opens /docs), View Script (shows test_yield.py).
  • Yield chatbot — LLM-powered (OpenRouter), answers plain-English questions grounded in the live data (POST /chat).
  • Selenium test that validates the 60% yield scenario end-to-end.

Project structure

yield_monitor/
├── main.py                 # FastAPI app entry point (routes, chatbot)
├── database.py             # SQLite connection, schema and queries
├── templates/
│   └── index.html          # Dashboard frontend (Chart.js)
├── static/
│   └── test_yield.py       # Selenium script (served to the "View Script" button)
├── test_yield.py           # Selenium script (run this one)
├── .env.example            # Template for the chatbot API key
├── requirements.txt
└── README.md

API endpoints

Method Path Description
POST /tests Insert a new test record
GET /tests Return all test records (newest first)
GET /stats Per-part-number yield statistics
GET /daily Daily unit count for the last 7 days
POST /chat Natural-language question → answer
GET /docs Swagger UI (built into FastAPI)

POST /tests body

{ "serial_number": "SN-001", "part_number": "001PN001", "status": true }

timestamp is set on the server at insert time; status is true = Pass.


Run locally

Requires Python 3.10+ and Google Chrome (for the Selenium test).

# 1. create a virtual environment
python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

# 2. install dependencies
pip install -r requirements.txt

# 3. configure the chatbot LLM (OpenRouter)
cp .env.example .env
#    then edit .env and set OPENROUTER_API_KEY=sk-or-v1-...

# 4. start the server
uvicorn main:app --reload

# 5. open the dashboard
#    http://localhost:8000
#    API docs: http://localhost:8000/docs

The SQLite database file yield_monitor.db is created automatically on first run. The chatbot needs an OPENROUTER_API_KEY; without one the dashboard and all other endpoints still work and the chatbot falls back to keyword matching.


Run the Selenium test

With the server running in one terminal:

source .venv/bin/activate
python test_yield.py

The test opens the dashboard, adds 5 records for 001PN001 (3 pass / 2 fail), selects that part number and asserts the gauge reads 60%, printing PASS or FAIL with the actual vs expected value. It runs Chrome headless, so no visible browser window is needed.


Chatbot

The POST /chat endpoint is LLM-powered with tool calling. The model (via OpenRouter, default openai/gpt-4o-mini, configurable with CHAT_MODEL) interprets the question and calls tools; every count and yield is computed in Python (get_yield_stats, list_daily_breakdown) against the database, never by the model's own arithmetic — so the figures are always exact. This lets it answer anything derivable from the data: a specific part, a specific day, a date range, best/worst day, trends, and so on. Questions that aren't about the system's testing/yield data get a friendly refusal.

If OPENROUTER_API_KEY is unset or the API call fails, /chat falls back to a deterministic keyword matcher so the chat keeps working offline during a demo.

Example questions:

  • "What is the yield for part 001PN001?"
  • "What was the yield from 07.01 to 07.04?"
  • "How many units of 001PN001 were tested on 2026-07-02?"
  • "Which day had the highest yield?"
  • "How many units were tested today?"

Deployment

The app is a standard FastAPI ASGI application and runs anywhere that supports Python (Replit, Render, Railway, PythonAnywhere). Set the OPENROUTER_API_KEY environment variable on the host (and optionally CHAT_MODEL). Generic start command:

uvicorn main:app --host 0.0.0.0 --port $PORT

Deploy on Replit (recommended)

  1. Create the Repl from GitHub — on replit.com: Create Repl → Import from GitHub → this repository. Replit reads the included .replit / replit.nix and installs requirements.txt automatically.
  2. Add the API key as a Secret — open the Secrets (🔒) tab and add OPENROUTER_API_KEY = your OpenRouter key. (Do not put it in .env on a public Repl; Secrets are the safe place.) Optionally add CHAT_MODEL. Add SEED_DEMO = 1 to auto-populate a sample dataset on startup so the deployed dashboard and chatbot have data to show (see below).
  3. Run / Deploy — press Run to test, then Deploy (Autoscale) to get a public *.replit.app URL the evaluator can open with no local setup.

The Selenium test is not run on the server — it's a local QA script that drives the deployed (or local) dashboard from your machine.

Sample data (SEED_DEMO)

A fresh deployment starts with an empty database. Set the env var SEED_DEMO=1 to have the app populate a deterministic sample dataset on startup (only when the table is empty): ~155 records across the last 7 days and all three part numbers, with distinct yields so the gauge shows every colour band (001PN001 ≈ 93%, 002PN002 = 76%, 003PN003 ≈ 87%).

SEED_DEMO is intentionally left unset locally so the Selenium test runs against a clean database and produces exactly 60% for the 001PN001 scenario.


Design notes

  • SQLite + stdlib keeps the project dependency-light and instantly runnable; status is stored as INTEGER (0/1) since SQLite has no native boolean.
  • /stats and /daily always return a complete set of part numbers / 7 days (zero-filled) so the charts have stable categories even with little data.
  • The Selenium script targets stable element IDs and clicks the legend row to select a part number, which is far more reliable than clicking a pixel on a <canvas> slice (the canvas slice is also clickable in the UI).
  • The chatbot uses grounded generation: live data is injected into the prompt and the model is constrained to answer only from it. The API key is read from the environment (.env, gitignored) and never committed.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors