mirror of
https://github.com/NovaOSS/nova-betterchat.git
synced 2024-11-25 19:33:59 +01:00
feat: auto generate title
This commit is contained in:
parent
68562b699f
commit
b080c185f4
|
@ -4,7 +4,7 @@ import useStore from '@store/store';
|
|||
import PlusIcon from '@icon/PlusIcon';
|
||||
|
||||
import { ChatInterface } from '@type/chat';
|
||||
import { defaultChatConfig, defaultSystemMessage } from '@constants/chat';
|
||||
import { generateDefaultChat } from '@constants/chat';
|
||||
|
||||
const NewMessageButton = React.memo(
|
||||
({ messageIndex }: { messageIndex: number }) => {
|
||||
|
@ -24,16 +24,7 @@ const NewMessageButton = React.memo(
|
|||
title = `New Chat ${titleIndex}`;
|
||||
}
|
||||
|
||||
updatedChats.unshift({
|
||||
title,
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
content: defaultSystemMessage,
|
||||
},
|
||||
],
|
||||
config: { ...defaultChatConfig },
|
||||
});
|
||||
updatedChats.unshift(generateDefaultChat(title));
|
||||
setChats(updatedChats);
|
||||
setCurrentChatIndex(0);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConfigInterface } from '@type/chat';
|
||||
import { ChatInterface, ConfigInterface } from '@type/chat';
|
||||
|
||||
const date = new Date();
|
||||
const dateString =
|
||||
|
@ -17,3 +17,10 @@ export const defaultChatConfig: ConfigInterface = {
|
|||
temperature: 1,
|
||||
presence_penalty: 0,
|
||||
};
|
||||
|
||||
export const generateDefaultChat = (title?: string): ChatInterface => ({
|
||||
title: title ? title : 'New Chat',
|
||||
messages: [{ role: 'system', content: defaultSystemMessage }],
|
||||
config: { ...defaultChatConfig },
|
||||
titleSet: false,
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import useStore from '@store/store';
|
||||
import { defaultChatConfig, defaultSystemMessage } from '@constants/chat';
|
||||
import { generateDefaultChat } from '@constants/chat';
|
||||
import { ChatInterface } from '@type/chat';
|
||||
|
||||
const useAddChat = () => {
|
||||
|
@ -19,11 +19,7 @@ const useAddChat = () => {
|
|||
title = `New Chat ${titleIndex}`;
|
||||
}
|
||||
|
||||
updatedChats.unshift({
|
||||
title,
|
||||
messages: [{ role: 'system', content: defaultSystemMessage }],
|
||||
config: { ...defaultChatConfig },
|
||||
});
|
||||
updatedChats.unshift(generateDefaultChat(title));
|
||||
setChats(updatedChats);
|
||||
setCurrentChatIndex(0);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,14 @@
|
|||
import React from 'react';
|
||||
import useStore from '@store/store';
|
||||
import { MessageInterface } from '@type/chat';
|
||||
import { defaultChatConfig, defaultSystemMessage } from '@constants/chat';
|
||||
import { generateDefaultChat } from '@constants/chat';
|
||||
|
||||
const useInitialiseNewChat = () => {
|
||||
const setChats = useStore((state) => state.setChats);
|
||||
const setCurrentChatIndex = useStore((state) => state.setCurrentChatIndex);
|
||||
|
||||
const initialiseNewChat = () => {
|
||||
const message: MessageInterface = {
|
||||
role: 'system',
|
||||
content: defaultSystemMessage,
|
||||
};
|
||||
setChats([
|
||||
{
|
||||
title: 'New Chat',
|
||||
messages: [message],
|
||||
config: { ...defaultChatConfig },
|
||||
},
|
||||
]);
|
||||
setChats([generateDefaultChat()]);
|
||||
setCurrentChatIndex(0);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import React from 'react';
|
||||
import useStore from '@store/store';
|
||||
import { ChatInterface } from '@type/chat';
|
||||
import { getChatCompletionStream as getChatCompletionStreamFree } from '@api/freeApi';
|
||||
import { getChatCompletionStream as getChatCompletionStreamCustom } from '@api/customApi';
|
||||
import { ChatInterface, MessageInterface } from '@type/chat';
|
||||
import {
|
||||
getChatCompletionStream as getChatCompletionStreamFree,
|
||||
getChatCompletion as getChatCompletionFree,
|
||||
} from '@api/freeApi';
|
||||
import {
|
||||
getChatCompletionStream as getChatCompletionStreamCustom,
|
||||
getChatCompletion as getChatCompletionCustom,
|
||||
} from '@api/customApi';
|
||||
import { parseEventSource } from '@api/helper';
|
||||
import { limitMessageTokens } from '@utils/messageUtils';
|
||||
import { defaultChatConfig } from '@constants/chat';
|
||||
|
||||
const useSubmit = () => {
|
||||
const error = useStore((state) => state.error);
|
||||
|
@ -16,6 +23,22 @@ const useSubmit = () => {
|
|||
const currentChatIndex = useStore((state) => state.currentChatIndex);
|
||||
const setChats = useStore((state) => state.setChats);
|
||||
|
||||
const generateTitle = async (
|
||||
message: MessageInterface[]
|
||||
): Promise<string> => {
|
||||
let data;
|
||||
if (apiFree) {
|
||||
data = await getChatCompletionFree(
|
||||
useStore.getState().apiFreeEndpoint,
|
||||
message,
|
||||
defaultChatConfig
|
||||
);
|
||||
} else if (apiKey) {
|
||||
data = await getChatCompletionCustom(apiKey, message, defaultChatConfig);
|
||||
}
|
||||
return data.choices[0].message.content;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const chats = useStore.getState().chats;
|
||||
if (generating || !chats) return;
|
||||
|
@ -94,6 +117,34 @@ const useSubmit = () => {
|
|||
reader.releaseLock();
|
||||
stream.cancel();
|
||||
}
|
||||
|
||||
// generate title for new chats
|
||||
const currChats = useStore.getState().chats;
|
||||
if (currChats && !currChats[currentChatIndex]?.titleSet) {
|
||||
const messages_length = currChats[currentChatIndex].messages.length;
|
||||
const assistant_message =
|
||||
currChats[currentChatIndex].messages[messages_length - 1].content;
|
||||
const user_message =
|
||||
currChats[currentChatIndex].messages[messages_length - 2].content;
|
||||
|
||||
const message: MessageInterface = {
|
||||
role: 'user',
|
||||
content: `Generate a title in less than 6 words for the following message:\nUser: ${user_message}\nAssistant: ${assistant_message}`,
|
||||
};
|
||||
|
||||
let title = await generateTitle([message]);
|
||||
if (title.startsWith('"') && title.endsWith('"')) {
|
||||
title = title.slice(1, -1);
|
||||
}
|
||||
const updatedChats: ChatInterface[] = JSON.parse(
|
||||
JSON.stringify(useStore.getState().chats)
|
||||
);
|
||||
updatedChats[currentChatIndex].title = title;
|
||||
updatedChats[currentChatIndex].titleSet = true;
|
||||
setChats(updatedChats);
|
||||
console.log(message);
|
||||
console.log(title);
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
const err = (e as Error).message;
|
||||
console.log(err);
|
||||
|
|
5
src/store/migrate.ts
Normal file
5
src/store/migrate.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { LocalStorageInterface } from '@type/chat';
|
||||
|
||||
export const migrateV0 = (persistedState: LocalStorageInterface) => {
|
||||
persistedState.chats.forEach((chat) => (chat.titleSet = false));
|
||||
};
|
|
@ -4,6 +4,8 @@ import { ChatSlice, createChatSlice } from './chat-slice';
|
|||
import { InputSlice, createInputSlice } from './input-slice';
|
||||
import { AuthSlice, createAuthSlice } from './auth-slice';
|
||||
import { ConfigSlice, createConfigSlice } from './config-slice';
|
||||
import { LocalStorageInterface } from '@type/chat';
|
||||
import { migrateV0 } from './migrate';
|
||||
|
||||
export type StoreState = ChatSlice & InputSlice & AuthSlice & ConfigSlice;
|
||||
|
||||
|
@ -30,6 +32,15 @@ const useStore = create<StoreState>()(
|
|||
apiFreeEndpoint: state.apiFreeEndpoint,
|
||||
theme: state.theme,
|
||||
}),
|
||||
version: 1,
|
||||
migrate: (persistedState, version) => {
|
||||
switch (version) {
|
||||
case 0:
|
||||
migrateV0(persistedState as LocalStorageInterface);
|
||||
break;
|
||||
}
|
||||
return persistedState as StoreState;
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Theme } from './theme';
|
||||
|
||||
export type Role = 'user' | 'assistant' | 'system';
|
||||
export const roles: Role[] = ['user', 'assistant', 'system'];
|
||||
|
||||
|
@ -10,9 +12,19 @@ export interface ChatInterface {
|
|||
title: string;
|
||||
messages: MessageInterface[];
|
||||
config: ConfigInterface;
|
||||
titleSet: boolean;
|
||||
}
|
||||
|
||||
export interface ConfigInterface {
|
||||
temperature: number;
|
||||
presence_penalty: number;
|
||||
}
|
||||
|
||||
export interface LocalStorageInterface {
|
||||
chats: ChatInterface[];
|
||||
currentChatIndex: number;
|
||||
apiKey: string;
|
||||
apiFree: boolean;
|
||||
apiFreeEndpoint: string;
|
||||
theme: Theme;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue