diff --git a/frontend/src/_locales/ja/main.json b/frontend/src/_locales/ja/main.json
index 62e00ec..549cf39 100644
--- a/frontend/src/_locales/ja/main.json
+++ b/frontend/src/_locales/ja/main.json
@@ -337,5 +337,6 @@
"Penalty Decay": "ペナルティ減衰",
"If you don't know what it is, keep it default.": "何であるかわからない場合はデフォルトのままにしてください。",
"Failed to find the base model, please try to change your base model.": "ベースモデルが見つかりませんでした、ベースモデルを変更してみてください。",
- "Markdown Renderer": "Markdownレンダリング"
+ "Markdown Renderer": "Markdownレンダリング",
+ "Load Conversation": "会話を読み込む"
}
\ No newline at end of file
diff --git a/frontend/src/_locales/zh-hans/main.json b/frontend/src/_locales/zh-hans/main.json
index 04154b0..fc5a6eb 100644
--- a/frontend/src/_locales/zh-hans/main.json
+++ b/frontend/src/_locales/zh-hans/main.json
@@ -337,5 +337,6 @@
"Penalty Decay": "惩罚衰减",
"If you don't know what it is, keep it default.": "如果你不知道这是什么,保持默认",
"Failed to find the base model, please try to change your base model.": "未找到基底模型,请尝试更换基底模型",
- "Markdown Renderer": "Markdown渲染"
+ "Markdown Renderer": "Markdown渲染",
+ "Load Conversation": "读取对话"
}
\ No newline at end of file
diff --git a/frontend/src/pages/AudiotrackManager/AudiotrackEditor.tsx b/frontend/src/pages/AudiotrackManager/AudiotrackEditor.tsx
index e47892f..c30f47d 100644
--- a/frontend/src/pages/AudiotrackManager/AudiotrackEditor.tsx
+++ b/frontend/src/pages/AudiotrackManager/AudiotrackEditor.tsx
@@ -29,14 +29,14 @@ import {
} from '../../types/composition';
import { toast } from 'react-toastify';
import {
- absPathAsset,
flushMidiRecordingContent,
getMidiRawContentMainInstrument,
getMidiRawContentTime,
getServerRoot,
+ OpenFileDialog,
refreshTracksTotalTime
} from '../../utils';
-import { OpenOpenFileDialog, PlayNote } from '../../../wailsjs/go/backend_golang/App';
+import { PlayNote } from '../../../wailsjs/go/backend_golang/App';
const snapValue = 25;
const minimalMoveTime = 8; // 1000/125=8ms wait_events=125
@@ -471,15 +471,7 @@ const AudiotrackEditor: FC<{ setPrompt: (prompt: string) => void }> = observer((
return;
}
- OpenOpenFileDialog('*.mid').then(async filePath => {
- if (!filePath)
- return;
-
- let blob: Blob;
- if (commonStore.platform === 'web')
- blob = (filePath as unknown as { blob: Blob }).blob;
- else
- blob = await fetch(absPathAsset(filePath)).then(r => r.blob());
+ OpenFileDialog('*.mid').then(async blob => {
const bodyForm = new FormData();
bodyForm.append('file_data', blob);
fetch(getServerRoot(commonStore.getCurrentModelConfig().apiParameters.apiPort) + '/midi-to-text', {
@@ -510,8 +502,6 @@ const AudiotrackEditor: FC<{ setPrompt: (prompt: string) => void }> = observer((
).catch(e => {
toast(t('Error') + ' - ' + (e.message || e), { type: 'error', autoClose: 2500 });
});
- }).catch(e => {
- toast(t('Error') + ' - ' + (e.message || e), { type: 'error', autoClose: 2500 });
});
}}>
{t('Import MIDI')}
diff --git a/frontend/src/pages/Chat.tsx b/frontend/src/pages/Chat.tsx
index f1fe03a..68bf8dd 100644
--- a/frontend/src/pages/Chat.tsx
+++ b/frontend/src/pages/Chat.tsx
@@ -26,6 +26,7 @@ import {
Delete28Regular,
Dismiss16Regular,
Dismiss24Regular,
+ FolderOpenVerticalRegular,
RecordStop28Regular,
SaveRegular,
TextAlignJustify24Regular,
@@ -37,9 +38,17 @@ import { toast } from 'react-toastify';
import { WorkHeader } from '../components/WorkHeader';
import { DialogButton } from '../components/DialogButton';
import { OpenFileFolder, OpenOpenFileDialog, OpenSaveFileDialog } from '../../wailsjs/go/backend_golang/App';
-import { absPathAsset, bytesToReadable, getServerRoot, setActivePreset, toastWithButton } from '../utils';
+import {
+ absPathAsset,
+ bytesToReadable,
+ getServerRoot,
+ newChatConversation,
+ OpenFileDialog,
+ setActivePreset,
+ toastWithButton
+} from '../utils';
import { useMediaQuery } from 'usehooks-ts';
-import { botName, ConversationMessage, MessageType, userName, welcomeUuid } from '../types/chat';
+import { botName, ConversationMessage, MessageType, Role, userName, welcomeUuid } from '../types/chat';
import { Labeled } from '../components/Labeled';
import { ValuedSlider } from '../components/ValuedSlider';
import { PresetsButton } from './PresetsManager/PresetsButton';
@@ -302,12 +311,45 @@ const SidePanel: FC = observer(() => {
});
}} />
} />
- {/*}*/}
- {/* onClick={() => {*/}
- {/* }}>*/}
- {/* {t('Load Conversation')}*/}
- {/**/}
+ }
+ onClick={() => {
+ OpenFileDialog('*.txt;*.md').then(async blob => {
+ const userNames = ['User:', 'Question:', 'Q:', 'Human:', 'Bob:'];
+ const assistantNames = ['Assistant:', 'Answer:', 'A:', 'Bot:', 'Alice:'];
+ const names = userNames.concat(assistantNames);
+ const content = await blob.text();
+ const lines = content.split('\n');
+
+ const { pushMessage, saveConversation } = newChatConversation();
+ let messageRole: Role = 'user';
+ let messageContent = '';
+ for (const [i, line] of lines.entries()) {
+ let lineName = '';
+ if (names.some(name => {
+ lineName = name;
+ return line.startsWith(name);
+ })) {
+ if (messageContent.trim())
+ pushMessage(messageRole, messageContent.trim());
+
+ if (userNames.includes(lineName))
+ messageRole = 'user';
+ else
+ messageRole = 'assistant';
+
+ messageContent = line.replace(lineName, '');
+ } else {
+ messageContent += '\n' + line;
+ }
+ if (i === lines.length - 1)
+ pushMessage(messageRole, messageContent.trim());
+ }
+ saveConversation();
+ });
+ }}>
+ {t('Load Conversation')}
+
}
onClick={() => {
diff --git a/frontend/src/utils/index.tsx b/frontend/src/utils/index.tsx
index 4900147..22b7a1d 100644
--- a/frontend/src/utils/index.tsx
+++ b/frontend/src/utils/index.tsx
@@ -4,6 +4,7 @@ import {
DepCheck,
InstallPyDep,
ListDirFiles,
+ OpenOpenFileDialog,
ReadFileInfo,
ReadJson,
SaveJson,
@@ -25,7 +26,7 @@ import { DataProcessParameters, LoraFinetuneParameters } from '../types/train';
import { InstrumentTypeNameMap, MidiMessage, tracksMinimalTotalTime } from '../types/composition';
import logo from '../assets/images/logo.png';
import { Preset } from '../types/presets';
-import { botName, Conversation, MessageType, userName } from '../types/chat';
+import { botName, Conversation, MessageType, Role, userName } from '../types/chat';
import { v4 as uuid } from 'uuid';
import { findLastIndex } from 'lodash-es';
@@ -579,24 +580,12 @@ export async function getSoundFont() {
export const setActivePreset = (preset: Preset | null) => {
commonStore.setActivePreset(preset);
//TODO if (preset.displayPresetMessages) {
- const conversation: Conversation = {};
- const conversationOrder: string[] = [];
+ const { pushMessage, saveConversation } = newChatConversation();
if (preset)
for (const message of preset.messages) {
- const newUuid = uuid();
- conversationOrder.push(newUuid);
- conversation[newUuid] = {
- sender: message.role === 'user' ? userName : botName,
- type: MessageType.Normal,
- color: message.role === 'user' ? 'brand' : 'colorful',
- time: new Date().toISOString(),
- content: message.content,
- side: message.role === 'user' ? 'right' : 'left',
- done: true
- };
+ pushMessage(message.role, message.content);
}
- commonStore.setConversation(conversation);
- commonStore.setConversationOrder(conversationOrder);
+ saveConversation();
//}
};
@@ -612,4 +601,49 @@ export function getSupportedCustomCudaFile(isBeta: boolean) {
'./backend-python/wkv_cuda_utils/wkv_cuda40.pyd';
else
return '';
+}
+
+// a wrapper for webOpenOpenFileDialog and OpenOpenFileDialog
+export function OpenFileDialog(filterPattern: string): Promise {
+ return new Promise((resolve) => {
+ OpenOpenFileDialog(filterPattern).then(async filePath => {
+ if (!filePath)
+ return;
+
+ let blob: Blob;
+ if (commonStore.platform === 'web')
+ blob = (filePath as unknown as { blob: Blob }).blob;
+ else
+ blob = await fetch(absPathAsset(filePath)).then(r => r.blob());
+
+ resolve(blob);
+ }).catch(e => {
+ toast(t('Error') + ' - ' + (e.message || e), { type: 'error', autoClose: 2500 });
+ });
+ }
+ );
+}
+
+export function newChatConversation() {
+ const conversation: Conversation = {};
+ const conversationOrder: string[] = [];
+ const pushMessage = (role: Role, content: string) => {
+ const newUuid = uuid();
+ conversationOrder.push(newUuid);
+ conversation[newUuid] = {
+ sender: role === 'user' ? userName : botName,
+ type: MessageType.Normal,
+ color: role === 'user' ? 'brand' : 'colorful',
+ avatarImg: role === 'user' ? undefined : logo,
+ time: new Date().toISOString(),
+ content: content,
+ side: role === 'user' ? 'right' : 'left',
+ done: true
+ };
+ };
+ const saveConversation = () => {
+ commonStore.setConversation(conversation);
+ commonStore.setConversationOrder(conversationOrder);
+ };
+ return { pushMessage, saveConversation };
}
\ No newline at end of file