3v324v23 commited on
Commit
ca9b615
·
1 Parent(s): 9dfaf87

更新版本

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .github/workflows/docker-image-arm64.yml +0 -3
  2. BT.md +3 -3
  3. Dockerfile +13 -9
  4. README.en.md +34 -5
  5. README.md +217 -10
  6. VERSION +1 -1
  7. common/constants.go +7 -2
  8. common/database.go +1 -0
  9. controller/channel-test.go +27 -6
  10. controller/relay.go +2 -0
  11. dto/embedding.go +57 -0
  12. dto/openai_request.go +18 -5
  13. dto/openai_response.go +1 -1
  14. go.mod +10 -4
  15. go.sum +23 -9
  16. main.go +7 -0
  17. middleware/distributor.go +2 -0
  18. model/cache.go +0 -100
  19. model/log.go +28 -6
  20. model/main.go +1 -1
  21. model/option.go +3 -0
  22. relay/channel/adapter.go +1 -0
  23. relay/channel/ali/adaptor.go +4 -3
  24. relay/channel/ali/text.go +5 -2
  25. relay/channel/aws/adaptor.go +6 -0
  26. relay/channel/baidu/adaptor.go +5 -3
  27. relay/channel/baidu/relay-baidu.go +1 -1
  28. relay/channel/baidu_v2/adaptor.go +76 -0
  29. relay/channel/baidu_v2/constants.go +29 -0
  30. relay/channel/claude/adaptor.go +5 -0
  31. relay/channel/cloudflare/adaptor.go +4 -0
  32. relay/channel/cohere/adaptor.go +6 -0
  33. relay/channel/deepseek/adaptor.go +6 -1
  34. relay/channel/dify/adaptor.go +6 -0
  35. relay/channel/gemini/adaptor.go +6 -0
  36. relay/channel/jina/adaptor.go +4 -0
  37. relay/channel/mistral/adaptor.go +6 -0
  38. relay/channel/mokaai/adaptor.go +93 -0
  39. relay/channel/mokaai/constants.go +9 -0
  40. relay/channel/mokaai/relay-mokaai.go +83 -0
  41. relay/channel/ollama/adaptor.go +5 -6
  42. relay/channel/ollama/relay-ollama.go +6 -6
  43. relay/channel/openai/adaptor.go +4 -0
  44. relay/channel/openai/relay-openai.go +6 -6
  45. relay/channel/palm/adaptor.go +6 -0
  46. relay/channel/perplexity/adaptor.go +6 -0
  47. relay/channel/siliconflow/adaptor.go +4 -0
  48. relay/channel/tencent/adaptor.go +6 -0
  49. relay/channel/vertex/adaptor.go +6 -0
  50. relay/channel/volcengine/adaptor.go +92 -0
.github/workflows/docker-image-arm64.yml CHANGED
@@ -52,9 +52,6 @@ jobs:
52
  calciumion/new-api
53
  ghcr.io/${{ github.repository }}
54
 
55
- - name: Update Go dependencies
56
- run: go get -u ./...
57
-
58
  - name: Build and push Docker images
59
  uses: docker/build-push-action@v3
60
  with:
 
52
  calciumion/new-api
53
  ghcr.io/${{ github.repository }}
54
 
 
 
 
55
  - name: Build and push Docker images
56
  uses: docker/build-push-action@v3
57
  with:
