Skip to content

Commit

Permalink
Merge branch 'ChatGPTNextWeb:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Loinver authored Sep 30, 2024
2 parents f2473da + fcba50f commit d297974
Show file tree
Hide file tree
Showing 93 changed files with 2,040 additions and 280 deletions.
2 changes: 1 addition & 1 deletion .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ ANTHROPIC_API_VERSION=
ANTHROPIC_URL=

### (optional)
WHITE_WEBDEV_ENDPOINTS=
WHITE_WEBDAV_ENDPOINTS=
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"extends": "next/core-web-vitals",
"plugins": ["prettier"]
"plugins": ["prettier", "unused-imports"],
"rules": {
"unused-imports/no-unused-imports": "warn"
}
}
2 changes: 1 addition & 1 deletion .github/workflows/deploy_preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: npm install --global vercel@latest

- name: Cache dependencies
uses: actions/cache@v2
uses: actions/cache@v4
id: cache-npm
with:
path: ~/.npm
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4

一键免费部署你的跨平台私人 ChatGPT 应用, 支持 GPT3, GPT4 & Gemini Pro 模型。

[![Saas][Saas-image]][saas-url]
[![Web][Web-image]][web-url]
[![Windows][Windows-image]][download-url]
[![MacOS][MacOS-image]][download-url]
[![Linux][Linux-image]][download-url]

