mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 20:12:39 +08:00
fix(billing): 适配 DeepSeek V4.1-Flash 新价与 pro→Flash 切换
- flash 低谷价更新为 $0.15/$0.60/$0.003 per MTok(2026-09-10 官方降价) - deepseek-v4-pro 自 2026-09-14 04:00 UTC 起按 Flash 价计费(上游路由变更) - 计费时点显式驱动 pro→Flash 切换,定价展示与计费两条路径同源 - deepseek-flash 保留 reasoning_effort=max;补 Codex 模型清单与前端白名单 - 价表 JSON 新增 deepseek-flash 条目并同步 flash 系价格
This commit is contained in:
@@ -1440,7 +1440,7 @@ func modelListingSource(platform string, availableModels, fallbackModels []strin
|
||||
func defaultCodexModelIDsForPlatform(platform string) []string {
|
||||
switch platform {
|
||||
case service.PlatformDeepseek:
|
||||
return []string{"deepseek-v4-pro", "deepseek-v4-flash"}
|
||||
return []string{"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-flash"}
|
||||
case service.PlatformMiniMax:
|
||||
return []string{"MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.5"}
|
||||
default:
|
||||
|
||||
@@ -914,7 +914,7 @@ func TestDefaultModelIDsForPlatform_CNProvidersKeepClaudeDefaults(t *testing.T)
|
||||
}
|
||||
|
||||
func TestDefaultCodexModelIDsForPlatform_DeepSeekUsesDeepSeekModels(t *testing.T) {
|
||||
require.Equal(t, []string{"deepseek-v4-pro", "deepseek-v4-flash"}, defaultCodexModelIDsForPlatform(service.PlatformDeepseek))
|
||||
require.Equal(t, []string{"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-flash"}, defaultCodexModelIDsForPlatform(service.PlatformDeepseek))
|
||||
require.Equal(t, []string{"MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.5"}, defaultCodexModelIDsForPlatform(service.PlatformMiniMax))
|
||||
require.Equal(t, defaultModelIDsForPlatform(service.PlatformAnthropic), defaultCodexModelIDsForPlatform(service.PlatformAnthropic))
|
||||
}
|
||||
|
||||
@@ -659,7 +659,7 @@ func TestTryModelFilePricing_DeepSeekPeakPricing(t *testing.T) {
|
||||
name string
|
||||
input, output, cacheReadPrice float64
|
||||
}{
|
||||
{"deepseek-v4-flash", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-v4-flash", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-pro", 6.6e-7, 1.98e-6, 2.2e-8},
|
||||
} {
|
||||
for _, usage := range []struct {
|
||||
@@ -711,7 +711,7 @@ func TestResolveAccountStatsCost_DeepSeekPricingPriority(t *testing.T) {
|
||||
noChannel bool
|
||||
want float64
|
||||
}{
|
||||
{name: "catalog", want: 1000 * 2.2e-7 * 2},
|
||||
{name: "catalog", want: 1000 * 1.5e-7 * 2},
|
||||
{name: "custom_rule", customRule: true, want: 1},
|
||||
{name: "custom_rule_before_customer_price", customRule: true, applyPricing: true, want: 1},
|
||||
{name: "customer_price", applyPricing: true, want: 0.75},
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/timezone"
|
||||
)
|
||||
|
||||
// ContextPricingBasis 阶梯的计价基准。当前只有整单口径;历史上的
|
||||
@@ -222,7 +224,10 @@ func (s *BillingService) contextPricingBreakpoints(resolver *ModelPricingResolve
|
||||
if pricing == nil {
|
||||
return plan
|
||||
}
|
||||
pricing = s.applyModelSpecificPricingPolicy(model, pricing)
|
||||
// 该路径无既有计费时点(ContextPricingScheduleInput 无时间字段),显式传
|
||||
// 当前时刻;此处 pricing 仅取 LongContextInputThreshold 等时间无关字段,
|
||||
// DeepSeek pro→Flash 切换不影响断点结果。
|
||||
pricing = s.applyModelSpecificPricingPolicyEx(model, pricing, true, timezone.Now())
|
||||
if pricing.LongContextInputThreshold <= 0 {
|
||||
return plan
|
||||
}
|
||||
|
||||
@@ -262,14 +262,21 @@ func resolvedChannelTimeMultiplier(resolved *ResolvedPricing, at time.Time) floa
|
||||
// sources can price the requested model.
|
||||
var ErrModelPricingUnavailable = errors.New("pricing not found")
|
||||
|
||||
// ---- DeepSeek 官方低谷价($/token,2026-08-23 起生效)----
|
||||
// Source: https://api-docs.deepseek.com/quick_start/pricing
|
||||
// ---- DeepSeek 官方低谷价($/token)----
|
||||
// 2026-09-10 官方公告:DeepSeek-V4.1-Flash(新名 deepseek-flash)大幅降价,
|
||||
// Flash 低谷价降为 $0.15/$0.60/$0.003 per MTok(输入缓存未命中/输出/缓存命中);
|
||||
// deepseek-v4-pro 名义价格暂不变,但自北京时间 2026-09-14 12:00(04:00 UTC)起
|
||||
// 其请求被上游路由到 V4.1-Flash 并按 Flash 价计费(见 deepseekProBilledAsFlash)。
|
||||
// Source: https://api-docs.deepseek.com/news/news260910
|
||||
//
|
||||
// https://api-docs.deepseek.com/quick_start/pricing
|
||||
//
|
||||
// 高峰价 = 2× 低谷价;高峰时段 01:00–04:00 与 06:00–10:00 UTC(仅工作日),
|
||||
// 北京时间周六/周日全天低谷。时段判定见 deepseekPeakMultiplierAt。
|
||||
const (
|
||||
deepseekFlashOffPeakInputPrice = 2.2e-7 // $0.22 per MTok (cache miss)
|
||||
deepseekFlashOffPeakOutputPrice = 6.6e-7 // $0.66 per MTok
|
||||
deepseekFlashOffPeakCacheRead = 7e-9 // $0.007 per MTok (cache hit)
|
||||
deepseekFlashOffPeakInputPrice = 1.5e-7 // $0.15 per MTok (cache miss)
|
||||
deepseekFlashOffPeakOutputPrice = 6.0e-7 // $0.60 per MTok
|
||||
deepseekFlashOffPeakCacheRead = 3e-9 // $0.003 per MTok (cache hit)
|
||||
deepseekProOffPeakInputPrice = 6.6e-7 // $0.66 per MTok (cache miss)
|
||||
deepseekProOffPeakOutputPrice = 1.98e-6 // $1.98 per MTok
|
||||
deepseekProOffPeakCacheRead = 2.2e-8 // $0.022 per MTok (cache hit)
|
||||
@@ -302,6 +309,27 @@ func deepseekPeakMultiplierAt(now time.Time) float64 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
// deepseekProRoutesToFlashAt:官方公告自北京时间 2026-09-14 12:00(04:00 UTC)起,
|
||||
// 所有 deepseek-v4-pro 请求被上游路由到 V4.1-Flash 并按 Flash 价计费(直至未来
|
||||
// V4.1 Pro 上线)。Source: https://api-docs.deepseek.com/news/news260910
|
||||
var deepseekProRoutesToFlashAt = time.Date(2026, 9, 14, 4, 0, 0, 0, time.UTC)
|
||||
|
||||
// deepseekProBilledAsFlash 报告指定计费时点 deepseek-v4-pro 是否已按 Flash 价
|
||||
// 计费:计费时点到达或晚于切换时点返回 true;零值时点回退当前时刻(与峰谷
|
||||
// 倍率的取时点方式一致,见 calculateTokenCost)。
|
||||
func deepseekProBilledAsFlash(pricingAt time.Time) bool {
|
||||
if pricingAt.IsZero() {
|
||||
pricingAt = timezone.Now()
|
||||
}
|
||||
return !pricingAt.Before(deepseekProRoutesToFlashAt)
|
||||
}
|
||||
|
||||
// isDeepSeekProModel 判断模型名是否归入 deepseek-v4-pro 档(含版本化名称,
|
||||
// 如 deepseek-v4-pro-0813)。
|
||||
func isDeepSeekProModel(model string) bool {
|
||||
return strings.Contains(strings.ToLower(strings.TrimSpace(model)), "deepseek-v4-pro")
|
||||
}
|
||||
|
||||
// BillingService 计费服务
|
||||
type BillingService struct {
|
||||
cfg *config.Config
|
||||
@@ -557,10 +585,11 @@ func (s *BillingService) initFallbackPricing() {
|
||||
|
||||
// ---- DeepSeek 系列 ----
|
||||
// Source: https://api-docs.deepseek.com/quick_start/pricing
|
||||
// 官方口径(2026-08-23 起生效):现行模型为 deepseek-v4-flash /
|
||||
// deepseek-v4-pro / deepseek-v4-flash-vision-exp;deepseek-chat /
|
||||
// deepseek-reasoner 已停止服务,其余 deepseek-*(含未知型号)统一按
|
||||
// flash 价兜底(见 getFallbackPricing),避免计费中断。
|
||||
// 官方口径(2026-09-10 公告降价后):现行模型为 deepseek-flash(=
|
||||
// DeepSeek-V4.1-Flash,旧名 deepseek-v4-flash 兼容路由)/ deepseek-v4-pro /
|
||||
// deepseek-v4-flash-vision-exp;deepseek-chat / deepseek-reasoner 已停止服务,
|
||||
// 其余 deepseek-*(含未知型号)统一按 flash 价兜底(见 getFallbackPricing),
|
||||
// 避免计费中断。
|
||||
// 以下均为官方低谷价;高峰价 = 2× 低谷价(高峰时段 01:00–04:00
|
||||
// 与 06:00–10:00 UTC,仅工作日;北京时间周六/周日全天低谷),见 deepseekPeakMultiplierAt。
|
||||
s.fallbackPrices["deepseek-v4-pro"] = &ModelPricing{
|
||||
@@ -570,9 +599,9 @@ func (s *BillingService) initFallbackPricing() {
|
||||
SupportsCacheBreakdown: false,
|
||||
}
|
||||
s.fallbackPrices["deepseek-v4-flash"] = &ModelPricing{
|
||||
InputPricePerToken: deepseekFlashOffPeakInputPrice, // $0.22 per MTok (cache miss, off-peak)
|
||||
OutputPricePerToken: deepseekFlashOffPeakOutputPrice, // $0.66 per MTok
|
||||
CacheReadPricePerToken: deepseekFlashOffPeakCacheRead, // $0.007 per MTok (cache hit)
|
||||
InputPricePerToken: deepseekFlashOffPeakInputPrice, // $0.15 per MTok (cache miss, off-peak)
|
||||
OutputPricePerToken: deepseekFlashOffPeakOutputPrice, // $0.60 per MTok
|
||||
CacheReadPricePerToken: deepseekFlashOffPeakCacheRead, // $0.003 per MTok (cache hit)
|
||||
SupportsCacheBreakdown: false,
|
||||
}
|
||||
s.fallbackPrices["deepseek-v4-flash-vision-exp"] = &ModelPricing{
|
||||
@@ -1167,6 +1196,14 @@ func (s *BillingService) HasIdentifiedTokenPricing(model string) bool {
|
||||
|
||||
// GetModelPricing 获取模型价格配置
|
||||
func (s *BillingService) GetModelPricing(model string) (*ModelPricing, error) {
|
||||
// 无显式计费时点,DeepSeek pro→Flash 切换按当前时刻判定。
|
||||
return s.getModelPricingAt(model, timezone.Now())
|
||||
}
|
||||
|
||||
// getModelPricingAt 是 GetModelPricing 的带计费时点内部变体:pricingAt 显式
|
||||
// 驱动 DeepSeek pro→Flash 切换判定(切换点前 Pro 价、之后 Flash 价),使
|
||||
// 展示/估算路径可与历史补账同刻复算,测试也能用固定时点钉住断言。
|
||||
func (s *BillingService) getModelPricingAt(model string, pricingAt time.Time) (*ModelPricing, error) {
|
||||
// 标准化模型名称(转小写)
|
||||
model = strings.ToLower(model)
|
||||
|
||||
@@ -1188,7 +1225,7 @@ func (s *BillingService) GetModelPricing(model string) (*ModelPricing, error) {
|
||||
price5m := litellmPricing.CacheCreationInputTokenCost
|
||||
price1h := litellmPricing.CacheCreationInputTokenCostAbove1hr
|
||||
enableBreakdown := price1h > 0 && price1h > price5m
|
||||
return s.applyModelSpecificPricingPolicy(model, &ModelPricing{
|
||||
return s.applyModelSpecificPricingPolicyEx(model, &ModelPricing{
|
||||
InputPricePerToken: litellmPricing.InputCostPerToken,
|
||||
InputPricePerTokenPriority: litellmPricing.InputCostPerTokenPriority,
|
||||
OutputPricePerToken: litellmPricing.OutputCostPerToken,
|
||||
@@ -1207,7 +1244,7 @@ func (s *BillingService) GetModelPricing(model string) (*ModelPricing, error) {
|
||||
LongContextOutputMultiplier: litellmPricing.LongContextOutputCostMultiplier,
|
||||
ImageInputPricePerToken: litellmPricing.InputCostPerImageToken,
|
||||
ImageOutputPricePerToken: litellmPricing.OutputCostPerImageToken,
|
||||
}), nil
|
||||
}, true, pricingAt), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1219,7 +1256,7 @@ func (s *BillingService) GetModelPricing(model string) (*ModelPricing, error) {
|
||||
if _, seen := s.fallbackWarnSeen.LoadOrStore(model, struct{}{}); !seen {
|
||||
log.Printf("[Billing] Using fallback pricing for model: %s", model)
|
||||
}
|
||||
return s.applyModelSpecificPricingPolicy(model, fallback), nil
|
||||
return s.applyModelSpecificPricingPolicyEx(model, fallback, true, pricingAt), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w for model: %s", ErrModelPricingUnavailable, model)
|
||||
@@ -1398,20 +1435,22 @@ func (s *BillingService) calculateTokenCost(resolved *ResolvedPricing, input Cos
|
||||
return nil, fmt.Errorf("no pricing available for model: %s: %w", input.Model, ErrModelPricingUnavailable)
|
||||
}
|
||||
|
||||
// 计费时点:优先请求级 PricingAt(历史补账与 DeepSeek pro→Flash 切换判定
|
||||
// 同源),零值回退当前时刻。
|
||||
pricingAt := input.PricingAt
|
||||
if pricingAt.IsZero() {
|
||||
pricingAt = timezone.Now()
|
||||
}
|
||||
|
||||
// 默认价卡(Source=LiteLLM)应用 DeepSeek 官方价强制覆盖(幂等,GetModelPricing
|
||||
// 内部已强制过);分组/渠道自定义定价保留运营者配置,不强制覆盖官方价。
|
||||
pricing = s.applyModelSpecificPricingPolicyEx(input.Model, pricing, resolved.Source == PricingSourceLiteLLM)
|
||||
pricing = s.applyModelSpecificPricingPolicyEx(input.Model, pricing, resolved.Source == PricingSourceLiteLLM, pricingAt)
|
||||
|
||||
// DeepSeek 模型默认价卡按官方峰谷口径调整:高峰时段(01:00–04:00 与
|
||||
// 06:00–10:00 UTC,仅工作日;北京时间周末全天低谷)按 2× 低谷价计费。
|
||||
// 仅作用于默认价卡(Source=LiteLLM,无分组/渠道自定义定价)——分组/渠道
|
||||
// 自定义定价保持运营者语义,不叠加。PricingAt 为零值时回退当前时刻。
|
||||
// 先克隆再乘,避免污染共享 fallbackPrices 指针。
|
||||
// 自定义定价保持运营者语义,不叠加。先克隆再乘,避免污染共享 fallbackPrices 指针。
|
||||
if resolved.Source == PricingSourceLiteLLM && isDeepSeekModel(input.Model) {
|
||||
pricingAt := input.PricingAt
|
||||
if pricingAt.IsZero() {
|
||||
pricingAt = timezone.Now()
|
||||
}
|
||||
if mult := deepseekPeakMultiplierAt(pricingAt); mult > 1 {
|
||||
cloned := *pricing
|
||||
cloned.InputPricePerToken *= mult
|
||||
@@ -1670,36 +1709,43 @@ func (s *BillingService) calculateCostInternalWithPolicy(
|
||||
// 强制覆盖;GPT-5.6 缺 cache_write 价时按官方规则补 1.25 倍输入价;Fast/priority
|
||||
// 档按业务倍率改写(本地/远程目录的 priority 价可能沿用官方旧口径)。长上下文
|
||||
// 阶梯不在此处补齐:一律由目录数据(above_XXXk 折算或显式 long_context_* 字段)
|
||||
// 驱动。默认强制 DeepSeek 官方价——该路径仅被默认价卡(GetModelPricing 内部)
|
||||
// 调用;分组/渠道自定义定价路径用带参数的 applyModelSpecificPricingPolicyEx
|
||||
// 关闭强制,保留运营者配置。
|
||||
// 驱动。强制 DeepSeek 官方价且无显式计费时点(pro→Flash 切换按当前时刻判定),
|
||||
// 供无既有时点的策略修正场景与测试使用;计费/展示主路径分别经
|
||||
// calculateTokenCost 与 getModelPricingAt 显式传时点,分组/渠道自定义定价
|
||||
// 用 applyModelSpecificPricingPolicyEx 关闭强制,保留运营者配置。
|
||||
func (s *BillingService) applyModelSpecificPricingPolicy(model string, pricing *ModelPricing) *ModelPricing {
|
||||
return s.applyModelSpecificPricingPolicyEx(model, pricing, true)
|
||||
return s.applyModelSpecificPricingPolicyEx(model, pricing, true, time.Time{})
|
||||
}
|
||||
|
||||
// applyModelSpecificPricingPolicyEx 与 applyModelSpecificPricingPolicy 相同,
|
||||
// 但由调用方控制是否强制 DeepSeek 官方价(forceDeepSeekRates)。
|
||||
// 但由调用方控制是否强制 DeepSeek 官方价(forceDeepSeekRates),并显式传入
|
||||
// 计费时点 pricingAt(零值表示按当前时刻判定)。
|
||||
// calculateTokenCost 对分组/渠道自定义定价(Source 非 LiteLLM)传 false:
|
||||
// 强制覆盖会把运营者配置的售价盖回官方价,违反自定义定价语义。
|
||||
func (s *BillingService) applyModelSpecificPricingPolicyEx(model string, pricing *ModelPricing, forceDeepSeekRates bool) *ModelPricing {
|
||||
func (s *BillingService) applyModelSpecificPricingPolicyEx(model string, pricing *ModelPricing, forceDeepSeekRates bool, pricingAt time.Time) *ModelPricing {
|
||||
if pricing == nil {
|
||||
return nil
|
||||
}
|
||||
// DeepSeek 模型:无论 JSON/远端价格表给什么价,一律强制官方低谷价
|
||||
// (2026-08-23 起生效)。这是覆盖远端旧价的关键——远端仓库不可改,生产会先
|
||||
// 拉到旧价,必须在此兜底修正;克隆后再覆盖,避免污染共享 fallbackPrices 指针。
|
||||
// (Flash 三档为 2026-09-10 官方降价后口径)。这是覆盖远端旧价的关键——远端
|
||||
// 仓库不可改,生产会先拉到旧价,必须在此兜底修正;克隆后再覆盖,避免污染
|
||||
// 共享 fallbackPrices 指针。
|
||||
// 档位判定:含 "deepseek-v4-pro" 的版本化名称(如 deepseek-v4-pro-0813)归 pro 档,
|
||||
// 其余 deepseek-*(含已停服的 chat/reasoner 与未知型号)统一归 flash 档。
|
||||
// 2026-09-14 04:00 UTC 起上游把 pro 请求路由到 V4.1-Flash,pro 档改按
|
||||
// Flash 三档价计费;历史时点(早于切换时刻)仍按 Pro 价。
|
||||
// 高峰时段倍率不在本函数处理,由 calculateTokenCost 按 deepseekPeakMultiplierAt
|
||||
// 对默认价卡另行叠加(分组/渠道自定义定价不叠加)。
|
||||
if forceDeepSeekRates && isDeepSeekModel(model) {
|
||||
cloned := *pricing
|
||||
if strings.Contains(strings.ToLower(strings.TrimSpace(model)), "deepseek-v4-pro") {
|
||||
if isDeepSeekProModel(model) && !deepseekProBilledAsFlash(pricingAt) {
|
||||
cloned.InputPricePerToken = deepseekProOffPeakInputPrice
|
||||
cloned.OutputPricePerToken = deepseekProOffPeakOutputPrice
|
||||
cloned.CacheReadPricePerToken = deepseekProOffPeakCacheRead
|
||||
} else {
|
||||
// deepseek-v4-flash / deepseek-v4-flash-vision-exp 与其余 deepseek-* 共用 flash 价。
|
||||
// deepseek-flash(= V4.1-Flash)、deepseek-v4-flash /
|
||||
// deepseek-v4-flash-vision-exp 与其余 deepseek-* 共用 flash 价;
|
||||
// 切换时点之后的 pro 请求同样按 flash 价计费。
|
||||
cloned.InputPricePerToken = deepseekFlashOffPeakInputPrice
|
||||
cloned.OutputPricePerToken = deepseekFlashOffPeakOutputPrice
|
||||
cloned.CacheReadPricePerToken = deepseekFlashOffPeakCacheRead
|
||||
|
||||
@@ -514,38 +514,46 @@ func TestGetFallbackPricing_FamilyMatching(t *testing.T) {
|
||||
{
|
||||
name: "deepseek v4 flash",
|
||||
model: "deepseek-v4-flash",
|
||||
expectedInput: 2.2e-7,
|
||||
expectedOutput: floatPtr(6.6e-7),
|
||||
expectedCacheRead: floatPtr(7e-9),
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
{
|
||||
// deepseek-flash(= V4.1-Flash 新名)经前缀兜底同样命中 flash 价卡。
|
||||
name: "deepseek flash v41 name maps to flash",
|
||||
model: "deepseek-flash",
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
{
|
||||
name: "deepseek v4 flash vision exp",
|
||||
model: "deepseek-v4-flash-vision-exp",
|
||||
expectedInput: 2.2e-7,
|
||||
expectedOutput: floatPtr(6.6e-7),
|
||||
expectedCacheRead: floatPtr(7e-9),
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
{
|
||||
// deepseek-chat / deepseek-reasoner 已停止服务,统一按 flash 价兜底。
|
||||
name: "deepseek chat discontinued maps to flash",
|
||||
model: "deepseek-chat",
|
||||
expectedInput: 2.2e-7,
|
||||
expectedOutput: floatPtr(6.6e-7),
|
||||
expectedCacheRead: floatPtr(7e-9),
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
{
|
||||
name: "deepseek reasoner discontinued maps to flash",
|
||||
model: "deepseek-reasoner",
|
||||
expectedInput: 2.2e-7,
|
||||
expectedOutput: floatPtr(6.6e-7),
|
||||
expectedCacheRead: floatPtr(7e-9),
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
{
|
||||
name: "unknown deepseek maps to flash",
|
||||
model: "deepseek-foo",
|
||||
expectedInput: 2.2e-7,
|
||||
expectedOutput: floatPtr(6.6e-7),
|
||||
expectedCacheRead: floatPtr(7e-9),
|
||||
expectedInput: 1.5e-7,
|
||||
expectedOutput: floatPtr(6e-7),
|
||||
expectedCacheRead: floatPtr(3e-9),
|
||||
},
|
||||
|
||||
// ---- 智谱 GLM(z.ai USD 口径)----
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestDeepseekPeakMultiplierAt(t *testing.T) {
|
||||
|
||||
func TestIsDeepSeekModel(t *testing.T) {
|
||||
deepseek := []string{
|
||||
"deepseek-v4-flash", "deepseek-v4-pro", "deepseek-v4-flash-vision-exp",
|
||||
"deepseek-flash", "deepseek-v4-flash", "deepseek-v4-pro", "deepseek-v4-flash-vision-exp",
|
||||
"deepseek-chat", "deepseek-reasoner", "deepseek-v3-2-251201",
|
||||
"deepseek-coder", "deepseek-foo", "deepseek-v4-pro-0813",
|
||||
"DEEPSEEK-V4-PRO", " deepseek-v4-flash ",
|
||||
@@ -85,8 +85,8 @@ func TestCalculateCostUnified_DeepseekDefaultCardPeakMultiplier(t *testing.T) {
|
||||
resolver := NewModelPricingResolver(nil, bs)
|
||||
|
||||
tokens := UsageTokens{InputTokens: 1000, OutputTokens: 500, CacheReadTokens: 1000}
|
||||
// 低谷成本:1000*2.2e-7 + 500*6.6e-7 + 1000*7e-9 = 5.57e-4
|
||||
offPeakTotal := 1000*2.2e-7 + 500*6.6e-7 + 1000*7e-9
|
||||
// 低谷成本(2026-09-10 官方新价):1000*1.5e-7 + 500*6e-7 + 1000*3e-9 = 4.53e-4
|
||||
offPeakTotal := 1000*1.5e-7 + 500*6e-7 + 1000*3e-9
|
||||
|
||||
offPeak, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: "deepseek-v4-flash", Tokens: tokens,
|
||||
@@ -134,7 +134,7 @@ func TestCalculateCostUnified_DeepseekVersionedNamePeakMultiplier(t *testing.T)
|
||||
resolver := NewModelPricingResolver(nil, bs)
|
||||
|
||||
tokens := UsageTokens{InputTokens: 1000, OutputTokens: 500, CacheReadTokens: 1000}
|
||||
offPeakTotal := 1000*2.2e-7 + 500*6.6e-7 + 1000*7e-9
|
||||
offPeakTotal := 1000*1.5e-7 + 500*6e-7 + 1000*3e-9
|
||||
|
||||
offPeak, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: "deepseek-v4-flash-0731", Tokens: tokens,
|
||||
@@ -170,8 +170,8 @@ func TestCalculateCostUnified_DeepseekGroupPricingNotScaledByPeak(t *testing.T)
|
||||
require.Equal(t, PricingSourceGroup, resolved.Source)
|
||||
|
||||
tokens := UsageTokens{InputTokens: 1000, OutputTokens: 500, CacheReadTokens: 1000}
|
||||
// 分组自定义价:1000*1e-6 + 500*2e-6 + 1000*7e-9(缓存读沿用官方 flash 价)
|
||||
groupTotal := 1000*1e-6 + 500*2e-6 + 1000*7e-9
|
||||
// 分组自定义价:1000*1e-6 + 500*2e-6 + 1000*3e-9(缓存读沿用官方 flash 价)
|
||||
groupTotal := 1000*1e-6 + 500*2e-6 + 1000*3e-9
|
||||
|
||||
for _, pricingAt := range []time.Time{
|
||||
time.Date(2026, 8, 24, 12, 0, 0, 0, time.UTC), // 低谷
|
||||
@@ -238,6 +238,7 @@ func TestCalculateCostUnified_DeepseekPricingAtZeroFallsBackToNow(t *testing.T)
|
||||
func TestGetModelPricing_DeepseekForcesOfficialRatesOverJSON(t *testing.T) {
|
||||
// JSON 给任意价(模拟远端旧价/占位价),deepseek-* 必须被强制覆盖为官方低谷价。
|
||||
pricingSvc := &PricingService{pricingData: map[string]*LiteLLMModelPricing{
|
||||
"deepseek-flash": {InputCostPerToken: 1e-6, OutputCostPerToken: 2e-6, CacheReadInputTokenCost: 1e-8},
|
||||
"deepseek-v4-flash": {InputCostPerToken: 1e-6, OutputCostPerToken: 2e-6, CacheReadInputTokenCost: 1e-8},
|
||||
"deepseek-v4-pro": {InputCostPerToken: 1e-6, OutputCostPerToken: 2e-6, CacheReadInputTokenCost: 1e-8},
|
||||
"deepseek-v4-flash-vision-exp": {InputCostPerToken: 1e-6, OutputCostPerToken: 2e-6, CacheReadInputTokenCost: 1e-8},
|
||||
@@ -250,31 +251,64 @@ func TestGetModelPricing_DeepseekForcesOfficialRatesOverJSON(t *testing.T) {
|
||||
model string
|
||||
input, output, cacheRead float64
|
||||
}{
|
||||
{"deepseek-v4-flash", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-v4-flash-vision-exp", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-v4-pro", 6.6e-7, 1.98e-6, 2.2e-8},
|
||||
// 2026-09-10 官方降价后:deepseek-flash(V4.1-Flash 新名)与旧名
|
||||
// deepseek-v4-flash 同按 Flash 新价。
|
||||
{"deepseek-flash", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-flash", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-flash-vision-exp", 1.5e-7, 6e-7, 3e-9},
|
||||
// 已停服的 chat/reasoner:即使 JSON 有旧条目也按 flash 价兜底。
|
||||
{"deepseek-chat", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-reasoner", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-chat", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-reasoner", 1.5e-7, 6e-7, 3e-9},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.model, func(t *testing.T) {
|
||||
// flash 档三档价与 pro→Flash 切换无关,GetModelPricing 断言不随时间翻转。
|
||||
pricing, err := bs.GetModelPricing(tt.model)
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, tt.input, pricing.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, tt.output, pricing.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, tt.cacheRead, pricing.CacheReadPricePerToken, 1e-15)
|
||||
// 固定时点(切换点之后的 2026-10-01)复核:仍走 Flash 新价。
|
||||
atPricing, err := bs.getModelPricingAt(tt.model, time.Date(2026, 10, 1, 0, 0, 0, 0, time.UTC))
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, tt.input, atPricing.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, tt.output, atPricing.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, tt.cacheRead, atPricing.CacheReadPricePerToken, 1e-15)
|
||||
require.True(t, bs.HasIdentifiedTokenPricing(tt.model))
|
||||
})
|
||||
}
|
||||
|
||||
// pro 档(含版本化名称):断言经固定时点的 getModelPricingAt,不依赖墙上时钟。
|
||||
// 2026-08-01 早于切换点 2026-09-14 04:00 UTC → Pro 价。
|
||||
for _, model := range []string{"deepseek-v4-pro", "deepseek-v4-pro-0813"} {
|
||||
t.Run(model+"/before-cutoff", func(t *testing.T) {
|
||||
pricing, err := bs.getModelPricingAt(model, time.Date(2026, 8, 1, 0, 0, 0, 0, time.UTC))
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, 6.6e-7, pricing.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 1.98e-6, pricing.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 2.2e-8, pricing.CacheReadPricePerToken, 1e-15)
|
||||
})
|
||||
}
|
||||
|
||||
// 半开边界钉死:2026-09-14 03:59:59 仍 Pro 价,04:00:00 整起 Flash 新价。
|
||||
proBefore, err := bs.getModelPricingAt("deepseek-v4-pro", time.Date(2026, 9, 14, 3, 59, 59, 0, time.UTC))
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, 6.6e-7, proBefore.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 1.98e-6, proBefore.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 2.2e-8, proBefore.CacheReadPricePerToken, 1e-15)
|
||||
proAtCutoff, err := bs.getModelPricingAt("deepseek-v4-pro", time.Date(2026, 9, 14, 4, 0, 0, 0, time.UTC))
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, 1.5e-7, proAtCutoff.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 6e-7, proAtCutoff.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 3e-9, proAtCutoff.CacheReadPricePerToken, 1e-15)
|
||||
|
||||
// 版本化名称(不在 JSON / fallbackPrices 精确表中):按子串归档计价。
|
||||
// flash-0731 归 flash 档,三档价与切换无关,GetModelPricing 断言稳定。
|
||||
versioned := []struct {
|
||||
model string
|
||||
input, output, cacheRead float64
|
||||
}{
|
||||
{"deepseek-v4-pro-0813", 6.6e-7, 1.98e-6, 2.2e-8},
|
||||
{"deepseek-v4-flash-0731", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-v4-flash-0731", 1.5e-7, 6e-7, 3e-9},
|
||||
}
|
||||
for _, tt := range versioned {
|
||||
t.Run(tt.model, func(t *testing.T) {
|
||||
@@ -289,7 +323,7 @@ func TestGetModelPricing_DeepseekForcesOfficialRatesOverJSON(t *testing.T) {
|
||||
|
||||
func TestGetModelPricing_UnknownDeepseekMapsToFlash(t *testing.T) {
|
||||
// JSON 含 $0 占位条目(如旧 deepseek-v3-2-251201):未知 deepseek-* 不再
|
||||
// fail-closed,统一按 flash 价兜底(2.2e-7/6.6e-7/7e-9),不得按 $0 计费。
|
||||
// fail-closed,统一按 flash 价兜底(1.5e-7/6e-7/3e-9),不得按 $0 计费。
|
||||
pricingSvc := &PricingService{pricingData: map[string]*LiteLLMModelPricing{
|
||||
"deepseek-v3-2-251201": {InputCostPerToken: 0, OutputCostPerToken: 0},
|
||||
}}
|
||||
@@ -299,9 +333,9 @@ func TestGetModelPricing_UnknownDeepseekMapsToFlash(t *testing.T) {
|
||||
t.Run(m, func(t *testing.T) {
|
||||
pricing, err := bs.GetModelPricing(m)
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, 2.2e-7, pricing.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 6.6e-7, pricing.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 7e-9, pricing.CacheReadPricePerToken, 1e-15)
|
||||
require.InDelta(t, 1.5e-7, pricing.InputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 6e-7, pricing.OutputPricePerToken, 1e-15)
|
||||
require.InDelta(t, 3e-9, pricing.CacheReadPricePerToken, 1e-15)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -329,8 +363,9 @@ func TestDeepseekPricingFileMatchesOfficialRates(t *testing.T) {
|
||||
model string
|
||||
input, output, cacheRead float64
|
||||
}{
|
||||
{"deepseek-v4-flash", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-v4-flash-vision-exp", 2.2e-7, 6.6e-7, 7e-9},
|
||||
{"deepseek-flash", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-flash", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-flash-vision-exp", 1.5e-7, 6e-7, 3e-9},
|
||||
{"deepseek-v4-pro", 6.6e-7, 1.98e-6, 2.2e-8},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -343,3 +378,68 @@ func TestDeepseekPricingFileMatchesOfficialRates(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 2026-09-10 官方降价:deepseek-flash(V4.1-Flash 新名)与旧名同价;
|
||||
// 2026-09-14 04:00 UTC 起 deepseek-v4-pro 按上游路由改按 Flash 价计费
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestCalculateCostUnified_DeepseekFlashAndLegacyFlashShareNewRates(t *testing.T) {
|
||||
bs := newTestBillingService()
|
||||
resolver := NewModelPricingResolver(nil, bs)
|
||||
|
||||
tokens := UsageTokens{InputTokens: 1000, OutputTokens: 500, CacheReadTokens: 1000}
|
||||
// 2026-09-10 官方新低谷价:1000*1.5e-7 + 500*6e-7 + 1000*3e-9 = 4.53e-4
|
||||
offPeakTotal := 1000*1.5e-7 + 500*6e-7 + 1000*3e-9
|
||||
|
||||
// deepseek-flash 与 deepseek-v4-flash 都取 Flash 新价。
|
||||
// 时点取切换日 2026-09-14(周一)12:00 UTC 低谷,峰谷倍率不影响断言。
|
||||
for _, model := range []string{"deepseek-flash", "deepseek-v4-flash"} {
|
||||
cost, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: model, Tokens: tokens,
|
||||
RateMultiplier: 1.0, Resolver: resolver,
|
||||
PricingAt: time.Date(2026, 9, 14, 12, 0, 0, 0, time.UTC),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, offPeakTotal, cost.TotalCost, 1e-10, "model %s must use new flash rates", model)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateCostUnified_DeepseekProRoutesToFlashAtCutoff(t *testing.T) {
|
||||
bs := newTestBillingService()
|
||||
resolver := NewModelPricingResolver(nil, bs)
|
||||
|
||||
tokens := UsageTokens{InputTokens: 1000, OutputTokens: 500, CacheReadTokens: 1000}
|
||||
proTotal := 1000*6.6e-7 + 500*1.98e-6 + 1000*2.2e-8 // 切换前 Pro 价
|
||||
flashTotal := 1000*1.5e-7 + 500*6e-7 + 1000*3e-9 // 切换后 Flash 价
|
||||
|
||||
// 切换时点之前(2026-09-13 周日,北京周末全天低谷):仍按 Pro 价。
|
||||
before, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: "deepseek-v4-pro", Tokens: tokens,
|
||||
RateMultiplier: 1.0, Resolver: resolver,
|
||||
PricingAt: time.Date(2026, 9, 13, 12, 0, 0, 0, time.UTC),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, proTotal, before.TotalCost, 1e-10,
|
||||
"deepseek-v4-pro must use Pro rates before the 2026-09-14 04:00 UTC cutoff")
|
||||
|
||||
// 到达切换时点(2026-09-14 04:00 UTC 整,周一低谷窗口边界外):按 Flash 价。
|
||||
after, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: "deepseek-v4-pro", Tokens: tokens,
|
||||
RateMultiplier: 1.0, Resolver: resolver,
|
||||
PricingAt: time.Date(2026, 9, 14, 4, 0, 0, 0, time.UTC),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, flashTotal, after.TotalCost, 1e-10,
|
||||
"deepseek-v4-pro must use Flash rates at/after the 2026-09-14 04:00 UTC cutoff")
|
||||
|
||||
// 版本化名称同口径:切换后 deepseek-v4-pro-0813 也按 Flash 价。
|
||||
versioned, err := bs.CalculateCostUnified(CostInput{
|
||||
Ctx: context.Background(), Model: "deepseek-v4-pro-0813", Tokens: tokens,
|
||||
RateMultiplier: 1.0, Resolver: resolver,
|
||||
PricingAt: time.Date(2026, 9, 14, 4, 0, 0, 0, time.UTC),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.InDelta(t, flashTotal, versioned.TotalCost, 1e-10,
|
||||
"versioned pro names must also route to Flash rates after the cutoff")
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ func TestGatewayServiceRecordUsage_DeepSeekAccountStatsUsesRequestPricingAtAndUp
|
||||
name string
|
||||
offPeakCost float64
|
||||
}{
|
||||
{"deepseek-v4-flash", 1000*2.2e-7 + 500*6.6e-7 + 1000*7e-9},
|
||||
{"deepseek-v4-flash", 1000*1.5e-7 + 500*6e-7 + 1000*3e-9},
|
||||
{"deepseek-v4-pro", 1000*6.6e-7 + 500*1.98e-6 + 1000*2.2e-8},
|
||||
} {
|
||||
for _, slot := range []struct {
|
||||
|
||||
@@ -575,7 +575,7 @@ func TestOpenAIGatewayServiceRecordUsage_DeepSeekAccountStatsUsesRequestPricingA
|
||||
name string
|
||||
offPeakCost float64
|
||||
}{
|
||||
{"deepseek-v4-flash", 1000*2.2e-7 + 500*6.6e-7 + 1000*7e-9},
|
||||
{"deepseek-v4-flash", 1000*1.5e-7 + 500*6e-7 + 1000*3e-9},
|
||||
{"deepseek-v4-pro", 1000*6.6e-7 + 500*1.98e-6 + 1000*2.2e-8},
|
||||
} {
|
||||
for _, slot := range []struct {
|
||||
|
||||
@@ -2180,7 +2180,8 @@ func supportsOpenAIReasoningEffortMax(model string) bool {
|
||||
normalized := strings.ToLower(lastOpenAIModelSegment(model))
|
||||
normalized = strings.ReplaceAll(normalized, "_", "-")
|
||||
switch {
|
||||
case strings.HasPrefix(normalized, "deepseek-v4"):
|
||||
case strings.HasPrefix(normalized, "deepseek-v4"), strings.HasPrefix(normalized, "deepseek-flash"):
|
||||
// deepseek-flash(= DeepSeek-V4.1-Flash)与 v4 系同为 low/high/max 档位。
|
||||
return true
|
||||
case strings.HasPrefix(normalized, "glm-"):
|
||||
return true
|
||||
|
||||
@@ -69,6 +69,7 @@ func TestNormalizeOpenAIReasoningEffortForMaxCapableModels(t *testing.T) {
|
||||
{name: "Terra 保留 max", raw: "max", model: "openai/gpt-5.6-terra", want: "max"},
|
||||
{name: "Luna 后缀保留 max", raw: "max", model: "gpt-5.6-luna-2026-07-09", want: "max"},
|
||||
{name: "DeepSeek V4 保留 max", raw: "max", model: "deepseek-v4-pro", want: "max"},
|
||||
{name: "DeepSeek Flash 保留 max", raw: "max", model: "deepseek-flash", want: "max"},
|
||||
{name: "旧 GPT 模型沿用 xhigh", raw: "max", model: "gpt-5.5", want: "xhigh"},
|
||||
}
|
||||
|
||||
|
||||
@@ -745,15 +745,38 @@
|
||||
"supports_web_search": true,
|
||||
"supports_xhigh_reasoning_effort": true
|
||||
},
|
||||
"deepseek-v4-flash": {
|
||||
"cache_read_input_token_cost": 7e-09,
|
||||
"input_cost_per_token": 2.2e-07,
|
||||
"deepseek-flash": {
|
||||
"cache_read_input_token_cost": 3e-09,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"litellm_provider": "deepseek",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 393216,
|
||||
"max_tokens": 393216,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 6.6e-07,
|
||||
"output_cost_per_token": 6e-07,
|
||||
"source": "https://api-docs.deepseek.com/quick_start/pricing",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"deepseek-v4-flash": {
|
||||
"cache_read_input_token_cost": 3e-09,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"litellm_provider": "deepseek",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 393216,
|
||||
"max_tokens": 393216,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 6e-07,
|
||||
"source": "https://api-docs.deepseek.com/quick_start/pricing",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions"
|
||||
@@ -768,14 +791,14 @@
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"deepseek-v4-flash-vision-exp": {
|
||||
"cache_read_input_token_cost": 7e-09,
|
||||
"input_cost_per_token": 2.2e-07,
|
||||
"cache_read_input_token_cost": 3e-09,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"litellm_provider": "deepseek",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 393216,
|
||||
"max_tokens": 393216,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 6.6e-07,
|
||||
"output_cost_per_token": 6e-07,
|
||||
"source": "https://api-docs.deepseek.com/quick_start/pricing",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions"
|
||||
|
||||
@@ -116,7 +116,7 @@ const qwenModels = [
|
||||
|
||||
// DeepSeek
|
||||
const deepseekModels = [
|
||||
'deepseek-v4-pro', 'deepseek-v4-flash', 'deepseek-v4-flash-vision-exp',
|
||||
'deepseek-v4-pro', 'deepseek-v4-flash', 'deepseek-v4-flash-vision-exp', 'deepseek-flash',
|
||||
'deepseek-coder',
|
||||
'deepseek-v3', 'deepseek-v3-0324',
|
||||
'deepseek-r1', 'deepseek-r1-0528',
|
||||
|
||||
Reference in New Issue
Block a user