Skip to content

Repository files navigation

Ethical Decision Simulator

Release CI License: MIT Audit Docker Streamlit

An ethical decision simulator for auditing how large language models reason through moral dilemmas — surfacing alignment risks, framework conflicts, and cross-model disagreement with structured, exportable outputs.

Educational tool: This app audits how LLMs reason through moral dilemmas — it does not provide moral guidance, legal advice, therapy, or crisis support. Model outputs may be incorrect; users are responsible for their own decisions.

Privacy (cloud demo): Dilemma text you enter is sent to Groq for inference when using the public Streamlit Cloud demo (or any cloud deployment with LLM_PROVIDER=groq). Do not submit classified data, credentials, PII, or sensitive organizational details you cannot share with Groq. Prefer curated scenarios or synthetic examples for testing. Session state is not written to a project database; see Privacy & data below.

Table of Contents
Section Description
Get started
🚀 Live Demo Try the live ethics audit demo (Cloud or local)
Features Capabilities at a glance
Quick Start Clone, install, run, test, Docker
Overview
🎯 Problem & Motivation Why auditable LLM ethics testing matters
🛠️ Tech Stack Languages, libraries, CI
📊 Data Sources & Attribution Scenarios and model licenses
📌 Version history Release highlights
Technical
🏗️ Architecture & Design Choices System design and pipeline
Full architecture doc Detailed system design (Mermaid)
Development Journey Capability pipeline diagram
🛡️ Safety Considerations Ethics, guardrails, and data privacy
🔄 CI/CD GitHub Actions, Docker, and deployment
📈 Project Status v1.0.1 capabilities
📁 Repository Layout File tree
Legal & contact
📄 License MIT License
🤝 Contact / Next Steps Feedback and V2 roadmap

🚀 Live Demo

▶ Open the live app on Streamlit Cloud

Before you open the app:

  • Cold start: This app runs on Streamlit Community Cloud and may go to sleep after inactivity. If you see “Zzzz — This app has gone to sleep due to inactivity”, click “Yes, get this app back up!” to wake it — anyone can do this; no special permissions required. Startup may take a minute after you click.
  • Privacy: The public demo sends dilemma text to Groq for inference. Do not enter classified data, credentials, PII, or sensitive details you cannot share with a third-party LLM API. Prefer curated scenarios or synthetic dilemmas. Session results stay in browser memory only — not stored in a project database. For local-only inference, run with LLM_PROVIDER=ollama (see Quick Start). Full details: Privacy & data.

Local demo: streamlit run app.py · Docker: docker compose up --buildhttp://localhost:8501

Screenshots

Explore — single-model ethical reasoning

Explore — structured verdict with creative alternatives, reasoning steps, and ethics primer. LLM-generated narrative text may differ by provider, model, and run.

Compare — multi-model audit

Compare — side-by-side model verdicts with semantic agreement metrics and optional JSON export. LLM-generated narrative text may differ by provider, model, and run.

✨ Features

  • Explore — single-model walkthrough with creative alternatives, reasoning steps, and ethics primers (on-screen results; no file export)
  • Compare — multi-model side-by-side audit with semantic agreement metrics
  • Framework stress test — utilitarian, deontological, and care-ethics lenses
  • Consistency test — rephrase variants to measure framing sensitivity
  • Export JSON (Compare) — download full metrics, runs, and consistency data after a multi-model comparison
  • Simulated mode — automatic fallback when API is unavailable (clearly labeled)

⚡ Quick Start

Prerequisites

Local setup

git clone https://github.com/rvong65/ethical-decision-simulator
cd ethical-decision-simulator
python -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txt
copy .streamlit\secrets.toml.example .streamlit\secrets.toml
# Edit secrets.toml — set GROQ_API_KEY
streamlit run app.py

Local Ollama profile:

$env:LLM_PROVIDER = "ollama"
streamlit run app.py

Docker

docker compose up --build
# Open http://localhost:8501

Optional: create a .env file with GROQ_API_KEY=your_key (never commit). Without a key, the app runs in Simulated mode.

Run tests

pytest tests/ -v --ignore=tests/test_api_integration.py   # 46 offline (matches CI)
pytest tests/test_api_integration.py -v -m api            # 3 live Groq smoke tests (local / optional)

See docs/architecture.md#deployment-topologies for local, Docker, and Streamlit Cloud details.

🎯 Problem & Motivation

AI systems do not share a single moral compass. When values conflict, models may disagree with each other, flip answers under slight rephrasing, or cite one ethical framework while reasoning like another. Teams deploying AI in sensitive domains need transparent, auditable ways to probe these behaviors — not a black-box “right answer.”

This project makes that visible: pick a dilemma, run one or more models, and inspect decisions, creative alternatives, reasoning chains, detected frameworks, and agreement metrics. It is an educational ethics auditing tool, not moral authority, legal advice, or a substitute for professional judgment.

