Просмотр исходного кода

Merge branch 'Calcium-Ion:main' into new512

iszcz 1 год назад
Родитель
Сommit
f956e4489f

+ 1 - 0
common/constants.go

@@ -208,6 +208,7 @@ const (
 	ChannelTypeLingYiWanWu    = 31
 	ChannelTypeAws            = 33
 	ChannelTypeCohere         = 34
+	ChannelTypeMiniMax        = 35
 
 	ChannelTypeDummy // this one is only for count, do not add any channel after this
 )

+ 23 - 3
common/model-ratio.go

@@ -69,9 +69,17 @@ var DefaultModelRatio = map[string]float64{
 	"claude-3-haiku-20240307":      0.125,  // $0.25 / 1M tokens
 	"claude-3-sonnet-20240229":     1.5,    // $3 / 1M tokens
 	"claude-3-opus-20240229":       7.5,    // $15 / 1M tokens
-	"ERNIE-Bot":                    0.8572, // ¥0.012 / 1k tokens
-	"ERNIE-Bot-turbo":              0.5715, // ¥0.008 / 1k tokens
-	"ERNIE-Bot-4":                  8.572,  // ¥0.12 / 1k tokens
+	"ERNIE-Bot":                    0.8572, // ¥0.012 / 1k tokens //renamed to ERNIE-3.5-8K
+	"ERNIE-Bot-turbo":              0.5715, // ¥0.008 / 1k tokens //renamed to ERNIE-Lite-8K
+	"ERNIE-Bot-4":                  8.572,  // ¥0.12 / 1k tokens //renamed to ERNIE-4.0-8K
+	"ERNIE-4.0-8K":                 8.572,  // ¥0.12 / 1k tokens
+	"ERNIE-3.5-8K":                 0.8572, // ¥0.012 / 1k tokens
+	"ERNIE-Speed-8K":               0.2858, // ¥0.004 / 1k tokens
+	"ERNIE-Speed-128K":             0.2858, // ¥0.004 / 1k tokens
+	"ERNIE-Lite-8K":                0.2143, // ¥0.003 / 1k tokens
+	"ERNIE-Tiny-8K":                0.0715, // ¥0.001 / 1k tokens
+	"ERNIE-Character-8K":           0.2858, // ¥0.004 / 1k tokens
+	"ERNIE-Functions-8K":           0.2858, // ¥0.004 / 1k tokens
 	"Embedding-V1":                 0.1429, // ¥0.002 / 1k tokens
 	"PaLM-2":                       1,
 	"gemini-pro":                   1, // $0.00025 / 1k characters -> $0.001 / 1k tokens
@@ -98,6 +106,9 @@ var DefaultModelRatio = map[string]float64{
 	"SparkDesk-v3.1":               1.2858, // ¥0.018 / 1k tokens
 	"SparkDesk-v3.5":               1.2858, // ¥0.018 / 1k tokens
 	"360GPT_S2_V9":                 0.8572, // ¥0.012 / 1k tokens
+	"360gpt-turbo":                 0.0858, // ¥0.0012 / 1k tokens
+	"360gpt-turbo-responsibility-8k": 0.8572, // ¥0.012 / 1k tokens
+	"360gpt-pro":                   0.8572, // ¥0.012 / 1k tokens
 	"embedding-bert-512-v1":        0.0715, // ¥0.001 / 1k tokens
 	"embedding_s1_v1":              0.0715, // ¥0.001 / 1k tokens
 	"semantic_similarity_s1_v1":    0.0715, // ¥0.001 / 1k tokens
@@ -289,6 +300,15 @@ func GetCompletionRatio(name string) float64 {
 	if strings.HasPrefix(name, "deepseek") {
 		return 2
 	}
+	if strings.HasPrefix(name, "ERNIE-Speed-") {
+		return 2
+	} else if strings.HasPrefix(name, "ERNIE-Lite-") {
+		return 2
+	} else if strings.HasPrefix(name, "ERNIE-Character") {
+		return 2
+	} else if strings.HasPrefix(name, "ERNIE-Functions") {
+		return 2
+	}
 	switch name {
 	case "llama2-70b-4096":
 		return 0.8 / 0.64

+ 9 - 0
common/utils.go

@@ -258,3 +258,12 @@ func MapToJsonStrFloat(m map[string]float64) string {
 	}
 	return string(bytes)
 }
+
+func StrToMap(str string) map[string]interface{} {
+	m := make(map[string]interface{})
+	err := json.Unmarshal([]byte(str), &m)
+	if err != nil {
+		return nil
+	}
+	return m
+}

+ 14 - 0
controller/channel-test.go

@@ -64,7 +64,21 @@ func testChannel(channel *model.Channel, testModel string) (err error, openaiErr
 		} else {
 			testModel = adaptor.GetModelList()[0]
 		}
+	} else {
+		modelMapping := *channel.ModelMapping
+		if modelMapping != "" && modelMapping != "{}" {
+			modelMap := make(map[string]string)
+			err := json.Unmarshal([]byte(modelMapping), &modelMap)
+			if err != nil {
+				openaiErr := service.OpenAIErrorWrapperLocal(err, "unmarshal_model_mapping_failed", http.StatusInternalServerError).Error
+				return err, &openaiErr
+			}
+			if modelMap[testModel] != "" {
+				testModel = modelMap[testModel]
+			}
+		}
 	}
+
 	request := buildTestRequest()
 	request.Model = testModel
 	meta.UpstreamModelName = testModel

+ 14 - 2
controller/model.go

@@ -11,6 +11,7 @@ import (
 	"one-api/relay"
 	"one-api/relay/channel/ai360"
 	"one-api/relay/channel/lingyiwanwu"
+	"one-api/relay/channel/minimax"
 	"one-api/relay/channel/moonshot"
 	relaycommon "one-api/relay/common"
 	relayconstant "one-api/relay/constant"
@@ -79,7 +80,7 @@ func init() {
 			Id:         modelName,
 			Object:     "model",
 			Created:    1626777600,
-			OwnedBy:    "moonshot",
+			OwnedBy:    moonshot.ChannelName,
 			Permission: permission,
 			Root:       modelName,
 			Parent:     nil,
@@ -90,7 +91,18 @@ func init() {
 			Id:         modelName,
 			Object:     "model",
 			Created:    1626777600,
-			OwnedBy:    "lingyiwanwu",
+			OwnedBy:    lingyiwanwu.ChannelName,
+			Permission: permission,
+			Root:       modelName,
+			Parent:     nil,
+		})
+	}
+	for _, modelName := range minimax.ModelList {
+		openAIModels = append(openAIModels, dto.OpenAIModels{
+			Id:         modelName,
+			Object:     "model",
+			Created:    1626777600,
+			OwnedBy:    minimax.ChannelName,
 			Permission: permission,
 			Root:       modelName,
 			Parent:     nil,

+ 5 - 2
controller/relay.go

@@ -43,7 +43,7 @@ func Relay(c *gin.Context) {
 	group := c.GetString("group")
 	originalModel := c.GetString("original_model")
 	openaiErr := relayHandler(c, relayMode)
-	useChannel := []int{channelId}
+	c.Set("use_channel", []string{fmt.Sprintf("%d", channelId)})
 	if openaiErr != nil {
 		go processChannelError(c, channelId, openaiErr)
 	} else {
@@ -56,7 +56,9 @@ func Relay(c *gin.Context) {
 			break
 		}
 		channelId = channel.Id
-		useChannel = append(useChannel, channelId)
+		useChannel := c.GetStringSlice("use_channel")
+		useChannel = append(useChannel, fmt.Sprintf("%d", channelId))
+		c.Set("use_channel", useChannel)
 		common.LogInfo(c.Request.Context(), fmt.Sprintf("using channel #%d to retry (remain times %d)", channel.Id, i))
 		middleware.SetupContextForSelectedChannel(c, channel, originalModel)
 
@@ -67,6 +69,7 @@ func Relay(c *gin.Context) {
 			go processChannelError(c, channelId, openaiErr)
 		}
 	}
+	useChannel := c.GetStringSlice("use_channel")
 	if len(useChannel) > 1 {
 		retryLogStr := fmt.Sprintf("重试:%s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(useChannel)), "->"), "[]"))
 		common.LogInfo(c.Request.Context(), retryLogStr)

+ 9 - 0
model/log.go

@@ -142,6 +142,15 @@ func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int
 		tx = tx.Where("created_at <= ?", endTimestamp)
 	}
 	err = tx.Order("id desc").Limit(num).Offset(startIdx).Omit("id").Find(&logs).Error
+	for i := range logs {
+		var otherMap map[string]interface{}
+		otherMap = common.StrToMap(logs[i].Other)
+		if otherMap != nil {
+			// delete admin
+			delete(otherMap, "admin_info")
+		}
+		logs[i].Other = common.MapToJsonStr(otherMap)
+	}
 	return logs, err
 }
 

+ 6 - 6
model/main.go

@@ -93,12 +93,12 @@ func InitDB() (err error) {
 		if !common.IsMasterNode {
 			return nil
 		}
-		if common.UsingMySQL {
-			_, _ = sqlDB.Exec("DROP INDEX idx_channels_key ON channels;")             // TODO: delete this line when most users have upgraded
-			_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY action VARCHAR(40);")   // TODO: delete this line when most users have upgraded
-			_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY progress VARCHAR(30);") // TODO: delete this line when most users have upgraded
-			_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY status VARCHAR(20);")   // TODO: delete this line when most users have upgraded
-		}
+		//if common.UsingMySQL {
+		//	_, _ = sqlDB.Exec("DROP INDEX idx_channels_key ON channels;")             // TODO: delete this line when most users have upgraded
+		//	_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY action VARCHAR(40);")   // TODO: delete this line when most users have upgraded
+		//	_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY progress VARCHAR(30);") // TODO: delete this line when most users have upgraded
+		//	_, _ = sqlDB.Exec("ALTER TABLE midjourneys MODIFY status VARCHAR(20);")   // TODO: delete this line when most users have upgraded
+		//}
 		common.SysLog("database migration started")
 		err = db.AutoMigrate(&Channel{})
 		if err != nil {

+ 1 - 1
model/token.go

@@ -11,7 +11,7 @@ import (
 
 type Token struct {
 	Id                 int            `json:"id"`
-	UserId             int            `json:"user_id"`
+	UserId             int            `json:"user_id" gorm:"index"`
 	Key                string         `json:"key" gorm:"type:char(48);uniqueIndex"`
 	Status             int            `json:"status" gorm:"default:1"`
 	Name               string         `json:"name" gorm:"index" `

+ 3 - 0
relay/channel/ai360/constants.go

@@ -1,6 +1,9 @@
 package ai360
 
 var ModelList = []string{
+	"360gpt-turbo",
+	"360gpt-turbo-responsibility-8k",
+	"360gpt-pro",
 	"360GPT_S2_V9",
 	"embedding-bert-512-v1",
 	"embedding_s1_v1",

+ 17 - 0
relay/channel/baidu/adaptor.go

@@ -9,6 +9,7 @@ import (
 	"one-api/relay/channel"
 	relaycommon "one-api/relay/common"
 	"one-api/relay/constant"
+	"strings"
 )
 
 type Adaptor struct {
@@ -33,8 +34,24 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
 		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant"
 	case "BLOOMZ-7B":
 		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/bloomz_7b1"
+	case "ERNIE-4.0-8K":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"
+	case "ERNIE-3.5-8K":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"
+	case "ERNIE-Speed-8K":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_speed"
+	case "ERNIE-Character-8K":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-char-8k"
+	case "ERNIE-Functions-8K":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-func-8k"
+	case "ERNIE-Lite-8K-0922":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant"
+	case "Yi-34B-Chat":
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/yi_34b_chat"
 	case "Embedding-V1":
 		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/embedding-v1"
+	default:
+		fullRequestURL = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/" + strings.ToLower(info.UpstreamModelName)
 	}
 	var accessToken string
 	var err error

+ 13 - 5
relay/channel/baidu/constants.go

@@ -1,11 +1,19 @@
 package baidu
 
 var ModelList = []string{
-	"ERNIE-Bot-4",
-	"ERNIE-Bot-8K",
-	"ERNIE-Bot",
-	"ERNIE-Speed",
-	"ERNIE-Bot-turbo",
+	"ERNIE-3.5-8K",
+	"ERNIE-4.0-8K",
+	"ERNIE-Speed-8K",
+	"ERNIE-Speed-128K",
+	"ERNIE-Lite-8K",
+	"ERNIE-Tiny-8K",
+	"ERNIE-Character-8K",
+	"ERNIE-Functions-8K",
+	//"ERNIE-Bot-4",
+	//"ERNIE-Bot-8K",
+	//"ERNIE-Bot",
+	//"ERNIE-Speed",
+	//"ERNIE-Bot-turbo",
 	"Embedding-V1",
 }
 

+ 11 - 9
relay/channel/lingyiwanwu/constrants.go

@@ -1,9 +1,11 @@
-package lingyiwanwu
-
-// https://platform.lingyiwanwu.com/docs
-
-var ModelList = []string{
-	"yi-34b-chat-0205",
-	"yi-34b-chat-200k",
-	"yi-vl-plus",
-}
+package lingyiwanwu
+
+// https://platform.lingyiwanwu.com/docs
+
+var ModelList = []string{
+	"yi-34b-chat-0205",
+	"yi-34b-chat-200k",
+	"yi-vl-plus",
+}
+
+var ChannelName = "lingyiwanwu"

+ 13 - 0
relay/channel/minimax/constants.go

@@ -0,0 +1,13 @@
+package minimax
+
+// https://www.minimaxi.com/document/guides/chat-model/V2?id=65e0736ab2845de20908e2dd
+
+var ModelList = []string{
+	"abab6.5-chat",
+	"abab6.5s-chat",
+	"abab6-chat",
+	"abab5.5-chat",
+	"abab5.5s-chat",
+}
+
+var ChannelName = "minimax"

+ 10 - 0
relay/channel/minimax/relay-minimax.go

@@ -0,0 +1,10 @@
+package minimax
+
+import (
+	"fmt"
+	relaycommon "one-api/relay/common"
+)
+
+func GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
+	return fmt.Sprintf("%s/v1/text/chatcompletion_v2", info.BaseUrl), nil
+}

+ 2 - 0
relay/channel/moonshot/constants.go

@@ -5,3 +5,5 @@ var ModelList = []string{
 	"moonshot-v1-32k",
 	"moonshot-v1-128k",
 }
+
+var ChannelName = "moonshot"

+ 25 - 3
relay/channel/openai/adaptor.go

@@ -11,6 +11,7 @@ import (
 	"one-api/relay/channel"
 	"one-api/relay/channel/ai360"
 	"one-api/relay/channel/lingyiwanwu"
+	"one-api/relay/channel/minimax"
 	"one-api/relay/channel/moonshot"
 	relaycommon "one-api/relay/common"
 	"one-api/service"
@@ -26,7 +27,8 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo, request dto.GeneralOpenAIReq
 }
 
 func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
-	if info.ChannelType == common.ChannelTypeAzure {
+	switch info.ChannelType {
+	case common.ChannelTypeAzure:
 		// https://learn.microsoft.com/en-us/azure/cognitive-services/openai/chatgpt-quickstart?pivots=rest-api&tabs=command-line#rest-api
 		requestURL := strings.Split(info.RequestURLPath, "?")[0]
 		requestURL = fmt.Sprintf("%s?api-version=%s", requestURL, info.ApiVersion)
@@ -37,8 +39,15 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
 
 		requestURL = fmt.Sprintf("/openai/deployments/%s/%s", model_, task)
 		return relaycommon.GetFullRequestURL(info.BaseUrl, requestURL, info.ChannelType), nil
+	case common.ChannelTypeMiniMax:
+		return minimax.GetRequestURL(info)
+	//case common.ChannelTypeCustom:
+	//	url := info.BaseUrl
+	//	url = strings.Replace(url, "{model}", info.UpstreamModelName, -1)
+	//	return url, nil
+	default:
+		return relaycommon.GetFullRequestURL(info.BaseUrl, info.RequestURLPath, info.ChannelType), nil
 	}
-	return relaycommon.GetFullRequestURL(info.BaseUrl, info.RequestURLPath, info.ChannelType), nil
 }
 
 func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error {
@@ -90,11 +99,24 @@ func (a *Adaptor) GetModelList() []string {
 		return moonshot.ModelList
 	case common.ChannelTypeLingYiWanWu:
 		return lingyiwanwu.ModelList
+	case common.ChannelTypeMiniMax:
+		return minimax.ModelList
 	default:
 		return ModelList
 	}
 }
 
 func (a *Adaptor) GetChannelName() string {
-	return ChannelName
+	switch a.ChannelType {
+	case common.ChannelType360:
+		return ai360.ChannelName
+	case common.ChannelTypeMoonshot:
+		return moonshot.ChannelName
+	case common.ChannelTypeLingYiWanWu:
+		return lingyiwanwu.ChannelName
+	case common.ChannelTypeMiniMax:
+		return minimax.ChannelName
+	default:
+		return ChannelName
+	}
 }

+ 2 - 2
relay/constant/api_type.go

@@ -15,7 +15,7 @@ const (
 	APITypeAIProxyLibrary
 	APITypeTencent
 	APITypeGemini
-	APITypeZhipu_v4
+	APITypeZhipuV4
 	APITypeOllama
 	APITypePerplexity
 	APITypeAws
@@ -48,7 +48,7 @@ func ChannelType2APIType(channelType int) (int, bool) {
 	case common.ChannelTypeGemini:
 		apiType = APITypeGemini
 	case common.ChannelTypeZhipu_v4:
-		apiType = APITypeZhipu_v4
+		apiType = APITypeZhipuV4
 	case common.ChannelTypeOllama:
 		apiType = APITypeOllama
 	case common.ChannelTypePerplexity:

+ 3 - 0
relay/relay-text.go

@@ -320,6 +320,9 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, textRe
 	other["group_ratio"] = groupRatio
 	other["completion_ratio"] = completionRatio
 	other["model_price"] = modelPrice
+	adminInfo := make(map[string]interface{})
+	adminInfo["use_channel"] = ctx.GetStringSlice("use_channel")
+	other["admin_info"] = adminInfo
 	model.RecordConsumeLog(ctx, relayInfo.UserId, relayInfo.ChannelId, promptTokens, completionTokens, logModel, tokenName, quota, logContent, relayInfo.TokenId, userQuota, int(useTimeSeconds), relayInfo.IsStream, other)
 
 	//if quota != 0 {

+ 1 - 1
relay/relay_adaptor.go

@@ -41,7 +41,7 @@ func GetAdaptor(apiType int) channel.Adaptor {
 		return &xunfei.Adaptor{}
 	case constant.APITypeZhipu:
 		return &zhipu.Adaptor{}
-	case constant.APITypeZhipu_v4:
+	case constant.APITypeZhipuV4:
 		return &zhipu_4v.Adaptor{}
 	case constant.APITypeOllama:
 		return &ollama.Adaptor{}

+ 7 - 0
web/src/components/ChannelsTable.js

@@ -6,6 +6,7 @@ import {
   showError,
   showInfo,
   showSuccess,
+  showWarning,
   timestamp2string,
 } from '../helpers';
 
@@ -309,6 +310,12 @@ const ChannelsTable = () => {
 
   const setChannelFormat = (channels) => {
     for (let i = 0; i < channels.length; i++) {
+      if (channels[i].type === 8) {
+        showWarning(
+          '检测到您使用了“自定义渠道”类型,请更换为“OpenAI”渠道类型!',
+        );
+        showWarning('下个版本将不再支持“自定义渠道”类型!');
+      }
       channels[i].key = '' + channels[i].id;
       let test_models = [];
       channels[i].models.split(',').forEach((item, index) => {

+ 24 - 0
web/src/components/LogsTable.js

@@ -294,6 +294,30 @@ const LogsTable = () => {
         );
       },
     },
+    {
+      title: '重试',
+      dataIndex: 'retry',
+      className: isAdmin() ? 'tableShow' : 'tableHiddle',
+      render: (text, record, index) => {
+        let content = '渠道:' + record.channel;
+        if (record.other !== '') {
+          let other = JSON.parse(record.other);
+          if (other.admin_info !== undefined) {
+            if (
+              other.admin_info.use_channel !== null &&
+              other.admin_info.use_channel !== undefined &&
+              other.admin_info.use_channel !== ''
+            ) {
+              // channel id array
+              let useChannel = other.admin_info.use_channel;
+              let useChannelStr = useChannel.join('->');
+              content = `渠道:${useChannelStr}`;
+            }
+          }
+        }
+        return isAdminUser ? <div>{content}</div> : <></>;
+      },
+    },
     {
       title: '详情',
       dataIndex: 'content',

+ 8 - 7
web/src/constants/channel.constants.js

@@ -36,13 +36,6 @@ export const CHANNEL_OPTIONS = [
     color: 'teal',
     label: 'Azure OpenAI',
   },
-  {
-    key: 11,
-    text: 'Google PaLM2',
-    value: 11,
-    color: 'orange',
-    label: 'Google PaLM2',
-  },
   {
     key: 24,
     text: 'Google Gemini',
@@ -92,10 +85,18 @@ export const CHANNEL_OPTIONS = [
     color: 'purple',
     label: '智谱 GLM-4V',
   },
+  {
+    key: 11,
+    text: 'Google PaLM2',
+    value: 11,
+    color: 'orange',
+    label: 'Google PaLM2',
+  },
   { key: 25, text: 'Moonshot', value: 25, color: 'green', label: 'Moonshot' },
   { key: 19, text: '360 智脑', value: 19, color: 'blue', label: '360 智脑' },
   { key: 23, text: '腾讯混元', value: 23, color: 'teal', label: '腾讯混元' },
   { key: 31, text: '零一万物', value: 31, color: 'green', label: '零一万物' },
+  { key: 35, text: 'MiniMax', value: 35, color: 'green', label: 'MiniMax' },
   { key: 8, text: '自定义渠道', value: 8, color: 'pink', label: '自定义渠道' },
   {
     key: 22,