Second Opinion

Dashboard

A local browser-based workspace for exploring wastewater readings and reviewing precomputed anomaly flags. The interface supports English and Dutch, light and dark themes, a searchable plant selector, a review queue, 28-day history and an optional Claude explanation. It is a small Python server with a plain JavaScript frontend.

What you need #

Start the dashboard #

  1. From the repository root, start the server:

    python dashboard/server.py
    

    On Windows, use py -3 dashboard/server.py if python is unavailable.

  2. Open http://127.0.0.1:8518. The server listens only on this computer.

  3. Results folder and Plant catalogue folder are prefilled with data/tai/pipeline and data/tai/extracted. Change them if your outputs live elsewhere (for example data/tai/pipeline_smoke30 after a smoke run), or clear the catalogue field if you have no extracted export. Relative paths resolve from the repository root. Click Connect results.

  4. Wait for indexing to finish. Search or select a plant, select a measurement and date range, then open a flagged reading to see its evidence and history.

Stop the server with Ctrl+C. Leave the terminal open while using the app.

Expected results layout #

Select the parent folder of the metric folders, not a single metric folder. Each available metric needs matching completed files, for example:

data/tai/pipeline/
  forest_ammonium/
    run_info.json
    scored_records.csv.gz
  history_ammonium/
    run_info.json

The same pattern applies to the other metrics: influent_volume, oxygen, nitrate, suspended_solids and temperature. A metric without valid matching result files is unavailable. The catalogue can list plants that do not have scored readings.

The server validates the measurement name, required fields, completion markers and provenance, and checks that eligible forest flags agree with the run's recorded threshold; a metric that fails is not shown. Missing, invalid and ineligible results are shown as not assessed, never as normal. The interface performs no model inference and never loads pickle or joblib files.

The dashboard reads a local SQLite index at data/tai/second_opinion_web_index.sqlite. A full python src/pipeline.py run builds it as its last stage, using this server's own build_index; you can also build it alone with python src/dashboard_index.py --results data/tai/pipeline --catalog data/tai/extracted. If the index is missing or out of date for the selected results, the first connection builds it, which can take time for large result sets. Later connections reuse unchanged results. The index contains derived partner data: keep it private and out of Git. If it is read-only, the app can reuse matching completed entries, but new or changed results need a writable index.

Views #

Optional: enable Claude #

Set your key in the same terminal before starting the server. In PowerShell, this prompt hides the input:

$secureKey = Read-Host -Prompt 'Claude API key' -AsSecureString
$keyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureKey)
try {
    $env:ANTHROPIC_API_KEY = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($keyPointer)
} finally {
    [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($keyPointer)
}
python dashboard/server.py

Optionally set ANTHROPIC_MODEL before starting; the default is claude-sonnet-5-5. Never paste a key into source code or commit it. If a key was exposed, revoke it and use a new one.

Open a flagged case, enter your question, confirm you are authorised to share the case, and click Ask Claude. The selected evidence and question are sent to Anthropic; the full dataset and source provenance are not sent, and the API key stays on the backend. No request is made automatically. Claude can make mistakes, so check its answer against the displayed evidence.

Troubleshooting #

Tests #

From the repository root:

python -B -m unittest discover -s dashboard -p "test_*.py" -v
node --test dashboard/test_assistant_ui.cjs
node --check dashboard/app.js

Tests use fictional fixtures and check the implementation's behaviour, not its operational accuracy.

Limitations #

The dashboard shows historical, provisional results, not live alerts or confirmed faults. A flag prompts investigation; the model inputs do not establish a cause or an operational limit. Scores from different models should not be compared. Retain and share TAI data only with the necessary permission.

Possible next steps: grouped cases, a combined review budget across metrics, persistent review feedback, and validating wording and translations with operators.

Choose an AI provider #

The case explanation panel supports Claude (Anthropic), GPT (OpenAI) and Grok (xAI). Select a provider, enter an API model ID available to your account, and enter its API key in the password field. Confirm permission to share the selected case with that provider, then click Ask. This is manual explanation, not model training or anomaly detection. Provider API charges may apply.

Entered keys travel only to the loopback server and selected provider. They are not written to disk, SQLite, logs or browser storage, and the input is cleared when sent. Changing providers clears the input and resets consent. As an alternative, configure ANTHROPIC_API_KEY / ANTHROPIC_MODEL, OPENAI_API_KEY / OPENAI_MODEL, or XAI_API_KEY / XAI_MODEL on the server. Environment keys are never returned to the browser. Leave the key field blank to use that provider's server configuration. Claude retains its existing server default; GPT and Grok require an explicit model ID or model environment variable.

Only fixed official API endpoints are supported. OpenAI uses Responses with store=false; xAI uses Chat Completions; Anthropic uses Messages. Provider data policies still apply. Only selected evidence and the question are transmitted; source-file paths and source-row fields are excluded. Local evidence remains available if a provider fails. Restart the Python server after updating backend code. Tests mock all provider calls; no live credentials or partner data are used.

Edit this page on GitHub ↗

Second Opinion · Built for TAI / Z-infoBack to top ↑