api-server/docs/ai-runtime-api-reference.md
wangdl 5c7b8d1855
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
docs: add API reference with error codes, rate limiting, changelog (API-AI-076)
- Complete error code enumeration: Internal API + User API + Runtime errors
- Rate limiting: user quota, platform circuit breaker, global throttle
- Changelog: v1.0.0 initial → v1.1.0 current with all changes
- Integration examples: heartbeat cancel detection, job creation idempotency

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:49:45 +08:00

192 lines
7.0 KiB
Markdown
Raw 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 Runtime 接入文档
面向 Runtime 开发者和 iOS/Admin 前端开发者的 API 参考。
---
## 1. 错误码枚举
### 1.1 Internal API 错误码Runtime ↔ API
| 错误码 | HTTP | 说明 | retryable |
|--------|------|------|:---------:|
| `JOB_NOT_FOUND` | 404 | Job 不存在 | false |
| `JOB_NOT_ACTIVE` | 409 | Job 状态不是 locked/running | false |
| `JOB_ALREADY_LOCKED` | 409 | 已被其他 Runtime 锁定 | true |
| `SNAPSHOT_NOT_FOUND` | 404 | 快照不存在(已废弃:自动重建) | false |
| `CREDENTIAL_NOT_FOUND` | 404 | 凭证不存在或已删除 | false |
| `CREDENTIAL_REQUIRED` | 400 | user_deepseek_key 模式缺少 credentialId | false |
| `RESULT_ALREADY_EXISTS` | 409 | 重复提交(幂等 key 冲突) | false |
| `RESULT_SCHEMA_UNSUPPORTED` | 422 | schema 版本不支持 | false |
| `INTERNAL_ERROR` | 500 | 服务器内部错误 | true |
### 1.2 User API 错误码iOS / Admin → API
| 错误码 | HTTP | 说明 |
|--------|------|------|
| `AI_ANALYSIS_DISABLED` | 400 | 用户未开启 AI 分析 |
| `INVALID_JOB_TYPE` | 400 | jobType 不在支持列表中 |
| `INVALID_TARGET_TYPE` | 400 | quiz/flashcard 必须 targetType=knowledge_base |
| `CREDENTIAL_REQUIRED` | 400 | user_deepseek_key 模式需要绑定凭证 |
| `CREDENTIAL_NOT_FOUND` | 404 | 凭证不存在或无权访问 |
| `DAILY_JOB_LIMIT_EXCEEDED` | 400 | 超过每日 AI Job 数量上限 |
| `DAILY_TOKEN_BUDGET_EXCEEDED` | 400 | 超过每日 Token 预算上限 |
| `PLATFORM_CIRCUIT_OPEN` | 503 | 平台熔断器开启,拒绝新请求 |
| `PLATFORM_CIRCUIT_HALF_OPEN` | 503 | 熔断器半开,仅允许少量请求 |
| `PLATFORM_TOKEN_BUDGET_EXCEEDED` | 400 | 平台日 Token 预算耗尽 |
| `PLATFORM_COST_BUDGET_EXCEEDED` | 400 | 平台日成本预算耗尽 |
### 1.3 Runtime 上报的错误码
Runtime 通过 `POST /internal/runtime/jobs/{jobId}/fail` 上报的错误码:
| 错误码 | 说明 | retryable |
|--------|------|:---------:|
| `JOB_CANCELLED` | 用户取消 Job | false |
| `JOB_TIMEOUT` | Job 执行超时(默认 120s | false |
| `MODEL_TIMEOUT` | DeepSeek API 超时/503/502/500 | true |
| `MODEL_RATE_LIMIT` | DeepSeek 429 限流 | true |
| `MODEL_NETWORK_ERROR` | 网络连接失败 | true |
| `SNAPSHOT_FETCH_FAILED` | 快照拉取失败 | true |
| `INVALID_SNAPSHOT` | 快照版本不兼容 | false |
| `CREDENTIAL_RESOLVE_FAILED` | 凭证解析失败 | false |
| `UNSUPPORTED_JOB_TYPE` | jobType 不支持 | false |
| `MODEL_RESPONSE_INVALID` | 模型返回无效 JSON | false |
| `MODEL_JSON_PARSE_FAILED` | 模型输出 JSON 解析失败 | false |
---
## 2. 限流说明
### 2.1 用户级限流
通过 `UserAiSettings` 控制,默认值:
| 参数 | 默认值 | 说明 |
|------|--------|------|
| `maxDailyAiJobs` | 20 | 每日 AI Job 创建上限 |
| `maxDailyTokenBudget` | 100,000 | 每日 Token 消耗上限 |
超出限制返回 `DAILY_JOB_LIMIT_EXCEEDED``DAILY_TOKEN_BUDGET_EXCEEDED`
限流粒度:`(userId, localDate, apiKeyMode)`platform_key 和 user_deepseek_key 独立计数。
### 2.2 平台级熔断
平台密钥platform_key模式启用的保护机制
```
├── 日 Token 预算10,000,000 tokens
├── 日成本预算:$500 (50000 cents)
├── 熔断阈值:连续 10 次失败 → open
├── 半开限制:最多 2 个活跃 platform_key Job
└── 恢复:单次成功 → closed重置失败计数
```
熔断状态流转:
```
closed ──[10次连续失败]──> open ──[手动半开]──> half_open ──[成功]──> closed
│ │
└───[超限]───<───────────────[超限]───┘
```
### 2.3 API 全局限流
通过 NestJS ThrottlerModule 控制,默认限制:
| 端点 | 限制 | 窗口 |
|------|------|------|
| `/ai/*` 用户端点 | 60 次/分钟 | 60s |
| `/internal/runtime/*` | 300 次/分钟 | 60s |
超限返回 HTTP 429。
---
## 3. 变更日志
### v1.1.02026-06
**新增**
- Heartbeat 响应新增 `cancelRequested` 字段HTTP 200 替代 204
- `getSnapshot` 自动重建过期/缺失快照(不再返回 SNAPSHOT_EXPIRED
- `submitFailure` 支持 `JOB_CANCELLED` 错误码
- 用户 API`POST /ai/jobs` 创建分析 Job11 步流程含幂等、配额、熔断)
- 用户 API`GET/POST/PUT/DELETE /ai/model-credentials` 凭证管理
- 用户 API`GET /ai/analyses`, `/ai/recommendations`, `/ai/weak-points` 分析结果查询
- 用户 API`GET /ai/quizzes`, `/ai/flashcards` 已发布内容查询
- 平台预算熔断:`PlatformBudgetService` 日 Token/成本限制 + 熔断器
- 结果落库:`persistResult` 支持 5 种 jobTypelearning_state_analysis / weak_point_analysis / next_action_planning / quiz_generation / flashcard_generation
- 候选转换:`convertQuizCandidates` / `convertFlashcardCandidates` 去重 + 正式记录创建
- Job 完成通知:`notifyJobComplete` 推送通知给用户
**修复**
- `getProfile``?? {}` 修复(之前 Promise 永远 truthy
- `HeartbeatResponse.cancel_requested: bool` 客户端适配
- N+1 去重查询 → 批量预取Quiz/Flashcard convertCandidates
- `persistResult` / `notifyJobComplete` fire-and-forget 增加日志 + 计数器
- `job-reaper` take:500 上限 → 游标批处理循环
- `checkAndReserve``checkQuota` 重命名(澄清只读语义)
- `testCredential` 使用 ConfigService 获取 DeepSeek baseUrl
- Quota 测试拆分 `mockSettingsFindUnique` / `mockUsageFindUnique`
### v1.0.02026-05
**初始版本**
- Internal APIPoll / Lock / Heartbeat / GetSnapshot / ResolveCredential / SubmitResult / SubmitFailure / SubmitInvocationLogs
- User APIProfile / Settings / Learning Profile CRUD
- 鉴权InternalAuthGuardx-internal-api-key+ JWT用户端点
- 加密CredentialEncryptionServiceAES-256-GCM
- 配额UserAiQuotaServicecheckQuota + incrementJobCount + recordTokenUsage
---
## 4. 接入示例
### 4.1 Runtime 心跳 + 取消检测v1.1
```
POST /internal/runtime/jobs/{jobId}/heartbeat
Authorization: Bearer <RUNTIME_SERVICE_TOKEN>
x-runtime-instance-id: runtime-001
```
响应 200
```json
{
"jobId": "job-abc123",
"lockUntil": 1700000000123,
"cancelRequested": false
}
```
`cancelRequested=true`Runtime 应在下一个 I/O 检查点中止执行并提交 `JOB_CANCELLED` fail。
### 4.2 前端创建分析 Job
```
POST /ai/jobs
Authorization: Bearer <USER_JWT>
{
"jobType": "quiz_generation",
"targetType": "knowledge_base",
"targetId": "kb-001",
"apiKeyMode": "platform_key",
"idempotencyKey": "client-uuid-xxx",
"questionCount": 10
}
```
幂等:相同 `idempotencyKey` 重复请求返回已有 Job ID不重复创建
---
## 5. 相关资源
- [Internal API 通信协议](./ai-runtime-internal-api-protocol.md)
- [AI Runtime 架构](./ai-runtime-architecture.md)
- [Job 状态机](./ai-job-state-machine.md)
- [数据权限与隐私](./ai-data-permission-privacy.md)
- [用户 AI API 文档](./ai-runtime-user-api.md)