BT.md CHANGED
@@ -1,3 +1,3 @@
1
- 密钥为环境变量SESSION_SECRET
2
-
3
- ![8285bba413e770fe9620f1bf9b40d44e](https://github.com/user-attachments/assets/7a6fc03e-c457-45e4-b8f9-184508fc26b0)
 
1
+ 密钥为环境变量SESSION_SECRET
2
+
3
+ ![8285bba413e770fe9620f1bf9b40d44e](https://github.com/user-attachments/assets/7a6fc03e-c457-45e4-b8f9-184508fc26b0)
Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM oven/bun:latest as builder
2
 
3
  WORKDIR /build
4
  COPY web/package.json .
@@ -7,25 +7,29 @@ COPY ./web .
7
  COPY ./VERSION .
8
  RUN DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(cat VERSION) bun run build
9
 
10
- FROM golang AS builder2
11
 
12
- ENV GO111MODULE=on
13
- ENV CGO_ENABLED=1
14
- ENV GOOS=linux
15
 
16
  WORKDIR /build
 
17
  ADD go.mod go.sum ./
18
  RUN go mod download
 
19
  COPY . .
20
  COPY --from=builder /build/dist ./web/dist
21
- RUN go build -ldflags "-s -w -X 'one-api/common.Version=$(cat VERSION)' -extldflags '-static'" -o one-api
22
 
23
  FROM alpine
24
 
25
- RUN apk update && apk upgrade && apk add --no-cache ca-certificates tzdata ffmpeg && update-ca-certificates
 
 
 
26
 
27
  COPY --from=builder2 /build/one-api /
28
- RUN mkdir -p /data/logs && chmod 777 /data/logs # 创建 logs 目录并设置 777 权限
29
  EXPOSE 3000
30
  WORKDIR /data
31
- ENTRYPOINT ["/one-api"]
 
1
+ FROM oven/bun:latest AS builder
2
 
3
  WORKDIR /build
4
  COPY web/package.json .
 
7
  COPY ./VERSION .
8
  RUN DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(cat VERSION) bun run build
9
 
10
+ FROM golang:alpine AS builder2
11
 
12
+ ENV GO111MODULE=on \
13
+ CGO_ENABLED=0 \
14
+ GOOS=linux
15
 
16
  WORKDIR /build
17
+
18
  ADD go.mod go.sum ./
19
  RUN go mod download
20
+
21
  COPY . .
22
  COPY --from=builder /build/dist ./web/dist
23
+ RUN go build -ldflags "-s -w -X 'one-api/common.Version=$(cat VERSION)'" -o one-api
24
 
25
  FROM alpine
26
 
27
+ RUN apk update \
28
+ && apk upgrade \
29
+ && apk add --no-cache ca-certificates tzdata ffmpeg \
30
+ && update-ca-certificates
31
 
32
  COPY --from=builder2 /build/one-api /
 
33
  EXPOSE 3000
34
  WORKDIR /data
35
+ ENTRYPOINT ["/one-api"]
README.en.md CHANGED
@@ -91,13 +91,10 @@ You can add custom models gpt-4-gizmo-* in channels. These are third-party model
91
  - `AZURE_DEFAULT_API_VERSION`: Azure channel default API version, if not specified in channel settings, use this version, default `2024-12-01-preview`
92
 
93
  ## Deployment
 
94
  > [!TIP]
95
  > Latest Docker image: `calciumion/new-api:latest`
96
- > Default account: root, password: 123456
97
- > Update command:
98
- > ```
99
- > docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
100
- > ```
101
 
102
  ### Multi-Server Deployment
103
  - Must set `SESSION_SECRET` environment variable, otherwise login state will not be consistent across multiple servers.
@@ -107,26 +104,58 @@ You can add custom models gpt-4-gizmo-* in channels. These are third-party model
107
  - Local database (default): SQLite (Docker deployment must mount `/data` directory)
108
  - Remote database: MySQL >= 5.7.8, PgSQL >= 9.6
109
 
 
 
 
 
 
 
110
  ### Docker Deployment
 
111
  ### Using Docker Compose (Recommended)
112
  ```shell
113
  # Clone project
114
  git clone https://github.com/Calcium-Ion/new-api.git
115
  cd new-api
116
  # Edit docker-compose.yml as needed
 
 
117
  # Start
118
  docker-compose up -d
119
  ```
120
 
 
 
 
 
 
 
121
  ### Direct Docker Image Usage
122
  ```shell
123
  # SQLite deployment:
124
  docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
 
125
  # MySQL deployment (add -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"), modify database connection parameters as needed
126
  # Example:
127
  docker run --name new-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
128
  ```
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  ## Channel Retry
131
  Channel retry is implemented, configurable in `Settings->Operation Settings->General Settings`. **Cache recommended**.
132
  First retry uses same priority, second retry uses next priority, and so on.
 
91
  - `AZURE_DEFAULT_API_VERSION`: Azure channel default API version, if not specified in channel settings, use this version, default `2024-12-01-preview`
92
 
93
  ## Deployment
94
+
95
  > [!TIP]
96
  > Latest Docker image: `calciumion/new-api:latest`
97
+ > Default account: root, password: 123456
 
 
 
 
98
 
99
  ### Multi-Server Deployment
100
  - Must set `SESSION_SECRET` environment variable, otherwise login state will not be consistent across multiple servers.
 
104
  - Local database (default): SQLite (Docker deployment must mount `/data` directory)
105
  - Remote database: MySQL >= 5.7.8, PgSQL >= 9.6
106
 
107
+ ### Deployment with BT Panel
108
+ Install BT Panel (**version 9.2.0** or above) from [BT Panel Official Website](https://www.bt.cn/new/download.html), choose the stable version script to download and install.
109
+ After installation, log in to BT Panel and click Docker in the menu bar. First-time access will prompt to install Docker service. Click Install Now and follow the prompts to complete installation.
110
+ After installation, find **New-API** in the app store, click install, configure basic options to complete installation.
111
+ [Pictorial Guide](BT.md)
112
+
113
  ### Docker Deployment
114
+
115
  ### Using Docker Compose (Recommended)
116
  ```shell
117
  # Clone project
118
  git clone https://github.com/Calcium-Ion/new-api.git
119
  cd new-api
120
  # Edit docker-compose.yml as needed
121
+ # nano docker-compose.yml
122
+ # vim docker-compose.yml
123
  # Start
124
  docker-compose up -d
125
  ```
126
 
127
+ #### Update Version
128
+ ```shell
129
+ docker-compose pull
130
+ docker-compose up -d
131
+ ```
132
+
133
  ### Direct Docker Image Usage
134
  ```shell
135
  # SQLite deployment:
136
  docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
137
+
138
  # MySQL deployment (add -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"), modify database connection parameters as needed
139
  # Example:
140
  docker run --name new-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
141
  ```
142
 
143
+ #### Update Version
144
+ ```shell
145
+ # Pull the latest image
146
+ docker pull calciumion/new-api:latest
147
+ # Stop and remove the old container
148
+ docker stop new-api
149
+ docker rm new-api
150
+ # Run the new container with the same parameters as before
151
+ docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
152
+ ```
153
+
154
+ Alternatively, you can use Watchtower for automatic updates (not recommended, may cause database incompatibility):
155
+ ```shell
156
+ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
157
+ ```
158
+
159
  ## Channel Retry
160
  Channel retry is implemented, configurable in `Settings->Operation Settings->General Settings`. **Cache recommended**.
161
  First retry uses same priority, second retry uses next priority, and so on.
README.md CHANGED
@@ -1,10 +1,217 @@
1
- ---
2
- title: Epa
3
- emoji: 🐢
4
- colorFrom: pink
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- app_port: 3000
9
- ---
10
- THIS IS EPA.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <p align="right">
2
+ <strong>中文</strong> | <a href="./README.en.md">English</a>
3
+ </p>
4
+ <div align="center">
5
+
6
+ ![new-api](/web/public/logo.png)
7
+
8
+ # New API
9
+
10
+
11
+ 🍥新一代大模型网关与AI资产管理系统
12
+
13
+ <a href="https://trendshift.io/repositories/8227" target="_blank"><img src="https://trendshift.io/api/badge/repositories/8227" alt="Calcium-Ion%2Fnew-api | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
14
+
15
+ <p align="center">
16
+ <a href="https://raw.githubusercontent.com/Calcium-Ion/new-api/main/LICENSE">
17
+ <img src="https://img.shields.io/github/license/Calcium-Ion/new-api?color=brightgreen" alt="license">
18
+ </a>
19
+ <a href="https://github.com/Calcium-Ion/new-api/releases/latest">
20
+ <img src="https://img.shields.io/github/v/release/Calcium-Ion/new-api?color=brightgreen&include_prereleases" alt="release">
21
+ </a>
22
+ <a href="https://github.com/users/Calcium-Ion/packages/container/package/new-api">
23
+ <img src="https://img.shields.io/badge/docker-ghcr.io-blue" alt="docker">
24
+ </a>
25
+ <a href="https://hub.docker.com/r/CalciumIon/new-api">
26
+ <img src="https://img.shields.io/badge/docker-dockerHub-blue" alt="docker">
27
+ </a>
28
+ <a href="https://goreportcard.com/report/github.com/Calcium-Ion/new-api">
29
+ <img src="https://goreportcard.com/badge/github.com/Calcium-Ion/new-api" alt="GoReportCard">
30
+ </a>
31
+ </p>
32
+ </div>
33
+
34
+ ## 📝 项目说明
35
+
36
+ > [!NOTE]
37
+ > 本项目为开源项目,在[One API](https://github.com/songquanpeng/one-api)的基础上进行二次开发
38
+
39
+ > [!IMPORTANT]
40
+ > - 使用者必须在遵循 OpenAI 的[使用条款](https://openai.com/policies/terms-of-use)以及**法律法规**的情况下使用,不得用于非法用途。
41
+ > - 本项目仅供个人学习使用,不保证稳定性,且不提供任何技术支持。
42
+ > - 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。
43
+
44
+ ## ✨ 主要特性
45
+
46
+ 1. 🎨 全新的UI界面(部分界面还待更新)
47
+ 2. 🌍 多语言支持(待完善)
48
+ 3. 🎨 添加[Midjourney-Proxy(Plus)](https://github.com/novicezk/midjourney-proxy)接口支持,[对接文档](Midjourney.md)
49
+ 4. 💰 支持在线充值功能,可在系统设置中设置:
50
+ - [x] 易支付
51
+ 5. 🔍 支持用key查询使用额度:
52
+ - 配合项目[neko-api-key-tool](https://github.com/Calcium-Ion/neko-api-key-tool)可实现用key查询使用
53
+ 6. 📑 分页支持选择每页显示数量
54
+ 7. 🔄 兼容原版One API的数据库,可直接使用原版数据库(one-api.db)
55
+ 8. 💵 支持模型按次数收费,可在 系统设置-运营设置 中设置
56
+ 9. ⚖️ 支持渠道**加权随机**
57
+ 10. 📈 数据看板(控制台)
58
+ 11. 🔒 可设置令牌能调用的模型
59
+ 12. 🤖 支持Telegram授权登录:
60
+ 1. 系统设置-配置登录注册-允许通过Telegram登录
61
+ 2. 对[@Botfather](https://t.me/botfather)输入指令/setdomain
62
+ 3. 选择你的bot,然后输入http(s)://你的网站地址/login
63
+ 4. Telegram Bot 名称是bot username 去掉@后的字符串
64
+ 13. 🎵 添加 [Suno API](https://github.com/Suno-API/Suno-API)接口支持,[对接文档](Suno.md)
65
+ 14. 🔄 支持Rerank模型,目前兼容Cohere和Jina,可接入Dify,[对接文档](Rerank.md)
66
+ 15. ⚡ **[OpenAI Realtime API](https://platform.openai.com/docs/guides/realtime/integration)** - 支持OpenAI的Realtime API,支持Azure渠道
67
+ 16. 支持使用路由/chat2link 进入聊天界面
68
+ 17. 🧠 支持通过模型名称后缀设置 reasoning effort:
69
+ - 添加后缀 `-high` 设置为 high reasoning effort (例如: `o3-mini-high`)
70
+ - 添加后缀 `-medium` 设置为 medium reasoning effort (例如: `o3-mini-medium`)
71
+ - 添加后缀 `-low` 设置为 low reasoning effort (例如: `o3-mini-low`)
72
+
73
+ ## 模型支持
74
+ 此版本额外支持以下模型:
75
+ 1. 第三方模型 **gps** (gpt-4-gizmo-*)
76
+ 2. [Midjourney-Proxy(Plus)](https://github.com/novicezk/midjourney-proxy)接口,[对接文档](Midjourney.md)
77
+ 3. 自定义渠道,支持填入完整调用地址
78
+ 4. [Suno API](https://github.com/Suno-API/Suno-API) 接口,[对接文档](Suno.md)
79
+ 5. Rerank模型,目前支持[Cohere](https://cohere.ai/)和[Jina](https://jina.ai/),[对接文档](Rerank.md)
80
+ 6. Dify
81
+
82
+ 您可以在渠道中添加自定义模型gpt-4-gizmo-*,此模型并非OpenAI官方模型,而是第三方模型,使用官方key无法调用。
83
+
84
+ ## 比原版One API多出的配置
85
+ - `GENERATE_DEFAULT_TOKEN`:是否为新注册用户生成初始令牌,默认为 `false`。
86
+ - `STREAMING_TIMEOUT`:设置流式一次回复的超时时间,默认为 60 秒。
87
+ - `DIFY_DEBUG`:设置 Dify 渠道是否输出工作流和节点信息到客户端,默认为 `true`。
88
+ - `FORCE_STREAM_OPTION`:是否覆盖客户端stream_options参数,请求上游返回流模式usage,默认为 `true`,建议开启,不影响客户端传入stream_options参数返回结果。
89
+ - `GET_MEDIA_TOKEN`:是否统计图片token,默认为 `true`,关闭后将不再在本地计算图片token,可能会导致和上游计费不同,此项覆盖 `GET_MEDIA_TOKEN_NOT_STREAM` 选项作用。
90
+ - `GET_MEDIA_TOKEN_NOT_STREAM`:是否在非流(`stream=false`)情况下统计图片token,默认为 `true`。
91
+ - `UPDATE_TASK`:是否更新异步任务(Midjourney、Suno),默认为 `true`,关闭后将不会更新任务进度。
92
+ - `GEMINI_MODEL_MAP`:Gemini模型指定版本(v1/v1beta),使用"模型:版本"指定,","分隔,例如:-e GEMINI_MODEL_MAP="gemini-1.5-pro-latest:v1beta,gemini-1.5-pro-001:v1beta",为空则使用默认配置(v1beta)
93
+ - `COHERE_SAFETY_SETTING`:Cohere模型[安全设置](https://docs.cohere.com/docs/safety-modes#overview),可选值为 `NONE`, `CONTEXTUAL`, `STRICT`,默认为 `NONE`。
94
+ - `GEMINI_VISION_MAX_IMAGE_NUM`:Gemini模型最大图片数量,默认为 `16`,设置为 `-1` 则不限制。
95
+ - `MAX_FILE_DOWNLOAD_MB`: 最大文件下载大小,单位 MB,默认为 `20`。
96
+ - `CRYPTO_SECRET`:加密密钥,用于加密数据库内容。
97
+ - `AZURE_DEFAULT_API_VERSION`:Azure渠道默认API版本,如果渠道设置中未指定API版本,则使用此版本,默认为 `2024-12-01-preview`
98
+ ## 部署
99
+
100
+ > [!TIP]
101
+ > 最新版Docker镜像:`calciumion/new-api:latest`
102
+ > 默认账号root 密码123456
103
+
104
+ ### 多机部署
105
+ - 必须设置环境变量 `SESSION_SECRET`,否则会导致多机部署时登录状态不一致。
106
+ - 如果公用Redis,必须设置 `CRYPTO_SECRET`,否则会导致多机部署时Redis内容无法获取。
107
+
108
+ ### 部署要求
109
+ - 本地数据库(默认):SQLite(Docker 部署默认使用 SQLite,必须挂载 `/data` 目录到宿主机)
110
+ - 远程数据库:MySQL 版本 >= 5.7.8,PgSQL 版本 >= 9.6
111
+
112
+ ### 使用宝塔面板Docker功能部署
113
+ 安装宝塔面板 (**9.2.0版本**及以上),前往 [宝塔面板](https://www.bt.cn/new/download.html) 官网,选择正式版的脚本下载安装
114
+ 安装后登录宝塔面板,在菜单栏中点击 Docker ,首次进入会提示安装 Docker 服务,点击立即安装,按提示完成安装
115
+ 安装完成后在应用商店中找到 **New-API** ,点击安装,配置基本选项 即可完成安装
116
+ [图文教程](BT.md)
117
+
118
+ ### 基于 Docker 进行部署
119
+
120
+ > [!TIP]
121
+ > 默认管理员账号root 密码123456
122
+
123
+ ### 使用 Docker Compose 部署(推荐)
124
+ ```shell
125
+ # 下载项目
126
+ git clone https://github.com/Calcium-Ion/new-api.git
127
+ cd new-api
128
+ # 按需编辑 docker-compose.yml
129
+ # nano docker-compose.yml
130
+ # vim docker-compose.yml
131
+ # 启动
132
+ docker-compose up -d
133
+ ```
134
+
135
+ #### 更新版本
136
+ ```shell
137
+ docker-compose pull
138
+ docker-compose up -d
139
+ ```
140
+
141
+ ### 直接使用 Docker 镜像
142
+ ```shell
143
+ # 使用 SQLite 的部署命令:
144
+ docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
145
+
146
+ # 使用 MySQL 的部署命令,在上面的基础上添加 `-e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"`,请自行修改数据库连接参数。
147
+ # 例如:
148
+ docker run --name new-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
149
+ ```
150
+
151
+ #### 更新版本
152
+ ```shell
153
+ # 拉取最新镜像
154
+ docker pull calciumion/new-api:latest
155
+ # 停止并删除旧容器
156
+ docker stop new-api
157
+ docker rm new-api
158
+ # 使用相同参数运行新容器
159
+ docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest
160
+ ```
161
+
162
+ 或者使用 Watchtower 自动更新(不推荐,可能会导致数据库不兼容):
163
+ ```shell
164
+ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
165
+ ```
166
+
167
+ ## 渠道重试
168
+ 渠道重试功能已经实现,可以在`设置->运营设置->通用设置`设置重试次数,**建议开启缓存**功能。
169
+ 如果开启了重试功能,第一次重试使用同优先级,第二次重试使用下一个优先级,以此类推。
170
+ ### 缓存设置方法
171
+ 1. `REDIS_CONN_STRING`:设置之后将使用 Redis 作为缓存使用。
172
+ + 例子:`REDIS_CONN_STRING=redis://default:redispw@localhost:49153`
173
+ 2. `MEMORY_CACHE_ENABLED`:启用内存缓存(如果设置了`REDIS_CONN_STRING`,则无需手动设置),会导致用户额度的更新存在一定的延迟,可选值为 `true` 和 `false`,未设置则默认为 `false`。
174
+ + 例子:`MEMORY_CACHE_ENABLED=true`
175
+ ### 为什么有的时候没有重试
176
+ 这些错误码不会重试:400,504,524
177
+ ### 我想让400也重试
178
+ 在`渠道->编辑`中,将`状态码复写`改为
179
+ ```json
180
+ {
181
+ "400": "500"
182
+ }
183
+ ```
184
+ 可以实现400错误转为500错误,从而重试
185
+
186
+ ## Midjourney接口设置文档
187
+ [对接文档](Midjourney.md)
188
+
189
+ ## Suno接口设置文档
190
+ [对接文档](Suno.md)
191
+
192
+ ## 界面截图
193
+ ![image](https://github.com/user-attachments/assets/a0dcd349-5df8-4dc8-9acf-ca272b239919)
194
+
195
+
196
+ ![image](https://github.com/user-attachments/assets/c7d0f7e1-729c-43e2-ac7c-2cb73b0afc8e)
197
+
198
+ ![image](https://github.com/user-attachments/assets/29f81de5-33fc-4fc5-a5ff-f9b54b653c7c)
199
+
200
+ ![image](https://github.com/user-attachments/assets/4fa53e18-d2c5-477a-9b26-b86e44c71e35)
201
+
202
+ ## 交流群
203
+ <img src="https://github.com/user-attachments/assets/9ca0bc82-e057-4230-a28d-9f198fa022e3" width="200">
204
+
205
+ ## 相关项目
206
+ - [One API](https://github.com/songquanpeng/one-api):原版项目
207
+ - [Midjourney-Proxy](https://github.com/novicezk/midjourney-proxy):Midjourney接口支持
208
+ - [chatnio](https://github.com/Deeptrain-Community/chatnio):下一代 AI 一站式 B/C 端解决方案
209
+ - [neko-api-key-tool](https://github.com/Calcium-Ion/neko-api-key-tool):用key查询使用额度
210
+
211
+ 其他基于New API的项目:
212
+ - [new-api-horizon](https://github.com/Calcium-Ion/new-api-horizon):New API高性能优化版,并支持Claude格式
213
+ - [VoAPI](https://github.com/VoAPI/VoAPI):基于New API的闭源项目
214
+
215
+ ## 🌟 Star History
216
+
217
+ [![Star History Chart](https://api.star-history.com/svg?repos=Calcium-Ion/new-api&type=Date)](https://star-history.com/#Calcium-Ion/new-api&Date)
VERSION CHANGED
@@ -1 +1 @@
1
- v0.4.6.11
 
1
+ v0.4.7.2.1
common/constants.go CHANGED
@@ -231,8 +231,10 @@ const (
231
  ChannelTypeVertexAi = 41
232
  ChannelTypeMistral = 42
233
  ChannelTypeDeepSeek = 43
234
-
235
- ChannelTypeDummy // this one is only for count, do not add any channel after this
 
 
236
 
237
  )
238
 
@@ -281,4 +283,7 @@ var ChannelBaseURLs = []string{
281
  "", //41
282
  "https://api.mistral.ai", //42
283
  "https://api.deepseek.com", //43
 
 
 
284
  }
 
231
  ChannelTypeVertexAi = 41
232
  ChannelTypeMistral = 42
233
  ChannelTypeDeepSeek = 43
234
+ ChannelTypeMokaAI = 44
235
+ ChannelTypeVolcEngine = 45
236
+ ChannelTypeBaiduV2 = 46
237
+ ChannelTypeDummy // this one is only for count, do not add any channel after this
238
 
239
  )
240
 
 
283
  "", //41
284
  "https://api.mistral.ai", //42
285
  "https://api.deepseek.com", //43
286
+ "https://api.moka.ai", //44
287
+ "https://ark.cn-beijing.volces.com", //45
288
+ "https://qianfan.baidubce.com", //46
289
  }
common/database.go CHANGED
@@ -3,5 +3,6 @@ package common
3
  var UsingSQLite = false
4
  var UsingPostgreSQL = false
5
  var UsingMySQL = false
 
6
 
7
  var SQLitePath = "one-api.db?_busy_timeout=5000"
 
3
  var UsingSQLite = false
4
  var UsingPostgreSQL = false
5
  var UsingMySQL = false
6
+ var UsingClickHouse = false
7
 
8
  var SQLitePath = "one-api.db?_busy_timeout=5000"
controller/channel-test.go CHANGED
@@ -41,9 +41,21 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
41
  }
42
  w := httptest.NewRecorder()
43
  c, _ := gin.CreateTestContext(w)
 
 
 
 
 
 
 
 
 
 
 
 
44
  c.Request = &http.Request{
45
  Method: "POST",
46
- URL: &url.URL{Path: "/v1/chat/completions"},
47
  Body: nil,
48
  Header: make(http.Header),
49
  }
@@ -55,7 +67,7 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
55
  if len(channel.GetModels()) > 0 {
56
  testModel = channel.GetModels()[0]
57
  } else {
58
- testModel = "gpt-3.5-turbo"
59
  }
60
  }
61
  }
@@ -88,7 +100,7 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
88
 
89
  request := buildTestRequest(testModel)
90
  meta.UpstreamModelName = testModel
91
- common.SysLog(fmt.Sprintf("testing channel %d with model %s", channel.Id, testModel))
92
 
93
  adaptor.Init(meta)
94
 
@@ -156,12 +168,21 @@ func buildTestRequest(model string) *dto.GeneralOpenAIRequest {
156
  Model: "", // this will be set later
157
  Stream: false,
158
  }
 
 
 
 
 
 
 
 
 
 
 
159
  if strings.HasPrefix(model, "o1") || strings.HasPrefix(model, "o3") {
160
  testRequest.MaxCompletionTokens = 10
161
- } else if strings.HasPrefix(model, "gemini-2.0-flash-thinking") {
162
- testRequest.MaxTokens = 10
163
  } else {
164
- testRequest.MaxTokens = 1
165
  }
166
  content, _ := json.Marshal("hi")
167
  testMessage := dto.Message{
 
41
  }
42
  w := httptest.NewRecorder()
43
  c, _ := gin.CreateTestContext(w)
44
+
45
+ requestPath := "/v1/chat/completions"
46
+
47
+ // 先判断是否为 Embedding 模型
48
+ if strings.Contains(strings.ToLower(testModel), "embedding") ||
49
+ strings.HasPrefix(testModel, "m3e") || // m3e 系列模型
50
+ strings.Contains(testModel, "bge-") || // bge 系列模型
51
+ testModel == "text-embedding-v1" ||
52
+ channel.Type == common.ChannelTypeMokaAI { // 其他 embedding 模型
53
+ requestPath = "/v1/embeddings" // 修改请求路径
54
+ }
55
+
56
  c.Request = &http.Request{
57
  Method: "POST",
58
+ URL: &url.URL{Path: requestPath}, // 使用动态路径
59
  Body: nil,
60
  Header: make(http.Header),
61
  }
 
67
  if len(channel.GetModels()) > 0 {
68
  testModel = channel.GetModels()[0]
69
  } else {
70
+ testModel = "gpt-4o-mini"
71
  }
72
  }
73
  }
 
100
 
101
  request := buildTestRequest(testModel)
102
  meta.UpstreamModelName = testModel
103
+ common.SysLog(fmt.Sprintf("testing channel %d with model %s , meta %v ", channel.Id, testModel, meta))
104
 
105
  adaptor.Init(meta)
106
 
 
168
  Model: "", // this will be set later
169
  Stream: false,
170
  }
171
+
172
+ // 先判断是否为 Embedding 模型
173
+ if strings.Contains(strings.ToLower(model), "embedding") ||
174
+ strings.HasPrefix(model, "m3e") || // m3e 系列模型
175
+ strings.Contains(model, "bge-") || // bge 系列模型
176
+ model == "text-embedding-v1" { // 其他 embedding 模型
177
+ // Embedding 请求
178
+ testRequest.Input = []string{"hello world"}
179
+ return testRequest
180
+ }
181
+ // 并非Embedding 模型
182
  if strings.HasPrefix(model, "o1") || strings.HasPrefix(model, "o3") {
183
  testRequest.MaxCompletionTokens = 10
 
 
184
  } else {
185
+ testRequest.MaxTokens = 10
186
  }
187
  content, _ := json.Marshal("hi")
188
  testMessage := dto.Message{
controller/relay.go CHANGED
@@ -33,6 +33,8 @@ func relayHandler(c *gin.Context, relayMode int) *dto.OpenAIErrorWithStatusCode
33
  err = relay.AudioHelper(c)
34
  case relayconstant.RelayModeRerank:
35
  err = relay.RerankHelper(c, relayMode)
 
 
36
  default:
37
  err = relay.TextHelper(c)
38
  }
 
33
  err = relay.AudioHelper(c)
34
  case relayconstant.RelayModeRerank:
35
  err = relay.RerankHelper(c, relayMode)
36
+ case relayconstant.RelayModeEmbeddings:
37
+ err = relay.EmbeddingHelper(c)
38
  default:
39
  err = relay.TextHelper(c)
40
  }
dto/embedding.go ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package dto
2
+
3
+ type EmbeddingOptions struct {
4
+ Seed int `json:"seed,omitempty"`
5
+ Temperature *float64 `json:"temperature,omitempty"`
6
+ TopK int `json:"top_k,omitempty"`
7
+ TopP *float64 `json:"top_p,omitempty"`
8
+ FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"`
9
+ PresencePenalty *float64 `json:"presence_penalty,omitempty"`
10
+ NumPredict int `json:"num_predict,omitempty"`
11
+ NumCtx int `json:"num_ctx,omitempty"`
12
+ }
13
+
14
+ type EmbeddingRequest struct {
15
+ Model string `json:"model"`
16
+ Input any `json:"input"`
17
+ EncodingFormat string `json:"encoding_format,omitempty"`
18
+ Dimensions int `json:"dimensions,omitempty"`
19
+ User string `json:"user,omitempty"`
20
+ Seed float64 `json:"seed,omitempty"`
21
+ Temperature *float64 `json:"temperature,omitempty"`
22
+ TopP float64 `json:"top_p,omitempty"`
23
+ FrequencyPenalty float64 `json:"frequency_penalty,omitempty"`
24
+ PresencePenalty float64 `json:"presence_penalty,omitempty"`
25
+ }
26
+
27
+ func (r EmbeddingRequest) ParseInput() []string {
28
+ if r.Input == nil {
29
+ return nil
30
+ }
31
+ var input []string
32
+ switch r.Input.(type) {
33
+ case string:
34
+ input = []string{r.Input.(string)}
35
+ case []any:
36
+ input = make([]string, 0, len(r.Input.([]any)))
37
+ for _, item := range r.Input.([]any) {
38
+ if str, ok := item.(string); ok {
39
+ input = append(input, str)
40
+ }
41
+ }
42
+ }
43
+ return input
44
+ }
45
+
46
+ type EmbeddingResponseItem struct {
47
+ Object string `json:"object"`
48
+ Index int `json:"index"`
49
+ Embedding []float64 `json:"embedding"`
50
+ }
51
+
52
+ type EmbeddingResponse struct {
53
+ Object string `json:"object"`
54
+ Data []EmbeddingResponseItem `json:"data"`
55
+ Model string `json:"model"`
56
+ Usage `json:"usage"`
57
+ }
dto/openai_request.go CHANGED
@@ -86,11 +86,13 @@ func (r GeneralOpenAIRequest) ParseInput() []string {
86
  }
87
 
88
  type Message struct {
89
- Role string `json:"role"`
90
- Content json.RawMessage `json:"content"`
91
- Name *string `json:"name,omitempty"`
92
- ToolCalls json.RawMessage `json:"tool_calls,omitempty"`
93
- ToolCallId string `json:"tool_call_id,omitempty"`
 
 
94
  }
95
 
96
  type MediaContent struct {
@@ -116,6 +118,17 @@ const (
116
  ContentTypeInputAudio = "input_audio"
117
  )
118
 
 
 
 
 
 
 
 
 
 
 
 
119
  func (m *Message) ParseToolCalls() []ToolCall {
120
  if m.ToolCalls == nil {
121
  return nil
 
86
  }
87
 
88
  type Message struct {
89
+ Role string `json:"role"`
90
+ Content json.RawMessage `json:"content"`
91
+ Name *string `json:"name,omitempty"`
92
+ Prefix *bool `json:"prefix,omitempty"`
93
+ ReasoningContent string `json:"reasoning_content,omitempty"`
94
+ ToolCalls json.RawMessage `json:"tool_calls,omitempty"`
95
+ ToolCallId string `json:"tool_call_id,omitempty"`
96
  }
97
 
98
  type MediaContent struct {
 
118
  ContentTypeInputAudio = "input_audio"
119
  )
120
 
121
+ func (m *Message) GetPrefix() bool {
122
+ if m.Prefix == nil {
123
+ return false
124
+ }
125
+ return *m.Prefix
126
+ }
127
+
128
+ func (m *Message) SetPrefix(prefix bool) {
129
+ m.Prefix = &prefix
130
+ }
131
+
132
  func (m *Message) ParseToolCalls() []ToolCall {
133
  if m.ToolCalls == nil {
134
  return nil
dto/openai_response.go CHANGED
@@ -81,7 +81,7 @@ func (c *ChatCompletionsStreamResponseChoiceDelta) GetContentString() string {
81
  type ToolCall struct {
82
  // Index is not nil only in chat completion chunk object
83
  Index *int `json:"index,omitempty"`
84
- ID string `json:"id"`
85
  Type any `json:"type"`
86
  Function FunctionCall `json:"function"`
87
  }
 
81
  type ToolCall struct {
82
  // Index is not nil only in chat completion chunk object
83
  Index *int `json:"index,omitempty"`
84
+ ID string `json:"id,omitempty"`
85
  Type any `json:"type"`
86
  Function FunctionCall `json:"function"`
87
  }
go.mod CHANGED
@@ -16,6 +16,7 @@ require (
16
  github.com/gin-contrib/sessions v0.0.5
17
  github.com/gin-contrib/static v0.0.1
18
  github.com/gin-gonic/gin v1.9.1
 
19
  github.com/go-playground/validator/v10 v10.20.0
20
  github.com/go-redis/redis/v8 v8.11.5
21
  github.com/golang-jwt/jwt v3.2.2+incompatible
@@ -32,8 +33,7 @@ require (
32
  golang.org/x/net v0.28.0
33
  gorm.io/driver/mysql v1.4.3
34
  gorm.io/driver/postgres v1.5.2
35
- gorm.io/driver/sqlite v1.4.3
36
- gorm.io/gorm v1.25.0
37
  )
38
 
39
  require (
@@ -49,12 +49,14 @@ require (
49
  github.com/cloudwego/iasm v0.2.0 // indirect
50
  github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
51
  github.com/dlclark/regexp2 v1.11.0 // indirect
 
52
  github.com/gabriel-vasile/mimetype v1.4.3 // indirect
53
  github.com/gin-contrib/sse v0.1.0 // indirect
 
54
  github.com/go-ole/go-ole v1.2.6 // indirect
55
  github.com/go-playground/locales v0.14.1 // indirect
56
  github.com/go-playground/universal-translator v0.18.1 // indirect
57
- github.com/go-sql-driver/mysql v1.6.0 // indirect
58
  github.com/goccy/go-json v0.10.2 // indirect
59
  github.com/google/go-cmp v0.6.0 // indirect
60
  github.com/gorilla/context v1.1.1 // indirect
@@ -70,11 +72,11 @@ require (
70
  github.com/klauspost/cpuid/v2 v2.2.9 // indirect
71
  github.com/leodido/go-urn v1.4.0 // indirect
72
  github.com/mattn/go-isatty v0.0.20 // indirect
73
- github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
74
  github.com/mitchellh/mapstructure v1.5.0 // indirect
75
  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
76
  github.com/modern-go/reflect2 v1.0.2 // indirect
77
  github.com/pelletier/go-toml/v2 v2.2.1 // indirect
 
78
  github.com/tklauser/go-sysconf v0.3.12 // indirect
79
  github.com/tklauser/numcpus v0.6.1 // indirect
80
  github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@@ -87,4 +89,8 @@ require (
87
  golang.org/x/text v0.21.0 // indirect
88
  google.golang.org/protobuf v1.34.2 // indirect
89
  gopkg.in/yaml.v3 v3.0.1 // indirect
 
 
 
 
90
  )
 
16
  github.com/gin-contrib/sessions v0.0.5
17
  github.com/gin-contrib/static v0.0.1
18
  github.com/gin-gonic/gin v1.9.1
19
+ github.com/glebarez/sqlite v1.9.0
20
  github.com/go-playground/validator/v10 v10.20.0
21
  github.com/go-redis/redis/v8 v8.11.5
22
  github.com/golang-jwt/jwt v3.2.2+incompatible
 
33
  golang.org/x/net v0.28.0
34
  gorm.io/driver/mysql v1.4.3
35
  gorm.io/driver/postgres v1.5.2
36
+ gorm.io/gorm v1.25.2
 
37
  )
38
 
39
  require (
 
49
  github.com/cloudwego/iasm v0.2.0 // indirect
50
  github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
51
  github.com/dlclark/regexp2 v1.11.0 // indirect
52
+ github.com/dustin/go-humanize v1.0.1 // indirect
53
  github.com/gabriel-vasile/mimetype v1.4.3 // indirect
54
  github.com/gin-contrib/sse v0.1.0 // indirect
55
+ github.com/glebarez/go-sqlite v1.21.2 // indirect
56
  github.com/go-ole/go-ole v1.2.6 // indirect
57
  github.com/go-playground/locales v0.14.1 // indirect
58
  github.com/go-playground/universal-translator v0.18.1 // indirect
59
+ github.com/go-sql-driver/mysql v1.7.0 // indirect
60
  github.com/goccy/go-json v0.10.2 // indirect
61
  github.com/google/go-cmp v0.6.0 // indirect
62
  github.com/gorilla/context v1.1.1 // indirect
 
72
  github.com/klauspost/cpuid/v2 v2.2.9 // indirect
73
  github.com/leodido/go-urn v1.4.0 // indirect
74
  github.com/mattn/go-isatty v0.0.20 // indirect
 
75
  github.com/mitchellh/mapstructure v1.5.0 // indirect
76
  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
77
  github.com/modern-go/reflect2 v1.0.2 // indirect
78
  github.com/pelletier/go-toml/v2 v2.2.1 // indirect
79
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
80
  github.com/tklauser/go-sysconf v0.3.12 // indirect
81
  github.com/tklauser/numcpus v0.6.1 // indirect
82
  github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 
89
  golang.org/x/text v0.21.0 // indirect
90
  google.golang.org/protobuf v1.34.2 // indirect
91
  gopkg.in/yaml.v3 v3.0.1 // indirect
92
+ modernc.org/libc v1.22.5 // indirect
93
+ modernc.org/mathutil v1.5.0 // indirect
94
+ modernc.org/memory v1.5.0 // indirect
95
+ modernc.org/sqlite v1.23.1 // indirect
96
  )
go.sum CHANGED
@@ -40,6 +40,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
40
  github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
41
  github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
42
  github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 
 
43
  github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
44
  github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
45
  github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
@@ -58,6 +60,10 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv
58
  github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
59
  github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
60
  github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
 
 
 
 
61
  github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
62
  github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
63
  github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@@ -77,8 +83,9 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx
77
  github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
78
  github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
79
  github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
80
- github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
81
  github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 
 
82
  github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
83
  github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
84
  github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
@@ -90,6 +97,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
90
  github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
91
  github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
92
  github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 
 
93
  github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
94
  github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
95
  github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
@@ -140,9 +149,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
140
  github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
141
  github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
142
  github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
143
- github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
144
- github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
145
- github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
146
  github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
147
  github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
148
  github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -167,6 +173,9 @@ github.com/pkoukk/tiktoken-go v0.1.7 h1:qOBHXX4PHtvIvmOtyg1EeKlwFRiMKAcoMp4Q+bLQ
167
  github.com/pkoukk/tiktoken-go v0.1.7/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg=
168
  github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
169
  github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 
 
 
170
  github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
171
  github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
172
  github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
@@ -263,11 +272,16 @@ gorm.io/driver/mysql v1.4.3 h1:/JhWJhO2v17d8hjApTltKNADm7K7YI2ogkR7avJUL3k=
263
  gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
264
  gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
265
  gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
266
- gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
267
- gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
268
  gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
269
- gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
270
- gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
271
- gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
 
 
 
 
 
 
 
272
  nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
273
  rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 
40
  github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
41
  github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
42
  github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
43
+ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
44
+ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
45
  github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
46
  github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
47
  github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
 
60
  github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
61
  github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
62
  github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
63
+ github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
64
+ github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
65
+ github.com/glebarez/sqlite v1.9.0 h1:Aj6bPA12ZEx5GbSF6XADmCkYXlljPNUY+Zf1EQxynXs=
66
+ github.com/glebarez/sqlite v1.9.0/go.mod h1:YBYCoyupOao60lzp1MVBLEjZfgkq0tdB1voAQ09K9zw=
67
  github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
68
  github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
69
  github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 
83
  github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
84
  github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
85
  github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
 
86
  github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
87
+ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
88
+ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
89
  github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
90
  github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
91
  github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 
97
  github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
98
  github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
99
  github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
100
+ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
101
+ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
102
  github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
103
  github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
104
  github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 
149
  github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
150
  github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
151
  github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 
 
 
152
  github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
153
  github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
154
  github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 
173
  github.com/pkoukk/tiktoken-go v0.1.7/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg=
174
  github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
175
  github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
176
+ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
177
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
178
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
179
  github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
180
  github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
181
  github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 
272
  gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
273
  gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
274
  gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
 
 
275
  gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
276
+ gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
277
+ gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
278
+ modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
279
+ modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
280
+ modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
281
+ modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
282
+ modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
283
+ modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
284
+ modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
285
+ modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
286
  nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
287
  rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
main.go CHANGED
@@ -145,6 +145,13 @@ func main() {
145
  middleware.SetUpLogger(server)
146
  // Initialize session store
147
  store := cookie.NewStore([]byte(common.SessionSecret))
 
 
 
 
 
 
 
148
  server.Use(sessions.Sessions("session", store))
149
 
150
  router.SetRouter(server, buildFS, indexPage)
 
145
  middleware.SetUpLogger(server)
146
  // Initialize session store
147
  store := cookie.NewStore([]byte(common.SessionSecret))
148
+ store.Options(sessions.Options{
149
+ Path: "/",
150
+ MaxAge: 2592000, // 30 days
151
+ HttpOnly: true,
152
+ Secure: false,
153
+ SameSite: http.SameSiteStrictMode,
154
+ })
155
  server.Use(sessions.Sessions("session", store))
156
 
157
  router.SetRouter(server, buildFS, indexPage)
middleware/distributor.go CHANGED
@@ -239,5 +239,7 @@ func SetupContextForSelectedChannel(c *gin.Context, channel *model.Channel, mode
239
  c.Set("plugin", channel.Other)
240
  case common.ChannelCloudflare:
241
  c.Set("api_version", channel.Other)
 
 
242
  }
243
  }
 
239
  c.Set("plugin", channel.Other)
240
  case common.ChannelCloudflare:
241
  c.Set("api_version", channel.Other)
242
+ case common.ChannelTypeMokaAI:
243
+ c.Set("api_version", channel.Other)
244
  }
245
  }
model/cache.go CHANGED
@@ -11,106 +11,6 @@ import (
11
  "time"
12
  )
13
 
14
- //func CacheGetUserGroup(id int) (group string, err error) {
15
- // if !common.RedisEnabled {
16
- // return GetUserGroup(id)
17
- // }
18
- // group, err = common.RedisGet(fmt.Sprintf("user_group:%d", id))
19
- // if err != nil {
20
- // group, err = GetUserGroup(id)
21
- // if err != nil {
22
- // return "", err
23
- // }
24
- // err = common.RedisSet(fmt.Sprintf("user_group:%d", id), group, time.Duration(constant.UserId2GroupCacheSeconds)*time.Second)
25
- // if err != nil {
26
- // common.SysError("Redis set user group error: " + err.Error())
27
- // }
28
- // }
29
- // return group, err
30
- //}
31
- //
32
- //func CacheGetUsername(id int) (username string, err error) {
33
- // if !common.RedisEnabled {
34
- // return GetUsernameById(id)
35
- // }
36
- // username, err = common.RedisGet(fmt.Sprintf("user_name:%d", id))
37
- // if err != nil {
38
- // username, err = GetUsernameById(id)
39
- // if err != nil {
40
- // return "", err
41
- // }
42
- // err = common.RedisSet(fmt.Sprintf("user_name:%d", id), username, time.Duration(constant.UserId2GroupCacheSeconds)*time.Second)
43
- // if err != nil {
44
- // common.SysError("Redis set user group error: " + err.Error())
45
- // }
46
- // }
47
- // return username, err
48
- //}
49
- //
50
- //func CacheGetUserQuota(id int) (quota int, err error) {
51
- // if !common.RedisEnabled {
52
- // return GetUserQuota(id)
53
- // }
54
- // quotaString, err := common.RedisGet(fmt.Sprintf("user_quota:%d", id))
55
- // if err != nil {
56
- // quota, err = GetUserQuota(id)
57
- // if err != nil {
58
- // return 0, err
59
- // }
60
- // return quota, nil
61
- // }
62
- // quota, err = strconv.Atoi(quotaString)
63
- // return quota, nil
64
- //}
65
- //
66
- //func CacheUpdateUserQuota(id int) error {
67
- // if !common.RedisEnabled {
68
- // return nil
69
- // }
70
- // quota, err := GetUserQuota(id)
71
- // if err != nil {
72
- // return err
73
- // }
74
- // return cacheSetUserQuota(id, quota)
75
- //}
76
- //
77
- //func cacheSetUserQuota(id int, quota int) error {
78
- // err := common.RedisSet(fmt.Sprintf("user_quota:%d", id), fmt.Sprintf("%d", quota), time.Duration(constant.UserId2QuotaCacheSeconds)*time.Second)
79
- // return err
80
- //}
81
- //
82
- //func CacheDecreaseUserQuota(id int, quota int) error {
83
- // if !common.RedisEnabled {
84
- // return nil
85
- // }
86
- // err := common.RedisDecrease(fmt.Sprintf("user_quota:%d", id), int64(quota))
87
- // return err
88
- //}
89
- //
90
- //func CacheIsUserEnabled(userId int) (bool, error) {
91
- // if !common.RedisEnabled {
92
- // return IsUserEnabled(userId)
93
- // }
94
- // enabled, err := common.RedisGet(fmt.Sprintf("user_enabled:%d", userId))
95
- // if err == nil {
96
- // return enabled == "1", nil
97
- // }
98
- //
99
- // userEnabled, err := IsUserEnabled(userId)
100
- // if err != nil {
101
- // return false, err
102
- // }
103
- // enabled = "0"
104
- // if userEnabled {
105
- // enabled = "1"
106
- // }
107
- // err = common.RedisSet(fmt.Sprintf("user_enabled:%d", userId), enabled, time.Duration(constant.UserId2StatusCacheSeconds)*time.Second)
108
- // if err != nil {
109
- // common.SysError("Redis set user enabled error: " + err.Error())
110
- // }
111
- // return userEnabled, err
112
- //}
113
-
114
  var group2model2channels map[string]map[string][]*Channel
115
  var channelsIDM map[int]*Channel
116
  var channelSyncLock sync.RWMutex
 
11
  "time"
12
  )
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  var group2model2channels map[string]map[string][]*Channel
15
  var channelsIDM map[int]*Channel
16
  var channelSyncLock sync.RWMutex
model/log.go CHANGED
@@ -133,9 +133,6 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName
133
  tx = LOG_DB.Where("logs.type = ?", logType)
134
  }
135
 
136
- tx = tx.Joins("LEFT JOIN channels ON logs.channel_id = channels.id")
137
- tx = tx.Select("logs.*, channels.name as channel_name")
138
-
139
  if modelName != "" {
140
  tx = tx.Where("logs.model_name like ?", modelName)
141
  }
@@ -165,6 +162,30 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName
165
  if err != nil {
166
  return nil, 0, err
167
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  return logs, total, err
169
  }
170
 
@@ -176,9 +197,6 @@ func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int
176
  tx = LOG_DB.Where("logs.user_id = ? and logs.type = ?", userId, logType)
177
  }
178
 
179
- tx = tx.Joins("LEFT JOIN channels ON logs.channel_id = channels.id")
180
- tx = tx.Select("logs.*, channels.name as channel_name")
181
-
182
  if modelName != "" {
183
  tx = tx.Where("logs.model_name like ?", modelName)
184
  }
@@ -199,6 +217,10 @@ func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int
199
  return nil, 0, err
200
  }
201
  err = tx.Order("logs.id desc").Limit(num).Offset(startIdx).Find(&logs).Error
 
 
 
 
202
  formatUserLogs(logs)
203
  return logs, total, err
204
  }
 
133
  tx = LOG_DB.Where("logs.type = ?", logType)
134
  }
135
 
 
 
 
136
  if modelName != "" {
137
  tx = tx.Where("logs.model_name like ?", modelName)
138
  }
 
162
  if err != nil {
163
  return nil, 0, err
164
  }
165
+
166
+ channelIds := make([]int, 0)
167
+ channelMap := make(map[int]string)
168
+ for _, log := range logs {
169
+ if log.ChannelId != 0 {
170
+ channelIds = append(channelIds, log.ChannelId)
171
+ }
172
+ }
173
+ if len(channelIds) > 0 {
174
+ var channels []struct {
175
+ Id int `gorm:"column:id"`
176
+ Name string `gorm:"column:name"`
177
+ }
178
+ if err = DB.Table("channels").Select("id, name").Where("id IN ?", channelIds).Find(&channels).Error; err != nil {
179
+ return logs, total, err
180
+ }
181
+ for _, channel := range channels {
182
+ channelMap[channel.Id] = channel.Name
183
+ }
184
+ for i := range logs {
185
+ logs[i].ChannelName = channelMap[logs[i].ChannelId]
186
+ }
187
+ }
188
+
189
  return logs, total, err
190
  }
191
 
 
197
  tx = LOG_DB.Where("logs.user_id = ? and logs.type = ?", userId, logType)
198
  }
199
 
 
 
 
200
  if modelName != "" {
201
  tx = tx.Where("logs.model_name like ?", modelName)
202
  }
 
217
  return nil, 0, err
218
  }
219
  err = tx.Order("logs.id desc").Limit(num).Offset(startIdx).Find(&logs).Error
220
+ if err != nil {
221
+ return nil, 0, err
222
+ }
223
+
224
  formatUserLogs(logs)
225
  return logs, total, err
226
  }
model/main.go CHANGED
@@ -1,9 +1,9 @@
1
  package model
2
 
3
  import (
 
4
  "gorm.io/driver/mysql"
5
  "gorm.io/driver/postgres"
6
- "gorm.io/driver/sqlite"
7
  "gorm.io/gorm"
8
  "log"
9
  "one-api/common"
 
1
  package model
2
 
3
  import (
4
+ "github.com/glebarez/sqlite"
5
  "gorm.io/driver/mysql"
6
  "gorm.io/driver/postgres"
 
7
  "gorm.io/gorm"
8
  "log"
9
  "one-api/common"
model/option.go CHANGED
@@ -110,6 +110,7 @@ func InitOptionMap() {
110
  common.OptionMap["StopOnSensitiveEnabled"] = strconv.FormatBool(setting.StopOnSensitiveEnabled)
111
  common.OptionMap["SensitiveWords"] = setting.SensitiveWordsToString()
112
  common.OptionMap["StreamCacheQueueLength"] = strconv.Itoa(setting.StreamCacheQueueLength)
 
113
 
114
  common.OptionMapRWMutex.Unlock()
115
  loadOptionsFromDatabase()
@@ -335,6 +336,8 @@ func updateOptionMap(key string, value string) (err error) {
335
  common.QuotaPerUnit, _ = strconv.ParseFloat(value, 64)
336
  case "SensitiveWords":
337
  setting.SensitiveWordsFromString(value)
 
 
338
  case "StreamCacheQueueLength":
339
  setting.StreamCacheQueueLength, _ = strconv.Atoi(value)
340
  }
 
110
  common.OptionMap["StopOnSensitiveEnabled"] = strconv.FormatBool(setting.StopOnSensitiveEnabled)
111
  common.OptionMap["SensitiveWords"] = setting.SensitiveWordsToString()
112
  common.OptionMap["StreamCacheQueueLength"] = strconv.Itoa(setting.StreamCacheQueueLength)
113
+ common.OptionMap["AutomaticDisableKeywords"] = setting.AutomaticDisableKeywordsToString()
114
 
115
  common.OptionMapRWMutex.Unlock()
116
  loadOptionsFromDatabase()
 
336
  common.QuotaPerUnit, _ = strconv.ParseFloat(value, 64)
337
  case "SensitiveWords":
338
  setting.SensitiveWordsFromString(value)
339
+ case "AutomaticDisableKeywords":
340
+ setting.AutomaticDisableKeywordsFromString(value)
341
  case "StreamCacheQueueLength":
342
  setting.StreamCacheQueueLength, _ = strconv.Atoi(value)
343
  }
relay/channel/adapter.go CHANGED
@@ -15,6 +15,7 @@ type Adaptor interface {
15
  SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error
16
  ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error)
17
  ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error)
 
18
  ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error)
19
  ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error)
20
  DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error)
 
15
  SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error
16
  ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error)
17
  ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error)
18
+ ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error)
19
  ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error)
20
  ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error)
21
  DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error)
relay/channel/ali/adaptor.go CHANGED
@@ -49,9 +49,6 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, re
49
  return nil, errors.New("request is nil")
50
  }
51
  switch info.RelayMode {
52
- case constant.RelayModeEmbeddings:
53
- baiduEmbeddingRequest := embeddingRequestOpenAI2Ali(*request)
54
- return baiduEmbeddingRequest, nil
55
  default:
56
  aliReq := requestOpenAI2Ali(*request)
57
  return aliReq, nil
@@ -67,6 +64,10 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
67
  return nil, errors.New("not implemented")
68
  }
69
 
 
 
 
 
70
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
71
  //TODO implement me
72
  return nil, errors.New("not implemented")
 
49
  return nil, errors.New("request is nil")
50
  }
51
  switch info.RelayMode {
 
 
 
52
  default:
53
  aliReq := requestOpenAI2Ali(*request)
54
  return aliReq, nil
 
64
  return nil, errors.New("not implemented")
65
  }
66
 
67
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
68
+ return embeddingRequestOpenAI2Ali(request), nil
69
+ }
70
+
71
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
72
  //TODO implement me
73
  return nil, errors.New("not implemented")
relay/channel/ali/text.go CHANGED
@@ -25,9 +25,12 @@ func requestOpenAI2Ali(request dto.GeneralOpenAIRequest) *dto.GeneralOpenAIReque
25
  return &request
26
  }
27
 
28
- func embeddingRequestOpenAI2Ali(request dto.GeneralOpenAIRequest) *AliEmbeddingRequest {
 
 
 
29
  return &AliEmbeddingRequest{
30
- Model: "text-embedding-v1",
31
  Input: struct {
32
  Texts []string `json:"texts"`
33
  }{
 
25
  return &request
26
  }
27
 
28
+ func embeddingRequestOpenAI2Ali(request dto.EmbeddingRequest) *AliEmbeddingRequest {
29
+ if request.Model == "" {
30
+ request.Model = "text-embedding-v1"
31
+ }
32
  return &AliEmbeddingRequest{
33
+ Model: request.Model,
34
  Input: struct {
35
  Texts []string `json:"texts"`
36
  }{
relay/channel/aws/adaptor.go CHANGED
@@ -59,6 +59,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
59
  return nil, nil
60
  }
61
 
 
 
 
 
 
 
62
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
63
  return nil, nil
64
  }
 
59
  return nil, nil
60
  }
61
 
62
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
63
+ //TODO implement me
64
+ return nil, errors.New("not implemented")
65
+ }
66
+
67
+
68
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
69
  return nil, nil
70
  }
relay/channel/baidu/adaptor.go CHANGED
@@ -109,9 +109,6 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, re
109
  return nil, errors.New("request is nil")
110
  }
111
  switch info.RelayMode {
112
- case constant.RelayModeEmbeddings:
113
- baiduEmbeddingRequest := embeddingRequestOpenAI2Baidu(*request)
114
- return baiduEmbeddingRequest, nil
115
  default:
116
  baiduRequest := requestOpenAI2Baidu(*request)
117
  return baiduRequest, nil
@@ -122,6 +119,11 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
122
  return nil, nil
123
  }
124
 
 
 
 
 
 
125
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
126
  return channel.DoApiRequest(a, c, info, requestBody)
127
  }
 