🛠️ Tech Stack

Python Streamlit Groq Ollama Pydantic pytest Docker

Layer Technology
UI Streamlit (st.navigation, wide layout)
Cloud LLM Groq API (GPT-OSS 20B, GPT-OSS 120B)
Local LLM Ollama (gemma3:4b) — optional dev profile
Schemas Pydantic v2 structured verdicts
Analysis Semantic decision agreement, consistency scoring
Tests pytest — 46 offline + 3 API smoke tests
CI / Docker GitHub Actions + Dockerfile / docker-compose.yml

📊 Data Sources & Attribution

Curated dilemmas are original scenario text in src/scenarios/library.json, inspired by classic ethics thought experiments and applied AI ethics cases — not copied from proprietary datasets.

Cloud demo uses production Groq models only (preview/evaluation models are excluded).

Model Role License / acknowledgment
gemma3:4b (Ollama) Local dev LLM Gemma Terms of Use
openai/gpt-oss-20b (Groq) Cloud LLM — fast baseline OpenAI open-weight via Groq — Groq Terms
openai/gpt-oss-120b (Groq) Cloud LLM — high-reasoning tier OpenAI open-weight via Groq — Groq Terms

📌 Version history

Version Date Highlights
1.0.1 2026-07-13 Groq model migration: GPT-OSS 20B + 120B
1.0.0 2026-06-28 MVP: Explore/Compare, 12 scenarios, CI, Docker, docs

Full details: CHANGELOG.md

🏗️ Architecture & Design Choices

Dilemmas flow through scenario loading → crisis check → lens-aware prompts → resilient LLM inference → JSON parse/validate → agreement analysis → Streamlit presentation (Explore for single-model review; Compare for multi-model audit and optional JSON export). Mock fallback and crisis guardrails keep the tool usable and responsible without hiding simulation.

Full design — goals, end-to-end diagram, module map, deployment topologies (local / Docker / Streamlit Cloud), and architecture-level safety: docs/architecture.md

Key design decisions

Decision Rationale
Structured JSON verdicts Auditable, exportable, comparable across models
Semantic decision agreement Lexical match alone mislabels moral agreement (e.g. same “report” decision, different wording)
Forced ethical lenses Surfaces when models mislabel frameworks (alignment audit signal)
Creative alternatives first Separates engineering escape hatches from forced tradeoff analysis
Mock fallback with labels App stays usable when Groq rate-limits or API key is missing — never silent simulation
Crisis disclaimer Self-harm scenarios show 988 resources; app is not a crisis service
Docker + CI Reproducible local runs and automated quality gates on every push

Development Journey

Capability pipeline (Explore, Compare, metrics, and export). Full design: docs/architecture.md#development-journey.

flowchart LR
    A[Structured prompts<br/>JSON verdicts] --> B[Explore + Compare<br/>12 scenarios]
    B --> C[Framework stress<br/>consistency tests]
    C --> D[Responsible AI<br/>crisis · mock · lens warnings]
    D --> E[Streamlit UI<br/>indigo sidebar theme]
    E --> F[Semantic metrics<br/>structured export]
    F --> G[46 offline tests<br/>3 API smoke tests]
    G --> H[GitHub Actions CI<br/>Docker]
    H --> I[Streamlit Cloud deploy<br/>MVP]
Loading

🛡️ Safety Considerations

Principle Implementation
Educational use only Framed as an alignment auditing tool — not moral guidance, legal advice, therapy, or crisis intervention (home footer + README)
Transparency Structured JSON verdicts, labeled live vs mock runs, lens-adherence mismatch warnings
No warranty Disclaimers state LLM outputs may be wrong; users are responsible for their own decisions
Crisis safety Regex detector + prominent 988 / Crisis Text Line banner for self-harm-related dilemma text
Honest simulation Mock fallback on rate limits or API failure — always labeled Simulated mode, never silent
Data minimization Session-only state; no project database; Compare JSON export is a user-initiated download
Third-party inference Groq/Ollama terms apply; dilemma text sent only to configured LLM provider
Privacy awareness Cloud-demo privacy notice, in-app Privacy & data expander, README data-flow table

Privacy & data

Ethical Decision Simulator is designed for educational alignment auditing, not as a certified data-processing platform. Understand where your input goes:

Data you submit Where it may be sent Notes
Dilemmas (curated or custom) LLM provider (Groq on cloud demo, or local Ollama) Cloud: processed per Groq Terms and their privacy policy
Ethical lens & model settings Same LLM provider Included in the prompts sent for inference
Comparison & consistency runs Same LLM provider Each selected model receives the dilemma text
Session results & sidebar state Streamlit session memory Cleared when the session ends; not written to a project database by this app
JSON exports (Compare) Your browser only User-initiated download after a multi-model comparison

