Merge pull request #91 from an-lee/main

Fix bugs & improve
This commit is contained in:
an-lee
2024-01-11 11:13:01 +08:00
committed by GitHub
10 changed files with 63 additions and 4 deletions

View File

@@ -21,6 +21,7 @@
"added": "Successfully added audio",
"removed": "Successfully removed audio",
"notFound": "Video not found",
"fileTooLarge": "File too large {{ file }}",
"failedToAdd": "Failed to add audio, {{ error }}",
"fileNotFound": "File not found {{file}}",
"fileNotSupported": "File not supported {{file}}",
@@ -45,6 +46,7 @@
"added": "Successfully added video",
"removed": "Successfully removed video",
"notFound": "Video not found",
"fileTooLarge": "File too large {{ file }}",
"failedToAdd": "Failed to add video, {{ error }}",
"fileNotFound": "File not found {{file}}",
"fileNotSupported": "File not supported {{file}}",
@@ -82,6 +84,7 @@
"ttsEngine": "TTS engine",
"ttsModel": "TTS model",
"ttsVoice": "TTS voice",
"ttsBaseUrl": "TTS base URL",
"notFound": "Conversation not found",
"contentRequired": "Content required"
},

View File

@@ -21,6 +21,7 @@
"added": "成功添加音频",
"removed": "成功删除音频",
"notFound": "未找到音频",
"fileTooLarge": "文件太大了 {{ file }}",
"failedToAdd": "添加音频失败, {{error}}",
"fileNotFound": "无法访问文件 {{file}}",
"fileNotSupported": "文件不支持 {{file}}",
@@ -45,6 +46,7 @@
"added": "成功添加视频",
"removed": "成功删除视频",
"notFound": "未找到视频",
"fileTooLarge": "文件太大了 {{ file }}",
"failedToAdd": "添加视频失败, {{error}}",
"fileNotFound": "无法访问文件 {{file}}",
"fileNotSupported": "文件不支持 {{file}}",
@@ -82,6 +84,7 @@
"ttsEngine": "TTS 引擎",
"ttsModel": "TTS 模型",
"ttsVoice": "TTS 声音",
"ttsBaseUrl": "TTS 请求地址",
"notFound": "未找到对话",
"contentRequired": "对话内容不能为空"
},

View File

@@ -29,6 +29,8 @@ import webApi from "@main/web-api";
import { startCase } from "lodash";
import { v5 as uuidv5 } from "uuid";
const SIZE_LIMIT = 1024 * 1024 * 50; // 50MB
const logger = log.scope("db/models/audio");
@Table({
modelName: "Audio",
@@ -240,6 +242,11 @@ export class Audio extends Model<Audio> {
throw new Error(t("models.audio.fileNotSupported", { file: filePath }));
}
const stats = fs.statSync(filePath);
if (stats.size > SIZE_LIMIT) {
throw new Error(t("models.audio.fileTooLarge", { file: filePath }));
}
const md5 = await hashFile(filePath, { algo: "md5" });
// Generate ID

View File

@@ -161,6 +161,7 @@ export class Speech extends Model<Speech> {
engine = "openai",
model = "tts-1",
voice = "alloy",
baseUrl,
} = configuration || {};
logger.debug("Generating speech", { engine, model, voice });
@@ -176,7 +177,9 @@ export class Speech extends Model<Speech> {
}
const openai = new OpenAI({
apiKey: key,
baseURL: baseUrl,
});
logger.debug("baseURL", openai.baseURL);
const file = await openai.audio.speech.create({
input: text,

View File

@@ -29,6 +29,8 @@ import webApi from "@main/web-api";
import { startCase } from "lodash";
import { v5 as uuidv5 } from "uuid";
const SIZE_LIMIT = 1024 * 1024 * 100; // 100MB
const logger = log.scope("db/models/video");
@Table({
modelName: "Video",
@@ -262,6 +264,11 @@ export class Video extends Model<Video> {
throw new Error(t("models.video.fileNotSupported", { file: filePath }));
}
const stats = fs.statSync(filePath);
if (stats.size > SIZE_LIMIT) {
throw new Error(t("models.video.fileTooLarge", { file: filePath }));
}
const md5 = await hashFile(filePath, { algo: "md5" });
// Generate ID

View File

@@ -2,7 +2,7 @@ import { Link } from "react-router-dom";
import { cn } from "@renderer/lib/utils";
export const AudioCard = (props: {
audio: ResourceType;
audio: AudioType;
className?: string;
}) => {
const { audio, className } = props;

View File

@@ -53,6 +53,7 @@ const conversationFormSchema = z.object({
engine: z.enum(["openai"]).default("openai"),
model: z.string().default("tts-1"),
voice: z.string().optional(),
baseUrl: z.string().optional(),
})
.optional(),
})
@@ -102,6 +103,9 @@ export const ConversationForm = (props: {
engine: conversation.engine,
configuration: {
...conversation.configuration,
tts: {
...conversation.configuration?.tts,
},
},
}
: {
@@ -128,6 +132,10 @@ export const ConversationForm = (props: {
configuration.baseUrl = LLM_PROVIDERS[engine]?.baseUrl;
}
if (!configuration.tts.baseUrl) {
configuration.tts.baseUrl = LLM_PROVIDERS[engine]?.baseUrl;
}
if (conversation?.id) {
EnjoyApp.conversations
.update(conversation.id, {
@@ -547,6 +555,21 @@ export const ConversationForm = (props: {
</FormItem>
)}
/>
<FormField
control={form.control}
name="configuration.tts.baseUrl"
render={({ field }) => (
<FormItem>
<FormLabel>{t("models.conversation.ttsBaseUrl")}</FormLabel>
<Input {...field} />
<FormDescription>
{t("models.conversation.baseUrl")}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</div>
</ScrollArea>
@@ -584,7 +607,9 @@ export const ConversationForm = (props: {
)}
<Button
disabled={submitting || !form.formState.isDirty}
disabled={
submitting || (conversation.id && !form.formState.isDirty)
}
className="w-full h-12"
size="lg"
type="submit"
@@ -686,8 +711,9 @@ const conversationDefaultConfiguration = {
maxTokens: 2048,
presencePenalty: 0,
frequencyPenalty: 0,
historyBufferSize: 10,
historyBufferSize: 0,
tts: {
baseUrl: "",
engine: "openai",
model: "tts-1",
voice: "alloy",

View File

@@ -54,6 +54,7 @@ export const AssistantMessageComponent = (props: {
engine: configuration?.tts?.engine,
model: configuration?.tts?.model,
voice: configuration?.tts?.voice,
baseUrl: configuration?.tts?.baseUrl,
})
.then((speech) => {
setSpeech(speech);

View File

@@ -104,6 +104,7 @@ export const WhisperModelOptions = () => {
}
if (state.state === "completed") {
model.downloaded = true;
setWhisperModel(model.name);
EnjoyApp.download.removeAllListeners();
}

View File

@@ -85,7 +85,15 @@ export default () => {
{conversations.map((conversation) => (
<Link key={conversation.id} to={`/conversations/${conversation.id}`}>
<div className="bg-white text-primary rounded-full w-full mb-2 p-4 hover:bg-primary hover:text-white cursor-pointer flex items-center">
<div
className="bg-white text-primary rounded-full w-full mb-2 p-4 hover:bg-primary hover:text-white cursor-pointer flex items-center"
style={{
borderLeftColor: `#${conversation.id
.replaceAll("-", "")
.substr(0, 6)}`,
borderLeftWidth: 3,
}}
>
<div className="">
<MessageCircleIcon className="mr-2" />
</div>