109
  return nil, errors.New("request is nil")
110
  }
111
  switch info.RelayMode {
 
 
 
112
  default:
113
  baiduRequest := requestOpenAI2Baidu(*request)
114
  return baiduRequest, nil
 
119
  return nil, nil
120
  }
121
 
122
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
123
+ baiduEmbeddingRequest := embeddingRequestOpenAI2Baidu(request)
124
+ return baiduEmbeddingRequest, nil
125
+ }
126
+
127
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
128
  return channel.DoApiRequest(a, c, info, requestBody)
129
  }
relay/channel/baidu/relay-baidu.go CHANGED
@@ -87,7 +87,7 @@ func streamResponseBaidu2OpenAI(baiduResponse *BaiduChatStreamResponse) *dto.Cha
87
  return &response
88
  }
89
 
90
- func embeddingRequestOpenAI2Baidu(request dto.GeneralOpenAIRequest) *BaiduEmbeddingRequest {
91
  return &BaiduEmbeddingRequest{
92
  Input: request.ParseInput(),
93
  }
 
87
  return &response
88
  }
89
 
90
+ func embeddingRequestOpenAI2Baidu(request dto.EmbeddingRequest) *BaiduEmbeddingRequest {
91
  return &BaiduEmbeddingRequest{
92
  Input: request.ParseInput(),
93
  }
relay/channel/baidu_v2/adaptor.go ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package baidu_v2
2
+
3
+ import (
4
+ "errors"
5
+ "fmt"
6
+ "github.com/gin-gonic/gin"
7
+ "io"
8
+ "net/http"
9
+ "one-api/dto"
10
+ "one-api/relay/channel"
11
+ "one-api/relay/channel/openai"
12
+ relaycommon "one-api/relay/common"
13
+ )
14
+
15
+ type Adaptor struct {
16
+ }
17
+
18
+ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
19
+ //TODO implement me
20
+ return nil, errors.New("not implemented")
21
+ }
22
+
23
+ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error) {
24
+ //TODO implement me
25
+ return nil, errors.New("not implemented")
26
+ }
27
+
28
+ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
29
+ }
30
+
31
+ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
32
+ return fmt.Sprintf("%s/v2/chat/completions", info.BaseUrl), nil
33
+ }
34
+
35
+ func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
36
+ channel.SetupApiRequestHeader(info, c, req)
37
+ req.Set("Authorization", "Bearer "+info.ApiKey)
38
+ return nil
39
+ }
40
+
41
+ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error) {
42
+ if request == nil {
43
+ return nil, errors.New("request is nil")
44
+ }
45
+ return request, nil
46
+ }
47
+
48
+ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
49
+ return nil, nil
50
+ }
51
+
52
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
53
+ //TODO implement me
54
+ return nil, errors.New("not implemented")
55
+ }
56
+
57
+ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
58
+ return channel.DoApiRequest(a, c, info, requestBody)
59
+ }
60
+
61
+ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
62
+ if info.IsStream {
63
+ err, usage = openai.OaiStreamHandler(c, resp, info)
64
+ } else {
65
+ err, usage = openai.OpenaiHandler(c, resp, info.PromptTokens, info.UpstreamModelName)
66
+ }
67
+ return
68
+ }
69
+
70
+ func (a *Adaptor) GetModelList() []string {
71
+ return ModelList
72
+ }
73
+
74
+ func (a *Adaptor) GetChannelName() string {
75
+ return ChannelName
76
+ }
relay/channel/baidu_v2/constants.go ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package baidu_v2
2
+
3
+ var ModelList = []string{
4
+ "ernie-4.0-8k-latest",
5
+ "ernie-4.0-8k-preview",
6
+ "ernie-4.0-8k",
7
+ "ernie-4.0-turbo-8k-latest",
8
+ "ernie-4.0-turbo-8k-preview",
9
+ "ernie-4.0-turbo-8k",
10
+ "ernie-4.0-turbo-128k",
11
+ "ernie-3.5-8k-preview",
12
+ "ernie-3.5-8k",
13
+ "ernie-3.5-128k",
14
+ "ernie-speed-8k",
15
+ "ernie-speed-128k",
16
+ "ernie-speed-pro-128k",
17
+ "ernie-lite-8k",
18
+ "ernie-lite-pro-128k",
19
+ "ernie-tiny-8k",
20
+ "ernie-char-8k",
21
+ "ernie-char-fiction-8k",
22
+ "ernie-novel-8k",
23
+ "deepseek-v3",
24
+ "deepseek-r1",
25
+ "deepseek-r1-distill-qwen-32b",
26
+ "deepseek-r1-distill-qwen-14b",
27
+ }
28
+
29
+ var ChannelName = "volcengine"
relay/channel/claude/adaptor.go CHANGED
@@ -73,6 +73,11 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
73
  return nil, nil
74
  }
75
 
 
 
 
 
 
76
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
77
  return channel.DoApiRequest(a, c, info, requestBody)
78
  }
 
73
  return nil, nil
74
  }
75
 
76
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
77
+ //TODO implement me
78
+ return nil, errors.New("not implemented")
79
+ }
80
+
81
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
82
  return channel.DoApiRequest(a, c, info, requestBody)
83
  }
relay/channel/cloudflare/adaptor.go CHANGED
@@ -56,6 +56,10 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
56
  return request, nil
57
  }
58
 
 
 
 
 
59
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
60
  // 添加文件字段
61
  file, _, err := c.Request.FormFile("file")
 
56
  return request, nil
57
  }
58
 
59
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
60
+ return request, nil
61
+ }
62
+
63
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
64
  // 添加文件字段
65
  file, _, err := c.Request.FormFile("file")
relay/channel/cohere/adaptor.go CHANGED
@@ -54,6 +54,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
54
  return requestConvertRerank2Cohere(request), nil
55
  }
56
 
 
 
 
 
 
 
57
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
58
  if info.RelayMode == constant.RelayModeRerank {
59
  err, usage = cohereRerankHandler(c, resp, info)
 
54
  return requestConvertRerank2Cohere(request), nil
55
  }
56
 
57
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
58
+ //TODO implement me
59
+ return nil, errors.New("not implemented")
60
+ }
61
+
62
+
63
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
64
  if info.RelayMode == constant.RelayModeRerank {
65
  err, usage = cohereRerankHandler(c, resp, info)
relay/channel/deepseek/adaptor.go CHANGED
@@ -29,7 +29,7 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
29
  }
