Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class InstanceSerializer(serializers.Serializer):
# 是否使用流的形式输出
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"))
# 未查询到引用分段
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def execute_stream(self, message_list: List[BaseMessage],
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,
Expand Down
1 change: 1 addition & 0 deletions apps/application/flow/i_step_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def handler(self, workflow):
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
Expand Down
2 changes: 1 addition & 1 deletion apps/application/flow/workflow_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ def get_runtime_details(self, get_details=lambda n, index: n.get_details(index))
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
Expand Down
3 changes: 3 additions & 0 deletions apps/chat/serializers/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ def chat_simple(self, chat_info: ChatInfo, instance, base_to_response):
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:
Expand All @@ -350,6 +351,8 @@ def chat_simple(self, chat_info: ChatInfo, instance, base_to_response):
# 构建运行参数
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)
Expand Down
108 changes: 95 additions & 13 deletions ui/src/components/ai-chat/component/question-content/index.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<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">
<template v-for="(item, index) in document_list" :key="index">
<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>
Expand Down Expand Up @@ -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>
Expand All @@ -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"
Expand All @@ -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
})
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions ui/src/components/ai-chat/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading