Dhudean commited on
Commit
e0b8007
·
1 Parent(s): 2d457a6
Dockerfile CHANGED
@@ -4,9 +4,8 @@ FROM golang AS builder
4
  # 设置环境变量
5
  ENV GO111MODULE=on \
6
  CGO_ENABLED=0 \
7
- GOOS=linux \
8
- AUTO_DEL_CHAT=1
9
-
10
  # 设置工作目录
11
  WORKDIR /build
12
 
@@ -25,12 +24,6 @@ FROM alpine
25
  # 安装基本的运行时依赖
26
  RUN apk --no-cache add ca-certificates tzdata
27
 
28
- # 在最终镜像里声明环境变量,容器真正运行时可见
29
- ENV AUTO_DEL_CHAT=1
30
-
31
- RUN echo "AUTO_DEL_CHAT is $AUTO_DEL_CHAT"
32
-
33
-
34
  # 从构建阶段复制可执行文件
35
  COPY --from=builder /genspark2api .
36
 
 
4
  # 设置环境变量
5
  ENV GO111MODULE=on \
6
  CGO_ENABLED=0 \
7
+ GOOS=linux
8
+
 
9
  # 设置工作目录
10
  WORKDIR /build
11
 
 
24
  # 安装基本的运行时依赖
25
  RUN apk --no-cache add ca-certificates tzdata
26
 
 
 
 
 
 
 
27
  # 从构建阶段复制可执行文件
28
  COPY --from=builder /genspark2api .
29
 
