Files

198 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 专用组件
原因是当前核心需求仍是单机模型安全测试平台。上述设施会明显增加维护成本,但不会直接提升当前测试能力。