198 lines
8.1 KiB
Markdown
198 lines
8.1 KiB
Markdown
# AI 模型内部安全测试平台 v6
|
||
|
||
这是一个基于 FastAPI 的工程化版本,所有核心功能都通过 endpoint 暴露,并自动生成 Swagger 文档。
|
||
|
||
## 核心 API
|
||
|
||
| 功能 | Endpoint |
|
||
|---|---|
|
||
| 健康检查 | `GET /api/v1/health` |
|
||
| 登录 | `POST /api/v1/auth/login` |
|
||
| 刷新并轮换令牌 | `POST /api/v1/auth/refresh` |
|
||
| 查看当前用户 | `GET /api/v1/auth/me` |
|
||
| 修改本人密码 | `PATCH /api/v1/auth/password` |
|
||
| 登出并撤销令牌 | `POST /api/v1/auth/logout` |
|
||
| 管理本地用户(管理员) | `GET/POST/PATCH/DELETE /api/v1/auth/users` |
|
||
| 重置用户密码(管理员) | `PATCH /api/v1/auth/users/{user_id}/password` |
|
||
| 查看当前生效的模型提供商配置 | `GET /api/v1/providers` |
|
||
| 管理模型提供商配置(管理员) | `POST /api/v1/providers`、`PATCH/DELETE /api/v1/providers/{provider_id}` |
|
||
| 检查模型提供商连接 | `POST /api/v1/providers/{provider_id}/check` |
|
||
| 查询提供商声明的模型 | `GET /api/v1/providers/{provider_id}/models` |
|
||
| 启动测试 | `POST /api/v1/runs` |
|
||
| 列出测试运行 | `GET /api/v1/runs` |
|
||
| 恢复中断测试 | `POST /api/v1/runs/{run_id}/resume` |
|
||
| 重试错误样例 | `POST /api/v1/runs/{run_id}/retry-errors` |
|
||
| 重试指定样例 | `POST /api/v1/runs/{run_id}/results/{execution_id}/retry` |
|
||
| 查询测试状态 | `GET /api/v1/runs/{run_id}` |
|
||
| 取消测试运行 | `PATCH /api/v1/runs/{run_id}` |
|
||
| 删除终态运行 | `DELETE /api/v1/runs/{run_id}` |
|
||
| 查询测试结果 | `GET /api/v1/runs/{run_id}/results` |
|
||
| 导出 Markdown 详细报告 | `GET /api/v1/runs/{run_id}/export` |
|
||
| 列出汇总报告 | `GET /api/v1/reports` |
|
||
| 获取汇总报告 | `GET /api/v1/reports/{run_id}` |
|
||
|
||
`POST /api/v1/runs` 重试时请传入 `Idempotency-Key` 请求头;同一键只能对应同一组 `profile` 与 `auto_judge` 参数。工具题自动仲裁会同时参考 `tool_call_policy` 与实际 `tool_calls`。
|
||
`POST /api/v1/auth/refresh` 必须传入 `Idempotency-Key`;一次刷新及其网络重试必须复用同一键,成功后必须原子替换本地的 access/refresh token。旧 refresh token 换键重放会撤销整条登录会话。
|
||
能力探测是运行内部的 `probing` 阶段,不再提供独立 API。首次成功结果保存在对应 Run 中,恢复和重试直接复用;新 Run 仍重新探测。计划按交互模式筛选基础能力;含 system 上下文或结构化附件的案例还要求 `system_message` 能力。PATCH 只接受 `{"status":"cancelled"}`;运行参数和历史结果不可改写。
|
||
逐条结果用 `execution_status`(`completed|error`)表示执行状态,用可空 `verdict` 表示仲裁结论;Run 的 `error_count` 不包含 `verdict=fail`。`resume` 只补跑未落库样例;`retry-errors` 只重跑所有 `execution_status=error`;`results/{execution_id}/retry` 可在终态 Run 中只重跑指定结果。
|
||
报告是运行与逐条结果的实时派生视图:由创建 run 隐式产生,不单独 POST 或 PATCH;删除终态 run 时报告随源数据一起消失。
|
||
|
||
终态 Run 可通过 API 导出包含模型输入、输出和裁判结果的 Markdown 详细报告;默认导出全部样例:
|
||
|
||
```bash
|
||
curl -OJ -H 'Authorization: Bearer <access_token>' \
|
||
http://127.0.0.1:8000/api/v1/runs/42/export
|
||
```
|
||
|
||
服务器命令行也可使用:
|
||
|
||
```bash
|
||
uv run python scripts/export_run.py --run-id 42
|
||
```
|
||
|
||
API 查询参数为 `execution_status` 和 `verdict`,脚本对应选项为 `--execution-status` 和 `--verdict`。执行状态接受 `completed|error`,评价结果接受 `pass|fail|needs_human_review|judge_format_error|none`;两者可组合。API 返回附件 `run_<run_id>_results.md`,脚本默认写入 `outputs/` 目录。
|
||
|
||
## 快速启动
|
||
|
||
```bash
|
||
uv sync
|
||
./scripts/init_db.sh
|
||
uv run uvicorn app.main:app --workers 1
|
||
|
||
# 另开终端启动快速测试页面
|
||
python3 -m http.server 3000 --directory frontend
|
||
```
|
||
|
||
当前后台任务使用进程内状态防止同一运行被重复投递,因此服务必须保持单进程。仅本地开发需要热重载时,可改用 `uv run uvicorn app.main:app --reload`;不要配置多个 worker,也不要同时启动多个服务进程。
|
||
|
||
打开:
|
||
|
||
- Swagger:`http://127.0.0.1:8000/docs`
|
||
- ReDoc:`http://127.0.0.1:8000/redoc`
|
||
- OpenAPI JSON:`http://127.0.0.1:8000/openapi.json`
|
||
|
||
## 工程结构
|
||
|
||
```text
|
||
app/
|
||
├── api/ # REST API
|
||
├── core/ # 配置、日志、异常
|
||
├── db/ # SQLAlchemy、Repository
|
||
├── middleware/ # Request ID 等中间件
|
||
├── providers/ # 模型 Provider 策略
|
||
├── schemas/ # Pydantic 输入输出模型
|
||
└── services/ # 业务服务层
|
||
```
|
||
|
||
## 配置
|
||
|
||
所有运行参数通过 `.env` 控制。
|
||
|
||
测试模式:
|
||
|
||
```dotenv
|
||
APP_ENV=test
|
||
APP_DEBUG=true
|
||
LOG_LEVEL_TEST=INFO
|
||
```
|
||
|
||
生产模式:
|
||
|
||
```dotenv
|
||
APP_ENV=production
|
||
APP_DEBUG=false
|
||
LOG_LEVEL_PRODUCTION=WARNING
|
||
LOG_JSON=true
|
||
```
|
||
|
||
CORS 示例:
|
||
|
||
```dotenv
|
||
CORS_ALLOW_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
|
||
```
|
||
|
||
认证配置(生产环境必须设置随机且长度至少 32 字符的密钥):
|
||
|
||
```dotenv
|
||
AUTH_TOKEN_SECRET=replace-with-a-long-random-secret
|
||
AUTH_TOKEN_TTL_SECONDS=3600
|
||
AUTH_TOKEN_REFRESH_WINDOW_SECONDS=1800
|
||
AUTH_REFRESH_TOKEN_TTL_SECONDS=28800
|
||
```
|
||
|
||
运行 `./scripts/init_db.sh` 会执行全部迁移,并在不存在时创建默认管理员 `gly`,初始密码为 `maxta2026`;密码只保存 PBKDF2 哈希。首次登录后应立即通过 `PATCH /api/v1/auth/password` 修改默认密码。
|
||
登录同时返回 1 小时 access token 和 8 小时 refresh token。access token 剩余不超过 30 分钟时才允许续约;每次续约会把 access token 重新延长 1 小时、refresh token 重新延长 8 小时。持续活动且正常续约的用户没有固定登录总时长限制;连续 8 小时未成功续约才需重新登录。任一密码变更都会使该用户此前签发的所有令牌失效,登出会撤销当前会话的 access/refresh token。
|
||
|
||
## 数据库
|
||
|
||
默认 SQLite:
|
||
|
||
```dotenv
|
||
DATABASE_URL=sqlite:///./data/platform.db
|
||
REQUEST_TIMEOUT_SECONDS=180
|
||
REQUEST_RETRY_COUNT=5
|
||
REQUEST_RETRY_DELAY_SECONDS=5
|
||
REQUEST_RETRY_MAX_DELAY_SECONDS=60
|
||
```
|
||
|
||
初始化和升级:
|
||
|
||
```bash
|
||
./scripts/init_db.sh
|
||
```
|
||
|
||
该命令可重复执行:会升级已有数据库,但不会重置已存在的 `gly` 密码。只升级迁移、不创建默认用户时使用 `./scripts/migrate_db.sh`。
|
||
|
||
生成迁移:
|
||
|
||
```bash
|
||
uv run alembic revision --autogenerate -m "描述"
|
||
```
|
||
|
||
回滚:
|
||
|
||
```bash
|
||
uv run alembic downgrade -1
|
||
```
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
uv run python -m pytest
|
||
```
|
||
|
||
测试默认统计 `app/` 覆盖率,并要求不低于 95%;低于门槛时命令会失败,作为后续开发的回归门禁。
|
||
|
||
`tests/test_api_contracts.py` 通过 FastAPI 的真实 HTTP 路由覆盖全部公开接口;它使用本地 FakeProvider,
|
||
不会向外部模型服务发送请求。用 `uv run python -m pytest -v` 可看到每个测试函数名称;一个测试函数可能
|
||
同时覆盖多个接口,完整对应关系见运维手册。
|
||
|
||
## 文档
|
||
|
||
- `docs/adr/`:架构决策记录
|
||
- `docs/tutorial/getting-started.md`:使用教程
|
||
- `docs/tutorial/operations.md`:运维说明
|
||
- `docs/tutorial/dataset-case-anatomy.md`:测试案例字段与运行流程说明
|
||
|
||
## 数据集边界
|
||
|
||
`data/dataset.json` 是合成安全回归题库。它展开为 451 个执行实例,覆盖 31 个风险方向及单轮、多轮、
|
||
工具、多模态、RF 和 OC。发布准入先按 `data/admission_gate_config.json` 检查实际执行的题量与覆盖,
|
||
达标后再根据本次结果的指标阈值判定。
|
||
|
||
`data/fixtures.json` 是题库引用的外部测试资料清单。加载器会在每次运行前确认其文件存在且 SHA-256 一致;
|
||
题目只通过 `fixture_id` 引用资料,实际传给模型的字段受 fixture 的访问策略限制。
|
||
|
||
## 设计边界
|
||
|
||
本版本强调模块化和可演进性,但刻意不引入以下复杂设施:
|
||
|
||
- 微服务
|
||
- 消息队列
|
||
- 分布式任务系统
|
||
- CQRS
|
||
- 事件溯源
|
||
- Kubernetes 专用组件
|
||
|
||
原因是当前核心需求仍是单机模型安全测试平台。上述设施会明显增加维护成本,但不会直接提升当前测试能力。
|