hold conversations
This commit is contained in:
@@ -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', () => [])
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
53
utils/helper.js
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user