Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Hk-Gosuto
2024-07-21 09:36:44 +00:00
66 changed files with 8668 additions and 3792 deletions

View File

@@ -71,7 +71,7 @@ import {
isSupportRAGModel,
} from "../utils";
import { compressImage } from "@/app/utils/chat";
import { uploadImage as uploadImageRemote } from "@/app/utils/chat";
import dynamic from "next/dynamic";
@@ -102,6 +102,7 @@ import {
Path,
REQUEST_TIMEOUT_MS,
UNFINISHED_INPUT,
ServiceProvider,
} from "../constant";
import { Avatar } from "./emoji";
import { ContextPrompts, MaskAvatar, MaskConfig } from "./mask";
@@ -269,11 +270,11 @@ function useSubmitHandler() {
};
}
export type RenderPompt = Pick<Prompt, "title" | "content">;
export type RenderPrompt = Pick<Prompt, "title" | "content">;
export function PromptHints(props: {
prompts: RenderPompt[];
onPromptSelect: (prompt: RenderPompt) => void;
prompts: RenderPrompt[];
onPromptSelect: (prompt: RenderPrompt) => void;
}) {
const noPrompts = props.prompts.length === 0;
const [selectIndex, setSelectIndex] = useState(0);
@@ -502,6 +503,9 @@ export function ChatActions(props: {
// switch model
const currentModel = chatStore.currentSession().mask.modelConfig.model;
const currentProviderName =
chatStore.currentSession().mask.modelConfig?.providerName ||
ServiceProvider.OpenAI;
const allModels = useAllModels();
const models = useMemo(() => {
const filteredModels = allModels.filter((m) => m.available);
@@ -517,6 +521,14 @@ export function ChatActions(props: {
return filteredModels;
}
}, [allModels]);
const currentModelName = useMemo(() => {
const model = models.find(
(m) =>
m.name == currentModel &&
m?.provider?.providerName == currentProviderName,
);
return model?.displayName ?? "";
}, [models, currentModel, currentProviderName]);
const [showModelSelector, setShowModelSelector] = useState(false);
const [showUploadImage, setShowUploadImage] = useState(false);
const [showUploadFile, setShowUploadFile] = useState(false);
@@ -542,13 +554,17 @@ export function ChatActions(props: {
const isUnavaliableModel = !models.some((m) => m.name === currentModel);
if (isUnavaliableModel && models.length > 0) {
// show next model to default model if exist
let nextModel: ModelType = (
models.find((model) => model.isDefault) || models[0]
).name;
chatStore.updateCurrentSession(
(session) => (session.mask.modelConfig.model = nextModel),
let nextModel = models.find((model) => model.isDefault) || models[0];
chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.model = nextModel.name;
session.mask.modelConfig.providerName = nextModel?.provider
?.providerName as ServiceProvider;
});
showToast(
nextModel?.provider?.providerName == "ByteDance"
? nextModel.displayName
: nextModel.name,
);
showToast(nextModel);
}
}, [chatStore, currentModel, models]);
@@ -584,7 +600,6 @@ export function ChatActions(props: {
icon={props.uploading ? <LoadingButtonIcon /> : <ImageIcon />}
/>
)}
{showUploadFile && (
<ChatAction
onClick={props.uploadFile}
@@ -607,6 +622,7 @@ export function ChatActions(props: {
</>
}
/>
<ChatAction
onClick={props.showPromptHints}
text={Locale.Chat.InputActions.Prompt}
@@ -620,13 +636,6 @@ export function ChatActions(props: {
text={Locale.Chat.InputActions.Masks}
icon={<MaskIcon />}
/>
<ChatAction
onClick={() => setShowModelSelector(true)}
text={currentModel}
icon={<RobotIcon />}
/>
{config.pluginConfig.enable &&
/^gpt(?!.*03\d{2}$).*$/.test(currentModel) &&
currentModel != "gpt-4-vision-preview" && (
@@ -641,21 +650,43 @@ export function ChatActions(props: {
/>
)}
<ChatAction
onClick={() => setShowModelSelector(true)}
text={currentModelName}
icon={<RobotIcon />}
/>
{showModelSelector && (
<Selector
defaultSelectedValue={currentModel}
defaultSelectedValue={`${currentModel}@${currentProviderName}`}
items={models.map((m) => ({
title: m.displayName,
value: m.name,
title: `${m.displayName}${
m?.provider?.providerName
? "(" + m?.provider?.providerName + ")"
: ""
}`,
value: `${m.name}@${m?.provider?.providerName}`,
}))}
onClose={() => setShowModelSelector(false)}
onSelection={(s) => {
if (s.length === 0) return;
const [model, providerName] = s[0].split("@");
chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.model = s[0] as ModelType;
session.mask.modelConfig.model = model as ModelType;
session.mask.modelConfig.providerName =
providerName as ServiceProvider;
session.mask.syncGlobalConfig = false;
});
showToast(s[0]);
if (providerName == "ByteDance") {
const selectedModel = models.find(
(m) =>
m.name == model &&
m?.provider?.providerName == providerName,
);
showToast(selectedModel?.displayName ?? "");
} else {
showToast(model);
}
}}
/>
)}
@@ -792,7 +823,7 @@ function _Chat() {
// prompt hints
const promptStore = usePromptStore();
const [promptHints, setPromptHints] = useState<RenderPompt[]>([]);
const [promptHints, setPromptHints] = useState<RenderPrompt[]>([]);
const onSearch = useDebouncedCallback(
(text: string) => {
const matchedPrompts = promptStore.search(text);
@@ -905,7 +936,7 @@ function _Chat() {
setAutoScroll(true);
};
const onPromptSelect = (prompt: RenderPompt) => {
const onPromptSelect = (prompt: RenderPrompt) => {
setTimeout(() => {
setPromptHints([]);
@@ -1319,7 +1350,7 @@ function _Chat() {
...(await new Promise<string[]>((res, rej) => {
setUploading(true);
const imagesData: string[] = [];
compressImage(file, 256 * 1024)
uploadImageRemote(file)
.then((dataUrl) => {
imagesData.push(dataUrl);
setUploading(false);
@@ -1361,7 +1392,7 @@ function _Chat() {
const imagesData: string[] = [];
for (let i = 0; i < files.length; i++) {
const file = event.target.files[i];
compressImage(file, 256 * 1024)
uploadImageRemote(file)
.then((dataUrl) => {
imagesData.push(dataUrl);
if (