# 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 ' \ 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__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 专用组件 原因是当前核心需求仍是单机模型安全测试平台。上述设施会明显增加维护成本,但不会直接提升当前测试能力。