Merge pull request #2316 from router-for-me/openai

Add per-model thinking support for OpenAI compatibility
This commit is contained in:
Luis Pater
2026-03-25 09:31:28 +08:00
committed by GitHub
4 changed files with 19 additions and 7 deletions

View File

@@ -206,7 +206,9 @@ nonstream-keepalive-interval: 0
# - api-key: "sk-or-v1-...b781" # without proxy-url # - api-key: "sk-or-v1-...b781" # without proxy-url
# models: # The models supported by the provider. # models: # The models supported by the provider.
# - name: "moonshotai/kimi-k2:free" # The actual model name. # - name: "moonshotai/kimi-k2:free" # The actual model name.
# alias: "kimi-k2" # The alias used in the API. # alias: "kimi-k2" # The alias used in the API.
# thinking: # optional: omit to default to levels ["low","medium","high"]
# levels: ["low", "medium", "high"]
# # You may repeat the same alias to build an internal model pool. # # You may repeat the same alias to build an internal model pool.
# # The client still sees only one alias in the model list. # # The client still sees only one alias in the model list.
# # Requests to that alias will round-robin across the upstream names below, # # Requests to that alias will round-robin across the upstream names below,

View File

@@ -13,6 +13,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/router-for-me/CLIProxyAPI/v6/internal/registry"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@@ -511,6 +512,10 @@ type OpenAICompatibilityModel struct {
// Alias is the model name alias that clients will use to reference this model. // Alias is the model name alias that clients will use to reference this model.
Alias string `yaml:"alias" json:"alias"` Alias string `yaml:"alias" json:"alias"`
// Thinking configures the thinking/reasoning capability for this model.
// If nil, the model defaults to level-based reasoning with levels ["low", "medium", "high"].
Thinking *registry.ThinkingSupport `yaml:"thinking,omitempty" json:"thinking,omitempty"`
} }
func (m OpenAICompatibilityModel) GetName() string { return m.Name } func (m OpenAICompatibilityModel) GetName() string { return m.Name }

View File

@@ -71,16 +71,16 @@ type availableModelsCacheEntry struct {
// Values are interpreted in provider-native token units. // Values are interpreted in provider-native token units.
type ThinkingSupport struct { type ThinkingSupport struct {
// Min is the minimum allowed thinking budget (inclusive). // Min is the minimum allowed thinking budget (inclusive).
Min int `json:"min,omitempty"` Min int `json:"min,omitempty" yaml:"min,omitempty"`
// Max is the maximum allowed thinking budget (inclusive). // Max is the maximum allowed thinking budget (inclusive).
Max int `json:"max,omitempty"` Max int `json:"max,omitempty" yaml:"max,omitempty"`
// ZeroAllowed indicates whether 0 is a valid value (to disable thinking). // ZeroAllowed indicates whether 0 is a valid value (to disable thinking).
ZeroAllowed bool `json:"zero_allowed,omitempty"` ZeroAllowed bool `json:"zero_allowed,omitempty" yaml:"zero-allowed,omitempty"`
// DynamicAllowed indicates whether -1 is a valid value (dynamic thinking budget). // DynamicAllowed indicates whether -1 is a valid value (dynamic thinking budget).
DynamicAllowed bool `json:"dynamic_allowed,omitempty"` DynamicAllowed bool `json:"dynamic_allowed,omitempty" yaml:"dynamic-allowed,omitempty"`
// Levels defines discrete reasoning effort levels (e.g., "low", "medium", "high"). // Levels defines discrete reasoning effort levels (e.g., "low", "medium", "high").
// When set, the model uses level-based reasoning instead of token budgets. // When set, the model uses level-based reasoning instead of token budgets.
Levels []string `json:"levels,omitempty"` Levels []string `json:"levels,omitempty" yaml:"levels,omitempty"`
} }
// ModelRegistration tracks a model's availability // ModelRegistration tracks a model's availability

View File

@@ -960,6 +960,10 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
if modelID == "" { if modelID == "" {
modelID = m.Name modelID = m.Name
} }
thinking := m.Thinking
if thinking == nil {
thinking = &registry.ThinkingSupport{Levels: []string{"low", "medium", "high"}}
}
ms = append(ms, &ModelInfo{ ms = append(ms, &ModelInfo{
ID: modelID, ID: modelID,
Object: "model", Object: "model",
@@ -967,7 +971,8 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
OwnedBy: compat.Name, OwnedBy: compat.Name,
Type: "openai-compatibility", Type: "openai-compatibility",
DisplayName: modelID, DisplayName: modelID,
UserDefined: true, UserDefined: false,
Thinking: thinking,
}) })
} }
// Register and return // Register and return