Commit 25671c81 authored by nick zheng's avatar nick zheng

Merge branch 'beta' into 'master'

feat: 多模型测试

See merge request !31
parents eb581b8c 32eb29f4
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
name="viewport" name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/> />
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_4711453_vrea727r3s.css" /> <link rel="stylesheet" href="//at.alicdn.com/t/c/font_4711453_egfmzk2ywd.css" />
<title>SuperLink</title> <title>SuperLink</title>
</head> </head>
......
export interface DiversityModeItem {
label: string
value: string
topP: number
temperature: number
communicationTurn: number
}
export const diversityModeList: DiversityModeItem[] = [
{
label: 'common_module.accurate_mode',
value: 'accurate',
topP: 0.1,
temperature: 0.1,
communicationTurn: 3,
},
{
label: 'common_module.balance_mode',
value: 'balance',
topP: 0.7,
temperature: 0.5,
communicationTurn: 3,
},
{
label: 'common_module.creative_mode',
value: 'creative',
topP: 0.7,
temperature: 0.95,
communicationTurn: 3,
},
{
label: 'common_module.custom',
value: 'custom',
topP: 0.5,
temperature: 0.8,
communicationTurn: 3,
},
]
...@@ -53,6 +53,11 @@ common_module: ...@@ -53,6 +53,11 @@ common_module:
select_all: '全选' select_all: '全选'
quit: '退出' quit: '退出'
retry: '重试' retry: '重试'
currently: '当前'
multi_model_debug: '多模型调试'
accurate_mode: '精准模式'
balance_mode: '平衡模式'
creative_mode: '创意模式'
dialogue_module: dialogue_module:
continue_question_message: '你可以继续提问' continue_question_message: '你可以继续提问'
...@@ -124,6 +129,7 @@ router_title_module: ...@@ -124,6 +129,7 @@ router_title_module:
upload_knowledge_document: '上传知识库文档' upload_knowledge_document: '上传知识库文档'
knowledge_document_list: '知识库文档列表' knowledge_document_list: '知识库文档列表'
knowledge_document_detail: '知识库文档详情' knowledge_document_detail: '知识库文档详情'
multi_model_dialogue: '多模型调试'
personal_space_module: personal_space_module:
title: '个人空间' title: '个人空间'
...@@ -297,3 +303,17 @@ share_agent_module: ...@@ -297,3 +303,17 @@ share_agent_module:
create_agent_dialogue_title: '温馨提示' create_agent_dialogue_title: '温馨提示'
create_agent_dialogue_content: '为保证您的体验,请通过pc端访问' create_agent_dialogue_content: '为保证您的体验,请通过pc端访问'
create_agent_dialogue_positive_text: '我知道啦' create_agent_dialogue_positive_text: '我知道啦'
multi_model_dialogue_module:
not_find_agent: '应用不存在'
add_model: '增加模型'
quit_test: '退出测试'
model_setting: '模型设置'
agent_system: '系统人设'
remove_dialogue: '移除'
one_click_configuration: '一键配置'
select_model: '选择模型'
please_select_model: '请选择模型'
please_select_model_first: '请先选择模型'
replace_configuration_tip: '是否将该模型的配置覆盖到原来的配置项上'
open_new_conversation: '已开启新会话'
...@@ -53,6 +53,11 @@ common_module: ...@@ -53,6 +53,11 @@ common_module:
select_all: '全選' select_all: '全選'
quit: '退出' quit: '退出'
retry: '重試' retry: '重試'
currently: '當前'
multi_model_debug: '多模型調試'
accurate_mode: '精準模式'
balance_mode: '平衡模式'
creative_mode: '創意模式'
dialogue_module: dialogue_module:
continue_question_message: '你可以繼續提問' continue_question_message: '你可以繼續提問'
...@@ -124,6 +129,7 @@ router_title_module: ...@@ -124,6 +129,7 @@ router_title_module:
upload_knowledge_document: '上傳知識庫文檔' upload_knowledge_document: '上傳知識庫文檔'
knowledge_document_list: '知識庫文檔列表' knowledge_document_list: '知識庫文檔列表'
knowledge_document_detail: '知識庫文檔詳情' knowledge_document_detail: '知識庫文檔詳情'
multi_model_dialogue: '多模型調試'
personal_space_module: personal_space_module:
title: '個人空間' title: '個人空間'
...@@ -297,3 +303,17 @@ share_agent_module: ...@@ -297,3 +303,17 @@ share_agent_module:
create_agent_dialogue_title: '溫馨提示' create_agent_dialogue_title: '溫馨提示'
create_agent_dialogue_content: '爲保證您的體驗,請通過pc端訪問' create_agent_dialogue_content: '爲保證您的體驗,請通過pc端訪問'
create_agent_dialogue_positive_text: '我知道啦' create_agent_dialogue_positive_text: '我知道啦'
multi_model_dialogue_module:
not_find_agent: '應用不存在'
add_model: '增加模型'
quit_test: '退出測試'
model_setting: '模型設置'
agent_system: '系統人設'
remove_dialogue: '移除'
one_click_configuration: '一鍵配置'
select_model: '選擇模型'
please_select_model: '請選擇模型'
please_select_model_first: '請先選擇模型'
replace_configuration_tip: '是否將該模型的配置覆蓋到原來的配置項上'
open_new_conversation: '已開啓新會話'
import { type RouteRecordRaw } from 'vue-router'
export default [
{
path: '/multi-model-dialogue/:agentId?',
name: 'MultiModelDialogue',
meta: {
rank: 1001,
title: 'router_title_module.multi_model_dialogue',
hideSideMenItem: true,
ignoreAuth: true,
},
component: () => import('@/views/multi-model-dialogue/multi-model-dialogue.vue'),
},
] as RouteRecordRaw[]
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { nanoid } from 'nanoid'
import { throttle } from 'lodash-es'
import { MessageItemInterface, MultiModelDialogueItem, QuestionMessageItem } from '../types'
import { fetchCustomEventSource } from '@/composables/useEventSource'
import Message from '@/components/custom-message/message'
const { t } = useI18n()
interface Props {
agentId: string
isAnswerResponseWait: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
addQuestionMessageItem: [messageId: string, messageItem: MessageItemInterface]
addAnswerMessageItem: [messageId: string, messageItem: MessageItemInterface, index: number]
updateMessageItem: [messageId: string, messageItem: Partial<MessageItemInterface>, index: number]
deleteMessageItem: [messageId: string, index: number]
messageListScrollToBottom: []
clearAllMessage: []
}>()
const multiModelDialogueList = defineModel<MultiModelDialogueItem[]>('multiModelDialogueList', { required: true })
const questionContent = ref('')
const isQuestionSubmitDisabled = computed(() => {
return questionContent.value.trim().length === 0
})
const isAllSelectedModelName = computed(() => {
return multiModelDialogueList.value.every((modelItem) => modelItem.modelNickName)
})
const isAllowClearAllMessage = computed(() => {
return multiModelDialogueList.value.some((modelItem) => modelItem.messageList.size > 0)
})
const messageListScrollToBottomThrottle = throttle(() => {
emit('messageListScrollToBottom')
}, 1000)
function handleClearAllMessage() {
isAllowClearAllMessage.value && emit('clearAllMessage')
}
function messageItemFactory() {
return {
role: 'user',
avatar: '',
nickName: '',
content: '',
timestamp: Date.now(),
isTextContentLoading: false,
isAnswerResponseLoading: false,
} as MessageItemInterface
}
function handleQuestionSubmit() {
if (isQuestionSubmitDisabled.value || props.isAnswerResponseWait) return
if (!isAllSelectedModelName.value) {
window.$message.warning(t('multi_model_dialogue_module.please_select_model_first'))
return
}
const questionMessageId = nanoid()
emit('addQuestionMessageItem', questionMessageId, { ...messageItemFactory(), content: questionContent.value })
emit('messageListScrollToBottom')
multiModelDialogueList.value.forEach((modelItem, modelIndex) => {
const messages: QuestionMessageItem[] = []
const { topP, temperature, agentSystem } = modelItem
modelItem.messageList.forEach((messageItem) => {
messages.push({
content: [
{
type: 'text',
text: messageItem.content,
image_url: {
url: '',
},
},
],
role: messageItem.role,
})
})
questionContent.value = ''
modelItem.isAnswerResponseWait = true
const answerMessageId = nanoid()
let messageContent = ''
let isFirstClip = true
emit(
'addAnswerMessageItem',
answerMessageId,
{ ...messageItemFactory(), role: 'assistant', isTextContentLoading: true, isAnswerResponseLoading: true },
modelIndex,
)
emit('messageListScrollToBottom')
modelItem.controller = new AbortController()
fetchCustomEventSource({
path: '/api/rest/agentApplicationInfoRest/preview.json',
payload: {
agentId: props.agentId,
messages,
topP,
temperature,
agentSystem,
},
controller: modelItem.controller,
onMessage: (data: any) => {
if (data === '[DONE]') {
emit('updateMessageItem', answerMessageId, { isAnswerResponseLoading: false }, modelIndex)
emit('messageListScrollToBottom')
modelItem.isAnswerResponseWait = false
return
}
if (data) {
messageContent += data
if (isFirstClip) {
emit(
'updateMessageItem',
answerMessageId,
{ content: messageContent, isTextContentLoading: false },
modelIndex,
)
isFirstClip = false
} else {
emit('updateMessageItem', answerMessageId, { content: messageContent }, modelIndex)
}
messageListScrollToBottomThrottle()
}
},
onRequestError: () => {
errorMessageResponse(questionMessageId, answerMessageId, modelIndex)
},
onFinally: () => {
modelItem.controller = null
modelItem.isAnswerResponseWait = false
Message({ type: 'error', text: '请求失败', to: '#vvv' })
},
})
})
}
function errorMessageResponse(questionMessageId: string, answerMessageId: string, modelIndex: number) {
emit('deleteMessageItem', questionMessageId, modelIndex)
emit('deleteMessageItem', answerMessageId, modelIndex)
}
</script>
<template>
<footer class="flex flex-col items-center">
<div class="mb-4 flex items-center gap-[18px]">
<NPopover trigger="hover">
<template #trigger>
<div
class="border-inactive-border-color flex h-[54px] w-[54px] shrink-0 items-center justify-center rounded-full border bg-white"
:class="
isAllowClearAllMessage
? 'text-font-color hover:text-theme-color cursor-pointer'
: 'text-gray-font-color cursor-not-allowed'
"
@click="handleClearAllMessage"
>
<i class="iconfont icon-clear text-xl leading-none" />
</div>
</template>
<span class="text-xs"> {{ t('common_module.dialogue_module.clear_message_popover_message') }}</span>
</NPopover>
<div class="relative">
<NInput
v-model:value="questionContent"
:placeholder="t('common_module.dialogue_module.question_input_placeholder')"
class="rounded-[26px]! w-[725px]! border-[#9EA3FF]! border py-[10px] pl-3 pr-[44px]"
@keydown.enter="handleQuestionSubmit"
/>
<i
class="iconfont icon-send-icon absolute right-6 top-[18px] text-xl leading-none"
:class="
isQuestionSubmitDisabled || isAnswerResponseWait
? 'text-hover-theme-color cursor-not-allowed'
: 'text-theme-color cursor-pointer hover:opacity-80'
"
@click="handleQuestionSubmit"
/>
</div>
</div>
<span class="text-gray-font-color select-none">
{{ t('common_module.dialogue_module.generate_warning_message') }}
</span>
</footer>
</template>
<script setup lang="ts">
interface Props {
activeColor: string
}
const { activeColor = '#fff' } = defineProps<Props>()
</script>
<template>
<div class="loader" />
</template>
<style lang="scss" scoped>
.loader {
width: 6px;
aspect-ratio: 1;
border-radius: 50%;
animation: l5 1s infinite linear alternate;
}
@keyframes l5 {
0% {
background: v-bind('activeColor');
box-shadow:
13px 0 v-bind('activeColor'),
-13px 0 #0002;
}
33% {
background: #0002;
box-shadow:
13px 0 v-bind('activeColor'),
-13px 0 #0002;
}
66% {
background: #0002;
box-shadow:
13px 0 #0002,
-13px 0 v-bind('activeColor');
}
100% {
background: v-bind('activeColor');
box-shadow:
13px 0 #0002,
-13px 0 v-bind('activeColor');
}
}
</style>
<script setup lang="ts">
import { computed, readonly } from 'vue'
import { useI18n } from 'vue-i18n'
import type { MessageItemInterface } from '../types'
import MarkdownRender from '@/components/markdown-render/markdown-render.vue'
import MessageBubbleLoading from './message-bubble-loading.vue'
interface Props {
messageItem: MessageItemInterface
}
const props = defineProps<Props>()
const { t } = useI18n()
const agentAvatarUrl = readonly({ url: 'https://gsst-poe-sit.gz.bcebos.com/icon/agent-avatar.png' })
const isAssistant = computed(() => {
return props.messageItem.role === 'assistant'
})
const assistantAvatarUrl = computed(() => {
return props.messageItem.avatar || agentAvatarUrl.url
})
</script>
<template>
<div class="mb-[20px] last:mb-0">
<div class="flex">
<img
class="h-[36px] w-[36px] rounded-full"
:src="isAssistant ? assistantAvatarUrl : props.messageItem.avatar"
alt="Avatar"
/>
<div class="ml-[11px]">
<div class="mb-[7px] line-clamp-1 break-all text-[12px] text-[#999]">
{{ props.messageItem.nickName }}
</div>
<div
class="box-content min-h-[21px] min-w-[10px] rounded-[10px] border border-[#9EA3FF] px-[15px] py-[12px] text-justify"
:class="{
'bg-[#777EF9]': isAssistant,
'text-[#fff]': isAssistant,
'!min-w-[80px]': messageItem.isTextContentLoading,
}"
>
<div v-if="messageItem.isTextContentLoading" class="flex h-[21px] w-[30px] items-center justify-center">
<MessageBubbleLoading :active-color="isAssistant ? '#fff' : '#192338'" />
</div>
<div v-else>
<MarkdownRender
:raw-text-content="
messageItem.content ? messageItem.content : t('common_module.dialogue_module.empty_message_content')
"
:color="isAssistant ? '#fff' : '#192338'"
/>
<div
v-show="isAssistant && messageItem.isAnswerResponseLoading"
class="mt-2.5 flex h-[21px] w-[30px] items-center justify-center"
>
<MessageBubbleLoading :active-color="isAssistant ? '#fff' : '#192338'" />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import { ScrollbarInst } from 'naive-ui'
import MessageItem from './message-item.vue'
import type { MessageItemInterface } from '../types'
interface Props {
messageList: Map<string, MessageItemInterface>
}
defineProps<Props>()
defineExpose({
scrollToBottom,
})
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')
function scrollToBottom() {
if (scrollbarRef.value) {
scrollbarRef.value.scrollTo({ top: 999999999, behavior: 'smooth' })
}
}
</script>
<template>
<div class="flex-1 overflow-hidden overflow-y-auto py-[20px]">
<n-scrollbar ref="scrollbarRef" class="min-h-full" content-class="min-h-full flex">
<div class="flex flex-col-reverse">
<div class="pr-[10px]">
<MessageItem v-for="[key, messageItem] in messageList" :key="key" :message-item="messageItem" />
</div>
</div>
</n-scrollbar>
</div>
</template>
<script setup lang="ts">
import { computed, h, nextTick, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { SelectOption } from 'naive-ui'
import { useVModel } from '@vueuse/core'
import { MultiModelDialogueItem } from '../types'
import ModelSetting from './model-setting.vue'
import MessageList from './message-list.vue'
interface Props {
modelDialogueItem: MultiModelDialogueItem
modelListOptions: SelectOption[]
totalNum: number
isCurrent: boolean
}
const { t } = useI18n()
const props = defineProps<Props>()
const emit = defineEmits<{
removeModelDialogueItem: [id: string]
updateConfig: [modelDialogueItem: MultiModelDialogueItem]
replaceConfig: [modelDialogueItem: MultiModelDialogueItem]
resetConversation: []
}>()
const modelConfig = useVModel(props, 'modelDialogueItem', emit)
const messageListRef = useTemplateRef<InstanceType<typeof MessageList>>('messageListRef')
defineExpose({
scrollToBottom,
})
const isShowModelConfigMenu = ref(false)
const allMoreOptions = [
{
label: () => h('span', {}, t('multi_model_dialogue_module.remove_dialogue')),
key: 'remove',
},
{
label: () => h('span', {}, t('multi_model_dialogue_module.one_click_configuration')),
key: 'replace-config',
},
]
const currentMoreOptions = computed(() => {
let currentOptions = allMoreOptions
if (!props.modelDialogueItem.modelNickName) {
currentOptions = currentOptions.filter((item) => item.key !== 'replace-config')
}
if (props.totalNum <= 2) {
currentOptions = currentOptions.filter((item) => item.key !== 'remove')
}
return currentOptions
})
// 选择更多操作
function handleSelectMoreOption(key: string) {
switch (key) {
case 'remove':
emit('removeModelDialogueItem', props.modelDialogueItem.id)
break
case 'replace-config':
window.$message.ctWarning('', t('multi_model_dialogue_module.replace_configuration_tip')).then(() => {
emit('replaceConfig', props.modelDialogueItem)
})
break
}
}
// 是否显示配置菜单
function handleUpdateModelConfigShow(isShow: boolean) {
isShowModelConfigMenu.value = isShow
}
// 滚动到底部
function scrollToBottom() {
nextTick(() => {
messageListRef.value?.scrollToBottom()
})
}
</script>
<template>
<div class="border-inactive-border-color flex flex-col overflow-hidden border-r px-6 last-of-type:border-none">
<div class="flex items-center justify-between">
<div class="flex items-center gap-5">
<n-popover
:key="modelConfig.id"
placement="bottom-start"
trigger="click"
:show-arrow="false"
:flip="false"
style="width: 386px; border-radius: 10px; box-shadow: 0 4px 13px 0 hsla(0deg, 0%, 0%, 0.08)"
@update:show="handleUpdateModelConfigShow"
>
<template #trigger>
<n-button class="w-[145px]! !h-[34px] !rounded-[10px] !p-0">
<div class="w-[145px]! box-border flex items-center justify-between px-[12px]">
<div v-if="modelDialogueItem.modelNickName" class="flex flex-1 items-center overflow-hidden">
<div
class="mr-[5px] h-[16px] w-[16px] rounded-full bg-cover"
:style="{ backgroundImage: `url(${modelDialogueItem.icon})` }"
/>
<div class="text-font-color flex-1 truncate text-start text-[14px]">
{{ modelDialogueItem.modelNickName }}
</div>
</div>
<div v-else class="text-gray-font-color">{{ t('multi_model_dialogue_module.select_model') }}</div>
<i
class="iconfont icon-left rotate-270 text-[10px] transition-[rotate] duration-300 ease-in-out"
:class="{ '!rotate-90': isShowModelConfigMenu }"
/>
</div>
</n-button>
</template>
<ModelSetting
v-model:model-config="modelConfig"
:model-list-options="modelListOptions"
:is-current="isCurrent"
@update-config="(modelConfig) => emit('updateConfig', modelConfig)"
@reset-conversation="emit('resetConversation')"
/>
</n-popover>
<div
v-show="isCurrent"
class="text-error-font-color font-600 select-none rounded-[10px] bg-[#FFF6F1] px-7 py-2.5 text-[13px] leading-none"
>
{{ t('common_module.currently') }}
</div>
</div>
<n-dropdown
v-if="currentMoreOptions.length"
trigger="hover"
:options="currentMoreOptions"
placement="left-start"
class="rounded-[10px]!"
@select="handleSelectMoreOption"
>
<div
v-show="!isCurrent"
class="hover:bg-background-color flex h-6 w-6 cursor-pointer items-center justify-center rounded-full"
>
<i class="iconfont icon-more text-[20px]" />
</div>
</n-dropdown>
</div>
<div v-if="!modelDialogueItem.modelNickName" class="flex flex-1 flex-col items-center justify-center">
<div class="h-13 w-13 bg-px-empty_model-png mb-3" />
<span class="text-font-color select-none">{{ t('multi_model_dialogue_module.please_select_model') }}</span>
</div>
<MessageList v-else ref="messageListRef" :message-list="modelDialogueItem.messageList" />
</div>
</template>
<style lang="scss" scoped>
:deep(.model-config-input-number .n-input__input-el) {
text-align: center !important;
}
:deep(.agent-system-input .n-input-wrapper) {
resize: none !important;
}
</style>
<script setup lang="ts">
import { computed, h, ref, VNodeChild, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { SelectOption } from 'naive-ui'
import { MultiModelDialogueItem } from '../types'
import { DiversityModeItem, diversityModeList } from '@/data/agent-setting-data'
interface Props {
modelListOptions: SelectOption[]
isCurrent: boolean
}
const { t } = useI18n()
const props = defineProps<Props>()
const emit = defineEmits<{
updateConfig: [modelDialogueItem: MultiModelDialogueItem]
resetConversation: []
}>()
const modelConfig = defineModel<MultiModelDialogueItem>('modelConfig', { required: true })
const currentDiversityMode = ref('balance')
const currentModelNickName = computed({
get: () => (modelConfig.value.modelNickName === '' ? undefined : modelConfig.value.modelNickName),
set: (newValue) => {
modelConfig.value.modelNickName = newValue || ''
},
})
const isDisabledModelConfig = computed(() => {
return currentDiversityMode.value !== 'custom'
})
watch(
() => modelConfig.value,
(newVal) => {
const { temperature, topP } = newVal
switch (temperature) {
case 0.1:
currentDiversityMode.value = topP === 0.1 ? 'accurate' : 'custom'
break
case 0.5:
currentDiversityMode.value = topP === 0.7 ? 'balance' : 'custom'
break
case 0.95:
currentDiversityMode.value = topP === 0.7 ? 'creative' : 'custom'
break
default:
currentDiversityMode.value = 'custom'
}
},
{ deep: true, once: true, immediate: true },
)
// 模型列表项渲染
function modelListRenderLabel(option: SelectOption): VNodeChild {
if (option.type === 'group') return `${option.label}`
return [
h('div', { class: 'flex items-center' }, [
h('div', {
style: {
width: '16px',
height: '16px',
marginRight: '6px',
flexShrink: 0,
background: `url(${option.icon})`,
backgroundSize: '100% 100%',
},
}),
h('span', {}, { default: () => option.label as string }),
]),
]
}
// 更新大模型
function handleUpdateLargeModel(_value: string, option: SelectOption) {
modelConfig.value.icon = option.icon as string
emit('resetConversation')
handleUpdateAgentConfig()
}
// 切换生成多样性
function handleDiversityModeChange(diversityModeItem: DiversityModeItem) {
const { value, topP, temperature } = diversityModeItem
currentDiversityMode.value = value
modelConfig.value.topP = topP
modelConfig.value.temperature = temperature
handleUpdateAgentConfig()
}
// 更新保存应用配置
function handleUpdateAgentConfig() {
props.isCurrent && emit('updateConfig', modelConfig.value)
}
</script>
<template>
<div class="px-1.5 py-1">
<p class="text-font-color font-600 mb-2 select-none">
{{ t('multi_model_dialogue_module.model_setting') }}
</p>
<n-select
v-model:value="currentModelNickName"
:options="modelListOptions"
:render-label="modelListRenderLabel"
:placeholder="t('multi_model_dialogue_module.please_select_model')"
@update:value="handleUpdateLargeModel"
/>
<p class="text-font-color font-600 mb-2 mt-[14px] select-none">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.generate_diversity') }}
</p>
<ul class="rounded-theme mt-2 grid grid-cols-4 overflow-hidden">
<li
v-for="(diversityModeItem, index) in diversityModeList"
:key="index"
class="hover:text-font-color flex h-[34px] w-full cursor-pointer items-center justify-center"
:class="
currentDiversityMode === diversityModeItem.value
? 'text-font-color bg-active-color'
: 'text-gray-font-color bg-[#F7F7FA]'
"
@click="handleDiversityModeChange(diversityModeItem)"
>
{{ t(diversityModeItem.label) }}
</li>
</ul>
<div class="mb-3 mt-[14px] flex h-[34px] items-center justify-between">
<div class="flex w-[70px] items-center">
<span class="text-font-color font-600 select-none">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.temperature') }}
</span>
</div>
<div class="mx-3 flex flex-1">
<n-slider
v-model:value="modelConfig.temperature"
:default-value="0"
:step="0.01"
:min="0.01"
:max="1"
:disabled="isDisabledModelConfig"
@update:value="handleUpdateAgentConfig"
/>
</div>
<n-input-number
v-model:value="modelConfig.temperature"
:bordered="false"
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledModelConfig"
placeholder=""
button-placement="both"
class="w-[100px]! model-config-input-number"
@update:value="handleUpdateAgentConfig"
>
<template #minus-icon>
<div
class="border-inactive-border-color h-6! w-6! rounded-theme flex shrink-0 items-center justify-center border"
>
<i class="iconfont icon-minus" />
</div>
</template>
<template #add-icon>
<div
class="border-inactive-border-color h-6! w-6! rounded-theme flex shrink-0 items-center justify-center border"
>
<i class="iconfont icon-add" />
</div>
</template>
</n-input-number>
</div>
<div class="mt-4 text-xs">
<div class="mb-3 flex h-[34px] items-center justify-between">
<div class="flex w-[70px] items-center">
<span class="text-font-color font-600 select-none">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.topP') }}
</span>
</div>
<div class="mx-3 flex flex-1">
<n-slider
v-model:value="modelConfig.topP"
:default-value="0"
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledModelConfig"
@update:value="handleUpdateAgentConfig"
/>
</div>
<n-input-number
v-model:value="modelConfig.topP"
:bordered="false"
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledModelConfig"
placeholder=""
button-placement="both"
class="w-[100px]! model-config-input-number"
@update:value="handleUpdateAgentConfig"
>
<template #minus-icon>
<div
class="border-inactive-border-color h-6! w-6! rounded-theme flex shrink-0 items-center justify-center border"
>
<i class="iconfont icon-minus" />
</div>
</template>
<template #add-icon>
<div
class="border-inactive-border-color h-6! w-6! rounded-theme flex shrink-0 items-center justify-center border"
>
<i class="iconfont icon-add" />
</div>
</template>
</n-input-number>
</div>
</div>
<p class="text-font-color font-600 mb-1.5 select-none">
{{ t('multi_model_dialogue_module.agent_system') }}
</p>
<n-input
v-model:value="modelConfig.agentSystem"
type="textarea"
placeholder=""
:rows="10"
class="agent-system-input"
@update:value="handleUpdateAgentConfig"
/>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { Left, Plus, Logout } from '@icon-park/vue-next'
interface Props {
agentTitle: string
agentDesc: string
totalNum: number
isAnswerResponseWait: boolean
}
const { t } = useI18n()
const props = defineProps<Props>()
const isDisabledAddModelBtn = computed(() => {
return props.totalNum >= 3 || props.isAnswerResponseWait
})
const emit = defineEmits<{
back: []
addModelDialogue: []
}>()
function handleBack() {
emit('back')
}
function handleAddModelDialogue() {
emit('addModelDialogue')
}
</script>
<template>
<header class="mb-[18px] flex items-end justify-between">
<div>
<div class="flex items-center">
<div
class="rounded-theme hover:bg-hover-background-color mr-0.5 flex h-7 w-7 cursor-pointer items-center justify-center"
@click="handleBack"
>
<Left theme="outline" size="20" fill="#333" class="mt-0.5" />
</div>
<span class="text-font-color font-600 line-clamp-1 break-all text-lg">
{{ agentTitle || '--' }}
</span>
</div>
<span class="text-gray-font-color ml-7.5 mt-1.5 line-clamp-1 break-all">
{{ agentDesc || t('personal_space_module.agent_module.agent_setting_module.missing_agent_desc_message') }}
</span>
</div>
<div class="flex gap-5">
<NButton
type="primary"
:bordered="false"
class="px-4!"
:disabled="isDisabledAddModelBtn"
@click="handleAddModelDialogue"
>
<Plus theme="outline" size="16" fill="#fff" :stroke-width="4" />
<span class="ml-[5px]">{{ t('multi_model_dialogue_module.add_model') }}{{ totalNum }}/3</span>
</NButton>
<NButton type="info" @click="handleBack">
<Logout theme="outline" size="16" fill="#575FFF" :stroke-width="4" />
<span class="ml-[5px]">{{ t('multi_model_dialogue_module.quit_test') }}</span>
</NButton>
</div>
</header>
</template>
This diff is collapsed.
export interface QuestionMessageItem {
role: 'user' | 'assistant'
content: [
{
type: string
text: string
image_url: {
url: string
}
},
]
}
export interface MultiModelDialogueItem {
id: string
icon: string
modelNickName: string
topP: number
temperature: number
agentSystem: string
controller: AbortController | null
isAnswerResponseWait: boolean
messageList: Map<string, MessageItemInterface>
}
export interface MessageItemInterface {
role: 'user' | 'assistant'
avatar: string
nickName: string
content: string
timestamp: number
isTextContentLoading: boolean
isAnswerResponseLoading: boolean
}
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { useRouter } from 'vue-router'
import Preamble from './preamble.vue' import Preamble from './preamble.vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import MessageList from './message-list.vue' import MessageList from './message-list.vue'
...@@ -9,6 +10,8 @@ import { usePersonalAppConfigStore } from '@/store/modules/personal-app-config' ...@@ -9,6 +10,8 @@ import { usePersonalAppConfigStore } from '@/store/modules/personal-app-config'
const { t } = useI18n() const { t } = useI18n()
const router = useRouter()
const personalAppConfigStore = usePersonalAppConfigStore() const personalAppConfigStore = usePersonalAppConfigStore()
const messageListRef = ref<InstanceType<typeof MessageList> | null>(null) const messageListRef = ref<InstanceType<typeof MessageList> | null>(null)
...@@ -67,13 +70,33 @@ function handleUpdateContinueQuestionStatus(status: 'default' | 'close') { ...@@ -67,13 +70,33 @@ function handleUpdateContinueQuestionStatus(status: 'default' | 'close') {
continuousQuestionStatus.value = status continuousQuestionStatus.value = status
continuousQuestionList.value = [] continuousQuestionList.value = []
} }
function handleTurnMultiModelDialogue() {
router.push({
name: 'MultiModelDialogue',
params: {
agentId: personalAppConfigStore.baseInfo.agentId,
},
})
}
</script> </script>
<template> <template>
<div class="flex h-full min-w-[300px] flex-1 flex-col overflow-hidden bg-[#f2f5f9]"> <div class="flex h-full min-w-[300px] flex-1 flex-col overflow-hidden bg-[#f2f5f9]">
<p class="mb-[18px] px-5 py-[18px] text-base"> <div class="mb-[18px] flex items-center justify-between px-5 py-[18px]">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.preview') }} <p class="text-base">
</p> {{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.preview') }}
</p>
<div
v-show="personalAppConfigStore.baseInfo.agentId"
class="text-font-color hover:text-theme-color cursor-pointer"
@click="handleTurnMultiModelDialogue"
>
<i class="iconfont icon-moxing mr-1 text-sm" />
<span>{{ t('common_module.multi_model_debug') }}</span>
</div>
</div>
<div class="flex w-full flex-1 overflow-hidden"> <div class="flex w-full flex-1 overflow-hidden">
<div v-show="messageList.length === 0" class="flex w-full"> <div v-show="messageList.length === 0" class="flex w-full">
......
...@@ -54,6 +54,11 @@ declare namespace I18n { ...@@ -54,6 +54,11 @@ declare namespace I18n {
select_all: string select_all: string
quit: string quit: string
retry: string retry: string
currently: string
multi_model_debug: string
accurate_mode: string
balance_mode: string
creative_mode: string
dialogue_module: { dialogue_module: {
continue_question_message: string continue_question_message: string
...@@ -130,6 +135,7 @@ declare namespace I18n { ...@@ -130,6 +135,7 @@ declare namespace I18n {
upload_knowledge_document: string upload_knowledge_document: string
knowledge_document_list: string knowledge_document_list: string
knowledge_document_detail: string knowledge_document_detail: string
multi_model_dialogue: string
} }
personal_space_module: { personal_space_module: {
...@@ -309,5 +315,20 @@ declare namespace I18n { ...@@ -309,5 +315,20 @@ declare namespace I18n {
create_agent_dialogue_content: string create_agent_dialogue_content: string
create_agent_dialogue_positive_text: string create_agent_dialogue_positive_text: string
} }
multi_model_dialogue_module: {
not_find_agent: string
add_model: string
quit_test: string
model_setting: string
agent_system: string
remove_dialogue: string
one_click_configuration: string
select_model: string
please_select_model: string
please_select_model_first: string
replace_configuration_tip: string
open_new_conversation: string
}
} }
} }
...@@ -54,6 +54,7 @@ export default defineConfig({ ...@@ -54,6 +54,7 @@ export default defineConfig({
'error-font-color': '#F25744', 'error-font-color': '#F25744',
'inactive-border-color': '#CCCCCC', 'inactive-border-color': '#CCCCCC',
'background-color': '#F3F5F8', 'background-color': '#F3F5F8',
'hover-background-color': '#E3E8F0',
}, },
height: { height: {
navbar: '56px', navbar: '56px',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment