fit chat restart (#107)
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minor",
|
||||
"comment": "fix chat restart",
|
||||
"packageName": "@acedatacloud/nexior",
|
||||
"email": "1348977728@qq.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
||||
@@ -56,6 +56,14 @@
|
||||
</div>
|
||||
<div class="operations">
|
||||
<copy-to-clipboard v-if="!Array.isArray(message.content)" :content="message.content!" class="btn-copy" />
|
||||
<restart-to-generate
|
||||
v-if="
|
||||
!Array.isArray(message.content) && message.role === 'assistant' && message === messages[messages.length - 1]
|
||||
"
|
||||
class="btn-restart"
|
||||
:messages="messages"
|
||||
@restart="sendRestart"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-alert v-else class="error" :title="errorText" type="error" :closable="false" />
|
||||
@@ -73,7 +81,8 @@ import { ElAlert, ElButton, ElImage, ElTooltip, ElInput } from 'element-plus';
|
||||
import MarkdownRenderer from '@/components/common/MarkdownRenderer.vue';
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
import { IApplication, IChatMessage, IChatMessageState } from '@/models';
|
||||
import CopyToClipboard from '../common/CopyToClipboard.vue';
|
||||
import CopyToClipboard from '@/components/common/CopyToClipboard.vue';
|
||||
import RestartToGenerate from '@/components/common/RestartToGenerate.vue';
|
||||
import {
|
||||
ERROR_CODE_API_ERROR,
|
||||
ERROR_CODE_BAD_REQUEST,
|
||||
@@ -98,6 +107,7 @@ export default defineComponent({
|
||||
name: 'Message',
|
||||
components: {
|
||||
CopyToClipboard,
|
||||
RestartToGenerate,
|
||||
AnsweringMark,
|
||||
MarkdownRenderer,
|
||||
ElAlert,
|
||||
@@ -108,6 +118,11 @@ export default defineComponent({
|
||||
ElInput
|
||||
},
|
||||
props: {
|
||||
messages: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
message: {
|
||||
type: Object as () => IChatMessage,
|
||||
required: true
|
||||
@@ -117,7 +132,7 @@ export default defineComponent({
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['stop', 'update:messages', 'edit'],
|
||||
emits: ['stop', 'edit', 'restart'],
|
||||
data(): IData {
|
||||
return {
|
||||
copied: false,
|
||||
@@ -165,6 +180,10 @@ export default defineComponent({
|
||||
cancelEdit() {
|
||||
this.isEditing = false;
|
||||
},
|
||||
sendRestart() {
|
||||
// Implement the logic to save the edited content
|
||||
this.$emit('restart', this.message);
|
||||
},
|
||||
sendEdit() {
|
||||
// Implement the logic to save the edited content
|
||||
this.isEditing = false;
|
||||
@@ -312,7 +331,13 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.operations {
|
||||
display: block;
|
||||
display: flex; // Use flexbox for better alignment
|
||||
gap: 10px; // Adjust the gap value as needed
|
||||
margin-left: 5px; // Adjust the value as needed
|
||||
.btn-restart {
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 14px;
|
||||
}
|
||||
.btn-copy {
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 14px;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<font-awesome-icon v-if="!copied" icon="fa-regular fa-copy" class="icon-copy" @click="onCopy" />
|
||||
<el-tooltip v-if="!copied" effect="dark" :content="$t('common.button.copy')" placement="top-start">
|
||||
<font-awesome-icon icon="fa-regular fa-copy" class="icon-copy" @click="onCopy"
|
||||
/></el-tooltip>
|
||||
|
||||
<el-tooltip v-else :visible="copied" effect="dark" :content="$t('common.message.copied')" placement="top-start">
|
||||
<font-awesome-icon icon="fa-solid fa-check" class="icon-check" />
|
||||
</el-tooltip>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<el-tooltip effect="dark" :content="$t('common.button.restart')" placement="top-start">
|
||||
<font-awesome-icon icon="fa-solid fa-sync" class="icon-sync" @click="onRestart" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
import { ElTooltip } from 'element-plus';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CopyToClipboard',
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
ElTooltip
|
||||
},
|
||||
props: {
|
||||
messages: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: ['restart'],
|
||||
data() {
|
||||
return {
|
||||
copied: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onRestart() {
|
||||
this.$emit('restart');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-check,
|
||||
.icon-copy {
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
@@ -3,6 +3,14 @@
|
||||
"message": "设置",
|
||||
"description": "按钮文本,用于设置某些内容"
|
||||
},
|
||||
"button.copy": {
|
||||
"message": "复制该消息",
|
||||
"description": "按钮文本,用于设置某些内容"
|
||||
},
|
||||
"button.restart": {
|
||||
"message": "重新生成",
|
||||
"description": "按钮文本,用于设置某些内容"
|
||||
},
|
||||
"button.preview": {
|
||||
"message": "预览",
|
||||
"description": "按钮文本,用于通过URL打开预览某个文件"
|
||||
@@ -123,10 +131,6 @@
|
||||
"message": "查看",
|
||||
"description": "按钮文本,用于查看某些内容"
|
||||
},
|
||||
"button.copy": {
|
||||
"message": "复制",
|
||||
"description": "按钮文本,用于复制某些内容"
|
||||
},
|
||||
"button.create": {
|
||||
"message": "创建",
|
||||
"description": "按钮文本,用于创建某些内容"
|
||||
@@ -195,6 +199,10 @@
|
||||
"message": "已成功复制",
|
||||
"description": "用于显示内容已成功复制的消息"
|
||||
},
|
||||
"message.restart": {
|
||||
"message": "重新生成",
|
||||
"description": "用于显示内容已成功复制的消息"
|
||||
},
|
||||
"message.confirmDelete": {
|
||||
"message": "确定要删除吗?",
|
||||
"description": "用于确认用户是否要删除某些内容的消息"
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
:application="application"
|
||||
class="message"
|
||||
@update:question="question = $event"
|
||||
@update:messages="messages = $event"
|
||||
@edit="onEdit"
|
||||
@restart="onRestart"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,6 +59,7 @@ import { chatOperator } from '@/operators';
|
||||
import ApplicationStatus from '@/components/application/Status.vue';
|
||||
|
||||
export interface IData {
|
||||
drawer: boolean;
|
||||
question: string;
|
||||
references: string[];
|
||||
answering: boolean;
|
||||
@@ -77,6 +78,7 @@ export default defineComponent({
|
||||
},
|
||||
data(): IData {
|
||||
return {
|
||||
drawer: false,
|
||||
question: '',
|
||||
references: [],
|
||||
answering: false,
|
||||
@@ -159,6 +161,84 @@ export default defineComponent({
|
||||
this.question = question;
|
||||
this.onSubmit();
|
||||
},
|
||||
async onRestart(targetMessage: IChatMessage) {
|
||||
// 1. Clear the following message
|
||||
const targetIndex = this.messages.findIndex((message) => message === targetMessage);
|
||||
const problem_message = this.messages[targetIndex - 1];
|
||||
if (targetIndex !== -1) {
|
||||
this.messages = this.messages.slice(0, targetIndex - 1);
|
||||
// @ts-ignore
|
||||
this.question = problem_message.content;
|
||||
}
|
||||
|
||||
// 2. Update the messages
|
||||
const token = this.credential?.token;
|
||||
const question = this.question;
|
||||
// reset question and references
|
||||
if (!token || !question) {
|
||||
console.error('no token or endpoint or question');
|
||||
this.messages.push({
|
||||
error: {
|
||||
code: ERROR_CODE_NOT_APPLIED
|
||||
},
|
||||
role: ROLE_ASSISTANT,
|
||||
state: IChatMessageState.FAILED
|
||||
});
|
||||
return;
|
||||
}
|
||||
let conversationId = this.conversationId;
|
||||
chatOperator
|
||||
.updateConversation(
|
||||
{
|
||||
id: this.conversationId,
|
||||
messages: this.messages
|
||||
},
|
||||
{
|
||||
token
|
||||
}
|
||||
)
|
||||
.then(async () => {
|
||||
await this.$store.dispatch('chat/setConversation', {
|
||||
id: conversationId,
|
||||
messages: this.messages
|
||||
});
|
||||
console.debug('finished update conversation', this.messages);
|
||||
this.messages.push({
|
||||
content: this.question,
|
||||
role: ROLE_USER
|
||||
});
|
||||
// 3. Send restart questions
|
||||
console.debug('onRestart', this.question);
|
||||
await this.onFetchAnswer();
|
||||
})
|
||||
.catch((error) => {
|
||||
if (this.messages && this.messages.length > 0) {
|
||||
this.messages[this.messages.length - 1].state = IChatMessageState.FAILED;
|
||||
}
|
||||
console.error(error);
|
||||
if (axios.isCancel(error)) {
|
||||
this.messages[this.messages.length - 1].error = {
|
||||
code: ERROR_CODE_CANCELED
|
||||
};
|
||||
} else if (error?.response?.data) {
|
||||
let data = error?.response?.data;
|
||||
if (isJSONString(data)) {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
console.debug('error', data);
|
||||
if (this.messages && this.messages.length > 0) {
|
||||
this.messages[this.messages.length - 1].error = data.error;
|
||||
}
|
||||
} else {
|
||||
if (this.messages && this.messages.length > 0) {
|
||||
this.messages[this.messages.length - 1].error = {
|
||||
code: ERROR_CODE_UNKNOWN
|
||||
};
|
||||
}
|
||||
}
|
||||
this.answering = false;
|
||||
});
|
||||
},
|
||||
async onEdit(targetMessage: IChatMessage, questionValue: string) {
|
||||
// 1. Clear the following message
|
||||
const targetIndex = this.messages.findIndex((message) => message === targetMessage);
|
||||
@@ -342,6 +422,7 @@ export default defineComponent({
|
||||
id: conversationId,
|
||||
messages: this.messages
|
||||
});
|
||||
console.log('messages', JSON.stringify(this.messages));
|
||||
this.answering = false;
|
||||
if (!this.conversationId) {
|
||||
await this.$router.push({
|
||||
@@ -395,6 +476,17 @@ export default defineComponent({
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
.setting {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.setting {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dialogue {
|
||||
flex: 1;
|
||||
@@ -409,6 +501,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '@fortawesome/free-regular-svg-icons';
|
||||
import { faDiscord as faBrandsDiscord, faWeixin as faBrandsWeixin } from '@fortawesome/free-brands-svg-icons';
|
||||
import {
|
||||
faSync as faSolidSync,
|
||||
faDownload as faSolidDownload,
|
||||
faMusic as faSolidMusic,
|
||||
faLanguage as faSolidLanguage,
|
||||
@@ -73,6 +74,7 @@ import {
|
||||
faWandMagic as faSolidWandMagic,
|
||||
faAngleDown as faSolidAngleDown
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
library.add(faSolidSync);
|
||||
library.add(faSolidMusic);
|
||||
library.add(faRegularCopy);
|
||||
library.add(faRegularMessage);
|
||||
|
||||
Reference in New Issue
Block a user