Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Hk-Gosuto 2024-05-17 21:01:15 +08:00
commit c5c3fc1cc2
12 changed files with 110 additions and 69 deletions

View File

@ -281,13 +281,16 @@ anthropic claude Api Url.
如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。 如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。
### `WHITE_WEBDEV_ENDPOINTS` (可选) ### `WHITE_WEBDEV_ENDPOINTS` (optional)
如果你想增加允许访问的webdav服务地址可以使用该选项格式要求 如果你想增加允许访问的webdav服务地址可以使用该选项格式要求
- 每一个地址必须是一个完整的 endpoint - 每一个地址必须是一个完整的 endpoint
> `https://xxxx/xxx` > `https://xxxx/xxx`
- 多个地址以`,`相连 - 多个地址以`,`相连
### `DEFAULT_INPUT_TEMPLATE` (可选)
自定义默认的 template用于初始化『设置』中的『用户输入预处理』配置项
## 部署 ## 部署
### 容器部署 (推荐) ### 容器部署 (推荐)

View File

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

View File

@ -67,11 +67,12 @@ import {
getMessageTextContent, getMessageTextContent,
getMessageImages, getMessageImages,
isVisionModel, isVisionModel,
compressImage,
isFirefox, isFirefox,
isSupportRAGModel, isSupportRAGModel,
} 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

@ -548,14 +548,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() {
@ -591,16 +590,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
@ -726,9 +724,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,
@ -35,6 +34,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
@ -42,7 +43,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,
@ -66,7 +67,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,
}, },
pluginConfig: { pluginConfig: {
@ -182,7 +183,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;
@ -213,6 +214,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

@ -84,48 +84,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");
@ -298,7 +256,7 @@ export function isVisionModel(model: string) {
"claude-3", "claude-3",
"gemini-1.5-pro", "gemini-1.5-pro",
"gemini-1.5-flash", "gemini-1.5-flash",
"gpt-4o" "gpt-4o",
]; ];
const isGpt4Turbo = const isGpt4Turbo =
model.includes("gpt-4-turbo") && !model.includes("preview"); model.includes("gpt-4-turbo") && !model.includes("preview");

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

@ -39,6 +39,7 @@
"epub2": "^3.0.2", "epub2": "^3.0.2",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"html-entities": "^2.4.0", "html-entities": "^2.4.0",
"heic2any": "^0.0.4",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"html-to-text": "^9.0.5", "html-to-text": "^9.0.5",
"https-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.2",

View File

@ -5548,9 +5548,14 @@ heap@^0.2.6:
resolved "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz" resolved "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz"
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.8.0: highlight.js@~11.8.0:
version "11.8.0" version "11.8.0"
resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65"
integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: