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

feat: support balance query for CloseAI (#240)

* 增加CloseAI余额查询功能

* 去除debug代码

* fix: bug fix

* docs: update README

---------

Co-authored-by: sudongyang <sudongyang@xiaomi.com>
Co-authored-by: JustSong <songquanpeng@foxmail.com>
Cross Fire 2 лет назад
Родитель
Сommit
d383302e8a
4 измененных файлов с 46 добавлено и 14 удалено
  1. 1 0
      README.md
  2. 14 14
      common/constants.go
  3. 28 0
      controller/channel-billing.go
  4. 3 0
      web/src/components/ChannelsTable.js

+ 1 - 0
README.md

@@ -66,6 +66,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
    + [x] [API2D](https://api2d.com/r/197971)
    + [x] [OhMyGPT](https://aigptx.top?aff=uFpUl2Kf)
    + [x] [AI Proxy](https://aiproxy.io/?i=OneAPI) (邀请码:`OneAPI`)
+   + [x] [CloseAI](https://console.closeai-asia.com/r/2412)
    + [x] 自定义渠道:例如各种未收录的第三方代理服务
 2. 支持通过**负载均衡**的方式访问多个渠道。
 3. 支持 **stream 模式**,可以通过流式传输实现打字机效果。

+ 14 - 14
common/constants.go

@@ -152,18 +152,18 @@ const (
 )
 
 var ChannelBaseURLs = []string{
-	"",                             // 0
-	"https://api.openai.com",       // 1
-	"https://oa.api2d.net",         // 2
-	"",                             // 3
-	"https://api.openai-proxy.org", // 4
-	"https://api.openai-sb.com",    // 5
-	"https://api.openaimax.com",    // 6
-	"https://api.ohmygpt.com",      // 7
-	"",                             // 8
-	"https://api.caipacity.com",    // 9
-	"https://api.aiproxy.io",       // 10
-	"",                             // 11
-	"https://api.api2gpt.com",      // 12
-	"https://api.aigc2d.com",       // 13
+	"",                              // 0
+	"https://api.openai.com",        // 1
+	"https://oa.api2d.net",          // 2
+	"",                              // 3
+	"https://api.closeai-proxy.xyz", // 4
+	"https://api.openai-sb.com",     // 5
+	"https://api.openaimax.com",     // 6
+	"https://api.ohmygpt.com",       // 7
+	"",                              // 8
+	"https://api.caipacity.com",     // 9
+	"https://api.aiproxy.io",        // 10
+	"",                              // 11
+	"https://api.api2gpt.com",       // 12
+	"https://api.aigc2d.com",        // 13
 }

+ 28 - 0
controller/channel-billing.go

@@ -32,6 +32,13 @@ type OpenAIUsageDailyCost struct {
 	}
 }
 
+type OpenAICreditGrants struct {
+	Object         string  `json:"object"`
+	TotalGranted   float64 `json:"total_granted"`
+	TotalUsed      float64 `json:"total_used"`
+	TotalAvailable float64 `json:"total_available"`
+}
+
 type OpenAIUsageResponse struct {
 	Object string `json:"object"`
 	//DailyCosts []OpenAIUsageDailyCost `json:"daily_costs"`
@@ -100,6 +107,22 @@ func GetResponseBody(method, url string, channel *model.Channel, headers http.He
 	return body, nil
 }
 
+func updateChannelCloseAIBalance(channel *model.Channel) (float64, error) {
+	url := fmt.Sprintf("%s/dashboard/billing/credit_grants", channel.BaseURL)
+	body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
+
+	if err != nil {
+		return 0, err
+	}
+	response := OpenAICreditGrants{}
+	err = json.Unmarshal(body, &response)
+	if err != nil {
+		return 0, err
+	}
+	channel.UpdateBalance(response.TotalAvailable)
+	return response.TotalAvailable, nil
+}
+
 func updateChannelOpenAISBBalance(channel *model.Channel) (float64, error) {
 	url := fmt.Sprintf("https://api.openai-sb.com/sb-api/user/status?api_key=%s", channel.Key)
 	body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
@@ -175,6 +198,9 @@ func updateChannelAIGC2DBalance(channel *model.Channel) (float64, error) {
 
 func updateChannelBalance(channel *model.Channel) (float64, error) {
 	baseURL := common.ChannelBaseURLs[channel.Type]
+	if channel.BaseURL == "" {
+		channel.BaseURL = baseURL
+	}
 	switch channel.Type {
 	case common.ChannelTypeOpenAI:
 		if channel.BaseURL != "" {
@@ -184,6 +210,8 @@ func updateChannelBalance(channel *model.Channel) (float64, error) {
 		return 0, errors.New("尚未实现")
 	case common.ChannelTypeCustom:
 		baseURL = channel.BaseURL
+	case common.ChannelTypeCloseAI:
+		return updateChannelCloseAIBalance(channel)
 	case common.ChannelTypeOpenAISB:
 		return updateChannelOpenAISBBalance(channel)
 	case common.ChannelTypeAIProxy:

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

@@ -30,6 +30,9 @@ function renderType(type) {
 function renderBalance(type, balance) {
   switch (type) {
     case 1: // OpenAI
+      return <span>${balance.toFixed(2)}</span>;
+    case 4: // CloseAI
+      return <span>¥{balance.toFixed(2)}</span>;
     case 8: // 自定义
       return <span>${balance.toFixed(2)}</span>;
     case 5: // OpenAI-SB