hold conversations

This commit is contained in:
Rafi
2023-02-23 22:59:58 +08:00
parent 8685c8e87f
commit 03d7dc2589
5 changed files with 154 additions and 60 deletions

View File

@@ -1,5 +1,10 @@
export const useModels = () => useState('models', () => getStoredModels()) export const useModels = () => useState('models', () => getStoredModels())
export const useCurrentModel = () => useState('currentModel', () => getCurrentModel()) export const useCurrentModel = () => useState('currentModel', () => getCurrentModel())
export const useApiKey = () => useState('apiKey', () => getStoredApiKey()) export const useApiKey = () => useState('apiKey', () => getStoredApiKey())
export const useConversion = () => useState('conversion', () => getDefaultConversionData())
export const useConversions = () => useState('conversions', () => [])

View File

@@ -1,4 +1,7 @@
<script setup> <script setup>
import {useConversions} from "../composables/states";
import {getConversions} from "../utils/helper";
const { $i18n } = useNuxtApp() const { $i18n } = useNuxtApp()
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
const colorMode = useColorMode() const colorMode = useColorMode()
@@ -19,6 +22,13 @@ const { locale, locales, setLocale } = useI18n()
const setLang = (lang) => { const setLang = (lang) => {
setLocale(lang) setLocale(lang)
} }
const conversations = useConversions()
onNuxtReady(async () => {
conversations.value = await getConversions()
})
</script> </script>
<template> <template>
@@ -28,11 +38,29 @@ const setLang = (lang) => {
<v-navigation-drawer <v-navigation-drawer
v-model="drawer" v-model="drawer"
> >
<div class="px-2 py-2">
<v-btn
block
variant="outlined"
prepend-icon="add"
size="large"
@click="createNewConversion()"
>
New conversation
</v-btn>
<v-list> <v-list>
<ModelDialog/> <v-list-item
v-for="conversation in conversations"
:key="conversation.id"
:title="conversation.topic"
active-color="primary"
@click="openConversationMessages(conversation)"
></v-list-item>
</v-list> </v-list>
</div>
<template v-slot:append> <template v-slot:append>
<div class="px-1">
<v-divider></v-divider> <v-divider></v-divider>
<v-list> <v-list>
<ApiKeyDialog/> <ApiKeyDialog/>
@@ -69,6 +97,7 @@ const setLang = (lang) => {
@click="feedback" @click="feedback"
></v-list-item> ></v-list-item>
</v-list> </v-list>
</div>
</template> </template>
</v-navigation-drawer> </v-navigation-drawer>
@@ -106,3 +135,16 @@ const setLang = (lang) => {
</v-main> </v-main>
</v-app> </v-app>
</template> </template>
<style>
.v-navigation-drawer__content::-webkit-scrollbar {
width: 0;
}
.v-navigation-drawer__content:hover::-webkit-scrollbar {
width: 6px;
}
.v-navigation-drawer__content:hover::-webkit-scrollbar-thumb {
background-color: #999;
border-radius: 3px;
}
</style>

View File

@@ -52,7 +52,7 @@ const fetchReply = async (message, parentMessageId) => {
throw err; throw err;
}, },
onmessage(message) { onmessage(message) {
console.log(message) // console.log(message)
const event = message.event const event = message.event
const data = JSON.parse(message.data) const data = JSON.parse(message.data)
@@ -63,19 +63,20 @@ const fetchReply = async (message, parentMessageId) => {
if (event === 'done') { if (event === 'done') {
if (currentConversation.value.id === null) { if (currentConversation.value.id === null) {
currentConversation.value.id = data.conversationId currentConversation.value.id = data.conversationId
genTitle(currentConversation.value.id)
} }
currentConversation.value.messages[currentConversation.value.messages.length - 1].id = data.messageId currentConversation.value.messages[currentConversation.value.messages.length - 1].id = data.messageId
abortFetch() abortFetch()
return; return;
} }
if (currentConversation.value.messages[currentConversation.value.messages.length - 1].from === 'ai') { if (currentConversation.value.messages[currentConversation.value.messages.length - 1].is_bot) {
currentConversation.value.messages[currentConversation.value.messages.length - 1].message += data.content currentConversation.value.messages[currentConversation.value.messages.length - 1].message += data.content
} else { } else {
currentConversation.value.messages.push({id: null, from: 'ai', message: data.content}) currentConversation.value.messages.push({id: null, is_bot: true, message: data.content})
} }
// scrollChatWindow() scrollChatWindow()
}, },
}) })
} catch (err) { } catch (err) {
@@ -85,11 +86,7 @@ const fetchReply = async (message, parentMessageId) => {
} }
} }
const defaultConversation = ref({ const currentConversation = useConversion()
id: null,
messages: []
})
const currentConversation = ref({})
const grab = ref(null) const grab = ref(null)
const scrollChatWindow = () => { const scrollChatWindow = () => {
@@ -99,20 +96,17 @@ const scrollChatWindow = () => {
grab.value.scrollIntoView({behavior: 'smooth'}) grab.value.scrollIntoView({behavior: 'smooth'})
} }
const createNewConversation = () => {
currentConversation.value = Object.assign(defaultConversation.value, {
})
}
const send = (message) => { const send = (message) => {
fetchingResponse.value = true fetchingResponse.value = true
let parentMessageId = null let parentMessageId = null
if (currentConversation.value.messages.length > 0) { if (currentConversation.value.messages.length > 0) {
const lastMessage = currentConversation.value.messages[currentConversation.value.messages.length - 1] const lastMessage = currentConversation.value.messages[currentConversation.value.messages.length - 1]
if (lastMessage.from === 'ai' && lastMessage.id !== null) { if (lastMessage.is_bot && lastMessage.id !== null) {
parentMessageId = lastMessage.id parentMessageId = lastMessage.id
} }
} }
currentConversation.value.messages.push({from: 'me', parentMessageId: parentMessageId, message: message}) currentConversation.value.messages.push({parentMessageId: parentMessageId, message: message})
fetchReply(message, parentMessageId) fetchReply(message, parentMessageId)
scrollChatWindow() scrollChatWindow()
} }
@@ -127,7 +121,6 @@ const showSnackbar = (text) => {
snackbar.value = true snackbar.value = true
} }
createNewConversation()
</script> </script>
<template> <template>
@@ -140,10 +133,10 @@ createNewConversation()
elevation="0" elevation="0"
v-for="(conversation, index) in currentConversation.messages" v-for="(conversation, index) in currentConversation.messages"
:key="index" :key="index"
:variant="conversation.from === 'ai' ? 'tonal' : 'text'" :variant="conversation.is_bot ? 'tonal' : 'text'"
> >
<v-container> <v-container>
<v-card-text class="text-caption text-disabled">{{ $t(`roles.${conversation.from}`) }}</v-card-text> <v-card-text class="text-caption text-disabled">{{ $t(`roles.${conversation.is_bot?'ai':'me'}`) }}</v-card-text>
<v-card-text> <v-card-text>
<MsgContent :content="conversation.message" /> <MsgContent :content="conversation.message" />
</v-card-text> </v-card-text>

