🚀 refactor: refine pricing refresh logic & hide disabled models
Summary
-------
1. Pricing generation
• `model/pricing.go`: skip any model whose `status != 1` when building
`pricingMap`, ensuring disabled models are never returned to the
front-end.
2. Cache refresh placement
• `controller/model_meta.go`
– Removed `model.RefreshPricing()` from pure read handlers
(`GetAllModelsMeta`, `SearchModelsMeta`).
– Kept refresh only in mutating handlers
(`Create`, `Update`, `Delete`), guaranteeing data is updated
immediately after an admin change while avoiding redundant work
on every read.
Result
------
Front-end no longer receives information about disabled models, and
pricing cache refreshes occur exactly when model data is modified,
improving efficiency and consistency.
This commit is contained in:
@@ -13,8 +13,6 @@ import (
|
||||
// GetAllModelsMeta 获取模型列表(分页)
|
||||
func GetAllModelsMeta(c *gin.Context) {
|
||||
|
||||
model.RefreshPricing()
|
||||
|
||||
pageInfo := common.GetPageQuery(c)
|
||||
modelsMeta, err := model.GetAllModels(pageInfo.GetStartIdx(), pageInfo.GetPageSize())
|
||||
if err != nil {
|
||||
@@ -35,8 +33,6 @@ func GetAllModelsMeta(c *gin.Context) {
|
||||
// SearchModelsMeta 搜索模型列表
|
||||
func SearchModelsMeta(c *gin.Context) {
|
||||
|
||||
model.RefreshPricing()
|
||||
|
||||
keyword := c.Query("keyword")
|
||||
vendor := c.Query("vendor")
|
||||
pageInfo := common.GetPageQuery(c)
|
||||
@@ -87,6 +83,7 @@ func CreateModelMeta(c *gin.Context) {
|
||||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
model.RefreshPricing()
|
||||
common.ApiSuccess(c, &m)
|
||||
}
|
||||
|
||||
@@ -116,6 +113,7 @@ func UpdateModelMeta(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
model.RefreshPricing()
|
||||
common.ApiSuccess(c, &m)
|
||||
}
|
||||
|
||||
@@ -131,6 +129,7 @@ func DeleteModelMeta(c *gin.Context) {
|
||||
common.ApiError(c, err)
|
||||
return
|
||||
}
|
||||
model.RefreshPricing()
|
||||
common.ApiSuccess(c, nil)
|
||||
}
|
||||
|
||||
@@ -149,5 +148,4 @@ func fillModelExtra(m *model.Model) {
|
||||
m.EnableGroups = model.GetModelEnableGroups(m.ModelName)
|
||||
// 填充计费类型
|
||||
m.QuotaType = model.GetModelQuotaType(m.ModelName)
|
||||
|
||||
}
|
||||
|
||||
@@ -118,15 +118,19 @@ func updatePricing() {
|
||||
for _, m := range prefixList {
|
||||
for _, pricingModel := range enableAbilities {
|
||||
if strings.HasPrefix(pricingModel.Model, m.ModelName) {
|
||||
metaMap[pricingModel.Model] = m
|
||||
}
|
||||
if _, exists := metaMap[pricingModel.Model]; !exists {
|
||||
metaMap[pricingModel.Model] = m
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, m := range suffixList {
|
||||
for _, pricingModel := range enableAbilities {
|
||||
if strings.HasSuffix(pricingModel.Model, m.ModelName) {
|
||||
metaMap[pricingModel.Model] = m
|
||||
}
|
||||
if _, exists := metaMap[pricingModel.Model]; !exists {
|
||||
metaMap[pricingModel.Model] = m
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, m := range containsList {
|
||||
@@ -205,8 +209,12 @@ func updatePricing() {
|
||||
SupportedEndpointTypes: modelSupportEndpointTypes[model],
|
||||
}
|
||||
|
||||
// 补充模型元数据(描述、标签、供应商等)
|
||||
// 补充模型元数据(描述、标签、供应商、状态)
|
||||
if meta, ok := metaMap[model]; ok {
|
||||
// 若模型被禁用(status!=1),则直接跳过,不返回给前端
|
||||
if meta.Status != 1 {
|
||||
continue
|
||||
}
|
||||
pricing.Description = meta.Description
|
||||
pricing.Tags = meta.Tags
|
||||
pricing.VendorID = meta.VendorID
|
||||
|
||||
@@ -305,7 +305,6 @@ const EditModelModal = (props) => {
|
||||
label={t('模型名称')}
|
||||
placeholder={t('请输入模型名称,如:gpt-4')}
|
||||
rules={[{ required: true, message: t('请输入模型名称') }]}
|
||||
disabled={isEdit || !!props.editingModel?.model_name}
|
||||
showClear
|
||||
/>
|
||||
</Col>
|
||||
@@ -317,9 +316,8 @@ const EditModelModal = (props) => {
|
||||
placeholder={t('请选择名称匹配类型')}
|
||||
optionList={nameRuleOptions.map(o => ({ label: t(o.label), value: o.value }))}
|
||||
rules={[{ required: true, message: t('请选择名称匹配类型') }]}
|
||||
disabled={!!props.editingModel?.model_name} // 通过未配置模型过来的禁用选择
|
||||
style={{ width: '100%' }}
|
||||
extraText={t('根据模型名称和匹配规则查找模型元数据,优先级:精确 > 前缀 > 后缀 > 包含')}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
@@ -339,13 +337,13 @@ const EditModelModal = (props) => {
|
||||
placeholder={t('选择标签组后将自动填充标签')}
|
||||
optionList={tagGroups.map(g => ({ label: g.name, value: g.id }))}
|
||||
showClear
|
||||
style={{ width: '100%' }}
|
||||
onChange={(value) => {
|
||||
const g = tagGroups.find(item => item.id === value);
|
||||
if (g && formApiRef.current) {
|
||||
formApiRef.current.setValue('tags', g.items || []);
|
||||
}
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
@@ -356,7 +354,6 @@ const EditModelModal = (props) => {
|
||||
placeholder={t('输入标签或使用","分隔多个标签')}
|
||||
addOnBlur
|
||||
showClear
|
||||
style={{ width: '100%' }}
|
||||
onChange={(newTags) => {
|
||||
if (!formApiRef.current) return;
|
||||
const normalize = (tags) => {
|
||||
@@ -366,6 +363,7 @@ const EditModelModal = (props) => {
|
||||
const normalized = normalize(newTags);
|
||||
formApiRef.current.setValue('tags', normalized);
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -391,13 +389,13 @@ const EditModelModal = (props) => {
|
||||
optionList={vendors.map(v => ({ label: v.name, value: v.id }))}
|
||||
filter
|
||||
showClear
|
||||
style={{ width: '100%' }}
|
||||
onChange={(value) => {
|
||||
const vendorInfo = vendors.find(v => v.id === value);
|
||||
if (vendorInfo && formApiRef.current) {
|
||||
formApiRef.current.setValue('vendor', vendorInfo.name);
|
||||
}
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
Reference in New Issue
Block a user