From c70c614018a5992890564cba28d3d6172c8f71b3 Mon Sep 17 00:00:00 2001 From: papersnake Date: Sun, 5 Nov 2023 17:59:38 +0800 Subject: [PATCH 1/9] feat: support chatglm_turbo (#648) * feat: support chatglm_turbo * fix: remove characterglm --- common/model-ratio.go | 1 + controller/model.go | 9 +++++++++ web/src/pages/Channel/EditChannel.js | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/common/model-ratio.go b/common/model-ratio.go index f52e1101..8f4be8c3 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -49,6 +49,7 @@ var ModelRatio = map[string]float64{ "ERNIE-Bot-4": 8.572, // ¥0.12 / 1k tokens "Embedding-V1": 0.1429, // ¥0.002 / 1k tokens "PaLM-2": 1, + "chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens "chatglm_pro": 0.7143, // ¥0.01 / 1k tokens "chatglm_std": 0.3572, // ¥0.005 / 1k tokens "chatglm_lite": 0.1429, // ¥0.002 / 1k tokens diff --git a/controller/model.go b/controller/model.go index ed35b7a6..2a7dc538 100644 --- a/controller/model.go +++ b/controller/model.go @@ -333,6 +333,15 @@ func init() { Root: "PaLM-2", Parent: nil, }, + { + Id: "chatglm_turbo", + Object: "model", + Created: 1677649963, + OwnedBy: "zhipu", + Permission: permission, + Root: "chatglm_turbo", + Parent: nil, + }, { Id: "chatglm_pro", Object: "model", diff --git a/web/src/pages/Channel/EditChannel.js b/web/src/pages/Channel/EditChannel.js index 3b059d7b..654a5d51 100644 --- a/web/src/pages/Channel/EditChannel.js +++ b/web/src/pages/Channel/EditChannel.js @@ -72,7 +72,7 @@ const EditChannel = () => { localModels = ['qwen-turbo', 'qwen-plus', 'text-embedding-v1']; break; case 16: - localModels = ['chatglm_pro', 'chatglm_std', 'chatglm_lite']; + localModels = ['chatglm_turbo', 'chatglm_pro', 'chatglm_std', 'chatglm_lite']; break; case 18: localModels = ['SparkDesk']; From 3fe76c8af7c11b8afd8893ed2621ecc200abcb12 Mon Sep 17 00:00:00 2001 From: wood chen <95951386+woodchen-ink@users.noreply.github.com> Date: Sun, 5 Nov 2023 05:08:25 -0600 Subject: [PATCH 2/9] fix: fix Cloudflare AI Gateway channel test support (#639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 当使用Cloudflare AI Gateway时,支持openai渠道测试 * refactor: change logic --------- Co-authored-by: JustSong --- controller/channel-test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/controller/channel-test.go b/controller/channel-test.go index ae4ab7d5..3c6c8f43 100644 --- a/controller/channel-test.go +++ b/controller/channel-test.go @@ -5,14 +5,14 @@ import ( "encoding/json" "errors" "fmt" + "github.com/gin-gonic/gin" "net/http" "one-api/common" "one-api/model" "strconv" + "strings" "sync" "time" - - "github.com/gin-gonic/gin" ) func testChannel(channel *model.Channel, request ChatRequest) (err error, openaiErr *OpenAIError) { @@ -50,6 +50,8 @@ func testChannel(channel *model.Channel, request ChatRequest) (err error, openai } requestURL += "/v1/chat/completions" } + // for Cloudflare AI gateway: https://github.com/songquanpeng/one-api/pull/639 + requestURL = strings.Replace(requestURL, "/v1/v1", "/v1", 1) jsonData, err := json.Marshal(request) if err != nil { From bc7c9105f4b6cb18d7302415567d502e5681381e Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 5 Nov 2023 19:15:06 +0800 Subject: [PATCH 3/9] chore: update quota calc logic (close #599) (#627) * fix: change quota calc code (close #599) Use float64 during calc and do math.Ceil after calc. This will result in the quota being used slightly more than the official standard, but it will be guaranteed that it will not be less. * chore: remove blank line --------- Co-authored-by: JustSong --- controller/relay-text.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/controller/relay-text.go b/controller/relay-text.go index 25b8bc06..a61c6f7c 100644 --- a/controller/relay-text.go +++ b/controller/relay-text.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "math" "net/http" "one-api/common" "one-api/model" @@ -414,9 +415,7 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { completionRatio := common.GetCompletionRatio(textRequest.Model) promptTokens = textResponse.Usage.PromptTokens completionTokens = textResponse.Usage.CompletionTokens - - quota = promptTokens + int(float64(completionTokens)*completionRatio) - quota = int(float64(quota) * ratio) + quota = int(math.Ceil((float64(promptTokens) + float64(completionTokens)*completionRatio) * ratio)) if ratio != 0 && quota <= 0 { quota = 1 } From e5311892d1075a7facfd32c6aa358e4a574138da Mon Sep 17 00:00:00 2001 From: JustSong Date: Wed, 8 Nov 2023 23:17:12 +0800 Subject: [PATCH 4/9] docs: update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79229a94..38e3e0b7 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用 + [x] [腾讯混元大模型](https://cloud.tencent.com/document/product/1729) 2. 支持配置镜像以及众多第三方代理服务: + [x] [OpenAI-SB](https://openai-sb.com) - + [x] [CloseAI](https://console.closeai-asia.com/r/2412) + + [x] [CloseAI](https://referer.shadowai.xyz/r/2412) + [x] [API2D](https://api2d.com/r/197971) + [x] [OhMyGPT](https://aigptx.top?aff=uFpUl2Kf) + [x] [AI Proxy](https://aiproxy.io/?i=OneAPI) (邀请码:`OneAPI`) From 9d43ec57d8e67aa89acb1af78f21c1469d26a113 Mon Sep 17 00:00:00 2001 From: Mikey Date: Fri, 10 Nov 2023 05:08:23 -0800 Subject: [PATCH 5/9] feat: sync pricing for new 1106 models (#696) * feat: sync pricing for new 1106 models * chore: change ratio after 2023-12-11 --------- Co-authored-by: JustSong --- common/model-ratio.go | 19 +++++++++++++++++++ controller/model.go | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/common/model-ratio.go b/common/model-ratio.go index 8f4be8c3..681f0ae7 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -3,6 +3,7 @@ package common import ( "encoding/json" "strings" + "time" ) // ModelRatio @@ -19,12 +20,15 @@ var ModelRatio = map[string]float64{ "gpt-4-32k": 30, "gpt-4-32k-0314": 30, "gpt-4-32k-0613": 30, + "gpt-4-1106-preview": 5, // $0.01 / 1K tokens + "gpt-4-vision-preview": 5, // $0.01 / 1K tokens "gpt-3.5-turbo": 0.75, // $0.0015 / 1K tokens "gpt-3.5-turbo-0301": 0.75, "gpt-3.5-turbo-0613": 0.75, "gpt-3.5-turbo-16k": 1.5, // $0.003 / 1K tokens "gpt-3.5-turbo-16k-0613": 1.5, "gpt-3.5-turbo-instruct": 0.75, // $0.0015 / 1K tokens + "gpt-3.5-turbo-1106": 0.5, // $0.001 / 1K tokens "text-ada-001": 0.2, "text-babbage-001": 0.25, "text-curie-001": 1, @@ -88,9 +92,24 @@ func GetModelRatio(name string) float64 { func GetCompletionRatio(name string) float64 { if strings.HasPrefix(name, "gpt-3.5") { + if strings.HasSuffix(name, "1106") { + return 2 + } + if name == "gpt-3.5-turbo" || name == "gpt-3.5-turbo-16k" { + // TODO: clear this after 2023-12-11 + now := time.Now() + // https://platform.openai.com/docs/models/continuous-model-upgrades + // if after 2023-12-11, use 2 + if now.After(time.Date(2023, 12, 11, 0, 0, 0, 0, time.UTC)) { + return 2 + } + } return 1.333333 } if strings.HasPrefix(name, "gpt-4") { + if strings.HasSuffix(name, "preview") { + return 3 + } return 2 } if strings.HasPrefix(name, "claude-instant-1") { diff --git a/controller/model.go b/controller/model.go index 2a7dc538..7bd9d097 100644 --- a/controller/model.go +++ b/controller/model.go @@ -117,6 +117,15 @@ func init() { Root: "gpt-3.5-turbo-16k-0613", Parent: nil, }, + { + Id: "gpt-3.5-turbo-1106", + Object: "model", + Created: 1699593571, + OwnedBy: "openai", + Permission: permission, + Root: "gpt-3.5-turbo-1106", + Parent: nil, + }, { Id: "gpt-3.5-turbo-instruct", Object: "model", @@ -180,6 +189,24 @@ func init() { Root: "gpt-4-32k-0613", Parent: nil, }, + { + Id: "gpt-4-1106-preview", + Object: "model", + Created: 1699593571, + OwnedBy: "openai", + Permission: permission, + Root: "gpt-4-1106-preview", + Parent: nil, + }, + { + Id: "gpt-4-vision-preview", + Object: "model", + Created: 1699593571, + OwnedBy: "openai", + Permission: permission, + Root: "gpt-4-vision-preview", + Parent: nil, + }, { Id: "text-embedding-ada-002", Object: "model", From 7c4505bdfc4af036dacea6050e04e4aa92f9c8d2 Mon Sep 17 00:00:00 2001 From: Baksi Date: Fri, 10 Nov 2023 21:20:05 +0800 Subject: [PATCH 6/9] fix: numeric sorting in tables (#695) * Update sorting method for id * Update sorting method for id (token) * Update sorting method for id (redemptions) * Update sorting method for id (channel) * chore: use same logic for all tables --------- Co-authored-by: JustSong --- web/src/components/ChannelsTable.js | 19 +++++++++---------- web/src/components/RedemptionsTable.js | 8 +++++++- web/src/components/TokensTable.js | 8 +++++++- web/src/components/UsersTable.js | 8 +++++++- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js index 732189cb..d44ea2d7 100644 --- a/web/src/components/ChannelsTable.js +++ b/web/src/components/ChannelsTable.js @@ -286,17 +286,15 @@ const ChannelsTable = () => { if (channels.length === 0) return; setLoading(true); let sortedChannels = [...channels]; - if (typeof sortedChannels[0][key] === 'string') { - sortedChannels.sort((a, b) => { + sortedChannels.sort((a, b) => { + if (!isNaN(a[key])) { + // If the value is numeric, subtract to sort + return a[key] - b[key]; + } else { + // If the value is not numeric, sort as strings return ('' + a[key]).localeCompare(b[key]); - }); - } else { - sortedChannels.sort((a, b) => { - if (a[key] === b[key]) return 0; - if (a[key] > b[key]) return -1; - if (a[key] < b[key]) return 1; - }); - } + } + }); if (sortedChannels[0].id === channels[0].id) { sortedChannels.reverse(); } @@ -304,6 +302,7 @@ const ChannelsTable = () => { setLoading(false); }; + return ( <>
diff --git a/web/src/components/RedemptionsTable.js b/web/src/components/RedemptionsTable.js index ae8b5b03..dfd59685 100644 --- a/web/src/components/RedemptionsTable.js +++ b/web/src/components/RedemptionsTable.js @@ -130,7 +130,13 @@ const RedemptionsTable = () => { setLoading(true); let sortedRedemptions = [...redemptions]; sortedRedemptions.sort((a, b) => { - return ('' + a[key]).localeCompare(b[key]); + if (!isNaN(a[key])) { + // If the value is numeric, subtract to sort + return a[key] - b[key]; + } else { + // If the value is not numeric, sort as strings + return ('' + a[key]).localeCompare(b[key]); + } }); if (sortedRedemptions[0].id === redemptions[0].id) { sortedRedemptions.reverse(); diff --git a/web/src/components/TokensTable.js b/web/src/components/TokensTable.js index a3bb6f91..db4745e4 100644 --- a/web/src/components/TokensTable.js +++ b/web/src/components/TokensTable.js @@ -228,7 +228,13 @@ const TokensTable = () => { setLoading(true); let sortedTokens = [...tokens]; sortedTokens.sort((a, b) => { - return ('' + a[key]).localeCompare(b[key]); + if (!isNaN(a[key])) { + // If the value is numeric, subtract to sort + return a[key] - b[key]; + } else { + // If the value is not numeric, sort as strings + return ('' + a[key]).localeCompare(b[key]); + } }); if (sortedTokens[0].id === tokens[0].id) { sortedTokens.reverse(); diff --git a/web/src/components/UsersTable.js b/web/src/components/UsersTable.js index f8fb0a75..ad4e9b49 100644 --- a/web/src/components/UsersTable.js +++ b/web/src/components/UsersTable.js @@ -133,7 +133,13 @@ const UsersTable = () => { setLoading(true); let sortedUsers = [...users]; sortedUsers.sort((a, b) => { - return ('' + a[key]).localeCompare(b[key]); + if (!isNaN(a[key])) { + // If the value is numeric, subtract to sort + return a[key] - b[key]; + } else { + // If the value is not numeric, sort as strings + return ('' + a[key]).localeCompare(b[key]); + } }); if (sortedUsers[0].id === users[0].id) { sortedUsers.reverse(); From 6c5307d0c4c7740ad6eb7917dced6dd2b939f3b1 Mon Sep 17 00:00:00 2001 From: Yuhang <2312744987@qq.com> Date: Fri, 10 Nov 2023 21:20:59 +0800 Subject: [PATCH 7/9] docs: add deploy to zeabur button (#693) * Update README.md * Update README.en.md * Update README.ja.md --- README.en.md | 2 ++ README.ja.md | 2 ++ README.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/README.en.md b/README.en.md index 783c140c..9345a219 100644 --- a/README.en.md +++ b/README.en.md @@ -189,6 +189,8 @@ If you encounter a blank page after deployment, refer to [#97](https://github.co > Zeabur's servers are located overseas, automatically solving network issues, and the free quota is sufficient for personal usage. +[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/7Q0KO3) + 1. First, fork the code. 2. Go to [Zeabur](https://zeabur.com?referralCode=songquanpeng), log in, and enter the console. 3. Create a new project. In Service -> Add Service, select Marketplace, and choose MySQL. Note down the connection parameters (username, password, address, and port). diff --git a/README.ja.md b/README.ja.md index fa3339c2..6faf9bee 100644 --- a/README.ja.md +++ b/README.ja.md @@ -190,6 +190,8 @@ Please refer to the [environment variables](#environment-variables) section for > Zeabur のサーバーは海外にあるため、ネットワークの問題は自動的に解決されます。 +[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/7Q0KO3) + 1. まず、コードをフォークする。 2. [Zeabur](https://zeabur.com?referralCode=songquanpeng) にアクセスしてログインし、コンソールに入る。 3. 新しいプロジェクトを作成します。Service -> Add ServiceでMarketplace を選択し、MySQL を選択する。接続パラメータ(ユーザー名、パスワード、アドレス、ポート)をメモします。 diff --git a/README.md b/README.md index 38e3e0b7..39eb5fa1 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,8 @@ docker run --name chatgpt-web -d -p 3002:3002 -e OPENAI_API_BASE_URL=https://ope > Zeabur 的服务器在国外,自动解决了网络的问题,同时免费的额度也足够个人使用 +[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/7Q0KO3) + 1. 首先 fork 一份代码。 2. 进入 [Zeabur](https://zeabur.com?referralCode=songquanpeng),登录,进入控制台。 3. 新建一个 Project,在 Service -> Add Service 选择 Marketplace,选择 MySQL,并记下连接参数(用户名、密码、地址、端口)。 From d306cb52293b4053105d0de869795bffc4593730 Mon Sep 17 00:00:00 2001 From: qingfengfenga <41416092+qingfengfenga@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:40:00 +0800 Subject: [PATCH 8/9] feat: add improve docker-compose.yml and support fast startup (#685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 王彦朋 Penn Wang --- .gitignore | 3 ++- README.md | 13 +++++++++++++ docker-compose.yml | 21 ++++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 1b2cf071..60abb13e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ upload *.db build *.db-journal -logs \ No newline at end of file +logs +data \ No newline at end of file diff --git a/README.md b/README.md index 39eb5fa1..4ef6505c 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,19 @@ sudo service nginx restart 初始账号用户名为 `root`,密码为 `123456`。 + +### 基于 Docker Compose 进行部署 + +> 仅启动方式不同,参数设置不变,请参考基于 Docker 部署部分 + +```shell +# 目前支持 MySQL 启动,数据存储在 ./data/mysql 文件夹内 +docker-compose up -d + +# 查看部署状态 +docker-compose ps +``` + ### 手动部署 1. 从 [GitHub Releases](https://github.com/songquanpeng/one-api/releases/latest) 下载可执行文件或者从源码编译: ```shell diff --git a/docker-compose.yml b/docker-compose.yml index 9b814a03..30edb281 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,19 +9,19 @@ services: ports: - "3000:3000" volumes: - - ./data:/data + - ./data/oneapi:/data - ./logs:/app/logs environment: - - SQL_DSN=root:123456@tcp(host.docker.internal:3306)/one-api # 修改此行,或注释掉以使用 SQLite 作为数据库 + - SQL_DSN=oneapi:123456@tcp(db:3306)/one-api # 修改此行,或注释掉以使用 SQLite 作为数据库 - REDIS_CONN_STRING=redis://redis - SESSION_SECRET=random_string # 修改为随机字符串 - TZ=Asia/Shanghai # - NODE_TYPE=slave # 多机部署时从节点取消注释该行 # - SYNC_FREQUENCY=60 # 需要定期从数据库加载数据时取消注释该行 # - FRONTEND_BASE_URL=https://openai.justsong.cn # 多机部署时从节点取消注释该行 - depends_on: - redis + - db healthcheck: test: [ "CMD-SHELL", "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' | awk -F: '{print $2}'" ] interval: 30s @@ -32,3 +32,18 @@ services: image: redis:latest container_name: redis restart: always + + db: + image: mysql:8.2.0 + restart: always + container_name: mysql + volumes: + - ./data/mysql:/var/lib/mysql # 挂载目录,持久化存储 + ports: + - '3306:3306' + environment: + TZ: Asia/Shanghai # 设置时区 + MYSQL_ROOT_PASSWORD: 'OneAPI@justsong' # 设置 root 用户的密码 + MYSQL_USER: oneapi # 创建专用用户 + MYSQL_PASSWORD: '123456' # 设置专用用户密码 + MYSQL_DATABASE: one-api # 自动创建数据库 \ No newline at end of file From 58bb3ab6f6008af8135464877259db610f89992d Mon Sep 17 00:00:00 2001 From: Dafei Zhao Date: Fri, 10 Nov 2023 08:50:52 -0500 Subject: [PATCH 9/9] fix: fix channel_id column name (#681, close #688) --- model/log.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model/log.go b/model/log.go index d26da9a2..3d3ffae3 100644 --- a/model/log.go +++ b/model/log.go @@ -94,7 +94,7 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName tx = tx.Where("created_at <= ?", endTimestamp) } if channel != 0 { - tx = tx.Where("channel = ?", channel) + tx = tx.Where("channel_id = ?", channel) } err = tx.Order("id desc").Limit(num).Offset(startIdx).Find(&logs).Error return logs, err @@ -151,7 +151,7 @@ func SumUsedQuota(logType int, startTimestamp int64, endTimestamp int64, modelNa tx = tx.Where("model_name = ?", modelName) } if channel != 0 { - tx = tx.Where("channel = ?", channel) + tx = tx.Where("channel_id = ?", channel) } tx.Where("type = ?", LogTypeConsume).Scan("a) return quota