mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-30 17:52:48 +00:00
feat: Support edit last question
This commit is contained in:
parent
fcaac9c11a
commit
592e429e3b
|
|
@ -69,6 +69,7 @@ class IChatStep(IBaseChatPipelineStep):
|
|||
# 是否使用流的形式输出
|
||||
stream = serializers.BooleanField(required=False, label=_("Streaming Output"))
|
||||
chat_user_id = serializers.CharField(required=True, label=_("Chat user id"))
|
||||
chat_record_id = serializers.CharField(required=False, label=_("Chat record id"))
|
||||
|
||||
chat_user_type = serializers.CharField(required=True, label=_("Chat user Type"))
|
||||
# 未查询到引用分段
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ class BaseChatStep(IChatStep):
|
|||
mcp_servers, mcp_source, tool_enable, tool_ids,
|
||||
application_enable, application_ids,
|
||||
mcp_output_enable)
|
||||
chat_record_id = uuid.uuid7()
|
||||
chat_record_id = self.context.get('step_args',{}).get('chat_record_id') if self.context.get('step_args',{}).get('chat_record_id') else uuid.uuid7()
|
||||
r = StreamingHttpResponse(
|
||||
streaming_content=event_content(chat_result, chat_id, chat_record_id, paragraph_list,
|
||||
post_response_handler, manage, self, chat_model, message_list, problem_text,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class WorkFlowPostHandler:
|
|||
answer_text_list)
|
||||
if workflow.chat_record is not None:
|
||||
chat_record = workflow.chat_record
|
||||
chat_record.problem_text = question
|
||||
chat_record.answer_text = answer_text
|
||||
chat_record.details = details
|
||||
chat_record.message_tokens = message_tokens
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ class WorkflowManage:
|
|||
details_result = {}
|
||||
for index in range(len(self.node_context)):
|
||||
node = self.node_context[index]
|
||||
if self.chat_record is not None and self.chat_record.details is not None:
|
||||
if self.chat_record is not None and self.chat_record.details is not None and self.start_node:
|
||||
details = self.chat_record.details.get(node.runtime_node_id)
|
||||
if details is not None and self.start_node.runtime_node_id != node.runtime_node_id:
|
||||
details_result[node.runtime_node_id] = details
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ class ChatSerializers(serializers.Serializer):
|
|||
chat_user_id = self.data.get('chat_user_id')
|
||||
chat_user_type = self.data.get('chat_user_type')
|
||||
form_data = instance.get("form_data")
|
||||
chat_record_id = instance.get('chat_record_id')
|
||||
pipeline_manage_builder = PipelineManage.builder()
|
||||
# 如果开启了问题优化,则添加上问题优化步骤
|
||||
if chat_info.application.problem_optimization:
|
||||
|
|
@ -350,6 +351,8 @@ class ChatSerializers(serializers.Serializer):
|
|||
# 构建运行参数
|
||||
params = chat_info.to_pipeline_manage_params(message, get_post_handler(chat_info), exclude_paragraph_id_list,
|
||||
chat_user_id, chat_user_type, stream, form_data)
|
||||
if chat_record_id:
|
||||
params['chat_record_id'] = chat_record_id
|
||||
chat_info.set_chat(message)
|
||||
# 运行流水线作业
|
||||
pipeline_message.run(params)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<!-- 问题内容 -->
|
||||
<div class="question-content item-content mb-16 lighter">
|
||||
<div class="content p-12-16 border-r-8" :class="getClassName">
|
||||
<div class="question-content item-content mb-4 lighter">
|
||||
<div v-if="!isReQuestion" class="content p-12-16 border-r-8" :class="getClassName">
|
||||
<div class="text break-all pre-wrap">
|
||||
<div class="mb-8" v-if="document_list.length">
|
||||
<el-space wrap class="w-full media-file-width">
|
||||
|
|
@ -9,12 +9,12 @@
|
|||
<el-card shadow="never" style="--el-card-padding: 8px" class="download-file cursor">
|
||||
<div class="download-button flex align-center" @click="downloadFile(item)">
|
||||
<el-icon class="mr-4">
|
||||
<Download/>
|
||||
<Download />
|
||||
</el-icon>
|
||||
{{ $t('chat.download') }}
|
||||
</div>
|
||||
<div class="show flex align-center">
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24"/>
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
||||
{{ item && item?.name }}
|
||||
</div>
|
||||
|
|
@ -78,12 +78,12 @@
|
|||
<el-card shadow="never" style="--el-card-padding: 8px" class="download-file cursor">
|
||||
<div class="download-button flex align-center" @click="downloadFile(item)">
|
||||
<el-icon class="mr-4">
|
||||
<Download/>
|
||||
<Download />
|
||||
</el-icon>
|
||||
{{ $t('chat.download') }}
|
||||
</div>
|
||||
<div class="show flex align-center">
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24"/>
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
||||
{{ item && item?.name }}
|
||||
</div>
|
||||
|
|
@ -95,6 +95,20 @@
|
|||
<span> {{ chatRecord.problem_text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-input v-else v-model="editText">
|
||||
<template #append>
|
||||
<div class="flex" style="gap: 8px">
|
||||
<el-button-group class="flex ml-8 mr-8">
|
||||
<el-button class="flex mr-8" text @click="cancelReQuestion"
|
||||
><el-icon><Close /></el-icon
|
||||
></el-button>
|
||||
<el-button :disabled="!editText.trim()" text @click="sendReQuestionMessage(chatRecord)">
|
||||
<el-icon><Comment /></el-icon>
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="avatar ml-8" v-if="showAvatar">
|
||||
<el-image
|
||||
v-if="application.user_avatar"
|
||||
|
|
@ -104,23 +118,51 @@
|
|||
style="width: 28px; height: 28px; display: block"
|
||||
/>
|
||||
<el-avatar v-else :size="28">
|
||||
<img src="@/assets/user-icon.svg" style="width: 50%" alt=""/>
|
||||
<img src="@/assets/user-icon.svg" style="width: 50%" alt="" />
|
||||
</el-avatar>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-right mb-8"
|
||||
:style="{
|
||||
'padding-right': showAvatar ? '36px' : '0',
|
||||
}"
|
||||
v-if="!isReQuestion"
|
||||
>
|
||||
<div class="text-right">
|
||||
<el-tooltip effect="dark" :content="$t('common.edit')" placement="top" v-if="props.isLast">
|
||||
<el-button text @click="handleEdit(chatRecord)">
|
||||
<AppIcon iconName="app-edit"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="$t('common.copy')" placement="top">
|
||||
<el-button text @click="copyClick(chatRecord?.problem_text)">
|
||||
<AppIcon iconName="app-copy"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {type chatType} from '@/api/type/application'
|
||||
import {getImgUrl, downloadByURL} from '@/utils/common'
|
||||
import {getAttrsArray} from '@/utils/array'
|
||||
import {onMounted, computed} from 'vue'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
import { getImgUrl, downloadByURL } from '@/utils/common'
|
||||
import { getAttrsArray } from '@/utils/array'
|
||||
import { onMounted, computed, ref } from 'vue'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
|
||||
const props = defineProps<{
|
||||
application: any
|
||||
chatRecord: chatType
|
||||
chatManagement: any
|
||||
sendMessage: (question: string, other_params_data?: any, chat?: chatType) => Promise<boolean>
|
||||
type: 'log' | 'ai-chat' | 'debug-ai-chat'
|
||||
isLast: boolean
|
||||
}>()
|
||||
|
||||
const isReQuestion = ref<boolean>(false)
|
||||
const editText = ref<string>('')
|
||||
const direction = ref<'horizontal' | 'vertical'>('horizontal')
|
||||
|
||||
const showAvatar = computed(() => {
|
||||
return props.application.show_user_avatar == undefined ? true : props.application.show_user_avatar
|
||||
})
|
||||
|
|
@ -184,8 +226,48 @@ function downloadFile(item: any) {
|
|||
downloadByURL(item.url, item.name)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
function handleEdit(chatRecord: any) {
|
||||
isReQuestion.value = true
|
||||
editText.value = chatRecord.problem_text
|
||||
}
|
||||
|
||||
const cancelReQuestion = () => {
|
||||
isReQuestion.value = false
|
||||
}
|
||||
|
||||
const emit = defineEmits(['reQuestion'])
|
||||
|
||||
function sendReQuestionMessage(chat: chatType) {
|
||||
const container = props.chatRecord?.upload_meta
|
||||
? props.chatRecord.upload_meta
|
||||
: props.chatRecord.execution_details?.find((detail) => detail.type === 'start-node')
|
||||
|
||||
props.chatRecord.problem_text = editText.value
|
||||
reset_answer_text_list(props.chatRecord.answer_text_list)
|
||||
props.chatRecord.write_ed = false
|
||||
|
||||
isReQuestion.value = false
|
||||
props.sendMessage(
|
||||
editText.value,
|
||||
{
|
||||
re_chat: true,
|
||||
image_list: container?.image_list || [],
|
||||
document_list: container?.document_list || [],
|
||||
audio_list: container?.audio_list || [],
|
||||
video_list: container?.video_list || [],
|
||||
other_list: container?.other_list || [],
|
||||
chat_record_id: props.chatRecord.record_id ? props.chatRecord.record_id : props.chatRecord.id,
|
||||
},
|
||||
{ ...props.chatRecord, problem_text: editText.value },
|
||||
)
|
||||
}
|
||||
|
||||
const reset_answer_text_list = (answer_text_list: any) => {
|
||||
answer_text_list.splice(0, answer_text_list.length)
|
||||
answer_text_list.push([])
|
||||
}
|
||||
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.question-content {
|
||||
|
|
|
|||
|
|
@ -36,9 +36,12 @@
|
|||
<template v-for="(item, index) in chatList" :key="index">
|
||||
<!-- 问题 -->
|
||||
<QuestionContent
|
||||
:chat-management="ChatManagement"
|
||||
:type="type"
|
||||
:application="applicationDetails"
|
||||
:send-message="sendMessage"
|
||||
:chat-record="item"
|
||||
:is-last="index >= chatList.length - 1"
|
||||
></QuestionContent>
|
||||
<!-- 回答 -->
|
||||
<AnswerContent
|
||||
|
|
|
|||
Loading…
Reference in New Issue