30
 
31
  func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
32
- return fmt.Sprintf("%s/chat/completions", info.BaseUrl), nil
33
  }
34
 
35
  func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
@@ -49,6 +49,11 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
49
  return nil, nil
50
  }
51
 
 
 
 
 
 
52
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
53
  return channel.DoApiRequest(a, c, info, requestBody)
54
  }
 
29
  }
30
 
31
  func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
32
+ return fmt.Sprintf("%s/v1/chat/completions", info.BaseUrl), nil
33
  }
34
 
35
  func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
 
49
  return nil, nil
50
  }
51
 
52
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
53
+ //TODO implement me
54
+ return nil, errors.New("not implemented")
55
+ }
56
+
57
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
58
  return channel.DoApiRequest(a, c, info, requestBody)
59
  }
relay/channel/dify/adaptor.go CHANGED
@@ -48,6 +48,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
48
  return nil, nil
49
  }
50
 
 
 
 
 
 
 
51
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
52
  return channel.DoApiRequest(a, c, info, requestBody)
53
  }
 
48
  return nil, nil
49
  }
50
 
51
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
52
+ //TODO implement me
53
+ return nil, errors.New("not implemented")
54
+ }
55
+
56
+
57
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
58
  return channel.DoApiRequest(a, c, info, requestBody)
