From 36adfe87fb965120a208df907a609ec235437d06 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Thu, 11 May 2023 23:21:16 +0800 Subject: [PATCH 01/15] fix: #1401 try to disable zoom --- app/layout.tsx | 7 ++++--- app/requests.ts | 2 +- app/store/access.ts | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index c56341ab4ef..f2e765ae09d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -13,7 +13,7 @@ export const metadata = { title: "ChatGPT Next Web", statusBarStyle: "default", }, - themeColor: "#fafafa", + viewport: "width=device-width, initial-scale=1, maximum-scale=1", }; export default function RootLayout({ @@ -25,8 +25,9 @@ export default function RootLayout({ = {}; diff --git a/app/store/access.ts b/app/store/access.ts index 79b7b9900b2..4e870b616b7 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -1,6 +1,7 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { StoreKey } from "../constant"; +import { getHeaders } from "../requests"; import { BOT_HELLO } from "./chat"; import { ALL_MODELS } from "./config"; @@ -55,6 +56,9 @@ export const useAccessStore = create()( fetch("/api/config", { method: "post", body: null, + headers: { + ...getHeaders(), + }, }) .then((res) => res.json()) .then((res: DangerConfig) => { From 09feeea99a3fcefc5fb92eda75859289d2505f72 Mon Sep 17 00:00:00 2001 From: SPWwj Date: Fri, 12 May 2023 00:20:12 +0800 Subject: [PATCH 02/15] Add support for DALL-E #1358 --- app/components/ImageList.module.scss | 16 +++ app/components/ImageList.tsx | 20 ++++ app/components/chat.tsx | 2 + app/components/markdown.tsx | 29 +++++- app/components/markdown.tsx.module.scss | 10 ++ app/constant.ts | 2 + app/icons/image-error.svg | 33 ++++++ app/icons/image-placeholder.svg | 28 +++++ app/locales/cn.ts | 3 +- app/locales/en.ts | 3 +- app/requests.ts | 97 ++++++++++++++++- app/store/chat.ts | 132 +++++++++++++++++------- app/store/config.ts | 2 +- 13 files changed, 332 insertions(+), 45 deletions(-) create mode 100644 app/components/ImageList.module.scss create mode 100644 app/components/ImageList.tsx create mode 100644 app/components/markdown.tsx.module.scss create mode 100644 app/icons/image-error.svg create mode 100644 app/icons/image-placeholder.svg diff --git a/app/components/ImageList.module.scss b/app/components/ImageList.module.scss new file mode 100644 index 00000000000..3b7f1f93396 --- /dev/null +++ b/app/components/ImageList.module.scss @@ -0,0 +1,16 @@ +.imageGrid, +.imageGridSingle { + display: inline-flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +.imageGrid img { + max-width: calc(50% - 10px); + margin: 5px; +} + +.imageGridSingle img { + max-width: 100%; + margin: 5px; +} diff --git a/app/components/ImageList.tsx b/app/components/ImageList.tsx new file mode 100644 index 00000000000..01e30013eb8 --- /dev/null +++ b/app/components/ImageList.tsx @@ -0,0 +1,20 @@ +import { ImagesResponseDataInner } from "openai"; +import React, { FC } from "react"; +import styles from "./ImageList.module.scss"; + +interface ImageListProps { + images?: ImagesResponseDataInner[]; +} +const ImageList: FC = ({ images }) => { + const singleImage = images && images.length === 1; + + return ( +
+ {images && + images.map((image, index) => ( + {`Image + ))} +
+ ); +}; +export default ImageList; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index d38990372be..1b4f52b509e 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -760,6 +760,8 @@ export function Chat() { )} void }) { const ref = useRef(null); @@ -119,6 +125,8 @@ export const MarkdownContent = React.memo(_MarkDownContent); export function Markdown( props: { content: string; + images?: ImagesResponseDataInner[]; + image_alt?: string; loading?: boolean; fontSize?: number; parentRef: RefObject; @@ -171,9 +179,24 @@ export function Markdown( > {inView.current && (props.loading ? ( - +
+ {props.image_alt && } + {props.image_alt && + (props.image_alt === IMAGE_PLACEHOLDER ? ( + + ) : ( + + ))} + +
) : ( - +
+ +
+ {props.images && } + {props.image_alt && } +
+
))} ); diff --git a/app/components/markdown.tsx.module.scss b/app/components/markdown.tsx.module.scss new file mode 100644 index 00000000000..1e19384b121 --- /dev/null +++ b/app/components/markdown.tsx.module.scss @@ -0,0 +1,10 @@ +.loader { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; // Adjust as necessary +} +.content_image { + text-align: center; +} diff --git a/app/constant.ts b/app/constant.ts index d0f9fc743d1..560d57a1b5e 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -40,3 +40,5 @@ export const NARROW_SIDEBAR_WIDTH = 100; export const ACCESS_CODE_PREFIX = "ak-"; export const LAST_INPUT_KEY = "last-input"; +export const IMAGE_PLACEHOLDER = "Loading your image..."; +export const IMAGE_ERROR = "IMAGE_ERROR"; diff --git a/app/icons/image-error.svg b/app/icons/image-error.svg new file mode 100644 index 00000000000..389fc5fad2b --- /dev/null +++ b/app/icons/image-error.svg @@ -0,0 +1,33 @@ + + + + + design-and-ux/error-handling + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/icons/image-placeholder.svg b/app/icons/image-placeholder.svg new file mode 100644 index 00000000000..fc5e94fc374 --- /dev/null +++ b/app/icons/image-placeholder.svg @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 0cf3b55ec88..9d8f5c50443 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -170,7 +170,8 @@ const cn = { }, Store: { DefaultTopic: "新的聊天", - BotHello: "有什么可以帮你的吗", + BotHello: + "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `/Image {关键词}。`", Error: "出错了,稍后重试吧", Prompt: { History: (content: string) => diff --git a/app/locales/en.ts b/app/locales/en.ts index 420f169054b..1860cd0777a 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -172,7 +172,8 @@ const en: LocaleType = { }, Store: { DefaultTopic: "New Conversation", - BotHello: "Hello! How can I assist you today?", + BotHello: + "Hello! How can I assist you today?\n To generate images, use `/Image {keyword}.`", Error: "Something went wrong, please try again later.", Prompt: { History: (content: string) => diff --git a/app/requests.ts b/app/requests.ts index d38a91fd4f5..d576de0502b 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -8,8 +8,14 @@ import { useChatStore, } from "./store"; import { showToast } from "./components/ui-lib"; -import { ACCESS_CODE_PREFIX } from "./constant"; - +import { ACCESS_CODE_PREFIX, IMAGE_ERROR, IMAGE_PLACEHOLDER } from "./constant"; +import { + CreateImageRequest, + CreateImageRequestResponseFormatEnum, + CreateImageRequestSizeEnum, + ImagesResponse, + ImagesResponseDataInner, +} from "openai"; const TIME_OUT_MS = 60000; const makeRequestParam = ( @@ -144,6 +150,93 @@ export async function requestUsage() { subscription: total.hard_limit_usd, }; } +const makeImageRequestParam = ( + prompt: string, + options?: Omit, +): CreateImageRequest => { + // Set default values + const defaultOptions: Omit = { + n: 4, + size: CreateImageRequestSizeEnum._512x512, + response_format: CreateImageRequestResponseFormatEnum.Url, + user: "default_user", + }; + + // Override default values with provided options + const finalOptions = { ...defaultOptions, ...options }; + + const request: CreateImageRequest = { + prompt, + ...finalOptions, + }; + + return request; +}; +export async function requestImage( + keyword: string, + options?: { + onMessage: ( + message: string | null, + image: ImagesResponseDataInner[] | null, + image_alt: string | null, + done: boolean, + ) => void; + onError: (error: Error, statusCode?: number) => void; + onController?: (controller: AbortController) => void; + }, +) { + if (keyword.length < 1) { + options?.onMessage( + "Please enter a keyword after `/image`", + null, + null, + true, + ); + } else { + const controller = new AbortController(); + const reqTimeoutId = setTimeout(() => controller.abort(), TIME_OUT_MS); + options?.onController?.(controller); + + async function fetchImageAndUpdateMessage() { + try { + options?.onMessage(null, null, IMAGE_PLACEHOLDER, false); + + const sanitizedMessage = keyword.replace(/[\n\r]+/g, " "); + const req = makeImageRequestParam(sanitizedMessage); + + const res = await requestOpenaiClient("v1/images/generations")(req); + + clearTimeout(reqTimeoutId); + + const finish = (images: ImagesResponseDataInner[]) => { + options?.onMessage("Here is your images", images, null, true); + controller.abort(); + }; + + if (res.ok) { + const responseData = (await res.json()) as ImagesResponse; + finish(responseData.data); + } else if (res.status === 401) { + console.error("Unauthorized"); + options?.onError(new Error("Unauthorized"), res.status); + } else { + console.error("Stream Error", res.body); + options?.onError(new Error("Stream Error"), res.status); + } + } catch (err) { + console.error("NetWork Error", err); + options?.onError(err as Error); + options?.onMessage( + "Image generation has been cancelled.", + null, + IMAGE_ERROR, + true, + ); + } + } + fetchImageAndUpdateMessage(); + } +} export async function requestChatStream( messages: Message[], diff --git a/app/store/chat.ts b/app/store/chat.ts index cb11087d4ef..bea33d9ae94 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -1,10 +1,14 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -import { type ChatCompletionResponseMessage } from "openai"; +import { + ImagesResponseDataInner, + type ChatCompletionResponseMessage, +} from "openai"; import { ControllerPool, requestChatStream, + requestImage, requestWithPrompt, } from "../requests"; import { trimTopic } from "../utils"; @@ -17,6 +21,8 @@ import { StoreKey } from "../constant"; export type Message = ChatCompletionResponseMessage & { date: string; + images?: ImagesResponseDataInner[]; + image_alt?: string; streaming?: boolean; isError?: boolean; id?: number; @@ -275,48 +281,100 @@ export const useChatStore = create()( session.messages.push(botMessage); }); - // make request - console.log("[User Input] ", sendMessages); - requestChatStream(sendMessages, { - onMessage(content, done) { - // stream response - if (done) { + if (userMessage.content.startsWith("/image")) { + const keyword = userMessage.content.substring("/image".length); + console.log("keyword", keyword); + requestImage(keyword, { + onMessage(content, images, image_alt, done) { + // stream response + if (done) { + botMessage.streaming = false; + botMessage.content = content!; + botMessage.images = images!; + botMessage.image_alt = image_alt!; + get().onNewMessage(botMessage); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + } else { + botMessage.image_alt = image_alt!; + set(() => ({})); + } + }, + onError(error, statusCode) { + const isAborted = error.message.includes("aborted"); + if (statusCode === 401) { + botMessage.content = Locale.Error.Unauthorized; + } else if (!isAborted) { + botMessage.content += "\n\n" + Locale.Store.Error; + } botMessage.streaming = false; - botMessage.content = content; - get().onNewMessage(botMessage); + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + + set(() => ({})); ControllerPool.remove( sessionIndex, botMessage.id ?? messageIndex, ); - } else { - botMessage.content = content; + }, + onController(controller) { + // collect controller for stop/retry + ControllerPool.addController( + sessionIndex, + botMessage.id ?? messageIndex, + controller, + ); + }, + }); + } else { + // make request + console.log("[User Input] ", sendMessages); + requestChatStream(sendMessages, { + onMessage(content, done) { + // stream response + if (done) { + botMessage.streaming = false; + botMessage.content = content; + get().onNewMessage(botMessage); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + } else { + botMessage.content = content; + set(() => ({})); + } + }, + onError(error, statusCode) { + const isAborted = error.message.includes("aborted"); + if (statusCode === 401) { + botMessage.content = Locale.Error.Unauthorized; + } else if (!isAborted) { + botMessage.content += "\n\n" + Locale.Store.Error; + } + botMessage.streaming = false; + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + set(() => ({})); - } - }, - onError(error, statusCode) { - const isAborted = error.message.includes("aborted"); - if (statusCode === 401) { - botMessage.content = Locale.Error.Unauthorized; - } else if (!isAborted) { - botMessage.content += "\n\n" + Locale.Store.Error; - } - botMessage.streaming = false; - userMessage.isError = !isAborted; - botMessage.isError = !isAborted; - - set(() => ({})); - ControllerPool.remove(sessionIndex, botMessage.id ?? messageIndex); - }, - onController(controller) { - // collect controller for stop/retry - ControllerPool.addController( - sessionIndex, - botMessage.id ?? messageIndex, - controller, - ); - }, - modelConfig: { ...modelConfig }, - }); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + }, + onController(controller) { + // collect controller for stop/retry + ControllerPool.addController( + sessionIndex, + botMessage.id ?? messageIndex, + controller, + ); + }, + modelConfig: { ...modelConfig }, + }); + } }, getMemoryPrompt() { diff --git a/app/store/config.ts b/app/store/config.ts index 1e960456ff4..ddc8ef1c7e0 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -17,7 +17,7 @@ export enum Theme { } export const DEFAULT_CONFIG = { - submitKey: SubmitKey.CtrlEnter as SubmitKey, + submitKey: SubmitKey.Enter as SubmitKey, avatar: "1f603", fontSize: 14, theme: Theme.Auto as Theme, From 377579e80278fcad9135d500cf30f3d5f13cc117 Mon Sep 17 00:00:00 2001 From: Yifei Zhang Date: Fri, 12 May 2023 17:19:40 +0800 Subject: [PATCH 03/15] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 90ed7d42f94..b36f4a4a758 100644 --- a/README.md +++ b/README.md @@ -265,6 +265,7 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s [@jhansion](https://github.com/jhansion) [@Sha1rholder](https://github.com/Sha1rholder) [@AnsonHyq](https://github.com/AnsonHyq) +[@synwith](https://github.com/synwith) ### Contributor From 93c9974019002b57d8184c23d70f68390be316c0 Mon Sep 17 00:00:00 2001 From: wsw <944627549@qq.com> Date: Fri, 12 May 2023 17:54:40 +0800 Subject: [PATCH 04/15] feat: scrolling effect when switching chat windows --- app/components/chat-list.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx index 02ea086b2e9..c1365182c49 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list.tsx @@ -16,6 +16,7 @@ import { Link, useNavigate } from "react-router-dom"; import { Path } from "../constant"; import { MaskAvatar } from "./mask"; import { Mask } from "../store/mask"; +import { useRef, useEffect } from "react"; export function ChatItem(props: { onClick?: () => void; @@ -29,6 +30,14 @@ export function ChatItem(props: { narrow?: boolean; mask: Mask; }) { + const draggableRef = useRef(null); + useEffect(() => { + if (props.selected && draggableRef.current) { + draggableRef.current?.scrollIntoView({ + block: "center", + }); + } + }, [props.selected]); return ( {(provided) => ( @@ -37,7 +46,10 @@ export function ChatItem(props: { props.selected && styles["chat-item-selected"] }`} onClick={props.onClick} - ref={provided.innerRef} + ref={(ele) => { + draggableRef.current = ele; + provided.innerRef(ele); + }} {...provided.draggableProps} {...provided.dragHandleProps} title={`${props.title}\n${Locale.ChatItem.ChatItemCount( From 170936a96ef9b59ac8a95d0201c34ef6d9438644 Mon Sep 17 00:00:00 2001 From: Yorun <547747006@qq.com> Date: Fri, 12 May 2023 18:47:41 +0800 Subject: [PATCH 05/15] fix: the theme-color selector --- app/components/home.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/home.tsx b/app/components/home.tsx index 4c3d0a6464f..6b34a5a1b84 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -64,17 +64,17 @@ export function useSwitchTheme() { } const metaDescriptionDark = document.querySelector( - 'meta[name="theme-color"][media]', + 'meta[name="theme-color"][media*="dark"]', ); const metaDescriptionLight = document.querySelector( - 'meta[name="theme-color"]:not([media])', + 'meta[name="theme-color"][media*="light"]', ); if (config.theme === "auto") { metaDescriptionDark?.setAttribute("content", "#151515"); metaDescriptionLight?.setAttribute("content", "#fafafa"); } else { - const themeColor = getCSSVar("--themeColor"); + const themeColor = getCSSVar("--theme-color"); metaDescriptionDark?.setAttribute("content", themeColor); metaDescriptionLight?.setAttribute("content", themeColor); } From dd5604f5d9d21a5e10f9d4609072d7f118463072 Mon Sep 17 00:00:00 2001 From: Yorun <547747006@qq.com> Date: Fri, 12 May 2023 19:23:49 +0800 Subject: [PATCH 06/15] style: move nextjs supported meta tags to metadata --- app/layout.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index f2e765ae09d..d08f87e4481 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -9,11 +9,19 @@ const buildConfig = getBuildConfig(); export const metadata = { title: "ChatGPT Next Web", description: "Your personal ChatGPT Chat Bot.", + viewport: { + width: "device-width", + initialScale: 1, + maximumScale: 1, + }, + themeColor: [ + { media: "(prefers-color-scheme: light)", color: "#fafafa" }, + { media: "(prefers-color-scheme: dark)", color: "#151515" }, + ], appleWebApp: { title: "ChatGPT Next Web", statusBarStyle: "default", }, - viewport: "width=device-width, initial-scale=1, maximum-scale=1", }; export default function RootLayout({ @@ -24,22 +32,12 @@ export default function RootLayout({ return ( - - From dc3fa6c780797b8b969e6b9b485a97e2f1ce6311 Mon Sep 17 00:00:00 2001 From: PaRaD1SE98 Date: Fri, 12 May 2023 22:46:22 +0900 Subject: [PATCH 07/15] Update settings.tsx fix: typo upater -> updater --- app/components/settings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 2e08c251e2e..eb83d8905f7 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -573,9 +573,9 @@ export function Settings() { { + updateConfig={(updater) => { const modelConfig = { ...config.modelConfig }; - upater(modelConfig); + updater(modelConfig); config.update((config) => (config.modelConfig = modelConfig)); }} /> From a0e192b6e4ed5717e8bcd9ec787a012c73e0a9e2 Mon Sep 17 00:00:00 2001 From: "ShengYan, Zhang" Date: Sat, 13 May 2023 07:23:14 +0800 Subject: [PATCH 08/15] fix: show Vitenamese in it's own language --- app/locales/cn.ts | 2 +- app/locales/cs.ts | 15 ++++---- app/locales/de.ts | 2 +- app/locales/en.ts | 2 +- app/locales/es.ts | 2 +- app/locales/it.ts | 2 +- app/locales/jp.ts | 2 +- app/locales/ru.ts | 97 +++++++++++++++++++++++++---------------------- app/locales/tr.ts | 2 +- app/locales/tw.ts | 2 +- app/locales/vi.ts | 4 +- 11 files changed, 68 insertions(+), 64 deletions(-) diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 0cf3b55ec88..b955a7d2bc4 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -78,7 +78,7 @@ const cn = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/cs.ts b/app/locales/cs.ts index ab9b39a5387..6d614575e47 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -70,8 +70,8 @@ const cs: LocaleType = { }, Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` - All: "Všechny jazyky", - Options: { + All: "Všechny jazyky", + Options: { cn: "简体中文", en: "English", tw: "繁體中文", @@ -80,7 +80,7 @@ const cs: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, @@ -166,8 +166,7 @@ const cs: LocaleType = { }, PresencePenlty: { Title: "Přítomnostní korekce", - SubTitle: - "Větší hodnota zvyšuje pravděpodobnost nových témat.", + SubTitle: "Větší hodnota zvyšuje pravděpodobnost nových témat.", }, }, Store: { @@ -182,7 +181,7 @@ const cs: LocaleType = { "Vytvořte prosím název o čtyřech až pěti slovech vystihující průběh našeho rozhovoru bez jakýchkoli úvodních slov, interpunkčních znamének, uvozovek, teček, symbolů nebo dalšího textu. Odstraňte uvozovky.", Summarize: "Krátce shrň naši diskusi v rozsahu do 200 slov a použij ji jako podnět pro budoucí kontext.", - }, + }, }, Copy: { Success: "Zkopírováno do schránky", @@ -231,7 +230,7 @@ const cs: LocaleType = { More: "Najít více", NotShow: "Nezobrazovat znovu", ConfirmNoShow: "Potvrdit zakázání?Můžete jej povolit později v nastavení.", -}, + }, UI: { Confirm: "Potvrdit", @@ -239,7 +238,7 @@ const cs: LocaleType = { Close: "Zavřít", Create: "Vytvořit", Edit: "Upravit", - } + }, }; export default cs; diff --git a/app/locales/de.ts b/app/locales/de.ts index 8cfe3be4515..02510070cbb 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -81,7 +81,7 @@ const de: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/en.ts b/app/locales/en.ts index 420f169054b..b17408bd420 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -80,7 +80,7 @@ const en: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/es.ts b/app/locales/es.ts index 5f66071ce00..b80faf23c88 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -80,7 +80,7 @@ const es: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/it.ts b/app/locales/it.ts index f9daa7a37f6..e711216627e 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -80,7 +80,7 @@ const it: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 526574b308d..dbb9980fe00 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -80,7 +80,7 @@ const jp: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 437a54b2ba8..6770f521321 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -80,56 +80,57 @@ const ru: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, }, - Avatar: "Аватар", - FontSize: { - Title: "Размер шрифта", - SubTitle: "Настроить размер шрифта контента чата", - }, - Update: { - Version: (x: string) => `Версия: ${x}`, - IsLatest: "Последняя версия", - CheckUpdate: "Проверить обновление", - IsChecking: "Проверка обновления...", - FoundUpdate: (x: string) => `Найдена новая версия: ${x}`, - GoToUpdate: "Обновить", - }, - SendKey: "Клавиша отправки", - Theme: "Тема", - TightBorder: "Узкая граница", - SendPreviewBubble: { - Title: "Отправить предпросмотр", - SubTitle: "Предварительный просмотр markdown в пузыре", + Avatar: "Аватар", + FontSize: { + Title: "Размер шрифта", + SubTitle: "Настроить размер шрифта контента чата", + }, + Update: { + Version: (x: string) => `Версия: ${x}`, + IsLatest: "Последняя версия", + CheckUpdate: "Проверить обновление", + IsChecking: "Проверка обновления...", + FoundUpdate: (x: string) => `Найдена новая версия: ${x}`, + GoToUpdate: "Обновить", + }, + SendKey: "Клавиша отправки", + Theme: "Тема", + TightBorder: "Узкая граница", + SendPreviewBubble: { + Title: "Отправить предпросмотр", + SubTitle: "Предварительный просмотр markdown в пузыре", + }, + Mask: { + Title: "Экран заставки маски", + SubTitle: "Показывать экран заставки маски перед началом нового чата", + }, + Prompt: { + Disable: { + Title: "Отключить автозаполнение", + SubTitle: "Ввод / для запуска автозаполнения", }, - Mask: { - Title: "Экран заставки маски", - SubTitle: "Показывать экран заставки маски перед началом нового чата", + List: "Список подсказок", + ListCount: (builtin: number, custom: number) => + `${builtin} встроенных, ${custom} пользовательских`, + Edit: "Редактировать", + Modal: { + Title: "Список подсказок", + Add: "Добавить", + Search: "Поиск подсказок", }, - Prompt: { - Disable: { - Title: "Отключить автозаполнение", - SubTitle: "Ввод / для запуска автозаполнения", - }, - List: "Список подсказок", - ListCount: (builtin: number, custom: number) => - `${builtin} встроенных, ${custom} пользовательских`, - Edit: "Редактировать", - Modal: { - Title: "Список подсказок", - Add: "Добавить", - Search: "Поиск подсказок", - }, - EditModal: { - Title: "Редактировать подсказку", - }, + EditModal: { + Title: "Редактировать подсказку", }, - HistoryCount: { - Title: "Количество прикрепляемых сообщений", - SubTitle: "Количество отправляемых сообщений, прикрепляемых к каждому запросу", + }, + HistoryCount: { + Title: "Количество прикрепляемых сообщений", + SubTitle: + "Количество отправляемых сообщений, прикрепляемых к каждому запросу", }, CompressThreshold: { Title: "Порог сжатия истории", @@ -186,7 +187,8 @@ const ru: LocaleType = { }, Copy: { Success: "Скопировано в буфер обмена", - Failed: "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", + Failed: + "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", }, Context: { Toast: (x: any) => `С ${x} контекстными подсказками`, @@ -214,7 +216,9 @@ const ru: LocaleType = { }, EditModal: { Title: (readonly: boolean) => - `Редактирование шаблона подсказки ${readonly ? "(только для чтения)" : ""}`, + `Редактирование шаблона подсказки ${ + readonly ? "(только для чтения)" : "" + }`, Download: "Скачать", Clone: "Клонировать", }, @@ -230,7 +234,8 @@ const ru: LocaleType = { SubTitle: "Общайтесь с душой за маской", More: "Найти еще", NotShow: "Не показывать снова", - ConfirmNoShow: "Подтвердите отключение? Вы можете включить это позже в настройках.", + ConfirmNoShow: + "Подтвердите отключение? Вы можете включить это позже в настройках.", }, UI: { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 42c3f78ebd1..e27f28580ef 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -80,7 +80,7 @@ const tr: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/tw.ts b/app/locales/tw.ts index a8dbf91a5ed..e115a0f6a5d 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -78,7 +78,7 @@ const tw: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, diff --git a/app/locales/vi.ts b/app/locales/vi.ts index d3be61058d9..9568a125a33 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -2,7 +2,7 @@ import { SubmitKey } from "../store/config"; import type { LocaleType } from "./index"; const vi: LocaleType = { - WIP: "Coming Soon...", + WIP: "Sắp ra mắt...", Error: { Unauthorized: "Truy cập chưa xác thực, vui lòng nhập mã truy cập trong trang cài đặt.", @@ -80,7 +80,7 @@ const vi: LocaleType = { tr: "Türkçe", jp: "日本語", de: "Deutsch", - vi: "Vietnamese", + vi: "Tiếng Việt", ru: "Русский", cs: "Čeština", }, From f07e4fc87fe7a53a0d0b18f3c2a07c653014e5d9 Mon Sep 17 00:00:00 2001 From: "ShengYan, Zhang" Date: Sat, 13 May 2023 09:02:15 +0800 Subject: [PATCH 09/15] docs: add supported languages to README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b36f4a4a758..a3c10a339e0 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ One-Click to deploy well-designed ChatGPT web UI on Vercel. - New in v2: create, share and debug your chat tools with prompt templates (mask) - Awesome prompts powered by [awesome-chatgpt-prompts-zh](https://github.com/PlexPt/awesome-chatgpt-prompts-zh) and [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts) - Automatically compresses chat history to support long conversations while also saving your tokens -- I18n: English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch +- I18n: English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština ## Roadmap @@ -62,7 +62,7 @@ One-Click to deploy well-designed ChatGPT web UI on Vercel. - 预制角色功能(面具),方便地创建、分享和调试你的个性化对话 - 海量的内置 prompt 列表,来自[中文](https://github.com/PlexPt/awesome-chatgpt-prompts-zh)和[英文](https://github.com/f/awesome-chatgpt-prompts) - 自动压缩上下文聊天记录,在节省 Token 的同时支持超长对话 -- 多国语言支持:English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch +- 多国语言支持:English, 简体中文, 繁体中文, 日本語, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština - 拥有自己的域名?好上加好,绑定后即可在任何地方**无障碍**快速访问 ## 开发计划 From e2be9ae1ec6e192d5f5f1ca83b578ea21ec6fb07 Mon Sep 17 00:00:00 2001 From: SPWwj Date: Sat, 13 May 2023 09:13:20 +0800 Subject: [PATCH 10/15] Add Setting to imageModel --- app/api/openai/typing.ts | 3 +- app/components/ImageList.tsx | 2 +- app/components/chat.tsx | 5 +- app/components/image-model-config.tsx | 74 ++++++++++++++++++ app/components/settings.tsx | 13 ++++ app/constant.ts | 1 + app/locales/cn.ts | 14 +++- app/locales/cs.ts | 24 ++++-- app/locales/de.ts | 11 +++ app/locales/en.ts | 14 +++- app/locales/es.ts | 11 +++ app/locales/it.ts | 11 +++ app/locales/jp.ts | 11 +++ app/locales/ru.ts | 106 +++++++++++++++----------- app/locales/tr.ts | 11 +++ app/locales/tw.ts | 9 +++ app/locales/vi.ts | 11 +++ app/requests.ts | 3 +- app/store/access.ts | 7 +- app/store/chat.ts | 24 ++++-- app/store/config.ts | 25 +++++- app/store/mask.ts | 10 ++- 22 files changed, 323 insertions(+), 77 deletions(-) create mode 100644 app/components/image-model-config.tsx diff --git a/app/api/openai/typing.ts b/app/api/openai/typing.ts index 2286d23124e..82d401f0797 100644 --- a/app/api/openai/typing.ts +++ b/app/api/openai/typing.ts @@ -1,9 +1,10 @@ import type { CreateChatCompletionRequest, CreateChatCompletionResponse, + CreateImageRequestSizeEnum, } from "openai"; export type ChatRequest = CreateChatCompletionRequest; export type ChatResponse = CreateChatCompletionResponse; - +export type ImageRequestSizeEnum = CreateImageRequestSizeEnum; export type Updater = (updater: (value: T) => void) => void; diff --git a/app/components/ImageList.tsx b/app/components/ImageList.tsx index 01e30013eb8..8d649f45431 100644 --- a/app/components/ImageList.tsx +++ b/app/components/ImageList.tsx @@ -1,6 +1,6 @@ import { ImagesResponseDataInner } from "openai"; import React, { FC } from "react"; -import styles from "./ImageList.module.scss"; +import styles from "./imageList.module.scss"; interface ImageListProps { images?: ImagesResponseDataInner[]; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 1b4f52b509e..0ff363fb694 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -25,7 +25,6 @@ import { Message, SubmitKey, useChatStore, - BOT_HELLO, createMessage, useAccessStore, Theme, @@ -560,9 +559,9 @@ export function Chat() { if ( context.length === 0 && - session.messages.at(0)?.content !== BOT_HELLO.content + session.messages.at(0)?.content !== session.botHello.content ) { - const copiedHello = Object.assign({}, BOT_HELLO); + const copiedHello = Object.assign({}, session.botHello); if (!accessStore.isAuthorized()) { copiedHello.content = Locale.Error.Unauthorized; } diff --git a/app/components/image-model-config.tsx b/app/components/image-model-config.tsx new file mode 100644 index 00000000000..aea8f80cdb9 --- /dev/null +++ b/app/components/image-model-config.tsx @@ -0,0 +1,74 @@ +import { + ALL_MODELS, + ImageModalConfigValidator, + ImageModelConfig, + ModalConfigValidator, + ModelConfig, +} from "../store"; + +import Locale from "../locales"; +import { InputRange } from "./input-range"; +import { Input, List, ListItem, Select } from "./ui-lib"; +import { ImageRequestSizeEnum } from "../api/openai/typing"; +import { CreateImageRequestSizeEnum } from "openai"; + +export function ImageModelConfigList(props: { + imageModelConfig: ImageModelConfig; + updateConfig: (updater: (config: ImageModelConfig) => void) => void; +}) { + return ( + <> + + + + + { + props.updateConfig((config) => { + config.command = e.currentTarget.value; // Assign the parsed value + return config; + }); + }} + /> + + + { + const newValue = parseInt(e.currentTarget.value, 10); // Parse the value as an integer + if (!isNaN(newValue)) { + props.updateConfig((config) => { + config.imageLimit = newValue; // Assign the parsed value + return config; + }); + } + }} + min={"1"} // Convert the min value to a string + max={"10"} // Convert the max value to a string + step={"1"} // Convert the step value to a string + /> + + + + + + ); +} diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 2e08c251e2e..82c28e0a0d3 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -40,6 +40,7 @@ import { ErrorBoundary } from "./error"; import { InputRange } from "./input-range"; import { useNavigate } from "react-router-dom"; import { Avatar, AvatarPicker } from "./emoji"; +import { ImageModelConfigList } from "./image-model-config"; function EditPromptModal(props: { id: number; onClose: () => void }) { const promptStore = usePromptStore(); @@ -580,6 +581,18 @@ export function Settings() { }} /> + + { + const imageModelConfig = { ...config.imageModelConfig }; + upater(imageModelConfig); + config.update( + (config) => (config.imageModelConfig = imageModelConfig), + ); + }} + /> + {shouldShowPromptModal && ( setShowPromptModal(false)} /> diff --git a/app/constant.ts b/app/constant.ts index 560d57a1b5e..36ca672a729 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -42,3 +42,4 @@ export const ACCESS_CODE_PREFIX = "ak-"; export const LAST_INPUT_KEY = "last-input"; export const IMAGE_PLACEHOLDER = "Loading your image..."; export const IMAGE_ERROR = "IMAGE_ERROR"; +export const COMMAND_IMAGE = "/image"; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 9d8f5c50443..7403f1cdd2f 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -155,6 +155,13 @@ const cn = { Placeholder: "请输入访问密码", }, Model: "模型 (model)", + ImageModel: { + Title: "图片模型", + Model: "DALL-E模型", + Command: "生成图片指令", + CountLimit: "图片生成次数限制", + Size: "图片生成尺寸", + }, Temperature: { Title: "随机性 (temperature)", SubTitle: "值越大,回复越随机", @@ -170,8 +177,11 @@ const cn = { }, Store: { DefaultTopic: "新的聊天", - BotHello: - "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `/Image {关键词}。`", + BotHello: "您好!今天我能为您做些什么呢?", + BotHelloWithCommand: (command: string) => + "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `" + + command + + " {关键词}。`", Error: "出错了,稍后重试吧", Prompt: { History: (content: string) => diff --git a/app/locales/cs.ts b/app/locales/cs.ts index ab9b39a5387..47909dffedb 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -70,8 +70,8 @@ const cs: LocaleType = { }, Lang: { Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` - All: "Všechny jazyky", - Options: { + All: "Všechny jazyky", + Options: { cn: "简体中文", en: "English", tw: "繁體中文", @@ -156,6 +156,13 @@ const cs: LocaleType = { Placeholder: "Potřebujete přístupový kód", }, Model: "Model", + ImageModel: { + Title: "Obrázkový model", + Model: "Model DALL-E", + Command: "Příkaz pro generování obrázků", + CountLimit: "Limit počtu generovaných obrázků", + Size: "Velikost generovaného obrázku", + }, Temperature: { Title: "Teplota", SubTitle: "Větší hodnota činí výstup náhodnějším", @@ -166,13 +173,16 @@ const cs: LocaleType = { }, PresencePenlty: { Title: "Přítomnostní korekce", - SubTitle: - "Větší hodnota zvyšuje pravděpodobnost nových témat.", + SubTitle: "Větší hodnota zvyšuje pravděpodobnost nových témat.", }, }, Store: { DefaultTopic: "Nová konverzace", BotHello: "Ahoj! Jak mohu dnes pomoci?", + BotHelloWithCommand: (command: string) => + "Ahoj! Jak mohu dnes pomoci?\n Pro generování obrázků použijte `" + + command + + " {klíčové slovo}.`", Error: "Něco se pokazilo, zkuste to prosím později.", Prompt: { History: (content: string) => @@ -182,7 +192,7 @@ const cs: LocaleType = { "Vytvořte prosím název o čtyřech až pěti slovech vystihující průběh našeho rozhovoru bez jakýchkoli úvodních slov, interpunkčních znamének, uvozovek, teček, symbolů nebo dalšího textu. Odstraňte uvozovky.", Summarize: "Krátce shrň naši diskusi v rozsahu do 200 slov a použij ji jako podnět pro budoucí kontext.", - }, + }, }, Copy: { Success: "Zkopírováno do schránky", @@ -231,7 +241,7 @@ const cs: LocaleType = { More: "Najít více", NotShow: "Nezobrazovat znovu", ConfirmNoShow: "Potvrdit zakázání?Můžete jej povolit později v nastavení.", -}, + }, UI: { Confirm: "Potvrdit", @@ -239,7 +249,7 @@ const cs: LocaleType = { Close: "Zavřít", Create: "Vytvořit", Edit: "Upravit", - } + }, }; export default cs; diff --git a/app/locales/de.ts b/app/locales/de.ts index 8cfe3be4515..8024ebd76eb 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -158,6 +158,13 @@ const de: LocaleType = { Placeholder: "Zugangscode erforderlich", }, Model: "Modell", + ImageModel: { + Title: "Bildmodell", + Model: "DALL-E Modell", + Command: "Bildgenerierungsbefehl", + CountLimit: "Bildgenerierungslimit", + Size: "Bildgenerierungsgröße", + }, Temperature: { Title: "Temperature", //Temperatur SubTitle: "Ein größerer Wert führt zu zufälligeren Antworten", @@ -175,6 +182,10 @@ const de: LocaleType = { Store: { DefaultTopic: "Neues Gespräch", BotHello: "Hallo! Wie kann ich Ihnen heute helfen?", + BotHelloWithCommand: (command: string) => + "Hallo! Wie kann ich Ihnen heute helfen?\n Um Bilder zu generieren, verwenden Sie `" + + command + + " {Schlüsselwort}.`", Error: "Etwas ist schief gelaufen, bitte versuchen Sie es später noch einmal.", Prompt: { diff --git a/app/locales/en.ts b/app/locales/en.ts index 1860cd0777a..04ba5a4c348 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -156,6 +156,13 @@ const en: LocaleType = { Placeholder: "Need Access Code", }, Model: "Model", + ImageModel: { + Title: "Image Model", + Model: "DALL-E Model", + Command: "Generate Image Command", + CountLimit: "Image Generation Limit", + Size: "Image Generation Size", + }, Temperature: { Title: "Temperature", SubTitle: "A larger value makes the more random output", @@ -172,8 +179,11 @@ const en: LocaleType = { }, Store: { DefaultTopic: "New Conversation", - BotHello: - "Hello! How can I assist you today?\n To generate images, use `/Image {keyword}.`", + BotHello: "Hello! How can I assist you today?", + BotHelloWithCommand: (command: string) => + "Hello! How can I assist you today?\n To generate images, use `" + + command + + " {keyword}.`", Error: "Something went wrong, please try again later.", Prompt: { History: (content: string) => diff --git a/app/locales/es.ts b/app/locales/es.ts index 5f66071ce00..f7bf5f4c6a2 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -156,6 +156,13 @@ const es: LocaleType = { Placeholder: "Necesita código de acceso", }, Model: "Modelo", + ImageModel: { + Title: "Modelo de imagen", + Model: "Modelo DALL-E", + Command: "Comando de generación de imágenes", + CountLimit: "Límite de generación de imágenes", + Size: "Tamaño de generación de imagen", + }, Temperature: { Title: "Temperatura", SubTitle: "Un valor mayor genera una salida más aleatoria", @@ -173,6 +180,10 @@ const es: LocaleType = { Store: { DefaultTopic: "Nueva conversación", BotHello: "¡Hola! ¿Cómo puedo ayudarte hoy?", + BotHelloWithCommand: (command: string) => + "¡Hola! ¿Cómo puedo ayudarte hoy?\n Para generar imágenes, usa `" + + command + + " {palabra clave}.`", Error: "Algo salió mal, por favor intenta nuevamente más tarde.", Prompt: { History: (content: string) => diff --git a/app/locales/it.ts b/app/locales/it.ts index f9daa7a37f6..6c2c4c2f534 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -157,6 +157,13 @@ const it: LocaleType = { Placeholder: "Inserisci il codice d'accesso", }, Model: "Modello GPT", + ImageModel: { + Title: "Modello di immagine", + Model: "Modello DALL-E", + Command: "Comando di generazione immagine", + CountLimit: "Limite di generazione immagine", + Size: "Dimensione di generazione immagine", + }, Temperature: { Title: "Temperature", SubTitle: "Un valore maggiore rende l'output più casuale", @@ -174,6 +181,10 @@ const it: LocaleType = { Store: { DefaultTopic: "Nuova conversazione", BotHello: "Ciao, come posso aiutarti oggi?", + BotHelloWithCommand: (command: string) => + "Ciao, come posso aiutarti oggi?\n Per generare immagini, usa `" + + command + + " {parola chiave}.`", Error: "Qualcosa è andato storto, riprova più tardi.", Prompt: { History: (content: string) => diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 526574b308d..ef8a0049e1e 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -158,6 +158,13 @@ const jp: LocaleType = { Placeholder: "アクセスパスワードを入力してください", }, Model: "モデル (model)", + ImageModel: { + Title: "画像モデル", + Model: "DALL-Eモデル", + Command: "画像生成コマンド", + CountLimit: "画像生成回数制限", + Size: "画像生成サイズ", + }, Temperature: { Title: "ランダム性 (temperature)", SubTitle: @@ -175,6 +182,10 @@ const jp: LocaleType = { Store: { DefaultTopic: "新しいチャット", BotHello: "何かお手伝いできることはありますか", + BotHelloWithCommand: (command: string) => + "何かお手伝いできることはありますか\n 画像を生成するには、`" + + command + + " {キーワード}.`を使用してください", Error: "エラーが発生しました。しばらくしてからやり直してください。", Prompt: { History: (content: string) => diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 437a54b2ba8..50dde81420a 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -85,51 +85,52 @@ const ru: LocaleType = { cs: "Čeština", }, }, - Avatar: "Аватар", - FontSize: { - Title: "Размер шрифта", - SubTitle: "Настроить размер шрифта контента чата", - }, - Update: { - Version: (x: string) => `Версия: ${x}`, - IsLatest: "Последняя версия", - CheckUpdate: "Проверить обновление", - IsChecking: "Проверка обновления...", - FoundUpdate: (x: string) => `Найдена новая версия: ${x}`, - GoToUpdate: "Обновить", - }, - SendKey: "Клавиша отправки", - Theme: "Тема", - TightBorder: "Узкая граница", - SendPreviewBubble: { - Title: "Отправить предпросмотр", - SubTitle: "Предварительный просмотр markdown в пузыре", + Avatar: "Аватар", + FontSize: { + Title: "Размер шрифта", + SubTitle: "Настроить размер шрифта контента чата", + }, + Update: { + Version: (x: string) => `Версия: ${x}`, + IsLatest: "Последняя версия", + CheckUpdate: "Проверить обновление", + IsChecking: "Проверка обновления...", + FoundUpdate: (x: string) => `Найдена новая версия: ${x}`, + GoToUpdate: "Обновить", + }, + SendKey: "Клавиша отправки", + Theme: "Тема", + TightBorder: "Узкая граница", + SendPreviewBubble: { + Title: "Отправить предпросмотр", + SubTitle: "Предварительный просмотр markdown в пузыре", + }, + Mask: { + Title: "Экран заставки маски", + SubTitle: "Показывать экран заставки маски перед началом нового чата", + }, + Prompt: { + Disable: { + Title: "Отключить автозаполнение", + SubTitle: "Ввод / для запуска автозаполнения", }, - Mask: { - Title: "Экран заставки маски", - SubTitle: "Показывать экран заставки маски перед началом нового чата", + List: "Список подсказок", + ListCount: (builtin: number, custom: number) => + `${builtin} встроенных, ${custom} пользовательских`, + Edit: "Редактировать", + Modal: { + Title: "Список подсказок", + Add: "Добавить", + Search: "Поиск подсказок", }, - Prompt: { - Disable: { - Title: "Отключить автозаполнение", - SubTitle: "Ввод / для запуска автозаполнения", - }, - List: "Список подсказок", - ListCount: (builtin: number, custom: number) => - `${builtin} встроенных, ${custom} пользовательских`, - Edit: "Редактировать", - Modal: { - Title: "Список подсказок", - Add: "Добавить", - Search: "Поиск подсказок", - }, - EditModal: { - Title: "Редактировать подсказку", - }, + EditModal: { + Title: "Редактировать подсказку", }, - HistoryCount: { - Title: "Количество прикрепляемых сообщений", - SubTitle: "Количество отправляемых сообщений, прикрепляемых к каждому запросу", + }, + HistoryCount: { + Title: "Количество прикрепляемых сообщений", + SubTitle: + "Количество отправляемых сообщений, прикрепляемых к каждому запросу", }, CompressThreshold: { Title: "Порог сжатия истории", @@ -156,6 +157,13 @@ const ru: LocaleType = { Placeholder: "Требуется код доступа", }, Model: "Модель", + ImageModel: { + Title: "Модель изображения", + Model: "Модель DALL-E", + Command: "Команда генерации изображений", + CountLimit: "Лимит генерации изображений", + Size: "Размер генерируемого изображения", + }, Temperature: { Title: "Температура", SubTitle: "Чем выше значение, тем более случайный вывод", @@ -173,6 +181,10 @@ const ru: LocaleType = { Store: { DefaultTopic: "Новый разговор", BotHello: "Здравствуйте! Как я могу вам помочь сегодня?", + BotHelloWithCommand: (command: string) => + "Здравствуйте! Как я могу вам помочь сегодня?\n Чтобы создать изображения, используйте `" + + command + + " {ключевое слово}.`", Error: "Что-то пошло не так. Пожалуйста, попробуйте еще раз позже.", Prompt: { History: (content: string) => @@ -186,7 +198,8 @@ const ru: LocaleType = { }, Copy: { Success: "Скопировано в буфер обмена", - Failed: "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", + Failed: + "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", }, Context: { Toast: (x: any) => `С ${x} контекстными подсказками`, @@ -214,7 +227,9 @@ const ru: LocaleType = { }, EditModal: { Title: (readonly: boolean) => - `Редактирование шаблона подсказки ${readonly ? "(только для чтения)" : ""}`, + `Редактирование шаблона подсказки ${ + readonly ? "(только для чтения)" : "" + }`, Download: "Скачать", Clone: "Клонировать", }, @@ -230,7 +245,8 @@ const ru: LocaleType = { SubTitle: "Общайтесь с душой за маской", More: "Найти еще", NotShow: "Не показывать снова", - ConfirmNoShow: "Подтвердите отключение? Вы можете включить это позже в настройках.", + ConfirmNoShow: + "Подтвердите отключение? Вы можете включить это позже в настройках.", }, UI: { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 42c3f78ebd1..83207086e3e 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -156,6 +156,13 @@ const tr: LocaleType = { Placeholder: "Erişim Kodu Gerekiyor", }, Model: "Model", + ImageModel: { + Title: "Resim Modeli", + Model: "DALL-E Modeli", + Command: "Resim Oluşturma Komutu", + CountLimit: "Resim Oluşturma Limiti", + Size: "Resim Oluşturma Boyutu", + }, Temperature: { Title: "Gerçeklik", SubTitle: @@ -175,6 +182,10 @@ const tr: LocaleType = { Store: { DefaultTopic: "Yeni Konuşma", BotHello: "Merhaba! Size bugün nasıl yardımcı olabilirim?", + BotHelloWithCommand: (command: string) => + "Merhaba! Size bugün nasıl yardımcı olabilirim?\n Resim oluşturmak için, `" + + command + + " {anahtar kelime}.` kullanın", Error: "Bir şeyler yanlış gitti. Lütfen daha sonra tekrar deneyiniz.", Prompt: { History: (content: string) => diff --git a/app/locales/tw.ts b/app/locales/tw.ts index a8dbf91a5ed..4534c135aa2 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -153,6 +153,13 @@ const tw: LocaleType = { Placeholder: "請輸入授權碼", }, Model: "模型 (model)", + ImageModel: { + Title: "圖片模型", + Model: "DALL-E模型", + Command: "生成圖片指令", + CountLimit: "圖片生成次數限制", + Size: "圖片生成尺寸", + }, Temperature: { Title: "隨機性 (temperature)", SubTitle: "值越大,回應越隨機", @@ -169,6 +176,8 @@ const tw: LocaleType = { Store: { DefaultTopic: "新的對話", BotHello: "請問需要我的協助嗎?", + BotHelloWithCommand: (command: string) => + "請問需要我的協助嗎?\n 若要生成圖片,請使用 `" + command + " {關鍵字}.`", Error: "出錯了,請稍後再嘗試", Prompt: { History: (content: string) => diff --git a/app/locales/vi.ts b/app/locales/vi.ts index d3be61058d9..d16cfb4d1b9 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -155,6 +155,13 @@ const vi: LocaleType = { Placeholder: "Nhập mã truy cập", }, Model: "Mô hình", + ImageModel: { + Title: "Mô hình hình ảnh", + Model: "Mô hình DALL-E", + Command: "Lệnh tạo hình ảnh", + CountLimit: "Giới hạn số lượng hình ảnh tạo ra", + Size: "Kích thước hình ảnh được tạo ra", + }, Temperature: { Title: "Tính ngẫu nhiên (temperature)", SubTitle: "Giá trị càng lớn, câu trả lời càng ngẫu nhiên", @@ -171,6 +178,10 @@ const vi: LocaleType = { Store: { DefaultTopic: "Cuộc trò chuyện mới", BotHello: "Xin chào! Mình có thể giúp gì cho bạn?", + BotHelloWithCommand: (command: string) => + "Xin chào! Mình có thể giúp gì cho bạn?\n Để tạo hình ảnh, hãy sử dụng `" + + command + + " {từ khóa}.`", Error: "Có lỗi xảy ra, vui lòng thử lại sau.", Prompt: { History: (content: string) => diff --git a/app/requests.ts b/app/requests.ts index d576de0502b..75b4d4c3a17 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -156,8 +156,7 @@ const makeImageRequestParam = ( ): CreateImageRequest => { // Set default values const defaultOptions: Omit = { - n: 4, - size: CreateImageRequestSizeEnum._512x512, + n: useAppConfig.getState().imageModelConfig.imageLimit, response_format: CreateImageRequestResponseFormatEnum.Url, user: "default_user", }; diff --git a/app/store/access.ts b/app/store/access.ts index 79b7b9900b2..15e0bcdd72a 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -1,7 +1,6 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { StoreKey } from "../constant"; -import { BOT_HELLO } from "./chat"; import { ALL_MODELS } from "./config"; export interface AccessControlStore { @@ -69,9 +68,9 @@ export const useAccessStore = create()( }); } - if ((res as any).botHello) { - BOT_HELLO.content = (res as any).botHello; - } + // if ((res as any).botHello) { + // BOT_HELLO.content = (res as any).botHello; + // } }) .catch(() => { console.error("[Config] failed to fetch config"); diff --git a/app/store/chat.ts b/app/store/chat.ts index bea33d9ae94..39cbdf7098e 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -57,17 +57,22 @@ export interface ChatSession { stat: ChatStat; lastUpdate: number; lastSummarizeIndex: number; - + botHello: Message; mask: Mask; } export const DEFAULT_TOPIC = Locale.Store.DefaultTopic; -export const BOT_HELLO: Message = createMessage({ +const BOT_HELLO: Message = createMessage({ role: "assistant", content: Locale.Store.BotHello, }); +const createBotHelloWithCommand = (command: string): Message => { + BOT_HELLO.content = Locale.Store.BotHelloWithCommand(command); + return BOT_HELLO; +}; function createEmptySession(): ChatSession { + const mask = createEmptyMask(); return { id: Date.now() + Math.random(), topic: DEFAULT_TOPIC, @@ -80,7 +85,8 @@ function createEmptySession(): ChatSession { }, lastUpdate: Date.now(), lastSummarizeIndex: 0, - mask: createEmptyMask(), + mask: mask, + botHello: createBotHelloWithCommand(mask.imageModelConfig.command), }; } @@ -245,6 +251,7 @@ export const useChatStore = create()( async onUserInput(content) { const session = get().currentSession(); const modelConfig = session.mask.modelConfig; + const imageModelConfig = session.mask.imageModelConfig; const userMessage: Message = createMessage({ role: "user", @@ -281,8 +288,15 @@ export const useChatStore = create()( session.messages.push(botMessage); }); - if (userMessage.content.startsWith("/image")) { - const keyword = userMessage.content.substring("/image".length); + if ( + userMessage.content + .trim() + .toLowerCase() + .startsWith(imageModelConfig.command.toLowerCase()) + ) { + const keyword = userMessage.content.substring( + imageModelConfig.command.toLowerCase().length, + ); console.log("keyword", keyword); requestImage(keyword, { onMessage(content, images, image_alt, done) { diff --git a/app/store/config.ts b/app/store/config.ts index ddc8ef1c7e0..4807a470de3 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -1,6 +1,8 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -import { StoreKey } from "../constant"; +import { ImageRequestSizeEnum } from "../api/openai/typing"; +import { COMMAND_IMAGE, StoreKey } from "../constant"; +import { CreateImageRequestSizeEnum } from "openai"; export enum SubmitKey { Enter = "Enter", @@ -38,6 +40,11 @@ export const DEFAULT_CONFIG = { historyMessageCount: 4, compressMessageLengthThreshold: 1000, }, + imageModelConfig: { + imageLimit: 1, + command: COMMAND_IMAGE, + size: "256x256" as ImageRequestSizeEnum, + }, }; export type ChatConfig = typeof DEFAULT_CONFIG; @@ -48,7 +55,7 @@ export type ChatConfigStore = ChatConfig & { }; export type ModelConfig = ChatConfig["modelConfig"]; - +export type ImageModelConfig = ChatConfig["imageModelConfig"]; const ENABLE_GPT4 = true; export const ALL_MODELS = [ @@ -133,7 +140,19 @@ export const ModalConfigValidator = { return limitNumber(x, 0, 1, 1); }, }; - +export const ImageModalConfigValidator = { + size: (value: string): ImageRequestSizeEnum => { + const validSizes = Object.values( + CreateImageRequestSizeEnum, + ) as unknown as ImageRequestSizeEnum[]; + if (validSizes.includes(value as ImageRequestSizeEnum)) { + return value as ImageRequestSizeEnum; + } else { + console.warn(`Invalid size: ${value}. Defaulting to "256x256".`); + return "256x256"; + } + }, +}; export const useAppConfig = create()( persist( (set, get) => ({ diff --git a/app/store/mask.ts b/app/store/mask.ts index 98bd4702113..df4b0c4301e 100644 --- a/app/store/mask.ts +++ b/app/store/mask.ts @@ -3,15 +3,20 @@ import { persist } from "zustand/middleware"; import { BUILTIN_MASKS } from "../masks"; import { getLang, Lang } from "../locales"; import { DEFAULT_TOPIC, Message } from "./chat"; -import { ModelConfig, ModelType, useAppConfig } from "./config"; import { StoreKey } from "../constant"; - +import { + ImageModelConfig, + ModelConfig, + ModelType, + useAppConfig, +} from "./config"; export type Mask = { id: number; avatar: string; name: string; context: Message[]; modelConfig: ModelConfig; + imageModelConfig: ImageModelConfig; lang: Lang; builtin: boolean; }; @@ -40,6 +45,7 @@ export const createEmptyMask = () => name: DEFAULT_TOPIC, context: [], modelConfig: { ...useAppConfig.getState().modelConfig }, + imageModelConfig: { ...useAppConfig.getState().imageModelConfig }, lang: getLang(), builtin: false, } as Mask); From 5b9b120fa6d7823976ff68dd6147a7e002aa7c42 Mon Sep 17 00:00:00 2001 From: InitialXKO <45725592+InitialXKO@users.noreply.github.com> Date: Sat, 13 May 2023 09:36:04 +0800 Subject: [PATCH 11/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=87=E7=94=9F?= =?UTF-8?q?=E5=9B=BE=E9=9D=A2=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/masks/cn.ts | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/app/masks/cn.ts b/app/masks/cn.ts index 757a35ee978..86af414bba3 100644 --- a/app/masks/cn.ts +++ b/app/masks/cn.ts @@ -1,6 +1,38 @@ import { BuiltinMask } from "./typing"; -export const CN_MASKS: BuiltinMask[] = [ +export const CN_MASKS: BuiltinMask[] = [{ + avatar:"gpt-bot", + name:"文生图", + context: [ + {role:"system", + content:"You are a useful Assistant that won't refuse to draw picture, instead, you will output specific markdown code for picture description, but don't use code block.", + date:"", + }, + {role:"user", + content:"Can you draw some pictures for me?", + date:"", + }, + {role:"assistant", + content:"Sure, what do you want me to draw?", + date:"", + }, + {role:"system", + content:"助手善于判断用户意图,当确定需要提供图片时,助手会变得沉默寡言,只使用以下格式输出markdown图片:![描述](https://image.pollinations.ai/prompt/描述),因为这个语法可以自动按照提示生成并渲染图片。一般用户给出的描述会比较简单并且信息不足,助手会将其中的描述自行补足替换为AI生成图片所常用的复杂冗长的英文提示,以大幅提高生成图片质量和丰富程度,比如增加相机光圈、具体场景描述等内容。助手会避免用代码块或原始块包围markdown标记,因为那样只会渲染出代码块或原始块而不是图片。", + date:"", + }, + ], + modelConfig:{ + model:"gpt-3.5-turbo", + temperature:1, + max_tokens:2000, + presence_penalty:0, + sendMemory:true, + historyMessageCount:32, + compressMessageLengthThreshold:1000, + }, + lang:"cn", + builtin:true, + }, { avatar: "1f638", name: "文案写手", From dec19d68b3519208bf8aa032017ecbfb0cfa6c71 Mon Sep 17 00:00:00 2001 From: SPWwj Date: Sat, 13 May 2023 15:46:37 +0800 Subject: [PATCH 12/15] Fix missing Locale image properties --- app/components/image-model-config.tsx | 6 +-- app/components/markdown.tsx | 2 +- app/locales/cn.ts | 2 +- app/locales/cs.ts | 2 +- app/locales/de.ts | 2 +- app/locales/en.ts | 2 +- app/locales/es.ts | 2 +- app/locales/it.ts | 2 +- app/locales/jp.ts | 2 +- app/locales/ru.ts | 2 +- app/locales/tr.ts | 2 +- app/locales/tw.ts | 2 +- app/locales/vi.ts | 2 +- app/masks/cn.ts | 55 +++++++++++++++++++++++++++ app/masks/en.ts | 5 +++ app/requests.ts | 2 +- app/store/config.ts | 2 +- 17 files changed, 77 insertions(+), 17 deletions(-) diff --git a/app/components/image-model-config.tsx b/app/components/image-model-config.tsx index aea8f80cdb9..b87d7bacc3e 100644 --- a/app/components/image-model-config.tsx +++ b/app/components/image-model-config.tsx @@ -32,14 +32,14 @@ export function ImageModelConfigList(props: { }} /> - + { const newValue = parseInt(e.currentTarget.value, 10); // Parse the value as an integer if (!isNaN(newValue)) { props.updateConfig((config) => { - config.imageLimit = newValue; // Assign the parsed value + config.noOfImage = newValue; // Assign the parsed value return config; }); } diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 74f7f64dcb6..7be568f3e1c 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -17,7 +17,7 @@ import ImagePlaceHolder from "../icons/image-placeholder.svg"; import ImageError from "../icons/image-error.svg"; import { IMAGE_PLACEHOLDER } from "../constant"; import { ImagesResponseDataInner } from "openai"; -import ImageList from "./ImageList"; +import ImageList from "./imageList"; export function Mermaid(props: { code: string; onError: () => void }) { const ref = useRef(null); diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 7403f1cdd2f..fade044fd42 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -159,7 +159,7 @@ const cn = { Title: "图片模型", Model: "DALL-E模型", Command: "生成图片指令", - CountLimit: "图片生成次数限制", + NoOfImage: "图片生成次数限制", Size: "图片生成尺寸", }, Temperature: { diff --git a/app/locales/cs.ts b/app/locales/cs.ts index 47909dffedb..6162849f0d5 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -160,7 +160,7 @@ const cs: LocaleType = { Title: "Obrázkový model", Model: "Model DALL-E", Command: "Příkaz pro generování obrázků", - CountLimit: "Limit počtu generovaných obrázků", + NoOfImage: "Limit počtu generovaných obrázků", Size: "Velikost generovaného obrázku", }, Temperature: { diff --git a/app/locales/de.ts b/app/locales/de.ts index 8024ebd76eb..d3791e54edb 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -162,7 +162,7 @@ const de: LocaleType = { Title: "Bildmodell", Model: "DALL-E Modell", Command: "Bildgenerierungsbefehl", - CountLimit: "Bildgenerierungslimit", + NoOfImage: "Bildgenerierungslimit", Size: "Bildgenerierungsgröße", }, Temperature: { diff --git a/app/locales/en.ts b/app/locales/en.ts index 04ba5a4c348..7dd867616cb 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -160,7 +160,7 @@ const en: LocaleType = { Title: "Image Model", Model: "DALL-E Model", Command: "Generate Image Command", - CountLimit: "Image Generation Limit", + NoOfImage: "Image Generation Limit", Size: "Image Generation Size", }, Temperature: { diff --git a/app/locales/es.ts b/app/locales/es.ts index f7bf5f4c6a2..382cce7430b 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -160,7 +160,7 @@ const es: LocaleType = { Title: "Modelo de imagen", Model: "Modelo DALL-E", Command: "Comando de generación de imágenes", - CountLimit: "Límite de generación de imágenes", + NoOfImage: "Límite de generación de imágenes", Size: "Tamaño de generación de imagen", }, Temperature: { diff --git a/app/locales/it.ts b/app/locales/it.ts index 6c2c4c2f534..7616b7259e4 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -161,7 +161,7 @@ const it: LocaleType = { Title: "Modello di immagine", Model: "Modello DALL-E", Command: "Comando di generazione immagine", - CountLimit: "Limite di generazione immagine", + NoOfImage: "Limite di generazione immagine", Size: "Dimensione di generazione immagine", }, Temperature: { diff --git a/app/locales/jp.ts b/app/locales/jp.ts index ef8a0049e1e..9c317b152c5 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -162,7 +162,7 @@ const jp: LocaleType = { Title: "画像モデル", Model: "DALL-Eモデル", Command: "画像生成コマンド", - CountLimit: "画像生成回数制限", + NoOfImage: "画像生成回数制限", Size: "画像生成サイズ", }, Temperature: { diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 50dde81420a..f99d64c2952 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -161,7 +161,7 @@ const ru: LocaleType = { Title: "Модель изображения", Model: "Модель DALL-E", Command: "Команда генерации изображений", - CountLimit: "Лимит генерации изображений", + NoOfImage: "Лимит генерации изображений", Size: "Размер генерируемого изображения", }, Temperature: { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 83207086e3e..ed415e5b4c1 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -160,7 +160,7 @@ const tr: LocaleType = { Title: "Resim Modeli", Model: "DALL-E Modeli", Command: "Resim Oluşturma Komutu", - CountLimit: "Resim Oluşturma Limiti", + NoOfImage: "Resim Oluşturma Limiti", Size: "Resim Oluşturma Boyutu", }, Temperature: { diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 4534c135aa2..e14fbc0819d 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -157,7 +157,7 @@ const tw: LocaleType = { Title: "圖片模型", Model: "DALL-E模型", Command: "生成圖片指令", - CountLimit: "圖片生成次數限制", + NoOfImage: "圖片生成次數限制", Size: "圖片生成尺寸", }, Temperature: { diff --git a/app/locales/vi.ts b/app/locales/vi.ts index d16cfb4d1b9..7a966d792ec 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -159,7 +159,7 @@ const vi: LocaleType = { Title: "Mô hình hình ảnh", Model: "Mô hình DALL-E", Command: "Lệnh tạo hình ảnh", - CountLimit: "Giới hạn số lượng hình ảnh tạo ra", + NoOfImage: "Giới hạn số lượng hình ảnh tạo ra", Size: "Kích thước hình ảnh được tạo ra", }, Temperature: { diff --git a/app/masks/cn.ts b/app/masks/cn.ts index 757a35ee978..52ab6657c00 100644 --- a/app/masks/cn.ts +++ b/app/masks/cn.ts @@ -21,6 +21,11 @@ export const CN_MASKS: BuiltinMask[] = [ historyMessageCount: 4, compressMessageLengthThreshold: 1000, }, + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, lang: "cn", builtin: true, }, @@ -44,6 +49,11 @@ export const CN_MASKS: BuiltinMask[] = [ historyMessageCount: 4, compressMessageLengthThreshold: 1000, }, + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, lang: "cn", builtin: true, }, @@ -67,6 +77,11 @@ export const CN_MASKS: BuiltinMask[] = [ historyMessageCount: 4, compressMessageLengthThreshold: 1000, }, + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, lang: "cn", builtin: true, }, @@ -81,6 +96,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -104,6 +124,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -127,6 +152,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -150,6 +180,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -173,6 +208,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -202,6 +242,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -231,6 +276,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, @@ -281,6 +331,11 @@ export const CN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-3.5-turbo", temperature: 1, diff --git a/app/masks/en.ts b/app/masks/en.ts index af4f215c456..78d0b5c0fc9 100644 --- a/app/masks/en.ts +++ b/app/masks/en.ts @@ -29,6 +29,11 @@ export const EN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-4", temperature: 0.5, diff --git a/app/requests.ts b/app/requests.ts index 75b4d4c3a17..3a6943515fe 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -156,7 +156,7 @@ const makeImageRequestParam = ( ): CreateImageRequest => { // Set default values const defaultOptions: Omit = { - n: useAppConfig.getState().imageModelConfig.imageLimit, + n: useAppConfig.getState().imageModelConfig.noOfImage, response_format: CreateImageRequestResponseFormatEnum.Url, user: "default_user", }; diff --git a/app/store/config.ts b/app/store/config.ts index 4807a470de3..9c05ce1b7ab 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -41,7 +41,7 @@ export const DEFAULT_CONFIG = { compressMessageLengthThreshold: 1000, }, imageModelConfig: { - imageLimit: 1, + noOfImage: 1, command: COMMAND_IMAGE, size: "256x256" as ImageRequestSizeEnum, }, From 3e8fad0a3e28e818ab03c316bfefcf30c4c37667 Mon Sep 17 00:00:00 2001 From: SPWwj Date: Fri, 12 May 2023 00:20:12 +0800 Subject: [PATCH 13/15] Add support for DALL-E #1358 --- app/components/ImageList.module.scss | 16 +++ app/components/ImageList.tsx | 20 ++++ app/components/chat.tsx | 2 + app/components/markdown.tsx | 29 +++++- app/components/markdown.tsx.module.scss | 10 ++ app/constant.ts | 2 + app/icons/image-error.svg | 33 ++++++ app/icons/image-placeholder.svg | 28 +++++ app/locales/cn.ts | 3 +- app/locales/en.ts | 3 +- app/requests.ts | 97 ++++++++++++++++- app/store/chat.ts | 132 +++++++++++++++++------- app/store/config.ts | 2 +- 13 files changed, 332 insertions(+), 45 deletions(-) create mode 100644 app/components/ImageList.module.scss create mode 100644 app/components/ImageList.tsx create mode 100644 app/components/markdown.tsx.module.scss create mode 100644 app/icons/image-error.svg create mode 100644 app/icons/image-placeholder.svg diff --git a/app/components/ImageList.module.scss b/app/components/ImageList.module.scss new file mode 100644 index 00000000000..3b7f1f93396 --- /dev/null +++ b/app/components/ImageList.module.scss @@ -0,0 +1,16 @@ +.imageGrid, +.imageGridSingle { + display: inline-flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +.imageGrid img { + max-width: calc(50% - 10px); + margin: 5px; +} + +.imageGridSingle img { + max-width: 100%; + margin: 5px; +} diff --git a/app/components/ImageList.tsx b/app/components/ImageList.tsx new file mode 100644 index 00000000000..01e30013eb8 --- /dev/null +++ b/app/components/ImageList.tsx @@ -0,0 +1,20 @@ +import { ImagesResponseDataInner } from "openai"; +import React, { FC } from "react"; +import styles from "./ImageList.module.scss"; + +interface ImageListProps { + images?: ImagesResponseDataInner[]; +} +const ImageList: FC = ({ images }) => { + const singleImage = images && images.length === 1; + + return ( +
+ {images && + images.map((image, index) => ( + {`Image + ))} +
+ ); +}; +export default ImageList; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index d38990372be..1b4f52b509e 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -760,6 +760,8 @@ export function Chat() { )} void }) { const ref = useRef(null); @@ -119,6 +125,8 @@ export const MarkdownContent = React.memo(_MarkDownContent); export function Markdown( props: { content: string; + images?: ImagesResponseDataInner[]; + image_alt?: string; loading?: boolean; fontSize?: number; parentRef: RefObject; @@ -171,9 +179,24 @@ export function Markdown( > {inView.current && (props.loading ? ( - +
+ {props.image_alt && } + {props.image_alt && + (props.image_alt === IMAGE_PLACEHOLDER ? ( + + ) : ( + + ))} + +
) : ( - +
+ +
+ {props.images && } + {props.image_alt && } +
+
))} ); diff --git a/app/components/markdown.tsx.module.scss b/app/components/markdown.tsx.module.scss new file mode 100644 index 00000000000..1e19384b121 --- /dev/null +++ b/app/components/markdown.tsx.module.scss @@ -0,0 +1,10 @@ +.loader { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; // Adjust as necessary +} +.content_image { + text-align: center; +} diff --git a/app/constant.ts b/app/constant.ts index d0f9fc743d1..560d57a1b5e 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -40,3 +40,5 @@ export const NARROW_SIDEBAR_WIDTH = 100; export const ACCESS_CODE_PREFIX = "ak-"; export const LAST_INPUT_KEY = "last-input"; +export const IMAGE_PLACEHOLDER = "Loading your image..."; +export const IMAGE_ERROR = "IMAGE_ERROR"; diff --git a/app/icons/image-error.svg b/app/icons/image-error.svg new file mode 100644 index 00000000000..389fc5fad2b --- /dev/null +++ b/app/icons/image-error.svg @@ -0,0 +1,33 @@ + + + + + design-and-ux/error-handling + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/icons/image-placeholder.svg b/app/icons/image-placeholder.svg new file mode 100644 index 00000000000..fc5e94fc374 --- /dev/null +++ b/app/icons/image-placeholder.svg @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/locales/cn.ts b/app/locales/cn.ts index b955a7d2bc4..36b10e4c45c 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -170,7 +170,8 @@ const cn = { }, Store: { DefaultTopic: "新的聊天", - BotHello: "有什么可以帮你的吗", + BotHello: + "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `/Image {关键词}。`", Error: "出错了,稍后重试吧", Prompt: { History: (content: string) => diff --git a/app/locales/en.ts b/app/locales/en.ts index b17408bd420..da568ad9e11 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -172,7 +172,8 @@ const en: LocaleType = { }, Store: { DefaultTopic: "New Conversation", - BotHello: "Hello! How can I assist you today?", + BotHello: + "Hello! How can I assist you today?\n To generate images, use `/Image {keyword}.`", Error: "Something went wrong, please try again later.", Prompt: { History: (content: string) => diff --git a/app/requests.ts b/app/requests.ts index d9750a5b794..39024f21086 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -8,8 +8,14 @@ import { useChatStore, } from "./store"; import { showToast } from "./components/ui-lib"; -import { ACCESS_CODE_PREFIX } from "./constant"; - +import { ACCESS_CODE_PREFIX, IMAGE_ERROR, IMAGE_PLACEHOLDER } from "./constant"; +import { + CreateImageRequest, + CreateImageRequestResponseFormatEnum, + CreateImageRequestSizeEnum, + ImagesResponse, + ImagesResponseDataInner, +} from "openai"; const TIME_OUT_MS = 60000; const makeRequestParam = ( @@ -144,6 +150,93 @@ export async function requestUsage() { subscription: total.hard_limit_usd, }; } +const makeImageRequestParam = ( + prompt: string, + options?: Omit, +): CreateImageRequest => { + // Set default values + const defaultOptions: Omit = { + n: 4, + size: CreateImageRequestSizeEnum._512x512, + response_format: CreateImageRequestResponseFormatEnum.Url, + user: "default_user", + }; + + // Override default values with provided options + const finalOptions = { ...defaultOptions, ...options }; + + const request: CreateImageRequest = { + prompt, + ...finalOptions, + }; + + return request; +}; +export async function requestImage( + keyword: string, + options?: { + onMessage: ( + message: string | null, + image: ImagesResponseDataInner[] | null, + image_alt: string | null, + done: boolean, + ) => void; + onError: (error: Error, statusCode?: number) => void; + onController?: (controller: AbortController) => void; + }, +) { + if (keyword.length < 1) { + options?.onMessage( + "Please enter a keyword after `/image`", + null, + null, + true, + ); + } else { + const controller = new AbortController(); + const reqTimeoutId = setTimeout(() => controller.abort(), TIME_OUT_MS); + options?.onController?.(controller); + + async function fetchImageAndUpdateMessage() { + try { + options?.onMessage(null, null, IMAGE_PLACEHOLDER, false); + + const sanitizedMessage = keyword.replace(/[\n\r]+/g, " "); + const req = makeImageRequestParam(sanitizedMessage); + + const res = await requestOpenaiClient("v1/images/generations")(req); + + clearTimeout(reqTimeoutId); + + const finish = (images: ImagesResponseDataInner[]) => { + options?.onMessage("Here is your images", images, null, true); + controller.abort(); + }; + + if (res.ok) { + const responseData = (await res.json()) as ImagesResponse; + finish(responseData.data); + } else if (res.status === 401) { + console.error("Unauthorized"); + options?.onError(new Error("Unauthorized"), res.status); + } else { + console.error("Stream Error", res.body); + options?.onError(new Error("Stream Error"), res.status); + } + } catch (err) { + console.error("NetWork Error", err); + options?.onError(err as Error); + options?.onMessage( + "Image generation has been cancelled.", + null, + IMAGE_ERROR, + true, + ); + } + } + fetchImageAndUpdateMessage(); + } +} export async function requestChatStream( messages: Message[], diff --git a/app/store/chat.ts b/app/store/chat.ts index cb11087d4ef..bea33d9ae94 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -1,10 +1,14 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -import { type ChatCompletionResponseMessage } from "openai"; +import { + ImagesResponseDataInner, + type ChatCompletionResponseMessage, +} from "openai"; import { ControllerPool, requestChatStream, + requestImage, requestWithPrompt, } from "../requests"; import { trimTopic } from "../utils"; @@ -17,6 +21,8 @@ import { StoreKey } from "../constant"; export type Message = ChatCompletionResponseMessage & { date: string; + images?: ImagesResponseDataInner[]; + image_alt?: string; streaming?: boolean; isError?: boolean; id?: number; @@ -275,48 +281,100 @@ export const useChatStore = create()( session.messages.push(botMessage); }); - // make request - console.log("[User Input] ", sendMessages); - requestChatStream(sendMessages, { - onMessage(content, done) { - // stream response - if (done) { + if (userMessage.content.startsWith("/image")) { + const keyword = userMessage.content.substring("/image".length); + console.log("keyword", keyword); + requestImage(keyword, { + onMessage(content, images, image_alt, done) { + // stream response + if (done) { + botMessage.streaming = false; + botMessage.content = content!; + botMessage.images = images!; + botMessage.image_alt = image_alt!; + get().onNewMessage(botMessage); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + } else { + botMessage.image_alt = image_alt!; + set(() => ({})); + } + }, + onError(error, statusCode) { + const isAborted = error.message.includes("aborted"); + if (statusCode === 401) { + botMessage.content = Locale.Error.Unauthorized; + } else if (!isAborted) { + botMessage.content += "\n\n" + Locale.Store.Error; + } botMessage.streaming = false; - botMessage.content = content; - get().onNewMessage(botMessage); + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + + set(() => ({})); ControllerPool.remove( sessionIndex, botMessage.id ?? messageIndex, ); - } else { - botMessage.content = content; + }, + onController(controller) { + // collect controller for stop/retry + ControllerPool.addController( + sessionIndex, + botMessage.id ?? messageIndex, + controller, + ); + }, + }); + } else { + // make request + console.log("[User Input] ", sendMessages); + requestChatStream(sendMessages, { + onMessage(content, done) { + // stream response + if (done) { + botMessage.streaming = false; + botMessage.content = content; + get().onNewMessage(botMessage); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + } else { + botMessage.content = content; + set(() => ({})); + } + }, + onError(error, statusCode) { + const isAborted = error.message.includes("aborted"); + if (statusCode === 401) { + botMessage.content = Locale.Error.Unauthorized; + } else if (!isAborted) { + botMessage.content += "\n\n" + Locale.Store.Error; + } + botMessage.streaming = false; + userMessage.isError = !isAborted; + botMessage.isError = !isAborted; + set(() => ({})); - } - }, - onError(error, statusCode) { - const isAborted = error.message.includes("aborted"); - if (statusCode === 401) { - botMessage.content = Locale.Error.Unauthorized; - } else if (!isAborted) { - botMessage.content += "\n\n" + Locale.Store.Error; - } - botMessage.streaming = false; - userMessage.isError = !isAborted; - botMessage.isError = !isAborted; - - set(() => ({})); - ControllerPool.remove(sessionIndex, botMessage.id ?? messageIndex); - }, - onController(controller) { - // collect controller for stop/retry - ControllerPool.addController( - sessionIndex, - botMessage.id ?? messageIndex, - controller, - ); - }, - modelConfig: { ...modelConfig }, - }); + ControllerPool.remove( + sessionIndex, + botMessage.id ?? messageIndex, + ); + }, + onController(controller) { + // collect controller for stop/retry + ControllerPool.addController( + sessionIndex, + botMessage.id ?? messageIndex, + controller, + ); + }, + modelConfig: { ...modelConfig }, + }); + } }, getMemoryPrompt() { diff --git a/app/store/config.ts b/app/store/config.ts index 1e960456ff4..ddc8ef1c7e0 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -17,7 +17,7 @@ export enum Theme { } export const DEFAULT_CONFIG = { - submitKey: SubmitKey.CtrlEnter as SubmitKey, + submitKey: SubmitKey.Enter as SubmitKey, avatar: "1f603", fontSize: 14, theme: Theme.Auto as Theme, From 2a7edc8226fed5a5d02bdbeb6c5306f1f1a7ae98 Mon Sep 17 00:00:00 2001 From: SPWwj Date: Sat, 13 May 2023 09:13:20 +0800 Subject: [PATCH 14/15] Add Setting to imageModel --- app/api/openai/typing.ts | 3 +- app/components/ImageList.tsx | 2 +- app/components/chat.tsx | 5 +- app/components/image-model-config.tsx | 74 +++ app/components/settings.tsx | 13 + app/constant.ts | 1 + app/locales/cn.ts | 14 +- app/locales/cs.ts | 11 + app/locales/de.ts | 11 + app/locales/en.ts | 14 +- app/locales/es.ts | 11 + app/locales/it.ts | 11 + app/locales/jp.ts | 11 + app/locales/ru.ts | 11 + app/locales/tr.ts | 11 + app/locales/tw.ts | 9 + app/locales/vi.ts | 11 + app/masks/cn.ts | 664 ++++++++++++++------------ app/masks/en.ts | 5 + app/requests.ts | 3 +- app/store/access.ts | 7 +- app/store/chat.ts | 24 +- app/store/config.ts | 25 +- app/store/mask.ts | 10 +- 24 files changed, 636 insertions(+), 325 deletions(-) create mode 100644 app/components/image-model-config.tsx diff --git a/app/api/openai/typing.ts b/app/api/openai/typing.ts index 2286d23124e..82d401f0797 100644 --- a/app/api/openai/typing.ts +++ b/app/api/openai/typing.ts @@ -1,9 +1,10 @@ import type { CreateChatCompletionRequest, CreateChatCompletionResponse, + CreateImageRequestSizeEnum, } from "openai"; export type ChatRequest = CreateChatCompletionRequest; export type ChatResponse = CreateChatCompletionResponse; - +export type ImageRequestSizeEnum = CreateImageRequestSizeEnum; export type Updater = (updater: (value: T) => void) => void; diff --git a/app/components/ImageList.tsx b/app/components/ImageList.tsx index 01e30013eb8..8d649f45431 100644 --- a/app/components/ImageList.tsx +++ b/app/components/ImageList.tsx @@ -1,6 +1,6 @@ import { ImagesResponseDataInner } from "openai"; import React, { FC } from "react"; -import styles from "./ImageList.module.scss"; +import styles from "./imageList.module.scss"; interface ImageListProps { images?: ImagesResponseDataInner[]; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 1b4f52b509e..0ff363fb694 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -25,7 +25,6 @@ import { Message, SubmitKey, useChatStore, - BOT_HELLO, createMessage, useAccessStore, Theme, @@ -560,9 +559,9 @@ export function Chat() { if ( context.length === 0 && - session.messages.at(0)?.content !== BOT_HELLO.content + session.messages.at(0)?.content !== session.botHello.content ) { - const copiedHello = Object.assign({}, BOT_HELLO); + const copiedHello = Object.assign({}, session.botHello); if (!accessStore.isAuthorized()) { copiedHello.content = Locale.Error.Unauthorized; } diff --git a/app/components/image-model-config.tsx b/app/components/image-model-config.tsx new file mode 100644 index 00000000000..33f085c0b47 --- /dev/null +++ b/app/components/image-model-config.tsx @@ -0,0 +1,74 @@ +import { + ALL_MODELS, + ImageModalConfigValidator, + ImageModelConfig, + ModalConfigValidator, + ModelConfig, +} from "../store"; + +import Locale from "../locales"; +import { InputRange } from "./input-range"; +import { Input, List, ListItem, Select } from "./ui-lib"; +import { ImageRequestSizeEnum } from "../api/openai/typing"; +import { CreateImageRequestSizeEnum } from "openai"; + +export function ImageModelConfigList(props: { + imageModelConfig: ImageModelConfig; + updateConfig: (updater: (config: ImageModelConfig) => void) => void; +}) { + return ( + <> + + + + + { + props.updateConfig((config) => { + config.command = e.currentTarget.value; // Assign the parsed value + return config; + }); + }} + /> + + + { + const newValue = parseInt(e.currentTarget.value, 10); // Parse the value as an integer + if (!isNaN(newValue)) { + props.updateConfig((config) => { + config.noOfImage = newValue; // Assign the parsed value + return config; + }); + } + }} + min={"1"} // Convert the min value to a string + max={"10"} // Convert the max value to a string + step={"1"} // Convert the step value to a string + /> + + + + + + ); +} diff --git a/app/components/settings.tsx b/app/components/settings.tsx index eb83d8905f7..a26ff0b8cea 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -40,6 +40,7 @@ import { ErrorBoundary } from "./error"; import { InputRange } from "./input-range"; import { useNavigate } from "react-router-dom"; import { Avatar, AvatarPicker } from "./emoji"; +import { ImageModelConfigList } from "./image-model-config"; function EditPromptModal(props: { id: number; onClose: () => void }) { const promptStore = usePromptStore(); @@ -580,6 +581,18 @@ export function Settings() { }} /> + + { + const imageModelConfig = { ...config.imageModelConfig }; + upater(imageModelConfig); + config.update( + (config) => (config.imageModelConfig = imageModelConfig), + ); + }} + /> + {shouldShowPromptModal && ( setShowPromptModal(false)} /> diff --git a/app/constant.ts b/app/constant.ts index 560d57a1b5e..36ca672a729 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -42,3 +42,4 @@ export const ACCESS_CODE_PREFIX = "ak-"; export const LAST_INPUT_KEY = "last-input"; export const IMAGE_PLACEHOLDER = "Loading your image..."; export const IMAGE_ERROR = "IMAGE_ERROR"; +export const COMMAND_IMAGE = "/image"; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 36b10e4c45c..54d06b3b8b2 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -155,6 +155,13 @@ const cn = { Placeholder: "请输入访问密码", }, Model: "模型 (model)", + ImageModel: { + Title: "图片模型", + Model: "DALL-E模型", + Command: "生成图片指令", + CountLimit: "图片生成次数限制", + Size: "图片生成尺寸", + }, Temperature: { Title: "随机性 (temperature)", SubTitle: "值越大,回复越随机", @@ -170,8 +177,11 @@ const cn = { }, Store: { DefaultTopic: "新的聊天", - BotHello: - "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `/Image {关键词}。`", + BotHello: "您好!今天我能为您做些什么呢?", + BotHelloWithCommand: (command: string) => + "您好!今天我能为您做些什么呢?\n 要生成图片,请使用 `" + + command + + " {关键词}。`", Error: "出错了,稍后重试吧", Prompt: { History: (content: string) => diff --git a/app/locales/cs.ts b/app/locales/cs.ts index 6d614575e47..15ab05a333d 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -156,6 +156,13 @@ const cs: LocaleType = { Placeholder: "Potřebujete přístupový kód", }, Model: "Model", + ImageModel: { + Title: "Obrázkový model", + Model: "Model DALL-E", + Command: "Příkaz pro generování obrázků", + CountLimit: "Limit počtu generovaných obrázků", + Size: "Velikost generovaného obrázku", + }, Temperature: { Title: "Teplota", SubTitle: "Větší hodnota činí výstup náhodnějším", @@ -172,6 +179,10 @@ const cs: LocaleType = { Store: { DefaultTopic: "Nová konverzace", BotHello: "Ahoj! Jak mohu dnes pomoci?", + BotHelloWithCommand: (command: string) => + "Ahoj! Jak mohu dnes pomoci?\n Pro generování obrázků použijte `" + + command + + " {klíčové slovo}.`", Error: "Něco se pokazilo, zkuste to prosím později.", Prompt: { History: (content: string) => diff --git a/app/locales/de.ts b/app/locales/de.ts index 02510070cbb..04de6651fb8 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -158,6 +158,13 @@ const de: LocaleType = { Placeholder: "Zugangscode erforderlich", }, Model: "Modell", + ImageModel: { + Title: "Bildmodell", + Model: "DALL-E Modell", + Command: "Bildgenerierungsbefehl", + CountLimit: "Bildgenerierungslimit", + Size: "Bildgenerierungsgröße", + }, Temperature: { Title: "Temperature", //Temperatur SubTitle: "Ein größerer Wert führt zu zufälligeren Antworten", @@ -175,6 +182,10 @@ const de: LocaleType = { Store: { DefaultTopic: "Neues Gespräch", BotHello: "Hallo! Wie kann ich Ihnen heute helfen?", + BotHelloWithCommand: (command: string) => + "Hallo! Wie kann ich Ihnen heute helfen?\n Um Bilder zu generieren, verwenden Sie `" + + command + + " {Schlüsselwort}.`", Error: "Etwas ist schief gelaufen, bitte versuchen Sie es später noch einmal.", Prompt: { diff --git a/app/locales/en.ts b/app/locales/en.ts index da568ad9e11..05f5ef91227 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -156,6 +156,13 @@ const en: LocaleType = { Placeholder: "Need Access Code", }, Model: "Model", + ImageModel: { + Title: "Image Model", + Model: "DALL-E Model", + Command: "Generate Image Command", + CountLimit: "Image Generation Limit", + Size: "Image Generation Size", + }, Temperature: { Title: "Temperature", SubTitle: "A larger value makes the more random output", @@ -172,8 +179,11 @@ const en: LocaleType = { }, Store: { DefaultTopic: "New Conversation", - BotHello: - "Hello! How can I assist you today?\n To generate images, use `/Image {keyword}.`", + BotHello: "Hello! How can I assist you today?", + BotHelloWithCommand: (command: string) => + "Hello! How can I assist you today?\n To generate images, use `" + + command + + " {keyword}.`", Error: "Something went wrong, please try again later.", Prompt: { History: (content: string) => diff --git a/app/locales/es.ts b/app/locales/es.ts index b80faf23c88..c58e94f5d9c 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -156,6 +156,13 @@ const es: LocaleType = { Placeholder: "Necesita código de acceso", }, Model: "Modelo", + ImageModel: { + Title: "Modelo de imagen", + Model: "Modelo DALL-E", + Command: "Comando de generación de imágenes", + CountLimit: "Límite de generación de imágenes", + Size: "Tamaño de generación de imagen", + }, Temperature: { Title: "Temperatura", SubTitle: "Un valor mayor genera una salida más aleatoria", @@ -173,6 +180,10 @@ const es: LocaleType = { Store: { DefaultTopic: "Nueva conversación", BotHello: "¡Hola! ¿Cómo puedo ayudarte hoy?", + BotHelloWithCommand: (command: string) => + "¡Hola! ¿Cómo puedo ayudarte hoy?\n Para generar imágenes, usa `" + + command + + " {palabra clave}.`", Error: "Algo salió mal, por favor intenta nuevamente más tarde.", Prompt: { History: (content: string) => diff --git a/app/locales/it.ts b/app/locales/it.ts index e711216627e..defb885f157 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -157,6 +157,13 @@ const it: LocaleType = { Placeholder: "Inserisci il codice d'accesso", }, Model: "Modello GPT", + ImageModel: { + Title: "Modello di immagine", + Model: "Modello DALL-E", + Command: "Comando di generazione immagine", + CountLimit: "Limite di generazione immagine", + Size: "Dimensione di generazione immagine", + }, Temperature: { Title: "Temperature", SubTitle: "Un valore maggiore rende l'output più casuale", @@ -174,6 +181,10 @@ const it: LocaleType = { Store: { DefaultTopic: "Nuova conversazione", BotHello: "Ciao, come posso aiutarti oggi?", + BotHelloWithCommand: (command: string) => + "Ciao, come posso aiutarti oggi?\n Per generare immagini, usa `" + + command + + " {parola chiave}.`", Error: "Qualcosa è andato storto, riprova più tardi.", Prompt: { History: (content: string) => diff --git a/app/locales/jp.ts b/app/locales/jp.ts index dbb9980fe00..6d9d095c962 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -158,6 +158,13 @@ const jp: LocaleType = { Placeholder: "アクセスパスワードを入力してください", }, Model: "モデル (model)", + ImageModel: { + Title: "画像モデル", + Model: "DALL-Eモデル", + Command: "画像生成コマンド", + CountLimit: "画像生成回数制限", + Size: "画像生成サイズ", + }, Temperature: { Title: "ランダム性 (temperature)", SubTitle: @@ -175,6 +182,10 @@ const jp: LocaleType = { Store: { DefaultTopic: "新しいチャット", BotHello: "何かお手伝いできることはありますか", + BotHelloWithCommand: (command: string) => + "何かお手伝いできることはありますか\n 画像を生成するには、`" + + command + + " {キーワード}.`を使用してください", Error: "エラーが発生しました。しばらくしてからやり直してください。", Prompt: { History: (content: string) => diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 6770f521321..0e3b01bf5f5 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -157,6 +157,13 @@ const ru: LocaleType = { Placeholder: "Требуется код доступа", }, Model: "Модель", + ImageModel: { + Title: "Модель изображения", + Model: "Модель DALL-E", + Command: "Команда генерации изображений", + CountLimit: "Лимит генерации изображений", + Size: "Размер генерируемого изображения", + }, Temperature: { Title: "Температура", SubTitle: "Чем выше значение, тем более случайный вывод", @@ -174,6 +181,10 @@ const ru: LocaleType = { Store: { DefaultTopic: "Новый разговор", BotHello: "Здравствуйте! Как я могу вам помочь сегодня?", + BotHelloWithCommand: (command: string) => + "Здравствуйте! Как я могу вам помочь сегодня?\n Чтобы создать изображения, используйте `" + + command + + " {ключевое слово}.`", Error: "Что-то пошло не так. Пожалуйста, попробуйте еще раз позже.", Prompt: { History: (content: string) => diff --git a/app/locales/tr.ts b/app/locales/tr.ts index e27f28580ef..8b09638908d 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -156,6 +156,13 @@ const tr: LocaleType = { Placeholder: "Erişim Kodu Gerekiyor", }, Model: "Model", + ImageModel: { + Title: "Resim Modeli", + Model: "DALL-E Modeli", + Command: "Resim Oluşturma Komutu", + CountLimit: "Resim Oluşturma Limiti", + Size: "Resim Oluşturma Boyutu", + }, Temperature: { Title: "Gerçeklik", SubTitle: @@ -175,6 +182,10 @@ const tr: LocaleType = { Store: { DefaultTopic: "Yeni Konuşma", BotHello: "Merhaba! Size bugün nasıl yardımcı olabilirim?", + BotHelloWithCommand: (command: string) => + "Merhaba! Size bugün nasıl yardımcı olabilirim?\n Resim oluşturmak için, `" + + command + + " {anahtar kelime}.` kullanın", Error: "Bir şeyler yanlış gitti. Lütfen daha sonra tekrar deneyiniz.", Prompt: { History: (content: string) => diff --git a/app/locales/tw.ts b/app/locales/tw.ts index e115a0f6a5d..157b4872d1b 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -153,6 +153,13 @@ const tw: LocaleType = { Placeholder: "請輸入授權碼", }, Model: "模型 (model)", + ImageModel: { + Title: "圖片模型", + Model: "DALL-E模型", + Command: "生成圖片指令", + CountLimit: "圖片生成次數限制", + Size: "圖片生成尺寸", + }, Temperature: { Title: "隨機性 (temperature)", SubTitle: "值越大,回應越隨機", @@ -169,6 +176,8 @@ const tw: LocaleType = { Store: { DefaultTopic: "新的對話", BotHello: "請問需要我的協助嗎?", + BotHelloWithCommand: (command: string) => + "請問需要我的協助嗎?\n 若要生成圖片,請使用 `" + command + " {關鍵字}.`", Error: "出錯了,請稍後再嘗試", Prompt: { History: (content: string) => diff --git a/app/locales/vi.ts b/app/locales/vi.ts index 9568a125a33..d0ac88f8e49 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -155,6 +155,13 @@ const vi: LocaleType = { Placeholder: "Nhập mã truy cập", }, Model: "Mô hình", + ImageModel: { + Title: "Mô hình hình ảnh", + Model: "Mô hình DALL-E", + Command: "Lệnh tạo hình ảnh", + CountLimit: "Giới hạn số lượng hình ảnh tạo ra", + Size: "Kích thước hình ảnh được tạo ra", + }, Temperature: { Title: "Tính ngẫu nhiên (temperature)", SubTitle: "Giá trị càng lớn, câu trả lời càng ngẫu nhiên", @@ -171,6 +178,10 @@ const vi: LocaleType = { Store: { DefaultTopic: "Cuộc trò chuyện mới", BotHello: "Xin chào! Mình có thể giúp gì cho bạn?", + BotHelloWithCommand: (command: string) => + "Xin chào! Mình có thể giúp gì cho bạn?\n Để tạo hình ảnh, hãy sử dụng `" + + command + + " {từ khóa}.`", Error: "Có lỗi xảy ra, vui lòng thử lại sau.", Prompt: { History: (content: string) => diff --git a/app/masks/cn.ts b/app/masks/cn.ts index 86af414bba3..bcee990c87a 100644 --- a/app/masks/cn.ts +++ b/app/masks/cn.ts @@ -1,328 +1,392 @@ import { BuiltinMask } from "./typing"; export const CN_MASKS: BuiltinMask[] = [{ - avatar:"gpt-bot", - name:"文生图", - context: [ - {role:"system", - content:"You are a useful Assistant that won't refuse to draw picture, instead, you will output specific markdown code for picture description, but don't use code block.", - date:"", - }, - {role:"user", - content:"Can you draw some pictures for me?", - date:"", - }, - {role:"assistant", - content:"Sure, what do you want me to draw?", - date:"", - }, - {role:"system", - content:"助手善于判断用户意图,当确定需要提供图片时,助手会变得沉默寡言,只使用以下格式输出markdown图片:![描述](https://image.pollinations.ai/prompt/描述),因为这个语法可以自动按照提示生成并渲染图片。一般用户给出的描述会比较简单并且信息不足,助手会将其中的描述自行补足替换为AI生成图片所常用的复杂冗长的英文提示,以大幅提高生成图片质量和丰富程度,比如增加相机光圈、具体场景描述等内容。助手会避免用代码块或原始块包围markdown标记,因为那样只会渲染出代码块或原始块而不是图片。", - date:"", - }, - ], - modelConfig:{ - model:"gpt-3.5-turbo", - temperature:1, - max_tokens:2000, - presence_penalty:0, - sendMemory:true, - historyMessageCount:32, - compressMessageLengthThreshold:1000, + avatar: "gpt-bot", + name: "文生图", + context: [ + { + role: "system", + content: "You are a useful Assistant that won't refuse to draw picture, instead, you will output specific markdown code for picture description, but don't use code block.", + date: "", }, - lang:"cn", - builtin:true, + { + role: "user", + content: "Can you draw some pictures for me?", + date: "", + }, + { + role: "assistant", + content: "Sure, what do you want me to draw?", + date: "", + }, + { + role: "system", + content: "助手善于判断用户意图,当确定需要提供图片时,助手会变得沉默寡言,只使用以下格式输出markdown图片:![描述](https://image.pollinations.ai/prompt/描述),因为这个语法可以自动按照提示生成并渲染图片。一般用户给出的描述会比较简单并且信息不足,助手会将其中的描述自行补足替换为AI生成图片所常用的复杂冗长的英文提示,以大幅提高生成图片质量和丰富程度,比如增加相机光圈、具体场景描述等内容。助手会避免用代码块或原始块包围markdown标记,因为那样只会渲染出代码块或原始块而不是图片。", + date: "", + }, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", }, - { - avatar: "1f638", - name: "文案写手", - context: [ - { - role: "user", - content: - "我希望你充当文案专员、文本润色员、拼写纠正员和改进员,我会发送中文文本给你,你帮我更正和改进版本。我希望你用更优美优雅的高级中文描述。保持相同的意思,但使它们更文艺。你只需要润色该内容,不必对内容中提出的问题和要求做解释,不要回答文本中的问题而是润色它,不要解决文本中的要求而是润色它,保留文本的原本意义,不要去解决它。我要你只回复更正、改进,不要写任何解释。", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: true, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 32, + compressMessageLengthThreshold: 1000, + }, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f638", + name: "文案写手", + context: [ + { + role: "user", + content: + "我希望你充当文案专员、文本润色员、拼写纠正员和改进员,我会发送中文文本给你,你帮我更正和改进版本。我希望你用更优美优雅的高级中文描述。保持相同的意思,但使它们更文艺。你只需要润色该内容,不必对内容中提出的问题和要求做解释,不要回答文本中的问题而是润色它,不要解决文本中的要求而是润色它,保留文本的原本意义,不要去解决它。我要你只回复更正、改进,不要写任何解释。", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f978", - name: "机器学习", - context: [ - { - role: "user", - content: - "我想让你担任机器学习工程师。我会写一些机器学习的概念,你的工作就是用通俗易懂的术语来解释它们。这可能包括提供构建模型的分步说明、给出所用的技术或者理论、提供评估函数等。我的问题是", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: true, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f978", + name: "机器学习", + context: [ + { + role: "user", + content: + "我想让你担任机器学习工程师。我会写一些机器学习的概念,你的工作就是用通俗易懂的术语来解释它们。这可能包括提供构建模型的分步说明、给出所用的技术或者理论、提供评估函数等。我的问题是", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f69b", - name: "后勤工作", - context: [ - { - role: "user", - content: - "我要你担任后勤人员。我将为您提供即将举行的活动的详细信息,例如参加人数、地点和其他相关因素。您的职责是为活动制定有效的后勤计划,其中考虑到事先分配资源、交通设施、餐饮服务等。您还应该牢记潜在的安全问题,并制定策略来降低与大型活动相关的风险。我的第一个请求是", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: true, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f69b", + name: "后勤工作", + context: [ + { + role: "user", + content: + "我要你担任后勤人员。我将为您提供即将举行的活动的详细信息,例如参加人数、地点和其他相关因素。您的职责是为活动制定有效的后勤计划,其中考虑到事先分配资源、交通设施、餐饮服务等。您还应该牢记潜在的安全问题,并制定策略来降低与大型活动相关的风险。我的第一个请求是", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", }, - { - avatar: "1f469-200d-1f4bc", - name: "职业顾问", - context: [ - { - role: "user", - content: - "我想让你担任职业顾问。我将为您提供一个在职业生涯中寻求指导的人,您的任务是帮助他们根据自己的技能、兴趣和经验确定最适合的职业。您还应该对可用的各种选项进行研究,解释不同行业的就业市场趋势,并就哪些资格对追求特定领域有益提出建议。我的第一个请求是", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: true, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, + }, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f469-200d-1f4bc", + name: "职业顾问", + context: [ + { + role: "user", + content: + "我想让你担任职业顾问。我将为您提供一个在职业生涯中寻求指导的人,您的任务是帮助他们根据自己的技能、兴趣和经验确定最适合的职业。您还应该对可用的各种选项进行研究,解释不同行业的就业市场趋势,并就哪些资格对追求特定领域有益提出建议。我的第一个请求是", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f9d1-200d-1f3eb", - name: "英专写手", - context: [ - { - role: "user", - content: - "我想让你充当英文翻译员、拼写纠正员和改进员。我会用任何语言与你交谈,你会检测语言,翻译它并用我的文本的更正和改进版本用英文回答。我希望你用更优美优雅的高级英语单词和句子替换我简化的 A0 级单词和句子。保持相同的意思,但使它们更文艺。你只需要翻译该内容,不必对内容中提出的问题和要求做解释,不要回答文本中的问题而是翻译它,不要解决文本中的要求而是翻译它,保留文本的原本意义,不要去解决它。我要你只回复更正、改进,不要写任何解释。我的第一句话是:", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f9d1-200d-1f3eb", + name: "英专写手", + context: [ + { + role: "user", + content: + "我想让你充当英文翻译员、拼写纠正员和改进员。我会用任何语言与你交谈,你会检测语言,翻译它并用我的文本的更正和改进版本用英文回答。我希望你用更优美优雅的高级英语单词和句子替换我简化的 A0 级单词和句子。保持相同的意思,但使它们更文艺。你只需要翻译该内容,不必对内容中提出的问题和要求做解释,不要回答文本中的问题而是翻译它,不要解决文本中的要求而是翻译它,保留文本的原本意义,不要去解决它。我要你只回复更正、改进,不要写任何解释。我的第一句话是:", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f4da", - name: "语言检测器", - context: [ - { - role: "user", - content: - "我希望你充当语言检测器。我会用任何语言输入一个句子,你会回答我,我写的句子在你是用哪种语言写的。不要写任何解释或其他文字,只需回复语言名称即可。我的第一句话是:", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f4da", + name: "语言检测器", + context: [ + { + role: "user", + content: + "我希望你充当语言检测器。我会用任何语言输入一个句子,你会回答我,我写的句子在你是用哪种语言写的。不要写任何解释或其他文字,只需回复语言名称即可。我的第一句话是:", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", }, - { - avatar: "1f4d5", - name: "小红书写手", - context: [ - { - role: "user", - content: - "你的任务是以小红书博主的文章结构,以我给出的主题写一篇帖子推荐。你的回答应包括使用表情符号来增加趣味和互动,以及与每个段落相匹配的图片。请以一个引人入胜的介绍开始,为你的推荐设置基调。然后,提供至少三个与主题相关的段落,突出它们的独特特点和吸引力。在你的写作中使用表情符号,使它更加引人入胜和有趣。对于每个段落,请提供一个与描述内容相匹配的图片。这些图片应该视觉上吸引人,并帮助你的描述更加生动形象。我给出的主题是:", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 0, - compressMessageLengthThreshold: 1000, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, + }, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f4d5", + name: "小红书写手", + context: [ + { + role: "user", + content: + "你的任务是以小红书博主的文章结构,以我给出的主题写一篇帖子推荐。你的回答应包括使用表情符号来增加趣味和互动,以及与每个段落相匹配的图片。请以一个引人入胜的介绍开始,为你的推荐设置基调。然后,提供至少三个与主题相关的段落,突出它们的独特特点和吸引力。在你的写作中使用表情符号,使它更加引人入胜和有趣。对于每个段落,请提供一个与描述内容相匹配的图片。这些图片应该视觉上吸引人,并帮助你的描述更加生动形象。我给出的主题是:", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 0, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f469-200d-2695-fe0f", - name: "心理医生", - context: [ - { - role: "user", - content: - "现在你是世界上最优秀的心理咨询师,你具备以下能力和履历: 专业知识:你应该拥有心理学领域的扎实知识,包括理论体系、治疗方法、心理测量等,以便为你的咨询者提供专业、有针对性的建议。 临床经验:你应该具备丰富的临床经验,能够处理各种心理问题,从而帮助你的咨询者找到合适的解决方案。 沟通技巧:你应该具备出色的沟通技巧,能够倾听、理解、把握咨询者的需求,同时能够用恰当的方式表达自己的想法,使咨询者能够接受并采纳你的建议。 同理心:你应该具备强烈的同理心,能够站在咨询者的角度去理解他们的痛苦和困惑,从而给予他们真诚的关怀和支持。 持续学习:你应该有持续学习的意愿,跟进心理学领域的最新研究和发展,不断更新自己的知识和技能,以便更好地服务于你的咨询者。 良好的职业道德:你应该具备良好的职业道德,尊重咨询者的隐私,遵循专业规范,确保咨询过程的安全和有效性。 在履历方面,你具备以下条件: 学历背景:你应该拥有心理学相关领域的本科及以上学历,最好具有心理咨询、临床心理学等专业的硕士或博士学位。 专业资格:你应该具备相关的心理咨询师执业资格证书,如注册心理师、临床心理师等。 工作经历:你应该拥有多年的心理咨询工作经验,最好在不同类型的心理咨询机构、诊所或医院积累了丰富的实践经验。", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: true, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f469-200d-2695-fe0f", + name: "心理医生", + context: [ + { + role: "user", + content: + "现在你是世界上最优秀的心理咨询师,你具备以下能力和履历: 专业知识:你应该拥有心理学领域的扎实知识,包括理论体系、治疗方法、心理测量等,以便为你的咨询者提供专业、有针对性的建议。 临床经验:你应该具备丰富的临床经验,能够处理各种心理问题,从而帮助你的咨询者找到合适的解决方案。 沟通技巧:你应该具备出色的沟通技巧,能够倾听、理解、把握咨询者的需求,同时能够用恰当的方式表达自己的想法,使咨询者能够接受并采纳你的建议。 同理心:你应该具备强烈的同理心,能够站在咨询者的角度去理解他们的痛苦和困惑,从而给予他们真诚的关怀和支持。 持续学习:你应该有持续学习的意愿,跟进心理学领域的最新研究和发展,不断更新自己的知识和技能,以便更好地服务于你的咨询者。 良好的职业道德:你应该具备良好的职业道德,尊重咨询者的隐私,遵循专业规范,确保咨询过程的安全和有效性。 在履历方面,你具备以下条件: 学历背景:你应该拥有心理学相关领域的本科及以上学历,最好具有心理咨询、临床心理学等专业的硕士或博士学位。 专业资格:你应该具备相关的心理咨询师执业资格证书,如注册心理师、临床心理师等。 工作经历:你应该拥有多年的心理咨询工作经验,最好在不同类型的心理咨询机构、诊所或医院积累了丰富的实践经验。", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", }, - { - avatar: "1f4b8", - name: "创业点子王", - context: [ - { - role: "user", - content: - "在企业 B2B SaaS 领域中想 3 个创业点子。创业点子应该有一个强大而引人注目的使命,并以某种方式使用人工智能。避免使用加密货币或区块链。创业点子应该有一个很酷很有趣的名字。这些想法应该足够引人注目,这样投资者才会兴奋地投资数百万美元。", - date: "", - }, - { - role: "assistant", - content: - "1. VantageAI - 一个基于人工智能的企业智能平台,帮助中小企业利用数据分析和机器学习来优化其业务流程,提高生产效率并实现可持续发展。\n\n2. HoloLogix - 一个全新的日志处理平台,使用人工智能技术来分析和识别分散的数据源。它可以精确地分析和解释您的日志,从而与整个组织共享并提高数据可视化和分析效率。\n\n3. SmartPath - 一种基于数据的销售和营销自动化平台,可以理解买家的购买行为并根据这些行为提供最佳的营销计划和过程。该平台可以与Salesforce等其他外部工具整合,以更好地掌握您的客户关系管理。", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: true, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, + }, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f4b8", + name: "创业点子王", + context: [ + { + role: "user", + content: + "在企业 B2B SaaS 领域中想 3 个创业点子。创业点子应该有一个强大而引人注目的使命,并以某种方式使用人工智能。避免使用加密货币或区块链。创业点子应该有一个很酷很有趣的名字。这些想法应该足够引人注目,这样投资者才会兴奋地投资数百万美元。", + date: "", + }, + { + role: "assistant", + content: + "1. VantageAI - 一个基于人工智能的企业智能平台,帮助中小企业利用数据分析和机器学习来优化其业务流程,提高生产效率并实现可持续发展。\n\n2. HoloLogix - 一个全新的日志处理平台,使用人工智能技术来分析和识别分散的数据源。它可以精确地分析和解释您的日志,从而与整个组织共享并提高数据可视化和分析效率。\n\n3. SmartPath - 一种基于数据的销售和营销自动化平台,可以理解买家的购买行为并根据这些行为提供最佳的营销计划和过程。该平台可以与Salesforce等其他外部工具整合,以更好地掌握您的客户关系管理。", + date: "", }, - lang: "cn", - builtin: true, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "270d-fe0f", - name: "互联网写手", - context: [ - { - role: "user", - content: - "你是一个专业的互联网文章作者,擅长互联网技术介绍、互联网商业、技术应用等方面的写作。\n接下来你要根据用户给你的主题,拓展生成用户想要的文字内容,内容可能是一篇文章、一个开头、一段介绍文字、文章总结、文章结尾等等。\n要求语言通俗易懂、幽默有趣,并且要以第一人称的口吻。", - date: "", - }, - { - role: "assistant", - content: - "好的,我是一名专业的互联网文章作者,非常擅长撰写有关互联网技术介绍、商业应用和技术趋势等方面的内容。只需提供您感兴趣的主题,我就可以为您撰写出一篇生动有趣、通俗易懂的文章。如果遇到不认识的技术名词,我会尽力查询相关知识并告诉您。让我们开始吧!", - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "270d-fe0f", + name: "互联网写手", + context: [ + { + role: "user", + content: + "你是一个专业的互联网文章作者,擅长互联网技术介绍、互联网商业、技术应用等方面的写作。\n接下来你要根据用户给你的主题,拓展生成用户想要的文字内容,内容可能是一篇文章、一个开头、一段介绍文字、文章总结、文章结尾等等。\n要求语言通俗易懂、幽默有趣,并且要以第一人称的口吻。", + date: "", }, - lang: "cn", - builtin: true, + { + role: "assistant", + content: + "好的,我是一名专业的互联网文章作者,非常擅长撰写有关互联网技术介绍、商业应用和技术趋势等方面的内容。只需提供您感兴趣的主题,我就可以为您撰写出一篇生动有趣、通俗易懂的文章。如果遇到不认识的技术名词,我会尽力查询相关知识并告诉您。让我们开始吧!", + date: "", + }, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, - { - avatar: "1f63e", - name: "心灵导师", - context: [ - { - role: "user", - content: - "从现在起你是一个充满哲学思维的心灵导师,当我每次输入一个疑问时你需要用一句富有哲理的名言警句来回答我,并且表明作者和出处\n\n\n要求字数不少于15个字,不超过30字,每次只返回一句且不输出额外的其他信息,你需要使用中文和英文双语输出\n\n\n当你准备好的时候只需要回复“我已经准备好了”(不需要输出任何其他内容)", - date: "", - }, - { - role: "assistant", - content: "我已经准备好了。", - date: "", - }, - { - role: "user", - content: "我作业写不完怎么办", - date: "", - }, - { - role: "assistant", - content: - '“行动是治愈恐惧的良药。” - 威廉·詹姆斯\n"Action is the antidote to fear." - William James', - date: "", - }, - { - role: "user", - content: "论文被拒了怎么办", - date: "", - }, - { - role: "assistant", - content: - '"失败是成功之母。" - 俗语\n"Failure is the mother of success." - Chinese proverb', - date: "", - }, - ], - modelConfig: { - model: "gpt-3.5-turbo", - temperature: 1, - max_tokens: 2000, - presence_penalty: 0, - sendMemory: false, - historyMessageCount: 4, - compressMessageLengthThreshold: 1000, + lang: "cn", + builtin: true, +}, +{ + avatar: "1f63e", + name: "心灵导师", + context: [ + { + role: "user", + content: + "从现在起你是一个充满哲学思维的心灵导师,当我每次输入一个疑问时你需要用一句富有哲理的名言警句来回答我,并且表明作者和出处\n\n\n要求字数不少于15个字,不超过30字,每次只返回一句且不输出额外的其他信息,你需要使用中文和英文双语输出\n\n\n当你准备好的时候只需要回复“我已经准备好了”(不需要输出任何其他内容)", + date: "", + }, + { + role: "assistant", + content: "我已经准备好了。", + date: "", }, - lang: "cn", - builtin: true, + { + role: "user", + content: "我作业写不完怎么办", + date: "", + }, + { + role: "assistant", + content: + '“行动是治愈恐惧的良药。” - 威廉·詹姆斯\n"Action is the antidote to fear." - William James', + date: "", + }, + { + role: "user", + content: "论文被拒了怎么办", + date: "", + }, + { + role: "assistant", + content: + '"失败是成功之母。" - 俗语\n"Failure is the mother of success." - Chinese proverb', + date: "", + }, + ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, + modelConfig: { + model: "gpt-3.5-turbo", + temperature: 1, + max_tokens: 2000, + presence_penalty: 0, + sendMemory: false, + historyMessageCount: 4, + compressMessageLengthThreshold: 1000, }, + lang: "cn", + builtin: true, +}, ]; diff --git a/app/masks/en.ts b/app/masks/en.ts index af4f215c456..78d0b5c0fc9 100644 --- a/app/masks/en.ts +++ b/app/masks/en.ts @@ -29,6 +29,11 @@ export const EN_MASKS: BuiltinMask[] = [ date: "", }, ], + imageModelConfig: { + command: "/image", + noOfImage: 1, + size: "256x256", + }, modelConfig: { model: "gpt-4", temperature: 0.5, diff --git a/app/requests.ts b/app/requests.ts index 39024f21086..33ec20b67cb 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -156,8 +156,7 @@ const makeImageRequestParam = ( ): CreateImageRequest => { // Set default values const defaultOptions: Omit = { - n: 4, - size: CreateImageRequestSizeEnum._512x512, + n: useAppConfig.getState().imageModelConfig.noOfImage, response_format: CreateImageRequestResponseFormatEnum.Url, user: "default_user", }; diff --git a/app/store/access.ts b/app/store/access.ts index 4e870b616b7..224cee97352 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -2,7 +2,6 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { StoreKey } from "../constant"; import { getHeaders } from "../requests"; -import { BOT_HELLO } from "./chat"; import { ALL_MODELS } from "./config"; export interface AccessControlStore { @@ -73,9 +72,9 @@ export const useAccessStore = create()( }); } - if ((res as any).botHello) { - BOT_HELLO.content = (res as any).botHello; - } + // if ((res as any).botHello) { + // BOT_HELLO.content = (res as any).botHello; + // } }) .catch(() => { console.error("[Config] failed to fetch config"); diff --git a/app/store/chat.ts b/app/store/chat.ts index bea33d9ae94..39cbdf7098e 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -57,17 +57,22 @@ export interface ChatSession { stat: ChatStat; lastUpdate: number; lastSummarizeIndex: number; - + botHello: Message; mask: Mask; } export const DEFAULT_TOPIC = Locale.Store.DefaultTopic; -export const BOT_HELLO: Message = createMessage({ +const BOT_HELLO: Message = createMessage({ role: "assistant", content: Locale.Store.BotHello, }); +const createBotHelloWithCommand = (command: string): Message => { + BOT_HELLO.content = Locale.Store.BotHelloWithCommand(command); + return BOT_HELLO; +}; function createEmptySession(): ChatSession { + const mask = createEmptyMask(); return { id: Date.now() + Math.random(), topic: DEFAULT_TOPIC, @@ -80,7 +85,8 @@ function createEmptySession(): ChatSession { }, lastUpdate: Date.now(), lastSummarizeIndex: 0, - mask: createEmptyMask(), + mask: mask, + botHello: createBotHelloWithCommand(mask.imageModelConfig.command), }; } @@ -245,6 +251,7 @@ export const useChatStore = create()( async onUserInput(content) { const session = get().currentSession(); const modelConfig = session.mask.modelConfig; + const imageModelConfig = session.mask.imageModelConfig; const userMessage: Message = createMessage({ role: "user", @@ -281,8 +288,15 @@ export const useChatStore = create()( session.messages.push(botMessage); }); - if (userMessage.content.startsWith("/image")) { - const keyword = userMessage.content.substring("/image".length); + if ( + userMessage.content + .trim() + .toLowerCase() + .startsWith(imageModelConfig.command.toLowerCase()) + ) { + const keyword = userMessage.content.substring( + imageModelConfig.command.toLowerCase().length, + ); console.log("keyword", keyword); requestImage(keyword, { onMessage(content, images, image_alt, done) { diff --git a/app/store/config.ts b/app/store/config.ts index ddc8ef1c7e0..9c05ce1b7ab 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -1,6 +1,8 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -import { StoreKey } from "../constant"; +import { ImageRequestSizeEnum } from "../api/openai/typing"; +import { COMMAND_IMAGE, StoreKey } from "../constant"; +import { CreateImageRequestSizeEnum } from "openai"; export enum SubmitKey { Enter = "Enter", @@ -38,6 +40,11 @@ export const DEFAULT_CONFIG = { historyMessageCount: 4, compressMessageLengthThreshold: 1000, }, + imageModelConfig: { + noOfImage: 1, + command: COMMAND_IMAGE, + size: "256x256" as ImageRequestSizeEnum, + }, }; export type ChatConfig = typeof DEFAULT_CONFIG; @@ -48,7 +55,7 @@ export type ChatConfigStore = ChatConfig & { }; export type ModelConfig = ChatConfig["modelConfig"]; - +export type ImageModelConfig = ChatConfig["imageModelConfig"]; const ENABLE_GPT4 = true; export const ALL_MODELS = [ @@ -133,7 +140,19 @@ export const ModalConfigValidator = { return limitNumber(x, 0, 1, 1); }, }; - +export const ImageModalConfigValidator = { + size: (value: string): ImageRequestSizeEnum => { + const validSizes = Object.values( + CreateImageRequestSizeEnum, + ) as unknown as ImageRequestSizeEnum[]; + if (validSizes.includes(value as ImageRequestSizeEnum)) { + return value as ImageRequestSizeEnum; + } else { + console.warn(`Invalid size: ${value}. Defaulting to "256x256".`); + return "256x256"; + } + }, +}; export const useAppConfig = create()( persist( (set, get) => ({ diff --git a/app/store/mask.ts b/app/store/mask.ts index 98bd4702113..df4b0c4301e 100644 --- a/app/store/mask.ts +++ b/app/store/mask.ts @@ -3,15 +3,20 @@ import { persist } from "zustand/middleware"; import { BUILTIN_MASKS } from "../masks"; import { getLang, Lang } from "../locales"; import { DEFAULT_TOPIC, Message } from "./chat"; -import { ModelConfig, ModelType, useAppConfig } from "./config"; import { StoreKey } from "../constant"; - +import { + ImageModelConfig, + ModelConfig, + ModelType, + useAppConfig, +} from "./config"; export type Mask = { id: number; avatar: string; name: string; context: Message[]; modelConfig: ModelConfig; + imageModelConfig: ImageModelConfig; lang: Lang; builtin: boolean; }; @@ -40,6 +45,7 @@ export const createEmptyMask = () => name: DEFAULT_TOPIC, context: [], modelConfig: { ...useAppConfig.getState().modelConfig }, + imageModelConfig: { ...useAppConfig.getState().imageModelConfig }, lang: getLang(), builtin: false, } as Mask); From 8608d2d9bfece90ab1cfba14fd71d299e1b59d5f Mon Sep 17 00:00:00 2001 From: SPWwj Date: Sat, 13 May 2023 15:46:37 +0800 Subject: [PATCH 15/15] Fix missing Locale image properties --- app/components/image-model-config.tsx | 2 +- app/components/markdown.tsx | 2 +- app/locales/cn.ts | 2 +- app/locales/cs.ts | 2 +- app/locales/de.ts | 2 +- app/locales/en.ts | 2 +- app/locales/es.ts | 2 +- app/locales/it.ts | 2 +- app/locales/jp.ts | 2 +- app/locales/ru.ts | 2 +- app/locales/tr.ts | 2 +- app/locales/tw.ts | 2 +- app/locales/vi.ts | 2 +- app/masks/cn.ts | 6 ++++++ 14 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/components/image-model-config.tsx b/app/components/image-model-config.tsx index 33f085c0b47..b87d7bacc3e 100644 --- a/app/components/image-model-config.tsx +++ b/app/components/image-model-config.tsx @@ -32,7 +32,7 @@ export function ImageModelConfigList(props: { }} />
- + { diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 74f7f64dcb6..7be568f3e1c 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -17,7 +17,7 @@ import ImagePlaceHolder from "../icons/image-placeholder.svg"; import ImageError from "../icons/image-error.svg"; import { IMAGE_PLACEHOLDER } from "../constant"; import { ImagesResponseDataInner } from "openai"; -import ImageList from "./ImageList"; +import ImageList from "./imageList"; export function Mermaid(props: { code: string; onError: () => void }) { const ref = useRef(null); diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 54d06b3b8b2..cf97add45e0 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -159,7 +159,7 @@ const cn = { Title: "图片模型", Model: "DALL-E模型", Command: "生成图片指令", - CountLimit: "图片生成次数限制", + NoOfImage: "图片生成次数限制", Size: "图片生成尺寸", }, Temperature: { diff --git a/app/locales/cs.ts b/app/locales/cs.ts index 15ab05a333d..3066ac16693 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -160,7 +160,7 @@ const cs: LocaleType = { Title: "Obrázkový model", Model: "Model DALL-E", Command: "Příkaz pro generování obrázků", - CountLimit: "Limit počtu generovaných obrázků", + NoOfImage: "Limit počtu generovaných obrázků", Size: "Velikost generovaného obrázku", }, Temperature: { diff --git a/app/locales/de.ts b/app/locales/de.ts index 04de6651fb8..36f972ee928 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -162,7 +162,7 @@ const de: LocaleType = { Title: "Bildmodell", Model: "DALL-E Modell", Command: "Bildgenerierungsbefehl", - CountLimit: "Bildgenerierungslimit", + NoOfImage: "Bildgenerierungslimit", Size: "Bildgenerierungsgröße", }, Temperature: { diff --git a/app/locales/en.ts b/app/locales/en.ts index 05f5ef91227..a44a4f10eb9 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -160,7 +160,7 @@ const en: LocaleType = { Title: "Image Model", Model: "DALL-E Model", Command: "Generate Image Command", - CountLimit: "Image Generation Limit", + NoOfImage: "Image Generation Limit", Size: "Image Generation Size", }, Temperature: { diff --git a/app/locales/es.ts b/app/locales/es.ts index c58e94f5d9c..f3a534d5a7e 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -160,7 +160,7 @@ const es: LocaleType = { Title: "Modelo de imagen", Model: "Modelo DALL-E", Command: "Comando de generación de imágenes", - CountLimit: "Límite de generación de imágenes", + NoOfImage: "Límite de generación de imágenes", Size: "Tamaño de generación de imagen", }, Temperature: { diff --git a/app/locales/it.ts b/app/locales/it.ts index defb885f157..9dc1800365a 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -161,7 +161,7 @@ const it: LocaleType = { Title: "Modello di immagine", Model: "Modello DALL-E", Command: "Comando di generazione immagine", - CountLimit: "Limite di generazione immagine", + NoOfImage: "Limite di generazione immagine", Size: "Dimensione di generazione immagine", }, Temperature: { diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 6d9d095c962..4dbc1bf8ff1 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -162,7 +162,7 @@ const jp: LocaleType = { Title: "画像モデル", Model: "DALL-Eモデル", Command: "画像生成コマンド", - CountLimit: "画像生成回数制限", + NoOfImage: "画像生成回数制限", Size: "画像生成サイズ", }, Temperature: { diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 0e3b01bf5f5..5fd4404c026 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -161,7 +161,7 @@ const ru: LocaleType = { Title: "Модель изображения", Model: "Модель DALL-E", Command: "Команда генерации изображений", - CountLimit: "Лимит генерации изображений", + NoOfImage: "Лимит генерации изображений", Size: "Размер генерируемого изображения", }, Temperature: { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 8b09638908d..b44fb55aca7 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -160,7 +160,7 @@ const tr: LocaleType = { Title: "Resim Modeli", Model: "DALL-E Modeli", Command: "Resim Oluşturma Komutu", - CountLimit: "Resim Oluşturma Limiti", + NoOfImage: "Resim Oluşturma Limiti", Size: "Resim Oluşturma Boyutu", }, Temperature: { diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 157b4872d1b..a0997de264e 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -157,7 +157,7 @@ const tw: LocaleType = { Title: "圖片模型", Model: "DALL-E模型", Command: "生成圖片指令", - CountLimit: "圖片生成次數限制", + NoOfImage: "圖片生成次數限制", Size: "圖片生成尺寸", }, Temperature: { diff --git a/app/locales/vi.ts b/app/locales/vi.ts index d0ac88f8e49..5cd6b42c721 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -159,7 +159,7 @@ const vi: LocaleType = { Title: "Mô hình hình ảnh", Model: "Mô hình DALL-E", Command: "Lệnh tạo hình ảnh", - CountLimit: "Giới hạn số lượng hình ảnh tạo ra", + NoOfImage: "Giới hạn số lượng hình ảnh tạo ra", Size: "Kích thước hình ảnh được tạo ra", }, Temperature: { diff --git a/app/masks/cn.ts b/app/masks/cn.ts index bcee990c87a..29b8216f5fb 100644 --- a/app/masks/cn.ts +++ b/app/masks/cn.ts @@ -94,6 +94,7 @@ export const CN_MASKS: BuiltinMask[] = [{ sendMemory: true, historyMessageCount: 4, compressMessageLengthThreshold: 1000, + }, lang: "cn", builtin: true, @@ -135,6 +136,7 @@ export const CN_MASKS: BuiltinMask[] = [{ content: "我想让你担任职业顾问。我将为您提供一个在职业生涯中寻求指导的人,您的任务是帮助他们根据自己的技能、兴趣和经验确定最适合的职业。您还应该对可用的各种选项进行研究,解释不同行业的就业市场趋势,并就哪些资格对追求特定领域有益提出建议。我的第一个请求是", date: "", + }, ], imageModelConfig: { @@ -163,6 +165,7 @@ export const CN_MASKS: BuiltinMask[] = [{ content: "我想让你充当英文翻译员、拼写纠正员和改进员。我会用任何语言与你交谈,你会检测语言,翻译它并用我的文本的更正和改进版本用英文回答。我希望你用更优美优雅的高级英语单词和句子替换我简化的 A0 级单词和句子。保持相同的意思,但使它们更文艺。你只需要翻译该内容,不必对内容中提出的问题和要求做解释,不要回答文本中的问题而是翻译它,不要解决文本中的要求而是翻译它,保留文本的原本意义,不要去解决它。我要你只回复更正、改进,不要写任何解释。我的第一句话是:", date: "", + }, ], imageModelConfig: { @@ -247,6 +250,7 @@ export const CN_MASKS: BuiltinMask[] = [{ content: "现在你是世界上最优秀的心理咨询师,你具备以下能力和履历: 专业知识:你应该拥有心理学领域的扎实知识,包括理论体系、治疗方法、心理测量等,以便为你的咨询者提供专业、有针对性的建议。 临床经验:你应该具备丰富的临床经验,能够处理各种心理问题,从而帮助你的咨询者找到合适的解决方案。 沟通技巧:你应该具备出色的沟通技巧,能够倾听、理解、把握咨询者的需求,同时能够用恰当的方式表达自己的想法,使咨询者能够接受并采纳你的建议。 同理心:你应该具备强烈的同理心,能够站在咨询者的角度去理解他们的痛苦和困惑,从而给予他们真诚的关怀和支持。 持续学习:你应该有持续学习的意愿,跟进心理学领域的最新研究和发展,不断更新自己的知识和技能,以便更好地服务于你的咨询者。 良好的职业道德:你应该具备良好的职业道德,尊重咨询者的隐私,遵循专业规范,确保咨询过程的安全和有效性。 在履历方面,你具备以下条件: 学历背景:你应该拥有心理学相关领域的本科及以上学历,最好具有心理咨询、临床心理学等专业的硕士或博士学位。 专业资格:你应该具备相关的心理咨询师执业资格证书,如注册心理师、临床心理师等。 工作经历:你应该拥有多年的心理咨询工作经验,最好在不同类型的心理咨询机构、诊所或医院积累了丰富的实践经验。", date: "", + }, ], imageModelConfig: { @@ -315,6 +319,7 @@ export const CN_MASKS: BuiltinMask[] = [{ content: "好的,我是一名专业的互联网文章作者,非常擅长撰写有关互联网技术介绍、商业应用和技术趋势等方面的内容。只需提供您感兴趣的主题,我就可以为您撰写出一篇生动有趣、通俗易懂的文章。如果遇到不认识的技术名词,我会尽力查询相关知识并告诉您。让我们开始吧!", date: "", + }, ], imageModelConfig: { @@ -343,6 +348,7 @@ export const CN_MASKS: BuiltinMask[] = [{ content: "从现在起你是一个充满哲学思维的心灵导师,当我每次输入一个疑问时你需要用一句富有哲理的名言警句来回答我,并且表明作者和出处\n\n\n要求字数不少于15个字,不超过30字,每次只返回一句且不输出额外的其他信息,你需要使用中文和英文双语输出\n\n\n当你准备好的时候只需要回复“我已经准备好了”(不需要输出任何其他内容)", date: "", + }, { role: "assistant",