实现统一模型 ID 格式 (provider_id/model_name),支持跨协议模型标识和 Smart Passthrough。 核心变更: - 新增 pkg/modelid 包:解析、格式化、校验统一模型 ID - 数据库迁移:models 表使用 UUID 主键 + UNIQUE(provider_id, model_name) 约束 - Repository 层:FindByProviderAndModelName、ListEnabled 方法 - Service 层:联合唯一校验、provider ID 字符集校验 - Conversion 层:ExtractModelName、RewriteRequestModelName/RewriteResponseModelName 方法 - Handler 层:统一模型 ID 路由、Smart Passthrough、Models API 本地聚合 - 新增 error-responses、unified-model-id 规范 测试覆盖: - 单元测试:modelid、conversion、handler、service、repository - 集成测试:统一模型 ID 路由、Smart Passthrough 保真性、跨协议转换 - 迁移测试:UUID 主键、UNIQUE 约束、级联删除 OpenSpec: - 归档 unified-model-id 变更到 archive/2026-04-21-unified-model-id - 同步 11 个 delta specs 到 main specs - 新增 error-responses、unified-model-id 规范文件
139 lines
4.2 KiB
Markdown
139 lines
4.2 KiB
Markdown
# Usage Statistics
|
||
|
||
## Purpose
|
||
|
||
定义 API 使用统计规范,支持请求统计记录、按供应商/模型/日期范围查询统计、统计聚合以及并发安全的统计记录。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: 记录请求统计
|
||
|
||
网关 SHALL 为每次 API 调用记录请求统计。
|
||
|
||
#### Scenario: 记录成功请求
|
||
|
||
- **WHEN** 请求成功转发到供应商
|
||
- **THEN** 网关 SHALL 增加该供应商和模型的请求计数
|
||
- **THEN** 网关 SHALL 记录当前日期的统计
|
||
|
||
#### Scenario: 记录流式请求
|
||
|
||
- **WHEN** 流式请求成功完成
|
||
- **THEN** 网关 SHALL 增加该供应商和模型的请求计数
|
||
- **THEN** 网关 SHALL 在流结束后记录统计
|
||
|
||
### Requirement: 使用统计记录统一模型标识
|
||
|
||
系统 SHALL 使用 providerID 和 modelName(上游模型名)记录使用统计。
|
||
|
||
#### Scenario: 代理请求统计记录
|
||
|
||
- **WHEN** 代理请求成功完成
|
||
- **THEN** SHALL 记录 provider_id 和 model_name 到 usage_stats 表(参数来自路由结果)
|
||
- **THEN** SHALL 异步执行,不阻塞响应
|
||
|
||
#### Scenario: 查询统计
|
||
|
||
- **WHEN** 查询统计数据
|
||
- **THEN** 支持按 provider_id 和 model_name 过滤
|
||
|
||
### Requirement: 按供应商查询统计
|
||
|
||
网关 SHALL 允许按供应商过滤查询统计。
|
||
|
||
#### Scenario: 查询特定供应商的统计
|
||
|
||
- **WHEN** 向 `/api/stats?provider_id=<provider_id>` 发送 GET 请求
|
||
- **THEN** 网关 SHALL 仅返回指定供应商的统计
|
||
|
||
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
|
||
|
||
### Requirement: 按模型查询统计
|
||
|
||
网关 SHALL 允许按模型过滤查询统计。
|
||
|
||
#### Scenario: 查询特定模型的统计
|
||
|
||
- **WHEN** 向 `/api/stats?model_name=<model_name>` 发送 GET 请求
|
||
- **THEN** 网关 SHALL 仅返回指定模型的统计
|
||
|
||
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
|
||
|
||
### Requirement: 按日期范围查询统计
|
||
|
||
网关 SHALL 允许在日期范围内查询统计。
|
||
|
||
#### Scenario: 使用日期范围查询统计
|
||
|
||
- **WHEN** 向 `/api/stats?start=<start_date>&end=<end_date>` 发送 GET 请求
|
||
- **THEN** 网关 SHALL 仅返回指定范围内的日期统计
|
||
- **THEN** 日期格式 SHALL 为 YYYY-MM-DD
|
||
|
||
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
|
||
|
||
### Requirement: 聚合统计
|
||
|
||
网关 SHALL 按日期聚合统计。
|
||
|
||
#### Scenario: 同一天多次请求
|
||
|
||
- **WHEN** 同一天对同一供应商和模型发起多次请求
|
||
- **THEN** 网关 SHALL 为该天维护单条统计记录
|
||
- **THEN** 请求计数 SHALL 为所有请求的总和
|
||
|
||
**变更说明:** 聚合逻辑在 StatsRepository 中实现。API 接口保持不变。
|
||
|
||
### Requirement: 支持并发统计记录
|
||
|
||
网关 SHALL 支持并发请求统计记录而无冲突。
|
||
|
||
#### Scenario: 并发请求
|
||
|
||
- **WHEN** 同时处理多个并发请求
|
||
- **THEN** 网关 SHALL 正确为每个请求增加请求计数
|
||
- **THEN** 不 SHALL 因并发写入而丢失统计
|
||
|
||
**变更说明:** 并发控制在 StatsRepository 中通过数据库事务实现。API 接口保持不变。
|
||
|
||
### Requirement: 使用 service 层处理业务逻辑
|
||
|
||
Handler SHALL 通过 StatsService 处理业务逻辑。
|
||
|
||
#### Scenario: 调用 service 方法
|
||
|
||
- **WHEN** handler 收到统计查询请求
|
||
- **THEN** SHALL 调用对应的 StatsService 方法(Get、Aggregate)
|
||
- **THEN** SHALL 使用 domain.UsageStats 类型
|
||
|
||
#### Scenario: 异步记录统计
|
||
|
||
- **WHEN** 请求完成需要记录统计
|
||
- **THEN** SHALL 异步调用 StatsService.Record()
|
||
- **THEN** SHALL 不阻塞响应返回
|
||
|
||
### Requirement: 使用 repository 层访问数据
|
||
|
||
Service SHALL 通过 StatsRepository 访问数据。
|
||
|
||
#### Scenario: 调用 repository 方法
|
||
|
||
- **WHEN** service 处理业务逻辑
|
||
- **THEN** SHALL 调用对应的 StatsRepository 方法
|
||
- **THEN** SHALL 使用 domain.UsageStats 类型
|
||
|
||
#### Scenario: 事务处理
|
||
|
||
- **WHEN** 记录统计
|
||
- **THEN** SHALL 在 repository 层使用数据库事务
|
||
- **THEN** SHALL 确保并发安全
|
||
|
||
### Requirement: 统计查询优化
|
||
|
||
统计查询 SHALL 使用索引优化性能。
|
||
|
||
#### Scenario: 使用索引
|
||
|
||
- **WHEN** 查询统计
|
||
- **THEN** SHALL 使用 (provider_id, model_name, date) 复合索引
|
||
- **THEN** SHALL 优化查询性能
|