59
  }
relay/channel/gemini/adaptor.go CHANGED
@@ -68,6 +68,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
68
  return nil, nil
69
  }
70
 
 
 
 
 
 
 
71
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
72
  return channel.DoApiRequest(a, c, info, requestBody)
73
  }
 
68
  return nil, nil
69
  }
70
 
71
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
72
+ //TODO implement me
73
+ return nil, errors.New("not implemented")
74
+ }
75
+
76
+
77
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
78
  return channel.DoApiRequest(a, c, info, requestBody)
79
  }
relay/channel/jina/adaptor.go CHANGED
@@ -55,6 +55,10 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
55
  return request, nil
56
  }
57
 
 
 
 
 
58
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
59
  if info.RelayMode == constant.RelayModeRerank {
60
  err, usage = jinaRerankHandler(c, resp)
 
55
  return request, nil
56
  }
57
 
58
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
59
+ return request, nil
60
+ }
61
+
62
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
63
  if info.RelayMode == constant.RelayModeRerank {
64
  err, usage = jinaRerankHandler(c, resp)
relay/channel/mistral/adaptor.go CHANGED
@@ -50,6 +50,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
50
  return nil, nil
51
  }
52
 
 
 
 
 
 
 
53
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
54
  return channel.DoApiRequest(a, c, info, requestBody)
