5.2 KiB
5.2 KiB
MODIFIED Requirements
Requirement: 代理请求路由
ProxyHandler SHALL 使用统一模型 ID 路由所有代理请求。
Scenario: 提取统一模型 ID
- WHEN 收到 Chat、Embeddings 或 Rerank 接口的 POST 请求(含请求体)
- THEN SHALL 调用客户端协议 adapter 的
ExtractModelName(body, ifaceType)提取 model 值 - THEN SHALL 调用
ParseUnifiedModelID解析得到 providerID 和 modelName - THEN SHALL 调用
RoutingService.RouteByModelName(providerID, modelName)路由
Scenario: GET 请求或无请求体
- WHEN 收到 GET 请求或请求体为空
- THEN SHALL 返回错误响应,状态码为 400,提示缺少 model 字段
Scenario: 无效的统一模型 ID
- WHEN 请求体中
model字段不是有效的统一模型 ID 格式 - THEN SHALL 返回错误响应,状态码为 400
Scenario: 模型不存在
- WHEN 解析统一模型 ID 后,数据库中找不到对应的 provider_id + model_name 组合
- THEN SHALL 返回错误响应,状态码为 404
Scenario: 模型已禁用
- WHEN 解析统一模型 ID 后,对应的模型 enabled 为 false
- THEN SHALL 返回错误响应,状态码为 404
Scenario: 供应商已禁用
- WHEN 解析统一模型 ID 后,对应的供应商 enabled 为 false
- THEN SHALL 返回错误响应,状态码为 404
Requirement: 同协议 Smart Passthrough
当客户端协议与供应商协议相同时,ProxyHandler SHALL 使用 Smart Passthrough 处理 Chat、Embedding、Rerank 请求。
Scenario: 同协议非流式请求
- WHEN 客户端协议 == 供应商协议,且为非流式请求
- THEN SHALL 调用 adapter 的
RewriteRequestModelName(body, modelName, ifaceType)将请求体中 model 从统一 ID 改写为上游模型名 - THEN SHALL 构建 URL 和 Headers(同当前透传逻辑)
- THEN SHALL 发送改写后的请求体到上游
- THEN SHALL 调用 adapter 的
RewriteResponseModelName(resp.Body, unifiedModelID, ifaceType)将响应中 model 从上游名改写为统一 ID - THEN SHALL NOT 对 body 做全量 decode → encode,保持未改写字段的原始 bytes
Scenario: 同协议流式请求
- WHEN 客户端协议 == 供应商协议,且为流式请求
- THEN SHALL 对请求体做
RewriteRequestModelName改写 model 字段 - THEN SHALL 逐 SSE chunk 调用
RewriteResponseModelName改写响应中 model 字段 - THEN SHALL NOT 对 chunk 做全量 decode → encode
Scenario: Smart Passthrough 保真性
- WHEN 客户端发送含未知参数的请求(如
{"model":"openai/gpt-4","some_new_param":"value"}) - THEN 上游 SHALL 收到
{"model":"gpt-4","some_new_param":"value"} - THEN
some_new_paramSHALL 保持原始值不变,不丢失、不改变类型
Requirement: 跨协议完整转换
当客户端协议与供应商协议不同时,ProxyHandler SHALL 使用全量转换路径。
Scenario: 跨协议非流式请求
- WHEN 客户端协议 != 供应商协议
- THEN SHALL 走
ConvertHttpRequest全量转换,encoder 中 provider.ModelName 覆盖 model - THEN SHALL 走
ConvertHttpResponse全量转换,modelOverride 参数覆写 canonical.Model
Scenario: 跨协议流式请求
- WHEN 客户端协议 != 供应商协议,且为流式请求
- THEN SHALL 走
CreateStreamConverter全量转换,modelOverride 参数覆写流式 canonical 事件中的 Model
Requirement: 模型列表本地聚合
ProxyHandler SHALL 从数据库聚合返回模型列表,不再透传上游。
Scenario: GET /v1/models
- WHEN 收到
GET /{protocol}/v1/models请求 - THEN SHALL 从数据库查询所有 enabled 的模型(关联 enabled 的供应商)
- THEN SHALL 组装
CanonicalModelList,每个模型的 ID 字段为统一模型 ID(provider_id/model_name),Name 字段为 model_name,OwnedBy 字段为 provider_id - THEN SHALL 使用客户端协议的 adapter 编码响应
- THEN SHALL NOT 请求上游供应商
Scenario: 无可用模型
- WHEN 数据库中没有 enabled 的模型
- THEN SHALL 返回空列表
Requirement: 模型详情本地查询
ProxyHandler SHALL 从数据库查询返回模型详情,不再透传上游。
Scenario: GET /v1/models/{unified_id}
- WHEN 收到
GET /{protocol}/v1/models/{provider_id}/{model_name}请求 - THEN SHALL 调用 adapter 的
ExtractUnifiedModelID提取统一模型 ID - THEN SHALL 解析统一模型 ID 得到 providerID 和 modelName
- THEN SHALL 从数据库查询对应的模型和供应商
- THEN SHALL 组装
CanonicalModelInfo,ID 字段为统一模型 ID(provider_id/model_name),Name 字段为 model_name,OwnedBy 字段为 provider_id - THEN SHALL 使用客户端协议的 adapter 编码响应
- THEN SHALL NOT 请求上游供应商
Scenario: 模型详情不存在
- WHEN 统一模型 ID 对应的模型不存在或已禁用
- THEN SHALL 返回错误响应,状态码为 404
Requirement: 统计记录
ProxyHandler SHALL 使用 providerID 和 modelName 记录使用统计。
Scenario: 异步记录统计
- WHEN 代理请求成功完成
- THEN SHALL 异步调用
StatsService.Record(providerID, modelName)