Merge pull request #4671 from ChatGPTNextWeb/chore-fix

Chore fix
This commit is contained in:
DeanYao 2024-05-16 14:51:06 +08:00 committed by GitHub
commit f55f04ab4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 109 additions and 67 deletions

View File

@ -245,13 +245,17 @@ To control custom models, use `+` to add a custom model, use `-` to hide a model
User `-all` to disable all default models, `+all` to enable all default models. User `-all` to disable all default models, `+all` to enable all default models.
### `WHITE_WEBDEV_ENDPOINTS` (可选) ### `WHITE_WEBDEV_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 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 - Each address must be a complete endpoint
> `https://xxxx/yyy` > `https://xxxx/yyy`
- Multiple addresses are connected by ', ' - Multiple addresses are connected by ', '
### `DEFAULT_INPUT_TEMPLATE` (optional)
Customize the default template used to initialize the User Input Preprocessing configuration item in Settings.
## Requirements ## Requirements
NodeJS >= 18, Docker >= 20 NodeJS >= 18, Docker >= 20

View File

@ -156,6 +156,9 @@ anthropic claude Api Url.
用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。 用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。
### `DEFAULT_INPUT_TEMPLATE` (可选)
自定义默认的 template用于初始化『设置』中的『用户输入预处理』配置项
## 开发 ## 开发
点击下方按钮,开始二次开发: 点击下方按钮,开始二次开发:

View File

@ -59,9 +59,10 @@ import {
getMessageTextContent, getMessageTextContent,
getMessageImages, getMessageImages,
isVisionModel, isVisionModel,
compressImage,
} from "../utils"; } from "../utils";
import { compressImage } from "@/app/utils/chat";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { ChatControllerPool } from "../client/controller"; import { ChatControllerPool } from "../client/controller";

View File

@ -1,4 +1,5 @@
import tauriConfig from "../../src-tauri/tauri.conf.json"; import tauriConfig from "../../src-tauri/tauri.conf.json";
import { DEFAULT_INPUT_TEMPLATE } from "../constant";
export const getBuildConfig = () => { export const getBuildConfig = () => {
if (typeof process === "undefined") { if (typeof process === "undefined") {
@ -38,6 +39,7 @@ export const getBuildConfig = () => {
...commitInfo, ...commitInfo,
buildMode, buildMode,
isApp, isApp,
template: process.env.DEFAULT_INPUT_TEMPLATE ?? DEFAULT_INPUT_TEMPLATE,
}; };
}; };

View File

@ -34,6 +34,9 @@ declare global {
// google tag manager // google tag manager
GTM_ID?: string; GTM_ID?: string;
// custom template for preprocessing user input
DEFAULT_INPUT_TEMPLATE?: string;
} }
} }
} }

View File

@ -428,14 +428,13 @@ export const useChatStore = createPersistStore(
getMemoryPrompt() { getMemoryPrompt() {
const session = get().currentSession(); const session = get().currentSession();
return { if (session.memoryPrompt.length) {
role: "system", return {
content: role: "system",
session.memoryPrompt.length > 0 content: Locale.Store.Prompt.History(session.memoryPrompt),
? Locale.Store.Prompt.History(session.memoryPrompt) date: "",
: "", } as ChatMessage;
date: "", }
} as ChatMessage;
}, },
getMessagesWithMemory() { getMessagesWithMemory() {
@ -471,16 +470,15 @@ export const useChatStore = createPersistStore(
systemPrompts.at(0)?.content ?? "empty", systemPrompts.at(0)?.content ?? "empty",
); );
} }
const memoryPrompt = get().getMemoryPrompt();
// long term memory // long term memory
const shouldSendLongTermMemory = const shouldSendLongTermMemory =
modelConfig.sendMemory && modelConfig.sendMemory &&
session.memoryPrompt && session.memoryPrompt &&
session.memoryPrompt.length > 0 && session.memoryPrompt.length > 0 &&
session.lastSummarizeIndex > clearContextIndex; session.lastSummarizeIndex > clearContextIndex;
const longTermMemoryPrompts = shouldSendLongTermMemory const longTermMemoryPrompts =
? [get().getMemoryPrompt()] shouldSendLongTermMemory && memoryPrompt ? [memoryPrompt] : [];
: [];
const longTermMemoryStartIndex = session.lastSummarizeIndex; const longTermMemoryStartIndex = session.lastSummarizeIndex;
// short term memory // short term memory
@ -605,9 +603,11 @@ export const useChatStore = createPersistStore(
Math.max(0, n - modelConfig.historyMessageCount), Math.max(0, n - modelConfig.historyMessageCount),
); );
} }
const memoryPrompt = get().getMemoryPrompt();
// add memory prompt if (memoryPrompt) {
toBeSummarizedMsgs.unshift(get().getMemoryPrompt()); // add memory prompt
toBeSummarizedMsgs.unshift(memoryPrompt);
}
const lastSummarizeIndex = session.messages.length; const lastSummarizeIndex = session.messages.length;

View File

@ -1,5 +1,4 @@
import { LLMModel } from "../client/api"; import { LLMModel } from "../client/api";
import { isMacOS } from "../utils";
import { getClientConfig } from "../config/client"; import { getClientConfig } from "../config/client";
import { import {
DEFAULT_INPUT_TEMPLATE, DEFAULT_INPUT_TEMPLATE,
@ -25,6 +24,8 @@ export enum Theme {
Light = "light", Light = "light",
} }
const config = getClientConfig();
export const DEFAULT_CONFIG = { export const DEFAULT_CONFIG = {
lastUpdate: Date.now(), // timestamp, to merge state lastUpdate: Date.now(), // timestamp, to merge state
@ -32,7 +33,7 @@ export const DEFAULT_CONFIG = {
avatar: "1f603", avatar: "1f603",
fontSize: 14, fontSize: 14,
theme: Theme.Auto as Theme, theme: Theme.Auto as Theme,
tightBorder: !!getClientConfig()?.isApp, tightBorder: !!config?.isApp,
sendPreviewBubble: true, sendPreviewBubble: true,
enableAutoGenerateTitle: true, enableAutoGenerateTitle: true,
sidebarWidth: DEFAULT_SIDEBAR_WIDTH, sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
@ -56,7 +57,7 @@ export const DEFAULT_CONFIG = {
historyMessageCount: 4, historyMessageCount: 4,
compressMessageLengthThreshold: 1000, compressMessageLengthThreshold: 1000,
enableInjectSystemPrompts: true, enableInjectSystemPrompts: true,
template: DEFAULT_INPUT_TEMPLATE, template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
}, },
}; };
@ -132,7 +133,7 @@ export const useAppConfig = createPersistStore(
}), }),
{ {
name: StoreKey.Config, name: StoreKey.Config,
version: 3.8, version: 3.9,
migrate(persistedState, version) { migrate(persistedState, version) {
const state = persistedState as ChatConfig; const state = persistedState as ChatConfig;
@ -163,6 +164,13 @@ export const useAppConfig = createPersistStore(
state.lastUpdate = Date.now(); state.lastUpdate = Date.now();
} }
if (version < 3.9) {
state.modelConfig.template =
state.modelConfig.template !== DEFAULT_INPUT_TEMPLATE
? state.modelConfig.template
: config?.template ?? DEFAULT_INPUT_TEMPLATE;
}
return state as any; return state as any;
}, },
}, },

View File

@ -83,48 +83,6 @@ export async function downloadAs(text: string, filename: string) {
} }
} }
export function compressImage(file: File, maxSize: number): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (readerEvent: any) => {
const image = new Image();
image.onload = () => {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let width = image.width;
let height = image.height;
let quality = 0.9;
let dataUrl;
do {
canvas.width = width;
canvas.height = height;
ctx?.clearRect(0, 0, canvas.width, canvas.height);
ctx?.drawImage(image, 0, 0, width, height);
dataUrl = canvas.toDataURL("image/jpeg", quality);
if (dataUrl.length < maxSize) break;
if (quality > 0.5) {
// Prioritize quality reduction
quality -= 0.1;
} else {
// Then reduce the size
width *= 0.9;
height *= 0.9;
}
} while (dataUrl.length > maxSize);
resolve(dataUrl);
};
image.onerror = reject;
image.src = readerEvent.target.result;
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
export function readFromFile() { export function readFromFile() {
return new Promise<string>((res, rej) => { return new Promise<string>((res, rej) => {
const fileInput = document.createElement("input"); const fileInput = document.createElement("input");

54
app/utils/chat.ts Normal file
View File

@ -0,0 +1,54 @@
import heic2any from "heic2any";
export function compressImage(file: File, maxSize: number): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (readerEvent: any) => {
const image = new Image();
image.onload = () => {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let width = image.width;
let height = image.height;
let quality = 0.9;
let dataUrl;
do {
canvas.width = width;
canvas.height = height;
ctx?.clearRect(0, 0, canvas.width, canvas.height);
ctx?.drawImage(image, 0, 0, width, height);
dataUrl = canvas.toDataURL("image/jpeg", quality);
if (dataUrl.length < maxSize) break;
if (quality > 0.5) {
// Prioritize quality reduction
quality -= 0.1;
} else {
// Then reduce the size
width *= 0.9;
height *= 0.9;
}
} while (dataUrl.length > maxSize);
resolve(dataUrl);
};
image.onerror = reject;
image.src = readerEvent.target.result;
};
reader.onerror = reject;
if (file.type.includes("heic")) {
heic2any({ blob: file, toType: "image/jpeg" })
.then((blob) => {
reader.readAsDataURL(blob as Blob);
})
.catch((e) => {
reject(e);
});
}
reader.readAsDataURL(file);
});
}

View File

@ -93,14 +93,17 @@ export function createUpstashClient(store: SyncStore) {
} }
let url; let url;
if (proxyUrl.length > 0 || proxyUrl === "/") { const pathPrefix = "/api/upstash/";
let u = new URL(proxyUrl + "/api/upstash/" + path);
try {
let u = new URL(proxyUrl + pathPrefix + path);
// add query params // add query params
u.searchParams.append("endpoint", config.endpoint); u.searchParams.append("endpoint", config.endpoint);
url = u.toString(); url = u.toString();
} else { } catch (e) {
url = "/api/upstash/" + path + "?endpoint=" + config.endpoint; url = pathPrefix + path + "?endpoint=" + config.endpoint;
} }
return url; return url;
}, },
}; };

View File

@ -24,6 +24,7 @@
"@vercel/speed-insights": "^1.0.2", "@vercel/speed-insights": "^1.0.2",
"emoji-picker-react": "^4.9.2", "emoji-picker-react": "^4.9.2",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"heic2any": "^0.0.4",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"mermaid": "^10.6.1", "mermaid": "^10.6.1",
"nanoid": "^5.0.3", "nanoid": "^5.0.3",

View File

@ -3669,6 +3669,11 @@ heap@^0.2.6:
resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==
heic2any@^0.0.4:
version "0.0.4"
resolved "https://registry.npmmirror.com/heic2any/-/heic2any-0.0.4.tgz#eddb8e6fec53c8583a6e18b65069bb5e8d19028a"
integrity sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA==
highlight.js@~11.7.0: highlight.js@~11.7.0:
version "11.7.0" version "11.7.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e"