Skip to content

Commit d957397

Browse files
committed
Merge remote-tracking branch 'origin/main' into website
2 parents cd354cf + b9d1dca commit d957397

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2838
-457
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ dev
4343
.env
4444

4545
*.key
46-
*.key.pub
46+
*.key.pub

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ COPY --from=builder /app/.next/server ./.next/server
4343
EXPOSE 3000
4444

4545
CMD if [ -n "$PROXY_URL" ]; then \
46-
export HOSTNAME="127.0.0.1"; \
46+
export HOSTNAME="0.0.0.0"; \
4747
protocol=$(echo $PROXY_URL | cut -d: -f1); \
4848
host=$(echo $PROXY_URL | cut -d/ -f3 | cut -d: -f1); \
4949
port=$(echo $PROXY_URL | cut -d: -f3); \

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 Zhang Yifei
3+
Copyright (c) 2023-2024 Zhang Yifei
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4
1818

1919
[网页版](https://app.nextchat.dev/) / [客户端](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [反馈](https://github.com/Yidadaa/ChatGPT-Next-Web/issues)
2020

21-
[web-url]: https://chatgpt.nextweb.fun
21+
[web-url]: https://app.nextchat.dev/
2222
[download-url]: https://github.com/Yidadaa/ChatGPT-Next-Web/releases
2323
[Web-image]: https://img.shields.io/badge/Web-PWA-orange?logo=microsoftedge
2424
[Windows-image]: https://img.shields.io/badge/-Windows-blue?logo=windows
@@ -181,6 +181,7 @@ Specify OpenAI organization ID.
181181
### `AZURE_URL` (optional)
182182

183183
> Example: https://{azure-resource-url}/openai/deployments/{deploy-name}
184+
> if you config deployment name in `CUSTOM_MODELS`, you can remove `{deploy-name}` in `AZURE_URL`
184185
185186
Azure deploy url.
186187

@@ -212,6 +213,34 @@ anthropic claude Api version.
212213

213214
anthropic claude Api Url.
214215

216+
### `BAIDU_API_KEY` (optional)
217+
218+
Baidu Api Key.
219+
220+
### `BAIDU_SECRET_KEY` (optional)
221+
222+
Baidu Secret Key.
223+
224+
### `BAIDU_URL` (optional)
225+
226+
Baidu Api Url.
227+
228+
### `BYTEDANCE_API_KEY` (optional)
229+
230+
ByteDance Api Key.
231+
232+
### `BYTEDANCE_URL` (optional)
233+
234+
ByteDance Api Url.
235+
236+
### `ALIBABA_API_KEY` (optional)
237+
238+
Alibaba Cloud Api Key.
239+
240+
### `ALIBABA_URL` (optional)
241+
242+
Alibaba Cloud Api Url.
243+
215244
### `HIDE_USER_API_KEY` (optional)
216245

217246
> Default: Empty
@@ -245,13 +274,27 @@ To control custom models, use `+` to add a custom model, use `-` to hide a model
245274

246275
User `-all` to disable all default models, `+all` to enable all default models.
247276

248-
### `WHITE_WEBDEV_ENDPOINTS` (可选)
277+
For Azure: use `modelName@azure=deploymentName` to customize model name and deployment name.
278+
> Example: `+gpt-3.5-turbo@azure=gpt35` will show option `gpt35(Azure)` in model list.
279+
280+
For ByteDance: use `modelName@bytedance=deploymentName` to customize model name and deployment name.
281+
> Example: `+Doubao-lite-4k@bytedance=ep-xxxxx-xxx` will show option `Doubao-lite-4k(ByteDance)` in model list.
282+
283+
### `DEFAULT_MODEL` (optional)
284+
285+
Change default model
286+
287+
### `WHITE_WEBDEV_ENDPOINTS` (optional)
249288

250289
You can use this option if you want to increase the number of webdav service addresses you are allowed to access, as required by the format:
251290
- Each address must be a complete endpoint
252291
> `https://xxxx/yyy`
253292
- Multiple addresses are connected by ', '
254293

294+
### `DEFAULT_INPUT_TEMPLATE` (optional)
295+
296+
Customize the default template used to initialize the User Input Preprocessing configuration item in Settings.
297+
255298
## Requirements
256299

257300
NodeJS >= 18, Docker >= 20

README_CN.md

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ OpenAI 接口代理 URL,如果你手动配置了 openai 接口代理,请填
9595
### `AZURE_URL` (可选)
9696

9797
> 形如:https://{azure-resource-url}/openai/deployments/{deploy-name}
98+
> 如果你已经在`CUSTOM_MODELS`中参考`displayName`的方式配置了{deploy-name},那么可以从`AZURE_URL`中移除`{deploy-name}`
9899
99100
Azure 部署地址。
100101

@@ -106,26 +107,54 @@ Azure 密钥。
106107

107108
Azure Api 版本,你可以在这里找到:[Azure 文档](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions)
108109

109-
### `GOOGLE_API_KEY` (optional)
110+
### `GOOGLE_API_KEY` (可选)
110111

111112
Google Gemini Pro 密钥.
112113

113-
### `GOOGLE_URL` (optional)
114+
### `GOOGLE_URL` (可选)
114115

115116
Google Gemini Pro Api Url.
116117

117-
### `ANTHROPIC_API_KEY` (optional)
118+
### `ANTHROPIC_API_KEY` (可选)
118119

119120
anthropic claude Api Key.
120121

121-
### `ANTHROPIC_API_VERSION` (optional)
122+
### `ANTHROPIC_API_VERSION` (可选)
122123

123124
anthropic claude Api version.
124125

125-
### `ANTHROPIC_URL` (optional)
126+
### `ANTHROPIC_URL` (可选)
126127

127128
anthropic claude Api Url.
128129

130+
### `BAIDU_API_KEY` (可选)
131+
132+
Baidu Api Key.
133+
134+
### `BAIDU_SECRET_KEY` (可选)
135+
136+
Baidu Secret Key.
137+
138+
### `BAIDU_URL` (可选)
139+
140+
Baidu Api Url.
141+
142+
### `BYTEDANCE_API_KEY` (可选)
143+
144+
ByteDance Api Key.
145+
146+
### `BYTEDANCE_URL` (可选)
147+
148+
ByteDance Api Url.
149+
150+
### `ALIBABA_API_KEY` (可选)
151+
152+
阿里云(千问)Api Key.
153+
154+
### `ALIBABA_URL` (可选)
155+
156+
阿里云(千问)Api Url.
157+
129158
### `HIDE_USER_API_KEY` (可选)
130159

131160
如果你不想让用户自行填入 API Key,将此环境变量设置为 1 即可。
@@ -156,6 +185,21 @@ anthropic claude Api Url.
156185
157186
用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。
158187

188+
在Azure的模式下,支持使用`modelName@azure=deploymentName`的方式配置模型名称和部署名称(deploy-name)
189+
> 示例:`+gpt-3.5-turbo@azure=gpt35`这个配置会在模型列表显示一个`gpt35(Azure)`的选项
190+
191+
在ByteDance的模式下,支持使用`modelName@bytedance=deploymentName`的方式配置模型名称和部署名称(deploy-name)
192+
> 示例: `+Doubao-lite-4k@bytedance=ep-xxxxx-xxx`这个配置会在模型列表显示一个`Doubao-lite-4k(ByteDance)`的选项
193+
194+
195+
### `DEFAULT_MODEL` (可选)
196+
197+
更改默认模型
198+
199+
### `DEFAULT_INPUT_TEMPLATE` (可选)
200+
201+
自定义默认的 template,用于初始化『设置』中的『用户输入预处理』配置项
202+
159203
## 开发
160204

161205
点击下方按钮,开始二次开发:

app/api/alibaba/[...path]/route.ts

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { getServerSideConfig } from "@/app/config/server";
2+
import {
3+
Alibaba,
4+
ALIBABA_BASE_URL,
5+
ApiPath,
6+
ModelProvider,
7+
ServiceProvider,
8+
} from "@/app/constant";
9+
import { prettyObject } from "@/app/utils/format";
10+
import { NextRequest, NextResponse } from "next/server";
11+
import { auth } from "@/app/api/auth";
12+
import { isModelAvailableInServer } from "@/app/utils/model";
13+
import type { RequestPayload } from "@/app/client/platforms/openai";
14+
15+
const serverConfig = getServerSideConfig();
16+
17+
async function handle(
18+
req: NextRequest,
19+
{ params }: { params: { path: string[] } },
20+
) {
21+
console.log("[Alibaba Route] params ", params);
22+
23+
if (req.method === "OPTIONS") {
24+
return NextResponse.json({ body: "OK" }, { status: 200 });
25+
}
26+
27+
const authResult = auth(req, ModelProvider.Qwen);
28+
if (authResult.error) {
29+
return NextResponse.json(authResult, {
30+
status: 401,
31+
});
32+
}
33+
34+
try {
35+
const response = await request(req);
36+
return response;
37+
} catch (e) {
38+
console.error("[Alibaba] ", e);
39+
return NextResponse.json(prettyObject(e));
40+
}
41+
}
42+
43+
export const GET = handle;
44+
export const POST = handle;
45+
46+
export const runtime = "edge";
47+
export const preferredRegion = [
48+
"arn1",
49+
"bom1",
50+
"cdg1",
51+
"cle1",
52+
"cpt1",
53+
"dub1",
54+
"fra1",
55+
"gru1",
56+
"hnd1",
57+
"iad1",
58+
"icn1",
59+
"kix1",
60+
"lhr1",
61+
"pdx1",
62+
"sfo1",
63+
"sin1",
64+
"syd1",
65+
];
66+
67+
async function request(req: NextRequest) {
68+
const controller = new AbortController();
69+
70+
// alibaba use base url or just remove the path
71+
let path = `${req.nextUrl.pathname}`.replaceAll(ApiPath.Alibaba, "");
72+
73+
let baseUrl = serverConfig.alibabaUrl || ALIBABA_BASE_URL;
74+
75+
if (!baseUrl.startsWith("http")) {
76+
baseUrl = `https://${baseUrl}`;
77+
}
78+
79+
if (baseUrl.endsWith("/")) {
80+
baseUrl = baseUrl.slice(0, -1);
81+
}
82+
83+
console.log("[Proxy] ", path);
84+
console.log("[Base Url]", baseUrl);
85+
86+
const timeoutId = setTimeout(
87+
() => {
88+
controller.abort();
89+
},
90+
10 * 60 * 1000,
91+
);
92+
93+
const fetchUrl = `${baseUrl}${path}`;
94+
const fetchOptions: RequestInit = {
95+
headers: {
96+
"Content-Type": "application/json",
97+
Authorization: req.headers.get("Authorization") ?? "",
98+
"X-DashScope-SSE": req.headers.get("X-DashScope-SSE") ?? "disable",
99+
},
100+
method: req.method,
101+
body: req.body,
102+
redirect: "manual",
103+
// @ts-ignore
104+
duplex: "half",
105+
signal: controller.signal,
106+
};
107+
108+
// #1815 try to refuse some request to some models
109+
if (serverConfig.customModels && req.body) {
110+
try {
111+
const clonedBody = await req.text();
112+
fetchOptions.body = clonedBody;
113+
114+
const jsonBody = JSON.parse(clonedBody) as { model?: string };
115+
116+
// not undefined and is false
117+
if (
118+
isModelAvailableInServer(
119+
serverConfig.customModels,
120+
jsonBody?.model as string,
121+
ServiceProvider.Alibaba as string,
122+
)
123+
) {
124+
return NextResponse.json(
125+
{
126+
error: true,
127+
message: `you are not allowed to use ${jsonBody?.model} model`,
128+
},
129+
{
130+
status: 403,
131+
},
132+
);
133+
}
134+
} catch (e) {
135+
console.error(`[Alibaba] filter`, e);
136+
}
137+
}
138+
try {
139+
const res = await fetch(fetchUrl, fetchOptions);
140+
141+
// to prevent browser prompt for credentials
142+
const newHeaders = new Headers(res.headers);
143+
newHeaders.delete("www-authenticate");
144+
// to disable nginx buffering
145+
newHeaders.set("X-Accel-Buffering", "no");
146+
147+
return new Response(res.body, {
148+
status: res.status,
149+
statusText: res.statusText,
150+
headers: newHeaders,
151+
});
152+
} finally {
153+
clearTimeout(timeoutId);
154+
}
155+
}

0 commit comments

Comments
 (0)