kloyaa/risk-assessment-system
GitHub: kloyaa/risk-assessment-system
结合规则引擎与 XGBoost 机器学习的实时金融交易欺诈检测平台,提供风险评分、自动决策和监控仪表板。
Stars: 0 | Forks: 0
# 风险评估系统 (RAS)
用于金融交易的实时欺诈检测平台。结合基于规则的启发式方法与 XGBoost ML 模型,生成风险评估、批准/拒绝决策以及实时仪表板警报。
## 架构
```
┌─────────────────────────────────────────────────────────────┐
│ SvelteKit Frontend (port 3000) │
│ Dashboard · Transactions · Labels · ML · Settings │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP + WebSocket
┌──────────────────────────▼──────────────────────────────────┐
│ FastAPI Backend (port 8000) │
│ │
│ POST /api/v1/transactions/assess │
│ ├─ Rule engine (velocity · amount · device/IP blocklist)│
│ └─ XGBoost ML (32 features, trained on labeled data) │
│ combined = 0.40 × rule_score + 0.60 × ml_score │
│ │
│ POST /api/v1/ml/train — trigger training │
│ POST /api/v1/ml/simulate — generate dataset │
│ POST /api/v1/ml/upload-dataset — upload CSV/JSONL │
└──────┬───────────────────────────────────────┬──────────────┘
│ asyncpg │ redis.asyncio
┌──────▼──────────┐ ┌─────────▼──────────────┐
│ PostgreSQL 16 │ │ Redis 7 │
│ Transactions │ │ WebSocket pub/sub │
│ Labels │ │ Training lock │
│ Risk scores │ └────────────────────────┘
│ API keys │
│ Settings │
└─────────────────┘
```
**风险等级:**
| 分数 | 等级 | 操作 |
|-------|-------|--------|
| 0.00 – 0.35 | 低 | 批准 |
| 0.35 – 0.70 | 中 | 批准 — 标记为人工审核 |
| 0.70 – 1.00 | 高 | **拒绝** |
任何高严重性 (HIGH) 规则都会强制拦截交易,无论综合得分如何。
## 快速开始
**要求:** Docker Desktop(包含 Compose v2)或 Docker Engine + Compose 插件。
```
git clone
cd risk-assessment-system
cp .env.example .env
```
编辑 `.env` — 至少设置以下内容(出于安全考虑必须设置):
```
SECRET_KEY=
ADMIN_PASSWORD=
HASH_SECRET=
```
启动所有服务:
```
docker compose up --build
```
首次启动时,后端会打印您的 API key:
```
docker compose logs backend | grep "FIRST API KEY"
```
| 服务 | URL |
|---------|-----|
| 仪表板 | http://localhost:3000 |
| API 文档 (Swagger) | http://localhost:8000/docs |
| 健康检查 | http://localhost:8000/health |
## 环境变量
将 `.env.example` 复制到 `.env`。以下所有变量都可以在那里或通过环境变量进行覆盖。
### 安全(生产环境中必需)
| 变量 | 描述 | 生成方法 |
|----------|-------------|-----------------|
| `SECRET_KEY` | 签署 JWT token | `python -c "import secrets; print(secrets.token_hex(32))"` |
| `ADMIN_PASSWORD` | 仪表板管理员登录密码 | 任何强密码 |
| `HASH_SECRET` | 用于账号哈希的 HMAC 密钥 | `python -c "import secrets; print(secrets.token_hex(32))"` |
| `ALLOWED_ORIGINS` | 逗号分隔的允许 CORS 来源 | `https://dashboard.yourdomain.com` |
| `ENV` | 设置为 `production` 以在存在不安全默认值时快速失败 | `production` |
### 数据库
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `POSTGRES_USER` | `ras` | PostgreSQL 用户 |
| `POSTGRES_PASSWORD` | `raspassword` | PostgreSQL 密码 — 请在生产环境中更改 |
| `POSTGRES_DB` | `ras_db` | 数据库名称 |
### 应用程序
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `DEBUG` | `false` | 启用 debug 级别日志记录 |
| `FIRST_API_KEY` | _(自动生成)_ | 覆盖初始化生成的 API key |
| `TRAINING_N_JOBS` | `2` | XGBoost CPU 线程数(`-1` = 所有核心,在共享主机上请避免使用) |
| `RATE_LIMIT_ASSESS_PER_MINUTE` | `120` | 每个 API key 每分钟最大 `/assess` 调用次数 |
| `MODEL_DIR` | `/app/ml_models` | 容器内的模型存储路径 |
### 前端(Vite 构建时,非机密)
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `VITE_API_BASE_URL` | `http://localhost:8000` | 浏览器所见的后端 URL |
| `VITE_WS_BASE_URL` | `ws://localhost:8000` | WebSocket URL |
## Docker 参考
### 开发模式(默认)
后端(`uvicorn --reload`)和前端(Vite HMR)均支持实时重载:
```
docker compose up # starts all services
docker compose up --build # rebuild images first (after dependency changes)
```
源文件通过 `develop.watch` 同步 — 保存文件后更改即刻生效,无需重新构建。
### 监视模式(依赖项变更时自动重新构建)
```
docker compose watch
```
当 `requirements.txt` 或 `package.json` 更改时,自动重新构建受影响的服务容器。
### 生产环境
```
# 将生产环境值放入 .env,然后:
docker compose up --build -d
```
当 `ENV=production` 时,如果 `SECRET_KEY`、`ADMIN_PASSWORD` 或 `HASH_SECRET` 保留不安全的默认值,后端将拒绝启动。
### 常用命令
```
docker compose logs -f backend # stream backend logs
docker compose logs -f # all services
docker compose ps # service status
docker compose down # stop + remove containers (volumes preserved)
docker compose down -v # full reset — deletes all data
```
### ML 模型持久化
训练后的模型存储在命名的 Docker 卷中(`ml_models → /app/ml_models`)。它**可以在重启和镜像重建中保留**。只有 `down -v` 会删除它。
备份模型卷:
```
docker run --rm \
-v risk-assessment-system_ml_models:/data \
-v $(pwd):/backup \
alpine tar czf /backup/ml_models_backup.tar.gz -C /data .
```
恢复:
```
docker run --rm \
-v risk-assessment-system_ml_models:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/ml_models_backup.tar.gz -C /data
```
## API 集成指南
### 认证
每个请求都需要 `X-API-Key` 标头:
```
X-API-Key: your-api-key-here
```
### 评估交易
```
POST /api/v1/transactions/assess
Content-Type: application/json
X-API-Key:
```
**最小请求:**
```
{
"transaction_id": "TXN-20241115-001",
"timestamp": "2024-11-15T14:30:00+08:00",
"amount": 15000.00,
"currency": "PHP",
"sender_account": "1234567890",
"receiver_account": "0987654321",
"transaction_type": "transfer",
"channel": "mobile"
}
```
**完整请求(推荐 — 设备和 IP 可提高 ML 准确率):**
```
{
"transaction_id": "TXN-20241115-001",
"timestamp": "2024-11-15T14:30:00+08:00",
"amount": 15000.00,
"currency": "PHP",
"sender_account": "1234567890",
"receiver_account": "0987654321",
"transaction_type": "transfer",
"channel": "mobile",
"is_international": false,
"location_country": "PH",
"merchant_category_code": "6012",
"device_fingerprint": "chrome-win10-abc123",
"ip_address": "192.168.1.100",
"extra_fields": {
"bank_reference": "BPI-2024-XYZ",
"branch_code": "BGC001"
}
}
```
**字段参考:**
| 字段 | 必填 | 值 |
|-------|----------|--------|
| `transaction_id` | 是 | 每笔交易的唯一字符串 |
| `timestamp` | 是 | 带时区的 ISO 8601 格式 |
| `amount` | 是 | 正数 |
| `currency` | 是 | ISO 4217(`PHP`、`USD` 等) |
| `sender_account` | 是 | 原始账号 — 存储前进行哈希处理 |
| `receiver_account` | 是 | 原始账号 — 存储前进行哈希处理 |
| `transaction_type` | 是 | `transfer` `payment` `withdrawal` `deposit` `purchase` `refund` |
| `channel` | 是 | `online` `mobile` `atm` `branch` `pos` `api` |
| `device_fingerprint` | 否 | 原始设备 ID — 后端对其进行哈希处理 |
| `ip_address` | 否 | 原始 IP 地址 — 后端对其进行哈希处理 |
| `is_international` | 否 | 布尔值,默认为 `false` |
| `location_country` | 否 | ISO 3166-1 alpha-2(`PH`、`US` 等) |
| `merchant_category_code` | 否 | ISO 18245 MCC |
| `extra_fields` | 否 | 任何 JSON 对象 — 已存储但未被 ML 使用 |
**响应:**
```
{
"transaction_id": "TXN-20241115-001",
"risk_score": 0.7823,
"ml_score": 0.8910,
"rule_score": 0.5000,
"risk_level": "HIGH",
"is_approved": false,
"decision_reason": "Transaction denied — high-severity rule(s) triggered: HIGH_AMOUNT",
"triggered_rules": [
{
"rule": "HIGH_AMOUNT",
"description": "Amount ≥ 50,000 PHP",
"severity": "HIGH",
"score_contribution": 0.50
}
],
"processing_ms": 12,
"assessed_at": "2024-11-15T06:30:00.123Z"
}
```
### 标记交易
```
POST /api/v1/transactions/{transaction_id}/label
Content-Type: application/json
X-API-Key:
```
```
{
"is_fraud": true,
"fraud_type": "account_takeover",
"notes": "Confirmed by customer — device not recognised"
}
```
`fraud_type` 选项:`account_takeover`、`identity_theft`、`card_fraud`、`phishing`、`money_laundering`、`money_mule`、`synthetic_identity`、`friendly_fraud`、`other`。
### 错误代码
| 状态 | 含义 |
|--------|---------|
| `401 Unauthorized` | 缺少或无效的 `X-API-Key` |
| `409 Conflict` | `transaction_id` 已被评估 |
| `422 Unprocessable Entity` | 请求体验证失败 |
| `429 Too Many Requests` | 超出速率限制 |
| `500 Internal Server Error` | 意外的服务器错误 |
### 处理拒绝
当 `is_approved: false` 时 — 拒绝交易。存储 `transaction_id`、`risk_score` 和 `decision_reason` 以供审计日志使用。
**不要**重试被拒绝的交易。重试相同的 ID 将返回 `409 Conflict`。如果客户对拒绝提出异议,请在仪表板中查看该交易,并在适当时将其标记为合法。
## 欺诈检测规则
| 规则 | 触发条件 | 严重性 |
|------|---------|---------|
| `HIGH_AMOUNT` | 金额 ≥ 阈值(默认 50,000 PHP) | 高(硬拦截) |
| `VELOCITY_TX_COUNT` | 同一发送方在时间窗口内 ≥ N 笔交易 | 高(硬拦截) |
| `VELOCITY_AMOUNT` | 同一发送方在时间窗口内的总金额超过限制 | 高(硬拦截) |
| `KNOWN_FRAUD_RECEIVER` | 接收方出现在已确认的欺诈交易中 | 高(硬拦截) |
| `KNOWN_FRAUD_DEVICE` | 设备指纹出现在已确认的欺诈交易中 | 高(硬拦截) |
| `KNOWN_FRAUD_IP` | IP 地址出现在已确认的欺诈交易中 | 高(硬拦截) |
| `NIGHT_TRANSACTION` | 22:00–05:59 间的交易 | 中 |
| `INTERNATIONAL` | 跨境交易 | 中 |
| `ROUND_AMOUNT` | 10,000 的倍数且 ≥ 50,000 | 低 |
所有阈值均可在运行时通过设置 → 规则阈值进行配置。
## ML 模型
### 训练流程
1. 交易被评估并存储。
2. 分析员通过标签页或 `POST /api/v1/labels/{id}` 标记已确认的欺诈/合法交易。
3. 一旦存在 ≥ 50 条标记记录,触发训练:`POST /api/v1/ml/train`(或等待 10 个新标签后的自动重新训练)。
4. XGBoost 模型在 32 个特征上进行训练。
5. 未来的评估使用综合规则 + ML 分数。
### 快速生成训练数据
```
# 生成 5,000 笔真实交易(10% 欺诈)
curl -X POST http://localhost:8000/api/v1/ml/simulate \
-H "X-API-Key: " \
-H "Content-Type: application/json" \
-d '{"count": 5000, "fraud_rate": 0.10, "include_labels": true}' \
-o training.jsonl
# 上传到数据库
curl -X POST http://localhost:8000/api/v1/ml/upload-dataset \
-H "X-API-Key: " \
-F "file=@training.jsonl"
# 训练
curl -X POST http://localhost:8000/api/v1/ml/train \
-H "X-API-Key: "
```
## 运维手册
### 首次启动后获取 API key
```
docker compose logs backend | grep "FIRST API KEY"
```
### 重置所有内容(完全擦除)
```
docker compose down -v && docker compose up --build
```
### 创建额外的 API key
1. 使用管理员凭据 `POST /api/v1/auth/login` → 获取 JWT
2. 使用该 JWT `POST /api/v1/api-keys/` → 复制 key(仅显示一次)
### 常见问题
| 症状 | 修复方法 |
|---------|-----|
| 后端崩溃:`column … does not exist` | `docker compose down -v && docker compose up` |
| 仪表板显示 "Offline" | 检查后端是否正在运行;验证 API key |
| 数据库重置后提示 "Invalid API key" | 从日志中获取新的 key |
| 尽管有高 (HIGH) 规则,所有交易仍被批准 | ML 尚未训练(返回中性值 0.5);标记 ≥ 50 笔交易然后训练 |
| 浏览器中出现 CORS 错误 | 设置 `ALLOWED_ORIGINS` 以匹配您的前端 URL |
| 训练从未开始 | 检查 `docker compose logs backend` 是否有锁/Redis 错误 |
## 安全说明
- 账号、设备指纹和 IP 地址**绝不以明文形式存储** — 仅存储 HMAC-SHA256 哈希(当设置了 `HASH_SECRET` 时)或 SHA-256 哈希。
- API key 以 SHA-256 哈希形式存储。
- 在生产环境中设置 `ENV=production` — 如果 `SECRET_KEY`、`ADMIN_PASSWORD` 或 `HASH_SECRET` 处于不安全的默认值,应用程序将拒绝启动。
- CORS 限制为 `ALLOWED_ORIGINS` 中列出的来源。从不使用通配符 `*`。
- `/assess` 端点按 API key 进行速率限制(默认 120 次/分钟)。
## 监管说明
旨在支持遵守 **BSP Circular 1213**(菲律宾中央银行欺诈管理系统要求)。所有交易和风险评分都持久化到 PostgreSQL 中,以满足所需的审计追踪。
标签:Apex, AV绕过, FastAPI, FinTech, PostgreSQL, Python, Redis, SvelteKit, TCP/UDP协议, WebSocket, XGBoost, 云计算, 交易验证, 仪表盘, 依赖分析, 反欺诈, 实时交易监控, 异常检测, 搜索引擎查询, 无后门, 机器学习, 欺诈检测, 欺诈预防, 测试用例, 电子支付, 网络安全, 规则引擎, 请求拦截, 逆向工具, 配置错误, 金融科技, 金融风控, 隐私保护, 风险评估系统, 风险评分, 黑名单