Merge branch 'main' of https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web
This commit is contained in:
commit
ca3c801046
|
@ -43,6 +43,7 @@ import QualityIcon from "../icons/hd.svg";
|
||||||
import StyleIcon from "../icons/palette.svg";
|
import StyleIcon from "../icons/palette.svg";
|
||||||
import PluginIcon from "../icons/plugin.svg";
|
import PluginIcon from "../icons/plugin.svg";
|
||||||
import ShortcutkeyIcon from "../icons/shortcutkey.svg";
|
import ShortcutkeyIcon from "../icons/shortcutkey.svg";
|
||||||
|
import ReloadIcon from "../icons/reload.svg";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
|
@ -624,7 +625,7 @@ export function ChatActions(props: {
|
||||||
items={models.map((m) => ({
|
items={models.map((m) => ({
|
||||||
title: `${m.displayName}${
|
title: `${m.displayName}${
|
||||||
m?.provider?.providerName
|
m?.provider?.providerName
|
||||||
? "(" + m?.provider?.providerName + ")"
|
? " (" + m?.provider?.providerName + ")"
|
||||||
: ""
|
: ""
|
||||||
}`,
|
}`,
|
||||||
value: `${m.name}@${m?.provider?.providerName}`,
|
value: `${m.name}@${m?.provider?.providerName}`,
|
||||||
|
@ -1541,6 +1542,17 @@ function _Chat() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="window-actions">
|
<div className="window-actions">
|
||||||
|
<div className="window-action-button">
|
||||||
|
<IconButton
|
||||||
|
icon={<ReloadIcon />}
|
||||||
|
bordered
|
||||||
|
title={Locale.Chat.Actions.RefreshTitle}
|
||||||
|
onClick={() => {
|
||||||
|
showToast(Locale.Chat.Actions.RefreshToast);
|
||||||
|
chatStore.summarizeSession(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{!isMobileScreen && (
|
{!isMobileScreen && (
|
||||||
<div className="window-action-button">
|
<div className="window-action-button">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -5,13 +5,19 @@ import Locale from "../locales";
|
||||||
import { InputRange } from "./input-range";
|
import { InputRange } from "./input-range";
|
||||||
import { ListItem, Select } from "./ui-lib";
|
import { ListItem, Select } from "./ui-lib";
|
||||||
import { useAllModels } from "../utils/hooks";
|
import { useAllModels } from "../utils/hooks";
|
||||||
|
import { groupBy } from "lodash-es";
|
||||||
|
|
||||||
export function ModelConfigList(props: {
|
export function ModelConfigList(props: {
|
||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
||||||
}) {
|
}) {
|
||||||
const allModels = useAllModels();
|
const allModels = useAllModels();
|
||||||
|
const groupModels = groupBy(
|
||||||
|
allModels.filter((v) => v.available),
|
||||||
|
"provider.providerName",
|
||||||
|
);
|
||||||
const value = `${props.modelConfig.model}@${props.modelConfig?.providerName}`;
|
const value = `${props.modelConfig.model}@${props.modelConfig?.providerName}`;
|
||||||
|
const compressModelValue = `${props.modelConfig.compressModel}@${props.modelConfig?.compressProviderName}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -19,6 +25,7 @@ export function ModelConfigList(props: {
|
||||||
<Select
|
<Select
|
||||||
aria-label={Locale.Settings.Model}
|
aria-label={Locale.Settings.Model}
|
||||||
value={value}
|
value={value}
|
||||||
|
align="left"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const [model, providerName] = e.currentTarget.value.split("@");
|
const [model, providerName] = e.currentTarget.value.split("@");
|
||||||
props.updateConfig((config) => {
|
props.updateConfig((config) => {
|
||||||
|
@ -27,13 +34,15 @@ export function ModelConfigList(props: {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{allModels
|
{Object.keys(groupModels).map((providerName, index) => (
|
||||||
.filter((v) => v.available)
|
<optgroup label={providerName} key={index}>
|
||||||
.map((v, i) => (
|
{groupModels[providerName].map((v, i) => (
|
||||||
<option value={`${v.name}@${v.provider?.providerName}`} key={i}>
|
<option value={`${v.name}@${v.provider?.providerName}`} key={i}>
|
||||||
{v.displayName}({v.provider?.providerName})
|
{v.displayName}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
</optgroup>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
|
@ -228,6 +237,30 @@ export function ModelConfigList(props: {
|
||||||
}
|
}
|
||||||
></input>
|
></input>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Settings.CompressModel.Title}
|
||||||
|
subTitle={Locale.Settings.CompressModel.SubTitle}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
aria-label={Locale.Settings.CompressModel.Title}
|
||||||
|
value={compressModelValue}
|
||||||
|
onChange={(e) => {
|
||||||
|
const [model, providerName] = e.currentTarget.value.split("@");
|
||||||
|
props.updateConfig((config) => {
|
||||||
|
config.compressModel = ModalConfigValidator.model(model);
|
||||||
|
config.compressProviderName = providerName as ServiceProvider;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{allModels
|
||||||
|
.filter((v) => v.available)
|
||||||
|
.map((v, i) => (
|
||||||
|
<option value={`${v.name}@${v.provider?.providerName}`} key={i}>
|
||||||
|
{v.displayName}({v.provider?.providerName})
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</ListItem>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,12 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
|
|
||||||
|
&.left-align-option {
|
||||||
|
option {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.select-with-icon-select {
|
.select-with-icon-select {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
|
|
|
@ -292,13 +292,19 @@ export function PasswordInput(
|
||||||
|
|
||||||
export function Select(
|
export function Select(
|
||||||
props: React.DetailedHTMLProps<
|
props: React.DetailedHTMLProps<
|
||||||
React.SelectHTMLAttributes<HTMLSelectElement>,
|
React.SelectHTMLAttributes<HTMLSelectElement> & {
|
||||||
|
align?: "left" | "center";
|
||||||
|
},
|
||||||
HTMLSelectElement
|
HTMLSelectElement
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
const { className, children, ...otherProps } = props;
|
const { className, children, align, ...otherProps } = props;
|
||||||
return (
|
return (
|
||||||
<div className={`${styles["select-with-icon"]} ${className}`}>
|
<div
|
||||||
|
className={`${styles["select-with-icon"]} ${
|
||||||
|
align === "left" ? styles["left-align-option"] : ""
|
||||||
|
} ${className}`}
|
||||||
|
>
|
||||||
<select className={styles["select-with-icon-select"]} {...otherProps}>
|
<select className={styles["select-with-icon-select"]} {...otherProps}>
|
||||||
{children}
|
{children}
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -43,6 +43,8 @@ const ar: PartialLocaleType = {
|
||||||
PinToastAction: "عرض",
|
PinToastAction: "عرض",
|
||||||
Delete: "حذف",
|
Delete: "حذف",
|
||||||
Edit: "تحرير",
|
Edit: "تحرير",
|
||||||
|
RefreshTitle: "تحديث العنوان",
|
||||||
|
RefreshToast: "تم إرسال طلب تحديث العنوان",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "دردشة جديدة",
|
new: "دردشة جديدة",
|
||||||
|
@ -404,6 +406,10 @@ const ar: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "النموذج",
|
Model: "النموذج",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "نموذج الضغط",
|
||||||
|
SubTitle: "النموذج المستخدم لضغط السجل التاريخي",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "العشوائية (temperature)",
|
Title: "العشوائية (temperature)",
|
||||||
SubTitle: "كلما زادت القيمة، زادت العشوائية في الردود",
|
SubTitle: "كلما زادت القيمة، زادت العشوائية في الردود",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const bn: PartialLocaleType = {
|
||||||
PinToastAction: "দেখুন",
|
PinToastAction: "দেখুন",
|
||||||
Delete: "মুছে ফেলুন",
|
Delete: "মুছে ফেলুন",
|
||||||
Edit: "সম্পাদনা করুন",
|
Edit: "সম্পাদনা করুন",
|
||||||
|
RefreshTitle: "শিরোনাম রিফ্রেশ করুন",
|
||||||
|
RefreshToast: "শিরোনাম রিফ্রেশ অনুরোধ পাঠানো হয়েছে",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "নতুন চ্যাট",
|
new: "নতুন চ্যাট",
|
||||||
|
@ -411,6 +413,10 @@ const bn: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "মডেল (model)",
|
Model: "মডেল (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "সংকোচন মডেল",
|
||||||
|
SubTitle: "ইতিহাস সংকুচিত করার জন্য ব্যবহৃত মডেল",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "যাদুকরিতা (temperature)",
|
Title: "যাদুকরিতা (temperature)",
|
||||||
SubTitle: "মান বাড়ালে উত্তর বেশি এলোমেলো হবে",
|
SubTitle: "মান বাড়ালে উত্তর বেশি এলোমেলো হবে",
|
||||||
|
|
|
@ -44,6 +44,8 @@ const cn = {
|
||||||
Delete: "删除",
|
Delete: "删除",
|
||||||
Edit: "编辑",
|
Edit: "编辑",
|
||||||
FullScreen: "全屏",
|
FullScreen: "全屏",
|
||||||
|
RefreshTitle: "刷新标题",
|
||||||
|
RefreshToast: "已发送刷新标题请求",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "新建聊天",
|
new: "新建聊天",
|
||||||
|
@ -470,6 +472,10 @@ const cn = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "模型 (model)",
|
Model: "模型 (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "压缩模型",
|
||||||
|
SubTitle: "用于压缩历史记录的模型",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "随机性 (temperature)",
|
Title: "随机性 (temperature)",
|
||||||
SubTitle: "值越大,回复越随机",
|
SubTitle: "值越大,回复越随机",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const cs: PartialLocaleType = {
|
||||||
PinToastAction: "Zobrazit",
|
PinToastAction: "Zobrazit",
|
||||||
Delete: "Smazat",
|
Delete: "Smazat",
|
||||||
Edit: "Upravit",
|
Edit: "Upravit",
|
||||||
|
RefreshTitle: "Obnovit název",
|
||||||
|
RefreshToast: "Požadavek na obnovení názvu byl odeslán",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Nová konverzace",
|
new: "Nová konverzace",
|
||||||
|
@ -410,6 +412,10 @@ const cs: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Model (model)",
|
Model: "Model (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Kompresní model",
|
||||||
|
SubTitle: "Model používaný pro kompresi historie",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Náhodnost (temperature)",
|
Title: "Náhodnost (temperature)",
|
||||||
SubTitle: "Čím vyšší hodnota, tím náhodnější odpovědi",
|
SubTitle: "Čím vyšší hodnota, tím náhodnější odpovědi",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const de: PartialLocaleType = {
|
||||||
PinToastAction: "Ansehen",
|
PinToastAction: "Ansehen",
|
||||||
Delete: "Löschen",
|
Delete: "Löschen",
|
||||||
Edit: "Bearbeiten",
|
Edit: "Bearbeiten",
|
||||||
|
RefreshTitle: "Titel aktualisieren",
|
||||||
|
RefreshToast: "Anfrage zur Titelaktualisierung gesendet",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Neues Gespräch",
|
new: "Neues Gespräch",
|
||||||
|
@ -421,6 +423,10 @@ const de: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modell",
|
Model: "Modell",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Kompressionsmodell",
|
||||||
|
SubTitle: "Modell zur Komprimierung des Verlaufs",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Zufälligkeit (temperature)",
|
Title: "Zufälligkeit (temperature)",
|
||||||
SubTitle: "Je höher der Wert, desto zufälliger die Antwort",
|
SubTitle: "Je höher der Wert, desto zufälliger die Antwort",
|
||||||
|
|
|
@ -45,6 +45,8 @@ const en: LocaleType = {
|
||||||
Delete: "Delete",
|
Delete: "Delete",
|
||||||
Edit: "Edit",
|
Edit: "Edit",
|
||||||
FullScreen: "FullScreen",
|
FullScreen: "FullScreen",
|
||||||
|
RefreshTitle: "Refresh Title",
|
||||||
|
RefreshToast: "Title refresh request sent",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Start a new chat",
|
new: "Start a new chat",
|
||||||
|
@ -474,6 +476,10 @@ const en: LocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Model",
|
Model: "Model",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Compression Model",
|
||||||
|
SubTitle: "Model used to compress history",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Temperature",
|
Title: "Temperature",
|
||||||
SubTitle: "A larger value makes the more random output",
|
SubTitle: "A larger value makes the more random output",
|
||||||
|
|
|
@ -44,6 +44,8 @@ const es: PartialLocaleType = {
|
||||||
PinToastAction: "Ver",
|
PinToastAction: "Ver",
|
||||||
Delete: "Eliminar",
|
Delete: "Eliminar",
|
||||||
Edit: "Editar",
|
Edit: "Editar",
|
||||||
|
RefreshTitle: "Actualizar título",
|
||||||
|
RefreshToast: "Se ha enviado la solicitud de actualización del título",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Nueva conversación",
|
new: "Nueva conversación",
|
||||||
|
@ -423,6 +425,10 @@ const es: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modelo (model)",
|
Model: "Modelo (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Modelo de compresión",
|
||||||
|
SubTitle: "Modelo utilizado para comprimir el historial",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Aleatoriedad (temperature)",
|
Title: "Aleatoriedad (temperature)",
|
||||||
SubTitle: "Cuanto mayor sea el valor, más aleatorio será el resultado",
|
SubTitle: "Cuanto mayor sea el valor, más aleatorio será el resultado",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const fr: PartialLocaleType = {
|
||||||
PinToastAction: "Voir",
|
PinToastAction: "Voir",
|
||||||
Delete: "Supprimer",
|
Delete: "Supprimer",
|
||||||
Edit: "Modifier",
|
Edit: "Modifier",
|
||||||
|
RefreshTitle: "Actualiser le titre",
|
||||||
|
RefreshToast: "Demande d'actualisation du titre envoyée",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Nouvelle discussion",
|
new: "Nouvelle discussion",
|
||||||
|
@ -422,6 +424,10 @@ const fr: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modèle",
|
Model: "Modèle",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Modèle de compression",
|
||||||
|
SubTitle: "Modèle utilisé pour compresser l'historique",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Aléatoire (temperature)",
|
Title: "Aléatoire (temperature)",
|
||||||
SubTitle: "Plus la valeur est élevée, plus les réponses sont aléatoires",
|
SubTitle: "Plus la valeur est élevée, plus les réponses sont aléatoires",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const id: PartialLocaleType = {
|
||||||
PinToastAction: "Lihat",
|
PinToastAction: "Lihat",
|
||||||
Delete: "Hapus",
|
Delete: "Hapus",
|
||||||
Edit: "Edit",
|
Edit: "Edit",
|
||||||
|
RefreshTitle: "Segarkan Judul",
|
||||||
|
RefreshToast: "Permintaan penyegaran judul telah dikirim",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Obrolan Baru",
|
new: "Obrolan Baru",
|
||||||
|
@ -411,6 +413,10 @@ const id: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Model",
|
Model: "Model",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Model Kompresi",
|
||||||
|
SubTitle: "Model yang digunakan untuk mengompres riwayat",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Randomness (temperature)",
|
Title: "Randomness (temperature)",
|
||||||
SubTitle: "Semakin tinggi nilainya, semakin acak responsnya",
|
SubTitle: "Semakin tinggi nilainya, semakin acak responsnya",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const it: PartialLocaleType = {
|
||||||
PinToastAction: "Visualizza",
|
PinToastAction: "Visualizza",
|
||||||
Delete: "Elimina",
|
Delete: "Elimina",
|
||||||
Edit: "Modifica",
|
Edit: "Modifica",
|
||||||
|
RefreshTitle: "Aggiorna titolo",
|
||||||
|
RefreshToast: "Richiesta di aggiornamento del titolo inviata",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Nuova chat",
|
new: "Nuova chat",
|
||||||
|
@ -423,6 +425,10 @@ const it: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modello (model)",
|
Model: "Modello (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Modello di compressione",
|
||||||
|
SubTitle: "Modello utilizzato per comprimere la cronologia",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Casualità (temperature)",
|
Title: "Casualità (temperature)",
|
||||||
SubTitle: "Valore più alto, risposte più casuali",
|
SubTitle: "Valore più alto, risposte più casuali",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const jp: PartialLocaleType = {
|
||||||
PinToastAction: "見る",
|
PinToastAction: "見る",
|
||||||
Delete: "削除",
|
Delete: "削除",
|
||||||
Edit: "編集",
|
Edit: "編集",
|
||||||
|
RefreshTitle: "タイトルを更新",
|
||||||
|
RefreshToast: "タイトル更新リクエストが送信されました",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "新しいチャット",
|
new: "新しいチャット",
|
||||||
|
@ -407,6 +409,10 @@ const jp: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "モデル (model)",
|
Model: "モデル (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "圧縮モデル",
|
||||||
|
SubTitle: "履歴を圧縮するために使用されるモデル",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "ランダム性 (temperature)",
|
Title: "ランダム性 (temperature)",
|
||||||
SubTitle: "値が大きいほど応答がランダムになります",
|
SubTitle: "値が大きいほど応答がランダムになります",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const ko: PartialLocaleType = {
|
||||||
PinToastAction: "보기",
|
PinToastAction: "보기",
|
||||||
Delete: "삭제",
|
Delete: "삭제",
|
||||||
Edit: "편집",
|
Edit: "편집",
|
||||||
|
RefreshTitle: "제목 새로고침",
|
||||||
|
RefreshToast: "제목 새로고침 요청이 전송되었습니다",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "새 채팅",
|
new: "새 채팅",
|
||||||
|
@ -404,6 +406,10 @@ const ko: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "모델 (model)",
|
Model: "모델 (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "압축 모델",
|
||||||
|
SubTitle: "기록을 압축하는 데 사용되는 모델",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "무작위성 (temperature)",
|
Title: "무작위성 (temperature)",
|
||||||
SubTitle: "값이 클수록 응답이 더 무작위적",
|
SubTitle: "값이 클수록 응답이 더 무작위적",
|
||||||
|
|
|
@ -44,6 +44,8 @@ const no: PartialLocaleType = {
|
||||||
PinToastAction: "Se",
|
PinToastAction: "Se",
|
||||||
Delete: "Slett",
|
Delete: "Slett",
|
||||||
Edit: "Rediger",
|
Edit: "Rediger",
|
||||||
|
RefreshTitle: "Oppdater tittel",
|
||||||
|
RefreshToast: "Forespørsel om titteloppdatering sendt",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Ny samtale",
|
new: "Ny samtale",
|
||||||
|
@ -415,6 +417,10 @@ const no: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modell",
|
Model: "Modell",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Komprimeringsmodell",
|
||||||
|
SubTitle: "Modell brukt for å komprimere historikken",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Tilfeldighet (temperature)",
|
Title: "Tilfeldighet (temperature)",
|
||||||
SubTitle: "Høyere verdi gir mer tilfeldige svar",
|
SubTitle: "Høyere verdi gir mer tilfeldige svar",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const pt: PartialLocaleType = {
|
||||||
PinToastAction: "Visualizar",
|
PinToastAction: "Visualizar",
|
||||||
Delete: "Deletar",
|
Delete: "Deletar",
|
||||||
Edit: "Editar",
|
Edit: "Editar",
|
||||||
|
RefreshTitle: "Atualizar Título",
|
||||||
|
RefreshToast: "Solicitação de atualização de título enviada",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Iniciar um novo chat",
|
new: "Iniciar um novo chat",
|
||||||
|
@ -346,6 +348,10 @@ const pt: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Modelo",
|
Model: "Modelo",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Modelo de Compressão",
|
||||||
|
SubTitle: "Modelo usado para comprimir o histórico",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Temperatura",
|
Title: "Temperatura",
|
||||||
SubTitle: "Um valor maior torna a saída mais aleatória",
|
SubTitle: "Um valor maior torna a saída mais aleatória",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const ru: PartialLocaleType = {
|
||||||
PinToastAction: "Просмотреть",
|
PinToastAction: "Просмотреть",
|
||||||
Delete: "Удалить",
|
Delete: "Удалить",
|
||||||
Edit: "Редактировать",
|
Edit: "Редактировать",
|
||||||
|
RefreshTitle: "Обновить заголовок",
|
||||||
|
RefreshToast: "Запрос на обновление заголовка отправлен",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Новый чат",
|
new: "Новый чат",
|
||||||
|
@ -414,6 +416,10 @@ const ru: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Модель",
|
Model: "Модель",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Модель сжатия",
|
||||||
|
SubTitle: "Модель, используемая для сжатия истории",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Случайность (temperature)",
|
Title: "Случайность (temperature)",
|
||||||
SubTitle: "Чем больше значение, тем более случайные ответы",
|
SubTitle: "Чем больше значение, тем более случайные ответы",
|
||||||
|
|
|
@ -45,6 +45,8 @@ const sk: PartialLocaleType = {
|
||||||
PinToastAction: "Zobraziť",
|
PinToastAction: "Zobraziť",
|
||||||
Delete: "Vymazať",
|
Delete: "Vymazať",
|
||||||
Edit: "Upraviť",
|
Edit: "Upraviť",
|
||||||
|
RefreshTitle: "Obnoviť názov",
|
||||||
|
RefreshToast: "Požiadavka na obnovenie názvu bola odoslaná",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Začať nový chat",
|
new: "Začať nový chat",
|
||||||
|
@ -365,6 +367,10 @@ const sk: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Model",
|
Model: "Model",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Kompresný model",
|
||||||
|
SubTitle: "Model používaný na kompresiu histórie",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Teplota",
|
Title: "Teplota",
|
||||||
SubTitle: "Vyššia hodnota robí výstup náhodnejším",
|
SubTitle: "Vyššia hodnota robí výstup náhodnejším",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const tr: PartialLocaleType = {
|
||||||
PinToastAction: "Görünüm",
|
PinToastAction: "Görünüm",
|
||||||
Delete: "Sil",
|
Delete: "Sil",
|
||||||
Edit: "Düzenle",
|
Edit: "Düzenle",
|
||||||
|
RefreshTitle: "Başlığı Yenile",
|
||||||
|
RefreshToast: "Başlık yenileme isteği gönderildi",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Yeni sohbet",
|
new: "Yeni sohbet",
|
||||||
|
@ -414,6 +416,10 @@ const tr: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Model (model)",
|
Model: "Model (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Sıkıştırma Modeli",
|
||||||
|
SubTitle: "Geçmişi sıkıştırmak için kullanılan model",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Rastgelelik (temperature)",
|
Title: "Rastgelelik (temperature)",
|
||||||
SubTitle: "Değer arttıkça yanıt daha rastgele olur",
|
SubTitle: "Değer arttıkça yanıt daha rastgele olur",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const tw = {
|
||||||
PinToastAction: "檢視",
|
PinToastAction: "檢視",
|
||||||
Delete: "刪除",
|
Delete: "刪除",
|
||||||
Edit: "編輯",
|
Edit: "編輯",
|
||||||
|
RefreshTitle: "刷新標題",
|
||||||
|
RefreshToast: "已發送刷新標題請求",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "新建聊天",
|
new: "新建聊天",
|
||||||
|
@ -368,6 +370,10 @@ const tw = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "模型 (model)",
|
Model: "模型 (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "壓縮模型",
|
||||||
|
SubTitle: "用於壓縮歷史記錄的模型",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "隨機性 (temperature)",
|
Title: "隨機性 (temperature)",
|
||||||
SubTitle: "值越大,回應越隨機",
|
SubTitle: "值越大,回應越隨機",
|
||||||
|
|
|
@ -43,6 +43,8 @@ const vi: PartialLocaleType = {
|
||||||
PinToastAction: "Xem",
|
PinToastAction: "Xem",
|
||||||
Delete: "Xóa",
|
Delete: "Xóa",
|
||||||
Edit: "Chỉnh sửa",
|
Edit: "Chỉnh sửa",
|
||||||
|
RefreshTitle: "Làm mới tiêu đề",
|
||||||
|
RefreshToast: "Đã gửi yêu cầu làm mới tiêu đề",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Tạo cuộc trò chuyện mới",
|
new: "Tạo cuộc trò chuyện mới",
|
||||||
|
@ -410,6 +412,10 @@ const vi: PartialLocaleType = {
|
||||||
},
|
},
|
||||||
|
|
||||||
Model: "Mô hình (model)",
|
Model: "Mô hình (model)",
|
||||||
|
CompressModel: {
|
||||||
|
Title: "Mô hình nén",
|
||||||
|
SubTitle: "Mô hình được sử dụng để nén lịch sử",
|
||||||
|
},
|
||||||
Temperature: {
|
Temperature: {
|
||||||
Title: "Độ ngẫu nhiên (temperature)",
|
Title: "Độ ngẫu nhiên (temperature)",
|
||||||
SubTitle: "Giá trị càng lớn, câu trả lời càng ngẫu nhiên",
|
SubTitle: "Giá trị càng lớn, câu trả lời càng ngẫu nhiên",
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
import { trimTopic, getMessageTextContent } from "../utils";
|
import { getMessageTextContent, trimTopic } from "../utils";
|
||||||
|
|
||||||
import Locale, { getLang } from "../locales";
|
import { indexedDBStorage } from "@/app/utils/indexedDB-storage";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
import type {
|
||||||
|
ClientApi,
|
||||||
|
MultimodalContent,
|
||||||
|
RequestMessage,
|
||||||
|
} from "../client/api";
|
||||||
|
import { getClientApi } from "../client/api";
|
||||||
|
import { ChatControllerPool } from "../client/controller";
|
||||||
import { showToast } from "../components/ui-lib";
|
import { showToast } from "../components/ui-lib";
|
||||||
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
|
||||||
import { createEmptyMask, Mask } from "./mask";
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_INPUT_TEMPLATE,
|
DEFAULT_INPUT_TEMPLATE,
|
||||||
DEFAULT_MODELS,
|
DEFAULT_MODELS,
|
||||||
DEFAULT_SYSTEM_TEMPLATE,
|
DEFAULT_SYSTEM_TEMPLATE,
|
||||||
KnowledgeCutOffDate,
|
KnowledgeCutOffDate,
|
||||||
StoreKey,
|
StoreKey,
|
||||||
SUMMARIZE_MODEL,
|
|
||||||
GEMINI_SUMMARIZE_MODEL,
|
|
||||||
} from "../constant";
|
} from "../constant";
|
||||||
import { getClientApi } from "../client/api";
|
import Locale, { getLang } from "../locales";
|
||||||
import type {
|
|
||||||
ClientApi,
|
|
||||||
RequestMessage,
|
|
||||||
MultimodalContent,
|
|
||||||
} from "../client/api";
|
|
||||||
import { ChatControllerPool } from "../client/controller";
|
|
||||||
import { prettyObject } from "../utils/format";
|
|
||||||
import { estimateTokenLength } from "../utils/token";
|
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
import { createPersistStore } from "../utils/store";
|
|
||||||
import { collectModelsWithDefaultModel } from "../utils/model";
|
|
||||||
import { useAccessStore } from "./access";
|
|
||||||
import { isDalle3, safeLocalStorage } from "../utils";
|
import { isDalle3, safeLocalStorage } from "../utils";
|
||||||
import { indexedDBStorage } from "@/app/utils/indexedDB-storage";
|
import { prettyObject } from "../utils/format";
|
||||||
|
import { createPersistStore } from "../utils/store";
|
||||||
|
import { estimateTokenLength } from "../utils/token";
|
||||||
|
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
||||||
|
import { createEmptyMask, Mask } from "./mask";
|
||||||
|
|
||||||
const localStorage = safeLocalStorage();
|
const localStorage = safeLocalStorage();
|
||||||
|
|
||||||
|
@ -106,27 +102,6 @@ function createEmptySession(): ChatSession {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSummarizeModel(currentModel: string) {
|
|
||||||
// if it is using gpt-* models, force to use 4o-mini to summarize
|
|
||||||
if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) {
|
|
||||||
const configStore = useAppConfig.getState();
|
|
||||||
const accessStore = useAccessStore.getState();
|
|
||||||
const allModel = collectModelsWithDefaultModel(
|
|
||||||
configStore.models,
|
|
||||||
[configStore.customModels, accessStore.customModels].join(","),
|
|
||||||
accessStore.defaultModel,
|
|
||||||
);
|
|
||||||
const summarizeModel = allModel.find(
|
|
||||||
(m) => m.name === SUMMARIZE_MODEL && m.available,
|
|
||||||
);
|
|
||||||
return summarizeModel?.name ?? currentModel;
|
|
||||||
}
|
|
||||||
if (currentModel.startsWith("gemini")) {
|
|
||||||
return GEMINI_SUMMARIZE_MODEL;
|
|
||||||
}
|
|
||||||
return currentModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
function countMessages(msgs: ChatMessage[]) {
|
function countMessages(msgs: ChatMessage[]) {
|
||||||
return msgs.reduce(
|
return msgs.reduce(
|
||||||
(pre, cur) => pre + estimateTokenLength(getMessageTextContent(cur)),
|
(pre, cur) => pre + estimateTokenLength(getMessageTextContent(cur)),
|
||||||
|
@ -572,7 +547,7 @@ export const useChatStore = createPersistStore(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
summarizeSession() {
|
summarizeSession(refreshTitle: boolean = false) {
|
||||||
const config = useAppConfig.getState();
|
const config = useAppConfig.getState();
|
||||||
const session = get().currentSession();
|
const session = get().currentSession();
|
||||||
const modelConfig = session.mask.modelConfig;
|
const modelConfig = session.mask.modelConfig;
|
||||||
|
@ -581,7 +556,7 @@ export const useChatStore = createPersistStore(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerName = modelConfig.providerName;
|
const providerName = modelConfig.compressProviderName;
|
||||||
const api: ClientApi = getClientApi(providerName);
|
const api: ClientApi = getClientApi(providerName);
|
||||||
|
|
||||||
// remove error messages if any
|
// remove error messages if any
|
||||||
|
@ -590,20 +565,30 @@ export const useChatStore = createPersistStore(
|
||||||
// should summarize topic after chating more than 50 words
|
// should summarize topic after chating more than 50 words
|
||||||
const SUMMARIZE_MIN_LEN = 50;
|
const SUMMARIZE_MIN_LEN = 50;
|
||||||
if (
|
if (
|
||||||
config.enableAutoGenerateTitle &&
|
(config.enableAutoGenerateTitle &&
|
||||||
session.topic === DEFAULT_TOPIC &&
|
session.topic === DEFAULT_TOPIC &&
|
||||||
countMessages(messages) >= SUMMARIZE_MIN_LEN
|
countMessages(messages) >= SUMMARIZE_MIN_LEN) ||
|
||||||
|
refreshTitle
|
||||||
) {
|
) {
|
||||||
const topicMessages = messages.concat(
|
const startIndex = Math.max(
|
||||||
createMessage({
|
0,
|
||||||
role: "user",
|
messages.length - modelConfig.historyMessageCount,
|
||||||
content: Locale.Store.Prompt.Topic,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
const topicMessages = messages
|
||||||
|
.slice(
|
||||||
|
startIndex < messages.length ? startIndex : messages.length - 1,
|
||||||
|
messages.length,
|
||||||
|
)
|
||||||
|
.concat(
|
||||||
|
createMessage({
|
||||||
|
role: "user",
|
||||||
|
content: Locale.Store.Prompt.Topic,
|
||||||
|
}),
|
||||||
|
);
|
||||||
api.llm.chat({
|
api.llm.chat({
|
||||||
messages: topicMessages,
|
messages: topicMessages,
|
||||||
config: {
|
config: {
|
||||||
model: getSummarizeModel(session.mask.modelConfig.model),
|
model: modelConfig.compressModel,
|
||||||
stream: false,
|
stream: false,
|
||||||
providerName,
|
providerName,
|
||||||
},
|
},
|
||||||
|
@ -666,7 +651,7 @@ export const useChatStore = createPersistStore(
|
||||||
config: {
|
config: {
|
||||||
...modelcfg,
|
...modelcfg,
|
||||||
stream: true,
|
stream: true,
|
||||||
model: getSummarizeModel(session.mask.modelConfig.model),
|
model: modelConfig.compressModel,
|
||||||
},
|
},
|
||||||
onUpdate(message) {
|
onUpdate(message) {
|
||||||
session.memoryPrompt = message;
|
session.memoryPrompt = message;
|
||||||
|
@ -715,7 +700,7 @@ export const useChatStore = createPersistStore(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: StoreKey.Chat,
|
name: StoreKey.Chat,
|
||||||
version: 3.1,
|
version: 3.2,
|
||||||
migrate(persistedState, version) {
|
migrate(persistedState, version) {
|
||||||
const state = persistedState as any;
|
const state = persistedState as any;
|
||||||
const newState = JSON.parse(
|
const newState = JSON.parse(
|
||||||
|
@ -762,6 +747,16 @@ export const useChatStore = createPersistStore(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add default summarize model for every session
|
||||||
|
if (version < 3.2) {
|
||||||
|
newState.sessions.forEach((s) => {
|
||||||
|
const config = useAppConfig.getState();
|
||||||
|
s.mask.modelConfig.compressModel = config.modelConfig.compressModel;
|
||||||
|
s.mask.modelConfig.compressProviderName =
|
||||||
|
config.modelConfig.compressProviderName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return newState as any;
|
return newState as any;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,7 +50,7 @@ export const DEFAULT_CONFIG = {
|
||||||
models: DEFAULT_MODELS as any as LLMModel[],
|
models: DEFAULT_MODELS as any as LLMModel[],
|
||||||
|
|
||||||
modelConfig: {
|
modelConfig: {
|
||||||
model: "gpt-3.5-turbo" as ModelType,
|
model: "gpt-4o-mini" as ModelType,
|
||||||
providerName: "OpenAI" as ServiceProvider,
|
providerName: "OpenAI" as ServiceProvider,
|
||||||
temperature: 0.5,
|
temperature: 0.5,
|
||||||
top_p: 1,
|
top_p: 1,
|
||||||
|
@ -60,6 +60,8 @@ export const DEFAULT_CONFIG = {
|
||||||
sendMemory: true,
|
sendMemory: true,
|
||||||
historyMessageCount: 4,
|
historyMessageCount: 4,
|
||||||
compressMessageLengthThreshold: 1000,
|
compressMessageLengthThreshold: 1000,
|
||||||
|
compressModel: "gpt-4o-mini" as ModelType,
|
||||||
|
compressProviderName: "OpenAI" as ServiceProvider,
|
||||||
enableInjectSystemPrompts: true,
|
enableInjectSystemPrompts: true,
|
||||||
template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
|
template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
|
||||||
size: "1024x1024" as DalleSize,
|
size: "1024x1024" as DalleSize,
|
||||||
|
@ -140,7 +142,7 @@ export const useAppConfig = createPersistStore(
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: StoreKey.Config,
|
name: StoreKey.Config,
|
||||||
version: 3.9,
|
version: 4,
|
||||||
migrate(persistedState, version) {
|
migrate(persistedState, version) {
|
||||||
const state = persistedState as ChatConfig;
|
const state = persistedState as ChatConfig;
|
||||||
|
|
||||||
|
@ -178,6 +180,13 @@ export const useAppConfig = createPersistStore(
|
||||||
: config?.template ?? DEFAULT_INPUT_TEMPLATE;
|
: config?.template ?? DEFAULT_INPUT_TEMPLATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version < 4) {
|
||||||
|
state.modelConfig.compressModel =
|
||||||
|
DEFAULT_CONFIG.modelConfig.compressModel;
|
||||||
|
state.modelConfig.compressProviderName =
|
||||||
|
DEFAULT_CONFIG.modelConfig.compressProviderName;
|
||||||
|
}
|
||||||
|
|
||||||
return state as any;
|
return state as any;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue