fix: 模型列表仅显示已启用渠道中的模型
This commit is contained in:
@@ -49,15 +49,22 @@ func (h *Handler) todayUsage(c *gin.Context, userID uint64) gin.H {
|
||||
}
|
||||
|
||||
// UserModels GET /api/v1/user/models — 控制台可用模型列表(无需 API Key)。
|
||||
// 仅返回启用的模型且至少绑定到一个启用且健康的渠道,与 /v1/models 口径一致。
|
||||
func (h *Handler) UserModels(c *gin.Context) {
|
||||
var ms []store.Model
|
||||
if err := h.a.DB.Where("enabled = ?", true).Order("sort ASC, id ASC").Find(&ms).Error; err != nil {
|
||||
var names []string
|
||||
if err := h.a.DB.Table("models").
|
||||
Joins("JOIN channel_model_bindings ON channel_model_bindings.model_id = models.id").
|
||||
Joins("JOIN channels ON channels.id = channel_model_bindings.channel_id").
|
||||
Where("models.enabled = ? AND channels.enabled = ? AND channels.health_status = ?",
|
||||
true, true, store.ChannelHealthHealthy).
|
||||
Distinct("models.name").
|
||||
Order("models.sort ASC, models.id ASC").
|
||||
Pluck("models.name", &names).Error; err != nil {
|
||||
resp.Fail(c, http.StatusInternalServerError, "failed to load models")
|
||||
return
|
||||
}
|
||||
out := make([]string, 0, len(ms))
|
||||
for _, m := range ms {
|
||||
out = append(out, m.Name)
|
||||
if names == nil {
|
||||
names = []string{}
|
||||
}
|
||||
resp.OK(c, gin.H{"items": out})
|
||||
resp.OK(c, gin.H{"items": names})
|
||||
}
|
||||
|
||||
@@ -87,6 +87,20 @@ func (s *Service) loadBound(bindings []store.ChannelModelBinding) []Candidate {
|
||||
return out
|
||||
}
|
||||
|
||||
// AvailableModelIDs 返回对外可见的模型 ID:启用的模型且至少绑定到一个启用且健康的渠道。
|
||||
// 与 Candidates 的过滤口径一致(enabled + health_status=healthy),避免暴露绑定到已停用渠道的模型。
|
||||
func (s *Service) AvailableModelIDs() []uint64 {
|
||||
var ids []uint64
|
||||
s.db.Model(&store.ChannelModelBinding{}).
|
||||
Joins("JOIN channels ON channels.id = channel_model_bindings.channel_id").
|
||||
Joins("JOIN models ON models.id = channel_model_bindings.model_id").
|
||||
Where("channels.enabled = ? AND channels.health_status = ?", true, store.ChannelHealthHealthy).
|
||||
Where("models.enabled = ?", true).
|
||||
Distinct("channel_model_bindings.model_id").
|
||||
Pluck("channel_model_bindings.model_id", &ids)
|
||||
return ids
|
||||
}
|
||||
|
||||
// Pick 按权重加权随机选一个候选渠道(负载均衡)。
|
||||
func (s *Service) Pick(cands []Candidate) *store.Channel {
|
||||
if len(cands) == 0 {
|
||||
|
||||
@@ -207,10 +207,15 @@ func (g *Gateway) Handle(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// models GET /v1/models:返回启用的全局模型(OpenAI 风格)。
|
||||
// models GET /v1/models:返回对外可见的模型(启用且至少绑定到一个启用且健康的渠道;OpenAI 风格)。
|
||||
func (g *Gateway) models(c *gin.Context) {
|
||||
ids := g.ch.AvailableModelIDs()
|
||||
if len(ids) == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{"object": "list", "data": []gin.H{}})
|
||||
return
|
||||
}
|
||||
var ms []store.Model
|
||||
if err := g.db.Where("enabled = ?", true).Order("sort ASC, id ASC").Find(&ms).Error; err != nil {
|
||||
if err := g.db.Where("id IN ? AND enabled = ?", ids, true).Order("sort ASC, id ASC").Find(&ms).Error; err != nil {
|
||||
apiError(c, http.StatusInternalServerError, "internal_error", "failed to load models")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user