Multiple improvements for conversation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import {EventStreamContentType, fetchEventSource} from '@microsoft/fetch-event-source'
|
||||
import {addConversation} from "../utils/helper";
|
||||
|
||||
const { $i18n, $auth } = useNuxtApp()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
@@ -137,9 +138,17 @@ const scrollChatWindow = () => {
|
||||
grab.value.scrollIntoView({behavior: 'smooth'})
|
||||
}
|
||||
|
||||
const checkOrAddConversation = () => {
|
||||
if (props.conversation.messages.length === 0) {
|
||||
props.conversation.messages.push({id: null, is_bot: true, message: ''})
|
||||
}
|
||||
}
|
||||
|
||||
const send = (message) => {
|
||||
fetchingResponse.value = true
|
||||
if (props.conversation.messages.length === 0) {
|
||||
addConversation(props.conversation)
|
||||
}
|
||||
props.conversation.messages.push({message: message})
|
||||
fetchReply(message)
|
||||
scrollChatWindow()
|
||||
@@ -182,7 +191,17 @@ watchEffect(() => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="conversation.messages"
|
||||
v-if="conversation.loadingMessages"
|
||||
class="text-center"
|
||||
>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="primary"
|
||||
></v-progress-circular>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="conversation.messages.length > 0"
|
||||
ref="chatWindow"
|
||||
>
|
||||
<v-container>
|
||||
@@ -217,7 +236,10 @@ watchEffect(() => {
|
||||
|
||||
<div ref="grab" class="w-100" style="height: 200px;"></div>
|
||||
</div>
|
||||
<Welcome v-else />
|
||||
<Welcome v-if="conversation.id === null && conversation.messages.length === 0" />
|
||||
</div>
|
||||
|
||||
|
||||
<v-footer app>
|
||||
<div class="px-md-16 w-100 d-flex flex-column">
|
||||
<div class="d-flex align-center">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"themeMode": "Theme Mode",
|
||||
"feedback": "Feedback",
|
||||
"newConversation": "New conversation",
|
||||
"defaultConversationTitle": "Unnamed",
|
||||
"clearConversations": "Clear conversations",
|
||||
"modelParameters": "Model Parameters",
|
||||
"model": "Model",
|
||||
@@ -40,6 +41,7 @@
|
||||
"signOut": "Sign out",
|
||||
"webSearch": "Web Search",
|
||||
"webSearchDefaultPrompt": "Web search results:\n\n[web_results]\nCurrent date: [current_date]\n\nInstructions: Using the provided web search results, write a comprehensive reply to the given query. Make sure to cite results using [[number](URL)] notation after the reference. If the provided search results refer to multiple subjects with the same name, write separate answers for each subject.\nQuery: [query]",
|
||||
"genTitlePrompt": "Generate a short title for the following content, no more than 10 words. \n\nContent: ",
|
||||
"welcomeScreen": {
|
||||
"introduction1": "is an unofficial client for ChatGPT, but uses the official OpenAI API.",
|
||||
"introduction2": "You will need an OpenAI API Key before you can use this client.",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"themeMode": "Тема",
|
||||
"feedback": "Обратная связь",
|
||||
"newConversation": "Новый чат",
|
||||
"defaultConversationTitle": "Безымянный",
|
||||
"clearConversations": "Очистить чаты",
|
||||
"modelParameters": "Параметры модели",
|
||||
"model": "Модель",
|
||||
@@ -40,6 +41,7 @@
|
||||
"signOut": "Выход",
|
||||
"webSearch": "Поиск в интернете",
|
||||
"webSearchDefaultPrompt": "Результаты веб-поиска:\n\n[web_results]\nТекущая дата: [current_date]\n\nИнструкции: Используя предоставленные результаты веб-поиска, напишите развернутый ответ на заданный запрос. Обязательно цитируйте результаты, используя обозначение [[number](URL)] после ссылки. Если предоставленные результаты поиска относятся к нескольким темам с одинаковым названием, напишите отдельные ответы для каждой темы.\nЗапрос: [query]",
|
||||
"genTitlePrompt": "Придумайте короткий заголовок для следующего содержания, не более 10 слов. \n\nСодержание: ",
|
||||
"welcomeScreen": {
|
||||
"introduction1": "является неофициальным клиентом для ChatGPT, но использует официальный API OpenAI.",
|
||||
"introduction2": "Вам понадобится ключ API OpenAI, прежде чем вы сможете использовать этот клиент.",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"themeMode": "主题模式",
|
||||
"feedback": "反馈",
|
||||
"newConversation": "新的对话",
|
||||
"defaultConversationTitle": "未命名",
|
||||
"clearConversations": "清除对话",
|
||||
"modelParameters": "模型参数",
|
||||
"model": "模型",
|
||||
@@ -40,6 +41,7 @@
|
||||
"signOut": "退出登录",
|
||||
"webSearch": "网页搜索",
|
||||
"webSearchDefaultPrompt": "网络搜索结果:\n\n[web_results]\n当前日期:[current_date]\n\n说明:使用提供的网络搜索结果,对给定的查询写出全面的回复。确保在引用参考文献后使用 [[number](URL)] 符号进行引用结果. 如果提供的搜索结果涉及到多个具有相同名称的主题,请针对每个主题编写单独的答案。\n查询:[query]",
|
||||
"genTitlePrompt": "为以下内容生成一个不超过10个字的简短标题。 \n\n内容: ",
|
||||
"welcomeScreen": {
|
||||
"introduction1": "是一个非官方的ChatGPT客户端,但使用OpenAI的官方API",
|
||||
"introduction2": "在使用本客户端之前,您需要一个OpenAI API密钥。",
|
||||
|
||||
@@ -54,6 +54,7 @@ const deleteConversation = async (index) => {
|
||||
deletingConversationIndex.value = null
|
||||
if (!error.value) {
|
||||
if (conversations.value[index].id === currentConversation.value.id) {
|
||||
console.log('delete current conversation')
|
||||
createNewConversation()
|
||||
}
|
||||
conversations.value.splice(index, 1)
|
||||
@@ -130,8 +131,8 @@ onMounted(async () => {
|
||||
block
|
||||
variant="outlined"
|
||||
prepend-icon="add"
|
||||
@click="createNewConversation()"
|
||||
class="text-none"
|
||||
@click="createNewConversation"
|
||||
>
|
||||
{{ $t('newConversation') }}
|
||||
</v-btn>
|
||||
@@ -172,19 +173,19 @@ onMounted(async () => {
|
||||
<v-list-item
|
||||
rounded="xl"
|
||||
active-color="primary"
|
||||
:to="`/${conversation.id}`"
|
||||
:to="conversation.id ? `/${conversation.id}` : undefined"
|
||||
v-bind="props"
|
||||
>
|
||||
<v-list-item-title>{{ conversation.topic }}</v-list-item-title>
|
||||
<template v-slot:append>
|
||||
<div
|
||||
v-show="isHovering"
|
||||
v-show="isHovering && conversation.id"
|
||||
>
|
||||
<v-btn
|
||||
icon="edit"
|
||||
size="small"
|
||||
variant="text"
|
||||
@click.stop="editConversation(cIdx)"
|
||||
@click.prevent="editConversation(cIdx)"
|
||||
>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
@@ -192,7 +193,7 @@ onMounted(async () => {
|
||||
size="small"
|
||||
variant="text"
|
||||
:loading="deletingConversationIndex === cIdx"
|
||||
@click.stop="deleteConversation(cIdx)"
|
||||
@click.prevent="deleteConversation(cIdx)"
|
||||
>
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
<script setup>
|
||||
import {getDefaultConversationData} from "~/utils/helper";
|
||||
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
path: '/:id?',
|
||||
keepalive: true
|
||||
})
|
||||
const route = useRoute()
|
||||
const conversation = ref({})
|
||||
const currentConversation = useConversation()
|
||||
const conversation = ref(getDefaultConversationData())
|
||||
watchEffect(() => {
|
||||
if (!route.params.id) {
|
||||
conversation.value = getDefaultConversationData()
|
||||
}
|
||||
})
|
||||
const loadMessage = async () => {
|
||||
conversation.value = Object.assign(conversation.value, conversation)
|
||||
conversation.value.loadingMessages = true
|
||||
const { data, error } = await useAuthFetch('/api/chat/messages/?conversationId=' + route.params.id)
|
||||
if (!error.value) {
|
||||
conversation.value.messages = data.value
|
||||
}
|
||||
conversation.value.loadingMessages = true
|
||||
conversation.value.loadingMessages = false
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (route.params.id) {
|
||||
conversation.value.id = parseInt(route.params.id)
|
||||
await loadMessage()
|
||||
}
|
||||
currentConversation.value = Object.assign({}, conversation.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
|
||||
export const getDefaultConversationData = () => {
|
||||
const { $i18n } = useNuxtApp()
|
||||
return {
|
||||
id: null,
|
||||
topic: null,
|
||||
topic: $i18n.t('defaultConversationTitle'),
|
||||
messages: [],
|
||||
loadingMessages: false,
|
||||
}
|
||||
@@ -19,34 +20,32 @@ export const getConversations = async () => {
|
||||
export const createNewConversation = () => {
|
||||
const conversation = useConversation()
|
||||
conversation.value = getDefaultConversationData()
|
||||
navigateTo('/')
|
||||
}
|
||||
|
||||
export const openConversationMessages = async (currentConversation) => {
|
||||
const conversation = useConversation()
|
||||
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 addConversation = (conversation) => {
|
||||
const conversations = useConversations()
|
||||
conversations.value = [conversation, ...conversations.value]
|
||||
}
|
||||
|
||||
|
||||
export const genTitle = async (conversationId) => {
|
||||
const { $i18n } = useNuxtApp()
|
||||
const { data, error } = await useAuthFetch('/api/gen_title/', {
|
||||
method: 'POST',
|
||||
body: {
|
||||
conversationId: conversationId
|
||||
conversationId: conversationId,
|
||||
prompt: $i18n.t('genTitlePrompt')
|
||||
}
|
||||
})
|
||||
if (!error.value) {
|
||||
const conversation = {
|
||||
id: conversationId,
|
||||
topic: data.value.title,
|
||||
}
|
||||
const conversations = useConversations()
|
||||
// prepend to conversations
|
||||
conversations.value = [conversation, ...conversations.value]
|
||||
let index = conversations.value.findIndex(item => item.id === conversationId)
|
||||
if (index === -1) {
|
||||
index = 0
|
||||
}
|
||||
conversations.value[index].topic = data.value.title
|
||||
return data.value.title
|
||||
}
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user