README.md CHANGED
@@ -1,10 +1,251 @@
1
- ---
2
- title: Genspark2api
3
- emoji: 💻
4
- colorFrom: red
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- app_port: 7055
10
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <p align="right">
2
+ <strong>中文</strong>
3
+ </p>
4
+ <div align="center">
5
+
6
+ # Genspark2API
7
+
8
+ _觉得有点意思的话 别忘了点个 ⭐_
9
+
10
+ <a href="https://t.me/+LGKwlC_xa-E5ZDk9">
11
+ <img src="https://telegram.org/img/website_icon.svg" width="16" height="16" style="vertical-align: middle;">
12
+ <span style="text-decoration: none; font-size: 12px; color: #0088cc; vertical-align: middle;">Telegram 交流群</span>
13
+ </a>
14
+
15
+ <sup><i>(原`coze-discord-proxy`交流群, 此项目仍可进此群**交流** / **反馈bug**)</i></sup>
16
+
17
+ </div>
18
+
19
+
20
+
21
+ ## 功能
22
+
23
+ - [x] 支持对话接口(流式/非流式)(`/chat/completions`)(请求非以下列表的模型会触发`Mixture-of-Agents`模式)
24
+ - **gpt-4o**
25
+ - **o1**
26
+ - **o3-mini-high**
27
+ - **claude-3-5-sonnet**
28
+ - **claude-3-5-haiku**
29
+ - **gemini-1.5-pro**
30
+ - **gemini-1.5-flash**
31
+ - **deep-seek-v3**
32
+ - **deep-seek-r1**
33
+ - [x] 支持识别**图片**/**文件**多轮对话
34
+ - [x] 支持文生图接口(`/images/generations`),详细请看[生图模型配置](#生图模型配置)
35
+ - **flux**
36
+ - **flux-speed**
37
+ - **flux-pro/ultra**
38
+ - **ideogram**
39
+ - **recraft-v3**
40
+ - **dall-e-3**
41
+ - [x] 支持自定义请求头校验值(Authorization)
42
+ - [x] 支持cookie池(随机)
43
+ - [x] 支持请求失败自动切换cookie重试(需配置cookie池)
44
+ - [x] 可配置自动删除对话记录
45
+ - [x] 可配置代理请求(环境变量`PROXY_URL`)
46
+ - [x] 可配置Model绑定Chat(解决模型自动切换导致**降智**),详细请看[进阶配置](#解决模型自动切换导致降智问题)。
47
+
48
+ ### 接口文档:
49
+
50
+
51
+
52
+ ### 示例:
53
+
54
+ <span><img src="docs/img2.png" width="800"/></span>
55
+
56
+ ## 如何使用
57
+
58
+
59
+
60
+ ## 如何集成NextChat
61
+
62
+ 填 接口地址(ip:端口/域名) 及 API-Key(`PROXY_SECRET`),其它的随便填随便选。
63
+
64
+ > 如果自己没有搭建NextChat面板,这里有个已经搭建好的可以使用 [NeatChat](https://ai.aytsao.cn/)
65
+
66
+ <span><img src="docs/img5.png" width="800"/></span>
67
+
68
+ ## 如何集成one-api
69
+
70
+ 填 `BaseURL`(ip:端口/域名) 及 密钥(`PROXY_SECRET`),其它的随便填随便选。
71
+
72
+ <span><img src="docs/img3.png" width="800"/></span>
73
+
74
+ ## 部署
75
+
76
+ ### 基于 Docker-Compose(All In One) 进行部署
77
+
78
+ ```shell
79
+ docker-compose pull && docker-compose up -d
80
+ ```
81
+
82
+ #### docker-compose.yml
83
+
84
+ ```docker
85
+ version: '3.4'
86
+
87
+ services:
88
+ genspark2api:
89
+ image: deanxv/genspark2api:latest
90
+ container_name: genspark2api
91
+ restart: always
92
+ ports:
93
+ - "7055:7055"
94
+ volumes:
95
+ - ./data:/app/genspark2api/data
96
+ environment:
97
+ - GS_COOKIE=****** # cookie (多个请以,分隔)
98
+ - API_SECRET=123456 # [可选]接口密钥-修改此行为请求头校验的值(多个请以,分隔)
99
+ - TZ=Asia/Shanghai
100
+ ```
101
+
102
+ ### 基于 Docker 进行部署
103
+
104
+ ```docker
105
+ docker run --name genspark2api -d --restart always \
106
+ -p 7055:7055 \
107
+ -v $(pwd)/data:/app/genspark2api/data \
108
+ -e GS_COOKIE=***** \
109
+ -e API_SECRET="123456" \
110
+ -e TZ=Asia/Shanghai \
111
+ deanxv/genspark2api
112
+ ```
113
+
114
+ 其中`API_SECRET`、`GS_COOKIE`修改为自己的。
115
+
116
+ 如果上面的镜像无法拉取,可以尝试使用 GitHub 的 Docker 镜像,将上面的`deanxv/genspark2api`替换为`ghcr.io/deanxv/genspark2api`即可。
117
+
118
+ ### 部署到第三方平台
119
+
120
+ <details>
121
+ <summary><strong>部署到 Zeabur</strong></summary>
122
+ <div>
123
+
124
+ > Zeabur 的服务器在国外,自动解决了网络的问题,~~同时免费的额度也足够个人使用~~
125
+
126
+ 1. 首先 **fork** 一份代码。
127
+ 2. 进入 [Zeabur](https://zeabur.com?referralCode=deanxv),使用github登录,进入控制台。
128
+ 3. 在 Service -> Add Service,选择 Git(第一次使用需要先授权),选择你 fork 的仓库。
129
+ 4. Deploy 会自动开始,先取消。
130
+ 5. 添加环境变量
131
+
132
+ `GS_COOKIE:******` cookie (多个请以,分隔)
133
+
134
+ `API_SECRET:123456` [可选]接口密钥-修改此行为请求头校验的值(多个请以,分隔)(与openai-API-KEY用法一致)
135
+
136
+ 保存。
137
+
138
+ 6. 选择 Redeploy。
139
+
140
+ </div>
141
+
142
+
143
+ </details>
144
+
145
+ <details>
146
+ <summary><strong>部署到 Render</strong></summary>
147
+ <div>
148
+
149
+ > Render 提供免费额度,绑卡后可以进一步提升额度
150
+
151
+ Render 可以直接部署 docker 镜像,不需要 fork 仓库:[Render](https://dashboard.render.com)
152
+
153
+ </div>
154
+ </details>
155
+
156
+ ## 配置
157
+
158
+ ### 环境变量
159
+
160
+ 1. `PORT=7055` [可选]端口,默认为7055
161
+ 2. `DEBUG=true` [可选]DEBUG模式,可打印更多信息[true:打开、false:关闭]
162
+ 3. `API_SECRET=123456` [可选]接口密钥-修改此行为请求头(Authorization)校验的值(同API-KEY)(多个请以,分隔)
163
+ 4. `GS_COOKIE=******` cookie (多个请以,分隔)
164
+ 5. `YES_CAPTCHA_CLIENT_KEY=******` [可选]YesCaptcha Client Key 过谷歌验证,详细请看[使用YesCaptcha过谷歌验证](#使用YesCaptcha过谷歌验证)
165
+ 6. `AUTO_DEL_CHAT=0` [可选]对话完成自动删除(默认:0)[0:关闭,1:开启]
166
+ 7. `REQUEST_RATE_LIMIT=60` [可选]每分钟下的单ip请求速率限制,默认:60次/min
167
+ 8. `PROXY_URL=http://127.0.0.1:10801` [可选]代理
168
+ 9. `AUTO_MODEL_CHAT_MAP_TYPE=1` [可选]自动配置Model绑定Chat(默认:1)[0:关闭,1:开启]
169
+ 10. `MODEL_CHAT_MAP=claude-3-5-sonnet=a649******00fa,gpt-4o=su74******47hd` [可选]Model绑定Chat(多个请以,分隔),详细请看[进阶配置](#解决模型自动切换导致降智问题)
170
+ 11. `SESSION_IMAGE_CHAT_MAP=aed9196b-********-4ed6e32f7e4d=0c6785e6-********-7ff6e5a2a29c,aefwer6b-********-casds22=fda234-********-sfaw123` [可选]Session绑定Image-Chat(多个请以,分隔),详细请看[进阶配置](#生图模型配置)
171
+
172
+ ### cookie获取方式
173
+
174
+ 1. 打开**F12**开发者工具。
175
+ 2. 发起对话。
176
+ 3. 点击ask请求,请求头中的**cookie**即为环境变量**GS_COOKIE**所需值。
177
+
178
+ > **【注】** 其中`session_id=f9c60******cb6d`是必须的,其他内容可要可不要,即环境变量`GS_COOKIE=session_id=f9c60******cb6d`
179
+
180
+
181
+ ![img.png](docs/img.png)
182
+
183
+ ## 进阶配置
184
+
185
+ ### 解决模型自动切换导致降智问题
186
+
187
+ #### 方案一 (默认启用此配置)【推荐】
188
+
189
+ > 配置环境变量 **AUTO_MODEL_CHAT_MAP_TYPE=1**
190
+ >
191
+ > 此配置下,会在调用模型时获取对话的id,并绑定模型。
192
+
193
+ #### 方案二
194
+
195
+ > 配置环境变量 MODEL_CHAT_MAP
196
+ >
197
+ > 【作用】指定对话,解决模型自动切换导致降智问题。
198
+
199
+ 1. 打开**F12**开发者工具。
200
+ 2. 选择需要绑定的对话的模型(示例:`claude-3-5-sonnet`),发起对话。
201
+ 3. 点击ask请求,此时最上方url中的`id`(或响应中的`id`)即为此对话唯一id。
202
+ ![img.png](docs/img4.png)
203
+ 4. 配置环境变量 `MODEL_CHAT_MAP=claude-3-5-sonnet=3cdcc******474c5` (多个请以,分隔)
204
+
205
+ ### 生图模型配置
206
+
207
+ > 配置环境变量 SESSION_IMAGE_CHAT_MAP
208
+
209
+ 1. 打开**F12**开发者工具。
210
+ 2. 选择生成图像,选择任一生图模型,发起对话。
211
+ 3. 点击ask请求,此时最上方url中的`id`(或响应中的`id`)即为此对话唯一id,然后在请求头中获取`session_id`的值。
212
+ ![img.png](docs/img7.png)
213
+ 4. 配置环境变量 `SESSION_IMAGE_CHAT_MAP=aed9196b-********-4ed6e32f7e4d=0c6785e6-********-7ff6e5a2a29c` (即session=chatId的格式,多个请以,分隔)
214
+
215
+ ### 使用YesCaptcha过谷歌验证[**暂不需要**]
216
+
217
+ > genspark官方目前文生图接口需要过谷歌验证,可使用YesCaptcha解决。
218
+ >
219
+ > **tip**: 过一次谷歌验证消耗20积分,约**0.0167元人民币**(1元人民币约能用60次)。
220
+
221
+
222
+ ~~1. 注册 [YesCaptcha](https://yescaptcha.com/i/021iAE)[此链接注册直达**vip5**]~~
223
+
224
+ ~~2. 获取`Client Key`~~
225
+ ~~![img.png](docs/img6.png)~~
226
+
227
+ ~~3. 配置环变量`YES_CAPTCHA_CLIENT_KEY=******`~~
228
+
229
+ ~~4. 重启服务~~
230
+
231
+ ## 报错排查
232
+
233
+ > `Detected Cloudflare Challenge Page`
234
+ >
235
+
236
+ 被Cloudflare拦截出5s盾,可配置`PROXY_URL`。
237
+
238
+ (【推荐方案】[自建ipv6代理池绕过cf对ip的速率限制及5s盾](https://linux.do/t/topic/367413)或购买[IProyal](https://iproyal.cn/?r=244330))
239
+
240
+ > `Genspark Service Unavailable`
241
+ >
242
+ Genspark官方服务不可用,请稍后再试。
243
+
244
+ > `All cookies are temporarily unavailable.`
245
+ >
246
+ 所有用户(cookie)均到达速率限制,更换用户cookie或稍后再试。
247
+
248
+ ## 其他
249
+
250
+ **Genspark**(
251
+ 注册领取1个月Plus): [https://www.genspark.ai](https://www.genspark.ai/invite?invite_code=YjVjMGRkYWVMZmE4YUw5MDc0TDM1ODlMZDYwMzQ4OTJlNmEx)
common/config/config.go CHANGED
@@ -13,8 +13,13 @@ import (
13
 
14
  var ApiSecret = os.Getenv("API_SECRET")
15
  var ApiSecrets = strings.Split(os.Getenv("API_SECRET"), ",")
 
16
  var GSCookie = os.Getenv("GS_COOKIE")
17
  var GSCookies = strings.Split(os.Getenv("GS_COOKIE"), ",")
 
 
 
 
18
  var AutoDelChat = env.Int("AUTO_DEL_CHAT", 0)
19
  var ProxyUrl = env.String("PROXY_URL", "")
20
  var AutoModelChatMapType = env.Int("AUTO_MODEL_CHAT_MAP_TYPE", 1)
 
13
 
14
  var ApiSecret = os.Getenv("API_SECRET")
15
  var ApiSecrets = strings.Split(os.Getenv("API_SECRET"), ",")
16
+
17
  var GSCookie = os.Getenv("GS_COOKIE")
18
  var GSCookies = strings.Split(os.Getenv("GS_COOKIE"), ",")
19
+
20
+ // var IpBlackList = os.Getenv("IP_BLACK_LIST")
21
+ var IpBlackList = strings.Split(os.Getenv("IP_BLACK_LIST"), ",")
22
+
23
  var AutoDelChat = env.Int("AUTO_DEL_CHAT", 0)
24
  var ProxyUrl = env.String("PROXY_URL", "")
25
  var AutoModelChatMapType = env.Int("AUTO_MODEL_CHAT_MAP_TYPE", 1)
common/constants.go CHANGED
@@ -3,7 +3,7 @@ package common
3
  import "time"
4
 
5
  var StartTime = time.Now().Unix() // unit: second
6
- var Version = "v1.8.6" // this hard coding will be replaced automatically when building, no need to manually change
7
 
8
  var DefaultOpenaiModelList = []string{
9
  "gpt-4o",
 
3
  import "time"
4
 
5
  var StartTime = time.Now().Unix() // unit: second
6
+ var Version = "v1.8.10" // this hard coding will be replaced automatically when building, no need to manually change
7
 
8
  var DefaultOpenaiModelList = []string{
9
  "gpt-4o",
controller/chat.go CHANGED
@@ -323,6 +323,8 @@ func fetchImageBytes(url string) ([]byte, error) {
323
  }
324
 
325
  func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string, openAIReq *model.OpenAIChatCompletionRequest) (map[string]interface{}, error) {
 
 
326
  // 处理消息中的图像 URL
327
  err := processMessages(c, client, cookie, openAIReq.Messages)
328
  if err != nil {
@@ -626,6 +628,11 @@ func makeDeleteRequest(client cycletls.CycleTLS, cookie, projectId string) (cycl
626
  return cycletls.Response{}, nil
627
  }
628
  }
 
 
 
 
 
629
  for _, v := range config.SessionImageChatMap {
630
  if v == projectId {
631
  return cycletls.Response{}, nil
 
323
  }
324
 
325
  func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string, openAIReq *model.OpenAIChatCompletionRequest) (map[string]interface{}, error) {
326
+ openAIReq.SystemMessagesProcess()
327
+
328
  // 处理消息中的图像 URL
329
  err := processMessages(c, client, cookie, openAIReq.Messages)
330
  if err != nil {
 
628
  return cycletls.Response{}, nil
629
  }
630
  }
631
+ for _, v := range config.GlobalSessionManager.GetChatIDsByCookie(cookie) {
632
+ if v == projectId {
633
+ return cycletls.Response{}, nil
634
+ }
635
+ }
636
  for _, v := range config.SessionImageChatMap {
637
  if v == projectId {
638
  return cycletls.Response{}, nil
middleware/ip-list.go ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package middleware
2
+
3
+ import (
4
+ "genspark2api/common/config"
5
+ "github.com/gin-gonic/gin"
6
+ "net/http"
7
+ "strings"
8
+ )
9
+
10
+ // IPBlacklistMiddleware 检查请求的IP是否在黑名单中
11
+ func IPBlacklistMiddleware() gin.HandlerFunc {
12
+ return func(c *gin.Context) {
13
+ // 获取请求的IP地址
14
+ clientIP := c.ClientIP()
15
+
16
+ // 检查IP是否在黑名单中
17
+ for _, blockedIP := range config.IpBlackList {
18
+ if strings.TrimSpace(blockedIP) == clientIP {
19
+ // 如果在黑名单中,返回403 Forbidden
20
+ c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
21
+ return
22
+ }
23
+ }
24
+
25
+ // 如果不在黑名单中,继续处理请求
26
+ c.Next()
27
+ }
28
+ }
model/openai.go CHANGED
@@ -16,6 +16,18 @@ type OpenAIChatMessage struct {
16
  Content interface{} `json:"content"`
17
  }
18
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  type OpenAIErrorResponse struct {
20
  OpenAIError OpenAIError `json:"error"`
21
  }
@@ -122,7 +134,7 @@ type OpenaiModelListResponse struct {
122
  Data []OpenaiModelResponse `json:"data"`
123
  }
124
 
125
- func (r OpenAIChatCompletionRequest) GetUserContent() []string {
126
  var userContent []string
127
 
128
  for i := len(r.Messages) - 1; i >= 0; i-- {
 
16
  Content interface{} `json:"content"`
17
  }
18
 
19
+ func (r *OpenAIChatCompletionRequest) SystemMessagesProcess() {
20
+ if r.Messages == nil {
21
+ return
22
+ }
23
+
24
+ for i := range r.Messages {
25
+ if r.Messages[i].Role == "system" {
26
+ r.Messages[i].Role = "user"
27
+ }
28
+ }
29
+ }
30
+
31
  type OpenAIErrorResponse struct {
32
  OpenAIError OpenAIError `json:"error"`
33
  }
 
134
  Data []OpenaiModelResponse `json:"data"`
135
  }
136
 
137
+ func (r *OpenAIChatCompletionRequest) GetUserContent() []string {
138
  var userContent []string
139
 
140
  for i := len(r.Messages) - 1; i >= 0; i-- {
router/api-router.go CHANGED
@@ -9,6 +9,7 @@ import (
9
  func SetApiRouter(router *gin.Engine) {
10
  router.Use(middleware.CORS())
11
  //router.Use(gzip.Gzip(gzip.DefaultCompression))
 
12
  router.Use(middleware.RequestRateLimit())
13
 
14
  router.GET("/")
 
9
  func SetApiRouter(router *gin.Engine) {
10
  router.Use(middleware.CORS())
11
  //router.Use(gzip.Gzip(gzip.DefaultCompression))
12
+ router.Use(middleware.IPBlacklistMiddleware())
13
  router.Use(middleware.RequestRateLimit())
14
 
15
  router.GET("/")