55
  }
 
50
  return nil, nil
51
  }
52
 
53
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
54
+ //TODO implement me
55
+ return nil, errors.New("not implemented")
56
+ }
57
+
58
+
59
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
60
  return channel.DoApiRequest(a, c, info, requestBody)
61
  }
relay/channel/mokaai/adaptor.go ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package mokaai
2
+
3
+ import (
4
+ "errors"
5
+ "fmt"
6
+ "github.com/gin-gonic/gin"
7
+ "io"
8
+ "net/http"
9
+ "one-api/dto"
10
+ "one-api/relay/channel"
11
+ relaycommon "one-api/relay/common"
12
+ "one-api/relay/constant"
13
+ "strings"
14
+ )
15
+
16
+ type Adaptor struct {
17
+ }
18
+
19
+ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
20
+ //TODO implement me
21
+ return nil, errors.New("not implemented")
22
+ }
23
+
24
+ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error) {
25
+ //TODO implement me
26
+ return nil, errors.New("not implemented")
27
+ }
28
+
29
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
30
+ //TODO implement me
31
+ return request, nil
32
+ }
33
+
34
+ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
35
+
36
+ }
37
+
38
+ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
39
+ // https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t
40
+ suffix := "chat/"
41
+ if strings.HasPrefix(info.UpstreamModelName, "m3e") {
42
+ suffix = "embeddings"
43
+ }
44
+ fullRequestURL := fmt.Sprintf("%s/%s", info.BaseUrl, suffix)
45
+ return fullRequestURL, nil
46
+ }
47
+
48
+ func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
49
+ channel.SetupApiRequestHeader(info, c, req)
50
+ req.Set("Authorization", fmt.Sprintf("Bearer %s", info.ApiKey))
51
+ return nil
52
+ }
53
+
54
+ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error) {
55
+ if request == nil {
56
+ return nil, errors.New("request is nil")
57
+ }
58
+ switch info.RelayMode {
59
+ case constant.RelayModeEmbeddings:
60
+ baiduEmbeddingRequest := embeddingRequestOpenAI2Moka(*request)
61
+ return baiduEmbeddingRequest, nil
62
+ default:
63
+ return nil, errors.New("not implemented")
64
+ }
65
+ }
66
+
67
+ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
68
+ return nil, nil
69
+ }
70
+
71
+ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
72
+ return channel.DoApiRequest(a, c, info, requestBody)
73
+ }
74
+
75
+ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
76
+
77
+ switch info.RelayMode {
78
+ case constant.RelayModeEmbeddings:
79
+ err, usage = mokaEmbeddingHandler(c, resp)
80
+ default:
81
+ // err, usage = mokaHandler(c, resp)
82
+
83
+ }
84
+ return
85
+ }
86
+
87
+ func (a *Adaptor) GetModelList() []string {
88
+ return ModelList
89
+ }
90
+
91
+ func (a *Adaptor) GetChannelName() string {
92
+ return ChannelName
93
+ }
relay/channel/mokaai/constants.go ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ package mokaai
2
+
3
+ var ModelList = []string{
4
+ "m3e-large",
5
+ "m3e-base",
6
+ "m3e-small",
7
+ }
8
+
9
+ var ChannelName = "mokaai"
relay/channel/mokaai/relay-mokaai.go ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package mokaai
2
+
3
+ import (
4
+ "encoding/json"
5
+ "github.com/gin-gonic/gin"
6
+ "io"
7
+ "net/http"
8
+ "one-api/dto"
9
+ "one-api/service"
10
+ )
11
+
12
+ func embeddingRequestOpenAI2Moka(request dto.GeneralOpenAIRequest) *dto.EmbeddingRequest {
13
+ var input []string // Change input to []string
14
+
15
+ switch v := request.Input.(type) {
16
+ case string:
17
+ input = []string{v} // Convert string to []string
18
+ case []string:
19
+ input = v // Already a []string, no conversion needed
20
+ case []interface{}:
21
+ for _, part := range v {
22
+ if str, ok := part.(string); ok {
23
+ input = append(input, str) // Append each string to the slice
24
+ }
25
+ }
26
+ }
27
+ return &dto.EmbeddingRequest{
28
+ Input: input,
29
+ Model: request.Model,
30
+ }
31
+ }
32
+
33
+ func embeddingResponseMoka2OpenAI(response *dto.EmbeddingResponse) *dto.OpenAIEmbeddingResponse {
34
+ openAIEmbeddingResponse := dto.OpenAIEmbeddingResponse{
35
+ Object: "list",
36
+ Data: make([]dto.OpenAIEmbeddingResponseItem, 0, len(response.Data)),
37
+ Model: "baidu-embedding",
38
+ Usage: response.Usage,
39
+ }
40
+ for _, item := range response.Data {
41
+ openAIEmbeddingResponse.Data = append(openAIEmbeddingResponse.Data, dto.OpenAIEmbeddingResponseItem{
42
+ Object: item.Object,
43
+ Index: item.Index,
44
+ Embedding: item.Embedding,
45
+ })
46
+ }
47
+ return &openAIEmbeddingResponse
48
+ }
49
+
50
+ func mokaEmbeddingHandler(c *gin.Context, resp *http.Response) (*dto.OpenAIErrorWithStatusCode, *dto.Usage) {
51
+ var baiduResponse dto.EmbeddingResponse
52
+ responseBody, err := io.ReadAll(resp.Body)
53
+ if err != nil {
54
+ return service.OpenAIErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError), nil
55
+ }
56
+ err = resp.Body.Close()
57
+ if err != nil {
58
+ return service.OpenAIErrorWrapper(err, "close_response_body_failed", http.StatusInternalServerError), nil
59
+ }
60
+ err = json.Unmarshal(responseBody, &baiduResponse)
61
+ if err != nil {
62
+ return service.OpenAIErrorWrapper(err, "unmarshal_response_body_failed", http.StatusInternalServerError), nil
63
+ }
64
+ // if baiduResponse.ErrorMsg != "" {
65
+ // return &dto.OpenAIErrorWithStatusCode{
66
+ // Error: dto.OpenAIError{
67
+ // Type: "baidu_error",
68
+ // Param: "",
69
+ // },
70
+ // StatusCode: resp.StatusCode,
71
+ // }, nil
72
+ // }
73
+ fullTextResponse := embeddingResponseMoka2OpenAI(&baiduResponse)
74
+ jsonResponse, err := json.Marshal(fullTextResponse)
75
+ if err != nil {
76
+ return service.OpenAIErrorWrapper(err, "marshal_response_body_failed", http.StatusInternalServerError), nil
77
+ }
78
+ c.Writer.Header().Set("Content-Type", "application/json")
79
+ c.Writer.WriteHeader(resp.StatusCode)
80
+ _, err = c.Writer.Write(jsonResponse)
81
+ return nil, &fullTextResponse.Usage
82
+ }
83
+
relay/channel/ollama/adaptor.go CHANGED
@@ -46,18 +46,17 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, re
46
  if request == nil {
47
  return nil, errors.New("request is nil")
48
  }
