修改重新回答功能,撤回千面的问答内容为可编辑内容,撤回的内容不会增加额外的上下文

This commit is contained in:
清柯
2025-05-08 09:28:53 +08:00
parent 615515094b
commit 19099aed6f
3 changed files with 152 additions and 33 deletions

View File

@@ -29,7 +29,9 @@
</div>
</div>
</div>
<div class="content" v-html="content"></div>
<div class="content position-relative">
<div v-html="content"></div>
</div>
<div class="bar" v-if="data.created_at > 0">
<span class="bar-item"
><el-icon><Clock /></el-icon> {{ dateFormat(data.created_at) }}</span
@@ -71,7 +73,9 @@
</div>
</div>
<div class="content-wrapper">
<div class="content" v-html="content"></div>
<div class="content position-relative">
<div v-html="content"></div>
</div>
</div>
<div class="bar" v-if="data.created_at > 0">
<span class="bar-item"
@@ -88,7 +92,7 @@
import { FormatFileSize, GetFileIcon, GetFileType } from '@/store/system'
import { httpPost } from '@/utils/http'
import { dateFormat, isImage, processPrompt } from '@/utils/libs'
import { Clock } from '@element-plus/icons-vue'
import { Clock, Edit } from '@element-plus/icons-vue'
import hl from 'highlight.js'
import MarkdownIt from 'markdown-it'
import emoji from 'markdown-it-emoji'
@@ -144,6 +148,9 @@ const finalTokens = ref(props.data.tokens)
const content = ref(processPrompt(props.data.content))
const files = ref([])
// 定义emit事件
const emit = defineEmits(['edit'])
onMounted(() => {
processFiles()
})
@@ -475,4 +482,39 @@ const isExternalImg = (link, files) => {
}
}
.operations
display none
position absolute
right 5px
top 5px
.text-box
&:hover
.operations
display flex
gap 5px
.op-edit
cursor pointer
color #409eff
font-size 16px
&:hover
color darken(#409eff, 10%)
.position-relative {
position: relative;
}
.action-buttons {
position: absolute;
top: 10px;
right: 10px;
display: none;
}
.content:hover .action-buttons {
display: block;
}
</style>

View File

@@ -26,7 +26,7 @@
</el-tooltip>
</span>
<span v-if="!readOnly" class="flex">
<span class="bar-item" @click="reGenerate(data.prompt)">
<span class="bar-item" @click="reGenerate()">
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
<el-icon><Refresh /></el-icon>
</el-tooltip>
@@ -92,7 +92,7 @@
</el-tooltip>
</span>
<span v-if="!readOnly" class="flex">
<span class="bar-item bg" @click="reGenerate(data.prompt)">
<span class="bar-item bg" @click="reGenerate()">
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
<el-icon><Refresh /></el-icon>
</el-tooltip>
@@ -233,9 +233,8 @@ const stopSynthesis = () => {
}
// 重新生成
const reGenerate = (prompt) => {
console.log(prompt)
emits('regen', prompt)
const reGenerate = () => {
emits('regen')
}
</script>

View File

@@ -264,7 +264,7 @@
<welcome @send="autofillPrompt" />
</div>
<div v-for="item in chatData" :key="item.id" v-else>
<chat-prompt v-if="item.type === 'prompt'" :data="item" :list-style="listStyle" />
<chat-prompt v-if="item.type === 'prompt'" :data="item" :list-style="listStyle" @edit="editUserPrompt" />
<chat-reply
v-else-if="item.type === 'reply'"
:data="item"
@@ -1189,30 +1189,108 @@ const stopGenerate = function () {
}
// 重新生成
const reGenerate = function (prompt) {
disableInput(false)
const text = '重新回答下述问题:' + prompt
// 追加消息
chatData.value.push({
type: 'prompt',
id: randString(32),
icon: loginUser.value.avatar,
content: text,
})
store.socket.conn.send(
JSON.stringify({
channel: 'chat',
type: 'text',
body: {
role_id: roleId.value,
model_id: modelID.value,
chat_id: chatId.value,
content: text,
tools: toolSelected.value,
stream: stream.value,
},
})
)
const reGenerate = function () {
// 恢复发送按钮状态
canSend.value = true;
showStopGenerate.value = false;
// 查找最后的用户消息和AI回复并删除
if (chatData.value.length >= 2) {
// 从后往前找如果最后一条是AI回复再往前一条是用户消息
if (chatData.value[chatData.value.length - 1].type === 'reply') {
// 删除AI回复
chatData.value.pop();
// 如果此时最后一条是用户消息,也删除它
if (chatData.value.length > 0 && chatData.value[chatData.value.length - 1].type === 'prompt') {
// 保存用户消息内容,填入输入框
const userPrompt = chatData.value[chatData.value.length - 1].content;
// 删除用户消息
chatData.value.pop();
// 填入输入框
prompt.value = userPrompt;
}
}
}
// 将光标定位到输入框并聚焦
nextTick(() => {
if (inputRef.value) {
inputRef.value.focus();
// 触发输入事件以更新文本高度
onInput({ keyCode: null });
}
});
}
// 编辑用户消息
const editUserPrompt = function (messageId) {
// 找到要编辑的消息及其索引
let messageIndex = -1;
let messageContent = '';
for (let i = 0; i < chatData.value.length; i++) {
if (chatData.value[i].id === messageId) {
messageIndex = i;
messageContent = chatData.value[i].content;
break;
}
}
if (messageIndex === -1) return;
// 弹出编辑对话框
ElMessageBox.prompt('', '编辑消息', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: messageContent,
inputType: 'textarea',
customClass: 'edit-prompt-dialog',
roundButton: true
}).then(({ value }) => {
if (value.trim() === '') {
ElMessage.warning('消息内容不能为空');
return;
}
// 更新用户消息
chatData.value[messageIndex].content = value;
// 移除该消息之后的所有消息
chatData.value = chatData.value.slice(0, messageIndex + 1);
// 添加空回复消息
const _role = getRoleById(roleId.value);
chatData.value.push({
chat_id: chatId,
role_id: roleId.value,
type: 'reply',
id: randString(32),
icon: _role['icon'],
content: '',
});
disableInput(false);
// 发送编辑后的消息
store.socket.conn.send(
JSON.stringify({
channel: 'chat',
type: 'text',
body: {
role_id: roleId.value,
model_id: modelID.value,
chat_id: chatId.value,
content: value,
tools: toolSelected.value,
stream: stream.value,
edit_message: true
},
})
);
}).catch(() => {
// 取消编辑
});
}
const chatName = ref('')