View File

@@ -84,10 +84,11 @@ export default defineNuxtPlugin(() => {
'refresh': refreshToken.value 'refresh': refreshToken.value
} }
}) })
console.log('refresh', data, error)
if (!error.value) { if (!error.value) {
token.value = data.value.access token.value = data.value.access
return data.value.access
} }
return null
} }
async callback () { async callback () {
@@ -105,9 +106,9 @@ export default defineNuxtPlugin(() => {
return null return null
} }
if (!token.value) { if (!token.value) {
await this.refresh() return await this.refresh()
} }
return token.value || null return token.value
} }
} }

53
utils/helper.js Normal file
View File

@@ -0,0 +1,53 @@
export const getDefaultConversionData = () => {
return {
id: null,
topic: null,
messages: [],
loadingMessages: false,
}
}
export const getConversions = async () => {
const { data, error } = await useAuthFetch('/api/chat/conversations')
if (!error.value) {
return data.value
}
return []
}
export const createNewConversion = () => {
const conversation = useConversion()
conversation.value = getDefaultConversionData()
}
export const openConversationMessages = async (currentConversation) => {
const conversation = useConversion()
conversation.value = Object.assign(conversation.value, currentConversation)
conversation.value.loadingMessages = true
const { data, error } = await useAuthFetch('/api/chat/messages/?conversationId=' + currentConversation.id)
if (!error.value) {
conversation.value.messages = data.value
}
conversation.value.loadingMessages = true
}
export const genTitle = async (conversationId) => {
const { data, error } = await useAuthFetch('/api/gen_title', {
method: 'POST',
body: {
conversationId: conversationId
}
})
if (!error.value) {
const conversation = {
id: conversationId,
topic: data.value.title,
}
const conversations = useConversions()
// prepend to conversations
conversations.value = [conversation, ...conversations.value]
return data.value.title
}
return null
}