feat: add retriever rank fe (#1557)

Co-authored-by: StyleZhang <jasonapring2015@outlook.com>
This commit is contained in:
Joel 2023-11-18 11:53:35 +08:00 • committed by GitHub
commit 888e8c6dac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 2757 additions and 467 deletions

View file

@ -16,7 +16,7 @@ export type ICardItemProps = {
onRemove: (id: string) => void
readonly?: boolean
}
// used in universal-chat
const CardItem: FC<ICardItemProps> = ({
className,
config,

View file

@ -1,16 +1,22 @@
.card {
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
width: calc(50% - 4px);
width: 100%;
}
.card:hover {
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
}
.deleteBtn {
.btnWrap {
padding-left: 64px;
visibility: hidden;
background: linear-gradient(270deg, #FFF 49.99%, rgba(255, 255, 255, 0.00) 98.1%);
}
.card:hover .deleteBtn {
.card:hover .btnWrap {
visibility: visible;
}
.settingBtn:hover {
background-color: rgba(0, 0, 0, 0.05);
}

View file

@ -105,7 +105,6 @@ const DatasetConfig: FC = () => {
onChange={handleSelectContextVar}
/>
)}
</FeaturePanel>
)
}

View file

@ -4,96 +4,23 @@ import { memo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import cn from 'classnames'
import { HelpCircle, Settings04 } from '@/app/components/base/icons/src/vender/line/general'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import Tooltip from '@/app/components/base/tooltip-plus'
import Slider from '@/app/components/base/slider'
import Switch from '@/app/components/base/switch'
import { Settings04 } from '@/app/components/base/icons/src/vender/line/general'
import ConfigContext from '@/context/debug-configuration'
// TODO
const PARAMS_KEY = [
'top_k',
'score_threshold',
]
const PARAMS = {
top_k: {
default: 2,
step: 1,
min: 1,
max: 10,
},
score_threshold: {
default: 0.7,
step: 0.01,
min: 0,
max: 1,
},
} as any
export type IParamItemProps = {
id: string
name: string
tip: string
value: number
enable: boolean
step?: number
min?: number
max: number
onChange: (key: string, value: number) => void
onSwitchChange: (key: string, enable: boolean) => void
}
const ParamItem: FC<IParamItemProps> = ({ id, name, tip, step = 0.1, min = 0, max, value, enable, onChange, onSwitchChange }) => {
return (
<div>
<div className="flex items-center justify-between">
<div className="flex items-center">
{id === 'score_threshold' && (
<Switch
size='md'
defaultValue={enable}
onChange={async (val) => {
onSwitchChange(id, val)
}}
/>
)}
<span className="mx-1 text-gray-800 text-[13px] leading-[18px] font-medium">{name}</span>
<Tooltip popupContent={<div className="w-[200px]">{tip}</div>}>
<HelpCircle className='w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
<div className="flex items-center"></div>
</div>
<div className="mt-2 flex items-center justify-between">
<div className="flex items-center h-7">
<div className="w-[148px]">
<Slider
disabled={!enable}
value={max < 5 ? value * 100 : value}
min={min < 1 ? min * 100 : min}
max={max < 5 ? max * 100 : max}
onChange={value => onChange(id, value / (max < 5 ? 100 : 1))}
/>
</div>
</div>
<div className="flex items-center">
<input disabled={!enable} type="number" min={min} max={max} step={step} className="block w-[48px] h-7 text-xs leading-[18px] rounded-lg border-0 pl-1 pl py-1.5 bg-gray-50 text-gray-900 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-primary-600 disabled:opacity-60" value={value} onChange={(e) => {
const value = parseFloat(e.target.value)
if (value < min || value > max)
return
onChange(id, value)
}} />
</div>
</div>
</div>
)
}
import TopKItem from '@/app/components/base/param-item/top-k-item'
import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import RadioCard from '@/app/components/base/radio-card/simple'
import { RETRIEVE_TYPE } from '@/types/app'
import ModelSelector from '@/app/components/header/account-setting/model-page/model-selector'
import { useProviderContext } from '@/context/provider-context'
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import Toast from '@/app/components/base/toast'
import { DATASET_DEFAULT } from '@/config'
import {
MultiPathRetrieval,
NTo1Retrieval,
} from '@/app/components/base/icons/src/public/common'
const ParamsConfig: FC = () => {
const { t } = useTranslation()
@ -102,24 +29,47 @@ const ParamsConfig: FC = () => {
datasetConfigs,
setDatasetConfigs,
} = useContext(ConfigContext)
const [tempDataSetConfigs, setTempDataSetConfigs] = useState(datasetConfigs)
const type = tempDataSetConfigs.retrieval_model
const setType = (value: RETRIEVE_TYPE) => {
setTempDataSetConfigs({
...tempDataSetConfigs,
retrieval_model: value,
})
}
const {
rerankDefaultModel,
isRerankDefaultModelVaild,
} = useProviderContext()
const rerankModel = (() => {
if (tempDataSetConfigs.reranking_model) {
return {
provider_name: tempDataSetConfigs.reranking_model.reranking_provider_name,
model_name: tempDataSetConfigs.reranking_model.reranking_model_name,
}
}
else if (rerankDefaultModel) {
return {
provider_name: rerankDefaultModel.model_provider.provider_name,
model_name: rerankDefaultModel.model_name,
}
}
})()
const handleParamChange = (key: string, value: number) => {
let notOutRangeValue = parseFloat(value.toFixed(2))
notOutRangeValue = Math.max(PARAMS[key].min, notOutRangeValue)
notOutRangeValue = Math.min(PARAMS[key].max, notOutRangeValue)
if (key === 'top_k') {
setDatasetConfigs({
...datasetConfigs,
top_k: notOutRangeValue,
setTempDataSetConfigs({
...tempDataSetConfigs,
top_k: value,
})
}
else if (key === 'score_threshold') {
setDatasetConfigs({
...datasetConfigs,
[key]: {
enable: datasetConfigs.score_threshold.enable,
value: notOutRangeValue,
},
setTempDataSetConfigs({
...tempDataSetConfigs,
score_threshold: value,
})
}
}
@ -128,54 +78,133 @@ const ParamsConfig: FC = () => {
if (key === 'top_k')
return
setDatasetConfigs({
...datasetConfigs,
[key]: {
enable,
value: (datasetConfigs as any)[key].value,
},
setTempDataSetConfigs({
...tempDataSetConfigs,
score_threshold_enabled: enable,
})
}
const isValid = () => {
let errMsg = ''
if (tempDataSetConfigs.retrieval_model === RETRIEVE_TYPE.multiWay) {
if (!tempDataSetConfigs.reranking_model?.reranking_model_name && (!rerankDefaultModel && isRerankDefaultModelVaild))
errMsg = t('appDebug.datasetConfig.rerankModelRequired')
}
if (errMsg) {
Toast.notify({
type: 'error',
message: errMsg,
})
}
return !errMsg
}
const handleSave = () => {
if (!isValid())
return
const config = { ...tempDataSetConfigs }
if (config.retrieval_model === RETRIEVE_TYPE.multiWay && !config.reranking_model) {
config.reranking_model = {
reranking_provider_name: rerankDefaultModel?.model_provider.provider_name,
reranking_model_name: rerankDefaultModel?.model_name,
} as any
}
setDatasetConfigs(config)
setOpen(false)
}
return (
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-end'
offset={{
mainAxis: 4,
}}
>
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<div className={cn('flex items-center rounded-md h-7 px-3 space-x-1 text-gray-700 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}>
<Settings04 className="w-[14px] h-[14px]" />
<div className='text-xs font-medium'>
{t('appDebug.datasetConfig.params')}
</div>
<div>
<div
className={cn('flex items-center rounded-md h-7 px-3 space-x-1 text-gray-700 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}
onClick={() => {
setTempDataSetConfigs({
...datasetConfigs,
top_k: datasetConfigs.top_k || DATASET_DEFAULT.top_k,
score_threshold: datasetConfigs.score_threshold || DATASET_DEFAULT.score_threshold,
})
setOpen(true)
}}
>
<Settings04 className="w-[14px] h-[14px]" />
<div className='text-xs font-medium'>
{t('appDebug.datasetConfig.params')}
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent style={{ zIndex: 50 }}>
<div className='w-[240px] p-4 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg space-y-3'>
{PARAMS_KEY.map((key: string) => {
const currentValue = key === 'top_k' ? datasetConfigs[key] : (datasetConfigs as any)[key]?.value
const currentEnableState = key === 'top_k' ? true : (datasetConfigs as any)[key]?.enable
return (
<ParamItem
key={key}
id={key}
name={t(`appDebug.datasetConfig.${key}`)}
tip={t(`appDebug.datasetConfig.${key}Tip`)}
{...PARAMS[key]}
value={currentValue}
enable={currentEnableState}
onChange={handleParamChange}
onSwitchChange={handleSwitch}
</div>
{
open && (
<Modal
isShow={open}
onClose={() => {
setOpen(false)
}}
className='min-w-[528px]'
wrapperClassName='z-50'
title={t('appDebug.datasetConfig.settingTitle')}
>
<div className='mt-2 space-y-3'>
<RadioCard
icon={<NTo1Retrieval className='shrink-0 mr-3 w-9 h-9 rounded-lg' />}
title={t('appDebug.datasetConfig.retrieveOneWay.title')}
description={t('appDebug.datasetConfig.retrieveOneWay.description')}
isChosen={type === RETRIEVE_TYPE.oneWay}
onChosen={() => { setType(RETRIEVE_TYPE.oneWay) }}
/>
)
})}
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
<RadioCard
icon={<MultiPathRetrieval className='shrink-0 mr-3 w-9 h-9 rounded-lg' />}
title={t('appDebug.datasetConfig.retrieveMultiWay.title')}
description={t('appDebug.datasetConfig.retrieveMultiWay.description')}
isChosen={type === RETRIEVE_TYPE.multiWay}
onChosen={() => { setType(RETRIEVE_TYPE.multiWay) }}
/>
</div>
{type === RETRIEVE_TYPE.multiWay && (
<>
<div className='mt-6'>
<div className='leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.rerankModel.key')}</div>
<div>
<ModelSelector
popClassName='!max-w-[100%] !w-full'
value={rerankModel && { providerName: rerankModel.provider_name, modelName: rerankModel.model_name } as any}
modelType={ModelType.reranking}
onChange={(v) => {
setTempDataSetConfigs({
...tempDataSetConfigs,
reranking_model: {
reranking_provider_name: v.model_provider.provider_name,
reranking_model_name: v.model_name,
},
})
}}
/>
</div>
</div>
<div className='mt-4 space-y-4'>
<TopKItem
value={tempDataSetConfigs.top_k}
onChange={handleParamChange}
enable={true}
/>
<ScoreThresholdItem
value={tempDataSetConfigs.score_threshold}
onChange={handleParamChange}
enable={tempDataSetConfigs.score_threshold_enabled}
hasSwitch={true}
onSwitchChange={handleSwitch}
/>
</div>
</>
)}
<div className='mt-6 flex justify-end'>
<Button className='mr-2 flex-shrink-0' onClick={() => {
setOpen(false)
}}>{t('common.operation.cancel')}</Button>
<Button type='primary' className='flex-shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button>
</div>
</Modal>
)
}
</div>
)
}
export default memo(ParamsConfig)

View file

@ -1,8 +1,11 @@
import type { FC } from 'react'
import { useState } from 'react'
import { useRef, useState } from 'react'
import { useClickAway } from 'ahooks'
import { useTranslation } from 'react-i18next'
import { isEqual } from 'lodash-es'
import cn from 'classnames'
import { BookOpenIcon } from '@heroicons/react/24/outline'
import IndexMethodRadio from '@/app/components/datasets/settings/index-method-radio'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import ModelSelector from '@/app/components/header/account-setting/model-page/model-selector'
import type { ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations'
@ -11,12 +14,29 @@ import type { DataSet } from '@/models/datasets'
import { useToastContext } from '@/app/components/base/toast'
import { updateDatasetSetting } from '@/service/datasets'
import { useModalContext } from '@/context/modal-context'
import { XClose } from '@/app/components/base/icons/src/vender/line/general'
import type { RetrievalConfig } from '@/types/app'
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
import { useProviderContext } from '@/context/provider-context'
import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
import PermissionsRadio from '@/app/components/datasets/settings/permissions-radio'
type SettingsModalProps = {
currentDataset: DataSet
onCancel: () => void
onSave: (newDataset: DataSet) => void
}
const rowClass = `
flex justify-between py-4
`
const labelClass = `
flex w-[168px] shrink-0
`
const SettingsModal: FC<SettingsModalProps> = ({
currentDataset,
onCancel,
@ -24,13 +44,28 @@ const SettingsModal: FC<SettingsModalProps> = ({
}) => {
const { t } = useTranslation()
const { notify } = useToastContext()
const ref = useRef(null)
useClickAway(() => {
if (ref)
onCancel()
}, ref)
const { setShowAccountSettingModal } = useModalContext()
const [loading, setLoading] = useState(false)
const [localeCurrentDataset, setLocaleCurrentDataset] = useState({ ...currentDataset })
const [indexMethod, setIndexMethod] = useState(currentDataset.indexing_technique)
const [retrievalConfig, setRetrievalConfig] = useState(localeCurrentDataset?.retrieval_model_dict as RetrievalConfig)
const {
rerankDefaultModel,
isRerankDefaultModelVaild,
} = useProviderContext()
const handleValueChange = (type: string, value: string) => {
setLocaleCurrentDataset({ ...localeCurrentDataset, [type]: value })
}
const [isHideChangedTip, setIsHideChangedTip] = useState(false)
const isRetrievalChanged = !isEqual(retrievalConfig, localeCurrentDataset?.retrieval_model_dict) || indexMethod !== localeCurrentDataset?.indexing_technique
const handleSave = async () => {
if (loading)
@ -39,19 +74,41 @@ const SettingsModal: FC<SettingsModalProps> = ({
notify({ type: 'error', message: t('datasetSettings.form.nameError') })
return
}
if (
!isReRankModelSelected({
rerankDefaultModel,
isRerankDefaultModelVaild,
retrievalConfig,
indexMethod,
})
) {
notify({ type: 'error', message: t('appDebug.datasetConfig.rerankModelRequired') })
return
}
const postRetrievalConfig = ensureRerankModelSelected({
rerankDefaultModel: rerankDefaultModel!,
retrievalConfig,
indexMethod,
})
try {
setLoading(true)
const { id, name, description, indexing_technique } = localeCurrentDataset
const { id, name, description, permission } = localeCurrentDataset
await updateDatasetSetting({
datasetId: id,
body: {
name,
description,
indexing_technique,
permission,
indexing_technique: indexMethod,
retrieval_model: postRetrievalConfig,
},
})
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
onSave(localeCurrentDataset)
onSave({
...localeCurrentDataset,
indexing_technique: indexMethod,
retrieval_model_dict: postRetrievalConfig,
})
}
catch (e) {
notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') })
@ -62,74 +119,162 @@ const SettingsModal: FC<SettingsModalProps> = ({
}
return (
<Modal
isShow
onClose={() => {}}
className='!p-8 !pb-6 !max-w-none !w-[640px]'
<div
className='fixed top-16 right-2 flex flex-col bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl z-10'
style={{
zIndex: 11,
width: 700,
height: 'calc(100vh - 72px)',
}}
ref={ref}
>
<div className='mb-2 text-xl font-semibold text-gray-900'>
{t('datasetSettings.title')}
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'>
<div className='flex flex-col text-base font-semibold text-gray-900'>
<div className='leading-6'>{t('datasetSettings.title')}</div>
</div>
<div className='flex items-center'>
<div
onClick={onCancel}
className='flex justify-center items-center w-6 h-6 cursor-pointer'
>
<XClose className='w-4 h-4 text-gray-500' />
</div>
</div>
</div>
<div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'>
{t('datasetSettings.form.name')}
</div>
<input
value={localeCurrentDataset.name}
onChange={e => handleValueChange('name', e.target.value)}
className='block px-3 w-full h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none'
placeholder={t('datasetSettings.form.namePlaceholder') || ''}
/>
</div>
<div className='py-2'>
<div className='flex justify-between items-center mb-1 h-5 text-sm font-medium text-gray-900'>
{t('datasetSettings.form.desc')}
</div>
<div className='mb-2 text-xs text-gray-500'>
{t('datasetSettings.form.descInfo')}<a href='/' className='text-primary-600'>{t('common.operation.learnMore')}</a>
</div>
<textarea
value={localeCurrentDataset.description || ''}
onChange={e => handleValueChange('description', e.target.value)}
className='block px-3 py-2 w-full h-[88px] rounded-lg bg-gray-100 text-sm outline-none appearance-none resize-none'
placeholder={t('datasetSettings.form.descPlaceholder') || ''}
/>
</div>
<div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'>
{t('datasetSettings.form.indexMethod')}
</div>
<div>
<IndexMethodRadio
disable={!localeCurrentDataset?.embedding_available}
value={localeCurrentDataset.indexing_technique}
onChange={v => handleValueChange('indexing_technique', v!)}
itemClassName='!w-[282px]'
{/* Body */}
<div className='p-6 pt-5 border-b overflow-y-auto pb-[68px]' style={{
borderBottom: 'rgba(0, 0, 0, 0.05)',
}}>
<div className={cn(rowClass, 'items-center')}>
<div className={labelClass}>
{t('datasetSettings.form.name')}
</div>
<input
value={localeCurrentDataset.name}
onChange={e => handleValueChange('name', e.target.value)}
className='block px-3 w-full h-9 bg-gray-100 rounded-lg text-sm text-gray-900 outline-none appearance-none'
placeholder={t('datasetSettings.form.namePlaceholder') || ''}
/>
</div>
</div>
<div className='py-2'>
<div className='leading-9 text-sm font-medium text-gray-900'>
{t('datasetSettings.form.embeddingModel')}
<div className={cn(rowClass)}>
<div className={labelClass}>
{t('datasetSettings.form.desc')}
</div>
<div className='grow'>
<textarea
value={localeCurrentDataset.description || ''}
onChange={e => handleValueChange('description', e.target.value)}
className='block px-3 py-2 w-full h-[88px] rounded-lg bg-gray-100 text-sm outline-none appearance-none resize-none'
placeholder={t('datasetSettings.form.descPlaceholder') || ''}
/>
<a className='mt-2 flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/advanced/datasets#how-to-write-a-good-dataset-description" target='_blank'>
<BookOpenIcon className='w-3 h-[18px] mr-1' />
{t('datasetSettings.form.descWrite')}
</a>
</div>
</div>
<div className='w-full h-9 rounded-lg bg-gray-100 opacity-60'>
<ModelSelector
readonly
value={{
providerName: localeCurrentDataset.embedding_model_provider as ProviderEnum,
modelName: localeCurrentDataset.embedding_model,
}}
modelType={ModelType.embeddings}
onChange={() => {}}
/>
<div className={rowClass}>
<div className={labelClass}>
<div>{t('datasetSettings.form.permissions')}</div>
</div>
<div className='w-[480px]'>
<PermissionsRadio
disable={!localeCurrentDataset?.embedding_available}
value={localeCurrentDataset.permission}
onChange={v => handleValueChange('permission', v!)}
itemClassName='!w-[227px]'
/>
</div>
</div>
<div className='mt-2 w-full text-xs leading-6 text-gray-500'>
{t('datasetSettings.form.embeddingModelTip')}
<span className='text-[#155eef] cursor-pointer' onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('datasetSettings.form.embeddingModelTipLink')}</span>
<div className="w-full h-0 border-b-[0.5px] border-b-gray-200 my-2"></div>
<div className={cn(rowClass)}>
<div className={labelClass}>
{t('datasetSettings.form.indexMethod')}
</div>
<div className='grow'>
<IndexMethodRadio
disable={!localeCurrentDataset?.embedding_available}
value={indexMethod}
onChange={v => setIndexMethod(v!)}
itemClassName='!w-[227px]'
/>
</div>
</div>
{indexMethod === 'high_quality' && (
<div className={cn(rowClass)}>
<div className={labelClass}>
{t('datasetSettings.form.embeddingModel')}
</div>
<div className='grow'>
<div className='w-full h-9 rounded-lg bg-gray-100 opacity-60'>
<ModelSelector
readonly
value={{
providerName: localeCurrentDataset.embedding_model_provider as ProviderEnum,
modelName: localeCurrentDataset.embedding_model,
}}
modelType={ModelType.embeddings}
onChange={() => {}}
/>
</div>
<div className='mt-2 w-full text-xs leading-6 text-gray-500'>
{t('datasetSettings.form.embeddingModelTip')}
<span className='text-[#155eef] cursor-pointer' onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('datasetSettings.form.embeddingModelTipLink')}</span>
</div>
</div>
</div>
)}
{/* Retrieval Method Config */}
<div className={rowClass}>
<div className={labelClass}>
<div>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='leading-[18px] text-xs font-normal text-gray-500'>
<a target='_blank' href='https://docs.dify.ai/v/zh-hans/advanced/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
{t('datasetSettings.form.retrievalSetting.description')}
</div>
</div>
</div>
<div className='w-[480px]'>
{indexMethod === 'high_quality'
? (
<RetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)
: (
<EconomicalRetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)}
</div>
</div>
</div>
<div></div>
<div className='flex items-center justify-end mt-6'>
{isRetrievalChanged && !isHideChangedTip && (
<div className='absolute z-10 left-[30px] right-[30px] bottom-[76px] flex h-10 items-center px-3 rounded-lg border border-[#FEF0C7] bg-[#FFFAEB] shadow-lg justify-between'>
<div className='flex items-center'>
<AlertTriangle className='mr-1 w-3 h-3 text-[#F79009]' />
<div className='leading-[18px] text-xs font-medium text-gray-700'>{t('appDebug.datasetConfig.retrieveChangeTip')}</div>
</div>
<div className='p-1 cursor-pointer' onClick={(e) => {
setIsHideChangedTip(true)
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}}>
<XClose className='w-4 h-4 text-gray-500 ' />
</div>
</div>
)}
<div
className='absolute z-10 bottom-0 w-full flex justify-end py-4 px-6 border-t bg-white '
style={{
borderColor: 'rgba(0, 0, 0, 0.05)',
}}
>
<Button
onClick={onCancel}
className='mr-2 text-sm font-medium'
@ -145,7 +290,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
{t('common.operation.save')}
</Button>
</div>
</Modal>
</div>
)
}

View file

@ -37,7 +37,7 @@ import { fetchAppDetail, updateAppModelConfig } from '@/service/apps'
import { promptVariablesToUserInputsForm, userInputsFormToPromptVariables } from '@/utils/model-config'
import { fetchDatasets } from '@/service/datasets'
import { useProviderContext } from '@/context/provider-context'
import { AppType, ModelModeType, Resolution, TransferMethod } from '@/types/app'
import { AppType, ModelModeType, RETRIEVE_TYPE, Resolution, TransferMethod } from '@/types/app'
import { FlipBackward } from '@/app/components/base/icons/src/vender/line/arrows'
import { PromptMode } from '@/models/debug'
import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config'
@ -127,11 +127,14 @@ const Configuration: FC = () => {
})
const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>({
top_k: 2,
score_threshold: {
enable: false,
value: 0.7,
retrieval_model: RETRIEVE_TYPE.oneWay,
reranking_model: {
reranking_provider_name: '',
reranking_model_name: '',
},
top_k: 2,
score_threshold_enabled: false,
score_threshold: 0.7,
})
const setModelConfig = (newModelConfig: ModelConfig) => {
@ -391,7 +394,10 @@ const Configuration: FC = () => {
syncToPublishedConfig(config)
setPublishedConfig(config)
setDatasetConfigs(modelConfig.dataset_configs)
setDatasetConfigs({
retrieval_model: RETRIEVE_TYPE.oneWay,
...modelConfig.dataset_configs,
})
setHasFetchedDetail(true)
})
}, [appId])