重构绘图相关

This commit is contained in:
sijinhui 2024-02-22 00:21:36 +08:00
parent 7c3c19e965
commit 747bed9826
11 changed files with 116 additions and 648 deletions

View File

@ -3,6 +3,7 @@ import { getServerSideConfig } from "../config/server";
import { DEFAULT_MODELS, OPENAI_BASE_URL, GEMINI_BASE_URL } from "../constant";
import { collectModelTable } from "../utils/model";
import { makeAzurePath } from "../azure";
import { getIP } from "@/app/api/auth";
const serverConfig = getServerSideConfig();
@ -130,3 +131,45 @@ export async function requestOpenai(
clearTimeout(timeoutId);
}
}
export async function requestLog(
req: NextRequest,
jsonBody: any,
url_path: string,
) {
// LOG
try {
if (url_path.startsWith("mj/") && !url_path.startsWith("mj/submit/")) {
return;
}
// const protocol = req.headers.get("x-forwarded-proto") || "http";
//const baseUrl = process.env.NEXTAUTH_URL ?? "http://localhost:3000";
const baseUrl = "http://localhost:3000";
const ip = getIP(req);
// 对其进行 Base64 解码
let h_userName = req.headers.get("x-request-name");
if (h_userName) {
const buffer = Buffer.from(h_userName, "base64");
h_userName = decodeURIComponent(buffer.toString("utf-8"));
}
console.log("[中文]", h_userName, baseUrl);
const logData = {
ip: ip,
path: url_path,
// logEntry: JSON.stringify(jsonBody),
model: url_path.startsWith("mj/") ? "midjourney" : jsonBody?.model, // 后面尝试请求是添加到参数
userName: h_userName,
};
await fetch(`${baseUrl}/api/logs/openai`, {
method: "POST",
headers: {
"Content-Type": "application/json",
// ...req.headers,
},
body: JSON.stringify(logData),
});
} catch (e) {
console.log("[LOG]", e, "==========");
}
}

View File

