chore: Add a "clean option" to remove conversation messages while keeping system message

This commit is contained in:
Louis 2023-11-24 14:00:46 +07:00
parent 15b9f8cd0e
commit 26bd092f03
4 changed files with 52 additions and 10 deletions

View File

@ -1,4 +1,4 @@
import { MessageStatus, ThreadMessage } from '@janhq/core' import { ChatCompletionRole, MessageStatus, ThreadMessage } from '@janhq/core'
import { atom } from 'jotai' import { atom } from 'jotai'
import { import {
@ -94,6 +94,14 @@ export const deleteConversationMessage = atom(null, (get, set, id: string) => {
set(chatMessages, newData) set(chatMessages, newData)
}) })
export const cleanConversationMessages = atom(null, (get, set, id: string) => {
const newData: Record<string, ThreadMessage[]> = {
...get(chatMessages),
}
newData[id] = newData[id].filter((e) => e.role === ChatCompletionRole.System)
set(chatMessages, newData)
})
export const updateMessageAtom = atom( export const updateMessageAtom = atom(
null, null,
( (

View File

@ -1,4 +1,4 @@
import { PluginType } from '@janhq/core' import { ChatCompletionRole, PluginType } from '@janhq/core'
import { ConversationalPlugin } from '@janhq/core/lib/plugins' import { ConversationalPlugin } from '@janhq/core/lib/plugins'
import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { useAtom, useAtomValue, useSetAtom } from 'jotai'
@ -10,7 +10,11 @@ import { pluginManager } from '../plugin/PluginManager'
import { useActiveModel } from './useActiveModel' import { useActiveModel } from './useActiveModel'
import { deleteConversationMessage } from '@/helpers/atoms/ChatMessage.atom' import {
cleanConversationMessages,
deleteConversationMessage,
getCurrentChatMessagesAtom,
} from '@/helpers/atoms/ChatMessage.atom'
import { import {
userConversationsAtom, userConversationsAtom,
getActiveConvoIdAtom, getActiveConvoIdAtom,
@ -27,7 +31,27 @@ export default function useDeleteConversation() {
const setActiveConvoId = useSetAtom(setActiveConvoIdAtom) const setActiveConvoId = useSetAtom(setActiveConvoIdAtom)
const deleteMessages = useSetAtom(deleteConversationMessage) const deleteMessages = useSetAtom(deleteConversationMessage)
const cleanMessages = useSetAtom(cleanConversationMessages)
const currentMessages = useAtomValue(getCurrentChatMessagesAtom)
const cleanConvo = async () => {
if (activeConvoId) {
const currentConversation = userConversations.filter(
(c) => c.id === activeConvoId
)[0]
cleanMessages(activeConvoId)
if (currentConversation)
await pluginManager
.get<ConversationalPlugin>(PluginType.Conversational)
?.saveConversation({
...currentConversation,
id: activeConvoId,
messages: currentMessages.filter(
(e) => e.role === ChatCompletionRole.System
),
})
}
}
const deleteConvo = async () => { const deleteConvo = async () => {
if (activeConvoId) { if (activeConvoId) {
try { try {
@ -56,6 +80,7 @@ export default function useDeleteConversation() {
} }
return { return {
cleanConvo,
deleteConvo, deleteConvo,
} }
} }

View File

@ -49,7 +49,7 @@ export default function useSendChatMessage() {
const summaryMsg: ChatCompletionMessage = { const summaryMsg: ChatCompletionMessage = {
role: ChatCompletionRole.User, role: ChatCompletionRole.User,
content: content:
'summary this conversation in a few words, the response should just include the summary', 'summary this conversation in less than 5 words, the response should just include the summary',
} }
// Request convo summary // Request convo summary
setTimeout(async () => { setTimeout(async () => {
@ -64,7 +64,7 @@ export default function useSendChatMessage() {
currentConvo.id === newMessage.threadId && currentConvo.id === newMessage.threadId &&
result?.content && result?.content &&
result?.content?.trim().length > 0 && result?.content?.trim().length > 0 &&
result.content.split(' ').length <= 10 result.content.split(' ').length <= 20
) { ) {
const updatedConv = { const updatedConv = {
...currentConvo, ...currentConvo,

View File

@ -1,15 +1,16 @@
import { Fragment, useEffect, useRef, useState } from 'react' import { Fragment, useContext, useEffect, useRef, useState } from 'react'
import { Model } from '@janhq/core/lib/types' import { Model } from '@janhq/core/lib/types'
import { Button, Badge, Textarea } from '@janhq/uikit' import { Button, Badge, Textarea } from '@janhq/uikit'
import { useAtom, useAtomValue } from 'jotai' import { useAtom, useAtomValue } from 'jotai'
import { Trash2Icon } from 'lucide-react' import { Trash2Icon, Paintbrush } from 'lucide-react'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { currentPromptAtom } from '@/containers/Providers/Jotai' import { currentPromptAtom } from '@/containers/Providers/Jotai'
import { FeatureToggleContext } from '@/context/FeatureToggle'
import ShortCut from '@/containers/Shortcut' import ShortCut from '@/containers/Shortcut'
import { MainViewState } from '@/constants/screens' import { MainViewState } from '@/constants/screens'
@ -42,7 +43,7 @@ import { currentConvoStateAtom } from '@/helpers/atoms/Conversation.atom'
const ChatScreen = () => { const ChatScreen = () => {
const currentConvo = useAtomValue(currentConversationAtom) const currentConvo = useAtomValue(currentConversationAtom)
const { downloadedModels } = useGetDownloadedModels() const { downloadedModels } = useGetDownloadedModels()
const { deleteConvo } = useDeleteConversation() const { deleteConvo, cleanConvo } = useDeleteConversation()
const { activeModel, stateModel } = useActiveModel() const { activeModel, stateModel } = useActiveModel()
const { setMainViewState } = useMainViewState() const { setMainViewState } = useMainViewState()
@ -60,6 +61,7 @@ const ChatScreen = () => {
const [isModelAvailable, setIsModelAvailable] = useState( const [isModelAvailable, setIsModelAvailable] = useState(
downloadedModels.some((x) => x.id === currentConvo?.modelId) downloadedModels.some((x) => x.id === currentConvo?.modelId)
) )
const { experimentalFeatureEnabed } = useContext(FeatureToggleContext)
const textareaRef = useRef<HTMLTextAreaElement>(null) const textareaRef = useRef<HTMLTextAreaElement>(null)
@ -147,13 +149,20 @@ const ChatScreen = () => {
Download Model Download Model
</Button> </Button>
)} )}
{!stateModel.loading && ( {experimentalFeatureEnabed && (
<Paintbrush
size={16}
className="cursor-pointer text-muted-foreground"
onClick={() => cleanConvo()}
/>
)}
{
<Trash2Icon <Trash2Icon
size={16} size={16}
className="cursor-pointer text-muted-foreground" className="cursor-pointer text-muted-foreground"
onClick={() => deleteConvo()} onClick={() => deleteConvo()}
/> />
)} }
</div> </div>
</div> </div>
</div> </div>