validate conversaton configuation & handle preset loading in poor network (#624)

This commit is contained in:
an-lee
2024-05-21 15:48:20 +08:00
committed by GitHub
parent 8c4ba9f30d
commit 9f48a8f6bd
5 changed files with 54 additions and 21 deletions

View File

@@ -91,7 +91,11 @@
"ttsBaseUrlDescription": "leave it blank if you don't have one",
"notFound": "Conversation not found",
"contentRequired": "Content required",
"failedToGenerateResponse": "Failed to generate response, please retry"
"failedToGenerateResponse": "Failed to generate response, please retry",
"modelIsRequired": "Model is required",
"ttsConfigurationsIsRequired": "TTS configurations is required",
"ttsModelIsRequired": "TTS model is required",
"ttsEngineIsRequired": "TTS engine is required"
},
"pronunciationAssessment": {
"pronunciationScore": "Pronunciation Score",

View File

@@ -91,7 +91,11 @@
"ttsBaseUrlDescription": "留空则使用默认值",
"notFound": "未找到对话",
"contentRequired": "对话内容不能为空",
"failedToGenerateResponse": "生成失败,请重试"
"failedToGenerateResponse": "生成失败,请重试",
"modelIsRequired": "AI 模型不能为空",
"ttsConfigurationsIsRequired": "TTS 配置不能为空",
"ttsModelIsRequired": "TTS 模型不能为空",
"ttsEngineIsRequired": "TTS 引擎不能为空"
},
"pronunciationAssessment": {
"pronunciationScore": "发音得分",

View File

@@ -10,10 +10,12 @@ import {
HasMany,
DataType,
AllowNull,
BeforeSave,
} from "sequelize-typescript";
import { Message, Speech } from "@main/db/models";
import mainWindow from "@main/window";
import log from "@main/logger";
import { t } from "i18next";
const logger = log.scope("db/models/conversation");
@Table({
@@ -64,6 +66,22 @@ export class Conversation extends Model<Conversation> {
@HasMany(() => Message)
messages: Message[];
@BeforeSave
static validateConfiguration(conversation: Conversation) {
if (!conversation.model) throw new Error(t("models.conversation.modelIsRequired"));
if (conversation.type === 'tts') {
if (!conversation.configuration.tts) {
throw new Error(t("models.conversation.ttsConfigurationIsRequired"))
}
if (!conversation.configuration.tts.engine) {
throw new Error(t("models.conversation.ttsEngineIsRequired"))
}
if (!conversation.configuration.tts.model) {
throw new Error("models.conversation.ttsModelIsRequired")
}
}
}
@AfterCreate
static notifyForCreate(conversation: Conversation) {
this.notify(conversation, "create");

View File

@@ -74,8 +74,8 @@ export const ConversationForm = (props: {
}) => {
const { conversation, onFinish } = props;
const [submitting, setSubmitting] = useState<boolean>(false);
const [gptProviders, setGptProviders] = useState<any>([]);
const [ttsProviders, setTtsProviders] = useState<any>([]);
const [gptProviders, setGptProviders] = useState<any>(GPT_PROVIDERS);
const [ttsProviders, setTtsProviders] = useState<any>(TTS_PROVIDERS);
const { EnjoyApp, webApi } = useContext(AppSettingsProviderContext);
const { openai } = useContext(AISettingsProviderContext);
const navigate = useNavigate();
@@ -234,15 +234,6 @@ export const ConversationForm = (props: {
}
});
if (configuration.type === "tts") {
if (!configuration.tts?.engine) {
throw new Error(t("models.conversation.ttsEngineRequired"));
}
if (!configuration.tts?.model) {
throw new Error(t("models.conversation.ttsModelRequired"));
}
}
// use default base url if not set
if (!configuration.baseUrl) {
configuration.baseUrl = gptProviders[engine]?.baseUrl;

View File

@@ -11,7 +11,11 @@ import {
ScrollArea,
toast,
} from "@renderer/components/ui";
import { ConversationCard, ConversationForm } from "@renderer/components";
import {
ConversationCard,
ConversationForm,
LoaderSpin,
} from "@renderer/components";
import { useState, useEffect, useContext, useReducer } from "react";
import { ChevronLeftIcon, LoaderIcon } from "lucide-react";
import { Link, useNavigate, useSearchParams } from "react-router-dom";
@@ -25,13 +29,6 @@ import { CONVERSATION_PRESETS } from "@/constants";
export default () => {
const [searchParams] = useSearchParams();
const [creating, setCreating] = useState<boolean>(false);
const [preset, setPreset] = useState<any>({});
const [config, setConfig] = useState<any>({
gptPresets: [],
customPreset: {},
ttsPreset: {},
});
const { addDblistener, removeDbListener } = useContext(DbProviderContext);
const { EnjoyApp, webApi } = useContext(AppSettingsProviderContext);
const { currentEngine } = useContext(AISettingsProviderContext);
@@ -39,6 +36,23 @@ export default () => {
conversationsReducer,
[]
);
const [creating, setCreating] = useState<boolean>(false);
const [preset, setPreset] = useState<any>({});
const [config, setConfig] = useState<any>({
gptPresets: [],
customPreset: {},
ttsPreset: {
key: "tts",
name: "TTS",
engine: currentEngine.name,
configuration: {
type: "tts",
tts: {
engine: currentEngine.name,
},
},
},
});
const [hasMore, setHasMore] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const navigate = useNavigate();
@@ -218,6 +232,8 @@ export default () => {
{t("chooseFromPresetGpts")}
</div>
<ScrollArea className="h-64 pr-4">
{config.gptPresets.length === 0 && <LoaderSpin />}
{config.gptPresets.map((preset: any) => (
<DialogTrigger
key={preset.key}