Spaces:
Configuration error
FraudShield π‘οΈ
Production-grade OpenEnv environment for e-commerce fraud detection
FraudShield simulates real marketplace fraud review workflows. Agents inspect transactions and predict fraud/legitimate status, receiving dense rewards shaped by business impact, confidence calibration, and classification accuracy.
Key Features:
- β Real-world task (marketplace fraud detection)
- β Deterministic graders with 3 difficulty levels (easy β medium β hard)
- β Dense reward function (business-cost sensitive)
- β Frozen snapshot (reproducible, 108 cases)
- β Production-ready (Docker + FastAPI)
- β Baseline scores verified (0.8660 final score)
The environment is grounded in real public fraud data, but it does not fetch live records during reset() or step(). Instead, it uses a frozen, versioned snapshot stored in data/fraudshield_cases.json. That gives you real-world grounding with deterministic grading, fast Docker startup, and reproducible evaluation on Hugging Face Spaces.
Competition fit
FraudShield is designed around the Round 1 requirements:
- Real-world task: marketplace fraud review, not a toy environment
- OpenEnv interface: typed action, observation, reward, plus
reset(),step(), andstate() - Three graded tasks: easy, medium, hard
- Dense reward shaping: correctness, business impact, confidence calibration, and bad-action penalties
- Baseline inference: root
inference.py, OpenAI-client path for competition mode - Docker/HF Space target: FastAPI app on port
7860 - Reproducibility: frozen snapshot data and fixed seed
Current readiness status
What has been verified locally in this repo:
python inference.pypasses- API smoke checks for
/healthand/resetpass - The snapshot bundle loads correctly
- Python import/compile sanity passes
What still must be verified on a machine with the right tooling installed:
openenv validate openenv.yamldocker buildanddocker run- Hugging Face router path with a valid
MODEL_NAMEandHF_TOKEN - Final Hugging Face Space deployment ping
Note:
uv.lockis checked in so the OpenEnv validator accepts the project structure on this machine- If you have
uvinstalled, regenerate it withuv lockbefore final submission
Why this design
For an OpenEnv submission, the safest pattern is:
- Fetch or refresh public source data offline
- Build a deterministic FraudShield snapshot
- Commit the snapshot used for evaluation
- Keep the environment runtime fully offline
That avoids runtime API failures, privacy issues, and non-reproducible scores.
Real-world data strategy
FraudShield currently builds its snapshot from the public Kaggle / ULB credit card fraud dataset:
- Source ID:
kaggle_creditcardfraud - Dataset:
mlg-ulb/creditcardfraud - URL:
https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud
The loader is now source-agnostic in code:
data_loader.pyexposes a public-source snapshot pipelinedownload_kaggle_data.pyrefreshes the local source CSV and rebuilds the frozen snapshotfraudshield_env.pyreads the snapshot only at runtime
The checked-in snapshot currently reports:
- Snapshot ID:
fraudshield-realworld-v2 - Schema version:
2.0 - Seed:
42 - Task sizes: easy
24, medium36, hard48
Tasks
| Task | Cases | Goal | What makes it hard |
|---|---|---|---|
| Easy | 24 | Catch obvious fraud while avoiding basic false positives | Single-transaction red flags are strong and low-noise |
| Medium | 36 | Balance fraud capture with calibration | No single signal is decisive; tradeoffs matter |
| Hard | 48 | Handle coordinated abuse and edge-case legitimate traffic | Fraud rings and flash-sale behavior intentionally overlap |
Action space
Agents emit a single FraudCheckAction:
FraudCheckAction(
transaction_id: str,
decision: Literal["fraud", "legitimate"],
confidence: float, # 0.0 to 1.0
reasoning: str,
)
Observation space
Each step returns a FraudCheckObservation with:
- Structured transaction facts such as amount, seller age, buyer age, geo mismatch, rating, prior flags, chargeback rate, shared-device counts, and address velocity
- Historical context such as seller velocity, linked cards, refund counts, cluster alert score, and source snapshot metadata
- Task metadata including difficulty and episode step
Reward design
Rewards in fraudshield_env.py are dense and cost-sensitive:
- Correct fraud catches receive the strongest positive reward
- Correct legitimate approvals still earn positive reward, but less than catching fraud
- False negatives are punished more than false positives
- Confidence is rewarded when it matches hidden case difficulty and punished when it is overconfident
- Submitting the wrong
transaction_idadds an extra penalty
Graders
The three task graders in graders.py are deterministic and return scores from 0.0 to 1.0.
- Easy: accuracy, F1, recall, and specificity
- Medium: F1, ROC-AUC, precision, and confidence calibration
- Hard: recall, precision, F1, ROC-AUC, and calibration
Baseline inference
The required root script is inference.py.
- Competition mode: if
API_BASE_URL,MODEL_NAME, andHF_TOKENare set, it uses the OpenAI client against that endpoint - Local smoke-test mode: if those variables are missing, it falls back to a deterministic heuristic agent
- If those variables are set but invalid, the script now fails loudly instead of silently switching agents
Required environment variables for the competition path:
API_BASE_URL=https://router.huggingface.co/v1
MODEL_NAME=<your-model-id>
HF_TOKEN=<your-token>
If your Hugging Face Space rejects underscores in variable names, FraudShield also accepts these aliases:
APIBASEURL=https://router.huggingface.co/v1
MODELNAME=<your-model-id>
HFTOKEN=<your-token>
Run it with:
python inference.py
The script writes fraudshield_baseline_results.json to the project root.
Tested local baseline
I reran the baseline after the snapshot-loader changes. With the deterministic heuristic fallback and seed 42, the tested local scores are:
| Task | Score |
|---|---|
| Easy | 1.0000 |
| Medium | 0.8773 |
| Hard | 0.7206 |
| Final | 0.8660 |
Project layout
fraudshield/
|-- data/
| |-- fraudshield_cases.json
|-- server/
| |-- __init__.py
| `-- app.py
|-- data_loader.py
|-- download_kaggle_data.py
|-- Dockerfile
|-- fraudshield_env.py
|-- graders.py
|-- inference.py
|-- inference_llm.py
|-- llm_agent.py
|-- models.py
|-- openenv.yaml
`-- pyproject.toml
Quick Start
1. Installation
# Install dependencies
pip install -e .
# (Optional) For local data refresh
pip install -e ".[dev]"
2. Run Baseline Locally
# Heuristic agent (no API call)
python inference.py
# Expected output: fraudshield_baseline_results.json with score β 0.8660
3. Deploy with Docker
# Build
docker build . -t fraudshield:v0.2.0
# Run
docker run -p 7860:7860 fraudshield:v0.2.0
# Test
curl http://localhost:7860/health
4. Hugging Face Space Deployment
- Create Space on huggingface.co/spaces
- Select "Docker" runtime
- Connect your GitHub repository
- HF automatically detects Dockerfile and deploys
- Set environment variables (optional for LLM mode):
API_BASE_URL=https://router.huggingface.co/v1 MODEL_NAME=<your-model> HF_TOKEN=<your-token>
API Examples
Reset Environment
curl -X POST http://localhost:7860/reset \
-H "Content-Type: application/json" \
-d '{"task":"easy"}'
Submit Action
curl -X POST http://localhost:7860/step \
-H "Content-Type: application/json" \
-d '{
"transaction_id": "txn_001",
"decision": "fraud",
"confidence": 0.85,
"reasoning": "High risk indicators: new seller, price anomaly"
}'
Get Episode State
curl http://localhost:7860/state | jq .
Rebuilding Data Snapshot (Optional)
To refresh the frozen snapshot from the public Kaggle dataset:
pip install -e ".[data]"
python download_kaggle_data.py
Note: If data/creditcard.csv exists, the script rebuilds without re-downloading.
Setup
Install the project:
python -m pip install -e .
Running locally
Python API
from fraudshield_env import FraudShieldEnvironment
from models import DecisionEnum, FraudCheckAction
env = FraudShieldEnvironment(data_path="data", seed=42)
env.load_data()
reset_result = env.reset("medium")
action = FraudCheckAction(
transaction_id=reset_result.observation.transaction_id,
decision=DecisionEnum.LEGITIMATE,
confidence=0.62,
reasoning="Signals are mixed but seller history is reasonably stable.",
)
step_result = env.step(action)
print(step_result.reward.value, step_result.done)
FastAPI server
uvicorn server.app:app --host 0.0.0.0 --port 7860
Endpoints:
GET /healthPOST /reset?task=easy|medium|hardPOST /stepGET /stateGET /infoGET /tasks
Docker
Build and run:
docker build -t fraudshield .
docker run -p 7860:7860 fraudshield
The container listens on port 7860, which matches Hugging Face Docker Spaces expectations.
Validation checklist
Before submission:
python inference.py
openenv validate openenv.yaml
docker build -t fraudshield .
docker run -p 7860:7860 fraudshield
Then verify:
http://localhost:7860/healthPOST http://localhost:7860/reset?task=easy
What must stay private
Do not commit or publish:
HF_TOKENHFTOKENOPENAI_API_KEYAPI_KEYkaggle.json.env,.env.local, or any file containing real tokens- raw shell history or logs that include auth headers or tokens
Safe to keep public:
API_BASE_URLAPIBASEURLMODEL_NAMEMODELNAMEopenenv.yamlfraudshield_baseline_results.jsondata/fraudshield_cases.json
Notes
- Runtime uses the committed snapshot only
- Public source refresh is optional and intended for offline rebuilds
inference_llm.pyremains as a thin wrapper toinference.py