mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
Merge pull request #4755 from wucm667/fix/issue-4754-channel-pricing-model-normalization
fix(billing): normalize channel pricing model names
This commit is contained in:
@@ -60,6 +60,16 @@ type channelModelKey struct {
|
||||
model string // lowercase
|
||||
}
|
||||
|
||||
// normalizeChannelPricingModelName makes Anthropic's dot and hyphen spelling
|
||||
// differences equivalent in channel pricing cache keys.
|
||||
func normalizeChannelPricingModelName(model string) string {
|
||||
model = strings.ToLower(strings.TrimSpace(model))
|
||||
if strings.HasPrefix(model, "claude-") {
|
||||
model = strings.ReplaceAll(model, ".", "-")
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
// channelGroupPlatformKey 通配符定价缓存键
|
||||
type channelGroupPlatformKey struct {
|
||||
groupID int64
|
||||
@@ -217,13 +227,13 @@ func expandPricingToCache(cache *channelCache, ch *Channel, gid int64, platform
|
||||
gpKey := channelGroupPlatformKey{groupID: gid, platform: pricingPlatform}
|
||||
for _, model := range pricing.Models {
|
||||
if strings.HasSuffix(model, "*") {
|
||||
prefix := strings.ToLower(strings.TrimSuffix(model, "*"))
|
||||
prefix := normalizeChannelPricingModelName(strings.TrimSuffix(model, "*"))
|
||||
cache.wildcardByGroupPlatform[gpKey] = append(cache.wildcardByGroupPlatform[gpKey], &wildcardPricingEntry{
|
||||
prefix: prefix,
|
||||
pricing: pricing,
|
||||
})
|
||||
} else {
|
||||
key := channelModelKey{groupID: gid, platform: pricingPlatform, model: strings.ToLower(model)}
|
||||
key := channelModelKey{groupID: gid, platform: pricingPlatform, model: normalizeChannelPricingModelName(model)}
|
||||
cache.pricingByGroupModel[key] = pricing
|
||||
}
|
||||
}
|
||||
@@ -402,6 +412,7 @@ func (c *channelCache) matchWildcardMapping(groupID int64, platform, modelLower
|
||||
// lookupPricingAcrossPlatforms 在分组平台内查找模型定价。
|
||||
// 各平台严格独立,只在本平台内查找(先精确匹配,再通配符)。
|
||||
func lookupPricingAcrossPlatforms(cache *channelCache, groupID int64, groupPlatform, modelLower string) *ChannelModelPricing {
|
||||
modelLower = normalizeChannelPricingModelName(modelLower)
|
||||
for _, p := range matchingPlatforms(groupPlatform) {
|
||||
key := channelModelKey{groupID: groupID, platform: p, model: modelLower}
|
||||
if pricing, ok := cache.pricingByGroupModel[key]; ok {
|
||||
|
||||
@@ -675,6 +675,25 @@ func TestGetChannelModelPricing_CaseInsensitive(t *testing.T) {
|
||||
require.Equal(t, int64(100), result.ID)
|
||||
}
|
||||
|
||||
func TestGetChannelModelPricing_NormalizesDotsAndHyphens(t *testing.T) {
|
||||
ch := Channel{
|
||||
ID: 1,
|
||||
Status: StatusActive,
|
||||
GroupIDs: []int64{10},
|
||||
ModelPricing: []ChannelModelPricing{
|
||||
{ID: 100, Platform: "anthropic", Models: []string{"claude-opus-4.8"}, BillingMode: BillingModePerRequest, PerRequestPrice: testPtrFloat64(0.007)},
|
||||
},
|
||||
}
|
||||
repo := makeStandardRepo(ch, map[int64]string{10: "anthropic"})
|
||||
svc := newTestChannelService(repo)
|
||||
|
||||
result := svc.GetChannelModelPricing(context.Background(), 10, "claude-opus-4-8")
|
||||
require.NotNil(t, result)
|
||||
require.Equal(t, int64(100), result.ID)
|
||||
require.Equal(t, BillingModePerRequest, result.BillingMode)
|
||||
require.InDelta(t, 0.007, *result.PerRequestPrice, 1e-12)
|
||||
}
|
||||
|
||||
func TestGetChannelModelPricing_WildcardMatch(t *testing.T) {
|
||||
ch := Channel{
|
||||
ID: 1,
|
||||
|
||||
Reference in New Issue
Block a user