@ -31,13 +31,18 @@ async function handle(
const regex_message = /(?<="content":")(.*?)(?="}[,\]])/g;
const matchAllMessage = request_data.logEntry.match(regex_message);
// console.log(matchAllMessage, "=====");
if (matchAllMessage.length > 0) {
if (matchAllMessage && matchAllMessage.length > 0) {
request_data.logToken =
getTokenLength(matchAllMessage.join(" ")) +
matchAllMessage.length * 3;
} else {
request_data.logToken = 0;
}
delete request_data["logEntry"];
}
if (request_data?.model == "midjourney") {
request_data.logToken = 1000;
}
} catch (e) {
console.log("[LOG]", "logToken", e);
request_data.logToken = 0;

View File

@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/api/auth";
import { auth, getIP } from "@/app/api/auth";
import { ModelProvider } from "@/app/constant";
import { requestLog } from "@/app/api/common";
const BASE_URL = process.env.MIDJOURNEY_PROXY_URL ?? null;
const MIDJOURNEY_PROXY_KEY = process.env.MIDJOURNEY_PROXY_KEY ?? null;
@ -53,6 +54,10 @@ async function handle(
"",
);
if (reqPath.startsWith("mj/submit/")) {
await requestLog(req, jsonBody, reqPath);
}
let fetchUrl = `${mjProxyUrl}/${reqPath}`;
console.log("[MJ Proxy] ", fetchUrl);

View File

@ -10,7 +10,7 @@ import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
import { auth, getIP } from "../../auth";
import { getToken } from "next-auth/jwt";
import { requestOpenai } from "../../common";
import { requestLog, requestOpenai } from "../../common";
import { headers } from "next/headers";
const ALLOWD_PATH = new Set(Object.values({ ...OpenaiPath, ...AZURE_PATH }));
@ -75,37 +75,7 @@ async function handle(
jsonBody = {};
}
try {
const protocol = req.headers.get("x-forwarded-proto") || "http";
//const baseUrl = process.env.NEXTAUTH_URL ?? "http://localhost:3000";
const baseUrl = "http://localhost:3000";
const ip = getIP(req);
// 对其进行 Base64 解码
let h_userName = req.headers.get("x-request-name");
if (h_userName) {
const buffer = Buffer.from(h_userName, "base64");
h_userName = decodeURIComponent(buffer.toString("utf-8"));
}
console.log("[中文]", h_userName, baseUrl);
const logData = {
ip: ip,
path: subpath,
logEntry: JSON.stringify(jsonBody),
model: jsonBody?.model,
userName: h_userName,
};
await fetch(`${baseUrl}/api/logs/openai`, {
method: "POST",
headers: {
"Content-Type": "application/json",
// ...req.headers,
},
body: JSON.stringify(logData),
});
} catch (e) {
console.log("[LOG]", e, "==========");
}
await requestLog(req, jsonBody, subpath);
const isAzure = AZURE_MODELS.includes(jsonBody?.model as string);
// console.log("[Models]", jsonBody?.model);

View File

@ -36,7 +36,7 @@ import AutoIcon from "../icons/auto.svg";
import BottomIcon from "../icons/bottom.svg";
import StopIcon from "../icons/pause.svg";
import RobotIcon from "../icons/robot.svg";
import UploadIcon from "../icons/upload.svg";
// import UploadIcon from "../icons/upload.svg";
import {
ChatMessage,
@ -433,7 +433,6 @@ export function ChatActions(props: {
showPromptModal: () => void;
scrollToBottom: () => void;
showPromptHints: () => void;
imageSelected: (img: any) => void;
hitBottom: boolean;
uploading: boolean;
}) {
@ -455,25 +454,6 @@ export function ChatActions(props: {
const couldStop = ChatControllerPool.hasPending();
const stopAll = () => ChatControllerPool.stopAll();
function selectImage() {
document.getElementById("chat-image-file-select-upload")?.click();
}
const onImageSelected = (e: any) => {
const file = e.target.files[0];
const filename = file.name;
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const base64 = reader.result;
props.imageSelected({
filename,
base64,
});
};
e.target.value = null;
};
// switch model
const currentModel = chatStore.currentSession().mask.modelConfig.model;
const allModels = useAllModels();
@ -529,13 +509,13 @@ export function ChatActions(props: {
{/* />*/}
{/*)}*/}
{showUploadImage && (
<ChatAction
onClick={props.uploadImage}
text={Locale.Chat.InputActions.UploadImage}
icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}
/>
)}
{/*{showUploadImage && (*/}
<ChatAction
onClick={props.uploadImage}
text={Locale.Chat.InputActions.UploadImage}
icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}
/>
{/*)}*/}
<ChatAction
onClick={nextTheme}
text={Locale.Chat.InputActions.Theme[theme]}
@ -587,18 +567,18 @@ export function ChatActions(props: {
icon={<RobotIcon />}
/>
<ChatAction
onClick={selectImage}
text={Locale.Chat.InputActions.UploadImage}
icon={<UploadIcon />}
/>
<input
type="file"
accept=".png,.jpg,.webp,.jpeg"
id="chat-image-file-select-upload"
style={{ display: "none" }}
onChange={onImageSelected}
/>
{/*<ChatAction*/}
{/* onClick={selectImage}*/}
{/* text={Locale.Chat.InputActions.UploadImage}*/}
{/* icon={<UploadIcon />}*/}
{/*/>*/}
{/*<input*/}
{/* type="file"*/}
{/* accept=".png,.jpg,.webp,.jpeg"*/}
{/* id="chat-image-file-select-upload"*/}
{/* style={{ display: "none" }}*/}
{/* onChange={onImageSelected}*/}
{/*/>*/}
{showModelSelector && (
<Selector
@ -705,7 +685,6 @@ function _Chat() {
const inputRef = useRef<HTMLTextAreaElement>(null);
const [userInput, setUserInput] = useState("");
const [useImages, setUseImages] = useState<any[]>([]);
const [mjImageMode, setMjImageMode] = useState<string>("IMAGINE");
const [isLoading, setIsLoading] = useState(false);
const { submitKey, shouldSubmit } = useSubmitHandler();
@ -784,36 +763,23 @@ function _Chat() {
const doSubmit = (userInput: string) => {
if (userInput.trim() === "") return;
if (useImages.length > 0) {
if (mjImageMode === "IMAGINE" && userInput == "") {
alert(Locale.Midjourney.NeedInputUseImgPrompt);
return;
}
} else {
const matchCommand = chatCommands.match(userInput);
if (matchCommand.matched) {
setUserInput("");
setPromptHints([]);
matchCommand.invoke();
return;
}
const matchCommand = chatCommands.match(userInput);
if (matchCommand.matched) {
setUserInput("");
setPromptHints([]);
matchCommand.invoke();
return;
}
setIsLoading(true);
chatStore
.onUserInput(
userInput,
{
useImages,
mjImageMode,
setAutoScroll,
},
attachImages,
)
.onUserInput(userInput, attachImages, {
mjImageMode,
setAutoScroll,
})
.then(() => setIsLoading(false));
setAttachImages([]);
localStorage.setItem(LAST_INPUT_KEY, userInput);
setUserInput("");
setUseImages([]);
setMjImageMode("IMAGINE");
setPromptHints([]);
if (!isMobileScreen) inputRef.current?.focus();
@ -1393,6 +1359,8 @@ function _Chat() {
className={styles["chat-message-item-image"]}
src={getMessageImages(message)[0]}
alt=""
width={100}
height={100}
/>
)}
{getMessageImages(message).length > 1 && (
@ -1413,6 +1381,8 @@ function _Chat() {
key={index}
src={image}
alt=""
width={20}
height={20}
/>
);
})}
@ -1588,54 +1558,7 @@ function _Chat() {
setUserInput("/");
onSearch("");
}}
imageSelected={(img: any) => {
if (useImages.length >= 5) {
alert(Locale.Midjourney.SelectImgMax(5));
return;
}
setUseImages([...useImages, img]);
}}
/>
{useImages.length > 0 && (
<div className={styles["chat-select-images"]}>
{useImages.map((img: any, i) => (
<Image
src={img.base64}
key={i}
onClick={() => {
setUseImages(useImages.filter((_, ii) => ii != i));
}}
title={img.filename}
alt={img.filename}
width={20}
height={20}
/>
))}
<div style={{ fontSize: "12px", marginBottom: "5px" }}>
{[
{ name: Locale.Midjourney.ModeImagineUseImg, value: "IMAGINE" },
// { name: Locale.Midjourney.ModeBlend, value: "BLEND" },
// { name: Locale.Midjourney.ModeDescribe, value: "DESCRIBE" },
].map((item, i) => (
<label key={i}>
<input
type="radio"
name="mj-img-mode"
checked={mjImageMode == item.value}
value={item.value}
onChange={(e) => {
setMjImageMode(e.target.value);
}}
/>
<span>{item.name}</span>
</label>
))}
</div>
<div style={{ fontSize: "12px" }}>
<small>{Locale.Midjourney.HasImgTip}</small>
</div>
</div>
)}
<label
className={`${styles["chat-input-panel-inner"]} ${
attachImages.length != 0
@ -1648,12 +1571,7 @@ function _Chat() {
id="chat-input"
ref={inputRef}
className={styles["chat-input"]}
// placeholder={Locale.Chat.Input(submitKey)}
placeholder={
useImages.length > 0 && mjImageMode != "IMAGINE"
? Locale.Midjourney.InputDisabled
: Locale.Chat.Input(submitKey)
}
placeholder={Locale.Chat.Input(submitKey)}
onInput={(e) => onInput(e.currentTarget.value)}
value={userInput}
onKeyDown={onInputKeyDown}

View File

@ -166,6 +166,16 @@ export const DEFAULT_MODELS = [
providerType: "openai",
},
},
{
name: "gpt-4-vision-preview",
available: true,
describe: "GPT-4多模态,图像识别",
provider: {
id: "openai",
providerName: "OpenAI",
providerType: "openai",
},
},
{
name: "gemini-pro",
available: true,
@ -178,7 +188,7 @@ export const DEFAULT_MODELS = [
},
{
name: "gemini-pro-vision",
available: true,
available: false,
describe: "谷歌多模态,图像识别",
provider: {
id: "google",

View File

View File

View File

@ -1,482 +0,0 @@
import { getClientConfig } from "../config/client";
import { SubmitKey } from "../store/config";
import { LocaleType } from "./index";
import type { PartialLocaleType } from "./index";
// if you are adding a new translation, please use PartialLocaleType instead of LocaleType
const isApp = !!getClientConfig()?.isApp;
const sk: PartialLocaleType = {
WIP: "Už čoskoro...",
Error: {
Unauthorized: isApp
? "Neplatný API kľúč, prosím skontrolujte ho na stránke [Nastavenia](/#/settings)."
: "Neoprávnený prístup, prosím zadajte prístupový kód na stránke [auth](/#/auth), alebo zadajte váš OpenAI API kľúč.",
},
Auth: {
Title: "Potrebný prístupový kód",
Tips: "Prosím, zadajte prístupový kód nižšie",
SubTips: "Alebo zadajte váš OpenAI alebo Google API kľúč",
Input: "prístupový kód",
Confirm: "Potvrdiť",
Later: "Neskôr",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} správ`,
},
Chat: {
SubTitle: (count: number) => `${count} správ`,
EditMessage: {
Title: "Upraviť všetky správy",
Topic: {
Title: "Téma",
SubTitle: "Zmeniť aktuálnu tému",
},
},
Actions: {
ChatList: "Prejsť na zoznam chatov",
CompressedHistory: "Komprimovaná história výziev",
Export: "Exportovať všetky správy ako Markdown",
Copy: "Kopírovať",
Stop: "Zastaviť",
Retry: "Skúsiť znova",
Pin: "Pripnúť",
PinToastContent: "Pripnuté 1 správy do kontextových výziev",
PinToastAction: "Zobraziť",
Delete: "Vymazať",
Edit: "Upraviť",
},
Commands: {
new: "Začať nový chat",
newm: "Začať nový chat s maskou",
next: "Ďalší Chat",
prev: "Predchádzajúci Chat",
clear: "Vymazať kontext",
del: "Vymazať Chat",
},
InputActions: {
Stop: "Zastaviť",
ToBottom: "Na najnovšie",
Theme: {
auto: "Automaticky",
light: "Svetlý motív",
dark: "Tmavý motív",
},
Prompt: "Výzvy",
Masks: "Masky",
Clear: "Vymazať kontext",
Settings: "Nastavenia",
},
Rename: "Premenovať Chat",
Typing: "Písanie…",
Input: (submitKey: string) => {
var inputHints = `${submitKey} na odoslanie`;
if (submitKey === String(SubmitKey.Enter)) {
inputHints += ", Shift + Enter na zalomenie";
}
return inputHints + ", / na vyhľadávanie výziev, : na použitie príkazov";
},
Send: "Odoslať",
Config: {
Reset: "Resetovať na predvolené",
SaveAs: "Uložiť ako masku",
},
IsContext: "Kontextová výzva",
},
Export: {
Title: "Export správ",
Copy: "Kopírovať všetko",
Download: "Stiahnuť",
MessageFromYou: "Správa od vás",
MessageFromChatGPT: "Správa od ChatGPT",
Share: "Zdieľať na ShareGPT",
Format: {
Title: "Formát exportu",
SubTitle: "Markdown alebo PNG obrázok",
},
IncludeContext: {
Title: "Vrátane kontextu",
SubTitle: "Exportovať kontextové výzvy v maske alebo nie",
},
Steps: {
Select: "Vybrať",
Preview: "Náhľad",
},
Image: {
Toast: "Snímanie obrázka...",
Modal:
"Dlhým stlačením alebo kliknutím pravým tlačidlom myši uložte obrázok",
},
},
Select: {
Search: "Hľadať",
All: "Vybrať všetko",
Latest: "Vybrať najnovšie",
Clear: "Vymazať",
},
Memory: {
Title: "Výzva pamäti",
EmptyContent: "Zatiaľ nič.",
Send: "Odoslať pamäť",
Copy: "Kopírovať pamäť",
Reset: "Resetovať reláciu",
ResetConfirm:
"Resetovaním sa vymaže aktuálna história konverzácie a historická pamäť. Ste si istí, že chcete resetovať?",
},
Home: {
NewChat: "Nový Chat",
DeleteChat: "Potvrdiť vymazanie vybranej konverzácie?",
DeleteToast: "Chat vymazaný",
Revert: "Vrátiť späť",
},
Settings: {
Title: "Nastavenia",
SubTitle: "Všetky nastavenia",
Danger: {
Reset: {
Title: "Resetovať všetky nastavenia",
SubTitle: "Resetovať všetky položky nastavení na predvolené",
Action: "Resetovať",
Confirm: "Potvrdiť resetovanie všetkých nastavení na predvolené?",
},
Clear: {
Title: "Vymazať všetky údaje",
SubTitle: "Vymazať všetky správy a nastavenia",
Action: "Vymazať",
Confirm: "Potvrdiť vymazanie všetkých správ a nastavení?",
},
},
Lang: {
Name: "Jazyk", // POZOR: ak pridávate nový preklad, prosím neprekladajte túto hodnotu, nechajte ju ako "Jazyk"
All: "Všetky jazyky",
},
Avatar: "Avatar",
FontSize: {
Title: "Veľkosť písma",
SubTitle: "Nastaviť veľkosť písma obsahu chatu",
},
InjectSystemPrompts: {
Title: "Vložiť systémové výzvy",
SubTitle: "Vložiť globálnu systémovú výzvu pre každú požiadavku",
},
InputTemplate: {
Title: "Šablóna vstupu",
SubTitle: "Najnovšia správa bude vyplnená do tejto šablóny",
},
Update: {
Version: (x: string) => `Verzia: ${x}`,
IsLatest: "Najnovšia verzia",
CheckUpdate: "Skontrolovať aktualizácie",
IsChecking: "Kontrola aktualizácií...",
FoundUpdate: (x: string) => `Nájdená nová verzia: ${x}`,
GoToUpdate: "Aktualizovať",
},
SendKey: "Odoslať kľúč",
Theme: "Motív",
TightBorder: "Tesný okraj",
SendPreviewBubble: {
Title: "Bublina náhľadu odoslania",
SubTitle: "Náhľad markdownu v bubline",
},
AutoGenerateTitle: {
Title: "Automaticky generovať názov",
SubTitle: "Generovať vhodný názov na základe obsahu konverzácie",
},
Sync: {
CloudState: "Posledná aktualizácia",
NotSyncYet: "Zatiaľ nesynchronizované",
Success: "Synchronizácia úspešná",
Fail: "Synchronizácia zlyhala",
Config: {
Modal: {
Title: "Konfigurácia synchronizácie",
Check: "Skontrolovať pripojenie",
},
SyncType: {
Title: "Typ synchronizácie",
SubTitle: "Vyberte svoju obľúbenú službu synchronizácie",
},
Proxy: {
Title: "Povoliť CORS Proxy",
SubTitle: "Povoliť proxy na obídenie obmedzení cross-origin",
},
ProxyUrl: {
Title: "Koncový bod Proxy",
SubTitle: "Platné len pre vstavaný CORS proxy tohto projektu",
},
WebDav: {
Endpoint: "Koncový bod WebDAV",
UserName: "Meno používateľa",
Password: "Heslo",
},
UpStash: {
Endpoint: "URL REST služby UpStash Redis",
UserName: "Názov zálohy",
Password: "Token REST služby UpStash Redis",
},
},
LocalState: "Lokálne údaje",
Overview: (overview: any) => {
return `${overview.chat} chaty, ${overview.message} správy, ${overview.prompt} výzvy, ${overview.mask} masky`;
},
ImportFailed: "Import z súboru zlyhal",
},
Mask: {
Splash: {
Title: "Úvodná obrazovka masky",
SubTitle: "Zobraziť úvodnú obrazovku masky pred začatím nového chatu",
},
Builtin: {
Title: "Skryť vstavané masky",
SubTitle: "Skryť vstavané masky v zozname masiek",
},
},
Prompt: {
Disable: {
Title: "Zakázať automatické dopĺňanie",
SubTitle: "Zadajte / na spustenie automatického dopĺňania",
},
List: "Zoznam výziev",
ListCount: (builtin: number, custom: number) =>
`${builtin} vstavaných, ${custom} užívateľsky definovaných`,
Edit: "Upraviť",
Modal: {
Title: "Zoznam výziev",
Add: "Pridať jednu",
Search: "Hľadať výzvy",
},
EditModal: {
Title: "Upraviť výzvu",
},
},
HistoryCount: {
Title: "Počet pripojených správ",
SubTitle: "Počet odoslaných správ pripojených na požiadavku",
},
CompressThreshold: {
Title: "Práh kompresie histórie",
SubTitle:
"Bude komprimované, ak dĺžka nekomprimovaných správ presiahne túto hodnotu",
},
Usage: {
Title: "Stav účtu",
SubTitle(used: any, total: any) {
return `Tento mesiac použité ${used}, predplatné ${total}`;
},
IsChecking: "Kontroluje sa...",
Check: "Skontrolovať",
NoAccess: "Zadajte API kľúč na skontrolovanie zostatku",
},
Access: {
AccessCode: {
Title: "Prístupový kód",
SubTitle: "Povolený prístupový kód",
Placeholder: "Zadajte kód",
},
CustomEndpoint: {
Title: "Vlastný koncový bod",
SubTitle: "Použiť vlastnú službu Azure alebo OpenAI",
},
Provider: {
Title: "Poskytovateľ modelu",
SubTitle: "Vyberte Azure alebo OpenAI",
},
OpenAI: {
ApiKey: {
Title: "API kľúč OpenAI",
SubTitle: "Použiť vlastný API kľúč OpenAI",
Placeholder: "sk-xxx",
},
Endpoint: {
Title: "Koncový bod OpenAI",
SubTitle:
"Musí začínať http(s):// alebo použiť /api/openai ako predvolený",
},
},
Azure: {
ApiKey: {
Title: "API kľúč Azure",
SubTitle: "Skontrolujte svoj API kľúč v Azure konzole",
Placeholder: "API kľúč Azure",
},
Endpoint: {
Title: "Koncový bod Azure",
SubTitle: "Príklad: ",
},
ApiVerion: {
Title: "Verzia API Azure",
SubTitle: "Skontrolujte svoju verziu API v Azure konzole",
},
},
CustomModel: {
Title: "Vlastné modely",
SubTitle: "Možnosti vlastného modelu, oddelené čiarkou",
},
Google: {
ApiKey: {
Title: "API kľúč",
SubTitle:
"Obísť obmedzenia prístupu heslom pomocou vlastného API kľúča Google AI Studio",
Placeholder: "API kľúč Google AI Studio",
},
Endpoint: {
Title: "Adresa koncového bodu",
SubTitle: "Príklad:",
},
ApiVersion: {
Title: "Verzia API (gemini-pro verzia API)",
SubTitle: "Vyberte špecifickú verziu časti",
},
},
},
Model: "Model",
Temperature: {
Title: "Teplota",
SubTitle: "Vyššia hodnota robí výstup náhodnejším",
},
TopP: {
Title: "Top P",
SubTitle: "Neupravujte túto hodnotu spolu s teplotou",
},
MaxTokens: {
Title: "Maximálny počet tokenov",
SubTitle: "Maximálna dĺžka vstupných tokenov a generovaných tokenov",
},
PresencePenalty: {
Title: "Penalizácia za prítomnosť",
SubTitle:
"Vyššia hodnota zvyšuje pravdepodobnosť hovorenia o nových témach",
},
FrequencyPenalty: {
Title: "Penalizácia za frekvenciu",
SubTitle:
"Vyššia hodnota znižuje pravdepodobnosť opakovania rovnakej línie",
},
},
Store: {
DefaultTopic: "Nová konverzácia",
BotHello: "Ahoj! Ako vám dnes môžem pomôcť?",
Error: "Niečo sa pokazilo, skúste to prosím neskôr znova.",
Prompt: {
History: (content: string) =>
"Toto je zhrnutie histórie chatu ako rekapitulácia: " + content,
Topic:
"Prosím, vygenerujte štvor- až päťslovný titul, ktorý zhrnie našu konverzáciu bez akéhokoľvek úvodu, interpunkcie, úvodzoviek, bodiek, symbolov, tučného textu alebo ďalšieho textu. Odstráňte uzatváracie úvodzovky.",
Summarize:
"Stručne zhrňte diskusiu na menej ako 200 slov, aby ste ju mohli použiť ako výzvu pre budúci kontext.",
},
},
Copy: {
Success: "Skopírované do schránky",
Failed:
"Kopírovanie zlyhalo, prosím udeľte povolenie na prístup k schránke",
},
Download: {
Success: "Obsah stiahnutý do vášho adresára.",
Failed: "Stiahnutie zlyhalo.",
},
Context: {
Toast: (x: any) => `S ${x} kontextovými výzvami`,
Edit: "Aktuálne nastavenia chatu",
Add: "Pridať výzvu",
Clear: "Kontext vyčistený",
Revert: "Vrátiť späť",
},
Plugin: {
Name: "Plugin",
},
FineTuned: {
Sysmessage: "Ste asistent, ktorý",
},
Mask: {
Name: "Maska",
Page: {
Title: "Šablóna výziev",
SubTitle: (count: number) => `${count} šablón výziev`,
Search: "Hľadať šablóny",
Create: "Vytvoriť",
},
Item: {
Info: (count: number) => `${count} výziev`,
Chat: "Chat",
View: "Zobraziť",
Edit: "Upraviť",
Delete: "Vymazať",
DeleteConfirm: "Potvrdiť vymazanie?",
},
EditModal: {
Title: (readonly: boolean) =>
`Upraviť šablónu výziev ${readonly ? "(iba na čítanie)" : ""}`,
Download: "Stiahnuť",
Clone: "Klonovať",
},
Config: {
Avatar: "Avatar robota",
Name: "Meno robota",
Sync: {
Title: "Použiť globálne nastavenia",
SubTitle: "Použiť globálne nastavenia v tomto chate",
Confirm: "Potvrdiť prepísanie vlastného nastavenia globálnym?",
},
HideContext: {
Title: "Skryť kontextové výzvy",
SubTitle: "Nezobrazovať kontextové výzvy v chate",
},
Share: {
Title: "Zdieľať túto masku",
SubTitle: "Vygenerovať odkaz na túto masku",
Action: "Kopírovať odkaz",
},
},
},
NewChat: {
Return: "Vrátiť sa",
Skip: "Len začať",
Title: "Vybrať masku",
SubTitle: "Chatovať s dušou za maskou",
More: "Nájsť viac",
NotShow: "Už nezobrazovať",
ConfirmNoShow:
"Potvrdiť deaktiváciu? Môžete ju neskôr znova povoliť v nastaveniach.",
},
UI: {
Confirm: "Potvrdiť",
Cancel: "Zrušiť",
Close: "Zavrieť",
Create: "Vytvoriť",
Edit: "Upraviť",
Export: "Exportovať",
Import: "Importovať",
Sync: "Synchronizovať",
Config: "Konfigurácia",
},
Exporter: {
Description: {
Title: "Zobrazia sa len správy po vyčistení kontextu",
},
Model: "Model",
Messages: "Správy",
Topic: "Téma",
Time: "Čas",
},
URLCommand: {
Code: "Zistený prístupový kód z URL, potvrdiť na aplikovanie?",
Settings: "Zistené nastavenia z URL, potvrdiť na aplikovanie?",
},
};
export default sk;

View File

@ -412,20 +412,21 @@ export const useChatStore = createPersistStore(
// async onUserInput(content: string, extAttr?: any) {
async onUserInput(
content: string,
extAttr?: any,
attachImages?: string[],
extAttr?: any,
) {
const session = get().currentSession();
const modelConfig = session.mask.modelConfig;
let userContent: string = "";
if (
extAttr?.mjImageMode &&
(extAttr?.useImages?.length ?? 0) > 0 &&
attachImages &&
attachImages.length > 0 &&
extAttr.mjImageMode !== "IMAGINE"
) {
if (
extAttr.mjImageMode === "BLEND" &&
(extAttr.useImages.length < 2 || extAttr.useImages.length > 5)
(attachImages.length < 2 || attachImages.length > 5)
) {
alert(Locale.Midjourney.BlendMinImg(2, 5));
return new Promise((resolve: any, reject) => {
@ -433,7 +434,7 @@ export const useChatStore = createPersistStore(
});
}
userContent = `/mj ${extAttr?.mjImageMode}`;
extAttr.useImages.forEach((img: any, index: number) => {
attachImages.forEach((img: any, index: number) => {
userContent += `::[${index + 1}]${img.filename}`;
});
} else {
@ -546,10 +547,10 @@ export const useChatStore = createPersistStore(
"POST",
JSON.stringify({
prompt: prompt,
// base64Array: extAttr?.useImages?.[0]?.base64 ?? null,
base64Array: extAttr?.useImages?.[0]?.base64
? [extAttr?.useImages?.[0]?.base64]
: null,
base64Array:
attachImages && attachImages.length > 0
? [attachImages?.[0]]
: null,
}),
);
break;
@ -559,15 +560,13 @@ export const useChatStore = createPersistStore(
"submit/describe",
"POST",
JSON.stringify({
base64: extAttr.useImages[0].base64,
base64: attachImages?.[0],
}),
);
break;
}
case "BLEND": {
const base64Array = extAttr.useImages.map(
(ui: any) => ui.base64,
);
const base64Array = attachImages;
res = await reqFn(
"submit/blend",
"POST",

View File

@ -137,7 +137,7 @@ export const useAppConfig = createPersistStore(
}),
{
name: StoreKey.Config,
version: 3.898,
version: 3.899,
migrate(persistedState, version) {
const state = persistedState as ChatConfig;
@ -168,7 +168,7 @@ export const useAppConfig = createPersistStore(
if (version < 3.8) {
state.lastUpdate = Date.now();
}
if (version < 3.898) {
if (version < 3.899) {
state.lastUpdate = Date.now();
return { ...DEFAULT_CONFIG };
}