feat(routing): add canonical shadow provider pack
This commit is contained in:
@@ -108,6 +108,14 @@
|
||||
- 前端只看到一个逻辑分组
|
||||
- 插件层先做 route 级 sticky,再把请求稳定转发到某个宿主 shadow group
|
||||
- 宿主继续只做单线路 group 内的 account sticky / 调度
|
||||
- 2026-05-29 已基于上述结论新增 canonical shadow pack:
|
||||
- `packs/openai-cn-pack-shadow-asxs/`
|
||||
- provider:`gpt-asxs-shadow-lab`
|
||||
- 当前约束是:
|
||||
- 一个 route 对应一个独立宿主 shadow group
|
||||
- 宿主 shadow group 只承载 canonical upstream model:`gpt-5.4`、`gpt-5.4-mini`
|
||||
- alias/public model 的抽象只保留在插件 `logical_group -> route -> shadow_model` 层,不再下沉到宿主 channel
|
||||
- 设计与验收路径已单独沉淀到 `docs/SHADOW_PROVIDER_VALIDATION.md`
|
||||
- 2026-05-28 已新增插件整体需求盘点 `docs/PLUGIN_REQUIREMENTS_OVERVIEW_2026-05-28.md`
|
||||
- 已把“增加模型、维护逻辑分组、智能路由、供应商帐号导入与停启用、普通用户前端”五大功能域统一收口
|
||||
- 并明确区分 `已完成 / 待优化 / 待完成 / 未来规划`
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Route Lab Validation
|
||||
|
||||
> 该文档现在只保留“同 group 多 channel + alias 下沉”失败实验的历史记录。
|
||||
> 针对插件前置路由架构的当前正确方向,请改看 [docs/SHADOW_PROVIDER_VALIDATION.md](/home/long/project/sub2api-cn-relay-manager/docs/SHADOW_PROVIDER_VALIDATION.md)。
|
||||
|
||||
本文件记录 `asxs + codex2api` 同组双线路实验的最小验证路径。
|
||||
|
||||
## 目标
|
||||
|
||||
70
docs/SHADOW_PROVIDER_VALIDATION.md
Normal file
70
docs/SHADOW_PROVIDER_VALIDATION.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Shadow Provider Validation
|
||||
|
||||
本文件记录插件前置路由架构下,`shadow provider` 的最小正确验证路径。
|
||||
|
||||
## 目标
|
||||
|
||||
验证以下结论是否成立:
|
||||
|
||||
1. 插件层可以继续维护 `logical_group/public_model`
|
||||
2. 宿主层的 `shadow group` 只承载 canonical upstream model
|
||||
3. 真实 managed key 能通过宿主 `/v1/models` 与 `/v1/chat/completions`
|
||||
4. 旧的 alias/public model 不再下沉到 stock host 的 `channel_mapped + restrict_models` 组合
|
||||
|
||||
## 设计结论
|
||||
|
||||
旧的 `route-lab` 已证明两件事:
|
||||
|
||||
1. 当前宿主不支持“多个 channel 复用同一个 group”
|
||||
2. 在 `weishaw/sub2api:0.1.129` 上,把 alias 继续下沉到宿主 shadow group,会触发 `channel pricing restriction`
|
||||
|
||||
因此新的 shadow provider 约束是:
|
||||
|
||||
```text
|
||||
plugin logical group
|
||||
-> route
|
||||
-> shadow group (host)
|
||||
-> canonical models only
|
||||
```
|
||||
|
||||
## 当前实验 pack
|
||||
|
||||
- pack 目录:`packs/openai-cn-pack-shadow-asxs`
|
||||
- provider:`gpt-asxs-shadow-lab`
|
||||
|
||||
## 实验建模
|
||||
|
||||
```text
|
||||
Shadow Group: GPT ASXS Shadow 实验
|
||||
Channel: GPT ASXS Shadow
|
||||
Models:
|
||||
- gpt-5.4
|
||||
- gpt-5.4-mini
|
||||
```
|
||||
|
||||
关键点:
|
||||
|
||||
- shadow group 不再暴露 `gpt-5.4-asxs`
|
||||
- 插件 route 层如果需要 alias,必须在 `logical_group_route_models.shadow_model` 之外处理
|
||||
- stock host 只看到 canonical 模型
|
||||
|
||||
## 建议验证顺序
|
||||
|
||||
1. 导入 `gpt-asxs-shadow-lab`
|
||||
2. 记录 `group_id / channel_id / account_id`
|
||||
3. 用宿主订阅 key 直接验证:
|
||||
- `GET /v1/models`
|
||||
- `POST /v1/chat/completions`
|
||||
4. 再用插件管理面创建临时 `logical_group / route`
|
||||
5. 调 `POST /api/routing/proxy/chat/completions`
|
||||
6. 核对:
|
||||
- `effective_gateway_key_source=managed_subscription`
|
||||
- `forward.upstream_status=200`
|
||||
- `route_decision_logs` 已写回同一 `request_id`
|
||||
|
||||
## 成功标准
|
||||
|
||||
- managed key `/v1/models` 返回 canonical model
|
||||
- managed key `/v1/chat/completions` 返回 `200`
|
||||
- 插件 `route proxy` 走真实 shadow group 时返回 `200`
|
||||
- 不再出现 `channel pricing restriction`
|
||||
@@ -49,6 +49,26 @@ func TestLoadPathIncludesFirstBatchOfficialProviders(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPathSupportsShadowASXSPack(t *testing.T) {
|
||||
loaded, err := LoadPath(filepath.Join("..", "..", "packs", "openai-cn-pack-shadow-asxs"))
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPath(shadow-asxs-pack) error = %v", err)
|
||||
}
|
||||
if loaded.Manifest.PackID != "openai-cn-pack-shadow-asxs" {
|
||||
t.Fatalf("PackID = %q, want %q", loaded.Manifest.PackID, "openai-cn-pack-shadow-asxs")
|
||||
}
|
||||
if len(loaded.Providers) != 1 {
|
||||
t.Fatalf("Providers len = %d, want 1", len(loaded.Providers))
|
||||
}
|
||||
provider := loaded.Providers[0]
|
||||
if provider.ProviderID != "gpt-asxs-shadow-lab" {
|
||||
t.Fatalf("ProviderID = %q, want %q", provider.ProviderID, "gpt-asxs-shadow-lab")
|
||||
}
|
||||
if len(provider.DefaultModels) != 2 || provider.DefaultModels[0] != "gpt-5.4" {
|
||||
t.Fatalf("DefaultModels = %v, want canonical gpt-5.4 models", provider.DefaultModels)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPathSupportsZipArchive(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
archivePath := filepath.Join(tempDir, "openai-cn-pack.zip")
|
||||
|
||||
29
packs/openai-cn-pack-shadow-asxs/README.md
Normal file
29
packs/openai-cn-pack-shadow-asxs/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# openai-cn-pack-shadow-asxs
|
||||
|
||||
这是一个面向插件前置路由架构的 **shadow provider** 实验 pack。
|
||||
|
||||
它与旧的 `openai-cn-pack-route-lab` 有两个关键差异:
|
||||
|
||||
- 不再尝试让多个 route 复用同一个宿主 group
|
||||
- 不再把 route alias 下沉到宿主 shadow group
|
||||
|
||||
当前 pack 只包含一条 canonical shadow provider:
|
||||
|
||||
- `gpt-asxs-shadow-lab`
|
||||
|
||||
它的设计约束是:
|
||||
|
||||
- 一个 route 对应一个独立的宿主 shadow group
|
||||
- 宿主 shadow group 只承载 canonical upstream model
|
||||
- 插件层负责 `logical_group/public_model -> route -> shadow_model` 映射
|
||||
- 宿主层只负责该 shadow group 内的账号调度与 managed key 验证
|
||||
|
||||
当前期望模型:
|
||||
|
||||
- `gpt-5.4`
|
||||
- `gpt-5.4-mini`
|
||||
|
||||
注意:
|
||||
|
||||
- `public model alias` 的抽象要保留在插件 `logical_group` 层,不要再写进宿主 shadow provider
|
||||
- 后续如果要增加 `codex2api` shadow route,应新增独立 shadow provider / shadow group,而不是与 `asxs` 共用同一个宿主 group
|
||||
2
packs/openai-cn-pack-shadow-asxs/checksums.txt
Normal file
2
packs/openai-cn-pack-shadow-asxs/checksums.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
ea12d19da5281c593b3710b9ea9e9fd3ebd3e092ad0f738b4a2e87e65a0f8fc7 pack.json
|
||||
b2f1765709a4aefc9d5d77896fb6f00ce5e11fe70cc8a80c5d09eb0135ce9dfb providers/gpt-asxs-shadow-lab.json
|
||||
10
packs/openai-cn-pack-shadow-asxs/pack.json
Normal file
10
packs/openai-cn-pack-shadow-asxs/pack.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"pack_id": "openai-cn-pack-shadow-asxs",
|
||||
"version": "0.1.0",
|
||||
"vendor": "YourTeam",
|
||||
"target_host": "sub2api",
|
||||
"min_host_version": "0.1.126",
|
||||
"max_host_version": "0.2.x",
|
||||
"providers_dir": "providers",
|
||||
"checksum_file": "checksums.txt"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"provider_id": "gpt-asxs-shadow-lab",
|
||||
"display_name": "GPT asxs shadow 实验",
|
||||
"base_url": "https://api.asxs.top/v1",
|
||||
"platform": "openai",
|
||||
"account_type": "apikey",
|
||||
"default_models": ["gpt-5.4", "gpt-5.4-mini"],
|
||||
"smoke_test_model": "gpt-5.4",
|
||||
"group_template": {
|
||||
"name": "GPT ASXS Shadow 实验",
|
||||
"rate_multiplier": 1.0
|
||||
},
|
||||
"channel_template": {
|
||||
"name": "GPT ASXS Shadow",
|
||||
"model_mapping": {
|
||||
"gpt-5.4": "gpt-5.4",
|
||||
"gpt-5.4-mini": "gpt-5.4-mini"
|
||||
}
|
||||
},
|
||||
"plan_template": {
|
||||
"name": "GPT ASXS Shadow 实验套餐",
|
||||
"price": 19.9,
|
||||
"validity_days": 30,
|
||||
"validity_unit": "day"
|
||||
},
|
||||
"import": {
|
||||
"supports_multi_key": true,
|
||||
"supports_strict": true,
|
||||
"supports_partial": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user