Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
052524dabd
|
@ -110,6 +110,16 @@ export class ChatGPTApi implements LLMApi {
|
||||||
// Please do not ask me why not send max_tokens, no reason, this param is just shit, I dont want to explain anymore.
|
// Please do not ask me why not send max_tokens, no reason, this param is just shit, I dont want to explain anymore.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// add max_tokens to vision model
|
||||||
|
if (visionModel) {
|
||||||
|
Object.defineProperty(requestPayload, "max_tokens", {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: modelConfig.max_tokens,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
console.log("[Request] openai payload: ", requestPayload);
|
console.log("[Request] openai payload: ", requestPayload);
|
||||||
|
|
||||||
const shouldStream = !!options.config.stream;
|
const shouldStream = !!options.config.stream;
|
||||||
|
|
|
@ -1105,6 +1105,47 @@ function _Chat() {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handlePaste = useCallback(
|
||||||
|
async (event: React.ClipboardEvent<HTMLTextAreaElement>) => {
|
||||||
|
const currentModel = chatStore.currentSession().mask.modelConfig.model;
|
||||||
|
if(!isVisionModel(currentModel)){return;}
|
||||||
|
const items = (event.clipboardData || window.clipboardData).items;
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.kind === "file" && item.type.startsWith("image/")) {
|
||||||
|
event.preventDefault();
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) {
|
||||||
|
const images: string[] = [];
|
||||||
|
images.push(...attachImages);
|
||||||
|
images.push(
|
||||||
|
...(await new Promise<string[]>((res, rej) => {
|
||||||
|
setUploading(true);
|
||||||
|
const imagesData: string[] = [];
|
||||||
|
compressImage(file, 256 * 1024)
|
||||||
|
.then((dataUrl) => {
|
||||||
|
imagesData.push(dataUrl);
|
||||||
|
setUploading(false);
|
||||||
|
res(imagesData);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setUploading(false);
|
||||||
|
rej(e);
|
||||||
|
});
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const imagesLength = images.length;
|
||||||
|
|
||||||
|
if (imagesLength > 3) {
|
||||||
|
images.splice(3, imagesLength - 3);
|
||||||
|
}
|
||||||
|
setAttachImages(images);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[attachImages, chatStore],
|
||||||
|
);
|
||||||
|
|
||||||
async function uploadImage() {
|
async function uploadImage() {
|
||||||
const images: string[] = [];
|
const images: string[] = [];
|
||||||
images.push(...attachImages);
|
images.push(...attachImages);
|
||||||
|
@ -1453,6 +1494,7 @@ function _Chat() {
|
||||||
onKeyDown={onInputKeyDown}
|
onKeyDown={onInputKeyDown}
|
||||||
onFocus={scrollToBottom}
|
onFocus={scrollToBottom}
|
||||||
onClick={scrollToBottom}
|
onClick={scrollToBottom}
|
||||||
|
onPaste={handlePaste}
|
||||||
rows={inputRows}
|
rows={inputRows}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
@ -30,6 +30,9 @@ declare global {
|
||||||
// google only
|
// google only
|
||||||
GOOGLE_API_KEY?: string;
|
GOOGLE_API_KEY?: string;
|
||||||
GOOGLE_URL?: string;
|
GOOGLE_URL?: string;
|
||||||
|
|
||||||
|
// google tag manager
|
||||||
|
GTM_ID?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ const tw = {
|
||||||
WIP: "該功能仍在開發中……",
|
WIP: "該功能仍在開發中……",
|
||||||
Error: {
|
Error: {
|
||||||
Unauthorized: isApp
|
Unauthorized: isApp
|
||||||
? "檢測到無效 API Key,請前往[設定](/#/settings)頁檢查 API Key 是否配置正確。"
|
? "檢測到無效 API Key,請前往[設定](/#/settings)頁檢查 API Key 是否設定正確。"
|
||||||
: "訪問密碼不正確或為空,請前往[登錄](/#/auth)頁輸入正確的訪問密碼,或者在[設定](/#/settings)頁填入你自己的 OpenAI API Key。",
|
: "訪問密碼不正確或為空,請前往[登入](/#/auth)頁輸入正確的訪問密碼,或者在[設定](/#/settings)頁填入你自己的 OpenAI API Key。",
|
||||||
},
|
},
|
||||||
|
|
||||||
Auth: {
|
Auth: {
|
||||||
|
@ -17,7 +17,7 @@ const tw = {
|
||||||
SubTips: "或者輸入你的 OpenAI 或 Google API 密鑰",
|
SubTips: "或者輸入你的 OpenAI 或 Google API 密鑰",
|
||||||
Input: "在此處填寫訪問碼",
|
Input: "在此處填寫訪問碼",
|
||||||
Confirm: "確認",
|
Confirm: "確認",
|
||||||
Later: "稍後再說",
|
Later: "稍候再說",
|
||||||
},
|
},
|
||||||
ChatItem: {
|
ChatItem: {
|
||||||
ChatItemCount: (count: number) => `${count} 則對話`,
|
ChatItemCount: (count: number) => `${count} 則對話`,
|
||||||
|
@ -53,8 +53,8 @@ const tw = {
|
||||||
del: "刪除聊天",
|
del: "刪除聊天",
|
||||||
},
|
},
|
||||||
InputActions: {
|
InputActions: {
|
||||||
Stop: "停止響應",
|
Stop: "停止回應",
|
||||||
ToBottom: "滾到最新",
|
ToBottom: "移至最新",
|
||||||
Theme: {
|
Theme: {
|
||||||
auto: "自動主題",
|
auto: "自動主題",
|
||||||
light: "亮色模式",
|
light: "亮色模式",
|
||||||
|
@ -107,7 +107,7 @@ const tw = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Select: {
|
Select: {
|
||||||
Search: "搜索消息",
|
Search: "查詢消息",
|
||||||
All: "選取全部",
|
All: "選取全部",
|
||||||
Latest: "最近幾條",
|
Latest: "最近幾條",
|
||||||
Clear: "清除選中",
|
Clear: "清除選中",
|
||||||
|
@ -133,15 +133,15 @@ const tw = {
|
||||||
Danger: {
|
Danger: {
|
||||||
Reset: {
|
Reset: {
|
||||||
Title: "重置所有設定",
|
Title: "重置所有設定",
|
||||||
SubTitle: "重置所有設定項回默認值",
|
SubTitle: "重置所有設定項回預設值",
|
||||||
Action: "立即重置",
|
Action: "立即重置",
|
||||||
Confirm: "確認重置所有設定?",
|
Confirm: "確認重置所有設定?",
|
||||||
},
|
},
|
||||||
Clear: {
|
Clear: {
|
||||||
Title: "清除所有數據",
|
Title: "清除所有資料",
|
||||||
SubTitle: "清除所有聊天、設定數據",
|
SubTitle: "清除所有聊天、設定資料",
|
||||||
Action: "立即清除",
|
Action: "立即清除",
|
||||||
Confirm: "確認清除所有聊天、設定數據?",
|
Confirm: "確認清除所有聊天、設定資料?",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Lang: {
|
Lang: {
|
||||||
|
@ -182,14 +182,14 @@ const tw = {
|
||||||
SubTitle: "根據對話內容生成合適的標題",
|
SubTitle: "根據對話內容生成合適的標題",
|
||||||
},
|
},
|
||||||
Sync: {
|
Sync: {
|
||||||
CloudState: "雲端數據",
|
CloudState: "雲端資料",
|
||||||
NotSyncYet: "還沒有進行過同步",
|
NotSyncYet: "還沒有進行過同步",
|
||||||
Success: "同步成功",
|
Success: "同步成功",
|
||||||
Fail: "同步失敗",
|
Fail: "同步失敗",
|
||||||
|
|
||||||
Config: {
|
Config: {
|
||||||
Modal: {
|
Modal: {
|
||||||
Title: "配置雲端同步",
|
Title: "設定雲端同步",
|
||||||
Check: "檢查可用性",
|
Check: "檢查可用性",
|
||||||
},
|
},
|
||||||
SyncType: {
|
SyncType: {
|
||||||
|
@ -218,7 +218,7 @@ const tw = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
LocalState: "本地數據",
|
LocalState: "本地資料",
|
||||||
Overview: (overview: any) => {
|
Overview: (overview: any) => {
|
||||||
return `${overview.chat} 次對話,${overview.message} 條消息,${overview.prompt} 條提示詞,${overview.mask} 個面具`;
|
return `${overview.chat} 次對話,${overview.message} 條消息,${overview.prompt} 條提示詞,${overview.mask} 個面具`;
|
||||||
},
|
},
|
||||||
|
@ -385,7 +385,7 @@ const tw = {
|
||||||
Edit: "前置上下文和歷史記憶",
|
Edit: "前置上下文和歷史記憶",
|
||||||
Add: "新增一條",
|
Add: "新增一條",
|
||||||
Clear: "上下文已清除",
|
Clear: "上下文已清除",
|
||||||
Revert: "恢覆上下文",
|
Revert: "恢復上下文",
|
||||||
},
|
},
|
||||||
Plugin: { Name: "外掛" },
|
Plugin: { Name: "外掛" },
|
||||||
FineTuned: { Sysmessage: "你是一個助手" },
|
FineTuned: { Sysmessage: "你是一個助手" },
|
||||||
|
@ -440,8 +440,8 @@ const tw = {
|
||||||
More: "搜尋更多",
|
More: "搜尋更多",
|
||||||
},
|
},
|
||||||
URLCommand: {
|
URLCommand: {
|
||||||
Code: "檢測到鏈接中已經包含訪問碼,是否自動填入?",
|
Code: "檢測到連結中已經包含訪問碼,是否自動填入?",
|
||||||
Settings: "檢測到鏈接中包含了預制設置,是否自動填入?",
|
Settings: "檢測到連結中包含了預設設定,是否自動填入?",
|
||||||
},
|
},
|
||||||
UI: {
|
UI: {
|
||||||
Confirm: "確認",
|
Confirm: "確認",
|
||||||
|
@ -452,7 +452,7 @@ const tw = {
|
||||||
Export: "導出",
|
Export: "導出",
|
||||||
Import: "導入",
|
Import: "導入",
|
||||||
Sync: "同步",
|
Sync: "同步",
|
||||||
Config: "配置",
|
Config: "設定",
|
||||||
},
|
},
|
||||||
Exporter: {
|
Exporter: {
|
||||||
Description: {
|
Description: {
|
||||||
|
|
11
app/utils.ts
11
app/utils.ts
|
@ -9,8 +9,9 @@ export function trimTopic(topic: string) {
|
||||||
// This will remove the specified punctuation from the end of the string
|
// This will remove the specified punctuation from the end of the string
|
||||||
// and also trim quotes from both the start and end if they exist.
|
// and also trim quotes from both the start and end if they exist.
|
||||||
return topic
|
return topic
|
||||||
.replace(/^["“”]+|["“”]+$/g, "")
|
// fix for gemini
|
||||||
.replace(/[,。!?”“"、,.!?]*$/, "");
|
.replace(/^["“”*]+|["“”*]+$/g, "")
|
||||||
|
.replace(/[,。!?”“"、,.!?*]*$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function copyToClipboard(text: string) {
|
export async function copyToClipboard(text: string) {
|
||||||
|
@ -292,8 +293,8 @@ export function getMessageImages(message: RequestMessage): string[] {
|
||||||
|
|
||||||
export function isVisionModel(model: string) {
|
export function isVisionModel(model: string) {
|
||||||
return (
|
return (
|
||||||
model.startsWith("gpt-4-vision") ||
|
// model.startsWith("gpt-4-vision") ||
|
||||||
model.startsWith("gemini-pro-vision") ||
|
// model.startsWith("gemini-pro-vision") ||
|
||||||
!DEFAULT_MODELS.find((m) => m.name == model)
|
model.includes("vision")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue