mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			v0.5.4-alp
			...
			v0.5.4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					56b5007379 | ||
| 
						 | 
					d09d317459 | 
@@ -154,26 +154,27 @@ const (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ChannelTypeUnknown   = 0
 | 
						ChannelTypeUnknown    = 0
 | 
				
			||||||
	ChannelTypeOpenAI    = 1
 | 
						ChannelTypeOpenAI     = 1
 | 
				
			||||||
	ChannelTypeAPI2D     = 2
 | 
						ChannelTypeAPI2D      = 2
 | 
				
			||||||
	ChannelTypeAzure     = 3
 | 
						ChannelTypeAzure      = 3
 | 
				
			||||||
	ChannelTypeCloseAI   = 4
 | 
						ChannelTypeCloseAI    = 4
 | 
				
			||||||
	ChannelTypeOpenAISB  = 5
 | 
						ChannelTypeOpenAISB   = 5
 | 
				
			||||||
	ChannelTypeOpenAIMax = 6
 | 
						ChannelTypeOpenAIMax  = 6
 | 
				
			||||||
	ChannelTypeOhMyGPT   = 7
 | 
						ChannelTypeOhMyGPT    = 7
 | 
				
			||||||
	ChannelTypeCustom    = 8
 | 
						ChannelTypeCustom     = 8
 | 
				
			||||||
	ChannelTypeAILS      = 9
 | 
						ChannelTypeAILS       = 9
 | 
				
			||||||
	ChannelTypeAIProxy   = 10
 | 
						ChannelTypeAIProxy    = 10
 | 
				
			||||||
	ChannelTypePaLM      = 11
 | 
						ChannelTypePaLM       = 11
 | 
				
			||||||
	ChannelTypeAPI2GPT   = 12
 | 
						ChannelTypeAPI2GPT    = 12
 | 
				
			||||||
	ChannelTypeAIGC2D    = 13
 | 
						ChannelTypeAIGC2D     = 13
 | 
				
			||||||
	ChannelTypeAnthropic = 14
 | 
						ChannelTypeAnthropic  = 14
 | 
				
			||||||
	ChannelTypeBaidu     = 15
 | 
						ChannelTypeBaidu      = 15
 | 
				
			||||||
	ChannelTypeZhipu     = 16
 | 
						ChannelTypeZhipu      = 16
 | 
				
			||||||
	ChannelTypeAli       = 17
 | 
						ChannelTypeAli        = 17
 | 
				
			||||||
	ChannelTypeXunfei    = 18
 | 
						ChannelTypeXunfei     = 18
 | 
				
			||||||
	ChannelType360       = 19
 | 
						ChannelType360        = 19
 | 
				
			||||||
 | 
						ChannelTypeOpenRouter = 20
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ChannelBaseURLs = []string{
 | 
					var ChannelBaseURLs = []string{
 | 
				
			||||||
@@ -197,4 +198,5 @@ var ChannelBaseURLs = []string{
 | 
				
			|||||||
	"https://dashscope.aliyuncs.com", // 17
 | 
						"https://dashscope.aliyuncs.com", // 17
 | 
				
			||||||
	"",                               // 18
 | 
						"",                               // 18
 | 
				
			||||||
	"https://ai.360.cn",              // 19
 | 
						"https://ai.360.cn",              // 19
 | 
				
			||||||
 | 
						"https://openrouter.ai/api",      // 20
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,7 @@ var ModelRatio = map[string]float64{
 | 
				
			|||||||
	"text-davinci-003":          10,
 | 
						"text-davinci-003":          10,
 | 
				
			||||||
	"text-davinci-edit-001":     10,
 | 
						"text-davinci-edit-001":     10,
 | 
				
			||||||
	"code-davinci-edit-001":     10,
 | 
						"code-davinci-edit-001":     10,
 | 
				
			||||||
	"whisper-1":                 10,
 | 
						"whisper-1":                 15, // $0.006 / minute -> $0.006 / 150 words -> $0.006 / 200 tokens -> $0.03 / 1k tokens
 | 
				
			||||||
	"davinci":                   10,
 | 
						"davinci":                   10,
 | 
				
			||||||
	"curie":                     10,
 | 
						"curie":                     10,
 | 
				
			||||||
	"babbage":                   10,
 | 
						"babbage":                   10,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,6 +63,15 @@ func init() {
 | 
				
			|||||||
			Root:       "dall-e",
 | 
								Root:       "dall-e",
 | 
				
			||||||
			Parent:     nil,
 | 
								Parent:     nil,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Id:         "whisper-1",
 | 
				
			||||||
 | 
								Object:     "model",
 | 
				
			||||||
 | 
								Created:    1677649963,
 | 
				
			||||||
 | 
								OwnedBy:    "openai",
 | 
				
			||||||
 | 
								Permission: permission,
 | 
				
			||||||
 | 
								Root:       "whisper-1",
 | 
				
			||||||
 | 
								Parent:     nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Id:         "gpt-3.5-turbo",
 | 
								Id:         "gpt-3.5-turbo",
 | 
				
			||||||
			Object:     "model",
 | 
								Object:     "model",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										147
									
								
								controller/relay-audio.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								controller/relay-audio.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
				
			|||||||
 | 
					package controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"one-api/common"
 | 
				
			||||||
 | 
						"one-api/model"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func relayAudioHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
 | 
				
			||||||
 | 
						audioModel := "whisper-1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tokenId := c.GetInt("token_id")
 | 
				
			||||||
 | 
						channelType := c.GetInt("channel")
 | 
				
			||||||
 | 
						userId := c.GetInt("id")
 | 
				
			||||||
 | 
						group := c.GetString("group")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						preConsumedTokens := common.PreConsumedQuota
 | 
				
			||||||
 | 
						modelRatio := common.GetModelRatio(audioModel)
 | 
				
			||||||
 | 
						groupRatio := common.GetGroupRatio(group)
 | 
				
			||||||
 | 
						ratio := modelRatio * groupRatio
 | 
				
			||||||
 | 
						preConsumedQuota := int(float64(preConsumedTokens) * ratio)
 | 
				
			||||||
 | 
						userQuota, err := model.CacheGetUserQuota(userId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "get_user_quota_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = model.CacheDecreaseUserQuota(userId, preConsumedQuota)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "decrease_user_quota_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if userQuota > 100*preConsumedQuota {
 | 
				
			||||||
 | 
							// in this case, we do not pre-consume quota
 | 
				
			||||||
 | 
							// because the user has enough quota
 | 
				
			||||||
 | 
							preConsumedQuota = 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if preConsumedQuota > 0 {
 | 
				
			||||||
 | 
							err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return errorWrapper(err, "pre_consume_token_quota_failed", http.StatusForbidden)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// map model name
 | 
				
			||||||
 | 
						modelMapping := c.GetString("model_mapping")
 | 
				
			||||||
 | 
						if modelMapping != "" {
 | 
				
			||||||
 | 
							modelMap := make(map[string]string)
 | 
				
			||||||
 | 
							err := json.Unmarshal([]byte(modelMapping), &modelMap)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return errorWrapper(err, "unmarshal_model_mapping_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if modelMap[audioModel] != "" {
 | 
				
			||||||
 | 
								audioModel = modelMap[audioModel]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						baseURL := common.ChannelBaseURLs[channelType]
 | 
				
			||||||
 | 
						requestURL := c.Request.URL.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.GetString("base_url") != "" {
 | 
				
			||||||
 | 
							baseURL = c.GetString("base_url")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fullRequestURL := fmt.Sprintf("%s%s", baseURL, requestURL)
 | 
				
			||||||
 | 
						requestBody := c.Request.Body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req, err := http.NewRequest(c.Request.Method, fullRequestURL, requestBody)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "new_request_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req.Header.Set("Authorization", c.Request.Header.Get("Authorization"))
 | 
				
			||||||
 | 
						req.Header.Set("Content-Type", c.Request.Header.Get("Content-Type"))
 | 
				
			||||||
 | 
						req.Header.Set("Accept", c.Request.Header.Get("Accept"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := httpClient.Do(req)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "do_request_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = req.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "close_request_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = c.Request.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "close_request_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var audioResponse AudioResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								quota := countTokenText(audioResponse.Text, audioModel)
 | 
				
			||||||
 | 
								quotaDelta := quota - preConsumedQuota
 | 
				
			||||||
 | 
								err := model.PostConsumeTokenQuota(tokenId, quotaDelta)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									common.SysError("error consuming token remain quota: " + err.Error())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								err = model.CacheUpdateUserQuota(userId)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									common.SysError("error update user quota cache: " + err.Error())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if quota != 0 {
 | 
				
			||||||
 | 
									tokenName := c.GetString("token_name")
 | 
				
			||||||
 | 
									logContent := fmt.Sprintf("模型倍率 %.2f,分组倍率 %.2f", modelRatio, groupRatio)
 | 
				
			||||||
 | 
									model.RecordConsumeLog(userId, 0, 0, audioModel, tokenName, quota, logContent)
 | 
				
			||||||
 | 
									model.UpdateUserUsedQuotaAndRequestCount(userId, quota)
 | 
				
			||||||
 | 
									channelId := c.GetInt("channel_id")
 | 
				
			||||||
 | 
									model.UpdateChannelUsedQuota(channelId, quota)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						responseBody, err := io.ReadAll(resp.Body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "read_response_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = resp.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "close_response_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = json.Unmarshal(responseBody, &audioResponse)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "unmarshal_response_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp.Body = io.NopCloser(bytes.NewBuffer(responseBody))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k, v := range resp.Header {
 | 
				
			||||||
 | 
							c.Writer.Header().Set(k, v[0])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Writer.WriteHeader(resp.StatusCode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = io.Copy(c.Writer, resp.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "copy_response_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = resp.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return errorWrapper(err, "close_response_body_failed", http.StatusInternalServerError)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -282,6 +282,10 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
 | 
				
			|||||||
				req.Header.Set("api-key", apiKey)
 | 
									req.Header.Set("api-key", apiKey)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				req.Header.Set("Authorization", c.Request.Header.Get("Authorization"))
 | 
									req.Header.Set("Authorization", c.Request.Header.Get("Authorization"))
 | 
				
			||||||
 | 
									if channelType == common.ChannelTypeOpenRouter {
 | 
				
			||||||
 | 
										req.Header.Set("HTTP-Referer", "https://github.com/songquanpeng/one-api")
 | 
				
			||||||
 | 
										req.Header.Set("X-Title", "One API")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case APITypeClaude:
 | 
							case APITypeClaude:
 | 
				
			||||||
			req.Header.Set("x-api-key", apiKey)
 | 
								req.Header.Set("x-api-key", apiKey)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ const (
 | 
				
			|||||||
	RelayModeModerations
 | 
						RelayModeModerations
 | 
				
			||||||
	RelayModeImagesGenerations
 | 
						RelayModeImagesGenerations
 | 
				
			||||||
	RelayModeEdits
 | 
						RelayModeEdits
 | 
				
			||||||
 | 
						RelayModeAudio
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// https://platform.openai.com/docs/api-reference/chat
 | 
					// https://platform.openai.com/docs/api-reference/chat
 | 
				
			||||||
@@ -63,6 +64,10 @@ type ImageRequest struct {
 | 
				
			|||||||
	Size   string `json:"size"`
 | 
						Size   string `json:"size"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AudioResponse struct {
 | 
				
			||||||
 | 
						Text string `json:"text,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Usage struct {
 | 
					type Usage struct {
 | 
				
			||||||
	PromptTokens     int `json:"prompt_tokens"`
 | 
						PromptTokens     int `json:"prompt_tokens"`
 | 
				
			||||||
	CompletionTokens int `json:"completion_tokens"`
 | 
						CompletionTokens int `json:"completion_tokens"`
 | 
				
			||||||
@@ -159,11 +164,15 @@ func Relay(c *gin.Context) {
 | 
				
			|||||||
		relayMode = RelayModeImagesGenerations
 | 
							relayMode = RelayModeImagesGenerations
 | 
				
			||||||
	} else if strings.HasPrefix(c.Request.URL.Path, "/v1/edits") {
 | 
						} else if strings.HasPrefix(c.Request.URL.Path, "/v1/edits") {
 | 
				
			||||||
		relayMode = RelayModeEdits
 | 
							relayMode = RelayModeEdits
 | 
				
			||||||
 | 
						} else if strings.HasPrefix(c.Request.URL.Path, "/v1/audio") {
 | 
				
			||||||
 | 
							relayMode = RelayModeAudio
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var err *OpenAIErrorWithStatusCode
 | 
						var err *OpenAIErrorWithStatusCode
 | 
				
			||||||
	switch relayMode {
 | 
						switch relayMode {
 | 
				
			||||||
	case RelayModeImagesGenerations:
 | 
						case RelayModeImagesGenerations:
 | 
				
			||||||
		err = relayImageHelper(c, relayMode)
 | 
							err = relayImageHelper(c, relayMode)
 | 
				
			||||||
 | 
						case RelayModeAudio:
 | 
				
			||||||
 | 
							err = relayAudioHelper(c, relayMode)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = relayTextHelper(c, relayMode)
 | 
							err = relayTextHelper(c, relayMode)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,10 @@ func Distribute() func(c *gin.Context) {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Select a channel for the user
 | 
								// Select a channel for the user
 | 
				
			||||||
			var modelRequest ModelRequest
 | 
								var modelRequest ModelRequest
 | 
				
			||||||
			err := common.UnmarshalBodyReusable(c, &modelRequest)
 | 
								var err error
 | 
				
			||||||
 | 
								if !strings.HasPrefix(c.Request.URL.Path, "/v1/audio") {
 | 
				
			||||||
 | 
									err = common.UnmarshalBodyReusable(c, &modelRequest)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				c.JSON(http.StatusBadRequest, gin.H{
 | 
									c.JSON(http.StatusBadRequest, gin.H{
 | 
				
			||||||
					"error": gin.H{
 | 
										"error": gin.H{
 | 
				
			||||||
@@ -84,6 +87,11 @@ func Distribute() func(c *gin.Context) {
 | 
				
			|||||||
					modelRequest.Model = "dall-e"
 | 
										modelRequest.Model = "dall-e"
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if strings.HasPrefix(c.Request.URL.Path, "/v1/audio") {
 | 
				
			||||||
 | 
									if modelRequest.Model == "" {
 | 
				
			||||||
 | 
										modelRequest.Model = "whisper-1"
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model)
 | 
								channel, err = model.CacheGetRandomSatisfiedChannel(userGroup, modelRequest.Model)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, modelRequest.Model)
 | 
									message := fmt.Sprintf("当前分组 %s 下对于模型 %s 无可用渠道", userGroup, modelRequest.Model)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@ func SetRelayRouter(router *gin.Engine) {
 | 
				
			|||||||
		relayV1Router.POST("/images/variations", controller.RelayNotImplemented)
 | 
							relayV1Router.POST("/images/variations", controller.RelayNotImplemented)
 | 
				
			||||||
		relayV1Router.POST("/embeddings", controller.Relay)
 | 
							relayV1Router.POST("/embeddings", controller.Relay)
 | 
				
			||||||
		relayV1Router.POST("/engines/:model/embeddings", controller.Relay)
 | 
							relayV1Router.POST("/engines/:model/embeddings", controller.Relay)
 | 
				
			||||||
		relayV1Router.POST("/audio/transcriptions", controller.RelayNotImplemented)
 | 
							relayV1Router.POST("/audio/transcriptions", controller.Relay)
 | 
				
			||||||
		relayV1Router.POST("/audio/translations", controller.RelayNotImplemented)
 | 
							relayV1Router.POST("/audio/translations", controller.Relay)
 | 
				
			||||||
		relayV1Router.GET("/files", controller.RelayNotImplemented)
 | 
							relayV1Router.GET("/files", controller.RelayNotImplemented)
 | 
				
			||||||
		relayV1Router.POST("/files", controller.RelayNotImplemented)
 | 
							relayV1Router.POST("/files", controller.RelayNotImplemented)
 | 
				
			||||||
		relayV1Router.DELETE("/files/:id", controller.RelayNotImplemented)
 | 
							relayV1Router.DELETE("/files/:id", controller.RelayNotImplemented)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ export const CHANNEL_OPTIONS = [
 | 
				
			|||||||
  { key: 16, text: '智谱 ChatGLM', value: 16, color: 'violet' },
 | 
					  { key: 16, text: '智谱 ChatGLM', value: 16, color: 'violet' },
 | 
				
			||||||
  { key: 19, text: '360 智脑', value: 19, color: 'blue' },
 | 
					  { key: 19, text: '360 智脑', value: 19, color: 'blue' },
 | 
				
			||||||
  { key: 8, text: '自定义渠道', value: 8, color: 'pink' },
 | 
					  { key: 8, text: '自定义渠道', value: 8, color: 'pink' },
 | 
				
			||||||
 | 
					  { key: 20, text: '代理:OpenRouter', value: 20, color: 'black' },
 | 
				
			||||||
  { key: 2, text: '代理:API2D', value: 2, color: 'blue' },
 | 
					  { key: 2, text: '代理:API2D', value: 2, color: 'blue' },
 | 
				
			||||||
  { key: 5, text: '代理:OpenAI-SB', value: 5, color: 'brown' },
 | 
					  { key: 5, text: '代理:OpenAI-SB', value: 5, color: 'brown' },
 | 
				
			||||||
  { key: 7, text: '代理:OhMyGPT', value: 7, color: 'purple' },
 | 
					  { key: 7, text: '代理:OhMyGPT', value: 7, color: 'purple' },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import React, { useEffect, useState } from 'react';
 | 
					import React, { useEffect, useState } from 'react';
 | 
				
			||||||
import { Button, Form, Header, Input, Message, Segment } from 'semantic-ui-react';
 | 
					import { Button, Form, Header, Input, Message, Segment } from 'semantic-ui-react';
 | 
				
			||||||
import { useParams, useNavigate } from 'react-router-dom';
 | 
					import { useNavigate, useParams } from 'react-router-dom';
 | 
				
			||||||
import { API, showError, showInfo, showSuccess, verifyJSON } from '../../helpers';
 | 
					import { API, showError, showInfo, showSuccess, verifyJSON } from '../../helpers';
 | 
				
			||||||
import { CHANNEL_OPTIONS } from '../../constants';
 | 
					import { CHANNEL_OPTIONS } from '../../constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,7 +19,7 @@ const EditChannel = () => {
 | 
				
			|||||||
  const handleCancel = () => {
 | 
					  const handleCancel = () => {
 | 
				
			||||||
    navigate('/channel');
 | 
					    navigate('/channel');
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
  const originInputs = {
 | 
					  const originInputs = {
 | 
				
			||||||
    name: '',
 | 
					    name: '',
 | 
				
			||||||
    type: 1,
 | 
					    type: 1,
 | 
				
			||||||
@@ -62,7 +62,7 @@ const EditChannel = () => {
 | 
				
			|||||||
          localModels = ['SparkDesk'];
 | 
					          localModels = ['SparkDesk'];
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case 19:
 | 
					        case 19:
 | 
				
			||||||
          localModels = ['360GPT_S2_V9', 'embedding-bert-512-v1', 'embedding_s1_v1', 'semantic_similarity_s1_v1', '360GPT_S2_V9.4']
 | 
					          localModels = ['360GPT_S2_V9', 'embedding-bert-512-v1', 'embedding_s1_v1', 'semantic_similarity_s1_v1', '360GPT_S2_V9.4'];
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      setInputs((inputs) => ({ ...inputs, models: localModels }));
 | 
					      setInputs((inputs) => ({ ...inputs, models: localModels }));
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user