Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
88759407
Commit
88759407
authored
Mar 31, 2026
by
erio
Browse files
feat(channel): 模型映射源支持通配符匹配
与定价通配符一致,映射源支持 * 后缀通配符(最长前缀优先): - `*` 匹配所有模型 - `claude-*` 匹配 claude- 开头的模型 - 精确匹配优先于通配符
parent
6c99cc61
Changes
1
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/channel_service.go
View file @
88759407
...
...
@@ -72,12 +72,19 @@ type wildcardPricingEntry struct {
pricing
*
ChannelModelPricing
}
// wildcardMappingEntry 通配符映射条目
type
wildcardMappingEntry
struct
{
prefix
string
target
string
}
// channelCache 渠道缓存快照(扁平化哈希结构,热路径 O(1) 查找)
type
channelCache
struct
{
// 热路径查找
pricingByGroupModel
map
[
channelModelKey
]
*
ChannelModelPricing
// (groupID, platform, model) → 定价
wildcardByGroupPlatform
map
[
channelGroupPlatformKey
][]
*
wildcardPricingEntry
// (groupID, platform) → 通配符定价(前缀长度降序)
mappingByGroupModel
map
[
channelModelKey
]
string
// (groupID, platform, model) → 映射目标
wildcardMappingByGP
map
[
channelGroupPlatformKey
][]
*
wildcardMappingEntry
// (groupID, platform) → 通配符映射(前缀长度降序)
channelByGroupID
map
[
int64
]
*
Channel
// groupID → 渠道
groupPlatform
map
[
int64
]
string
// groupID → platform
...
...
@@ -173,6 +180,7 @@ func (s *ChannelService) buildCache(ctx context.Context) (*channelCache, error)
pricingByGroupModel
:
make
(
map
[
channelModelKey
]
*
ChannelModelPricing
),
wildcardByGroupPlatform
:
make
(
map
[
channelGroupPlatformKey
][]
*
wildcardPricingEntry
),
mappingByGroupModel
:
make
(
map
[
channelModelKey
]
string
),
wildcardMappingByGP
:
make
(
map
[
channelGroupPlatformKey
][]
*
wildcardMappingEntry
),
channelByGroupID
:
make
(
map
[
int64
]
*
Channel
),
groupPlatform
:
make
(
map
[
int64
]
string
),
byID
:
make
(
map
[
int64
]
*
Channel
),
...
...
@@ -200,6 +208,7 @@ func (s *ChannelService) buildCache(ctx context.Context) (*channelCache, error)
pricingByGroupModel
:
make
(
map
[
channelModelKey
]
*
ChannelModelPricing
),
wildcardByGroupPlatform
:
make
(
map
[
channelGroupPlatformKey
][]
*
wildcardPricingEntry
),
mappingByGroupModel
:
make
(
map
[
channelModelKey
]
string
),
wildcardMappingByGP
:
make
(
map
[
channelGroupPlatformKey
][]
*
wildcardMappingEntry
),
channelByGroupID
:
make
(
map
[
int64
]
*
Channel
),
groupPlatform
:
groupPlatforms
,
byID
:
make
(
map
[
int64
]
*
Channel
,
len
(
channels
)),
...
...
@@ -240,8 +249,18 @@ func (s *ChannelService) buildCache(ctx context.Context) (*channelCache, error)
// 只展开该平台的模型映射到 (groupID, platform, model) → target
if
platformMapping
,
ok
:=
ch
.
ModelMapping
[
platform
];
ok
{
for
src
,
dst
:=
range
platformMapping
{
key
:=
channelModelKey
{
groupID
:
gid
,
platform
:
platform
,
model
:
strings
.
ToLower
(
src
)}
cache
.
mappingByGroupModel
[
key
]
=
dst
if
strings
.
HasSuffix
(
src
,
"*"
)
{
// 通配符映射 → 存入 wildcardMappingByGP
prefix
:=
strings
.
ToLower
(
strings
.
TrimSuffix
(
src
,
"*"
))
gpKey
:=
channelGroupPlatformKey
{
groupID
:
gid
,
platform
:
platform
}
cache
.
wildcardMappingByGP
[
gpKey
]
=
append
(
cache
.
wildcardMappingByGP
[
gpKey
],
&
wildcardMappingEntry
{
prefix
:
prefix
,
target
:
dst
,
})
}
else
{
key
:=
channelModelKey
{
groupID
:
gid
,
platform
:
platform
,
model
:
strings
.
ToLower
(
src
)}
cache
.
mappingByGroupModel
[
key
]
=
dst
}
}
}
}
...
...
@@ -254,6 +273,12 @@ func (s *ChannelService) buildCache(ctx context.Context) (*channelCache, error)
})
cache
.
wildcardByGroupPlatform
[
gpKey
]
=
entries
}
for
gpKey
,
entries
:=
range
cache
.
wildcardMappingByGP
{
sort
.
Slice
(
entries
,
func
(
i
,
j
int
)
bool
{
return
len
(
entries
[
i
]
.
prefix
)
>
len
(
entries
[
j
]
.
prefix
)
})
cache
.
wildcardMappingByGP
[
gpKey
]
=
entries
}
s
.
cache
.
Store
(
cache
)
return
cache
,
nil
...
...
@@ -277,6 +302,18 @@ func (c *channelCache) matchWildcard(groupID int64, platform, modelLower string)
return
nil
}
// matchWildcardMapping 在通配符映射中查找匹配项(最长前缀优先)
func
(
c
*
channelCache
)
matchWildcardMapping
(
groupID
int64
,
platform
,
modelLower
string
)
string
{
gpKey
:=
channelGroupPlatformKey
{
groupID
:
groupID
,
platform
:
platform
}
wildcards
:=
c
.
wildcardMappingByGP
[
gpKey
]
for
_
,
wc
:=
range
wildcards
{
if
strings
.
HasPrefix
(
modelLower
,
wc
.
prefix
)
{
return
wc
.
target
}
}
return
""
}
// GetChannelForGroup 获取分组关联的渠道(热路径 O(1))
func
(
s
*
ChannelService
)
GetChannelForGroup
(
ctx
context
.
Context
,
groupID
int64
)
(
*
Channel
,
error
)
{
cache
,
err
:=
s
.
loadCache
(
ctx
)
...
...
@@ -348,6 +385,9 @@ func (s *ChannelService) ResolveChannelMapping(ctx context.Context, groupID int6
if
mapped
,
ok
:=
cache
.
mappingByGroupModel
[
key
];
ok
{
result
.
MappedModel
=
mapped
result
.
Mapped
=
true
}
else
if
mapped
:=
cache
.
matchWildcardMapping
(
groupID
,
platform
,
strings
.
ToLower
(
model
));
mapped
!=
""
{
result
.
MappedModel
=
mapped
result
.
Mapped
=
true
}
return
result
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment