mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-10-31 13:53:41 +08:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			v0.6.11-pr
			...
			v0.6.11-pr
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 6916debf66 | ||
|  | 53da209134 | ||
|  | 517f6ad211 | ||
|  | 10aba11f18 | ||
|  | 4d011c5f98 | ||
|  | eb96aa635e | ||
|  | c715f2bc1d | 
| @@ -163,4 +163,4 @@ var UserContentRequestProxy = env.String("USER_CONTENT_REQUEST_PROXY", "") | ||||
| var UserContentRequestTimeout = env.Int("USER_CONTENT_REQUEST_TIMEOUT", 30) | ||||
|  | ||||
| var EnforceIncludeUsage = env.Bool("ENFORCE_INCLUDE_USAGE", false) | ||||
| var TestPrompt = env.String("TEST_PROMPT", "Print your model name exactly and do not output without any other text.") | ||||
| var TestPrompt = env.String("TEST_PROMPT", "Output only your specific model name with no additional text.") | ||||
|   | ||||
| @@ -112,6 +112,13 @@ type DeepSeekUsageResponse struct { | ||||
| 	} `json:"balance_infos"` | ||||
| } | ||||
|  | ||||
| type OpenRouterResponse struct { | ||||
| 	Data struct { | ||||
| 		TotalCredits float64 `json:"total_credits"` | ||||
| 		TotalUsage   float64 `json:"total_usage"` | ||||
| 	} `json:"data"` | ||||
| } | ||||
|  | ||||
| // GetAuthHeader get auth header | ||||
| func GetAuthHeader(token string) http.Header { | ||||
| 	h := http.Header{} | ||||
| @@ -285,6 +292,22 @@ func updateChannelDeepSeekBalance(channel *model.Channel) (float64, error) { | ||||
| 	return balance, nil | ||||
| } | ||||
|  | ||||
| func updateChannelOpenRouterBalance(channel *model.Channel) (float64, error) { | ||||
| 	url := "https://openrouter.ai/api/v1/credits" | ||||
| 	body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key)) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	response := OpenRouterResponse{} | ||||
| 	err = json.Unmarshal(body, &response) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	balance := response.Data.TotalCredits - response.Data.TotalUsage | ||||
| 	channel.UpdateBalance(balance) | ||||
| 	return balance, nil | ||||
| } | ||||
|  | ||||
| func updateChannelBalance(channel *model.Channel) (float64, error) { | ||||
| 	baseURL := channeltype.ChannelBaseURLs[channel.Type] | ||||
| 	if channel.GetBaseURL() == "" { | ||||
| @@ -313,6 +336,8 @@ func updateChannelBalance(channel *model.Channel) (float64, error) { | ||||
| 		return updateChannelSiliconFlowBalance(channel) | ||||
| 	case channeltype.DeepSeek: | ||||
| 		return updateChannelDeepSeekBalance(channel) | ||||
| 	case channeltype.OpenRouter: | ||||
| 		return updateChannelOpenRouterBalance(channel) | ||||
| 	default: | ||||
| 		return 0, errors.New("尚未实现") | ||||
| 	} | ||||
|   | ||||
| @@ -153,6 +153,7 @@ func testChannel(ctx context.Context, channel *model.Channel, request *relaymode | ||||
| 	rawResponse := w.Body.String() | ||||
| 	_, responseMessage, err = parseTestResponse(rawResponse) | ||||
| 	if err != nil { | ||||
| 		logger.SysError(fmt.Sprintf("failed to parse error: %s, \nresponse: %s", err.Error(), rawResponse)) | ||||
| 		return "", err, nil | ||||
| 	} | ||||
| 	result := w.Result() | ||||
|   | ||||
							
								
								
									
										20
									
								
								relay/adaptor/alibailian/constants.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								relay/adaptor/alibailian/constants.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package alibailian | ||||
|  | ||||
| // https://help.aliyun.com/zh/model-studio/getting-started/models | ||||
|  | ||||
| var ModelList = []string{ | ||||
| 	"qwen-turbo", | ||||
| 	"qwen-plus", | ||||
| 	"qwen-long", | ||||
| 	"qwen-max", | ||||
| 	"qwen-coder-plus", | ||||
| 	"qwen-coder-plus-latest", | ||||
| 	"qwen-coder-turbo", | ||||
| 	"qwen-coder-turbo-latest", | ||||
| 	"qwen-mt-plus", | ||||
| 	"qwen-mt-turbo", | ||||
| 	"qwq-32b-preview", | ||||
|  | ||||
| 	"deepseek-r1", | ||||
| 	"deepseek-v3", | ||||
| } | ||||
							
								
								
									
										19
									
								
								relay/adaptor/alibailian/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								relay/adaptor/alibailian/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| package alibailian | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/songquanpeng/one-api/relay/meta" | ||||
| 	"github.com/songquanpeng/one-api/relay/relaymode" | ||||
| ) | ||||
|  | ||||
| func GetRequestURL(meta *meta.Meta) (string, error) { | ||||
| 	switch meta.Mode { | ||||
| 	case relaymode.ChatCompletions: | ||||
| 		return fmt.Sprintf("%s/compatible-mode/v1/chat/completions", meta.BaseURL), nil | ||||
| 	case relaymode.Embeddings: | ||||
| 		return fmt.Sprintf("%s/compatible-mode/v1/embeddings", meta.BaseURL), nil | ||||
| 	default: | ||||
| 	} | ||||
| 	return "", fmt.Errorf("unsupported relay mode %d for ali bailian", meta.Mode) | ||||
| } | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/gin-gonic/gin" | ||||
|  | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/alibailian" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/baiduv2" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/doubao" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/minimax" | ||||
| @@ -56,6 +57,8 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { | ||||
| 		return novita.GetRequestURL(meta) | ||||
| 	case channeltype.BaiduV2: | ||||
| 		return baiduv2.GetRequestURL(meta) | ||||
| 	case channeltype.AliBailian: | ||||
| 		return alibailian.GetRequestURL(meta) | ||||
| 	default: | ||||
| 		return GetFullRequestURL(meta.BaseURL, meta.RequestURLPath, meta.ChannelType), nil | ||||
| 	} | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package openai | ||||
|  | ||||
| import ( | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/ai360" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/alibailian" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/baichuan" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/baiduv2" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/deepseek" | ||||
| @@ -12,6 +13,7 @@ import ( | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/mistral" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/moonshot" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/novita" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/openrouter" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/siliconflow" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/stepfun" | ||||
| 	"github.com/songquanpeng/one-api/relay/adaptor/togetherai" | ||||
| @@ -76,6 +78,10 @@ func GetCompatibleChannelMeta(channelType int) (string, []string) { | ||||
| 		return "baiduv2", baiduv2.ModelList | ||||
| 	case channeltype.XunfeiV2: | ||||
| 		return "xunfeiv2", xunfeiv2.ModelList | ||||
| 	case channeltype.OpenRouter: | ||||
| 		return "openrouter", openrouter.ModelList | ||||
| 	case channeltype.AliBailian: | ||||
| 		return "alibailian", alibailian.ModelList | ||||
| 	default: | ||||
| 		return "openai", ModelList | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										20
									
								
								relay/adaptor/openrouter/constants.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								relay/adaptor/openrouter/constants.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package openrouter | ||||
|  | ||||
| var ModelList = []string{ | ||||
| 	"openai/gpt-3.5-turbo", | ||||
| 	"openai/chatgpt-4o-latest", | ||||
| 	"openai/o1", | ||||
| 	"openai/o1-preview", | ||||
| 	"openai/o1-mini", | ||||
| 	"openai/o3-mini", | ||||
| 	"google/gemini-2.0-flash-001", | ||||
| 	"google/gemini-2.0-flash-thinking-exp:free", | ||||
| 	"google/gemini-2.0-flash-lite-preview-02-05:free", | ||||
| 	"google/gemini-2.0-pro-exp-02-05:free", | ||||
| 	"google/gemini-flash-1.5-8b", | ||||
| 	"anthropic/claude-3.5-sonnet", | ||||
| 	"anthropic/claude-3.5-haiku", | ||||
| 	"deepseek/deepseek-r1:free", | ||||
| 	"deepseek/deepseek-r1", | ||||
| 	"qwen/qwen-vl-plus:free", | ||||
| } | ||||
| @@ -1,5 +1,14 @@ | ||||
| package xai | ||||
|  | ||||
| //https://console.x.ai/ | ||||
|  | ||||
| var ModelList = []string{ | ||||
| 	"grok-2", | ||||
| 	"grok-vision-beta", | ||||
| 	"grok-2-vision-1212", | ||||
| 	"grok-2-vision", | ||||
| 	"grok-2-vision-latest", | ||||
| 	"grok-2-1212", | ||||
| 	"grok-2-latest", | ||||
| 	"grok-beta", | ||||
| } | ||||
|   | ||||
| @@ -50,5 +50,6 @@ const ( | ||||
| 	Replicate | ||||
| 	BaiduV2 | ||||
| 	XunfeiV2 | ||||
| 	AliBailian | ||||
| 	Dummy | ||||
| ) | ||||
|   | ||||
| @@ -50,6 +50,7 @@ var ChannelBaseURLs = []string{ | ||||
| 	"https://api.replicate.com/v1/models/",      // 46 | ||||
| 	"https://qianfan.baidubce.com",              // 47 | ||||
| 	"https://spark-api-open.xf-yun.com",         // 48 | ||||
| 	"https://dashscope.aliyuncs.com",            // 49 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
|   | ||||
| @@ -35,7 +35,7 @@ export const CHANNEL_OPTIONS = [ | ||||
|   { key: 8, text: '自定义渠道', value: 8, color: 'pink' }, | ||||
|   { key: 22, text: '知识库:FastGPT', value: 22, color: 'blue' }, | ||||
|   { key: 21, text: '知识库:AI Proxy', value: 21, color: 'purple' }, | ||||
|   { key: 20, text: '代理:OpenRouter', value: 20, color: 'black' }, | ||||
|   {key: 20, text: 'OpenRouter', value: 20, color: 'black'}, | ||||
|   { key: 2, text: '代理:API2D', value: 2, color: 'blue' }, | ||||
|   { key: 5, text: '代理:OpenAI-SB', value: 5, color: 'brown' }, | ||||
|   { key: 7, text: '代理:OhMyGPT', value: 7, color: 'purple' }, | ||||
|   | ||||
| @@ -217,7 +217,7 @@ export const CHANNEL_OPTIONS = { | ||||
|   }, | ||||
|   20: { | ||||
|     key: 20, | ||||
|     text: '代理:OpenRouter', | ||||
|       text: 'OpenRouter', | ||||
|     value: 20, | ||||
|     color: 'success' | ||||
|   }, | ||||
|   | ||||
| @@ -57,6 +57,8 @@ function renderBalance(type, balance, t) { | ||||
|       return <span>¥{balance.toFixed(2)}</span>; | ||||
|     case 13: // AIGC2D | ||||
|       return <span>{renderNumber(balance)}</span>; | ||||
|     case 20: // OpenRouter | ||||
|       return <span>${balance.toFixed(2)}</span>; | ||||
|     case 36: // DeepSeek | ||||
|       return <span>¥{balance.toFixed(2)}</span>; | ||||
|     case 44: // SiliconFlow | ||||
| @@ -488,7 +490,6 @@ const ChannelsTable = () => { | ||||
|               onClick={() => { | ||||
|                 sortChannel('balance'); | ||||
|               }} | ||||
|               hidden={!showDetail} | ||||
|             > | ||||
|               {t('channel.table.balance')} | ||||
|             </Table.HeaderCell> | ||||
| @@ -497,6 +498,7 @@ const ChannelsTable = () => { | ||||
|               onClick={() => { | ||||
|                 sortChannel('priority'); | ||||
|               }} | ||||
|               hidden={!showDetail} | ||||
|             > | ||||
|               {t('channel.table.priority')} | ||||
|             </Table.HeaderCell> | ||||
| @@ -536,7 +538,7 @@ const ChannelsTable = () => { | ||||
|                       basic | ||||
|                     /> | ||||
|                   </Table.Cell> | ||||
|                   <Table.Cell hidden={!showDetail}> | ||||
|                   <Table.Cell> | ||||
|                     <Popup | ||||
|                       trigger={ | ||||
|                         <span | ||||
| @@ -552,7 +554,7 @@ const ChannelsTable = () => { | ||||
|                       basic | ||||
|                     /> | ||||
|                   </Table.Cell> | ||||
|                   <Table.Cell> | ||||
|                   <Table.Cell hidden={!showDetail}> | ||||
|                     <Popup | ||||
|                       trigger={ | ||||
|                         <Input | ||||
|   | ||||
| @@ -28,7 +28,14 @@ export const CHANNEL_OPTIONS = [ | ||||
|     color: 'blue', | ||||
|     tip: '请前往<a href="https://console.bce.baidu.com/iam/#/iam/apikey/list" target="_blank">此处</a>获取 API Key,注意本渠道仅支持<a target="_blank" href="https://cloud.baidu.com/doc/WENXINWORKSHOP/s/em4tsqo3v">推理服务 V2</a>相关模型', | ||||
|   }, | ||||
|   {key: 17, text: '阿里通义千问', value: 17, color: 'orange'}, | ||||
|     { | ||||
|         key: 17, | ||||
|         text: '阿里通义千问', | ||||
|         value: 17, | ||||
|         color: 'orange', | ||||
|         tip: '如需使用阿里云百炼,请使用<strong>阿里云百炼</strong>渠道', | ||||
|     }, | ||||
|     {key: 49, text: '阿里云百炼', value: 49, color: 'orange'}, | ||||
|   { | ||||
|     key: 18, | ||||
|     text: '讯飞星火认知', | ||||
| @@ -67,7 +74,7 @@ export const CHANNEL_OPTIONS = [ | ||||
|     {key: 8, text: '自定义渠道', value: 8, color: 'pink'}, | ||||
|     {key: 22, text: '知识库:FastGPT', value: 22, color: 'blue'}, | ||||
|     {key: 21, text: '知识库:AI Proxy', value: 21, color: 'purple'}, | ||||
|   {key: 20, text: '代理:OpenRouter', value: 20, color: 'black'}, | ||||
|     {key: 20, text: 'OpenRouter', value: 20, color: 'black'}, | ||||
|     {key: 2, text: '代理:API2D', value: 2, color: 'blue'}, | ||||
|     {key: 5, text: '代理:OpenAI-SB', value: 5, color: 'brown'}, | ||||
|     {key: 7, text: '代理:OhMyGPT', value: 7, color: 'purple'}, | ||||
|   | ||||
| @@ -122,11 +122,11 @@ const Dashboard = () => { | ||||
|         ? new Date(Math.min(...dates.map((d) => new Date(d)))) | ||||
|         : new Date(); | ||||
|  | ||||
|     // 确保至少显示5天的数据 | ||||
|     const fiveDaysAgo = new Date(); | ||||
|     fiveDaysAgo.setDate(fiveDaysAgo.getDate() - 4); // -4是因为包含今天 | ||||
|     if (minDate > fiveDaysAgo) { | ||||
|       minDate = fiveDaysAgo; | ||||
|     // 确保至少显示7天的数据 | ||||
|     const sevenDaysAgo = new Date(); | ||||
|     sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 6); // -6是因为包含今天 | ||||
|     if (minDate > sevenDaysAgo) { | ||||
|       minDate = sevenDaysAgo; | ||||
|     } | ||||
|  | ||||
|     // 生成所有日期 | ||||
| @@ -164,11 +164,11 @@ const Dashboard = () => { | ||||
|         ? new Date(Math.min(...dates.map((d) => new Date(d)))) | ||||
|         : new Date(); | ||||
|  | ||||
|     // 确保至少显示5天的数据 | ||||
|     const fiveDaysAgo = new Date(); | ||||
|     fiveDaysAgo.setDate(fiveDaysAgo.getDate() - 4); // -4是因为包含今天 | ||||
|     if (minDate > fiveDaysAgo) { | ||||
|       minDate = fiveDaysAgo; | ||||
|     // 确保至少显示7天的数据 | ||||
|     const sevenDaysAgo = new Date(); | ||||
|     sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 6); // -6是因为包含今天 | ||||
|     if (minDate > sevenDaysAgo) { | ||||
|       minDate = sevenDaysAgo; | ||||
|     } | ||||
|  | ||||
|     // 生成所有日期 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user