diff --git a/common/api_type.go b/common/api_type.go index 44841e11b8fc..b92cbaea3f16 100644 --- a/common/api_type.go +++ b/common/api_type.go @@ -81,6 +81,8 @@ func ChannelType2APIType(channelType int) (int, bool) { apiType = constant.APITypeSub2API case constant.ChannelTypeNewAPI: apiType = constant.APITypeNewAPI + case constant.ChannelTypeAvalAI: + apiType = constant.APITypeAvalAI } if apiType == -1 { return constant.APITypeOpenAI, false diff --git a/constant/api_type.go b/constant/api_type.go index 2a561c6d2bfd..9a7b0e108c10 100644 --- a/constant/api_type.go +++ b/constant/api_type.go @@ -39,5 +39,6 @@ const ( APITypeAdvancedCustom APITypeSub2API APITypeNewAPI + APITypeAvalAI APITypeDummy // this one is only for count, do not add any channel after this ) diff --git a/constant/channel.go b/constant/channel.go index 2a6c4a31c138..74e0f6476812 100644 --- a/constant/channel.go +++ b/constant/channel.go @@ -58,6 +58,7 @@ const ( ChannelTypeAdvancedCustom = 58 ChannelTypeSub2API = 59 ChannelTypeNewAPI = 60 + ChannelTypeAvalAI = 61 ChannelTypeDummy // this one is only for count, do not add any channel after this ) @@ -124,6 +125,7 @@ var ChannelBaseURLs = []string{ "", //58 "", //59 "", //60 + "https://api.avalai.ir", //61 } var ChannelTypeNames = map[int]string{ @@ -184,6 +186,7 @@ var ChannelTypeNames = map[int]string{ ChannelTypeAdvancedCustom: "Advanced Custom", ChannelTypeSub2API: "Sub2API", ChannelTypeNewAPI: "New API", + ChannelTypeAvalAI: "AvalAI", } func GetChannelTypeName(channelType int) string { diff --git a/relay/channel/avalai/constants.go b/relay/channel/avalai/constants.go new file mode 100644 index 000000000000..af31e48eb4fd --- /dev/null +++ b/relay/channel/avalai/constants.go @@ -0,0 +1,23 @@ +package avalai + +// https://docs.avalai.ir +// AvalAI is an OpenAI-compatible AI gateway that proxies models from +// OpenAI, Anthropic, Google, DeepSeek and other providers. +// The full model list can be fetched from upstream /v1/models. + +var ModelList = []string{ + "gpt-4o", + "gpt-4o-mini", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "o4-mini", + "claude-3-5-sonnet-20241022", + "claude-sonnet-4-20250514", + "gemini-2.0-flash", + "gemini-2.5-pro", + "deepseek-chat", + "deepseek-reasoner", +} + +var ChannelName = "avalai" diff --git a/relay/channel/openai/adaptor.go b/relay/channel/openai/adaptor.go index 4f1c42863dba..b36c5f9d1939 100644 --- a/relay/channel/openai/adaptor.go +++ b/relay/channel/openai/adaptor.go @@ -18,6 +18,7 @@ import ( "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/relay/channel" "github.com/QuantumNous/new-api/relay/channel/ai360" + "github.com/QuantumNous/new-api/relay/channel/avalai" "github.com/QuantumNous/new-api/relay/channel/lingyiwanwu" "github.com/QuantumNous/new-api/relaykit/dto" @@ -674,6 +675,8 @@ func (a *Adaptor) GetModelList() []string { return ai360.ModelList case constant.ChannelTypeLingYiWanWu: return lingyiwanwu.ModelList + case constant.ChannelTypeAvalAI: + return avalai.ModelList //case constant.ChannelTypeMiniMax: // return minimax.ModelList case constant.ChannelTypeXinference: @@ -691,6 +694,8 @@ func (a *Adaptor) GetChannelName() string { return ai360.ChannelName case constant.ChannelTypeLingYiWanWu: return lingyiwanwu.ChannelName + case constant.ChannelTypeAvalAI: + return avalai.ChannelName //case constant.ChannelTypeMiniMax: // return minimax.ChannelName case constant.ChannelTypeXinference: diff --git a/relay/common/relay_info.go b/relay/common/relay_info.go index 45ae30bf9fe8..e8a4b6e5caf8 100644 --- a/relay/common/relay_info.go +++ b/relay/common/relay_info.go @@ -348,6 +348,7 @@ var streamSupportedChannels = map[int]bool{ constant.ChannelTypeSub2API: true, constant.ChannelTypeNewAPI: true, constant.ChannelTypeTencent: true, + constant.ChannelTypeAvalAI: true, } func GenRelayInfoWs(c *gin.Context, ws *websocket.Conn) *RelayInfo { diff --git a/relay/relay_adaptor.go b/relay/relay_adaptor.go index e6298dc034f3..3f861fa4ad3e 100644 --- a/relay/relay_adaptor.go +++ b/relay/relay_adaptor.go @@ -129,6 +129,8 @@ func GetAdaptor(apiType int) channel.Adaptor { return &sub2api.Adaptor{} case constant.APITypeNewAPI: return &newapi.Adaptor{} + case constant.APITypeAvalAI: + return &openai.Adaptor{} } return nil } diff --git a/web/src/features/channels/constants.ts b/web/src/features/channels/constants.ts index a3cb726d5418..117fc6fdeb97 100644 --- a/web/src/features/channels/constants.ts +++ b/web/src/features/channels/constants.ts @@ -81,12 +81,13 @@ export const CHANNEL_TYPES = { 58: 'Advanced Custom', 59: 'Sub2API', 60: 'New API', + 61: 'AvalAI', } as const const CHANNEL_TYPE_DISPLAY_ORDER: number[] = [ - 1, 14, 33, 24, 43, 3, 41, 48, 60, 58, 42, 34, 20, 4, 40, 27, 25, 17, 26, 15, - 46, 23, 18, 45, 31, 35, 49, 19, 47, 37, 38, 39, 11, 8, 57, 59, 22, 21, 44, 2, - 5, 36, 50, 51, 52, 53, 54, 55, 56, + 1, 14, 33, 24, 43, 3, 41, 48, 60, 58, 42, 34, 20, 61, 4, 40, 27, 25, 17, 26, + 15, 46, 23, 18, 45, 31, 35, 49, 19, 47, 37, 38, 39, 11, 8, 57, 59, 22, 21, + 44, 2, 5, 36, 50, 51, 52, 53, 54, 55, 56, ] export const CHANNEL_TYPE_OPTIONS: { value: number; label: string }[] = (() => { @@ -389,7 +390,7 @@ export const FIELD_DESCRIPTIONS = { export const MODEL_FETCHABLE_TYPES = new Set([ 1, 4, 14, 17, 20, 23, 24, 25, 26, 27, 31, 34, 35, 40, 42, 43, 47, 48, 57, 58, - 59, 60, + 59, 60, 61, ]) export const TYPE_TO_KEY_PROMPT: Record = { diff --git a/web/src/features/channels/lib/channel-utils.ts b/web/src/features/channels/lib/channel-utils.ts index 9424a8521b6f..1b6c0456e3d5 100644 --- a/web/src/features/channels/lib/channel-utils.ts +++ b/web/src/features/channels/lib/channel-utils.ts @@ -113,6 +113,7 @@ export function getChannelTypeIcon(type: number): string { 53: 'OpenAI', // Submodel // AI Proxy services + 61: 'OpenAI', // AvalAI 10: 'OpenAI', // AI Proxy 21: 'OpenAI', // AI Proxy Library 12: 'OpenAI', // API2GPT