Commit 8cb410ce authored by nick zheng's avatar nick zheng

Merge branch 'beta' into 'master'

feat: 应用配置引用知识库

See merge request !47
parents 3f882d31 74b3b6f9
......@@ -73,6 +73,14 @@ export function fetchTrainKnowledge<T>(payload: object) {
return request.post<T>('/knowledgeRest/trainKnowledge.json', payload)
}
/**
* @params kdIds 知识库Id列表
* @returns 【根据知识库ID】获取知识库列表
*/
export function fetchGetKnowledgeListByKdIds<T>(kdIds: number[]) {
return request.post<T>('/knowledgeRest/getKnowledgeListByKnowledgeInfoIds.json', kdIds)
}
/* 知识库部分结束 */
/* 知识库文档部分开始 */
......
......@@ -15,6 +15,7 @@ interface Props {
confirmBtnText?: string // 取消按钮文字
labelWidth?: number // 标签的宽度
labelPlacement?: 'left' | 'top' // 标签显示的位置
contentStyle?: object
}
interface Emits {
......@@ -35,6 +36,7 @@ const props = withDefaults(defineProps<Props>(), {
confirmBtnText: 'common_module.confirm_btn_text',
labelWidth: 80,
labelPlacement: 'left',
contentStyle: () => ({}),
})
const emit = defineEmits<Emits>()
......@@ -47,6 +49,10 @@ const modalBasicStyle = {
borderRadius: props.borderRadius + 'px',
}
const contentStyle = computed(() => {
return { ...modalContentStyle, ...props.contentStyle }
})
const showModal = computed({
get() {
return props.isShow
......@@ -76,14 +82,14 @@ function handleConfirm() {
:bordered="false"
:auto-focus="false"
:header-style="modalHeaderStyle"
:content-style="modalContentStyle"
:content-style="contentStyle"
:footer-style="modalFooterStyle"
:on-mask-click="handleCloseModal"
@close="handleCloseModal"
>
<template #header>
<slot v-if="slots.header" name="header" />
<div v-else>{{ title }}</div>
<div v-else class="text-[18px] leading-none">{{ title }}</div>
</template>
<div>
......
export const modalHeaderStyle = {
padding: '24px 24px 16px',
fontSize: '18px',
padding: '24px',
}
export const modalContentStyle = {
......
......@@ -75,6 +75,13 @@ common_module:
wipe_data: 'Wipe Data '
delete_all_tip_title: 'Clear Data Prompt'
search: 'Search'
add: 'Add'
remove: 'Remove'
add_knowledge: 'Add Knowledge Base'
no_file: 'No file'
view_file: 'View file'
total_file: '1 file in total | {count} files in total'
dialogue_module:
continue_question_message: 'You can keep asking questions'
......@@ -257,6 +264,8 @@ personal_space_module:
memory_variable_delete_tip_content: 'After deletion, it cannot be revoked. If the application has already been released, after the update is released, users of the application will not be able to use the memory variable. Do you want to continue?'
memory_fragment_delete_all_tip_content: 'After data is cleared, it cannot be revoked. Are you sure you want to clear it all?'
memory_fragment_delete_row_tip_content: 'After data deletion, it cannot be revoked. Are you sure you want to delete it?'
add_knowledge_successfully: 'Data set {0} was added successfully'
remove_knowledge_successfully: 'Data set {0} was removed successfully'
memory_variable_modal:
edit_memory_variable: 'Edit memory variable'
......
......@@ -74,6 +74,13 @@ common_module:
wipe_data: '清空数据'
delete_all_tip_title: '清空数据提示'
search: '搜索'
add: '添加'
remove: '移除'
add_knowledge: '添加知识库'
no_file: '暂无文件'
view_file: '查看文件'
total_file: '共{count}个文件'
dialogue_module:
continue_question_message: '你可以继续提问'
......@@ -255,6 +262,8 @@ personal_space_module:
memory_variable_delete_tip_content: '删除后不可撤销。如应用已发布,更新发布后该应用的用户无法使用该记忆变量,是否继续?'
memory_fragment_delete_all_tip_content: '数据清空后不可撤销,确定要全部清空吗?'
memory_fragment_delete_row_tip_content: '数据删除后不可撤销,确定要删除吗?'
add_knowledge_successfully: '数据集 {0} 添加成功'
remove_knowledge_successfully: '数据集 {0} 移除成功'
memory_variable_modal:
edit_memory_variable: '编辑记忆变量'
......
......@@ -74,6 +74,12 @@ common_module:
wipe_data: '清空數據'
delete_all_tip_title: '清空數據提示'
search: '搜索'
add: '添加'
remove: '移除'
add_knowledge: '添加知識庫'
no_file: '暫無文件'
view_file: '查看文件'
total_file: '共{count}個文件'
dialogue_module:
continue_question_message: '你可以繼續提問'
......@@ -255,6 +261,8 @@ personal_space_module:
memory_variable_delete_tip_content: '删除後不可撤銷。 如應用已發佈,更新發佈後該應用的用戶無法使用該記憶變數,是否繼續?'
memory_fragment_delete_all_tip_content: '數據清空後不可撤銷,確定要全部清空嗎?'
memory_fragment_delete_row_tip_content: '數據删除後不可撤銷,確定要删除嗎?'
add_knowledge_successfully: '數據集 {0} 添加成功'
remove_knowledge_successfully: '數據集 {0} 移除成功'
memory_variable_modal:
edit_memory_variable: '編輯記憶變數'
......
......@@ -26,7 +26,7 @@ export interface PersonalAppConfigState {
isLongMemory: string
}
knowledgeConfig: {
knowledgeIds: string[] //知识库ID
knowledgeIds: number[] //知识库ID
}
commModelConfig: {
largeModel: string //大模型
......
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { Plus, RightOne } from '@icon-park/vue-next'
import { fetchGetKnowledgeListByKdIds } from '@/apis/knowledge'
import AssociatedKnowledgeModal from './associated-knowledge-modal.vue'
import { KnowledgeItem } from '../../personal-knowledge/knowledge-type'
const { t } = useI18n()
const knowledgeConfig = defineModel<{ knowledgeIds: number[] }>('knowledgeConfig', { required: true })
const isShowAssociatedKnowledgeModel = ref(false)
const knowledgeConfigExpandedNames = ref<string[]>([])
const selectKnowledgeList = ref<KnowledgeItem[]>([])
const hoverKdId = ref(0)
watch(
() => knowledgeConfig.value.knowledgeIds,
async (newKdIds) => {
if (newKdIds.length > 0) {
knowledgeConfigExpandedNames.value = ['knowledge']
await handleGetKnowledgeListByIds()
knowledgeConfig.value.knowledgeIds = []
selectKnowledgeList.value.forEach((knowledgeItem) => {
knowledgeConfig.value.knowledgeIds.push(knowledgeItem.id)
})
}
},
{ once: true },
)
const isHoverKnowledgeItem = computed(() => (kdId: number) => {
return hoverKdId.value === kdId
})
async function handleGetKnowledgeListByIds() {
const res = await fetchGetKnowledgeListByKdIds<KnowledgeItem[]>(knowledgeConfig.value.knowledgeIds)
if (res.code === 0) {
selectKnowledgeList.value = res.data
}
}
function handleShowAssociatedKnowledgeModel() {
isShowAssociatedKnowledgeModel.value = true
}
function handleUpdateKnowledgeConfigExpandedNames(expandedNames: string[]) {
knowledgeConfigExpandedNames.value = expandedNames
}
function handleMouseoverKnowledgeItem(kdId: number) {
hoverKdId.value = kdId
}
function handleMouseleaveKnowledgeItem() {
hoverKdId.value = 0
}
function handleToKnowledgeDocument(kdId: number) {
const url = `${window.location.origin}/fe/knowledge/document/${kdId}`
window.open(url, '_blank')
}
function handleDeleteKnowledgeItem(kdId: number) {
knowledgeConfig.value.knowledgeIds = knowledgeConfig.value.knowledgeIds.filter((id) => id !== kdId)
selectKnowledgeList.value = selectKnowledgeList.value.filter((item) => item.id !== kdId)
}
function handleCloseAssociatedKnowledgeModal() {
knowledgeConfig.value.knowledgeIds.length && handleGetKnowledgeListByIds()
}
</script>
<template>
<section class="border-b border-[#e8e9eb] px-5">
<div class="pt-4">
<h2 class="my-3 text-[#84868c]">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge') }}
</h2>
<NCollapse
:expanded-names="knowledgeConfigExpandedNames"
:trigger-areas="['main', 'arrow']"
@update:expanded-names="handleUpdateKnowledgeConfigExpandedNames"
>
<template #arrow>
<RightOne theme="multi-color" size="17" fill="#333" />
</template>
<NCollapseItem
:title="t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge_base')"
name="knowledge"
class="my-[13px]!"
>
<template #header-extra>
<NTooltip trigger="hover">
<template #trigger>
<Plus
theme="outline"
size="21"
:stroke-width="3"
class="text-theme-color cursor-pointer"
@click="handleShowAssociatedKnowledgeModel"
/>
</template>
{{ t('common_module.add_knowledge') }}
</NTooltip>
</template>
<ul v-show="selectKnowledgeList.length" class="flex flex-col gap-2">
<li
v-for="knowledgeItem in selectKnowledgeList"
:key="knowledgeItem.id"
class="rounded-theme flex cursor-pointer justify-between gap-2 border border-[#f2f5f9] px-3 py-1.5 hover:bg-[#f2f5f9]"
@mouseover="handleMouseoverKnowledgeItem(knowledgeItem.id)"
@mouseleave="handleMouseleaveKnowledgeItem"
@click="handleToKnowledgeDocument(knowledgeItem.id)"
>
<div class="flex items-center gap-2 overflow-hidden">
<div
class="h-6 w-6 bg-[url(https://gsst-poe-sit.gz.bcebos.com/data/20241012/1728700558225.png)] bg-contain bg-no-repeat"
/>
<n-ellipsis class="flex-1">
<span class="text-xs">{{ knowledgeItem.knowledgeName }}</span>
<template #tooltip>
<div class="max-w-[500px]">
<span class="text-xs"> {{ knowledgeItem.knowledgeName }}</span>
</div>
</template>
</n-ellipsis>
</div>
<div v-show="isHoverKnowledgeItem(knowledgeItem.id)" class="flex items-center justify-center">
<i
class="hover:text-error-font-color text-font-color iconfont icon-reduce cursor-pointer outline-none"
@click.stop="handleDeleteKnowledgeItem(knowledgeItem.id)"
/>
</div>
</li>
</ul>
<span v-show="!knowledgeConfig.knowledgeIds.length" class="text-xs text-[#84868c]">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge_base_desc') }}
</span>
</NCollapseItem>
</NCollapse>
</div>
</section>
<AssociatedKnowledgeModal
v-model:is-show-modal="isShowAssociatedKnowledgeModel"
v-model:knowledge-ids="knowledgeConfig.knowledgeIds"
:btn-loading="false"
:modal-title="t('common_module.add_knowledge')"
@close="handleCloseAssociatedKnowledgeModal"
/>
</template>
<script setup lang="ts">
import { computed, h, onMounted, reactive, VNodeChild } from 'vue'
import { SelectOption } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { Help, Down } from '@icon-park/vue-next'
import { PersonalAppConfigState } from '@/store/types/personal-app-config'
import { DiversityModeItem, diversityModeList } from '@/data/agent-setting-data'
import { fetchGetLargeModelList } from '@/apis/agent-application'
const { t } = useI18n()
let modalListOptions = reactive<SelectOption[]>([])
let modalListRenderLabel: (option: SelectOption) => VNodeChild
const personalAppConfig = defineModel<PersonalAppConfigState>('personalAppConfig', { required: true })
const currentDiversityMode = defineModel<string>('currentDiversityMode', { required: true })
const currentLargeModelIcon = defineModel<string>('currentLargeModelIcon', { required: true })
const isDisabledCommModelConfig = computed(() => {
return currentDiversityMode.value !== 'custom'
})
onMounted(() => {
handleGetLargeModelList()
})
// 获取大模型列表
async function handleGetLargeModelList() {
modalListOptions = []
const res = await fetchGetLargeModelList<{ owner: string; models: string[]; icon: string }[]>()
res.data.forEach((item) => {
modalListOptions.push({
type: 'group',
label: item.owner,
key: item.owner,
children: item.models.map((model) => ({
label: model,
value: model,
style: { fontSize: '12px' },
icon: item.icon,
})),
})
})
modalListRenderLabel = (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) {
currentLargeModelIcon.value = option.icon as string
}
function handleDiversityModeChange(diversityModeItem: DiversityModeItem) {
const { value, topP, temperature, communicationTurn } = diversityModeItem
currentDiversityMode.value = value
personalAppConfig.value.commModelConfig.topP = topP
personalAppConfig.value.commModelConfig.temperature = temperature
personalAppConfig.value.commModelConfig.communicationTurn = communicationTurn
}
</script>
<template>
<div>
<NPopover placement="bottom" trigger="click" style="width: 420px">
<template #trigger>
<div
class="hover:border-theme-color flex cursor-pointer items-center justify-between rounded-md border border-[#d4d6d9] px-3 py-[7px]"
>
<img :src="currentLargeModelIcon || '@/assets/images/lingjing-icon.png'" class="mr-1 h-4 w-4" />
<span class="line-clamp-1 w-[100px] text-xs text-[#5c5f66]">
{{ personalAppConfig.commModelConfig.largeModel }}
</span>
<Down theme="outline" size="16" fill="#333" class="ml-1.5 text-base outline-none" />
</div>
</template>
<div class="mb-2 mt-[6px] flex items-center">
<span class="font-500 mr-3 text-sm text-[#151b26]">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.question_answer_model') }}
</span>
<span class="rounded bg-[#f2f5f9] px-1 text-xs text-[#5c5f66]">
{{
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.question_answer_model_desc')
}}
</span>
</div>
<NSelect
v-model:value="personalAppConfig.commModelConfig.largeModel"
class="model-select"
:options="modalListOptions"
:render-label="modalListRenderLabel"
@update:value="handleUpdateLargeModel"
/>
<div class="mt-4">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.generate_diversity') }}
</span>
<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 text-xs"
: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>
<div class="mt-4 text-xs">
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.topP') }}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.topP_popover_message')
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.topP"
:default-value="0"
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
/>
<span class="ml-4 w-8">{{ personalAppConfig.commModelConfig.topP }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.topP"
placeholder=""
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
size="small"
class="w-[90px]! text-xs!"
/>
</div>
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.temperature') }}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.temperature_popover_message',
)
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.temperature"
:default-value="0"
:step="0.01"
:min="0.01"
:max="1"
:disabled="isDisabledCommModelConfig"
/>
<span class="ml-4 w-[32px]">{{ personalAppConfig.commModelConfig.temperature }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.temperature"
placeholder=""
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
size="small"
class="w-[90px]! text-xs!"
/>
</div>
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.communication_turn') }}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.communication_turn_popover_message',
)
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.communicationTurn"
:default-value="3"
:step="1"
:min="0"
:max="100"
/>
<span class="ml-4 w-8">{{ personalAppConfig.commModelConfig.communicationTurn }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.communicationTurn"
:step="1"
:min="0"
:max="100"
size="small"
class="w-[90px]!"
placeholder=""
/>
</div>
</div>
</NPopover>
</div>
</template>
<style lang="scss" scoped>
.model-select {
:deep(.n-base-selection) {
font-size: 12px;
border-radius: 6px;
}
}
</style>
......@@ -91,7 +91,7 @@ function handleOpenMemoryPreviewModal(MemoryTabName: string) {
</script>
<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-[2_2_0%] flex-col overflow-hidden bg-[#f2f5f9]">
<div class="flex justify-between">
<div class="mb-[18px] flex w-full items-center justify-between px-5 py-[18px]">
<p class="text-base">
......
<script setup lang="ts">
import { computed, h, nextTick, onMounted, onUnmounted, reactive, ref, VNodeChild, watch } from 'vue'
import { computed, h, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { FormInst, InputInst, SelectOption } from 'naive-ui'
import { FormInst, InputInst } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { useThrottleFn } from '@vueuse/core'
import CustomIcon from '@/components/custom-icon/custom-icon.vue'
......@@ -18,13 +18,13 @@ import {
fetchCreatePreamble,
fetchGetDebugApplicationInfo,
fetchGetLargeModelInfo,
fetchGetLargeModelList,
fetchSaveAgentApplication,
} from '@/apis/agent-application'
import { fetchCustomEventSource } from '@/composables/useEventSource'
import { DiversityModeItem, diversityModeList } from '../app-setting-config'
import MemoryVariableModal from './memory-variable-modal.vue'
import type { MemoryVariableForm } from './memory-variable-modal.vue'
import AgentModelSetting from './agent-model-setting.vue'
import AgentAssociatedKnowledge from './agent-associated-knowledge.vue'
import { copyToClip } from '@/utils/copy'
const { t } = useI18n()
......@@ -60,10 +60,6 @@ const questionSettingOptions = [
},
]
let modalListOptions = reactive<SelectOption[]>([])
let modalListRenderLabel: (option: SelectOption) => VNodeChild
const currentLargeModelIcon = ref('') // 当前大模型icon
const commConfigExpandedNames = ref<string[]>(['continuousQuestion'])
......@@ -122,10 +118,6 @@ const isUpdatePersonalAgentConfig = computed(() => {
return !isInitGetAgentAppDetail.value
})
const isDisabledCommModelConfig = computed(() => {
return currentDiversityMode.value !== 'custom'
})
watch(
() => personalAppConfig.value,
() => {
......@@ -155,7 +147,6 @@ onMounted(async () => {
await handleGetAgentApplicationDetail(router.currentRoute.value.params.agentId as string)
isInitGetAgentAppDetail.value = false
}
await handleGetLargeModelList()
await handleGetLargeModelInfo()
})
......@@ -208,46 +199,6 @@ async function handleGetAgentApplicationDetail(agentId: string) {
}
}
// 获取大模型列表
async function handleGetLargeModelList() {
modalListOptions = []
const res = await fetchGetLargeModelList<{ owner: string; models: string[]; icon: string }[]>()
res.data.forEach((item) => {
modalListOptions.push({
type: 'group',
label: item.owner,
key: item.owner,
children: item.models.map((model) => ({
label: model,
value: model,
style: { fontSize: '12px' },
icon: item.icon,
})),
})
})
modalListRenderLabel = (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 }),
]),
]
}
}
// 获取大模型信息
async function handleGetLargeModelInfo() {
const res = await fetchGetLargeModelInfo<{ icon: string }>(personalAppConfig.value.commModelConfig.largeModel)
......@@ -257,11 +208,6 @@ async function handleGetLargeModelInfo() {
}
}
// 更换大模型
function handleUpdateLargeModel(_value: string, option: SelectOption) {
currentLargeModelIcon.value = option.icon as string
}
// 保存应用配置
async function handleSaveAgentApplication() {
await fetchSaveAgentApplication<PersonalAppConfigState>(personalAppConfigStore.$state)
......@@ -468,14 +414,6 @@ function handleStopGenerate() {
isFullScreenLoading.value = false
}
function handleDiversityModeChange(diversityModeItem: DiversityModeItem) {
const { value, topP, temperature, communicationTurn } = diversityModeItem
currentDiversityMode.value = value
personalAppConfig.value.commModelConfig.topP = topP
personalAppConfig.value.commModelConfig.temperature = temperature
personalAppConfig.value.commModelConfig.communicationTurn = communicationTurn
}
function handleShowMemoryVariableModal() {
isShowMemoryVariableModal.value = true
}
......@@ -531,7 +469,7 @@ function handleChangeMemoryFragmentState(value: boolean) {
</script>
<template>
<div class="flex h-full w-[800px] flex-col xl:w-[1000px]">
<div class="flex h-full flex-[3_3_0%] flex-col">
<div
class="flex h-[56px] w-full items-center justify-between border-r border-[#e8e9eb] px-5 text-[#333] shadow-[inset_0_-1px_#e8e9eb]"
>
......@@ -551,211 +489,11 @@ function handleChangeMemoryFragmentState(value: boolean) {
</div>
</div>
<div>
<NPopover placement="bottom" trigger="click" style="width: 420px">
<template #trigger>
<div
class="hover:border-theme-color flex cursor-pointer items-center justify-between rounded-md border border-[#d4d6d9] px-3 py-[7px]"
>
<img :src="currentLargeModelIcon || '@/assets/images/lingjing-icon.png'" class="mr-1 h-4 w-4" />
<span class="line-clamp-1 w-[100px] text-xs text-[#5c5f66]">
{{ personalAppConfig.commModelConfig.largeModel }}
</span>
<Down theme="outline" size="16" fill="#333" class="ml-1.5 text-base outline-none" />
</div>
</template>
<div class="mb-2 mt-[6px] flex items-center">
<span class="font-500 mr-3 text-sm text-[#151b26]">
{{
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.question_answer_model')
}}
</span>
<span class="rounded bg-[#f2f5f9] px-1 text-xs text-[#5c5f66]">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.question_answer_model_desc',
)
}}
</span>
</div>
<NSelect
v-model:value="personalAppConfig.commModelConfig.largeModel"
class="model-select"
:options="modalListOptions"
:render-label="modalListRenderLabel"
@update:value="handleUpdateLargeModel"
/>
<div class="mt-4">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.generate_diversity') }}
</span>
<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 text-xs"
: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>
<div class="mt-4 text-xs">
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.topP') }}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.topP_popover_message',
)
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.topP"
:default-value="0"
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
/>
<span class="ml-4 w-8">{{ personalAppConfig.commModelConfig.topP }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.topP"
placeholder=""
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
size="small"
class="w-[90px]! text-xs!"
/>
</div>
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.temperature') }}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.temperature_popover_message',
)
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.temperature"
:default-value="0"
:step="0.01"
:min="0.01"
:max="1"
:disabled="isDisabledCommModelConfig"
/>
<span class="ml-4 w-[32px]">{{ personalAppConfig.commModelConfig.temperature }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.temperature"
placeholder=""
:step="0.01"
:min="0"
:max="1"
:disabled="isDisabledCommModelConfig"
size="small"
class="w-[90px]! text-xs!"
/>
</div>
<div class="mb-2.5 flex h-[34px] items-center justify-between">
<div class="flex w-[105px] items-center">
<span>
{{
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.communication_turn')
}}
</span>
<NPopover trigger="hover">
<template #trigger>
<Help
theme="outline"
size="15"
fill="#333"
:stroke-width="3"
class="ml-1 cursor-pointer text-base text-[#999] outline-none"
/>
</template>
<span class="text-xs">
{{
t(
'personal_space_module.agent_module.agent_setting_module.agent_config_module.communication_turn_popover_message',
)
}}
</span>
</NPopover>
</div>
<div class="mx-5 flex flex-1">
<NSlider
v-model:value="personalAppConfig.commModelConfig.communicationTurn"
:default-value="3"
:step="1"
:min="0"
:max="100"
/>
<span class="ml-4 w-8">{{ personalAppConfig.commModelConfig.communicationTurn }}</span>
</div>
<NInputNumber
v-model:value="personalAppConfig.commModelConfig.communicationTurn"
:step="1"
:min="0"
:max="100"
size="small"
class="w-[90px]!"
placeholder=""
/>
</div>
</div>
</NPopover>
</div>
<AgentModelSetting
v-model:personal-app-config="personalAppConfig"
v-model:current-diversity-mode="currentDiversityMode"
v-model:current-large-model-icon="currentLargeModelIcon"
/>
</div>
<div class="flex h-[calc(100vh-56px-56px)]">
......@@ -965,30 +703,7 @@ function handleChangeMemoryFragmentState(value: boolean) {
</span>
</div>
<section class="border-b border-[#e8e9eb] px-5">
<div class="pt-4">
<h2 class="my-3 text-[#84868c]">
{{ t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge') }}
</h2>
<NCollapse :trigger-areas="['main', 'arrow']">
<template #arrow>
<RightOne theme="multi-color" size="17" :fill="['#333', '#333', '#333', '#333']" />
</template>
<NCollapseItem
:title="t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge_base')"
name="1"
class="my-[13px]!"
>
<span class="text-xs text-[#84868c]">
{{
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.knowledge_base_desc')
}}
</span>
</NCollapseItem>
</NCollapse>
</div>
</section>
<AgentAssociatedKnowledge v-model:knowledge-config="personalAppConfig.knowledgeConfig" />
<section class="border-b border-[#e8e9eb] px-5">
<div class="pt-4">
......@@ -1374,6 +1089,8 @@ function handleChangeMemoryFragmentState(value: boolean) {
</template>
<style lang="scss" scoped>
@include custom-scrollbar(0);
:deep(.n-form-item-feedback-wrapper) {
--n-feedback-height: 14px;
}
......@@ -1391,12 +1108,11 @@ function handleChangeMemoryFragmentState(value: boolean) {
:deep(.prompt-input .n-input-wrapper) {
padding: 0;
}
.model-select {
:deep(.n-base-selection) {
font-size: 12px;
border-radius: 6px;
.n-scrollbar-rail,
.n-scrollbar {
--n-scrollbar-width: 0px !important;
--n-scrollbar-height: 0px !important;
}
}
......
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { Search } from '@icon-park/vue-next'
import { usePagination } from '@/composables/usePagination.ts'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
import { fetchCreateKnowledge, fetchGetKnowledgeList } from '@/apis/knowledge'
import { KnowledgeDocumentItem, KnowledgeItem } from '@/views/personal-space/personal-knowledge/knowledge-type'
import { formatDateTime } from '@/utils/date-formatter'
import CreateKnowledgeModal, {
KnowledgeFormDataInterface,
} from '../../personal-knowledge/components/create-knowledge-modal.vue'
interface Props {
isShowModal: boolean
btnLoading: boolean
modalTitle: string
}
interface Emits {
(e: 'update:isShowModal', value: boolean): void
(e: 'close'): void
}
const { t } = useI18n()
const knowledgeIds = defineModel<number[]>('knowledgeIds', { required: true })
const router = useRouter()
const { paginationData } = usePagination()
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const searchKnowledgeInputValue = ref('')
const knowledgeListLoading = ref(false)
const isSearchEmptyList = ref(false)
const knowledgeList = ref<KnowledgeItem[]>([])
const showCreateKnowledgeModal = ref(false)
const createKnowledgeBtnLoading = ref(false)
const showModal = computed({
get() {
return props.isShowModal
},
set(value: boolean) {
emit('update:isShowModal', value)
},
})
const documentIcon = (documentName: string) => {
const type = documentName.split('.')?.pop()?.toLowerCase()
return type ? `https://gsst-poe-sit.gz.bcebos.com/icon/${type}.svg` : ''
}
const documentNameListText = computed(() => (documentInfos: KnowledgeDocumentItem[]) => {
let documentNameListText = ''
if (Array.isArray(documentInfos)) {
documentInfos.forEach((knowledgeDocumentItem) => {
if (knowledgeDocumentItem.documentName) {
documentNameListText += `${knowledgeDocumentItem.documentName}、`
}
})
return documentNameListText.slice(0, -1)
} else {
return '---'
}
})
const isAddedKdId = computed(() => (kdId: number) => {
return knowledgeIds.value.includes(kdId)
})
const addKdIdBtnDisabled = computed(() => {
return knowledgeIds.value.length >= 5
})
const emptyKnowledgeListText = computed(() => {
return isSearchEmptyList.value ? t('common_module.search_empty_data') : t('common_module.empty_data')
})
watch(
() => props.isShowModal,
(newVal) => {
newVal && handleGetKnowledgeList()
},
)
async function handleGetKnowledgeList() {
paginationData.pageSize = 999999
knowledgeListLoading.value = true
const res = await fetchGetKnowledgeList<KnowledgeItem[]>('', searchKnowledgeInputValue.value, {
pagingInfo: paginationData,
})
if (res.code === 0) {
knowledgeList.value = res.data
paginationData.totalRows = res.pagingInfo?.totalPages || 0
paginationData.totalPages = res.pagingInfo?.totalPages || 0
isSearchEmptyList.value = !!searchKnowledgeInputValue.value && paginationData.totalRows === 0
knowledgeListLoading.value = false
}
}
function handleAddKnowledgeId(kdId: number, knowledgeName: string) {
knowledgeIds.value.push(kdId)
window.$message.success(
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.add_knowledge_successfully', [
knowledgeName,
]),
)
}
function handleDeleteKnowledgeId(kdId: number, knowledgeName: string) {
knowledgeIds.value = knowledgeIds.value.filter((id) => id !== kdId)
window.$message.success(
t('personal_space_module.agent_module.agent_setting_module.agent_config_module.remove_knowledge_successfully', [
knowledgeName,
]),
)
}
function handleToKnowledgeDocument(kdId: number) {
const url = `${window.location.origin}/fe/knowledge/document/${kdId}`
window.open(url, '_blank')
}
function handleToDocumentDetail(kdId: number, documentId: number) {
const url = `${window.location.origin}/fe/knowledge/document/detail/${kdId}/${documentId}`
window.open(url, '_blank')
}
async function handleCreateKnowledgeNextStep(createKnowledgeData: KnowledgeFormDataInterface) {
createKnowledgeBtnLoading.value = true
const res = await fetchCreateKnowledge<{ id: number }>({
knowledgeName: createKnowledgeData.knowledgeName,
desc: createKnowledgeData.knowledgeDesc,
})
if (res.code === 0) {
router.push({
name: 'UploadKnowledge',
params: {
id: res.data.id,
type: createKnowledgeData.knowledgeType + '-' + createKnowledgeData.knowledgeImportType,
},
})
showCreateKnowledgeModal.value = false
createKnowledgeBtnLoading.value = false
}
}
</script>
<template>
<CustomModal
v-model:is-show="showModal"
:title="modalTitle"
:width="690"
:height="675"
:content-style="{ padding: '0 12px 24px' }"
@close="emit('close')"
>
<template #content>
<div class="flex w-full justify-end px-3">
<div class="gap-4.5 flex items-center">
<NInput
v-model:value="searchKnowledgeInputValue"
:placeholder="t('personal_space_module.knowledge_module.search_knowledge_placeholder')"
class="w-[214px]!"
@keyup.enter="handleGetKnowledgeList"
>
<template #suffix>
<Search theme="outline" size="16" fill="#999" class="cursor-pointer" @click="handleGetKnowledgeList" />
</template>
</NInput>
<NButton type="primary" @click="showCreateKnowledgeModal = true">
{{ t('personal_space_module.knowledge_module.create_knowledge_modal_title') }}
</NButton>
</div>
</div>
<n-virtual-list
v-show="!knowledgeListLoading"
class="mt-[18px] max-h-[533px] w-full pl-3"
:item-size="136"
:items="knowledgeList"
key-field="id"
items-style="padding-right: 12px;"
>
<template #default="{ item }">
<div
:key="item.id"
class="border-inactive-border-color hover:border-theme-color mb-4.5 flex h-[118px] w-full cursor-pointer items-center gap-4 rounded-[10px] border px-4 py-3.5"
@click="handleToKnowledgeDocument(item.id)"
>
<div class="flex flex-1 flex-col overflow-hidden">
<div class="flex flex-1">
<div
class="mt-[3px] h-9 w-9 flex-shrink-0 bg-[url(https://gsst-poe-sit.gz.bcebos.com/data/20241106/1730873304749.png)] bg-contain"
/>
<div class="ml-3.5 flex flex-col items-start overflow-hidden">
<n-ellipsis class="flex-1">
<span class="font-600">{{ item.knowledgeName }}</span>
</n-ellipsis>
<span class="text-gray-font-color mt-1 line-clamp-1 h-4 break-all text-xs">
{{ documentNameListText(item.documentInfos) }}
</span>
<div class="mt-3 flex items-center gap-4">
<span
v-show="!item.documentInfos?.length"
class="text-gray-font-color rounded-theme inline-block cursor-not-allowed bg-[#F7F7FA] px-2.5 py-[5px] text-[12px] leading-4"
>
{{ t('common_module.no_file') }}
</span>
<n-popover placement="bottom" content-style="padding: 16px 8px;" scrollable>
<template #trigger>
<span
v-show="item.documentInfos?.length"
class="text-theme-color rounded-theme inline-block cursor-pointer bg-[#F7F7FA] px-2.5 py-[5px] text-[12px] leading-4 hover:opacity-80"
>
{{ t('common_module.view_file') }}
</span>
</template>
<div>
<p class="text-gray-font-color h-5 px-4 text-[12px] leading-5">
{{
t(
'common_module.total_file',
{ count: item.documentInfos.length },
item.documentInfos.length,
)
}}
</p>
<n-scrollbar class="max-h-[200px] px-4">
<ul class="min-w-[300px]">
<li
v-for="documentItem in item.documentInfos"
:key="documentItem.kdId"
class="text-font-color flex h-[50px] cursor-pointer items-center gap-2.5 border-b border-[#F4F4F4] text-xs hover:opacity-80"
@click="handleToDocumentDetail(item.id, documentItem.kdId)"
>
<img :src="documentIcon(documentItem.documentName)" class="h-5.5 w-5.5" />
<n-ellipsis class="max-w-[400px]">
<span>{{ documentItem.documentName }}</span>
</n-ellipsis>
</li>
</ul>
</n-scrollbar>
</div>
</n-popover>
<span class="text-gray-font-color text-[12px]">
{{ t('common_module.created_time') }}:
{{ formatDateTime(item.createdTime, 'YYYY-MM-DD') || '--' }}
</span>
</div>
</div>
</div>
</div>
<n-button
v-show="!isAddedKdId(item.id)"
class="min-w-17!"
:bordered="addKdIdBtnDisabled"
:type="addKdIdBtnDisabled ? '' : 'primary'"
:disabled="addKdIdBtnDisabled"
@click.stop="handleAddKnowledgeId(item.id, item.knowledgeName)"
>
{{ t('common_module.add') }}
</n-button>
<n-button
v-show="isAddedKdId(item.id)"
class="min-w-17!"
type="error"
ghost
@click.stop="handleDeleteKnowledgeId(item.id, item.knowledgeName)"
>
{{ t('common_module.remove') }}
</n-button>
</div>
</template>
</n-virtual-list>
<div v-show="knowledgeListLoading" class="px-3">
<n-skeleton v-for="i in 4" :key="i" :height="118" :sharp="false" size="medium" class="mt-4.5" />
</div>
<div
v-show="!knowledgeListLoading && knowledgeList.length === 0"
class="flex h-[533px] items-center justify-center"
>
<div class="flex flex-col items-center justify-center">
<div
class="mb-5 h-[68px] w-[68px]"
:class="isSearchEmptyList ? 'bg-px-search_empty_list-png' : 'bg-px-empty_list-png'"
/>
<p class="text-gray-font-color select-none">{{ emptyKnowledgeListText }}</p>
</div>
</div>
</template>
<template #footer />
</CustomModal>
<CreateKnowledgeModal
v-model:is-show-modal="showCreateKnowledgeModal"
:btn-loading="createKnowledgeBtnLoading"
@confirm="handleCreateKnowledgeNextStep"
/>
</template>
......@@ -86,6 +86,14 @@ watch(
{ deep: true },
)
watch(
() => personalAppConfig.value.knowledgeConfig.knowledgeIds,
(newVal) => {
newVal && (isInitGetAgentAppDetail.value = true)
},
{ once: true },
)
onMounted(() => {
if (router.currentRoute.value.params.agentId) {
isInitGetAgentAppDetail.value = true
......
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import PageNarbar from './components/page-narbar.vue'
import PageNarBar from './components/page-narbar.vue'
import AppSetting from './components/app-setting.vue'
import AppPreview from './components/app-preview.vue'
import AppPublish from './components/app-publish.vue'
......@@ -29,8 +29,8 @@ function handleChangeAgentAppTabKey(currentTabKey: string) {
</script>
<template>
<main class="h-full min-w-[1000px]">
<PageNarbar @change-agent-app-tab-key="handleChangeAgentAppTabKey" />
<main class="h-full min-w-[1280px]">
<PageNarBar @change-agent-app-tab-key="handleChangeAgentAppTabKey" />
<div class="h-content flex w-full flex-1">
<div v-if="currentAgentAppTabKey === 'config'" class="flex h-full w-full flex-1">
......
......@@ -75,6 +75,12 @@ declare namespace I18n {
wipe_data: string
delete_all_tip_title: string
search: string
add: string
remove: string
add_knowledge: string
no_file: string
view_file: string
total_file: string
dialogue_module: {
continue_question_message: string
......@@ -255,6 +261,8 @@ declare namespace I18n {
memory_variable_delete_tip_content: string
memory_fragment_delete_all_tip_content: string
memory_fragment_delete_row_tip_content: string
add_knowledge_successfully: string
remove_knowledge_successfully: string
memory_variable_modal: {
edit_memory_variable: string
......
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