feat: Support converting text prompts (#2702)
This commit is contained in:
parent
7145f303da
commit
3797613182
@ -529,6 +529,7 @@ const uploadRecording = async (audioBlob: Blob) => {
|
|||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', audioBlob, 'recording.mp3')
|
formData.append('file', audioBlob, 'recording.mp3')
|
||||||
|
bus.emit('on:transcribing', true)
|
||||||
applicationApi
|
applicationApi
|
||||||
.postSpeechToText(props.applicationDetails.id as string, formData, localLoading)
|
.postSpeechToText(props.applicationDetails.id as string, formData, localLoading)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@ -548,6 +549,7 @@ const uploadRecording = async (audioBlob: Blob) => {
|
|||||||
recorderLoading.value = false
|
recorderLoading.value = false
|
||||||
console.error(`${t('chat.uploadFile.errorMessage')}:`, error)
|
console.error(`${t('chat.uploadFile.errorMessage')}:`, error)
|
||||||
})
|
})
|
||||||
|
.finally(() => bus.emit('on:transcribing', false))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
recorderLoading.value = false
|
recorderLoading.value = false
|
||||||
console.error(`${t('chat.uploadFile.errorMessage')}:`, error)
|
console.error(`${t('chat.uploadFile.errorMessage')}:`, error)
|
||||||
|
|||||||
105
ui/src/components/ai-chat/component/transition-content/index.vue
Normal file
105
ui/src/components/ai-chat/component/transition-content/index.vue
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 问题内容 -->
|
||||||
|
<div class="question-content item-content mb-16 lighter">
|
||||||
|
<div class="content p-12-16 border-r-8">
|
||||||
|
<span> {{ text }}</span
|
||||||
|
><span class="dotting"></span>
|
||||||
|
</div>
|
||||||
|
<div class="avatar ml-8" v-if="application.show_user_avatar">
|
||||||
|
<el-image
|
||||||
|
v-if="application.user_avatar"
|
||||||
|
:src="application.user_avatar"
|
||||||
|
alt=""
|
||||||
|
fit="cover"
|
||||||
|
style="width: 28px; height: 28px; display: block"
|
||||||
|
/>
|
||||||
|
<AppAvatar v-else>
|
||||||
|
<img src="@/assets/user-icon.svg" style="width: 50%" alt="" />
|
||||||
|
</AppAvatar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
text: string
|
||||||
|
application: any
|
||||||
|
type: 'log' | 'ai-chat' | 'debug-ai-chat'
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.question-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-left: var(--padding-left);
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background: #d6e2ff;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-file {
|
||||||
|
height: 43px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
border: 1px solid var(--el-color-primary);
|
||||||
|
|
||||||
|
.download-button {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.media-file-width {
|
||||||
|
:deep(.el-space__item) {
|
||||||
|
min-width: 40% !important;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.media_2 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.media_0 {
|
||||||
|
flex: inherit;
|
||||||
|
}
|
||||||
|
.media_1 {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.question-content {
|
||||||
|
.media-file-width {
|
||||||
|
:deep(.el-space__item) {
|
||||||
|
min-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.media_1 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.debug-ai-chat {
|
||||||
|
.question-content {
|
||||||
|
.media-file-width {
|
||||||
|
:deep(.el-space__item) {
|
||||||
|
min-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.media_1 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -47,6 +47,12 @@
|
|||||||
:chat-management="ChatManagement"
|
:chat-management="ChatManagement"
|
||||||
></AnswerContent>
|
></AnswerContent>
|
||||||
</template>
|
</template>
|
||||||
|
<TransitionContent
|
||||||
|
v-if="transcribing"
|
||||||
|
:text="t('chat.transcribing')"
|
||||||
|
:type="type"
|
||||||
|
:application="applicationDetails"
|
||||||
|
></TransitionContent>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
||||||
@ -94,14 +100,17 @@ import { ChatManagement, type chatType } from '@/api/type/application'
|
|||||||
import { randomId } from '@/utils/utils'
|
import { randomId } from '@/utils/utils'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { isWorkFlow } from '@/utils/application'
|
import { isWorkFlow } from '@/utils/application'
|
||||||
import { debounce, first } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import AnswerContent from '@/components/ai-chat/component/answer-content/index.vue'
|
import AnswerContent from '@/components/ai-chat/component/answer-content/index.vue'
|
||||||
import QuestionContent from '@/components/ai-chat/component/question-content/index.vue'
|
import QuestionContent from '@/components/ai-chat/component/question-content/index.vue'
|
||||||
|
import TransitionContent from '@/components/ai-chat/component/transition-content/index.vue'
|
||||||
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/index.vue'
|
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/index.vue'
|
||||||
import PrologueContent from '@/components/ai-chat/component/prologue-content/index.vue'
|
import PrologueContent from '@/components/ai-chat/component/prologue-content/index.vue'
|
||||||
import UserForm from '@/components/ai-chat/component/user-form/index.vue'
|
import UserForm from '@/components/ai-chat/component/user-form/index.vue'
|
||||||
import Control from '@/components/ai-chat/component/control/index.vue'
|
import Control from '@/components/ai-chat/component/control/index.vue'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
import bus from '@/bus'
|
||||||
|
const transcribing = ref<boolean>(false)
|
||||||
defineOptions({ name: 'AiChat' })
|
defineOptions({ name: 'AiChat' })
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const {
|
const {
|
||||||
@ -498,6 +507,9 @@ const handleScroll = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.speechSynthesis.cancel()
|
window.speechSynthesis.cancel()
|
||||||
window.sendMessage = sendMessage
|
window.sendMessage = sendMessage
|
||||||
|
bus.on('on:transcribing', (status: boolean) => {
|
||||||
|
transcribing.value = status
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export default {
|
|||||||
userInput: 'User Input',
|
userInput: 'User Input',
|
||||||
quote: 'Quote',
|
quote: 'Quote',
|
||||||
download: 'Click to Download',
|
download: 'Click to Download',
|
||||||
|
transcribing: 'Transcribing',
|
||||||
passwordValidator: {
|
passwordValidator: {
|
||||||
title: 'Enter Password to Access',
|
title: 'Enter Password to Access',
|
||||||
errorMessage1: 'Password cannot be empty',
|
errorMessage1: 'Password cannot be empty',
|
||||||
@ -24,13 +25,15 @@ export default {
|
|||||||
cancelOppose: 'Undo Dislike',
|
cancelOppose: 'Undo Dislike',
|
||||||
continue: 'Continue',
|
continue: 'Continue',
|
||||||
stopChat: 'Stop Response',
|
stopChat: 'Stop Response',
|
||||||
startChat: 'Start Chat',
|
startChat: 'Start Chat'
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
error500Message: 'Sorry, the service is currently under maintenance. Please try again later!',
|
error500Message: 'Sorry, the service is currently under maintenance. Please try again later!',
|
||||||
errorIdentifyMessage: 'Unable to verify user identity',
|
errorIdentifyMessage: 'Unable to verify user identity',
|
||||||
errorLimitMessage: 'Sorry, you have reached the maximum number of questions. Please try again tomorrow!',
|
errorLimitMessage:
|
||||||
answerMessage: 'Sorry, no relevant content found. Please rephrase your question or provide more details.',
|
'Sorry, you have reached the maximum number of questions. Please try again tomorrow!',
|
||||||
|
answerMessage:
|
||||||
|
'Sorry, no relevant content found. Please rephrase your question or provide more details.',
|
||||||
stopAnswer: 'Response Stopped',
|
stopAnswer: 'Response Stopped',
|
||||||
answerLoading: 'Generating Response...',
|
answerLoading: 'Generating Response...',
|
||||||
recorderTip: `<p>This feature requires microphone access. Browsers block recording on insecure pages. Solutions:<br/>
|
recorderTip: `<p>This feature requires microphone access. Browsers block recording on insecure pages. Solutions:<br/>
|
||||||
@ -92,5 +95,5 @@ export default {
|
|||||||
question: 'User Question',
|
question: 'User Question',
|
||||||
optimizationQuestion: 'Optimized Question'
|
optimizationQuestion: 'Optimized Question'
|
||||||
},
|
},
|
||||||
editTitle: 'Edit Title',
|
editTitle: 'Edit Title'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export default {
|
|||||||
userInput: '用户输入',
|
userInput: '用户输入',
|
||||||
quote: '引用',
|
quote: '引用',
|
||||||
download: '点击下载文件',
|
download: '点击下载文件',
|
||||||
|
transcribing: '转文字中',
|
||||||
passwordValidator: {
|
passwordValidator: {
|
||||||
title: '请输入密码打开链接',
|
title: '请输入密码打开链接',
|
||||||
errorMessage1: '密码不能为空',
|
errorMessage1: '密码不能为空',
|
||||||
@ -24,7 +25,7 @@ export default {
|
|||||||
cancelOppose: '取消反对',
|
cancelOppose: '取消反对',
|
||||||
continue: '继续',
|
continue: '继续',
|
||||||
stopChat: '停止回答',
|
stopChat: '停止回答',
|
||||||
startChat: '开始对话',
|
startChat: '开始对话'
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
|
||||||
@ -92,5 +93,5 @@ export default {
|
|||||||
question: '用户问题',
|
question: '用户问题',
|
||||||
optimizationQuestion: '优化后问题'
|
optimizationQuestion: '优化后问题'
|
||||||
},
|
},
|
||||||
editTitle: '编辑标题',
|
editTitle: '编辑标题'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export default {
|
|||||||
userInput: '用戶輸入',
|
userInput: '用戶輸入',
|
||||||
quote: '引用',
|
quote: '引用',
|
||||||
download: '點擊下載文件',
|
download: '點擊下載文件',
|
||||||
|
transcribing: '轉文字中',
|
||||||
passwordValidator: {
|
passwordValidator: {
|
||||||
title: '請輸入密碼打開連結',
|
title: '請輸入密碼打開連結',
|
||||||
errorMessage1: '密碼不能為空',
|
errorMessage1: '密碼不能為空',
|
||||||
@ -24,7 +25,7 @@ export default {
|
|||||||
cancelOppose: '取消反對',
|
cancelOppose: '取消反對',
|
||||||
continue: '繼續',
|
continue: '繼續',
|
||||||
stopChat: '停止回答',
|
stopChat: '停止回答',
|
||||||
startChat: '開始對話',
|
startChat: '開始對話'
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
error500Message: '抱歉,當前正在維護,無法提供服務,請稍後再試!',
|
error500Message: '抱歉,當前正在維護,無法提供服務,請稍後再試!',
|
||||||
@ -92,5 +93,5 @@ export default {
|
|||||||
question: '用戶問題',
|
question: '用戶問題',
|
||||||
optimizationQuestion: '優化後問題'
|
optimizationQuestion: '優化後問題'
|
||||||
},
|
},
|
||||||
editTitle: '編輯標題',
|
editTitle: '編輯標題'
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user