更新版本
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .github/workflows/docker-image-arm64.yml +0 -3
- BT.md +3 -3
- Dockerfile +13 -9
- README.en.md +34 -5
- README.md +217 -10
- VERSION +1 -1
- common/constants.go +7 -2
- common/database.go +1 -0
- controller/channel-test.go +27 -6
- controller/relay.go +2 -0
- dto/embedding.go +57 -0
- dto/openai_request.go +18 -5
- dto/openai_response.go +1 -1
- go.mod +10 -4
- go.sum +23 -9
- main.go +7 -0
- middleware/distributor.go +2 -0
- model/cache.go +0 -100
- model/log.go +28 -6
- model/main.go +1 -1
- model/option.go +3 -0
- relay/channel/adapter.go +1 -0
- relay/channel/ali/adaptor.go +4 -3
- relay/channel/ali/text.go +5 -2
- relay/channel/aws/adaptor.go +6 -0
- relay/channel/baidu/adaptor.go +5 -3
- relay/channel/baidu/relay-baidu.go +1 -1
- relay/channel/baidu_v2/adaptor.go +76 -0
- relay/channel/baidu_v2/constants.go +29 -0
- relay/channel/claude/adaptor.go +5 -0
- relay/channel/cloudflare/adaptor.go +4 -0
- relay/channel/cohere/adaptor.go +6 -0
- relay/channel/deepseek/adaptor.go +6 -1
- relay/channel/dify/adaptor.go +6 -0
- relay/channel/gemini/adaptor.go +6 -0
- relay/channel/jina/adaptor.go +4 -0
- relay/channel/mistral/adaptor.go +6 -0
- relay/channel/mokaai/adaptor.go +93 -0
- relay/channel/mokaai/constants.go +9 -0
- relay/channel/mokaai/relay-mokaai.go +83 -0
- relay/channel/ollama/adaptor.go +5 -6
- relay/channel/ollama/relay-ollama.go +6 -6
- relay/channel/openai/adaptor.go +4 -0
- relay/channel/openai/relay-openai.go +6 -6
- relay/channel/palm/adaptor.go +6 -0
- relay/channel/perplexity/adaptor.go +6 -0
- relay/channel/siliconflow/adaptor.go +4 -0
- relay/channel/tencent/adaptor.go +6 -0
- relay/channel/vertex/adaptor.go +6 -0
- 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 |
-

|
|
|
|
| 1 |
+
密钥为环境变量SESSION_SECRET
|
| 2 |
+
|
| 3 |
+

|
Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
FROM oven/bun:latest
|
| 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 |
-
|
| 14 |
-
|
| 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)'
|
| 22 |
|
| 23 |
FROM alpine
|
| 24 |
|
| 25 |
-
RUN apk update
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<p align="right">
|
| 2 |
+
<strong>中文</strong> | <a href="./README.en.md">English</a>
|
| 3 |
+
</p>
|
| 4 |
+
<div align="center">
|
| 5 |
+
|
| 6 |
+

|
| 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 |
+

|
| 194 |
+
|
| 195 |
+
|
| 196 |
+

|
| 197 |
+
|
| 198 |
+

|
| 199 |
+
|
| 200 |
+

|
| 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 |
+
[](https://star-history.com/#Calcium-Ion/new-api&Date)
|
VERSION
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
v0.4.
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
| 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:
|
| 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-
|
| 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 =
|
| 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
|
| 90 |
-
Content
|
| 91 |
-
Name
|
| 92 |
-
|
| 93 |
-
|
|
|
|
|
|
|
| 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/
|
| 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.
|
| 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.
|
| 270 |
-
gorm.io/gorm v1.25.
|
| 271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
|
|
|
|
|
|
|
|
|
| 29 |
return &AliEmbeddingRequest{
|
| 30 |
-
Model:
|
| 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.
|
| 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 |
-
|
| 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.
|
| 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 |
-
|
|
|
|
|
|
|
| 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[:
|
| 95 |
continue
|
| 96 |
}
|
| 97 |
mu.Lock()
|
| 98 |
-
data = data[
|
|
|
|
| 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 |
+
}
|