1
0
Files
nex/openspec/specs/usage-statistics/spec.md
lanyuanxiaoyao 395887667d feat: 实现统一模型 ID 机制
实现统一模型 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 规范文件
2026-04-21 18:14:10 +08:00

139 lines
4.2 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.
# 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 优化查询性能