-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
feat: 实现模型别名系统,支持跨渠道统一模型名称 #2311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,8 +54,12 @@ func (channel *Channel) AddAbilities() error { | |
| models_ := strings.Split(channel.Models, ",") | ||
| models_ = utils.DeDuplication(models_) | ||
| groups_ := strings.Split(channel.Group, ",") | ||
| abilities := make([]Ability, 0, len(models_)) | ||
| for _, model := range models_ { | ||
|
|
||
| // Expand models to include aliases for standard names | ||
| expandedModels := expandModelsWithAliases(models_, channel.Type) | ||
|
|
||
| abilities := make([]Ability, 0, len(expandedModels)) | ||
| for _, model := range expandedModels { | ||
| for _, group := range groups_ { | ||
| ability := Ability{ | ||
| Group: group, | ||
|
|
@@ -70,6 +74,73 @@ func (channel *Channel) AddAbilities() error { | |
| return DB.Create(&abilities).Error | ||
| } | ||
|
|
||
| // expandModelsWithAliases expands model list to include standard names for channel-specific models | ||
| func expandModelsWithAliases(models []string, channelType int) []string { | ||
| expandedModels := make([]string, 0) | ||
| modelSet := make(map[string]bool) | ||
|
|
||
| for _, model := range models { | ||
| model = strings.TrimSpace(model) | ||
| if model == "" { | ||
| continue | ||
| } | ||
|
|
||
| // Add original model | ||
| if !modelSet[model] { | ||
| expandedModels = append(expandedModels, model) | ||
| modelSet[model] = true | ||
| } | ||
|
|
||
| // Try to find standard name for this channel-specific model | ||
| standardName := getStandardModelNameForChannel(model, channelType) | ||
| if standardName != model && !modelSet[standardName] { | ||
| expandedModels = append(expandedModels, standardName) | ||
| modelSet[standardName] = true | ||
| } | ||
| } | ||
|
|
||
| return expandedModels | ||
| } | ||
|
|
||
| // getStandardModelNameForChannel returns the standard name for a channel-specific model | ||
| func getStandardModelNameForChannel(actualName string, channelType int) string { | ||
| // Import alias mapping (we'll create a lightweight version here to avoid circular imports) | ||
| aliasMap := getModelAliasesForChannelType(channelType) | ||
|
|
||
| for standard, actual := range aliasMap { | ||
| if actual == actualName { | ||
| return standard | ||
| } | ||
| } | ||
|
|
||
| return actualName | ||
| } | ||
|
|
||
| // getModelAliasesForChannelType returns model aliases for specific channel type | ||
| // This is a lightweight version to avoid importing the full alias module | ||
| func getModelAliasesForChannelType(channelType int) map[string]string { | ||
| switch channelType { | ||
| case 24: // OpenRouter | ||
| return map[string]string{ | ||
| "gpt-4o": "openai/gpt-4o", | ||
| "gpt-4o-mini": "openai/gpt-4o-mini", | ||
| "gpt-4": "openai/gpt-4", | ||
| "gpt-4-turbo": "openai/gpt-4-turbo", | ||
| "gpt-3.5-turbo": "openai/gpt-3.5-turbo", | ||
| "o1": "openai/o1", | ||
| "o1-mini": "openai/o1-mini", | ||
| "o1-preview": "openai/o1-preview", | ||
| "claude-3-haiku": "anthropic/claude-3-haiku", | ||
| "claude-3-sonnet": "anthropic/claude-3-sonnet", | ||
| "claude-3-opus": "anthropic/claude-3-opus", | ||
| "claude-3.5-sonnet": "anthropic/claude-3.5-sonnet", | ||
| "claude-3.5-haiku": "anthropic/claude-3.5-haiku", | ||
| } | ||
| default: | ||
| return map[string]string{} | ||
| } | ||
| } | ||
|
Comment on lines
+121
to
+142
|
||
|
|
||
| func (channel *Channel) DeleteAbilities() error { | ||
| return DB.Where("channel_id = ?", channel.Id).Delete(&Ability{}).Error | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -692,23 +692,90 @@ func GetModelRatio(name string, channelType int) float64 { | |||||||||||||||||||||||||||||||||||||||||||||||||||
| if strings.HasPrefix(name, "command-") && strings.HasSuffix(name, "-internet") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| name = strings.TrimSuffix(name, "-internet") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try channel-specific model ratio first | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| model := fmt.Sprintf("%s(%d)", name, channelType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := ModelRatio[model]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := DefaultModelRatio[model]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try direct model name | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := ModelRatio[name]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := DefaultModelRatio[name]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try to find standard model name for alias lookup | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standardName := getStandardModelNameForBilling(name, channelType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if standardName != name { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try standard model name | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := ModelRatio[standardName]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := DefaultModelRatio[standardName]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try standard model with channel type | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standardModel := fmt.Sprintf("%s(%d)", standardName, channelType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := ModelRatio[standardModel]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ratio, ok := DefaultModelRatio[standardModel]; ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ratio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.SysError("model ratio not found: " + name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 30 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // getStandardModelNameForBilling returns the standard model name for billing lookup | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| func getStandardModelNameForBilling(actualName string, channelType int) string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Reverse alias mapping for billing | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| aliasMap := getBillingAliasMap(channelType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| for standard, actual := range aliasMap { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if actual == actualName { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return standard | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| return actualName | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // getBillingAliasMap returns alias mapping for billing purposes | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| func getBillingAliasMap(channelType int) map[string]string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch channelType { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 24: // OpenRouter | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return map[string]string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gpt-4o": "openai/gpt-4o", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gpt-4o-mini": "openai/gpt-4o-mini", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gpt-4": "openai/gpt-4", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gpt-4-turbo": "openai/gpt-4-turbo", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gpt-3.5-turbo": "openai/gpt-3.5-turbo", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-haiku": "anthropic/claude-3-haiku", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-sonnet": "anthropic/claude-3-sonnet", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-opus": "anthropic/claude-3-opus", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3.5-sonnet": "anthropic/claude-3.5-sonnet", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 18: // Anthropic | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return map[string]string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-haiku": "claude-3-haiku-20240307", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-sonnet": "claude-3-sonnet-20240229", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3-opus": "claude-3-opus-20240229", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "claude-3.5-sonnet": "claude-3-5-sonnet-20241022", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return map[string]string{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+754
to
+776
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch channelType { | |
| case 24: // OpenRouter | |
| return map[string]string{ | |
| "gpt-4o": "openai/gpt-4o", | |
| "gpt-4o-mini": "openai/gpt-4o-mini", | |
| "gpt-4": "openai/gpt-4", | |
| "gpt-4-turbo": "openai/gpt-4-turbo", | |
| "gpt-3.5-turbo": "openai/gpt-3.5-turbo", | |
| "claude-3-haiku": "anthropic/claude-3-haiku", | |
| "claude-3-sonnet": "anthropic/claude-3-sonnet", | |
| "claude-3-opus": "anthropic/claude-3-opus", | |
| "claude-3.5-sonnet": "anthropic/claude-3.5-sonnet", | |
| } | |
| case 18: // Anthropic | |
| return map[string]string{ | |
| "claude-3-haiku": "claude-3-haiku-20240307", | |
| "claude-3-sonnet": "claude-3-sonnet-20240229", | |
| "claude-3-opus": "claude-3-opus-20240229", | |
| "claude-3.5-sonnet": "claude-3-5-sonnet-20241022", | |
| } | |
| default: | |
| return map[string]string{} | |
| } | |
| // Use the alias mapping from relay/model/alias.go as the single source of truth | |
| return model.GetAliasMap(channelType) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,64 @@ func getMappedModelName(modelName string, mapping map[string]string) (string, bo | |
| return modelName, false | ||
| } | ||
|
|
||
| // resolveModelAlias resolves standard model names to channel-specific names | ||
| func resolveModelAlias(modelName string, channelType int) string { | ||
| // Lightweight alias resolution to avoid circular imports | ||
| aliasMap := getChannelModelAliases(channelType) | ||
|
|
||
| if actualName, exists := aliasMap[modelName]; exists { | ||
| return actualName | ||
| } | ||
|
|
||
| return modelName | ||
| } | ||
|
|
||
| // getChannelModelAliases returns model aliases for specific channel type | ||
| func getChannelModelAliases(channelType int) map[string]string { | ||
| switch channelType { | ||
| case 24: // OpenRouter | ||
| return map[string]string{ | ||
| "gpt-4o": "openai/gpt-4o", | ||
| "gpt-4o-mini": "openai/gpt-4o-mini", | ||
| "gpt-4": "openai/gpt-4", | ||
| "gpt-4-turbo": "openai/gpt-4-turbo", | ||
| "gpt-3.5-turbo": "openai/gpt-3.5-turbo", | ||
| "gpt-3.5-turbo-0125": "openai/gpt-3.5-turbo-0125", | ||
| "o1": "openai/o1", | ||
| "o1-mini": "openai/o1-mini", | ||
| "o1-preview": "openai/o1-preview", | ||
| "claude-3-haiku": "anthropic/claude-3-haiku", | ||
| "claude-3-sonnet": "anthropic/claude-3-sonnet", | ||
| "claude-3-opus": "anthropic/claude-3-opus", | ||
| "claude-3.5-sonnet": "anthropic/claude-3.5-sonnet", | ||
| "claude-3.5-haiku": "anthropic/claude-3.5-haiku", | ||
| } | ||
| case 18: // Anthropic | ||
| return map[string]string{ | ||
| "claude-3-haiku": "claude-3-haiku-20240307", | ||
| "claude-3-sonnet": "claude-3-sonnet-20240229", | ||
| "claude-3-opus": "claude-3-opus-20240229", | ||
| "claude-3.5-sonnet": "claude-3-5-sonnet-20241022", | ||
| "claude-3.5-haiku": "claude-3-5-haiku-20241022", | ||
| } | ||
| case 28: // Gemini | ||
| return map[string]string{ | ||
| "gemini-pro": "gemini-pro", | ||
| "gemini-pro-1.5": "gemini-1.5-pro-latest", | ||
| "gemini-flash-1.5": "gemini-1.5-flash-latest", | ||
| } | ||
| case 33: // Groq | ||
| return map[string]string{ | ||
| "llama-3-8b-instruct": "llama3-8b-8192", | ||
| "llama-3-70b-instruct": "llama3-70b-8192", | ||
| "llama-3.1-8b-instruct": "llama-3.1-8b-instant", | ||
| "llama-3.1-70b-instruct": "llama-3.1-70b-versatile", | ||
| } | ||
| default: | ||
| return map[string]string{} | ||
| } | ||
| } | ||
|
Comment on lines
+167
to
+210
|
||
|
|
||
| func isErrorHappened(meta *meta.Meta, resp *http.Response) bool { | ||
| if resp == nil { | ||
| if meta.ChannelType == channeltype.AwsClaude { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic numbers are used for channel types instead of constants from the channeltype package. This makes the code harder to maintain and understand. Consider using channeltype.OpenRouter, etc.