49
- switch info.RelayMode {
50
- case relayconstant.RelayModeEmbeddings:
51
- return requestOpenAI2Embeddings(*request), nil
52
- default:
53
- return requestOpenAI2Ollama(*request), nil
54
- }
55
  }
56
 
57
  func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
58
  return nil, nil
59
  }
60
 
 
 
 
 
61
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
62
  return channel.DoApiRequest(a, c, info, requestBody)
63
  }
 
46
  if request == nil {
47
  return nil, errors.New("request is nil")
48
  }
49
+ return requestOpenAI2Ollama(*request), nil
 
 
 
 
 
50
  }
51
 
52
  func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
53
  return nil, nil
54
  }
55
 
56
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
57
+ return requestOpenAI2Embeddings(request), nil
58
+ }
59
+
60
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
61
  return channel.DoApiRequest(a, c, info, requestBody)
62
  }
relay/channel/ollama/relay-ollama.go CHANGED
@@ -42,7 +42,7 @@ func requestOpenAI2Ollama(request dto.GeneralOpenAIRequest) *OllamaRequest {
42
  }
43
  }
44
 
45
- func requestOpenAI2Embeddings(request dto.GeneralOpenAIRequest) *OllamaEmbeddingRequest {
46
  return &OllamaEmbeddingRequest{
47
  Model: request.Model,
48
  Input: request.ParseInput(),
@@ -123,9 +123,9 @@ func ollamaEmbeddingHandler(c *gin.Context, resp *http.Response, promptTokens in
123
  }
124
 
125
  func flattenEmbeddings(embeddings [][]float64) []float64 {
126
- flattened := []float64{}
127
- for _, row := range embeddings {
128
- flattened = append(flattened, row...)
 
 
129
  }
130
- return flattened
131
- }
 
42
  }
43
  }
44
 
45
+ func requestOpenAI2Embeddings(request dto.EmbeddingRequest) *OllamaEmbeddingRequest {
46
  return &OllamaEmbeddingRequest{
47
  Model: request.Model,
48
  Input: request.ParseInput(),
 
123
  }
124
 
125
  func flattenEmbeddings(embeddings [][]float64) []float64 {
126
+ flattened := []float64{}
127
+ for _, row := range embeddings {
128
+ flattened = append(flattened, row...)
129
+ }
130
+ return flattened
131
  }
 
 
relay/channel/openai/adaptor.go CHANGED
@@ -149,6 +149,10 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
149
  return nil, errors.New("not implemented")
150
  }
151
 
 
 
 
 
152
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
153
  a.ResponseFormat = request.ResponseFormat
154
  if info.RelayMode == constant.RelayModeAudioSpeech {
 
149
  return nil, errors.New("not implemented")
150
  }
151
 
152
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
153
+ return request, nil
154
+ }
155
+
156
  func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
157
  a.ResponseFormat = request.ResponseFormat
158
  if info.RelayMode == constant.RelayModeAudioSpeech {
relay/channel/openai/relay-openai.go CHANGED
@@ -5,6 +5,9 @@ import (
5
  "bytes"
6
  "encoding/json"
7
  "fmt"
 
 
 
8
  "github.com/pkg/errors"
9
  "io"
10
  "math"
@@ -20,10 +23,6 @@ import (
20
  "strings"
21
  "sync"
22
  "time"
23
-
24
- "github.com/bytedance/gopkg/util/gopool"
25
- "github.com/gin-gonic/gin"
26
- "github.com/gorilla/websocket"
27
  )
28
 
29
  func sendStreamData(c *gin.Context, data string, forceFormat bool) error {
@@ -91,11 +90,12 @@ func OaiStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.Rel
91
  if len(data) < 6 { // ignore blank line or wrong format
92
  continue
93
  }
94
- if data[:6] != "data: " && data[:6] != "[DONE]" {
95
  continue
96
  }
97
  mu.Lock()
98
- data = data[6:]
 
99
  if !strings.HasPrefix(data, "[DONE]") {
100
  if lastStreamData != "" {
101
  err := sendStreamData(c, lastStreamData, forceFormat)
 
5
  "bytes"
6
  "encoding/json"
7
  "fmt"
8
+ "github.com/bytedance/gopkg/util/gopool"
9
+ "github.com/gin-gonic/gin"
10
+ "github.com/gorilla/websocket"
11
  "github.com/pkg/errors"
12
  "io"
13
  "math"
 
23
  "strings"
24
  "sync"
25
  "time"
 
 
 
 
26
  )
27
 
28
  func sendStreamData(c *gin.Context, data string, forceFormat bool) error {
 
90
  if len(data) < 6 { // ignore blank line or wrong format
91
  continue
92
  }
93
+ if data[:5] != "data:" && data[:6] != "[DONE]" {
94
  continue
95
  }
96
  mu.Lock()
97
+ data = data[5:]
98
+ data = strings.TrimSpace(data)
99
  if !strings.HasPrefix(data, "[DONE]") {
100
  if lastStreamData != "" {
101
  err := sendStreamData(c, lastStreamData, forceFormat)
relay/channel/palm/adaptor.go CHANGED
@@ -49,6 +49,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
49
  return nil, nil
50
  }
51
 
 
 
 
 
 
 
52
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
53
  return channel.DoApiRequest(a, c, info, requestBody)
54
  }
 
49
  return nil, nil
50
  }
51
 
52
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
53
+ //TODO implement me
54
+ return nil, errors.New("not implemented")
55
+ }
56
+
57
+
58
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
59
  return channel.DoApiRequest(a, c, info, requestBody)
60
  }
relay/channel/perplexity/adaptor.go CHANGED
@@ -52,6 +52,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
52
  return nil, nil
53
  }
54
 
 
 
 
 
 
 
55
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
56
  return channel.DoApiRequest(a, c, info, requestBody)
57
  }
 
52
  return nil, nil
53
  }
54
 
55
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
56
+ //TODO implement me
57
+ return nil, errors.New("not implemented")
58
+ }
59
+
60
+
61
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
62
  return channel.DoApiRequest(a, c, info, requestBody)
63
  }
relay/channel/siliconflow/adaptor.go CHANGED
@@ -58,6 +58,10 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
58
  return request, nil
59
  }
60
 
 
 
 
 
61
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
62
  switch info.RelayMode {
63
  case constant.RelayModeRerank:
 
58
  return request, nil
59
  }
60
 
61
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
62
+ return request, nil
63
+ }
64
+
65
  func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
66
  switch info.RelayMode {
67
  case constant.RelayModeRerank:
relay/channel/tencent/adaptor.go CHANGED
@@ -73,6 +73,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
73
  return nil, nil
74
  }
75
 
 
 
 
 
 
 
76
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
77
  return channel.DoApiRequest(a, c, info, requestBody)
78
  }
 
73
  return nil, nil
74
  }
75
 
76
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
77
+ //TODO implement me
78
+ return nil, errors.New("not implemented")
79
+ }
80
+
81
+
82
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
83
  return channel.DoApiRequest(a, c, info, requestBody)
84
  }
relay/channel/vertex/adaptor.go CHANGED
@@ -151,6 +151,12 @@ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dt
151
  return nil, nil
152
  }
153
 
 
 
 
 
 
 
154
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
155
  return channel.DoApiRequest(a, c, info, requestBody)
156
  }
 
151
  return nil, nil
152
  }
153
 
154
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
155
+ //TODO implement me
156
+ return nil, errors.New("not implemented")
157
+ }
158
+
159
+
160
  func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
161
  return channel.DoApiRequest(a, c, info, requestBody)
162
  }
relay/channel/volcengine/adaptor.go ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package volcengine
2
+
3
+ import (
4
+ "errors"
5
+ "fmt"
6
+ "github.com/gin-gonic/gin"
7
+ "io"
8
+ "net/http"
9
+ "one-api/dto"
10
+ "one-api/relay/channel"
11
+ "one-api/relay/channel/openai"
12
+ relaycommon "one-api/relay/common"
13
+ "one-api/relay/constant"
14
+ "strings"
15
+ )
16
+
17
+ type Adaptor struct {
18
+ }
19
+
20
+ func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
21
+ //TODO implement me
22
+ return nil, errors.New("not implemented")
23
+ }
24
+
25
+ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.ImageRequest) (any, error) {
26
+ //TODO implement me
27
+ return nil, errors.New("not implemented")
28
+ }
29
+
30
+ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
31
+ }
32
+
33
+ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
34
+ switch info.RelayMode {
35
+ case constant.RelayModeChatCompletions:
36
+ if strings.HasPrefix(info.UpstreamModelName, "bot") {
37
+ return fmt.Sprintf("%s/api/v3/bots/chat/completions", info.BaseUrl), nil
38
+ }
39
+ return fmt.Sprintf("%s/api/v3/chat/completions", info.BaseUrl), nil
40
+ case constant.RelayModeEmbeddings:
41
+ return fmt.Sprintf("%s/api/v3/embeddings", info.BaseUrl), nil
42
+ default:
43
+ }
44
+ return "", fmt.Errorf("unsupported relay mode: %d", info.RelayMode)
45
+ }
46
+
47
+ func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Header, info *relaycommon.RelayInfo) error {
48
+ channel.SetupApiRequestHeader(info, c, req)
49
+ req.Set("Authorization", "Bearer "+info.ApiKey)
50
+ return nil
51
+ }
52
+
53
+ func (a *Adaptor) ConvertRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeneralOpenAIRequest) (any, error) {
54
+ if request == nil {
55
+ return nil, errors.New("request is nil")
56
+ }
57
+ return request, nil
58
+ }
59
+
60
+ func (a *Adaptor) ConvertRerankRequest(c *gin.Context, relayMode int, request dto.RerankRequest) (any, error) {
61
+ return nil, nil
62
+ }
63
+
64
+ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.EmbeddingRequest) (any, error) {
65
+ return request, nil
66
+ }
67
+
68
+ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, requestBody io.Reader) (any, error) {
69
+ return channel.DoApiRequest(a, c, info, requestBody)
70
+ }
71
+
72
+ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *dto.OpenAIErrorWithStatusCode) {
73
+ switch info.RelayMode {
74
+ case constant.RelayModeChatCompletions:
75
+ if info.IsStream {
76
+ err, usage = openai.OaiStreamHandler(c, resp, info)
77
+ } else {
78
+ err, usage = openai.OpenaiHandler(c, resp, info.PromptTokens, info.UpstreamModelName)
79
+ }
80
+ case constant.RelayModeEmbeddings:
81
+ err, usage = openai.OpenaiHandler(c, resp, info.PromptTokens, info.UpstreamModelName)
82
+ }
83
+ return
84
+ }
85
+
86
+ func (a *Adaptor) GetModelList() []string {
87
+ return ModelList
88
+ }
89
+
90
+ func (a *Adaptor) GetChannelName() string {
91
+ return ChannelName
92
+ }