Public Streamlit Cloud demo: Treat it like any shared SaaS chat UI — no classified data, credentials, PII, or sensitive organizational details you cannot share with Groq. Prefer built-in curated scenarios or synthetic moral dilemmas for testing.

Sensitive environments: Run locally or in Docker with LLM_PROVIDER=ollama so inference stays on your network (requires local Ollama with gemma3:4b).

Note: This app does not intentionally log dilemma text to disk. Streamlit Community Cloud and Groq may retain operational or API logs under their own policies — review their documentation if compliance matters.

🔄 CI/CD

GitHub Actions runs on every push and pull request to main / master:

Job Step Action
offline-tests Trigger Push or PR to main / master
Environment ubuntu-latest, Python 3.11
Install pip install -r requirements.txt
Test pytest tests/ --ignore=tests/test_api_integration.py46 offline tests (parser, scenarios, semantic metrics, crisis guard, mock pipeline, LLM error mapping)
docker-tests Build docker build -t ethical-decision-simulator:ci .
Test Run 46 offline tests inside the container
Run docker compose up on port 8501 (no API key required — Simulated mode)
Health Streamlit /_stcore/health
api-smoke-tests Trigger Push to main only (after offline-tests pass)
Test pytest tests/test_api_integration.py -m api3 live Groq tests (skipped if GROQ_API_KEY secret unset)

Workflow file: .github/workflows/tests.yml

Releases: Version history in CHANGELOG.md. GitHub Releases are created manually when tagging (e.g. v1.0.0) — release notes may differ from the changelog.

No API keys required for CI gate — offline tests and the Docker job use fixtures and mocks only; Docker verifies the image builds, tests pass, and Streamlit responds.

API smoke tests require GROQ_API_KEY as a GitHub repository secret on main. Run them locally anytime with pytest tests/test_api_integration.py -m api.

Streamlit Cloud deploys independently from the main branch when connected to this repository (app.py + requirements.txt + Streamlit secret GROQ_API_KEY).

Docker locally:

docker compose up --build
docker run --rm ethical-decision-simulator:ci pytest tests/ -v --ignore=tests/test_api_integration.py

📈 Project Status

Current release: v1.0.1Streamlit demo · GitHub repo

Capability Included
Structured prompts + JSON verdict pipeline
12 curated scenarios + custom dilemmas
Explore (single-model) & Compare (multi-model audit)
Framework stress + consistency tests
Semantic agreement metrics + Compare JSON export
Crisis disclaimer + mock fallback
46 offline tests + optional API smoke tests
GitHub Actions CI + Docker

📁 Repository Layout

├── app.py                          # Streamlit navigation entry
├── Dockerfile                      # Production / CI container image
├── docker-compose.yml              # One-command local run
├── CHANGELOG.md                    # Version-by-version change history
├── pages/
│   ├── home.py                     # Landing + how it works
│   ├── explore.py                  # Single-model ethical reasoning
│   └── compare.py                  # Multi-model audit + export
├── src/
│   ├── config.py                   # Secrets bootstrap (no key values exposed)
│   ├── llm/                        # Groq / Ollama / mock / resilient provider
│   ├── ethics/                     # Framework prompts + parser
│   ├── scenarios/                  # library.json (12 dilemmas)
│   ├── analysis/                   # Agreement, consistency, export, semantic
│   ├── models/                     # Pydantic EthicalVerdict types
│   └── ui/                         # Theme, components, crisis, sidebar, glossary
│       ├── glossary.py             # In-app help: lenses, metrics, Compare modes
├── docs/
│   ├── architecture.md             # Full system design reference
│   ├── screenshots/                # README + GitHub social preview images
│   └── assets/                     # icon, favicon, logo (light/dark)
├── tests/                          # 46 offline + 3 API smoke tests
├── .github/workflows/
│   └── tests.yml                   # CI — offline, Docker, API smoke
├── .streamlit/
│   ├── config.toml                 # Theme (indigo sidebar)
│   └── secrets.toml.example        # GROQ_API_KEY template
├── requirements.txt                # App + Streamlit Cloud runtime deps
├── pytest.ini
└── LICENSE                         # MIT

📄 License

MIT License — see LICENSE.

🤝 Contact / Next Steps

Open to feedback, suggestions, and mission-aligned collaboration on responsible AI tooling.

V2 roadmap (planned)

Area Direction
Metrics Embedding-based semantic agreement (beyond keyword buckets)
UX Dedicated “alternatives-only” workshop mode before forced tradeoff analysis
Content Additional scenario packs (healthcare, policy, enterprise AI governance)
Analysis Multi-turn debate mode between models on the same dilemma
Data Persisted audit sessions (optional user export history)

About

Ethical Decision Simulator: audit how LLMs reason through moral dilemmas—multi-model compare, ethical lens stress tests, semantic agreement metrics, and exportable JSON verdicts. Python, Streamlit, Groq or Ollama—deployed on Streamlit Cloud.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages