Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed May 17, 2024
2 parents f4757d7 + f55f04a commit 71db96f
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 67 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

### `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:
- Each address must be a complete endpoint
> `https://xxxx/yyy`
- 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

NodeJS >= 18, Docker >= 20
Expand Down
3 changes: 3 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ anthropic claude Api Url.
用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。

### `DEFAULT_INPUT_TEMPLATE` (可选)
自定义默认的 template,用于初始化『设置』中的『用户输入预处理』配置项

## 开发

点击下方按钮,开始二次开发:
Expand Down
3 changes: 2 additions & 1 deletion app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ import {
getMessageTextContent,
getMessageImages,
isVisionModel,
compressImage,
} from "../utils";

import { compressImage } from "@/app/utils/chat";

import dynamic from "next/dynamic";

import { ChatControllerPool } from "../client/controller";
Expand Down
2 changes: 2 additions & 0 deletions app/config/build.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import tauriConfig from "../../src-tauri/tauri.conf.json";
import { DEFAULT_INPUT_TEMPLATE } from "../constant";

export const getBuildConfig = () => {
if (typeof process === "undefined") {
Expand Down Expand Up @@ -38,6 +39,7 @@ export const getBuildConfig = () => {
...commitInfo,
buildMode,
isApp,
template: process.env.DEFAULT_INPUT_TEMPLATE ?? DEFAULT_INPUT_TEMPLATE,
};
};

Expand Down
3 changes: 3 additions & 0 deletions app/config/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ declare global {

// google tag manager
GTM_ID?: string;

// custom template for preprocessing user input
DEFAULT_INPUT_TEMPLATE?: string;
}
}
}
Expand Down
30 changes: 15 additions & 15 deletions app/store/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,13 @@ export const useChatStore = createPersistStore(
getMemoryPrompt() {
const session = get().currentSession();

return {
role: "system",
content:
session.memoryPrompt.length > 0
? Locale.Store.Prompt.History(session.memoryPrompt)
: "",
date: "",
} as ChatMessage;
if (session.memoryPrompt.length) {
return {
role: "system",
content: Locale.Store.Prompt.History(session.memoryPrompt),
date: "",
} as ChatMessage;
}
},

getMessagesWithMemory() {
Expand Down Expand Up @@ -471,16 +470,15 @@ export const useChatStore = createPersistStore(
systemPrompts.at(0)?.content ?? "empty",
);
}

const memoryPrompt = get().getMemoryPrompt();
// long term memory
const shouldSendLongTermMemory =
modelConfig.sendMemory &&
session.memoryPrompt &&
session.memoryPrompt.length > 0 &&
session.lastSummarizeIndex > clearContextIndex;
const longTermMemoryPrompts = shouldSendLongTermMemory
? [get().getMemoryPrompt()]
: [];
const longTermMemoryPrompts =
shouldSendLongTermMemory && memoryPrompt ? [memoryPrompt] : [];
const longTermMemoryStartIndex = session.lastSummarizeIndex;

// short term memory
Expand Down Expand Up @@ -605,9 +603,11 @@ export const useChatStore = createPersistStore(
Math.max(0, n - modelConfig.historyMessageCount),
);
}

// add memory prompt
toBeSummarizedMsgs.unshift(get().getMemoryPrompt());
const memoryPrompt = get().getMemoryPrompt();
if (memoryPrompt) {
// add memory prompt
toBeSummarizedMsgs.unshift(memoryPrompt);
}

const lastSummarizeIndex = session.messages.length;

Expand Down
16 changes: 12 additions & 4 deletions app/store/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { LLMModel } from "../client/api";
import { isMacOS } from "../utils";
import { getClientConfig } from "../config/client";
import {
DEFAULT_INPUT_TEMPLATE,
Expand All @@ -25,14 +24,16 @@ export enum Theme {
Light = "light",
}

const config = getClientConfig();

export const DEFAULT_CONFIG = {
lastUpdate: Date.now(), // timestamp, to merge state

submitKey: SubmitKey.Enter,
avatar: "1f603",
fontSize: 14,
theme: Theme.Auto as Theme,
tightBorder: !!getClientConfig()?.isApp,
tightBorder: !!config?.isApp,
sendPreviewBubble: true,
enableAutoGenerateTitle: true,
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
Expand All @@ -56,7 +57,7 @@ export const DEFAULT_CONFIG = {
historyMessageCount: 4,
compressMessageLengthThreshold: 1000,
enableInjectSystemPrompts: true,
template: DEFAULT_INPUT_TEMPLATE,
template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
},
};

Expand Down Expand Up @@ -132,7 +133,7 @@ export const useAppConfig = createPersistStore(
}),
{
name: StoreKey.Config,
version: 3.8,
version: 3.9,
migrate(persistedState, version) {
const state = persistedState as ChatConfig;

Expand Down Expand Up @@ -163,6 +164,13 @@ export const useAppConfig = createPersistStore(
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;
},
},
Expand Down
43 changes: 1 addition & 42 deletions app/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
return new Promise<string>((res, rej) => {
const fileInput = document.createElement("input");
Expand Down Expand Up @@ -297,6 +255,7 @@ export function isVisionModel(model: string) {
"claude-3",
"gemini-1.5-pro",
"gemini-1.5-flash",
"gpt-4o",
];
const isGpt4Turbo =
model.includes("gpt-4-turbo") && !model.includes("preview");
Expand Down
54 changes: 54 additions & 0 deletions app/utils/chat.ts
Original file line number Diff line number Diff line change
@@ -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);
});
}
11 changes: 7 additions & 4 deletions app/utils/cloud/upstash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,17 @@ export function createUpstashClient(store: SyncStore) {
}

let url;
if (proxyUrl.length > 0 || proxyUrl === "/") {
let u = new URL(proxyUrl + "/api/upstash/" + path);
const pathPrefix = "/api/upstash/";

try {
let u = new URL(proxyUrl + pathPrefix + path);
// add query params
u.searchParams.append("endpoint", config.endpoint);
url = u.toString();
} else {
url = "/api/upstash/" + path + "?endpoint=" + config.endpoint;
} catch (e) {
url = pathPrefix + path + "?endpoint=" + config.endpoint;
}

return url;
},
};
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@vercel/speed-insights": "^1.0.2",
"emoji-picker-react": "^4.9.2",
"fuse.js": "^7.0.0",
"heic2any": "^0.0.4",
"html-to-image": "^1.11.11",
"mermaid": "^10.6.1",
"nanoid": "^5.0.3",
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3669,6 +3669,11 @@ heap@^0.2.6:
resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
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:
version "11.7.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e"
Expand Down

0 comments on commit 71db96f

Please sign in to comment.