From a433d1606cc9f24cec7f7cc0a947e416373a5d7b Mon Sep 17 00:00:00 2001 From: Yiming Zhang Date: Tue, 10 Dec 2024 00:22:45 -0500 Subject: [PATCH 01/13] feat: use regex patterns for vision models and allow adding capabilities to models through env var NEXT_PUBLIC_VISION_MODELS. --- app/constant.ts | 15 +++++++++++++++ app/utils.ts | 29 +++++++++-------------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/app/constant.ts b/app/constant.ts index 25c8d98ea..fe38fb1fe 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -291,6 +291,21 @@ export const DEFAULT_TTS_VOICES = [ "shimmer", ]; +export const VISION_MODEL_REGEXES = [ + /vision/, + /gpt-4o/, + /claude-3/, + /gemini-1\.5/, + /gemini-exp/, + /learnlm/, + /qwen-vl/, + /qwen2-vl/, + /gpt-4-turbo(?!.*preview)/, // Matches "gpt-4-turbo" but not "gpt-4-turbo-preview" + /^dall-e-3$/, // Matches exactly "dall-e-3" +]; + +export const EXCLUDE_VISION_MODEL_REGEXES = [/claude-3-5-haiku-20241022/]; + const openaiModels = [ "gpt-3.5-turbo", "gpt-3.5-turbo-1106", diff --git a/app/utils.ts b/app/utils.ts index b62bc126d..fafbc9e79 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -5,6 +5,7 @@ import { RequestMessage } from "./client/api"; import { ServiceProvider } from "./constant"; // import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; import { fetch as tauriStreamFetch } from "./utils/stream"; +import { VISION_MODEL_REGEXES, EXCLUDE_VISION_MODEL_REGEXES } from "./constant"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -252,27 +253,15 @@ export function getMessageImages(message: RequestMessage): string[] { } export function isVisionModel(model: string) { - // Note: This is a better way using the TypeScript feature instead of `&&` or `||` (ts v5.5.0-dev.20240314 I've been using) - - const excludeKeywords = ["claude-3-5-haiku-20241022"]; - const visionKeywords = [ - "vision", - "gpt-4o", - "claude-3", - "gemini-1.5", - "gemini-exp", - "learnlm", - "qwen-vl", - "qwen2-vl", - ]; - const isGpt4Turbo = - model.includes("gpt-4-turbo") && !model.includes("preview"); - + const envVisionModels = process.env.NEXT_PUBLIC_VISION_MODELS?.split(",").map( + (m) => m.trim(), + ); + if (envVisionModels?.includes(model)) { + return true; + } return ( - !excludeKeywords.some((keyword) => model.includes(keyword)) && - (visionKeywords.some((keyword) => model.includes(keyword)) || - isGpt4Turbo || - isDalle3(model)) + !EXCLUDE_VISION_MODEL_REGEXES.some((regex) => regex.test(model)) && + VISION_MODEL_REGEXES.some((regex) => regex.test(model)) ); } From e27e8fb0e16ee61865d11606682f2c4cbd075e73 Mon Sep 17 00:00:00 2001 From: "Nacho.L" <112751823+fengzai6@users.noreply.github.com> Date: Fri, 13 Dec 2024 07:22:16 +0800 Subject: [PATCH 02/13] Update google models --- app/constant.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/constant.ts b/app/constant.ts index 25c8d98ea..429d52b3d 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -317,13 +317,14 @@ const openaiModels = [ ]; const googleModels = [ - "gemini-1.0-pro", + "gemini-1.0-pro", // Deprecated on 2/15/2025 "gemini-1.5-pro-latest", "gemini-1.5-flash-latest", + "gemini-1.5-flash-8b-latest", "gemini-exp-1114", "gemini-exp-1121", "learnlm-1.5-pro-experimental", - "gemini-pro-vision", + "gemini-2.0-flash-exp", ]; const anthropicModels = [ From 46a0b100f73058d651b884341b43e126e2c04a00 Mon Sep 17 00:00:00 2001 From: "Nacho.L" <112751823+fengzai6@users.noreply.github.com> Date: Fri, 13 Dec 2024 08:29:43 +0800 Subject: [PATCH 03/13] Update versionKeywords --- app/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/utils.ts b/app/utils.ts index b62bc126d..30f95fa02 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -261,6 +261,7 @@ export function isVisionModel(model: string) { "claude-3", "gemini-1.5", "gemini-exp", + "gemini-2.0", "learnlm", "qwen-vl", "qwen2-vl", From e939ce5a027150d2481508691e1c4f818a4f9130 Mon Sep 17 00:00:00 2001 From: InitialXKO <45725592+InitialXKO@users.noreply.github.com> Date: Fri, 13 Dec 2024 22:29:14 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E9=9D=A2=E5=85=B7=E2=80=9C=E4=BB=A5?= =?UTF-8?q?=E6=96=87=E6=90=9C=E5=9B=BE=E2=80=9D=E6=94=B9=E6=88=90=E2=80=9C?= =?UTF-8?q?AI=E6=96=87=E7=94=9F=E5=9B=BE=E2=80=9D=EF=BC=8C=E5=BE=AE?= =?UTF-8?q?=E8=B0=83=E6=8F=90=E7=A4=BA=E8=AE=A9=E5=9B=BE=E7=89=87=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=9B=B4=E7=A8=B3=E5=AE=9A=E6=97=A0=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/masks/cn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/masks/cn.ts b/app/masks/cn.ts index ed507d734..64842f6e8 100644 --- a/app/masks/cn.ts +++ b/app/masks/cn.ts @@ -3,7 +3,7 @@ import { BuiltinMask } from "./typing"; export const CN_MASKS: BuiltinMask[] = [ { avatar: "1f5bc-fe0f", - name: "以文搜图", + name: "AI文生图", context: [ { id: "text-to-pic-0", @@ -28,7 +28,7 @@ export const CN_MASKS: BuiltinMask[] = [ id: "text-to-pic-3", role: "system", content: - "助手善于判断用户意图,当确定需要提供图片时,助手会变得沉默寡言,只使用以下格式输出markdown图片:![描述](https://image.pollinations.ai/prompt/描述),因为这个语法可以自动按照提示生成并渲染图片。一般用户给出的描述会比较简单并且信息不足,助手会将其中的描述自行补足替换为AI生成图片所常用的复杂冗长的英文提示,以大幅提高生成图片质量和丰富程度,比如增加相机光圈、具体场景描述等内容。助手会避免用代码块或原始块包围markdown标记,因为那样只会渲染出代码块或原始块而不是图片。", + "助手善于判断用户意图,当确定需要提供图片时,助手会变得沉默寡言,只使用以下格式输出markdown图片:![description](https://image.pollinations.ai/prompt/description?nologo=true),因为这个语法可以自动按照提示生成并渲染图片。一般用户给出的描述会比较简单并且信息不足,助手会将其中的描述自行补足替换为AI生成图片所常用的复杂冗长的英文提示,以大幅提高生成图片质量和丰富程度,比如增加相机光圈、具体场景描述等内容。助手会避免用代码块或原始块包围markdown标记,因为那样只会渲染出代码块或原始块而不是图片。url中的空格等符号需要转义。", date: "", }, ], From acdded8161860def9fe0f3806798bcdc57754644 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:57:34 +0000 Subject: [PATCH 05/13] chore(deps-dev): bump @testing-library/react from 16.0.1 to 16.1.0 Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 16.0.1 to 16.1.0. - [Release notes](https://github.com/testing-library/react-testing-library/releases) - [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/react-testing-library/compare/v16.0.1...v16.1.0) --- updated-dependencies: - dependency-name: "@testing-library/react" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f7b544bb2..e081567a4 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@tauri-apps/cli": "1.5.11", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.0.1", + "@testing-library/react": "^16.1.0", "@types/jest": "^29.5.14", "@types/js-yaml": "4.0.9", "@types/lodash-es": "^4.17.12", diff --git a/yarn.lock b/yarn.lock index ff257a3ef..dffc35e9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2127,10 +2127,10 @@ lodash "^4.17.21" redent "^3.0.0" -"@testing-library/react@^16.0.1": - version "16.0.1" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.1.tgz#29c0ee878d672703f5e7579f239005e4e0faa875" - integrity sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg== +"@testing-library/react@^16.1.0": + version "16.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.1.0.tgz#aa0c61398bac82eaf89776967e97de41ac742d71" + integrity sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg== dependencies: "@babel/runtime" "^7.12.5" From 0a056a7c5c0be993321174706d8b679e7ffde038 Mon Sep 17 00:00:00 2001 From: dupl Date: Sat, 21 Dec 2024 08:00:37 +0800 Subject: [PATCH 06/13] add gemini-exp-1206, gemini-2.0-flash-thinking-exp-1219 --- app/constant.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/constant.ts b/app/constant.ts index 429d52b3d..28700cb14 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -325,6 +325,15 @@ const googleModels = [ "gemini-exp-1121", "learnlm-1.5-pro-experimental", "gemini-2.0-flash-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-flash-8b", + "gemini-1.5-flash-exp-0827", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.5-pro-exp-0827", + "gemini-2.0-flash-thinking-exp-1219", + "gemini-exp-1206", ]; const anthropicModels = [ From ed8c3580c8fce9c12c42e2a8ac086ea2f8887953 Mon Sep 17 00:00:00 2001 From: Yiming Zhang Date: Fri, 20 Dec 2024 19:07:00 -0500 Subject: [PATCH 07/13] test: add unit tests for isVisionModel utility function --- test/vision-model-checker.test.ts | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/vision-model-checker.test.ts diff --git a/test/vision-model-checker.test.ts b/test/vision-model-checker.test.ts new file mode 100644 index 000000000..842ef644a --- /dev/null +++ b/test/vision-model-checker.test.ts @@ -0,0 +1,67 @@ +import { isVisionModel } from "../app/utils"; + +describe("isVisionModel", () => { + const originalEnv = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...originalEnv }; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + test("should identify vision models using regex patterns", () => { + const visionModels = [ + "gpt-4-vision", + "claude-3-opus", + "gemini-1.5-pro", + "gemini-2.0", + "gemini-exp-vision", + "learnlm-vision", + "qwen-vl-max", + "qwen2-vl-max", + "gpt-4-turbo", + "dall-e-3", + ]; + + visionModels.forEach((model) => { + expect(isVisionModel(model)).toBe(true); + }); + }); + + test("should exclude specific models", () => { + expect(isVisionModel("claude-3-5-haiku-20241022")).toBe(false); + }); + + test("should not identify non-vision models", () => { + const nonVisionModels = [ + "gpt-3.5-turbo", + "gpt-4-turbo-preview", + "claude-2", + "regular-model", + ]; + + nonVisionModels.forEach((model) => { + expect(isVisionModel(model)).toBe(false); + }); + }); + + test("should identify models from NEXT_PUBLIC_VISION_MODELS env var", () => { + process.env.NEXT_PUBLIC_VISION_MODELS = "custom-vision-model,another-vision-model"; + + expect(isVisionModel("custom-vision-model")).toBe(true); + expect(isVisionModel("another-vision-model")).toBe(true); + expect(isVisionModel("unrelated-model")).toBe(false); + }); + + test("should handle empty or missing NEXT_PUBLIC_VISION_MODELS", () => { + process.env.NEXT_PUBLIC_VISION_MODELS = ""; + expect(isVisionModel("unrelated-model")).toBe(false); + + delete process.env.NEXT_PUBLIC_VISION_MODELS; + expect(isVisionModel("unrelated-model")).toBe(false); + expect(isVisionModel("gpt-4-vision")).toBe(true); + }); +}); \ No newline at end of file From 93ac0e501737f8e01d046a367d0aeb0055c15633 Mon Sep 17 00:00:00 2001 From: dupl <67990457+dupl@users.noreply.github.com> Date: Sat, 21 Dec 2024 15:26:33 +0800 Subject: [PATCH 08/13] Reorganized the Gemini model --- app/constant.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/constant.ts b/app/constant.ts index 28700cb14..aa01c56e1 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -319,21 +319,21 @@ const openaiModels = [ const googleModels = [ "gemini-1.0-pro", // Deprecated on 2/15/2025 "gemini-1.5-pro-latest", - "gemini-1.5-flash-latest", - "gemini-1.5-flash-8b-latest", - "gemini-exp-1114", - "gemini-exp-1121", - "learnlm-1.5-pro-experimental", - "gemini-2.0-flash-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-flash-8b", - "gemini-1.5-flash-exp-0827", "gemini-1.5-pro", "gemini-1.5-pro-002", "gemini-1.5-pro-exp-0827", - "gemini-2.0-flash-thinking-exp-1219", + "gemini-1.5-flash-latest", + "gemini-1.5-flash-8b-latest", + "gemini-1.5-flash", + "gemini-1.5-flash-8b", + "gemini-1.5-flash-002", + "gemini-1.5-flash-exp-0827", + "learnlm-1.5-pro-experimental", + "gemini-exp-1114", + "gemini-exp-1121", "gemini-exp-1206", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-thinking-exp-1219", ]; const anthropicModels = [ From 210b29bfbecaebc53c4f37ed23c5df28d28d41fb Mon Sep 17 00:00:00 2001 From: Yiming Zhang Date: Sat, 21 Dec 2024 03:51:54 -0500 Subject: [PATCH 09/13] refactor: remove NEXT_PUBLIC_ prefix from VISION_MODELS env var --- app/config/build.ts | 1 + app/utils.ts | 8 +++++--- test/vision-model-checker.test.ts | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/config/build.ts b/app/config/build.ts index b2b1ad49d..aa7c10729 100644 --- a/app/config/build.ts +++ b/app/config/build.ts @@ -40,6 +40,7 @@ export const getBuildConfig = () => { buildMode, isApp, template: process.env.DEFAULT_INPUT_TEMPLATE ?? DEFAULT_INPUT_TEMPLATE, + visionModels: process.env.VISION_MODELS || "", }; }; diff --git a/app/utils.ts b/app/utils.ts index fafbc9e79..f49f1a466 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -6,6 +6,7 @@ import { ServiceProvider } from "./constant"; // import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; import { fetch as tauriStreamFetch } from "./utils/stream"; import { VISION_MODEL_REGEXES, EXCLUDE_VISION_MODEL_REGEXES } from "./constant"; +import { getClientConfig } from "./config/client"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -253,9 +254,10 @@ export function getMessageImages(message: RequestMessage): string[] { } export function isVisionModel(model: string) { - const envVisionModels = process.env.NEXT_PUBLIC_VISION_MODELS?.split(",").map( - (m) => m.trim(), - ); + const clientConfig = getClientConfig(); + const envVisionModels = clientConfig.visionModels + ?.split(",") + .map((m) => m.trim()); if (envVisionModels?.includes(model)) { return true; } diff --git a/test/vision-model-checker.test.ts b/test/vision-model-checker.test.ts index 842ef644a..734e992d8 100644 --- a/test/vision-model-checker.test.ts +++ b/test/vision-model-checker.test.ts @@ -48,19 +48,19 @@ describe("isVisionModel", () => { }); }); - test("should identify models from NEXT_PUBLIC_VISION_MODELS env var", () => { - process.env.NEXT_PUBLIC_VISION_MODELS = "custom-vision-model,another-vision-model"; + test("should identify models from VISION_MODELS env var", () => { + process.env.VISION_MODELS = "custom-vision-model,another-vision-model"; expect(isVisionModel("custom-vision-model")).toBe(true); expect(isVisionModel("another-vision-model")).toBe(true); expect(isVisionModel("unrelated-model")).toBe(false); }); - test("should handle empty or missing NEXT_PUBLIC_VISION_MODELS", () => { - process.env.NEXT_PUBLIC_VISION_MODELS = ""; + test("should handle empty or missing VISION_MODELS", () => { + process.env.VISION_MODELS = ""; expect(isVisionModel("unrelated-model")).toBe(false); - delete process.env.NEXT_PUBLIC_VISION_MODELS; + delete process.env.VISION_MODELS; expect(isVisionModel("unrelated-model")).toBe(false); expect(isVisionModel("gpt-4-vision")).toBe(true); }); From ea1329f73e516546dab7193425e1e7dfdd232eb6 Mon Sep 17 00:00:00 2001 From: Yiming Zhang Date: Sat, 21 Dec 2024 04:07:58 -0500 Subject: [PATCH 10/13] fix: add optional chaining to prevent errors when accessing visionModels --- app/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utils.ts b/app/utils.ts index f49f1a466..962e68a10 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -255,7 +255,7 @@ export function getMessageImages(message: RequestMessage): string[] { export function isVisionModel(model: string) { const clientConfig = getClientConfig(); - const envVisionModels = clientConfig.visionModels + const envVisionModels = clientConfig?.visionModels ?.split(",") .map((m) => m.trim()); if (envVisionModels?.includes(model)) { From a127ae1fb45d641b9f138057e56a10ece96b2964 Mon Sep 17 00:00:00 2001 From: Yiming Zhang Date: Sat, 21 Dec 2024 13:12:41 -0500 Subject: [PATCH 11/13] docs: add VISION_MODELS section to README files --- README.md | 7 +++++++ README_CN.md | 7 +++++++ README_JA.md | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/README.md b/README.md index 0c06b73f0..79e041f3d 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,13 @@ For ByteDance: use `modelName@bytedance=deploymentName` to customize model name Change default model +### `VISION_MODELS` (optional) + +> Default: Empty +> Example: `gpt-4-vision,claude-3-opus,my-custom-model` means add vision capabilities to these models in addition to the default pattern matches (which detect models containing keywords like "vision", "claude-3", "gemini-1.5", etc). + +Add additional models to have vision capabilities, beyond the default pattern matching. Multiple models should be separated by commas. + ### `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: diff --git a/README_CN.md b/README_CN.md index d4da8b9da..8173b9c4d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -235,6 +235,13 @@ ChatGLM Api Url. 更改默认模型 +### `VISION_MODELS` (可选) + +> 默认值:空 +> 示例:`gpt-4-vision,claude-3-opus,my-custom-model` 表示为这些模型添加视觉能力,作为对默认模式匹配的补充(默认会检测包含"vision"、"claude-3"、"gemini-1.5"等关键词的模型)。 + +在默认模式匹配之外,添加更多具有视觉能力的模型。多个模型用逗号分隔。 + ### `DEFAULT_INPUT_TEMPLATE` (可选) 自定义默认的 template,用于初始化『设置』中的『用户输入预处理』配置项 diff --git a/README_JA.md b/README_JA.md index 062c11262..29eb0d275 100644 --- a/README_JA.md +++ b/README_JA.md @@ -217,6 +217,13 @@ ByteDance モードでは、`modelName@bytedance=deploymentName` 形式でモデ デフォルトのモデルを変更します。 +### `VISION_MODELS` (オプション) + +> デフォルト:空 +> 例:`gpt-4-vision,claude-3-opus,my-custom-model` は、これらのモデルにビジョン機能を追加します。これはデフォルトのパターンマッチング("vision"、"claude-3"、"gemini-1.5"などのキーワードを含むモデルを検出)に加えて適用されます。 + +デフォルトのパターンマッチングに加えて、追加のモデルにビジョン機能を付与します。複数のモデルはカンマで区切ります。 + ### `DEFAULT_INPUT_TEMPLATE` (オプション) 『設定』の『ユーザー入力前処理』の初期設定に使用するテンプレートをカスタマイズします。 From 3c859fc29fc11ac9c229ed024d2d25366b8d2d99 Mon Sep 17 00:00:00 2001 From: RiverRay Date: Mon, 23 Dec 2024 22:47:16 +0800 Subject: [PATCH 12/13] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 79e041f3d..9168480c5 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@
- - icon + + icon +

NextChat (ChatGPT Next Web)

English / [简体中文](./README_CN.md) -One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4 & Gemini Pro support. +One-Click to get a well-designed cross-platform ChatGPT web UI, with Claude, GPT4 & Gemini Pro support. -一键免费部署你的跨平台私人 ChatGPT 应用, 支持 GPT3, GPT4 & Gemini Pro 模型。 +一键免费部署你的跨平台私人 ChatGPT 应用, 支持 Claude, GPT4 & Gemini Pro 模型。 [![Saas][Saas-image]][saas-url] [![Web][Web-image]][web-url] @@ -31,7 +32,7 @@ One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4 [MacOS-image]: https://img.shields.io/badge/-MacOS-black?logo=apple [Linux-image]: https://img.shields.io/badge/-Linux-333?logo=ubuntu -[Deploy on Vercel](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) [Deploy on Zeabur](https://zeabur.com/templates/ZBUEFA) [Open in Gitpod](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web) [BT Deply Install](https://www.bt.cn/new/download.html) [Deploy to Alibaba Cloud](https://computenest.aliyun.com/market/service-f1c9b75e59814dc49d52) +[Deploy on Vercel](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) [Deploy on Zeabur](https://zeabur.com/templates/ZBUEFA) [Open in Gitpod](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web) [BT Deply Install](https://www.bt.cn/new/download.html) [](https://monica.im/?utm=nxcrp) From 5b1a759f860a660cb95af64cc16ee5f4fffec523 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Fri, 20 Dec 2024 22:17:12 +0800 Subject: [PATCH 13/13] Update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9168480c5..e01cfa51d 100644 --- a/README.md +++ b/README.md @@ -477,7 +477,7 @@ If you want to add a new translation, read this [document](./docs/translation.md ## Donation -[Buy Me a Coffee](https://www.buymeacoffee.com/yidadaa) +[Buy Me a Coffee](https://1kafei.com/dogtiti) ## Special Thanks