[Web App](https://app.nextchat.dev/) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Discord](https://discord.gg/YCkeafCafC) / [Enterprise Edition](#enterprise-edition) / [Twitter](https://twitter.com/NextChatDev)
[NextChatAI](https://nextchat.dev/chat) / [Web App](https://app.nextchat.dev) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Discord](https://discord.gg/YCkeafCafC) / [Enterprise Edition](#enterprise-edition) / [Twitter](https://twitter.com/NextChatDev)

[网页版](https://app.nextchat.dev/) / [客户端](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [反馈](https://github.com/Yidadaa/ChatGPT-Next-Web/issues)
[NextChatAI](https://nextchat.dev/chat) / [网页版](https://app.nextchat.dev) / [客户端](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [反馈](https://github.com/Yidadaa/ChatGPT-Next-Web/issues)

[saas-url]: https://nextchat.dev/chat
[saas-image]: https://img.shields.io/badge/NextChat-Saas-green?logo=microsoftedge
[web-url]: https://app.nextchat.dev/
[download-url]: https://github.com/Yidadaa/ChatGPT-Next-Web/releases
[Web-image]: https://img.shields.io/badge/Web-PWA-orange?logo=microsoftedge
Expand Down Expand Up @@ -172,7 +175,7 @@ We recommend that you follow the steps below to re-deploy:

### Enable Automatic Updates

> If you encounter a failure of Upstream Sync execution, please manually sync fork once.
> If you encounter a failure of Upstream Sync execution, please [manually update code](./README.md#manually-updating-code).
After forking the project, due to the limitations imposed by GitHub, you need to manually enable Workflows and Upstream Sync Action on the Actions page of the forked project. Once enabled, automatic updates will be scheduled every hour:

Expand Down Expand Up @@ -340,7 +343,7 @@ For ByteDance: use `modelName@bytedance=deploymentName` to customize model name

Change default model

### `WHITE_WEBDEV_ENDPOINTS` (optional)
### `WHITE_WEBDAV_ENDPOINTS` (optional)

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:
- Each address must be a complete endpoint
Expand Down
6 changes: 3 additions & 3 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

一键免费部署你的私人 ChatGPT 网页应用,支持 GPT3, GPT4 & Gemini Pro 模型。

[企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) /[演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N)
[NextChatAI](https://nextchat.dev/chat) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N)

[<img src="https://vercel.com/button" alt="Deploy on Zeabur" height="30">](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FChatGPTNextWeb%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=nextchat&repository-name=NextChat) [<img src="https://zeabur.com/button.svg" alt="Deploy on Zeabur" height="30">](https://zeabur.com/templates/ZBUEFA) [<img src="https://gitpod.io/button/open-in-gitpod.svg" alt="Open in Gitpod" height="30">](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)

Expand Down Expand Up @@ -54,7 +54,7 @@

### 打开自动更新

> 如果你遇到了 Upstream Sync 执行错误,请手动 Sync Fork 一次!
> 如果你遇到了 Upstream Sync 执行错误,[手动 Sync Fork 一次](./README_CN.md#手动更新代码)
当你 fork 项目之后,由于 Github 的限制,需要手动去你 fork 后的项目的 Actions 页面启用 Workflows,并启用 Upstream Sync Action,启用之后即可开启每小时定时自动更新:

Expand Down Expand Up @@ -202,7 +202,7 @@ ByteDance Api Url.

如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。

### `WHITE_WEBDEV_ENDPOINTS` (可选)
### `WHITE_WEBDAV_ENDPOINTS` (可选)

如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
- 每一个地址必须是一个完整的 endpoint
Expand Down
6 changes: 3 additions & 3 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

ワンクリックで無料であなた専用の ChatGPT ウェブアプリをデプロイ。GPT3、GPT4 & Gemini Pro モデルをサポート。

[企業版](#企業版) / [デモ](https://chat-gpt-next-web.vercel.app/) / [フィードバック](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Discordに参加](https://discord.gg/zrhvHCr79N)
[NextChatAI](https://nextchat.dev/chat) / [企業版](#企業版) / [デモ](https://chat-gpt-next-web.vercel.app/) / [フィードバック](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Discordに参加](https://discord.gg/zrhvHCr79N)

[<img src="https://vercel.com/button" alt="Zeaburでデプロイ" height="30">](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FChatGPTNextWeb%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=nextchat&repository-name=NextChat) [<img src="https://zeabur.com/button.svg" alt="Zeaburでデプロイ" height="30">](https://zeabur.com/templates/ZBUEFA) [<img src="https://gitpod.io/button/open-in-gitpod.svg" alt="Gitpodで開く" height="30">](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)

Expand Down Expand Up @@ -54,7 +54,7 @@

### 自動更新を開く

> Upstream Sync の実行エラーが発生した場合は、手動で Sync Fork してください!
> Upstream Sync の実行エラーが発生した場合は、[手動で Sync Fork](./README_JA.md#手動でコードを更新する) してください!
プロジェクトを fork した後、GitHub の制限により、fork 後のプロジェクトの Actions ページで Workflows を手動で有効にし、Upstream Sync Action を有効にする必要があります。有効化後、毎時の定期自動更新が可能になります:

Expand Down Expand Up @@ -193,7 +193,7 @@ ByteDance API の URL。

リンクからのプリセット設定解析を無効にしたい場合は、この環境変数を 1 に設定します。

### `WHITE_WEBDEV_ENDPOINTS` (オプション)
### `WHITE_WEBDAV_ENDPOINTS` (オプション)

アクセス許可を与える WebDAV サービスのアドレスを追加したい場合、このオプションを使用します。フォーマット要件:
- 各アドレスは完全なエンドポイントでなければなりません。
Expand Down
2 changes: 1 addition & 1 deletion app/api/[provider]/[...path]/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiPath } from "@/app/constant";
import { NextRequest, NextResponse } from "next/server";
import { NextRequest } from "next/server";
import { handle as openaiHandler } from "../../openai";
import { handle as azureHandler } from "../../azure";
import { handle as googleHandler } from "../../google";
Expand Down
2 changes: 0 additions & 2 deletions app/api/alibaba.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getServerSideConfig } from "@/app/config/server";
import {
Alibaba,
ALIBABA_BASE_URL,
ApiPath,
ModelProvider,
Expand All @@ -10,7 +9,6 @@ import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/api/auth";
import { isModelAvailableInServer } from "@/app/utils/model";
import type { RequestPayload } from "@/app/client/platforms/openai";

const serverConfig = getServerSideConfig();

Expand Down
1 change: 0 additions & 1 deletion app/api/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ANTHROPIC_BASE_URL,
Anthropic,
ApiPath,
DEFAULT_MODELS,
ServiceProvider,
ModelProvider,
} from "@/app/constant";
Expand Down
1 change: 0 additions & 1 deletion app/api/azure.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { getServerSideConfig } from "@/app/config/server";
import { ModelProvider } from "@/app/constant";
import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
Expand Down
1 change: 0 additions & 1 deletion app/api/baidu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
BAIDU_BASE_URL,
ApiPath,
ModelProvider,
BAIDU_OATUH_URL,
ServiceProvider,
} from "@/app/constant";
import { prettyObject } from "@/app/utils/format";
Expand Down
7 changes: 1 addition & 6 deletions app/api/common.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { getServerSideConfig } from "../config/server";
import {
DEFAULT_MODELS,
OPENAI_BASE_URL,
GEMINI_BASE_URL,
ServiceProvider,
} from "../constant";
import { OPENAI_BASE_URL, ServiceProvider } from "../constant";
import { isModelAvailableInServer } from "../utils/model";
import { cloudflareAIGatewayUrl } from "../utils/cloudflare";

Expand Down
17 changes: 8 additions & 9 deletions app/api/google.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from "./auth";
import { getServerSideConfig } from "@/app/config/server";
import {
ApiPath,
GEMINI_BASE_URL,
Google,
ModelProvider,
} from "@/app/constant";
import { ApiPath, GEMINI_BASE_URL, ModelProvider } from "@/app/constant";
import { prettyObject } from "@/app/utils/format";

const serverConfig = getServerSideConfig();
Expand All @@ -28,7 +23,8 @@ export async function handle(
});
}

const bearToken = req.headers.get("Authorization") ?? "";
const bearToken =
req.headers.get("x-goog-api-key") || req.headers.get("Authorization") || "";
const token = bearToken.trim().replaceAll("Bearer ", "").trim();

const apiKey = token ? token : serverConfig.googleApiKey;
Expand Down Expand Up @@ -96,15 +92,18 @@ async function request(req: NextRequest, apiKey: string) {
},
10 * 60 * 1000,
);
const fetchUrl = `${baseUrl}${path}?key=${apiKey}${
req?.nextUrl?.searchParams?.get("alt") === "sse" ? "&alt=sse" : ""
const fetchUrl = `${baseUrl}${path}${
req?.nextUrl?.searchParams?.get("alt") === "sse" ? "?alt=sse" : ""
}`;

console.log("[Fetch Url] ", fetchUrl);
const fetchOptions: RequestInit = {
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-store",
"x-goog-api-key":
req.headers.get("x-goog-api-key") ||
(req.headers.get("Authorization") ?? "").replace("Bearer ", ""),
},
method: req.method,
body: req.body,
Expand Down
2 changes: 0 additions & 2 deletions app/api/iflytek.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getServerSideConfig } from "@/app/config/server";
import {
Iflytek,
IFLYTEK_BASE_URL,
ApiPath,
ModelProvider,
Expand All @@ -10,7 +9,6 @@ import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/api/auth";
import { isModelAvailableInServer } from "@/app/utils/model";
import type { RequestPayload } from "@/app/client/platforms/openai";
// iflytek

const serverConfig = getServerSideConfig();
Expand Down
2 changes: 0 additions & 2 deletions app/api/moonshot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getServerSideConfig } from "@/app/config/server";
import {
Moonshot,
MOONSHOT_BASE_URL,
ApiPath,
ModelProvider,
Expand All @@ -10,7 +9,6 @@ import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/api/auth";
import { isModelAvailableInServer } from "@/app/utils/model";
import type { RequestPayload } from "@/app/client/platforms/openai";

const serverConfig = getServerSideConfig();

Expand Down
9 changes: 1 addition & 8 deletions app/api/tencent/route.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import { getServerSideConfig } from "@/app/config/server";
import {
TENCENT_BASE_URL,
ApiPath,
ModelProvider,
ServiceProvider,
Tencent,
} from "@/app/constant";
import { TENCENT_BASE_URL, ModelProvider } from "@/app/constant";
import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/api/auth";
import { isModelAvailableInServer } from "@/app/utils/model";
import { getHeader } from "@/app/utils/tencent";

const serverConfig = getServerSideConfig();
Expand Down
2 changes: 1 addition & 1 deletion app/api/webdav/[...path]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const config = getServerSideConfig();

const mergedAllowedWebDavEndpoints = [
...internalAllowedWebDavEndpoints,
...config.allowedWebDevEndpoints,
...config.allowedWebDavEndpoints,
].filter((domain) => Boolean(domain.trim()));

const normalizeUrl = (url: string) => {
Expand Down
40 changes: 30 additions & 10 deletions app/client/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { getClientConfig } from "../config/client";
import {
ACCESS_CODE_PREFIX,
Azure,
ModelProvider,
ServiceProvider,
} from "../constant";
Expand All @@ -26,6 +25,7 @@ export const ROLES = ["system", "user", "assistant"] as const;
export type MessageRole = (typeof ROLES)[number];

export const Models = ["gpt-3.5-turbo", "gpt-4"] as const;
export const TTSModels = ["tts-1", "tts-1-hd"] as const;
export type ChatModel = ModelType;

export interface MultimodalContent {
Expand Down Expand Up @@ -54,6 +54,15 @@ export interface LLMConfig {
style?: DalleRequestPayload["style"];
}

export interface SpeechOptions {
model: string;
input: string;
voice: string;
response_format?: string;
speed?: number;
onController?: (controller: AbortController) => void;
}

export interface ChatOptions {
messages: RequestMessage[];
config: LLMConfig;
Expand Down Expand Up @@ -88,6 +97,7 @@ export interface LLMModelProvider {

export abstract class LLMApi {
abstract chat(options: ChatOptions): Promise<void>;
abstract speech(options: SpeechOptions): Promise<ArrayBuffer>;
abstract usage(): Promise<LLMUsage>;
abstract models(): Promise<LLMModel[]>;
}
Expand Down Expand Up @@ -206,13 +216,16 @@ export function validString(x: string): boolean {
return x?.length > 0;
}

export function getHeaders() {
export function getHeaders(ignoreHeaders: boolean = false) {
const accessStore = useAccessStore.getState();
const chatStore = useChatStore.getState();
const headers: Record<string, string> = {
"Content-Type": "application/json",
Accept: "application/json",
};
let headers: Record<string, string> = {};
if (!ignoreHeaders) {
headers = {
"Content-Type": "application/json",
Accept: "application/json",
};
}

const clientConfig = getClientConfig();

Expand Down Expand Up @@ -259,7 +272,13 @@ export function getHeaders() {
}

function getAuthHeader(): string {
return isAzure ? "api-key" : isAnthropic ? "x-api-key" : "Authorization";
return isAzure
? "api-key"
: isAnthropic
? "x-api-key"
: isGoogle
? "x-goog-api-key"
: "Authorization";
}

const {
Expand All @@ -270,14 +289,15 @@ export function getHeaders() {
apiKey,
isEnabledAccessControl,
} = getConfig();
// when using google api in app, not set auth header
if (isGoogle && clientConfig?.isApp) return headers;
// when using baidu api in app, not set auth header
if (isBaidu && clientConfig?.isApp) return headers;

const authHeader = getAuthHeader();

const bearerToken = getBearerToken(apiKey, isAzure || isAnthropic);
const bearerToken = getBearerToken(
apiKey,
isAzure || isAnthropic || isGoogle,
);

if (bearerToken) {
headers[authHeader] = bearerToken;
Expand Down
5 changes: 5 additions & 0 deletions app/client/platforms/alibaba.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getHeaders,
LLMApi,
LLMModel,
SpeechOptions,
MultimodalContent,
} from "../api";
import Locale from "../../locales";
Expand Down Expand Up @@ -83,6 +84,10 @@ export class QwenApi implements LLMApi {
return res?.output?.choices?.at(0)?.message?.content ?? "";
}

speech(options: SpeechOptions): Promise<ArrayBuffer> {
throw new Error("Method not implemented.");
}

async chat(options: ChatOptions) {
const messages = options.messages.map((v) => ({
role: v.role,
Expand Down
Loading

0 comments on commit d297974

Please sign in to comment.