Unverified Commit 888e8c6d authored by Joel's avatar Joel Committed by GitHub

feat: add retriever rank fe (#1557)

Co-authored-by: 's avatarStyleZhang <jasonapring2015@outlook.com>
parent e017eff5
...@@ -153,7 +153,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => { ...@@ -153,7 +153,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
return <Loading /> return <Loading />
return ( return (
<div className='flex' style={{ height: 'calc(100vh - 56px)' }}> <div className='flex'>
{!hideSideBar && <AppSideBar {!hideSideBar && <AppSideBar
title={datasetRes?.name || '--'} title={datasetRes?.name || '--'}
icon={datasetRes?.icon || 'https://static.dify.ai/images/dataset-default-icon.png'} icon={datasetRes?.icon || 'https://static.dify.ai/images/dataset-default-icon.png'}
...@@ -168,7 +168,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => { ...@@ -168,7 +168,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
dataset: datasetRes, dataset: datasetRes,
mutateDatasetRes: () => mutateDatasetRes(), mutateDatasetRes: () => mutateDatasetRes(),
}}> }}>
<div className="bg-white grow">{children}</div> <div className="bg-white grow" style={{ minHeight: 'calc(100vh - 56px)' }}>{children}</div>
</DatasetDetailContext.Provider> </DatasetDetailContext.Provider>
</div> </div>
) )
......
...@@ -16,7 +16,7 @@ export type ICardItemProps = { ...@@ -16,7 +16,7 @@ export type ICardItemProps = {
onRemove: (id: string) => void onRemove: (id: string) => void
readonly?: boolean readonly?: boolean
} }
// used in universal-chat
const CardItem: FC<ICardItemProps> = ({ const CardItem: FC<ICardItemProps> = ({
className, className,
config, config,
......
.card { .card {
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05); box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
width: calc(50% - 4px); width: 100%;
} }
.card:hover { .card:hover {
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06); 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; 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; visibility: visible;
}
.settingBtn:hover {
background-color: rgba(0, 0, 0, 0.05);
} }
\ No newline at end of file
...@@ -105,7 +105,6 @@ const DatasetConfig: FC = () => { ...@@ -105,7 +105,6 @@ const DatasetConfig: FC = () => {
onChange={handleSelectContextVar} onChange={handleSelectContextVar}
/> />
)} )}
</FeaturePanel> </FeaturePanel>
) )
} }
......
...@@ -37,7 +37,7 @@ import { fetchAppDetail, updateAppModelConfig } from '@/service/apps' ...@@ -37,7 +37,7 @@ import { fetchAppDetail, updateAppModelConfig } from '@/service/apps'
import { promptVariablesToUserInputsForm, userInputsFormToPromptVariables } from '@/utils/model-config' import { promptVariablesToUserInputsForm, userInputsFormToPromptVariables } from '@/utils/model-config'
import { fetchDatasets } from '@/service/datasets' import { fetchDatasets } from '@/service/datasets'
import { useProviderContext } from '@/context/provider-context' 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 { FlipBackward } from '@/app/components/base/icons/src/vender/line/arrows'
import { PromptMode } from '@/models/debug' import { PromptMode } from '@/models/debug'
import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config' import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config'
...@@ -127,11 +127,14 @@ const Configuration: FC = () => { ...@@ -127,11 +127,14 @@ const Configuration: FC = () => {
}) })
const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>({ const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>({
top_k: 2, retrieval_model: RETRIEVE_TYPE.oneWay,
score_threshold: { reranking_model: {
enable: false, reranking_provider_name: '',
value: 0.7, reranking_model_name: '',
}, },
top_k: 2,
score_threshold_enabled: false,
score_threshold: 0.7,
}) })
const setModelConfig = (newModelConfig: ModelConfig) => { const setModelConfig = (newModelConfig: ModelConfig) => {
...@@ -391,7 +394,10 @@ const Configuration: FC = () => { ...@@ -391,7 +394,10 @@ const Configuration: FC = () => {
syncToPublishedConfig(config) syncToPublishedConfig(config)
setPublishedConfig(config) setPublishedConfig(config)
setDatasetConfigs(modelConfig.dataset_configs) setDatasetConfigs({
retrieval_model: RETRIEVE_TYPE.oneWay,
...modelConfig.dataset_configs,
})
setHasFetchedDetail(true) setHasFetchedDetail(true)
}) })
}, [appId]) }, [appId])
......
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_13429_43710)">
<rect width="36" height="36" rx="8" fill="#FFF6ED"/>
<path opacity="0.7" d="M22.25 28C22.25 29.7949 20.7949 31.25 19 31.25C17.2051 31.25 15.75 29.7949 15.75 28C15.75 26.2051 17.2051 24.75 19 24.75C20.7949 24.75 22.25 26.2051 22.25 28Z" stroke="#FB6514" stroke-width="1.5"/>
<path d="M19 12C21.2091 12 23 10.2091 23 8C23 5.79086 21.2091 4 19 4C16.7909 4 15 5.79086 15 8C15 10.2091 16.7909 12 19 12Z" fill="#FB6514"/>
<path d="M15 22C17.2091 22 19 20.2091 19 18C19 15.7909 17.2091 14 15 14C12.7909 14 11 15.7909 11 18C11 20.2091 12.7909 22 15 22Z" fill="#FB6514"/>
<path d="M36 23C38.7614 23 41 20.7614 41 18C41 15.2386 38.7614 13 36 13C33.2386 13 31 15.2386 31 18C31 20.7614 33.2386 23 36 23Z" fill="#FB6514"/>
<path d="M0 18H10" stroke="#FB6514" stroke-width="1.5"/>
<path d="M20 18L30 18" stroke="#FB6514" stroke-width="1.5"/>
<path d="M0.00112438 15C0.00112438 15 -5.64364 15 0.851673 15C7.34699 15 7.84654 8 14 8" stroke="#FB6514" stroke-width="1.5"/>
<path d="M23.75 9.28125C26.5688 10.1847 27.699 13.2045 30.625 15.0312" stroke="#FB6514" stroke-width="1.5"/>
<path opacity="0.7" d="M-0.000543833 21C-0.000543833 21 -5.57819 21 0.893635 21C7.36546 21 7.8688 28 14 28" stroke="#FB6514" stroke-width="1.5"/>
</g>
<defs>
<clipPath id="clip0_13429_43710">
<rect width="36" height="36" rx="8" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_13429_43700)">
<rect width="36" height="36" rx="8" fill="#EEF4FF"/>
<path opacity="0.7" d="M23.25 28C23.25 29.7949 21.7949 31.25 20 31.25C18.2051 31.25 16.75 29.7949 16.75 28C16.75 26.2051 18.2051 24.75 20 24.75C21.7949 24.75 23.25 26.2051 23.25 28Z" stroke="#444CE7" stroke-width="1.5"/>
<path opacity="0.7" d="M23.25 8C23.25 9.79493 21.7949 11.25 20 11.25C18.2051 11.25 16.75 9.79493 16.75 8C16.75 6.20507 18.2051 4.75 20 4.75C21.7949 4.75 23.25 6.20507 23.25 8Z" stroke="#444CE7" stroke-width="1.5"/>
<path d="M16 22C18.2091 22 20 20.2091 20 18C20 15.7909 18.2091 14 16 14C13.7909 14 12 15.7909 12 18C12 20.2091 13.7909 22 16 22Z" fill="#444CE7"/>
<path d="M36 23C38.7614 23 41 20.7614 41 18C41 15.2386 38.7614 13 36 13C33.2386 13 31 15.2386 31 18C31 20.7614 33.2386 23 36 23Z" fill="#444CE7"/>
<path d="M0 18L11 18" stroke="#444CE7" stroke-width="1.5"/>
<path d="M21 18L30 18" stroke="#444CE7" stroke-width="1.5"/>
<path opacity="0.7" d="M-0.00160408 15C-0.00160408 15 -6.00089 15 1.12411 15C8.24911 15 8.24908 8.25 14.9991 8.25" stroke="#444CE7" stroke-width="1.5"/>
<path opacity="0.7" d="M0.000488281 21C0.000488281 21 -5.92692 21 1.17228 21C8.27148 21 8.27423 27.75 14.9998 27.75" stroke="#444CE7" stroke-width="1.5"/>
</g>
<defs>
<clipPath id="clip0_13429_43700">
<rect width="36" height="36" rx="8" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="120" height="24" viewBox="0 0 120 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M34.4917 21.9129C37.4378 21.9129 40.0162 20.4398 41.0355 17.4656C41.2334 16.8701 40.9496 16.4743 40.384 16.4743H39.2787C38.7689 16.4743 38.4292 16.7002 38.2013 17.1818C37.3239 18.9108 36.1047 19.5324 34.5757 19.5324C31.8553 19.5324 30.1844 17.6335 30.1844 14.4616C30.1844 11.2896 31.9133 9.39083 34.5177 9.39083C36.1046 9.39083 37.4079 10.0704 38.2293 11.6854C38.4852 12.1671 38.795 12.3929 39.3067 12.3929H40.412C40.9776 12.3929 41.2614 12.0251 41.0635 11.4855C39.8742 8.25556 37.2099 7.01035 34.4917 7.01035C30.3843 7.01035 27.3242 10.0424 27.3242 14.4616C27.3242 18.8808 30.2424 21.9129 34.4917 21.9129ZM108.627 13.1584C108.995 10.75 110.638 9.24892 112.876 9.24892C115.115 9.24892 116.786 10.7779 116.983 13.1584H108.627ZM112.99 21.9129C115.596 21.9129 118.203 20.6956 119.478 17.9474C119.79 17.2958 119.506 16.8421 118.94 16.8421H117.892C117.383 16.8421 117.071 17.0679 116.816 17.5216C115.966 19.0227 114.493 19.6463 112.992 19.6463C110.414 19.6463 108.743 17.8894 108.545 15.0292H118.943C119.508 15.0292 119.878 14.7174 119.878 14.1219C119.764 9.67465 116.876 7.01235 112.88 7.01235C108.885 7.01235 105.713 9.90251 105.713 14.4636C105.713 19.0247 108.801 21.9148 112.994 21.9148L112.99 21.9129ZM96.5025 14.8313H97.4378C98.0035 14.8313 98.3152 14.5196 98.4012 13.9239C98.9409 10.0964 101.182 9.5887 103.564 9.70264C104.074 9.72661 104.491 9.33487 104.491 8.82319V7.94575C104.491 7.38012 104.208 7.03833 103.642 7.01035C101.533 6.9304 99.6525 7.65393 98.5651 9.70264C98.5052 9.81455 98.3373 9.78458 98.3233 9.65866L98.1474 8.11365C98.0915 7.54801 97.7796 7.26418 97.212 7.26418H92.9347C92.435 7.26418 92.0272 7.66993 92.0272 8.17161V8.6533C92.0272 9.15298 92.433 9.56072 92.9347 9.56072H94.6916C95.1912 9.56072 95.599 9.96646 95.599 10.4681V13.9239C95.599 14.4236 96.0048 14.8313 96.5064 14.8313H96.5025ZM92.6788 21.631H101.545C102.111 21.631 102.453 21.2913 102.453 20.7236V20.2418C102.453 19.6762 102.113 19.3345 101.545 19.3345H99.2787C98.7131 19.3345 98.3712 18.9947 98.3712 18.4271V16.8681C98.3712 16.3024 98.0315 15.9606 97.4638 15.9606H96.5005C95.9348 15.9606 95.593 16.3004 95.593 16.8681V18.4271C95.593 18.9927 95.2532 19.3345 94.6856 19.3345H92.6749C92.1092 19.3345 91.7674 19.6743 91.7674 20.2418V20.7236C91.7674 21.2893 92.1073 21.631 92.6749 21.631H92.6788ZM78.9955 13.1604C79.3633 10.752 81.0062 9.25092 83.2449 9.25092C85.4834 9.25092 87.1544 10.7799 87.3522 13.1604H78.9955ZM83.3587 21.9148C85.9651 21.9148 88.5714 20.6977 89.8466 17.9493C90.1585 17.2978 89.8746 16.844 89.309 16.844H88.2617C87.7519 16.844 87.4402 17.0699 87.1844 17.5236C86.3349 19.0247 84.8618 19.6482 83.3607 19.6482C80.7824 19.6482 79.1115 17.8914 78.9136 15.0313H89.311C89.8766 15.0313 90.2464 14.7194 90.2464 14.1238C90.1324 9.67665 87.2443 7.01434 83.2488 7.01434C79.2533 7.01434 76.0814 9.9045 76.0814 14.4656C76.0814 19.0266 79.1694 21.9168 83.3628 21.9168L83.3587 21.9148ZM50.5835 21.9148C54.8329 21.9148 57.8649 18.7708 57.8649 14.4636C57.8649 10.1563 54.8329 7.01235 50.5835 7.01235C46.3342 7.01235 43.3022 10.2143 43.3022 14.4636C43.3022 15.455 43.472 16.5602 43.9816 17.7775C44.2375 18.3731 44.7192 18.4571 45.2289 18.0892L46.0504 17.4936C46.4761 17.1818 46.588 16.8141 46.4461 16.2765C46.2202 15.5689 46.1623 14.9453 46.1623 14.4076C46.1623 11.4335 47.9472 9.39283 50.5815 9.39283C53.2159 9.39283 55.0007 11.4035 55.0007 14.4636C55.0007 17.5236 53.2439 19.5344 50.6375 19.5344C49.7301 19.5344 48.8806 19.3645 47.8612 18.5989C47.4355 18.2592 47.0397 18.2032 46.586 18.5429L45.9624 18.9967C45.4527 19.3645 45.3968 19.8741 45.8764 20.2718C47.3496 21.4611 49.0485 21.9148 50.5795 21.9148H50.5835ZM61.4606 21.631H62.3961C62.8957 21.631 63.3035 21.2252 63.3035 20.7236V13.9539C63.3035 11.0937 64.8324 9.39283 67.213 9.39283C69.3656 9.39283 70.6128 10.8099 70.6128 13.4163V20.7255C70.6128 21.2252 71.0186 21.633 71.5203 21.633H72.4836C72.9833 21.633 73.391 21.2272 73.391 20.7255V12.9625C73.391 9.13899 71.4363 7.01434 68.1224 7.01434C65.8659 7.01434 64.5327 7.93776 63.5373 9.22294C63.4613 9.32088 63.3075 9.26691 63.3075 9.14499V2.99092C63.3014 2.48924 62.8957 2.0835 62.3961 2.0835H61.4606C60.9609 2.0835 60.5532 2.48924 60.5532 2.99092V20.7236C60.5532 21.2232 60.959 21.631 61.4606 21.631Z" fill="#39594D"/>
<mask id="mask0_13223_52628" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="1" y="2" width="20" height="20">
<path d="M20.8354 2.08319H1.00195V21.9165H20.8354V2.08319Z" fill="white"/>
</mask>
<g mask="url(#mask0_13223_52628)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.42768 13.8921C7.96151 13.8921 9.02342 13.8628 10.4912 13.2585C12.2017 12.5542 15.6047 11.2758 18.0597 9.96274C19.7765 9.04432 20.5291 7.82964 20.5291 6.19387C20.5291 3.92362 18.6887 2.08319 16.4185 2.08319H6.90643C3.64547 2.08319 1.00195 4.72669 1.00195 7.98763C1.00195 11.2486 3.47706 13.8921 7.42768 13.8921Z" fill="#39594D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.03711 17.958C9.03711 16.3596 9.99942 14.9184 11.4758 14.3057L14.4713 13.0625C17.5013 11.805 20.8364 14.0316 20.8364 17.3123C20.8364 19.8539 18.7755 21.9141 16.2338 21.9134L12.9906 21.9126C10.807 21.912 9.03711 20.1417 9.03711 17.958Z" fill="#D18EE2"/>
<path d="M4.40571 14.6705C2.5259 14.6705 1.00195 16.1943 1.00195 18.0741V18.515C1.00195 20.3947 2.52584 21.9186 4.40565 21.9186C6.28547 21.9186 7.80941 20.3947 7.80941 18.515V18.0741C7.80941 16.1943 6.28552 14.6705 4.40571 14.6705Z" fill="#FF7759"/>
</g>
</svg>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Clip path group">
<mask id="mask0_13224_9519" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="22" height="22">
<g id="clip0_2207_90691">
<path id="Vector" d="M21.5 0.5H0.5V21.5H21.5V0.5Z" fill="white"/>
</g>
</mask>
<g mask="url(#mask0_13224_9519)">
<g id="Group">
<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M7.30367 13.0035C7.8689 13.0035 8.99327 12.9725 10.5474 12.3326C12.3585 11.587 15.9617 10.2334 18.561 8.84305C20.3788 7.8706 21.1757 6.58448 21.1757 4.85248C21.1757 2.44869 19.2271 0.5 16.8233 0.5H6.75176C3.299 0.5 0.5 3.299 0.5 6.75176C0.5 10.2045 3.12069 13.0035 7.30367 13.0035Z" fill="#39594D"/>
<path id="Vector_3" fill-rule="evenodd" clip-rule="evenodd" d="M9.00732 17.3086C9.00732 15.6162 10.0262 14.0902 11.5894 13.4414L14.7612 12.1251C17.9694 10.7936 21.5006 13.1513 21.5006 16.6249C21.5006 19.316 19.3185 21.4974 16.6273 21.4967L13.1933 21.4958C10.8813 21.4952 9.00732 19.6207 9.00732 17.3086Z" fill="#D18EE2"/>
<path id="Vector_4" d="M4.10396 13.8277C2.11358 13.8277 0.5 15.4411 0.5 17.4315V17.8984C0.5 19.8887 2.11352 21.5022 4.1039 21.5022C6.09428 21.5022 7.70785 19.8887 7.70785 17.8984V17.4315C7.70785 15.4411 6.09434 13.8277 4.10396 13.8277Z" fill="#FF7759"/>
</g>
</g>
</g>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.01488 2.54553C8.91549 2.45869 8.79321 2.40229 8.66264 2.38306C8.53206 2.36384 8.39872 2.38261 8.27852 2.43712C8.15833 2.49164 8.05636 2.5796 7.98481 2.6905C7.91325 2.8014 7.87513 2.93055 7.875 3.06253V6.50003C6.05164 6.50003 4.30295 7.22436 3.01364 8.51367C1.72433 9.80299 1 11.5517 1 13.375C1 15.1984 1.72433 16.9471 3.01364 18.2364C4.30295 19.5257 6.05164 20.25 7.875 20.25H12C12.3647 20.25 12.7144 20.1052 12.9723 19.8473C13.2301 19.5894 13.375 19.2397 13.375 18.875C13.375 18.5104 13.2301 18.1606 12.9723 17.9028C12.7144 17.6449 12.3647 17.5 12 17.5H7.875C6.78098 17.5 5.73177 17.0654 4.95818 16.2919C4.1846 15.5183 3.75 14.4691 3.75 13.375C3.75 12.281 4.1846 11.2318 4.95818 10.4582C5.73177 9.68463 6.78098 9.25003 7.875 9.25003V12.6875C7.87513 12.8195 7.91325 12.9487 7.98481 13.0596C8.05636 13.1705 8.15833 13.2584 8.27852 13.3129C8.39872 13.3675 8.53206 13.3862 8.66264 13.367C8.79321 13.3478 8.91549 13.2914 9.01488 13.2045L14.5149 8.39203C14.5885 8.32751 14.6475 8.24801 14.6879 8.15885C14.7283 8.06969 14.7492 7.97292 14.7492 7.87503C14.7492 7.77714 14.7283 7.68038 14.6879 7.59122C14.6475 7.50206 14.5885 7.42256 14.5149 7.35803L9.01488 2.54553Z" fill="#212121"/>
<path d="M21.625 17.5H17.5C17.1353 17.5 16.7856 17.6449 16.5277 17.9028C16.2699 18.1606 16.125 18.5104 16.125 18.875C16.125 19.2397 16.2699 19.5894 16.5277 19.8473C16.7856 20.1052 17.1353 20.25 17.5 20.25H21.625C21.9897 20.25 22.3394 20.1052 22.5973 19.8473C22.8551 19.5894 23 19.2397 23 18.875C23 18.5104 22.8551 18.1606 22.5973 17.9028C22.3394 17.6449 21.9897 17.5 21.625 17.5Z" fill="#212121"/>
<path d="M21.625 12H17.5C17.1353 12 16.7856 12.1449 16.5277 12.4028C16.2699 12.6606 16.125 13.0104 16.125 13.375C16.125 13.7397 16.2699 14.0894 16.5277 14.3473C16.7856 14.6052 17.1353 14.75 17.5 14.75H21.625C21.9897 14.75 22.3394 14.6052 22.5973 14.3473C22.8551 14.0894 23 13.7397 23 13.375C23 13.0104 22.8551 12.6606 22.5973 12.4028C22.3394 12.1449 21.9897 12 21.625 12Z" fill="#212121"/>
<path d="M17.5 9.25003H21.625C21.9897 9.25003 22.3394 9.10517 22.5973 8.8473C22.8551 8.58944 23 8.23971 23 7.87503C23 7.51036 22.8551 7.16062 22.5973 6.90276C22.3394 6.6449 21.9897 6.50003 21.625 6.50003H17.5C17.1353 6.50003 16.7856 6.6449 16.5277 6.90276C16.2699 7.16062 16.125 7.51036 16.125 7.87503C16.125 8.23971 16.2699 8.58944 16.5277 8.8473C16.7856 9.10517 17.1353 9.25003 17.5 9.25003Z" fill="#212121"/>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.72727 22C4.18787 22 3.66058 21.84 3.21208 21.5404C2.76359 21.2407 2.41402 20.8148 2.2076 20.3164C2.00118 19.8181 1.94717 19.2697 2.05241 18.7407C2.15764 18.2116 2.41739 17.7257 2.7988 17.3443C3.18022 16.9628 3.66617 16.7031 4.19521 16.5979C4.72425 16.4926 5.27261 16.5466 5.77096 16.7531C6.2693 16.9595 6.69524 17.309 6.99492 17.7575C7.2946 18.206 7.45455 18.7333 7.45455 19.2727C7.45455 19.996 7.16721 20.6897 6.65575 21.2012C6.14429 21.7127 5.45059 22 4.72727 22Z" fill="#212121"/>
<path d="M12 9.27273C11.4606 9.27273 10.9333 9.43268 10.4848 9.73236C10.0363 10.032 9.68675 10.458 9.48033 10.9563C9.27391 11.4547 9.2199 12.003 9.32513 12.5321C9.43036 13.0611 9.69011 13.5471 10.0715 13.9285C10.4529 14.3099 10.9389 14.5696 11.4679 14.6749C11.997 14.7801 12.5453 14.7261 13.0437 14.5197C13.542 14.3133 13.968 13.9637 14.2676 13.5152C14.5673 13.0667 14.7273 12.5394 14.7273 12C14.7273 11.2767 14.4399 10.583 13.9285 10.0715C13.417 9.56006 12.7233 9.27273 12 9.27273Z" fill="#212121"/>
<path d="M4.72727 2C4.18787 2 3.66058 2.15995 3.21208 2.45963C2.76358 2.7593 2.41402 3.18525 2.2076 3.68359C2.00118 4.18193 1.94717 4.7303 2.05241 5.25934C2.15764 5.78838 2.41738 6.27433 2.7988 6.65575C3.18022 7.03716 3.66617 7.29691 4.19521 7.40214C4.72425 7.50737 5.27261 7.45336 5.77096 7.24694C6.2693 7.04052 6.69524 6.69096 6.99492 6.24246C7.29459 5.79397 7.45455 5.26668 7.45455 4.72727C7.45455 4.00395 7.16721 3.31026 6.65575 2.7988C6.14428 2.28734 5.45059 2 4.72727 2Z" fill="#212121"/>
<path d="M19.2727 2C18.7333 2 18.206 2.15995 17.7575 2.45963C17.309 2.75931 16.9595 3.18525 16.7531 3.68359C16.5466 4.18194 16.4926 4.7303 16.5979 5.25934C16.7031 5.78838 16.9628 6.27433 17.3443 6.65575C17.7257 7.03716 18.2116 7.29691 18.7407 7.40214C19.2697 7.50737 19.8181 7.45337 20.3164 7.24694C20.8148 7.04052 21.2407 6.69096 21.5404 6.24247C21.84 5.79397 22 5.26668 22 4.72727C22 4.00396 21.7127 3.31026 21.2012 2.7988C20.6897 2.28734 19.996 2 19.2727 2Z" fill="#212121"/>
<path d="M19.2727 16.5455C18.7333 16.5455 18.206 16.7054 17.7575 17.0051C17.309 17.3048 16.9595 17.7307 16.7531 18.229C16.5466 18.7274 16.4926 19.2758 16.5979 19.8048C16.7031 20.3338 16.9628 20.8198 17.3443 21.2012C17.7257 21.5826 18.2116 21.8424 18.7407 21.9476C19.2697 22.0528 19.8181 21.9988 20.3164 21.7924C20.8148 21.586 21.2407 21.2364 21.5404 20.7879C21.84 20.3394 22 19.8121 22 19.2727C22 18.5494 21.7127 17.8557 21.2012 17.3443C20.6897 16.8328 19.996 16.5455 19.2727 16.5455Z" fill="#212121"/>
<path d="M7.45455 9.27273H2V14.7273H7.45455V9.27273Z" fill="#212121"/>
<path d="M22 9.27273H16.5455V14.7273H22V9.27273Z" fill="#212121"/>
<path d="M14.7273 2H9.27273V7.45455H14.7273V2Z" fill="#212121"/>
<path d="M14.7273 16.5455H9.27273V22H14.7273V16.5455Z" fill="#212121"/>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.5833 12.945C16.4856 13.3276 16.2038 14.272 15.7382 15.7784H17.4432C17.0038 14.3674 16.7569 13.5692 16.7025 13.3841C16.6493 13.1998 16.609 13.0532 16.5833 12.945Z" fill="#212121"/>
<path d="M21.1667 9.33333H12C11.5138 9.33333 11.0475 9.52649 10.7036 9.87031C10.3598 10.2141 10.1667 10.6804 10.1667 11.1667V19.4167C10.1667 19.9029 10.3598 20.3692 10.7036 20.713C11.0475 21.0568 11.5138 21.25 12 21.25H17.5L21.1667 24V21.25C21.6529 21.25 22.1192 21.0568 22.463 20.713C22.8068 20.3692 23 19.9029 23 19.4167V11.1667C23 10.6804 22.8068 10.2141 22.463 9.87031C22.1192 9.52649 21.6529 9.33333 21.1667 9.33333ZM18.2507 18.5L17.775 16.9417H15.3917L14.9159 18.5H13.4208L15.7308 11.9293H17.4267L19.7458 18.5H18.2507Z" fill="#212121"/>
<path d="M12 2H2.83333C2.3471 2 1.88079 2.19315 1.53697 2.53697C1.19315 2.88079 1 3.3471 1 3.83333V12.0833C1 12.5696 1.19315 13.0359 1.53697 13.3797C1.88079 13.7235 2.3471 13.9167 2.83333 13.9167V16.6667L6.5 13.9167H9.25V11.1667C9.25381 11.0459 9.26606 10.9255 9.28667 10.8064C8.64229 10.5527 8.0315 10.2208 7.468 9.81825C6.5802 10.4316 5.59355 10.8877 4.55117 11.1667C4.394 10.6965 4.15573 10.2575 3.84717 9.86958C4.76378 9.70375 5.64426 9.37861 6.44867 8.90892C6.07755 8.50417 5.75993 8.05346 5.50358 7.56783C5.29175 7.16889 5.12217 6.74892 4.99758 6.31475C4.56583 6.31475 4.3165 6.32942 3.94983 6.35875V5.03233C4.30266 5.0703 4.65741 5.08744 5.01225 5.08367H6.63292V4.64367C6.63379 4.48979 6.61904 4.33623 6.58892 4.18533H8.05833C8.02877 4.33229 8.01403 4.48185 8.01433 4.63175V5.07908H9.756C10.1108 5.08303 10.4656 5.06589 10.8184 5.02775V6.35875C10.4958 6.32942 10.2098 6.31475 9.778 6.31475C9.67623 6.80565 9.51074 7.28115 9.28575 7.72917C9.06864 8.16083 8.79489 8.56159 8.47175 8.92083C8.89523 9.17057 9.34617 9.37051 9.81558 9.51667C10.0695 9.17655 10.399 8.90012 10.7781 8.70922C11.1573 8.51831 11.5755 8.41816 12 8.41667H13.8333V3.83333C13.8333 3.3471 13.6402 2.88079 13.2964 2.53697C12.9525 2.19315 12.4862 2 12 2Z" fill="#212121"/>
<path d="M7.43133 8.0885C7.87722 7.58102 8.19195 6.97201 8.348 6.31475H6.40833C6.59708 6.98164 6.94861 7.59116 7.43133 8.0885Z" fill="#212121"/>
</svg>
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "36",
"height": "36",
"viewBox": "0 0 36 36",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"clip-path": "url(#clip0_13429_43710)"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "36",
"height": "36",
"rx": "8",
"fill": "#FFF6ED"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M22.25 28C22.25 29.7949 20.7949 31.25 19 31.25C17.2051 31.25 15.75 29.7949 15.75 28C15.75 26.2051 17.2051 24.75 19 24.75C20.7949 24.75 22.25 26.2051 22.25 28Z",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M19 12C21.2091 12 23 10.2091 23 8C23 5.79086 21.2091 4 19 4C16.7909 4 15 5.79086 15 8C15 10.2091 16.7909 12 19 12Z",
"fill": "#FB6514"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M15 22C17.2091 22 19 20.2091 19 18C19 15.7909 17.2091 14 15 14C12.7909 14 11 15.7909 11 18C11 20.2091 12.7909 22 15 22Z",
"fill": "#FB6514"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M36 23C38.7614 23 41 20.7614 41 18C41 15.2386 38.7614 13 36 13C33.2386 13 31 15.2386 31 18C31 20.7614 33.2386 23 36 23Z",
"fill": "#FB6514"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M0 18H10",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M20 18L30 18",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M0.00112438 15C0.00112438 15 -5.64364 15 0.851673 15C7.34699 15 7.84654 8 14 8",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M23.75 9.28125C26.5688 10.1847 27.699 13.2045 30.625 15.0312",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M-0.000543833 21C-0.000543833 21 -5.57819 21 0.893635 21C7.36546 21 7.8688 28 14 28",
"stroke": "#FB6514",
"stroke-width": "1.5"
},
"children": []
}
]
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "clipPath",
"attributes": {
"id": "clip0_13429_43710"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "36",
"height": "36",
"rx": "8",
"fill": "white"
},
"children": []
}
]
}
]
}
]
},
"name": "MultiPathRetrieval"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './MultiPathRetrieval.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'MultiPathRetrieval'
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "36",
"height": "36",
"viewBox": "0 0 36 36",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"clip-path": "url(#clip0_13429_43700)"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "36",
"height": "36",
"rx": "8",
"fill": "#EEF4FF"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M23.25 28C23.25 29.7949 21.7949 31.25 20 31.25C18.2051 31.25 16.75 29.7949 16.75 28C16.75 26.2051 18.2051 24.75 20 24.75C21.7949 24.75 23.25 26.2051 23.25 28Z",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M23.25 8C23.25 9.79493 21.7949 11.25 20 11.25C18.2051 11.25 16.75 9.79493 16.75 8C16.75 6.20507 18.2051 4.75 20 4.75C21.7949 4.75 23.25 6.20507 23.25 8Z",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M16 22C18.2091 22 20 20.2091 20 18C20 15.7909 18.2091 14 16 14C13.7909 14 12 15.7909 12 18C12 20.2091 13.7909 22 16 22Z",
"fill": "#444CE7"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M36 23C38.7614 23 41 20.7614 41 18C41 15.2386 38.7614 13 36 13C33.2386 13 31 15.2386 31 18C31 20.7614 33.2386 23 36 23Z",
"fill": "#444CE7"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M0 18L11 18",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M21 18L30 18",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M-0.00160408 15C-0.00160408 15 -6.00089 15 1.12411 15C8.24911 15 8.24908 8.25 14.9991 8.25",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"opacity": "0.7",
"d": "M0.000488281 21C0.000488281 21 -5.92692 21 1.17228 21C8.27148 21 8.27423 27.75 14.9998 27.75",
"stroke": "#444CE7",
"stroke-width": "1.5"
},
"children": []
}
]
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "clipPath",
"attributes": {
"id": "clip0_13429_43700"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "36",
"height": "36",
"rx": "8",
"fill": "white"
},
"children": []
}
]
}
]
}
]
},
"name": "NTo1Retrieval"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './NTo1Retrieval.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'NTo1Retrieval'
export default Icon
export { default as Dify } from './Dify' export { default as Dify } from './Dify'
export { default as Github } from './Github' export { default as Github } from './Github'
export { default as MessageChatSquare } from './MessageChatSquare' export { default as MessageChatSquare } from './MessageChatSquare'
export { default as MultiPathRetrieval } from './MultiPathRetrieval'
export { default as NTo1Retrieval } from './NTo1Retrieval'
export { default as Notion } from './Notion' export { default as Notion } from './Notion'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "22",
"height": "22",
"viewBox": "0 0 22 22",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Clip path group"
},
"children": [
{
"type": "element",
"name": "mask",
"attributes": {
"id": "mask0_13224_9519",
"style": "mask-type:luminance",
"maskUnits": "userSpaceOnUse",
"x": "0",
"y": "0",
"width": "22",
"height": "22"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "clip0_2207_90691"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector",
"d": "M21.5 0.5H0.5V21.5H21.5V0.5Z",
"fill": "white"
},
"children": []
}
]
}
]
},
{
"type": "element",
"name": "g",
"attributes": {
"mask": "url(#mask0_13224_9519)"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Group"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_2",
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M7.30367 13.0035C7.8689 13.0035 8.99327 12.9725 10.5474 12.3326C12.3585 11.587 15.9617 10.2334 18.561 8.84305C20.3788 7.8706 21.1757 6.58448 21.1757 4.85248C21.1757 2.44869 19.2271 0.5 16.8233 0.5H6.75176C3.299 0.5 0.5 3.299 0.5 6.75176C0.5 10.2045 3.12069 13.0035 7.30367 13.0035Z",
"fill": "#39594D"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_3",
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M9.00732 17.3086C9.00732 15.6162 10.0262 14.0902 11.5894 13.4414L14.7612 12.1251C17.9694 10.7936 21.5006 13.1513 21.5006 16.6249C21.5006 19.316 19.3185 21.4974 16.6273 21.4967L13.1933 21.4958C10.8813 21.4952 9.00732 19.6207 9.00732 17.3086Z",
"fill": "#D18EE2"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"id": "Vector_4",
"d": "M4.10396 13.8277C2.11358 13.8277 0.5 15.4411 0.5 17.4315V17.8984C0.5 19.8887 2.11352 21.5022 4.1039 21.5022C6.09428 21.5022 7.70785 19.8887 7.70785 17.8984V17.4315C7.70785 15.4411 6.09434 13.8277 4.10396 13.8277Z",
"fill": "#FF7759"
},
"children": []
}
]
}
]
}
]
}
]
},
"name": "Cohere"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Cohere.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'Cohere'
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "120",
"height": "24",
"viewBox": "0 0 120 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M34.4917 21.9129C37.4378 21.9129 40.0162 20.4398 41.0355 17.4656C41.2334 16.8701 40.9496 16.4743 40.384 16.4743H39.2787C38.7689 16.4743 38.4292 16.7002 38.2013 17.1818C37.3239 18.9108 36.1047 19.5324 34.5757 19.5324C31.8553 19.5324 30.1844 17.6335 30.1844 14.4616C30.1844 11.2896 31.9133 9.39083 34.5177 9.39083C36.1046 9.39083 37.4079 10.0704 38.2293 11.6854C38.4852 12.1671 38.795 12.3929 39.3067 12.3929H40.412C40.9776 12.3929 41.2614 12.0251 41.0635 11.4855C39.8742 8.25556 37.2099 7.01035 34.4917 7.01035C30.3843 7.01035 27.3242 10.0424 27.3242 14.4616C27.3242 18.8808 30.2424 21.9129 34.4917 21.9129ZM108.627 13.1584C108.995 10.75 110.638 9.24892 112.876 9.24892C115.115 9.24892 116.786 10.7779 116.983 13.1584H108.627ZM112.99 21.9129C115.596 21.9129 118.203 20.6956 119.478 17.9474C119.79 17.2958 119.506 16.8421 118.94 16.8421H117.892C117.383 16.8421 117.071 17.0679 116.816 17.5216C115.966 19.0227 114.493 19.6463 112.992 19.6463C110.414 19.6463 108.743 17.8894 108.545 15.0292H118.943C119.508 15.0292 119.878 14.7174 119.878 14.1219C119.764 9.67465 116.876 7.01235 112.88 7.01235C108.885 7.01235 105.713 9.90251 105.713 14.4636C105.713 19.0247 108.801 21.9148 112.994 21.9148L112.99 21.9129ZM96.5025 14.8313H97.4378C98.0035 14.8313 98.3152 14.5196 98.4012 13.9239C98.9409 10.0964 101.182 9.5887 103.564 9.70264C104.074 9.72661 104.491 9.33487 104.491 8.82319V7.94575C104.491 7.38012 104.208 7.03833 103.642 7.01035C101.533 6.9304 99.6525 7.65393 98.5651 9.70264C98.5052 9.81455 98.3373 9.78458 98.3233 9.65866L98.1474 8.11365C98.0915 7.54801 97.7796 7.26418 97.212 7.26418H92.9347C92.435 7.26418 92.0272 7.66993 92.0272 8.17161V8.6533C92.0272 9.15298 92.433 9.56072 92.9347 9.56072H94.6916C95.1912 9.56072 95.599 9.96646 95.599 10.4681V13.9239C95.599 14.4236 96.0048 14.8313 96.5064 14.8313H96.5025ZM92.6788 21.631H101.545C102.111 21.631 102.453 21.2913 102.453 20.7236V20.2418C102.453 19.6762 102.113 19.3345 101.545 19.3345H99.2787C98.7131 19.3345 98.3712 18.9947 98.3712 18.4271V16.8681C98.3712 16.3024 98.0315 15.9606 97.4638 15.9606H96.5005C95.9348 15.9606 95.593 16.3004 95.593 16.8681V18.4271C95.593 18.9927 95.2532 19.3345 94.6856 19.3345H92.6749C92.1092 19.3345 91.7674 19.6743 91.7674 20.2418V20.7236C91.7674 21.2893 92.1073 21.631 92.6749 21.631H92.6788ZM78.9955 13.1604C79.3633 10.752 81.0062 9.25092 83.2449 9.25092C85.4834 9.25092 87.1544 10.7799 87.3522 13.1604H78.9955ZM83.3587 21.9148C85.9651 21.9148 88.5714 20.6977 89.8466 17.9493C90.1585 17.2978 89.8746 16.844 89.309 16.844H88.2617C87.7519 16.844 87.4402 17.0699 87.1844 17.5236C86.3349 19.0247 84.8618 19.6482 83.3607 19.6482C80.7824 19.6482 79.1115 17.8914 78.9136 15.0313H89.311C89.8766 15.0313 90.2464 14.7194 90.2464 14.1238C90.1324 9.67665 87.2443 7.01434 83.2488 7.01434C79.2533 7.01434 76.0814 9.9045 76.0814 14.4656C76.0814 19.0266 79.1694 21.9168 83.3628 21.9168L83.3587 21.9148ZM50.5835 21.9148C54.8329 21.9148 57.8649 18.7708 57.8649 14.4636C57.8649 10.1563 54.8329 7.01235 50.5835 7.01235C46.3342 7.01235 43.3022 10.2143 43.3022 14.4636C43.3022 15.455 43.472 16.5602 43.9816 17.7775C44.2375 18.3731 44.7192 18.4571 45.2289 18.0892L46.0504 17.4936C46.4761 17.1818 46.588 16.8141 46.4461 16.2765C46.2202 15.5689 46.1623 14.9453 46.1623 14.4076C46.1623 11.4335 47.9472 9.39283 50.5815 9.39283C53.2159 9.39283 55.0007 11.4035 55.0007 14.4636C55.0007 17.5236 53.2439 19.5344 50.6375 19.5344C49.7301 19.5344 48.8806 19.3645 47.8612 18.5989C47.4355 18.2592 47.0397 18.2032 46.586 18.5429L45.9624 18.9967C45.4527 19.3645 45.3968 19.8741 45.8764 20.2718C47.3496 21.4611 49.0485 21.9148 50.5795 21.9148H50.5835ZM61.4606 21.631H62.3961C62.8957 21.631 63.3035 21.2252 63.3035 20.7236V13.9539C63.3035 11.0937 64.8324 9.39283 67.213 9.39283C69.3656 9.39283 70.6128 10.8099 70.6128 13.4163V20.7255C70.6128 21.2252 71.0186 21.633 71.5203 21.633H72.4836C72.9833 21.633 73.391 21.2272 73.391 20.7255V12.9625C73.391 9.13899 71.4363 7.01434 68.1224 7.01434C65.8659 7.01434 64.5327 7.93776 63.5373 9.22294C63.4613 9.32088 63.3075 9.26691 63.3075 9.14499V2.99092C63.3014 2.48924 62.8957 2.0835 62.3961 2.0835H61.4606C60.9609 2.0835 60.5532 2.48924 60.5532 2.99092V20.7236C60.5532 21.2232 60.959 21.631 61.4606 21.631Z",
"fill": "#39594D"
},
"children": []
},
{
"type": "element",
"name": "mask",
"attributes": {
"id": "mask0_13223_52628",
"style": "mask-type:luminance",
"maskUnits": "userSpaceOnUse",
"x": "1",
"y": "2",
"width": "20",
"height": "20"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M20.8354 2.08319H1.00195V21.9165H20.8354V2.08319Z",
"fill": "white"
},
"children": []
}
]
},
{
"type": "element",
"name": "g",
"attributes": {
"mask": "url(#mask0_13223_52628)"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M7.42768 13.8921C7.96151 13.8921 9.02342 13.8628 10.4912 13.2585C12.2017 12.5542 15.6047 11.2758 18.0597 9.96274C19.7765 9.04432 20.5291 7.82964 20.5291 6.19387C20.5291 3.92362 18.6887 2.08319 16.4185 2.08319H6.90643C3.64547 2.08319 1.00195 4.72669 1.00195 7.98763C1.00195 11.2486 3.47706 13.8921 7.42768 13.8921Z",
"fill": "#39594D"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M9.03711 17.958C9.03711 16.3596 9.99942 14.9184 11.4758 14.3057L14.4713 13.0625C17.5013 11.805 20.8364 14.0316 20.8364 17.3123C20.8364 19.8539 18.7755 21.9141 16.2338 21.9134L12.9906 21.9126C10.807 21.912 9.03711 20.1417 9.03711 17.958Z",
"fill": "#D18EE2"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.40571 14.6705C2.5259 14.6705 1.00195 16.1943 1.00195 18.0741V18.515C1.00195 20.3947 2.52584 21.9186 4.40565 21.9186C6.28547 21.9186 7.80941 20.3947 7.80941 18.515V18.0741C7.80941 16.1943 6.28552 14.6705 4.40571 14.6705Z",
"fill": "#FF7759"
},
"children": []
}
]
}
]
},
"name": "CohereText"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './CohereText.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'CohereText'
export default Icon
...@@ -8,6 +8,8 @@ export { default as BaichuanText } from './BaichuanText' ...@@ -8,6 +8,8 @@ export { default as BaichuanText } from './BaichuanText'
export { default as Baichuan } from './Baichuan' export { default as Baichuan } from './Baichuan'
export { default as ChatglmText } from './ChatglmText' export { default as ChatglmText } from './ChatglmText'
export { default as Chatglm } from './Chatglm' export { default as Chatglm } from './Chatglm'
export { default as CohereText } from './CohereText'
export { default as Cohere } from './Cohere'
export { default as Gpt3 } from './Gpt3' export { default as Gpt3 } from './Gpt3'
export { default as Gpt4 } from './Gpt4' export { default as Gpt4 } from './Gpt4'
export { default as HuggingfaceTextHub } from './HuggingfaceTextHub' export { default as HuggingfaceTextHub } from './HuggingfaceTextHub'
......
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "24",
"height": "24",
"viewBox": "0 0 24 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M9.01488 2.54553C8.91549 2.45869 8.79321 2.40229 8.66264 2.38306C8.53206 2.36384 8.39872 2.38261 8.27852 2.43712C8.15833 2.49164 8.05636 2.5796 7.98481 2.6905C7.91325 2.8014 7.87513 2.93055 7.875 3.06253V6.50003C6.05164 6.50003 4.30295 7.22436 3.01364 8.51367C1.72433 9.80299 1 11.5517 1 13.375C1 15.1984 1.72433 16.9471 3.01364 18.2364C4.30295 19.5257 6.05164 20.25 7.875 20.25H12C12.3647 20.25 12.7144 20.1052 12.9723 19.8473C13.2301 19.5894 13.375 19.2397 13.375 18.875C13.375 18.5104 13.2301 18.1606 12.9723 17.9028C12.7144 17.6449 12.3647 17.5 12 17.5H7.875C6.78098 17.5 5.73177 17.0654 4.95818 16.2919C4.1846 15.5183 3.75 14.4691 3.75 13.375C3.75 12.281 4.1846 11.2318 4.95818 10.4582C5.73177 9.68463 6.78098 9.25003 7.875 9.25003V12.6875C7.87513 12.8195 7.91325 12.9487 7.98481 13.0596C8.05636 13.1705 8.15833 13.2584 8.27852 13.3129C8.39872 13.3675 8.53206 13.3862 8.66264 13.367C8.79321 13.3478 8.91549 13.2914 9.01488 13.2045L14.5149 8.39203C14.5885 8.32751 14.6475 8.24801 14.6879 8.15885C14.7283 8.06969 14.7492 7.97292 14.7492 7.87503C14.7492 7.77714 14.7283 7.68038 14.6879 7.59122C14.6475 7.50206 14.5885 7.42256 14.5149 7.35803L9.01488 2.54553Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M21.625 17.5H17.5C17.1353 17.5 16.7856 17.6449 16.5277 17.9028C16.2699 18.1606 16.125 18.5104 16.125 18.875C16.125 19.2397 16.2699 19.5894 16.5277 19.8473C16.7856 20.1052 17.1353 20.25 17.5 20.25H21.625C21.9897 20.25 22.3394 20.1052 22.5973 19.8473C22.8551 19.5894 23 19.2397 23 18.875C23 18.5104 22.8551 18.1606 22.5973 17.9028C22.3394 17.6449 21.9897 17.5 21.625 17.5Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M21.625 12H17.5C17.1353 12 16.7856 12.1449 16.5277 12.4028C16.2699 12.6606 16.125 13.0104 16.125 13.375C16.125 13.7397 16.2699 14.0894 16.5277 14.3473C16.7856 14.6052 17.1353 14.75 17.5 14.75H21.625C21.9897 14.75 22.3394 14.6052 22.5973 14.3473C22.8551 14.0894 23 13.7397 23 13.375C23 13.0104 22.8551 12.6606 22.5973 12.4028C22.3394 12.1449 21.9897 12 21.625 12Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M17.5 9.25003H21.625C21.9897 9.25003 22.3394 9.10517 22.5973 8.8473C22.8551 8.58944 23 8.23971 23 7.87503C23 7.51036 22.8551 7.16062 22.5973 6.90276C22.3394 6.6449 21.9897 6.50003 21.625 6.50003H17.5C17.1353 6.50003 16.7856 6.6449 16.5277 6.90276C16.2699 7.16062 16.125 7.51036 16.125 7.87503C16.125 8.23971 16.2699 8.58944 16.5277 8.8473C16.7856 9.10517 17.1353 9.25003 17.5 9.25003Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "HighPriority"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './HighPriority.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'HighPriority'
export default Icon
export { default as HighPriority } from './HighPriority'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "24",
"height": "24",
"viewBox": "0 0 24 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.72727 22C4.18787 22 3.66058 21.84 3.21208 21.5404C2.76359 21.2407 2.41402 20.8148 2.2076 20.3164C2.00118 19.8181 1.94717 19.2697 2.05241 18.7407C2.15764 18.2116 2.41739 17.7257 2.7988 17.3443C3.18022 16.9628 3.66617 16.7031 4.19521 16.5979C4.72425 16.4926 5.27261 16.5466 5.77096 16.7531C6.2693 16.9595 6.69524 17.309 6.99492 17.7575C7.2946 18.206 7.45455 18.7333 7.45455 19.2727C7.45455 19.996 7.16721 20.6897 6.65575 21.2012C6.14429 21.7127 5.45059 22 4.72727 22Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M12 9.27273C11.4606 9.27273 10.9333 9.43268 10.4848 9.73236C10.0363 10.032 9.68675 10.458 9.48033 10.9563C9.27391 11.4547 9.2199 12.003 9.32513 12.5321C9.43036 13.0611 9.69011 13.5471 10.0715 13.9285C10.4529 14.3099 10.9389 14.5696 11.4679 14.6749C11.997 14.7801 12.5453 14.7261 13.0437 14.5197C13.542 14.3133 13.968 13.9637 14.2676 13.5152C14.5673 13.0667 14.7273 12.5394 14.7273 12C14.7273 11.2767 14.4399 10.583 13.9285 10.0715C13.417 9.56006 12.7233 9.27273 12 9.27273Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4.72727 2C4.18787 2 3.66058 2.15995 3.21208 2.45963C2.76358 2.7593 2.41402 3.18525 2.2076 3.68359C2.00118 4.18193 1.94717 4.7303 2.05241 5.25934C2.15764 5.78838 2.41738 6.27433 2.7988 6.65575C3.18022 7.03716 3.66617 7.29691 4.19521 7.40214C4.72425 7.50737 5.27261 7.45336 5.77096 7.24694C6.2693 7.04052 6.69524 6.69096 6.99492 6.24246C7.29459 5.79397 7.45455 5.26668 7.45455 4.72727C7.45455 4.00395 7.16721 3.31026 6.65575 2.7988C6.14428 2.28734 5.45059 2 4.72727 2Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M19.2727 2C18.7333 2 18.206 2.15995 17.7575 2.45963C17.309 2.75931 16.9595 3.18525 16.7531 3.68359C16.5466 4.18194 16.4926 4.7303 16.5979 5.25934C16.7031 5.78838 16.9628 6.27433 17.3443 6.65575C17.7257 7.03716 18.2116 7.29691 18.7407 7.40214C19.2697 7.50737 19.8181 7.45337 20.3164 7.24694C20.8148 7.04052 21.2407 6.69096 21.5404 6.24247C21.84 5.79397 22 5.26668 22 4.72727C22 4.00396 21.7127 3.31026 21.2012 2.7988C20.6897 2.28734 19.996 2 19.2727 2Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M19.2727 16.5455C18.7333 16.5455 18.206 16.7054 17.7575 17.0051C17.309 17.3048 16.9595 17.7307 16.7531 18.229C16.5466 18.7274 16.4926 19.2758 16.5979 19.8048C16.7031 20.3338 16.9628 20.8198 17.3443 21.2012C17.7257 21.5826 18.2116 21.8424 18.7407 21.9476C19.2697 22.0528 19.8181 21.9988 20.3164 21.7924C20.8148 21.586 21.2407 21.2364 21.5404 20.7879C21.84 20.3394 22 19.8121 22 19.2727C22 18.5494 21.7127 17.8557 21.2012 17.3443C20.6897 16.8328 19.996 16.5455 19.2727 16.5455Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M7.45455 9.27273H2V14.7273H7.45455V9.27273Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M22 9.27273H16.5455V14.7273H22V9.27273Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.7273 2H9.27273V7.45455H14.7273V2Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.7273 16.5455H9.27273V22H14.7273V16.5455Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "PatternRecognition"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './PatternRecognition.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'PatternRecognition'
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "24",
"height": "24",
"viewBox": "0 0 24 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M16.5833 12.945C16.4856 13.3276 16.2038 14.272 15.7382 15.7784H17.4432C17.0038 14.3674 16.7569 13.5692 16.7025 13.3841C16.6493 13.1998 16.609 13.0532 16.5833 12.945Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M21.1667 9.33333H12C11.5138 9.33333 11.0475 9.52649 10.7036 9.87031C10.3598 10.2141 10.1667 10.6804 10.1667 11.1667V19.4167C10.1667 19.9029 10.3598 20.3692 10.7036 20.713C11.0475 21.0568 11.5138 21.25 12 21.25H17.5L21.1667 24V21.25C21.6529 21.25 22.1192 21.0568 22.463 20.713C22.8068 20.3692 23 19.9029 23 19.4167V11.1667C23 10.6804 22.8068 10.2141 22.463 9.87031C22.1192 9.52649 21.6529 9.33333 21.1667 9.33333ZM18.2507 18.5L17.775 16.9417H15.3917L14.9159 18.5H13.4208L15.7308 11.9293H17.4267L19.7458 18.5H18.2507Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M12 2H2.83333C2.3471 2 1.88079 2.19315 1.53697 2.53697C1.19315 2.88079 1 3.3471 1 3.83333V12.0833C1 12.5696 1.19315 13.0359 1.53697 13.3797C1.88079 13.7235 2.3471 13.9167 2.83333 13.9167V16.6667L6.5 13.9167H9.25V11.1667C9.25381 11.0459 9.26606 10.9255 9.28667 10.8064C8.64229 10.5527 8.0315 10.2208 7.468 9.81825C6.5802 10.4316 5.59355 10.8877 4.55117 11.1667C4.394 10.6965 4.15573 10.2575 3.84717 9.86958C4.76378 9.70375 5.64426 9.37861 6.44867 8.90892C6.07755 8.50417 5.75993 8.05346 5.50358 7.56783C5.29175 7.16889 5.12217 6.74892 4.99758 6.31475C4.56583 6.31475 4.3165 6.32942 3.94983 6.35875V5.03233C4.30266 5.0703 4.65741 5.08744 5.01225 5.08367H6.63292V4.64367C6.63379 4.48979 6.61904 4.33623 6.58892 4.18533H8.05833C8.02877 4.33229 8.01403 4.48185 8.01433 4.63175V5.07908H9.756C10.1108 5.08303 10.4656 5.06589 10.8184 5.02775V6.35875C10.4958 6.32942 10.2098 6.31475 9.778 6.31475C9.67623 6.80565 9.51074 7.28115 9.28575 7.72917C9.06864 8.16083 8.79489 8.56159 8.47175 8.92083C8.89523 9.17057 9.34617 9.37051 9.81558 9.51667C10.0695 9.17655 10.399 8.90012 10.7781 8.70922C11.1573 8.51831 11.5755 8.41816 12 8.41667H13.8333V3.83333C13.8333 3.3471 13.6402 2.88079 13.2964 2.53697C12.9525 2.19315 12.4862 2 12 2Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M7.43133 8.0885C7.87722 7.58102 8.19195 6.97201 8.348 6.31475H6.40833C6.59708 6.98164 6.94861 7.59116 7.43133 8.0885Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "Semantic"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Semantic.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'Semantic'
export default Icon
export { default as Container } from './Container' export { default as Container } from './Container'
export { default as Database02 } from './Database02' export { default as Database02 } from './Database02'
export { default as Database03 } from './Database03' export { default as Database03 } from './Database03'
export { default as PatternRecognition } from './PatternRecognition'
export { default as PuzzlePiece01 } from './PuzzlePiece01' export { default as PuzzlePiece01 } from './PuzzlePiece01'
export { default as Semantic } from './Semantic'
export { default as TerminalSquare } from './TerminalSquare' export { default as TerminalSquare } from './TerminalSquare'
...@@ -41,7 +41,7 @@ const ScoreThresholdItem: FC<Props> = ({ ...@@ -41,7 +41,7 @@ const ScoreThresholdItem: FC<Props> = ({
className={className} className={className}
id={key} id={key}
name={t(`appDebug.datasetConfig.${key}`)} name={t(`appDebug.datasetConfig.${key}`)}
tip={t(`appDebug.datasetConfig.${key}Tip`)} tip={t(`appDebug.datasetConfig.${key}Tip`) as string}
{...VALUE_LIMIT} {...VALUE_LIMIT}
value={value} value={value}
enable={enable} enable={enable}
......
...@@ -37,7 +37,7 @@ const TopKItem: FC<Props> = ({ ...@@ -37,7 +37,7 @@ const TopKItem: FC<Props> = ({
className={className} className={className}
id={key} id={key}
name={t(`appDebug.datasetConfig.${key}`)} name={t(`appDebug.datasetConfig.${key}`)}
tip={t(`appDebug.datasetConfig.${key}Tip`)} tip={t(`appDebug.datasetConfig.${key}Tip`) as string}
{...VALUE_LIMIT} {...VALUE_LIMIT}
value={value} value={value}
enable={enable} enable={enable}
......
'use client'
import type { FC } from 'react'
import React from 'react'
import cn from 'classnames'
import s from './style.module.css'
type Props = {
className?: string
icon: React.ReactNode
iconBgClassName?: string
title: React.ReactNode
description: string
noRadio?: boolean
isChosen?: boolean
onChosen?: () => void
chosenConfig?: React.ReactNode
chosenConfigWrapClassName?: string
}
const RadioCard: FC<Props> = ({
icon,
iconBgClassName = 'bg-[#F5F3FF]',
title,
description,
noRadio,
isChosen,
onChosen = () => {},
chosenConfig,
chosenConfigWrapClassName,
}) => {
return (
<div className={cn(s.item, isChosen && s.active)}>
<div className='flex py-3 pl-3 pr-4' onClick={onChosen}>
<div className={cn(iconBgClassName, 'mr-3 shrink-0 flex w-8 justify-center h-8 items-center rounded-lg')}>
{icon}
</div>
<div className='grow'>
<div className='leading-5 text-sm font-medium text-gray-900'>{title}</div>
<div className='leading-[18px] text-xs font-normal text-[#667085]'>{description}</div>
</div>
{!noRadio && (
<div className='shrink-0 flex items-center h-8'>
<div className={s.radio}></div>
</div>
)}
</div>
{((isChosen && chosenConfig) || noRadio) && (
<div className={cn(chosenConfigWrapClassName, 'pt-2 px-14 pb-6 border-t border-gray-200')}>
{chosenConfig}
</div>
)}
</div>
)
}
export default React.memo(RadioCard)
'use client'
import type { FC } from 'react'
import React from 'react'
import cn from 'classnames'
import s from './style.module.css'
type Props = {
className?: string
title: string
description: string
isChosen: boolean
onChosen: () => void
chosenConfig?: React.ReactNode
icon?: JSX.Element
}
const RadioCard: FC<Props> = ({
title,
description,
isChosen,
onChosen,
icon,
}) => {
return (
<div
className={cn(s.item, isChosen && s.active, 'flex')}
onClick={onChosen}
>
{icon}
<div>
<div className='flex justify-between items-center'>
<div className='leading-5 text-sm font-medium text-gray-900'>{title}</div>
<div className={s.radio}></div>
</div>
<div className='leading-[18px] text-xs font-normal text-gray-500'>{description}</div>
</div>
</div>
)
}
export default React.memo(RadioCard)
.item {
@apply relative p-4 rounded-xl border border-gray-100 cursor-pointer;
background-color: #fcfcfd;
}
.item.active {
border-width: 1.5px;
border-color: #528BFF;
box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06);
}
.item:hover {
background-color: #ffffff;
border-color: #B2CCFF;
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
}
.radio {
@apply w-4 h-4 border-[2px] border-gray-200 rounded-full;
}
.item.active .radio {
border-width: 5px;
border-color: #155EEF;
}
\ No newline at end of file
.item {
@apply relative rounded-xl border border-gray-100 cursor-pointer;
background-color: #fcfcfd;
}
.item.active {
border-width: 1.5px;
border-color: #528BFF;
box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06);
}
.item:hover {
background-color: #ffffff;
border-color: #B2CCFF;
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
}
.radio {
@apply w-4 h-4 border-[2px] border-gray-200 rounded-full;
}
.item.active .radio {
border-width: 5px;
border-color: #155EEF;
}
import ReactSlider from 'react-slider' import ReactSlider from 'react-slider'
import cn from 'classnames' import cn from 'classnames'
import './style.css' import './style.css'
type ISliderProps = { type ISliderProps = {
className?: string className?: string
value: number value: number
......
import type { BackendModel } from '../../header/account-setting/model-page/declarations'
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
export const isReRankModelSelected = ({
rerankDefaultModel,
isRerankDefaultModelVaild,
retrievalConfig,
indexMethod,
}: {
rerankDefaultModel?: BackendModel
isRerankDefaultModelVaild: boolean
retrievalConfig: RetrievalConfig
indexMethod?: string
}) => {
const rerankModel = (retrievalConfig.reranking_model?.reranking_model_name ? retrievalConfig.reranking_model : undefined) || (isRerankDefaultModelVaild ? rerankDefaultModel : undefined)
if (
indexMethod === 'high_quality'
&& (retrievalConfig.reranking_enable || retrievalConfig.search_method === RETRIEVE_METHOD.fullText)
&& !rerankModel
)
return false
return true
}
export const ensureRerankModelSelected = ({
rerankDefaultModel,
indexMethod,
retrievalConfig,
}: {
rerankDefaultModel: BackendModel
retrievalConfig: RetrievalConfig
indexMethod?: string
}) => {
const rerankModel = retrievalConfig.reranking_model?.reranking_model_name ? retrievalConfig.reranking_model : undefined
if (
indexMethod === 'high_quality'
&& (retrievalConfig.reranking_enable || retrievalConfig.search_method === RETRIEVE_METHOD.fullText)
&& !rerankModel
) {
return {
...retrievalConfig,
reranking_model: {
reranking_provider_name: rerankDefaultModel.model_provider.provider_name,
reranking_model_name: rerankDefaultModel.model_name,
},
}
}
return retrievalConfig
}
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import RetrievalParamConfig from '../retrieval-param-config'
import { RETRIEVE_METHOD } from '@/types/app'
import RadioCard from '@/app/components/base/radio-card'
import { HighPriority } from '@/app/components/base/icons/src/vender/solid/arrows'
import type { RetrievalConfig } from '@/types/app'
type Props = {
value: RetrievalConfig
onChange: (value: RetrievalConfig) => void
}
const EconomicalRetrievalMethodConfig: FC<Props> = ({
value,
onChange,
}) => {
const { t } = useTranslation()
return (
<div className='space-y-2'>
<RadioCard
icon={<HighPriority className='w-4 h-4 text-[#7839EE]' />}
title={t('dataset.retrieval.invertedIndex.title')}
description={t('dataset.retrieval.invertedIndex.description')}
noRadio
chosenConfig={
<RetrievalParamConfig
type={RETRIEVE_METHOD.invertedIndex}
value={value}
onChange={onChange}
/>
}
/>
</div>
)
}
export default React.memo(EconomicalRetrievalMethodConfig)
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import RetrievalParamConfig from '../retrieval-param-config'
import type { RetrievalConfig } from '@/types/app'
import { RETRIEVE_METHOD } from '@/types/app'
import RadioCard from '@/app/components/base/radio-card'
import { PatternRecognition, Semantic } from '@/app/components/base/icons/src/vender/solid/development'
import { FileSearch02 } from '@/app/components/base/icons/src/vender/solid/files'
import { useProviderContext } from '@/context/provider-context'
type Props = {
value: RetrievalConfig
onChange: (value: RetrievalConfig) => void
}
const RetrievalMethodConfig: FC<Props> = ({
value,
onChange,
}) => {
const { t } = useTranslation()
const { supportRetrievalMethods } = useProviderContext()
return (
<div className='space-y-2'>
{supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
<RadioCard
icon={<Semantic className='w-4 h-4 text-[#7839EE]' />}
title={t('dataset.retrieval.semantic_search.title')}
description={t('dataset.retrieval.semantic_search.description')}
isChosen={value.search_method === RETRIEVE_METHOD.semantic}
onChosen={() => onChange({
...value,
search_method: RETRIEVE_METHOD.semantic,
})}
chosenConfig={
<RetrievalParamConfig
type={RETRIEVE_METHOD.semantic}
value={value}
onChange={onChange}
/>
}
/>
)}
{supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
<RadioCard
icon={<FileSearch02 className='w-4 h-4 text-[#7839EE]' />}
title={t('dataset.retrieval.full_text_search.title')}
description={t('dataset.retrieval.full_text_search.description')}
isChosen={value.search_method === RETRIEVE_METHOD.fullText}
onChosen={() => onChange({
...value,
search_method: RETRIEVE_METHOD.fullText,
})}
chosenConfig={
<RetrievalParamConfig
type={RETRIEVE_METHOD.fullText}
value={value}
onChange={onChange}
/>
}
/>
)}
{supportRetrievalMethods.includes(RETRIEVE_METHOD.semantic) && (
<RadioCard
icon={<PatternRecognition className='w-4 h-4 text-[#7839EE]' />}
title={
<div className='flex items-center space-x-1'>
<div>{t('dataset.retrieval.hybrid_search.title')}</div>
<div className='flex h-full items-center px-1.5 rounded-md border border-[#E0EAFF] text-xs font-medium text-[#444CE7]'>{t('dataset.retrieval.hybrid_search.recommend')}</div>
</div>
}
description={t('dataset.retrieval.hybrid_search.description')}
isChosen={value.search_method === RETRIEVE_METHOD.hybrid}
onChosen={() => onChange({
...value,
search_method: RETRIEVE_METHOD.hybrid,
})}
chosenConfig={
<RetrievalParamConfig
type={RETRIEVE_METHOD.hybrid}
value={value}
onChange={onChange}
/>
}
/>
)}
</div>
)
}
export default React.memo(RetrievalMethodConfig)
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import type { RetrievalConfig } from '@/types/app'
import { RETRIEVE_METHOD } from '@/types/app'
import RadioCard from '@/app/components/base/radio-card'
import { HighPriority } from '@/app/components/base/icons/src/vender/solid/arrows'
import { PatternRecognition, Semantic } from '@/app/components/base/icons/src/vender/solid/development'
import { FileSearch02 } from '@/app/components/base/icons/src/vender/solid/files'
type Props = {
value: RetrievalConfig
}
export const getIcon = (type: RETRIEVE_METHOD) => {
return ({
[RETRIEVE_METHOD.semantic]: Semantic,
[RETRIEVE_METHOD.fullText]: FileSearch02,
[RETRIEVE_METHOD.hybrid]: PatternRecognition,
[RETRIEVE_METHOD.invertedIndex]: HighPriority,
})[type] || FileSearch02
}
const EconomicalRetrievalMethodConfig: FC<Props> = ({
// type,
value,
}) => {
const { t } = useTranslation()
const type = value.search_method
const Icon = getIcon(type)
return (
<div className='space-y-2'>
<RadioCard
icon={<Icon className='w-4 h-4 text-[#7839EE]' />}
title={t(`dataset.retrieval.${type}.title`)}
description={t(`dataset.retrieval.${type}.description`)}
noRadio
chosenConfigWrapClassName='!pb-3'
chosenConfig={
<div className='flex flex-wrap leading-[18px] text-xs font-normal'>
{value.reranking_model.reranking_model_name && (
<div className='mr-8 flex space-x-1'>
<div className='text-gray-500'>{t('common.modelProvider.rerankModel.key')}</div>
<div className='font-medium text-gray-800'>{value.reranking_model.reranking_model_name}</div>
</div>
)}
<div className='mr-8 flex space-x-1'>
<div className='text-gray-500'>{t('appDebug.datasetConfig.top_k')}</div>
<div className='font-medium text-gray-800'>{value.top_k}</div>
</div>
<div className='mr-8 flex space-x-1'>
<div className='text-gray-500'>{t('appDebug.datasetConfig.score_threshold')}</div>
<div className='font-medium text-gray-800'>{value.score_threshold}</div>
</div>
</div>
}
/>
</div>
)
}
export default React.memo(EconomicalRetrievalMethodConfig)
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
import TopKItem from '@/app/components/base/param-item/top-k-item'
import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
import { RETRIEVE_METHOD } from '@/types/app'
import Switch from '@/app/components/base/switch'
import Tooltip from '@/app/components/base/tooltip-plus'
import { HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
import ModelSelector from '@/app/components/header/account-setting/model-page/model-selector'
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import type { RetrievalConfig } from '@/types/app'
import { useProviderContext } from '@/context/provider-context'
type Props = {
type: RETRIEVE_METHOD
value: RetrievalConfig
onChange: (value: RetrievalConfig) => void
}
const RetrievalParamConfig: FC<Props> = ({
type,
value,
onChange,
}) => {
const { t } = useTranslation()
const canToggleRerankModalEnable = type !== RETRIEVE_METHOD.hybrid
const isEconomical = type === RETRIEVE_METHOD.invertedIndex
const {
rerankDefaultModel,
} = useProviderContext()
const rerankModel = (() => {
if (value.reranking_model) {
return {
provider_name: value.reranking_model.reranking_provider_name,
model_name: value.reranking_model.reranking_model_name,
}
}
else if (rerankDefaultModel) {
return {
provider_name: rerankDefaultModel.model_provider.provider_name,
model_name: rerankDefaultModel.model_name,
}
}
})()
return (
<div>
{!isEconomical && (
<div>
<div className='flex h-8 items-center text-[13px] font-medium text-gray-900 space-x-2'>
{canToggleRerankModalEnable && (
<Switch
size='md'
defaultValue={value.reranking_enable}
onChange={(v) => {
onChange({
...value,
reranking_enable: v,
})
}}
/>
)}
<div className='flex items-center'>
<span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span>
<Tooltip popupContent={<div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>}>
<HelpCircle className='w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
</div>
<div>
<ModelSelector
whenEmptyGoToSetting
popClassName='!max-w-[100%] !w-full'
value={rerankModel && { providerName: rerankModel.provider_name, modelName: rerankModel.model_name } as any}
modelType={ModelType.reranking}
readonly={!value.reranking_enable && type !== RETRIEVE_METHOD.hybrid}
onChange={(v) => {
onChange({
...value,
reranking_model: {
reranking_provider_name: v.model_provider.provider_name,
reranking_model_name: v.model_name,
},
})
}}
/>
</div>
</div>
)}
<div className={cn(!isEconomical && 'mt-4', 'flex space-between space-x-6')}>
<TopKItem
className='grow'
value={value.top_k}
onChange={(_key, v) => {
onChange({
...value,
top_k: v,
})
}}
enable={true}
/>
{(!isEconomical && !(value.search_method === RETRIEVE_METHOD.fullText && !value.reranking_enable)) && (
<ScoreThresholdItem
className='grow'
value={value.score_threshold}
onChange={(_key, v) => {
onChange({
...value,
score_threshold: v,
})
}}
enable={value.score_threshold_enable}
hasSwitch={true}
onSwitchChange={(_key, v) => {
onChange({
...value,
score_threshold_enable: v,
})
}}
/>
)}
</div>
</div>
)
}
export default React.memo(RetrievalParamConfig)
...@@ -7,6 +7,7 @@ import { XMarkIcon } from '@heroicons/react/20/solid' ...@@ -7,6 +7,7 @@ import { XMarkIcon } from '@heroicons/react/20/solid'
import cn from 'classnames' import cn from 'classnames'
import Link from 'next/link' import Link from 'next/link'
import { groupBy } from 'lodash-es' import { groupBy } from 'lodash-es'
import RetrievalMethodInfo from '../../common/retrieval-method-info'
import PreviewItem, { PreviewType } from './preview-item' import PreviewItem, { PreviewType } from './preview-item'
import LanguageSelect from './language-select' import LanguageSelect from './language-select'
import s from './index.module.css' import s from './index.module.css'
...@@ -19,7 +20,10 @@ import { ...@@ -19,7 +20,10 @@ import {
} from '@/service/datasets' } from '@/service/datasets'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
import { type RetrievalConfig } from '@/types/app'
import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { formatNumber } from '@/utils/format' import { formatNumber } from '@/utils/format'
import type { NotionPage } from '@/models/common' import type { NotionPage } from '@/models/common'
...@@ -31,6 +35,8 @@ import { XClose } from '@/app/components/base/icons/src/vender/line/general' ...@@ -31,6 +35,8 @@ import { XClose } from '@/app/components/base/icons/src/vender/line/general'
import { useDatasetDetailContext } from '@/context/dataset-detail' import { useDatasetDetailContext } from '@/context/dataset-detail'
import I18n from '@/context/i18n' import I18n from '@/context/i18n'
import { IS_CE_EDITION } from '@/config' import { IS_CE_EDITION } from '@/config'
import { RETRIEVE_METHOD } from '@/types/app'
import { useProviderContext } from '@/context/provider-context'
type ValueOf<T> = T[keyof T] type ValueOf<T> = T[keyof T]
type StepTwoProps = { type StepTwoProps = {
...@@ -78,7 +84,7 @@ const StepTwo = ({ ...@@ -78,7 +84,7 @@ const StepTwo = ({
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n) const { locale } = useContext(I18n)
const { mutateDatasetRes } = useDatasetDetailContext() const { dataset: currentDataset, mutateDatasetRes } = useDatasetDetailContext()
const scrollRef = useRef<HTMLDivElement>(null) const scrollRef = useRef<HTMLDivElement>(null)
const [scrolled, setScrolled] = useState(false) const [scrolled, setScrolled] = useState(false)
const previewScrollRef = useRef<HTMLDivElement>(null) const previewScrollRef = useRef<HTMLDivElement>(null)
...@@ -254,7 +260,10 @@ const StepTwo = ({ ...@@ -254,7 +260,10 @@ const StepTwo = ({
} }
} }
} }
const {
rerankDefaultModel,
isRerankDefaultModelVaild,
} = useProviderContext()
const getCreationParams = () => { const getCreationParams = () => {
let params let params
if (isSetting) { if (isSetting) {
...@@ -263,9 +272,30 @@ const StepTwo = ({ ...@@ -263,9 +272,30 @@ const StepTwo = ({
doc_form: docForm, doc_form: docForm,
doc_language: docLanguage, doc_language: docLanguage,
process_rule: getProcessRule(), process_rule: getProcessRule(),
// eslint-disable-next-line @typescript-eslint/no-use-before-define
retrieval_model: retrievalConfig, // Readonly. If want to changed, just go to settings page.
} as CreateDocumentReq } as CreateDocumentReq
} }
else { else { // create
const indexMethod = getIndexing_technique()
if (
!isReRankModelSelected({
rerankDefaultModel,
isRerankDefaultModelVaild,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
retrievalConfig,
indexMethod: indexMethod as string,
})
) {
Toast.notify({ type: 'error', message: t('appDebug.datasetConfig.rerankModelRequired') })
return
}
const postRetrievalConfig = ensureRerankModelSelected({
rerankDefaultModel: rerankDefaultModel!,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
retrievalConfig,
indexMethod: indexMethod as string,
})
params = { params = {
data_source: { data_source: {
type: dataSourceType, type: dataSourceType,
...@@ -277,6 +307,8 @@ const StepTwo = ({ ...@@ -277,6 +307,8 @@ const StepTwo = ({
process_rule: getProcessRule(), process_rule: getProcessRule(),
doc_form: docForm, doc_form: docForm,
doc_language: docLanguage, doc_language: docLanguage,
retrieval_model: postRetrievalConfig,
} as CreateDocumentReq } as CreateDocumentReq
if (dataSourceType === DataSourceType.FILE) { if (dataSourceType === DataSourceType.FILE) {
params.data_source.info_list.file_info_list = { params.data_source.info_list.file_info_list = {
...@@ -330,7 +362,7 @@ const StepTwo = ({ ...@@ -330,7 +362,7 @@ const StepTwo = ({
setIsCreating(true) setIsCreating(true)
if (!datasetId) { if (!datasetId) {
res = await createFirstDocument({ res = await createFirstDocument({
body: params, body: params as CreateDocumentReq,
}) })
updateIndexingTypeCache && updateIndexingTypeCache(indexType as string) updateIndexingTypeCache && updateIndexingTypeCache(indexType as string)
updateResultCache && updateResultCache(res) updateResultCache && updateResultCache(res)
...@@ -338,7 +370,7 @@ const StepTwo = ({ ...@@ -338,7 +370,7 @@ const StepTwo = ({
else { else {
res = await createDocument({ res = await createDocument({
datasetId, datasetId,
body: params, body: params as CreateDocumentReq,
}) })
updateIndexingTypeCache && updateIndexingTypeCache(indexType as string) updateIndexingTypeCache && updateIndexingTypeCache(indexType as string)
updateResultCache && updateResultCache(res) updateResultCache && updateResultCache(res)
...@@ -441,6 +473,18 @@ const StepTwo = ({ ...@@ -441,6 +473,18 @@ const StepTwo = ({
} }
}, [segmentationType, indexType]) }, [segmentationType, indexType])
const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict || {
search_method: RETRIEVE_METHOD.semantic,
reranking_enable: false,
reranking_model: {
reranking_provider_name: rerankDefaultModel?.model_provider.provider_name,
reranking_model_name: rerankDefaultModel?.model_name,
},
top_k: 3,
score_threshold_enable: false,
score_threshold: 0.5,
} as RetrievalConfig)
return ( return (
<div className='flex w-full h-full'> <div className='flex w-full h-full'>
<div ref={scrollRef} className='relative h-full w-full overflow-y-scroll'> <div ref={scrollRef} className='relative h-full w-full overflow-y-scroll'>
...@@ -626,6 +670,56 @@ const StepTwo = ({ ...@@ -626,6 +670,56 @@ const StepTwo = ({
)} )}
</div> </div>
)} )}
{/* Retrieval Method Config */}
<div>
{!datasetId
? (
<div className={s.label}>
{t('datasetSettings.form.retrievalSetting.title')}
<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.longDescription')}
</div>
</div>
)
: (
<div className={cn(s.label, 'flex justify-between items-center')}>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div>
</div>
)}
<div className='max-w-[640px]'>
{!datasetId
? (<>
{getIndexing_technique() === IndexingType.QUALIFIED
? (
<RetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)
: (
<EconomicalRetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)}
</>)
: (
<div>
<RetrievalMethodInfo
value={retrievalConfig}
/>
<div className='mt-2 text-xs text-gray-500 font-medium'>
{t('datasetCreation.stepTwo.retrivalSettedTip')}
<Link className='text-[#155EEF]' href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
</div>
</div>
)}
</div>
</div>
<div className={s.source}> <div className={s.source}>
<div className={s.sourceContent}> <div className={s.sourceContent}>
{dataSourceType === DataSourceType.FILE && ( {dataSourceType === DataSourceType.FILE && (
......
...@@ -141,10 +141,16 @@ const SegmentCard: FC<ISegmentCardProps> = ({ ...@@ -141,10 +141,16 @@ const SegmentCard: FC<ISegmentCardProps> = ({
)} )}
</div> </div>
</> </>
: <div className={s.hitTitleWrapper}> : (
<div className={cn(s.commonIcon, s.targetIcon, loading ? '!bg-gray-300' : '', '!w-3.5 !h-3.5')} /> score !== null
<ProgressBar percent={score ?? 0} loading={loading} /> ? (
</div>} <div className={s.hitTitleWrapper}>
<div className={cn(s.commonIcon, s.targetIcon, loading ? '!bg-gray-300' : '', '!w-3.5 !h-3.5')} />
<ProgressBar percent={score ?? 0} loading={loading} />
</div>
)
: null
)}
</div> </div>
{loading {loading
? ( ? (
......
...@@ -6,16 +6,20 @@ import useSWR from 'swr' ...@@ -6,16 +6,20 @@ import useSWR from 'swr'
import { omit } from 'lodash-es' import { omit } from 'lodash-es'
import cn from 'classnames' import cn from 'classnames'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useContext } from 'use-context-selector'
import SegmentCard from '../documents/detail/completed/SegmentCard' import SegmentCard from '../documents/detail/completed/SegmentCard'
import docStyle from '../documents/detail/completed/style.module.css' import docStyle from '../documents/detail/completed/style.module.css'
import Textarea from './textarea' import Textarea from './textarea'
import s from './style.module.css' import s from './style.module.css'
import HitDetail from './hit-detail' import HitDetail from './hit-detail'
import ModifyRetrievalModal from './modify-retrieval-modal'
import type { HitTestingResponse, HitTesting as HitTestingType } from '@/models/datasets' import type { HitTestingResponse, HitTesting as HitTestingType } from '@/models/datasets'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import Pagination from '@/app/components/base/pagination' import Pagination from '@/app/components/base/pagination'
import { fetchTestingRecords } from '@/service/datasets' import { fetchTestingRecords } from '@/service/datasets'
import DatasetDetailContext from '@/context/dataset-detail'
import type { RetrievalConfig } from '@/types/app'
const limit = 10 const limit = 10
...@@ -55,6 +59,11 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => { ...@@ -55,6 +59,11 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
setCurrParagraph({ paraInfo: detail, showModal: true }) setCurrParagraph({ paraInfo: detail, showModal: true })
} }
const { dataset: currentDataset } = useContext(DatasetDetailContext)
const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict as RetrievalConfig)
const [isShowModifyRetrievalModal, setIsShowModifyRetrievalModal] = useState(false)
return ( return (
<div className={s.container}> <div className={s.container}>
<div className={s.leftDiv}> <div className={s.leftDiv}>
...@@ -70,6 +79,9 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => { ...@@ -70,6 +79,9 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
setLoading={setSubmitLoading} setLoading={setSubmitLoading}
setText={setText} setText={setText}
text={text} text={text}
onClickRetrievalMethod={() => setIsShowModifyRetrievalModal(true)}
retrievalConfig={retrievalConfig}
isEconomy={currentDataset?.indexing_technique === 'economy'}
/> />
<div className={cn(s.title, 'mt-8 mb-2')}>{t('datasetHitTesting.recents')}</div> <div className={cn(s.title, 'mt-8 mb-2')}>{t('datasetHitTesting.recents')}</div>
{(!recordsRes && !error) {(!recordsRes && !error)
...@@ -178,6 +190,18 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => { ...@@ -178,6 +190,18 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
}} }}
/>} />}
</Modal> </Modal>
{isShowModifyRetrievalModal && (
<ModifyRetrievalModal
indexMethod={currentDataset?.indexing_technique || ''}
value={retrievalConfig}
isShow={isShowModifyRetrievalModal}
onHide={() => setIsShowModifyRetrievalModal(false)}
onSave={(value) => {
setRetrievalConfig(value)
setIsShowModifyRetrievalModal(false)
}}
/>
)}
</div> </div>
) )
} }
......
'use client'
import type { FC } from 'react'
import React, { useRef, useState } from 'react'
import { useClickAway } from 'ahooks'
import { useTranslation } from 'react-i18next'
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 Button from '@/app/components/base/button'
type Props = {
indexMethod: string
value: RetrievalConfig
isShow: boolean
onHide: () => void
onSave: (value: RetrievalConfig) => void
}
const ModifyRetrievalModal: FC<Props> = ({
indexMethod,
value,
isShow,
onHide,
onSave,
}) => {
const ref = useRef(null)
const { t } = useTranslation()
const [retrievalConfig, setRetrievalConfig] = useState(value)
useClickAway(() => {
if (ref)
onHide()
}, ref)
if (!isShow)
return null
return (
<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={{
width: 632,
height: 'calc(100vh - 72px)',
}}
ref={ref}
>
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'>
<div className='text-base font-semibold text-gray-900'>
<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 className='flex items-center'>
<div
onClick={onHide}
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='p-6 border-b' style={{
borderBottom: 'rgba(0, 0, 0, 0.05)',
}}>
{indexMethod === 'high_quality'
? (
<RetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)
: (
<EconomicalRetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)}
</div>
<div
className='flex justify-end pt-6 px-6 border-t'
style={{
borderColor: 'rgba(0, 0, 0, 0.05)',
}}
>
<Button className='mr-2 flex-shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button>
<Button type='primary' className='flex-shrink-0' onClick={() => onSave(retrievalConfig)} >{t('common.operation.save')}</Button>
</div>
</div>
)
}
export default React.memo(ModifyRetrievalModal)
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
@apply text-sm font-normal text-gray-500; @apply text-sm font-normal text-gray-500;
} }
.textarea { .textarea {
min-height: 96px; height: 220px;
@apply border-none resize-none font-normal caret-primary-600 text-gray-700 text-sm w-full bg-gray-25 focus-visible:outline-none placeholder:text-gray-300 placeholder:text-sm placeholder:font-normal !important; @apply border-none resize-none font-normal caret-primary-600 text-gray-700 text-sm w-full focus-visible:outline-none placeholder:text-gray-300 placeholder:text-sm placeholder:font-normal !important;
} }
.table { .table {
@apply text-[13px] text-gray-500; @apply text-[13px] text-gray-500;
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
} }
.wrapper { .wrapper {
@apply relative border border-primary-600 min-h-[200px] rounded-xl pt-3 pb-14 px-4 bg-gray-25; @apply relative border border-primary-600 rounded-xl;
} }
.cardWrapper { .cardWrapper {
......
import type { FC } from "react"; import type { FC } from 'react'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import { DocumentTextIcon } from "@heroicons/react/24/solid"; import { useTranslation } from 'react-i18next'
import { useTranslation } from "react-i18next"; import cn from 'classnames'
import { hitTesting } from "@/service/datasets"; import Button from '../../base/button'
import Tag from '../../base/tag'
import Tooltip from '../../base/tooltip'
import { getIcon } from '../common/retrieval-method-info'
import s from './style.module.css'
import DatasetDetailContext from '@/context/dataset-detail' import DatasetDetailContext from '@/context/dataset-detail'
import { HitTestingResponse } from "@/models/datasets"; import type { HitTestingResponse } from '@/models/datasets'
import cn from "classnames"; import { hitTesting } from '@/service/datasets'
import Button from "../../base/button"; import { asyncRunSafe } from '@/utils'
import Tag from "../../base/tag"; import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
import Tooltip from "../../base/tooltip";
import s from "./style.module.css";
import { asyncRunSafe } from "@/utils";
type Props = { type Props = {
datasetId: string; datasetId: string
onUpdateList: () => void; onUpdateList: () => void
setHitResult: (res: HitTestingResponse) => void; setHitResult: (res: HitTestingResponse) => void
loading: boolean; loading: boolean
setLoading: (v: boolean) => void; setLoading: (v: boolean) => void
text: string; text: string
setText: (v: string) => void; setText: (v: string) => void
}; onClickRetrievalMethod: () => void
retrievalConfig: RetrievalConfig
isEconomy: boolean
}
const TextAreaWithButton: FC<Props> = ({ const TextAreaWithButton: FC<Props> = ({
datasetId, datasetId,
...@@ -30,87 +34,109 @@ const TextAreaWithButton: FC<Props> = ({ ...@@ -30,87 +34,109 @@ const TextAreaWithButton: FC<Props> = ({
loading, loading,
text, text,
setText, setText,
onClickRetrievalMethod,
retrievalConfig,
isEconomy,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation()
const { indexingTechnique } = useContext(DatasetDetailContext) const { indexingTechnique } = useContext(DatasetDetailContext)
// 处理文本框内容变化的函数
function handleTextChange(event: any) { function handleTextChange(event: any) {
setText(event.target.value); setText(event.target.value)
} }
// 处理按钮点击的函数
const onSubmit = async () => { const onSubmit = async () => {
setLoading(true); setLoading(true)
const [e, res] = await asyncRunSafe<HitTestingResponse>( const [e, res] = await asyncRunSafe<HitTestingResponse>(
hitTesting({ datasetId, queryText: text }) as Promise<HitTestingResponse> hitTesting({ datasetId, queryText: text, retrieval_model: retrievalConfig }) as Promise<HitTestingResponse>,
); )
if (!e) { if (!e) {
setHitResult(res); setHitResult(res)
onUpdateList?.(); onUpdateList?.()
} }
setLoading(false); setLoading(false)
}; }
const retrievalMethod = isEconomy ? RETRIEVE_METHOD.invertedIndex : retrievalConfig.search_method
const Icon = getIcon(retrievalMethod)
return ( return (
<> <>
<div className={s.wrapper}> <div className={s.wrapper}>
<div className="flex items-center mb-3"> <div className='pt-2 rounded-tl-xl rounded-tr-xl bg-[#EEF4FF]'>
<DocumentTextIcon className="w-4 h-4 text-primary-600 mr-2" /> <div className="px-4 pb-2 flex justify-between h-8 items-center">
<span className="text-gray-800 font-semibold text-sm"> <span className="text-gray-800 font-semibold text-sm">
{t("datasetHitTesting.input.title")} {t('datasetHitTesting.input.title')}
</span> </span>
</div>
<textarea
value={text}
onChange={handleTextChange}
placeholder={t("datasetHitTesting.input.placeholder") as string}
className={s.textarea}
/>
<div className="absolute inset-x-0 bottom-0 flex items-center justify-between mx-4 mt-2 mb-4">
{text?.length > 200 ? (
<Tooltip <Tooltip
content={t("datasetHitTesting.input.countWarning") as string} selector={'change-retrieval-method'}
selector="hit-testing-warning" htmlContent={t('dataset.retrieval.changeRetrievalMethod')}
> >
<div> <div
<Tag color="red" className="!text-red-600"> onClick={onClickRetrievalMethod}
{text?.length} className='flex px-2 h-7 items-center space-x-1 bg-white hover:bg-[#ECE9FE] rounded-md shadow-sm cursor-pointer text-[#6927DA]'
<span className="text-red-300 mx-0.5">/</span> >
<Icon className='w-3.5 h-3.5'></Icon>
<div className='text-xs font-medium'>{t(`dataset.retrieval.${retrievalMethod}.title`)}</div>
</div>
</Tooltip>
</div>
<div className='h-2 rounded-tl-xl rounded-tr-xl bg-white'></div>
</div>
<div className='px-4 pb-11'>
<textarea
value={text}
onChange={handleTextChange}
placeholder={t('datasetHitTesting.input.placeholder') as string}
className={s.textarea}
/>
<div className="absolute inset-x-0 bottom-0 flex items-center justify-between mx-4 mt-2 mb-2">
{text?.length > 200
? (
<Tooltip
content={t('datasetHitTesting.input.countWarning') as string}
selector="hit-testing-warning"
>
<div>
<Tag color="red" className="!text-red-600">
{text?.length}
<span className="text-red-300 mx-0.5">/</span>
200 200
</Tag>
</div>
</Tooltip>
)
: (
<Tag
color="gray"
className={cn('!text-gray-500', text?.length ? '' : 'opacity-50')}
>
{text?.length}
<span className="text-gray-300 mx-0.5">/</span>
200
</Tag> </Tag>
)}
<Tooltip
selector="hit-testing-submit"
disabled={indexingTechnique === 'high_quality'}
content={t('datasetHitTesting.input.indexWarning') as string}
>
<div>
<Button
onClick={onSubmit}
type="primary"
loading={loading}
disabled={indexingTechnique !== 'high_quality' ? true : (!text?.length || text?.length > 200)}
>
{t('datasetHitTesting.input.testing')}
</Button>
</div> </div>
</Tooltip> </Tooltip>
) : ( </div>
<Tag
color="gray"
className={cn("!text-gray-500", text?.length ? "" : "opacity-50")}
>
{text?.length}
<span className="text-gray-300 mx-0.5">/</span>
200
</Tag>
)}
<Tooltip
selector="hit-testing-submit"
disabled={indexingTechnique === 'high_quality'}
content={t("datasetHitTesting.input.indexWarning") as string}
>
<div>
<Button
onClick={onSubmit}
type="primary"
loading={loading}
disabled={indexingTechnique !== 'high_quality' ? true : (!text?.length || text?.length > 200)}
>
{t("datasetHitTesting.input.testing")}
</Button>
</div>
</Tooltip>
</div> </div>
</div> </div>
</> </>
); )
}; }
export default TextAreaWithButton; export default TextAreaWithButton
...@@ -9,6 +9,8 @@ import { useSWRConfig } from 'swr' ...@@ -9,6 +9,8 @@ import { useSWRConfig } from 'swr'
import { unstable_serialize } from 'swr/infinite' import { unstable_serialize } from 'swr/infinite'
import PermissionsRadio from '../permissions-radio' import PermissionsRadio from '../permissions-radio'
import IndexMethodRadio from '../index-method-radio' import IndexMethodRadio from '../index-method-radio'
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { updateDatasetSetting } from '@/service/datasets' import { updateDatasetSetting } from '@/service/datasets'
...@@ -17,8 +19,10 @@ import ModelSelector from '@/app/components/header/account-setting/model-page/mo ...@@ -17,8 +19,10 @@ import ModelSelector from '@/app/components/header/account-setting/model-page/mo
import type { ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations' import type { ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations'
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations' import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import DatasetDetailContext from '@/context/dataset-detail' import DatasetDetailContext from '@/context/dataset-detail'
import { type RetrievalConfig } from '@/types/app'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
const rowClass = ` const rowClass = `
flex justify-between py-4 flex justify-between py-4
` `
...@@ -51,6 +55,12 @@ const Form = () => { ...@@ -51,6 +55,12 @@ const Form = () => {
const [description, setDescription] = useState(currentDataset?.description ?? '') const [description, setDescription] = useState(currentDataset?.description ?? '')
const [permission, setPermission] = useState(currentDataset?.permission) const [permission, setPermission] = useState(currentDataset?.permission)
const [indexMethod, setIndexMethod] = useState(currentDataset?.indexing_technique) const [indexMethod, setIndexMethod] = useState(currentDataset?.indexing_technique)
const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict as RetrievalConfig)
const {
rerankDefaultModel,
isRerankDefaultModelVaild,
} = useProviderContext()
const handleSave = async () => { const handleSave = async () => {
if (loading) if (loading)
return return
...@@ -58,6 +68,22 @@ const Form = () => { ...@@ -58,6 +68,22 @@ const Form = () => {
notify({ type: 'error', message: t('datasetSettings.form.nameError') }) notify({ type: 'error', message: t('datasetSettings.form.nameError') })
return return
} }
if (
!isReRankModelSelected({
rerankDefaultModel,
isRerankDefaultModelVaild,
retrievalConfig,
indexMethod,
})
) {
notify({ type: 'error', message: t('appDebug.datasetConfig.rerankModelRequired') })
return
}
const postRetrievalConfig = ensureRerankModelSelected({
rerankDefaultModel: rerankDefaultModel!,
retrievalConfig,
indexMethod,
})
try { try {
setLoading(true) setLoading(true)
await updateDatasetSetting({ await updateDatasetSetting({
...@@ -67,6 +93,7 @@ const Form = () => { ...@@ -67,6 +93,7 @@ const Form = () => {
description, description,
permission, permission,
indexing_technique: indexMethod, indexing_technique: indexMethod,
retrieval_model: postRetrievalConfig,
}, },
}) })
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
...@@ -172,6 +199,33 @@ const Form = () => { ...@@ -172,6 +199,33 @@ const Form = () => {
</div> </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>
{currentDataset?.embedding_available && ( {currentDataset?.embedding_available && (
<div className={rowClass}> <div className={rowClass}>
<div className={labelClass} /> <div className={labelClass} />
......
...@@ -13,12 +13,14 @@ const radioClass = ` ...@@ -13,12 +13,14 @@ const radioClass = `
type IPermissionsRadioProps = { type IPermissionsRadioProps = {
value?: DataSet['permission'] value?: DataSet['permission']
onChange: (v?: DataSet['permission']) => void onChange: (v?: DataSet['permission']) => void
itemClassName?: string
disable?: boolean disable?: boolean
} }
const PermissionsRadio = ({ const PermissionsRadio = ({
value, value,
onChange, onChange,
itemClassName,
disable, disable,
}: IPermissionsRadioProps) => { }: IPermissionsRadioProps) => {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -41,6 +43,7 @@ const PermissionsRadio = ({ ...@@ -41,6 +43,7 @@ const PermissionsRadio = ({
key={option.key} key={option.key}
className={classNames( className={classNames(
itemClass, itemClass,
itemClassName,
s.item, s.item,
option.key === value && s['item-active'], option.key === value && s['item-active'],
disable && s.disable, disable && s.disable,
......
import { ProviderEnum } from '../declarations'
import type { ProviderConfig } from '../declarations'
import { Cohere, CohereText } from '@/app/components/base/icons/src/public/llm'
const config: ProviderConfig = {
selector: {
name: {
'en': 'cohere',
'zh-Hans': 'cohere',
},
icon: <Cohere className='w-full h-full' />,
},
item: {
key: ProviderEnum.cohere,
titleIcon: {
'en': <CohereText className='w-[120px] h-6' />,
'zh-Hans': <CohereText className='w-[120px] h-6' />,
},
},
modal: {
key: ProviderEnum.cohere,
title: {
'en': 'cohere',
'zh-Hans': 'cohere',
},
icon: <Cohere className='w-6 h-6' />,
link: {
href: 'https://dashboard.cohere.com/api-keys',
label: {
'en': 'Get your API key from cohere',
'zh-Hans': '从 cohere 获取 API Key',
},
},
validateKeys: ['api_key'],
fields: [
{
type: 'text',
key: 'api_key',
required: true,
label: {
'en': 'API Key',
'zh-Hans': 'API Key',
},
placeholder: {
'en': 'Enter your API key here',
'zh-Hans': '在此输入您的 API Key',
},
},
],
},
}
export default config
...@@ -13,6 +13,7 @@ import openllm from './openllm' ...@@ -13,6 +13,7 @@ import openllm from './openllm'
import localai from './localai' import localai from './localai'
import zhipuai from './zhipuai' import zhipuai from './zhipuai'
import baichuan from './baichuan' import baichuan from './baichuan'
import cohere from './cohere'
export default { export default {
openai, openai,
...@@ -30,4 +31,5 @@ export default { ...@@ -30,4 +31,5 @@ export default {
localai, localai,
zhipuai, zhipuai,
baichuan, baichuan,
cohere,
} }
...@@ -45,6 +45,7 @@ export enum ProviderEnum { ...@@ -45,6 +45,7 @@ export enum ProviderEnum {
'localai' = 'localai', 'localai' = 'localai',
'zhipuai' = 'zhipuai', 'zhipuai' = 'zhipuai',
'baichuan' = 'baichuan', 'baichuan' = 'baichuan',
'cohere' = 'cohere',
} }
export type ProviderConfigItem = { export type ProviderConfigItem = {
...@@ -67,6 +68,7 @@ export enum ModelType { ...@@ -67,6 +68,7 @@ export enum ModelType {
textGeneration = 'text-generation', textGeneration = 'text-generation',
embeddings = 'embeddings', embeddings = 'embeddings',
speech2text = 'speech2text', speech2text = 'speech2text',
reranking = 'reranking',
} }
export enum ModelFeature { export enum ModelFeature {
......
...@@ -3,33 +3,28 @@ import useSWR from 'swr' ...@@ -3,33 +3,28 @@ import useSWR from 'swr'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import type { import type {
BackendModel,
FormValue, FormValue,
ProviderConfigModal, ProviderConfigModal,
ProviderEnum, ProviderEnum,
} from './declarations' } from './declarations'
import ModelSelector from './model-selector'
import ModelCard from './model-card' import ModelCard from './model-card'
import ModelItem from './model-item' import ModelItem from './model-item'
import ModelModal from './model-modal' import ModelModal from './model-modal'
import SystemModel from './system-model'
import config from './configs' import config from './configs'
import { ConfigurableProviders } from './utils' import { ConfigurableProviders } from './utils'
import { HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
import { import {
changeModelProviderPriority, changeModelProviderPriority,
deleteModelProvider, deleteModelProvider,
deleteModelProviderModel, deleteModelProviderModel,
fetchDefaultModal,
fetchModelProviders, fetchModelProviders,
setModelProvider, setModelProvider,
updateDefaultModel,
} from '@/service/common' } from '@/service/common'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
import Confirm from '@/app/components/base/confirm/common' import Confirm from '@/app/components/base/confirm/common'
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations' import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import Tooltip from '@/app/components/base/tooltip'
import I18n from '@/context/i18n' import I18n from '@/context/i18n'
const MODEL_CARD_LIST = [ const MODEL_CARD_LIST = [
...@@ -37,13 +32,6 @@ const MODEL_CARD_LIST = [ ...@@ -37,13 +32,6 @@ const MODEL_CARD_LIST = [
config.anthropic, config.anthropic,
] ]
const titleClassName = `
flex items-center h-9 text-sm font-medium text-gray-900
`
const tipClassName = `
ml-0.5 w-[14px] h-[14px] text-gray-400
`
type DeleteModel = { type DeleteModel = {
model_name: string model_name: string
model_type: string model_type: string
...@@ -54,13 +42,8 @@ const ModelPage = () => { ...@@ -54,13 +42,8 @@ const ModelPage = () => {
const { locale } = useContext(I18n) const { locale } = useContext(I18n)
const { const {
updateModelList, updateModelList,
embeddingsDefaultModel,
mutateEmbeddingsDefaultModel,
speech2textDefaultModel,
mutateSpeech2textDefaultModel,
} = useProviderContext() } = useProviderContext()
const { data: providers, mutate: mutateProviders } = useSWR('/workspaces/current/model-providers', fetchModelProviders) const { data: providers, mutate: mutateProviders } = useSWR('/workspaces/current/model-providers', fetchModelProviders)
const { data: textGenerationDefaultModel, mutate: mutateTextGenerationDefaultModel } = useSWR('/workspaces/current/default-model?model_type=text-generation', fetchDefaultModal)
const [showModal, setShowModal] = useState(false) const [showModal, setShowModal] = useState(false)
const { notify } = useToastContext() const { notify } = useToastContext()
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()
...@@ -76,6 +59,7 @@ const ModelPage = () => { ...@@ -76,6 +59,7 @@ const ModelPage = () => {
config.azure_openai, config.azure_openai,
config.replicate, config.replicate,
config.huggingface_hub, config.huggingface_hub,
config.cohere,
config.zhipuai, config.zhipuai,
config.baichuan, config.baichuan,
config.spark, config.spark,
...@@ -91,6 +75,7 @@ const ModelPage = () => { ...@@ -91,6 +75,7 @@ const ModelPage = () => {
else { else {
modelList = [ modelList = [
config.huggingface_hub, config.huggingface_hub,
config.cohere,
config.zhipuai, config.zhipuai,
config.spark, config.spark,
config.baichuan, config.baichuan,
...@@ -127,6 +112,7 @@ const ModelPage = () => { ...@@ -127,6 +112,7 @@ const ModelPage = () => {
updateModelList(ModelType.textGeneration) updateModelList(ModelType.textGeneration)
updateModelList(ModelType.embeddings) updateModelList(ModelType.embeddings)
updateModelList(ModelType.speech2text) updateModelList(ModelType.speech2text)
updateModelList(ModelType.reranking)
mutateProviders() mutateProviders()
} }
const handleSave = async (originValue?: FormValue) => { const handleSave = async (originValue?: FormValue) => {
...@@ -210,95 +196,12 @@ const ModelPage = () => { ...@@ -210,95 +196,12 @@ const ModelPage = () => {
} }
} }
const mutateDefaultModel = (type: ModelType) => {
if (type === ModelType.textGeneration)
mutateTextGenerationDefaultModel()
if (type === ModelType.embeddings)
mutateEmbeddingsDefaultModel()
if (type === ModelType.speech2text)
mutateSpeech2textDefaultModel()
}
const handleChangeDefaultModel = async (type: ModelType, v: BackendModel) => {
const res = await updateDefaultModel({
url: '/workspaces/current/default-model',
body: {
model_type: type,
provider_name: v.model_provider.provider_name,
model_name: v.model_name,
},
})
if (res.result === 'success') {
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
mutateDefaultModel(type)
}
}
return ( return (
<div className='relative pt-1 -mt-2'> <div className='relative pt-1 -mt-2'>
<div className='grid grid-cols-3 gap-4 mb-5'> <div className='flex items-center justify-between mb-2 h-8'>
<div className='w-full'> <div className='text-sm font-medium text-gray-800'>{t('common.modelProvider.models')}</div>
<div className={titleClassName}> <SystemModel />
{t('common.modelProvider.systemReasoningModel.key')}
<Tooltip
selector='model-page-system-reasoning-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.systemReasoningModel.tip')}</div>
}
>
<HelpCircle className={tipClassName} />
</Tooltip>
</div>
<div>
<ModelSelector
value={textGenerationDefaultModel && { providerName: textGenerationDefaultModel.model_provider.provider_name, modelName: textGenerationDefaultModel.model_name }}
modelType={ModelType.textGeneration}
onChange={v => handleChangeDefaultModel(ModelType.textGeneration, v)}
/>
</div>
</div>
<div className='w-full'>
<div className={titleClassName}>
{t('common.modelProvider.embeddingModel.key')}
<Tooltip
selector='model-page-system-embedding-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.embeddingModel.tip')}</div>
}
>
<HelpCircle className={tipClassName} />
</Tooltip>
</div>
<div>
<ModelSelector
value={embeddingsDefaultModel && { providerName: embeddingsDefaultModel.model_provider.provider_name, modelName: embeddingsDefaultModel.model_name }}
modelType={ModelType.embeddings}
onChange={v => handleChangeDefaultModel(ModelType.embeddings, v)}
/>
</div>
</div>
<div className='w-full'>
<div className={titleClassName}>
{t('common.modelProvider.speechToTextModel.key')}
<Tooltip
selector='model-page-system-speechToText-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.speechToTextModel.tip')}</div>
}
>
<HelpCircle className={tipClassName} />
</Tooltip>
</div>
<div>
<ModelSelector
value={speech2textDefaultModel && { providerName: speech2textDefaultModel.model_provider.provider_name, modelName: speech2textDefaultModel.model_name }}
modelType={ModelType.speech2text}
onChange={v => handleChangeDefaultModel(ModelType.speech2text, v)}
/>
</div>
</div>
</div> </div>
<div className='mb-5 h-[0.5px] bg-gray-100' />
<div className='mb-3 text-sm font-medium text-gray-800'>{t('common.modelProvider.models')}</div>
<div className='grid grid-cols-2 gap-4 mb-6'> <div className='grid grid-cols-2 gap-4 mb-6'>
{ {
MODEL_CARD_LIST.map((model, index) => ( MODEL_CARD_LIST.map((model, index) => (
......
...@@ -34,6 +34,7 @@ type Props = { ...@@ -34,6 +34,7 @@ type Props = {
popClassName?: string popClassName?: string
readonly?: boolean readonly?: boolean
triggerIconSmall?: boolean triggerIconSmall?: boolean
whenEmptyGoToSetting?: boolean
} }
type ModelOption = { type ModelOption = {
...@@ -57,10 +58,17 @@ const ModelSelector: FC<Props> = ({ ...@@ -57,10 +58,17 @@ const ModelSelector: FC<Props> = ({
popClassName, popClassName,
readonly, readonly,
triggerIconSmall, triggerIconSmall,
whenEmptyGoToSetting,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { setShowAccountSettingModal } = useModalContext() const { setShowAccountSettingModal } = useModalContext()
const { textGenerationModelList, embeddingsModelList, speech2textModelList, agentThoughtModelList } = useProviderContext() const {
textGenerationModelList,
embeddingsModelList,
speech2textModelList,
rerankModelList,
agentThoughtModelList,
} = useProviderContext()
const [search, setSearch] = useState('') const [search, setSearch] = useState('')
const modelList = supportAgentThought const modelList = supportAgentThought
? agentThoughtModelList ? agentThoughtModelList
...@@ -68,6 +76,7 @@ const ModelSelector: FC<Props> = ({ ...@@ -68,6 +76,7 @@ const ModelSelector: FC<Props> = ({
[ModelType.textGeneration]: textGenerationModelList, [ModelType.textGeneration]: textGenerationModelList,
[ModelType.embeddings]: embeddingsModelList, [ModelType.embeddings]: embeddingsModelList,
[ModelType.speech2text]: speech2textModelList, [ModelType.speech2text]: speech2textModelList,
[ModelType.reranking]: rerankModelList,
})[modelType] })[modelType]
const currModel = modelList.find(item => item.model_name === value?.modelName && item.model_provider.provider_name === value.providerName) const currModel = modelList.find(item => item.model_name === value?.modelName && item.model_provider.provider_name === value.providerName)
const allModelNames = (() => { const allModelNames = (() => {
...@@ -116,7 +125,7 @@ const ModelSelector: FC<Props> = ({ ...@@ -116,7 +125,7 @@ const ModelSelector: FC<Props> = ({
return ( return (
<div className=''> <div className=''>
<Popover className='relative'> <Popover className='relative'>
<Popover.Button className={cn('flex items-center px-2.5 w-full h-9 rounded-lg', readonly ? '!cursor-auto' : 'bg-gray-100', hasRemoved && '!bg-[#FEF3F2]')}> <Popover.Button className={cn('flex items-center px-2.5 w-full h-9 rounded-lg', readonly ? '!cursor-auto bg-gray-100 opacity-50' : 'bg-gray-100', hasRemoved && '!bg-[#FEF3F2]')}>
{ {
({ open }) => ( ({ open }) => (
<> <>
...@@ -130,7 +139,7 @@ const ModelSelector: FC<Props> = ({ ...@@ -130,7 +139,7 @@ const ModelSelector: FC<Props> = ({
providerName={value.providerName} providerName={value.providerName}
/> />
<div className='mr-1.5 grow flex items-center text-left text-sm text-gray-900 truncate'> <div className='mr-1.5 grow flex items-center text-left text-sm text-gray-900 truncate'>
<ModelName modelId={value.modelName} modelDisplayName={currModel?.model_display_name} /> <ModelName modelId={value.modelName} modelDisplayName={currModel?.model_display_name || value.modelName} />
{isShowModelModeType && ( {isShowModelModeType && (
<ModelModeTypeLabel className='ml-2' type={currModel?.model_mode as ModelModeType} /> <ModelModeTypeLabel className='ml-2' type={currModel?.model_mode as ModelModeType} />
)} )}
...@@ -237,7 +246,22 @@ const ModelSelector: FC<Props> = ({ ...@@ -237,7 +246,22 @@ const ModelSelector: FC<Props> = ({
return null return null
}) })
} }
{(search && filteredModelList.length === 0) && ( {
whenEmptyGoToSetting && modelList.length === 0 && (
<div className='pt-6'>
<div className='flex items-center justify-center mx-auto mb-2 w-12 h-12 rounded-[10px] border border-[#EAECF5]'>
<CubeOutline className='w-6 h-6 text-gray-500' />
</div>
<div className='mb-1 text-center text-[13px] font-medium text-gray-500'>
{t('common.modelProvider.selector.emptyTip')}
</div>
<div className='mb-6 text-center text-xs text-primary-500'>
<span onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('common.modelProvider.selector.emptySetting')}</span>
</div>
</div>
)
}
{modelList.length !== 0 && (search && filteredModelList.length === 0) && (
<div className='px-3 pt-1.5 h-[30px] text-center text-xs text-gray-500'>{t('common.modelProvider.noModelFound', { model: search })}</div> <div className='px-3 pt-1.5 h-[30px] text-center text-xs text-gray-500'>{t('common.modelProvider.noModelFound', { model: search })}</div>
)} )}
......
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import ModelSelector from '../model-selector'
import type {
BackendModel, ProviderEnum,
} from '../declarations'
import Tooltip from '@/app/components/base/tooltip'
import { HelpCircle, Settings01 } from '@/app/components/base/icons/src/vender/line/general'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { useProviderContext } from '@/context/provider-context'
import { updateDefaultModel } from '@/service/common'
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import { useToastContext } from '@/app/components/base/toast'
import Button from '@/app/components/base/button'
const SystemModel = () => {
const { t } = useTranslation()
const {
textGenerationDefaultModel,
mutateTextGenerationDefaultModel,
embeddingsDefaultModel,
mutateEmbeddingsDefaultModel,
speech2textDefaultModel,
mutateSpeech2textDefaultModel,
rerankDefaultModel,
mutateRerankDefaultModel,
} = useProviderContext()
const { notify } = useToastContext()
const [open, setOpen] = useState(false)
const [selectedModel, setSelectedModel] = useState<Record<ModelType, { providerName: ProviderEnum; modelName: string } | undefined>>({
[ModelType.textGeneration]: textGenerationDefaultModel && { providerName: textGenerationDefaultModel.model_provider.provider_name, modelName: textGenerationDefaultModel.model_name },
[ModelType.embeddings]: embeddingsDefaultModel && { providerName: embeddingsDefaultModel.model_provider.provider_name, modelName: embeddingsDefaultModel.model_name },
[ModelType.speech2text]: speech2textDefaultModel && { providerName: speech2textDefaultModel.model_provider.provider_name, modelName: speech2textDefaultModel.model_name },
[ModelType.reranking]: rerankDefaultModel && { providerName: rerankDefaultModel.model_provider.provider_name, modelName: rerankDefaultModel.model_name },
})
const mutateDefaultModel = (types: ModelType[]) => {
types.forEach((type) => {
if (type === ModelType.textGeneration)
mutateTextGenerationDefaultModel()
if (type === ModelType.embeddings)
mutateEmbeddingsDefaultModel()
if (type === ModelType.speech2text)
mutateSpeech2textDefaultModel()
if (type === ModelType.reranking)
mutateRerankDefaultModel()
})
}
const handleChangeDefaultModel = async (type: ModelType, v: BackendModel) => {
setSelectedModel({
...selectedModel,
[type]: {
providerName: v.model_provider.provider_name,
modelName: v.model_name,
},
})
}
const handleSave = async () => {
const kesArray = Object.keys(selectedModel) as ModelType[]
const res = await updateDefaultModel({
url: '/workspaces/current/default-model',
body: {
model_settings: kesArray.map((key) => {
return {
model_type: key,
provider_name: selectedModel?.[key]?.providerName,
model_name: selectedModel?.[key]?.modelName,
}
}),
},
})
if (res.result === 'success') {
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
mutateDefaultModel(kesArray)
}
}
return (
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-end'
offset={{
mainAxis: 4,
crossAxis: 8,
}}
>
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<div className={`
flex items-center px-2 h-6 text-xs text-gray-700 cursor-pointer rounded-md border-[0.5px] border-gray-200 shadow-xs
hover:bg-gray-100 hover:shadow-none
${open && 'bg-gray-100 shadow-none'}
`}>
<Settings01 className='mr-1 w-3 h-3 text-gray-500' />
{t('common.modelProvider.systemModelSettings')}
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-50'>
<div className='pt-4 w-[360px] rounded-xl border-[0.5px] border-black/5 bg-white shadow-xl'>
<div className='px-6 py-1'>
<div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
{t('common.modelProvider.systemReasoningModel.key')}
<Tooltip
selector='model-page-system-reasoning-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.systemReasoningModel.tip')}</div>
}
>
<HelpCircle className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
<div>
<ModelSelector
value={selectedModel[ModelType.textGeneration]}
modelType={ModelType.textGeneration}
onChange={v => handleChangeDefaultModel(ModelType.textGeneration, v)}
/>
</div>
</div>
<div className='px-6 py-1'>
<div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
{t('common.modelProvider.embeddingModel.key')}
<Tooltip
selector='model-page-system-embedding-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.embeddingModel.tip')}</div>
}
>
<HelpCircle className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
<div>
<ModelSelector
value={selectedModel[ModelType.embeddings]}
modelType={ModelType.embeddings}
onChange={v => handleChangeDefaultModel(ModelType.embeddings, v)}
/>
</div>
</div>
<div className='px-6 py-1'>
<div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
{t('common.modelProvider.rerankModel.key')}
<Tooltip
selector='model-page-system-rerankModel-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.rerankModel.tip')}</div>
}
>
<HelpCircle className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
<div>
<ModelSelector
value={selectedModel[ModelType.reranking]}
modelType={ModelType.reranking}
onChange={v => handleChangeDefaultModel(ModelType.reranking, v)}
/>
</div>
</div>
<div className='px-6 py-1'>
<div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
{t('common.modelProvider.speechToTextModel.key')}
<Tooltip
selector='model-page-system-speechToText-model-tip'
htmlContent={
<div className='w-[261px] text-gray-500'>{t('common.modelProvider.speechToTextModel.tip')}</div>
}
>
<HelpCircle className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
</Tooltip>
</div>
<div>
<ModelSelector
value={selectedModel[ModelType.speech2text]}
modelType={ModelType.speech2text}
onChange={v => handleChangeDefaultModel(ModelType.speech2text, v)}
/>
</div>
</div>
<div className='flex items-center justify-end px-6 py-4'>
<Button
className='mr-2 !h-8 !text-[13px]'
onClick={() => setOpen(false)}
>
{t('common.operation.cancel')}
</Button>
<Button
type='primary'
className='!h-8 !text-[13px]'
onClick={handleSave}
>
{t('common.operation.save')}
</Button>
</div>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
)
}
export default SystemModel
...@@ -141,3 +141,8 @@ export const VAR_ITEM_TEMPLATE = { ...@@ -141,3 +141,8 @@ export const VAR_ITEM_TEMPLATE = {
export const appDefaultIconBackground = '#D5F5F6' export const appDefaultIconBackground = '#D5F5F6'
export const NEED_REFRESH_APP_LIST_KEY = 'needRefreshAppList' export const NEED_REFRESH_APP_LIST_KEY = 'needRefreshAppList'
export const DATASET_DEFAULT = {
top_k: 2,
score_threshold: 0.5,
}
...@@ -20,7 +20,7 @@ import type { ...@@ -20,7 +20,7 @@ import type {
import type { ExternalDataTool } from '@/models/common' import type { ExternalDataTool } from '@/models/common'
import type { DataSet } from '@/models/datasets' import type { DataSet } from '@/models/datasets'
import type { VisionSettings } from '@/types/app' import type { VisionSettings } from '@/types/app'
import { ModelModeType, Resolution, TransferMethod } from '@/types/app' import { ModelModeType, RETRIEVE_TYPE, Resolution, TransferMethod } from '@/types/app'
import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config' import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config'
type IDebugConfiguration = { type IDebugConfiguration = {
...@@ -180,11 +180,14 @@ const DebugConfigurationContext = createContext<IDebugConfiguration>({ ...@@ -180,11 +180,14 @@ const DebugConfigurationContext = createContext<IDebugConfiguration>({
showSelectDataSet: () => { }, showSelectDataSet: () => { },
setDataSets: () => { }, setDataSets: () => { },
datasetConfigs: { datasetConfigs: {
top_k: 2, retrieval_model: RETRIEVE_TYPE.oneWay,
score_threshold: { reranking_model: {
enable: false, reranking_provider_name: '',
value: 0.7, reranking_model_name: '',
}, },
top_k: 2,
score_threshold_enabled: false,
score_threshold: 0.7,
}, },
setDatasetConfigs: () => {}, setDatasetConfigs: () => {},
hasSetContextVar: false, hasSetContextVar: false,
......
...@@ -2,29 +2,44 @@ ...@@ -2,29 +2,44 @@
import { createContext, useContext } from 'use-context-selector' import { createContext, useContext } from 'use-context-selector'
import useSWR from 'swr' import useSWR from 'swr'
import { fetchDefaultModal, fetchModelList } from '@/service/common' import { fetchDefaultModal, fetchModelList, fetchSupportRetrievalMethods } from '@/service/common'
import { ModelFeature, ModelType } from '@/app/components/header/account-setting/model-page/declarations' import { ModelFeature, ModelType } from '@/app/components/header/account-setting/model-page/declarations'
import type { BackendModel } from '@/app/components/header/account-setting/model-page/declarations' import type { BackendModel } from '@/app/components/header/account-setting/model-page/declarations'
import type { RETRIEVE_METHOD } from '@/types/app'
const ProviderContext = createContext<{ const ProviderContext = createContext<{
textGenerationModelList: BackendModel[] textGenerationModelList: BackendModel[]
embeddingsModelList: BackendModel[] embeddingsModelList: BackendModel[]
speech2textModelList: BackendModel[] speech2textModelList: BackendModel[]
rerankModelList: BackendModel[]
agentThoughtModelList: BackendModel[] agentThoughtModelList: BackendModel[]
updateModelList: (type: ModelType) => void updateModelList: (type: ModelType) => void
textGenerationDefaultModel?: BackendModel
mutateTextGenerationDefaultModel: () => void
embeddingsDefaultModel?: BackendModel embeddingsDefaultModel?: BackendModel
mutateEmbeddingsDefaultModel: () => void mutateEmbeddingsDefaultModel: () => void
speech2textDefaultModel?: BackendModel speech2textDefaultModel?: BackendModel
mutateSpeech2textDefaultModel: () => void mutateSpeech2textDefaultModel: () => void
rerankDefaultModel?: BackendModel
isRerankDefaultModelVaild: boolean
mutateRerankDefaultModel: () => void
supportRetrievalMethods: RETRIEVE_METHOD[]
}>({ }>({
textGenerationModelList: [], textGenerationModelList: [],
embeddingsModelList: [], embeddingsModelList: [],
speech2textModelList: [], speech2textModelList: [],
rerankModelList: [],
agentThoughtModelList: [], agentThoughtModelList: [],
updateModelList: () => {}, updateModelList: () => {},
textGenerationDefaultModel: undefined,
mutateTextGenerationDefaultModel: () => {},
speech2textDefaultModel: undefined, speech2textDefaultModel: undefined,
mutateSpeech2textDefaultModel: () => {}, mutateSpeech2textDefaultModel: () => {},
embeddingsDefaultModel: undefined, embeddingsDefaultModel: undefined,
mutateEmbeddingsDefaultModel: () => {}, mutateEmbeddingsDefaultModel: () => {},
rerankDefaultModel: undefined,
isRerankDefaultModelVaild: false,
mutateRerankDefaultModel: () => {},
supportRetrievalMethods: [],
}) })
export const useProviderContext = () => useContext(ProviderContext) export const useProviderContext = () => useContext(ProviderContext)
...@@ -35,21 +50,34 @@ type ProviderContextProviderProps = { ...@@ -35,21 +50,34 @@ type ProviderContextProviderProps = {
export const ProviderContextProvider = ({ export const ProviderContextProvider = ({
children, children,
}: ProviderContextProviderProps) => { }: ProviderContextProviderProps) => {
const { data: textGenerationDefaultModel, mutate: mutateTextGenerationDefaultModel } = useSWR('/workspaces/current/default-model?model_type=text-generation', fetchDefaultModal)
const { data: embeddingsDefaultModel, mutate: mutateEmbeddingsDefaultModel } = useSWR('/workspaces/current/default-model?model_type=embeddings', fetchDefaultModal) const { data: embeddingsDefaultModel, mutate: mutateEmbeddingsDefaultModel } = useSWR('/workspaces/current/default-model?model_type=embeddings', fetchDefaultModal)
const { data: speech2textDefaultModel, mutate: mutateSpeech2textDefaultModel } = useSWR('/workspaces/current/default-model?model_type=speech2text', fetchDefaultModal) const { data: speech2textDefaultModel, mutate: mutateSpeech2textDefaultModel } = useSWR('/workspaces/current/default-model?model_type=speech2text', fetchDefaultModal)
const { data: rerankDefaultModel, mutate: mutateRerankDefaultModel } = useSWR('/workspaces/current/default-model?model_type=reranking', fetchDefaultModal)
const fetchModelListUrlPrefix = '/workspaces/current/models/model-type/' const fetchModelListUrlPrefix = '/workspaces/current/models/model-type/'
const { data: textGenerationModelList, mutate: mutateTextGenerationModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.textGeneration}`, fetchModelList) const { data: textGenerationModelList, mutate: mutateTextGenerationModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.textGeneration}`, fetchModelList)
const { data: embeddingsModelList, mutate: mutateEmbeddingsModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.embeddings}`, fetchModelList) const { data: embeddingsModelList, mutate: mutateEmbeddingsModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.embeddings}`, fetchModelList)
const { data: speech2textModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.speech2text}`, fetchModelList) const { data: speech2textModelList, mutate: mutateSpeech2textModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.speech2text}`, fetchModelList)
const { data: rerankModelList, mutate: mutateRerankModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelType.reranking}`, fetchModelList)
const { data: supportRetrievalMethods } = useSWR('/datasets/retrieval-setting', fetchSupportRetrievalMethods)
const agentThoughtModelList = textGenerationModelList?.filter((item) => { const agentThoughtModelList = textGenerationModelList?.filter((item) => {
return item.features?.includes(ModelFeature.agentThought) return item.features?.includes(ModelFeature.agentThought)
}) })
const isRerankDefaultModelVaild = !!rerankModelList?.find(
item => item.model_name === rerankDefaultModel?.model_name && item.model_provider.provider_name === rerankDefaultModel?.model_provider.provider_name,
)
const updateModelList = (type: ModelType) => { const updateModelList = (type: ModelType) => {
if (type === ModelType.textGeneration) if (type === ModelType.textGeneration)
mutateTextGenerationModelList() mutateTextGenerationModelList()
if (type === ModelType.embeddings) if (type === ModelType.embeddings)
mutateEmbeddingsModelList() mutateEmbeddingsModelList()
if (type === ModelType.speech2text)
mutateSpeech2textModelList()
if (type === ModelType.reranking)
mutateRerankModelList()
} }
return ( return (
...@@ -57,12 +85,19 @@ export const ProviderContextProvider = ({ ...@@ -57,12 +85,19 @@ export const ProviderContextProvider = ({
textGenerationModelList: textGenerationModelList || [], textGenerationModelList: textGenerationModelList || [],
embeddingsModelList: embeddingsModelList || [], embeddingsModelList: embeddingsModelList || [],
speech2textModelList: speech2textModelList || [], speech2textModelList: speech2textModelList || [],
rerankModelList: rerankModelList || [],
agentThoughtModelList: agentThoughtModelList || [], agentThoughtModelList: agentThoughtModelList || [],
updateModelList, updateModelList,
textGenerationDefaultModel,
mutateTextGenerationDefaultModel,
embeddingsDefaultModel, embeddingsDefaultModel,
mutateEmbeddingsDefaultModel, mutateEmbeddingsDefaultModel,
speech2textDefaultModel, speech2textDefaultModel,
mutateSpeech2textDefaultModel, mutateSpeech2textDefaultModel,
rerankDefaultModel,
isRerankDefaultModelVaild,
mutateRerankDefaultModel,
supportRetrievalMethods: supportRetrievalMethods?.retrieval_method || [],
}}> }}>
{children} {children}
</ProviderContext.Provider> </ProviderContext.Provider>
......
...@@ -305,11 +305,22 @@ const translation = { ...@@ -305,11 +305,22 @@ const translation = {
}, },
result: 'Output Text', result: 'Output Text',
datasetConfig: { datasetConfig: {
settingTitle: 'Retrieve Settings',
retrieveOneWay: {
title: 'N-to-1 retrieval',
description: 'Based on user intent and dataset descriptions, the Agent autonomously selects the best dataset for querying. Best for applications with distinct, limited datasets.',
},
retrieveMultiWay: {
title: 'Multi-path retrieval',
description: 'Based on user intent, queries across all datasets, retrieves relevant text from multi-sources, and selects the best results matching the user query after reranking. Configuration of the Rerank model API is required.',
},
rerankModelRequired: 'Rerank model is required',
params: 'Params', params: 'Params',
top_k: 'Top K', top_k: 'Top K',
top_kTip: 'Used to filter segments that are most similar to user questions. The system will also dynamically adjust the value of Top K, according to max_tokens of the selected model.', top_kTip: 'Used to filter segments that are most similar to user questions. The system will also dynamically adjust the value of Top K, according to max_tokens of the selected model.',
score_threshold: 'Score Threshold', score_threshold: 'Score Threshold',
score_thresholdTip: 'Used to set the similarity threshold for segment filtering.', score_thresholdTip: 'Used to set the similarity threshold for segment filtering.',
retrieveChangeTip: 'Modifying the index mode and retrieval mode may affect applications associated with this dataset.',
}, },
} }
......
...@@ -299,11 +299,22 @@ const translation = { ...@@ -299,11 +299,22 @@ const translation = {
}, },
result: '结果', result: '结果',
datasetConfig: { datasetConfig: {
settingTitle: '召回设置',
retrieveOneWay: {
title: 'N选1召回',
description: '根据用户意图和数据集描述,由 Agent 自主判断选择最匹配的单个数据集来查询相关文本,适合数据集区分度大且数据集数量偏少的应用。',
},
retrieveMultiWay: {
title: '多路召回',
description: '根据用户意图同时匹配所有数据集,从多路数据集查询相关文本片段,经过重排序步骤,从多路查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。',
},
rerankModelRequired: '请选择 Rerank 模型',
params: '参数设置', params: '参数设置',
top_k: 'Top K', top_k: 'Top K',
top_kTip: '用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整分段数量。', top_kTip: '用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整分段数量。',
score_threshold: 'Score 阈值', score_threshold: 'Score 阈值',
score_thresholdTip: '用于设置文本片段筛选的相似度阈值。', score_thresholdTip: '用于设置文本片段筛选的相似度阈值。',
retrieveChangeTip: '修改索引模式和检索模式可能会影响与该数据集关联的应用程序。',
}, },
} }
......
...@@ -223,6 +223,8 @@ const translation = { ...@@ -223,6 +223,8 @@ const translation = {
}, },
}, },
modelProvider: { modelProvider: {
systemModelSettings: 'System Model Settings',
systemModelSettingsLink: 'Why is it necessary to set up a system model?',
selectModel: 'Select your model', selectModel: 'Select your model',
setupModelFirst: 'Please set up your model first', setupModelFirst: 'Please set up your model first',
systemReasoningModel: { systemReasoningModel: {
...@@ -237,6 +239,10 @@ const translation = { ...@@ -237,6 +239,10 @@ const translation = {
key: 'Speech-to-Text Model', key: 'Speech-to-Text Model',
tip: 'Set the default model for speech-to-text input in conversation.', tip: 'Set the default model for speech-to-text input in conversation.',
}, },
rerankModel: {
key: 'Rerank Model',
tip: 'Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking',
},
quota: 'Quota', quota: 'Quota',
searchModel: 'Search model', searchModel: 'Search model',
noModelFound: 'No model found for {{model}}', noModelFound: 'No model found for {{model}}',
...@@ -244,6 +250,8 @@ const translation = { ...@@ -244,6 +250,8 @@ const translation = {
showMoreModelProvider: 'Show more model provider', showMoreModelProvider: 'Show more model provider',
selector: { selector: {
tip: 'This model has been removed. Please add a model or select another model.', tip: 'This model has been removed. Please add a model or select another model.',
emptyTip: 'No available models',
emptySetting: 'Please go to settings to configure',
}, },
card: { card: {
quota: 'QUOTA', quota: 'QUOTA',
...@@ -351,7 +359,7 @@ const translation = { ...@@ -351,7 +359,7 @@ const translation = {
}, },
datasetMenus: { datasetMenus: {
documents: 'Documents', documents: 'Documents',
hitTesting: 'Hit Testing', hitTesting: 'Retrieval Testing',
settings: 'Settings', settings: 'Settings',
emptyTip: 'The data set has not been associated, please go to the application or plug-in to complete the association.', emptyTip: 'The data set has not been associated, please go to the application or plug-in to complete the association.',
viewDoc: 'View documentation', viewDoc: 'View documentation',
...@@ -382,9 +390,9 @@ const translation = { ...@@ -382,9 +390,9 @@ const translation = {
title: 'CITATIONS', title: 'CITATIONS',
linkToDataset: 'Link to dataset', linkToDataset: 'Link to dataset',
characters: 'Characters:', characters: 'Characters:',
hitCount: 'Hit count:', hitCount: 'Retrieval count:',
vectorHash: 'Vector hash:', vectorHash: 'Vector hash:',
hitScore: 'Hit Score:', hitScore: 'Retrieval Score:',
}, },
}, },
promptEditor: { promptEditor: {
......
...@@ -223,6 +223,8 @@ const translation = { ...@@ -223,6 +223,8 @@ const translation = {
}, },
}, },
modelProvider: { modelProvider: {
systemModelSettings: '系统模型设置',
systemModelSettingsLink: '为什么需要设置系统模型?',
selectModel: '选择您的模型', selectModel: '选择您的模型',
setupModelFirst: '请先设置您的模型', setupModelFirst: '请先设置您的模型',
systemReasoningModel: { systemReasoningModel: {
...@@ -237,6 +239,10 @@ const translation = { ...@@ -237,6 +239,10 @@ const translation = {
key: '语音转文本模型', key: '语音转文本模型',
tip: '设置对话中语音转文字输入的默认使用模型。', tip: '设置对话中语音转文字输入的默认使用模型。',
}, },
rerankModel: {
key: 'Rerank 模型',
tip: '重排序模型将根据候选文档列表与用户问题语义匹配度进行重新排序,从而改进语义排序的结果',
},
quota: '额度', quota: '额度',
searchModel: '搜索模型', searchModel: '搜索模型',
noModelFound: '找不到模型 {{model}}', noModelFound: '找不到模型 {{model}}',
...@@ -244,6 +250,8 @@ const translation = { ...@@ -244,6 +250,8 @@ const translation = {
showMoreModelProvider: '显示更多模型提供商', showMoreModelProvider: '显示更多模型提供商',
selector: { selector: {
tip: '该模型已被删除。请添模型或选择其他模型。', tip: '该模型已被删除。请添模型或选择其他模型。',
emptyTip: '无可用模型',
emptySetting: '请前往设置进行配置',
}, },
card: { card: {
quota: '额度', quota: '额度',
...@@ -351,7 +359,7 @@ const translation = { ...@@ -351,7 +359,7 @@ const translation = {
}, },
datasetMenus: { datasetMenus: {
documents: '文档', documents: '文档',
hitTesting: '命中测试', hitTesting: '召回测试',
settings: '设置', settings: '设置',
emptyTip: ' 数据集尚未关联,请前往应用程序或插件完成关联。', emptyTip: ' 数据集尚未关联,请前往应用程序或插件完成关联。',
viewDoc: '查看文档', viewDoc: '查看文档',
...@@ -382,9 +390,9 @@ const translation = { ...@@ -382,9 +390,9 @@ const translation = {
title: '引用', title: '引用',
linkToDataset: '跳转至数据集', linkToDataset: '跳转至数据集',
characters: '字符:', characters: '字符:',
hitCount: '命中次数:', hitCount: '召回次数:',
vectorHash: '向量哈希:', vectorHash: '向量哈希:',
hitScore: '命中得分:', hitScore: '召回得分:',
}, },
}, },
promptEditor: { promptEditor: {
......
...@@ -101,6 +101,7 @@ const translation = { ...@@ -101,6 +101,7 @@ const translation = {
previewSwitchTipEnd: ' consume additional tokens', previewSwitchTipEnd: ' consume additional tokens',
characters: 'characters', characters: 'characters',
indexSettedTip: 'To change the index method, please go to the ', indexSettedTip: 'To change the index method, please go to the ',
retrivalSettedTip: 'To change the index method, please go to the ',
datasetSettingLink: 'dataset settings.', datasetSettingLink: 'dataset settings.',
}, },
stepThree: { stepThree: {
......
...@@ -101,6 +101,7 @@ const translation = { ...@@ -101,6 +101,7 @@ const translation = {
previewSwitchTipEnd: '消耗额外的 token', previewSwitchTipEnd: '消耗额外的 token',
characters: '字符', characters: '字符',
indexSettedTip: '要更改索引方法,请转到', indexSettedTip: '要更改索引方法,请转到',
retrivalSettedTip: '要更改检索方法,请转到',
datasetSettingLink: '数据集设置。', datasetSettingLink: '数据集设置。',
}, },
stepThree: { stepThree: {
......
...@@ -8,7 +8,7 @@ const translation = { ...@@ -8,7 +8,7 @@ const translation = {
header: { header: {
fileName: 'FILE NAME', fileName: 'FILE NAME',
words: 'WORDS', words: 'WORDS',
hitCount: 'HIT COUNT', hitCount: 'RETRIEVAL COUNT',
uploadTime: 'UPLOAD TIME', uploadTime: 'UPLOAD TIME',
status: 'STATUS', status: 'STATUS',
action: 'ACTION', action: 'ACTION',
...@@ -216,7 +216,7 @@ const translation = { ...@@ -216,7 +216,7 @@ const translation = {
segmentLength: 'Segment length', segmentLength: 'Segment length',
avgParagraphLength: 'Avg. paragraph length', avgParagraphLength: 'Avg. paragraph length',
paragraphs: 'Paragraphs', paragraphs: 'Paragraphs',
hitCount: 'Hit count', hitCount: 'Retrieval count',
embeddingTime: 'Embedding time', embeddingTime: 'Embedding time',
embeddedSpend: 'Embedded spend', embeddedSpend: 'Embedded spend',
}, },
...@@ -332,7 +332,7 @@ const translation = { ...@@ -332,7 +332,7 @@ const translation = {
addKeyWord: 'Add key word', addKeyWord: 'Add key word',
keywordError: 'The maximum length of keyword is 20', keywordError: 'The maximum length of keyword is 20',
characters: 'characters', characters: 'characters',
hitCount: 'hit count', hitCount: 'Retrieval count',
vectorHash: 'Vector hash: ', vectorHash: 'Vector hash: ',
questionPlaceholder: 'add question here', questionPlaceholder: 'add question here',
questionEmpty: 'Question can not be empty', questionEmpty: 'Question can not be empty',
......
...@@ -8,7 +8,7 @@ const translation = { ...@@ -8,7 +8,7 @@ const translation = {
header: { header: {
fileName: '文件名', fileName: '文件名',
words: '字符数', words: '字符数',
hitCount: '命中次数', hitCount: '召回次数',
uploadTime: '上传时间', uploadTime: '上传时间',
status: '状态', status: '状态',
action: '操作', action: '操作',
...@@ -215,7 +215,7 @@ const translation = { ...@@ -215,7 +215,7 @@ const translation = {
segmentLength: '段落长度', segmentLength: '段落长度',
avgParagraphLength: '平均段落长度', avgParagraphLength: '平均段落长度',
paragraphs: '段落数量', paragraphs: '段落数量',
hitCount: '命中次数', hitCount: '召回次数',
embeddingTime: '嵌入时间', embeddingTime: '嵌入时间',
embeddedSpend: '嵌入花费', embeddedSpend: '嵌入花费',
}, },
...@@ -331,7 +331,7 @@ const translation = { ...@@ -331,7 +331,7 @@ const translation = {
addKeyWord: '添加关键词', addKeyWord: '添加关键词',
keywordError: '关键词最大长度为 20', keywordError: '关键词最大长度为 20',
characters: '字符', characters: '字符',
hitCount: '命中次数', hitCount: '召回次数',
vectorHash: '向量哈希:', vectorHash: '向量哈希:',
questionPlaceholder: '在这里添加问题', questionPlaceholder: '在这里添加问题',
questionEmpty: '问题不能为空', questionEmpty: '问题不能为空',
......
const translation = { const translation = {
title: "Hit Testing", title: 'Retrieval Testing',
desc: "Test the hitting effect of the dataset based on the given query text.", desc: 'Test the hitting effect of the dataset based on the given query text.',
dateTimeFormat: 'MM/DD/YYYY hh:mm A', dateTimeFormat: 'MM/DD/YYYY hh:mm A',
recents: 'Recents', recents: 'Recents',
table: { table: {
header: { header: {
source: "Source", source: 'Source',
text: "Text", text: 'Text',
time: "Time", time: 'Time',
}, },
}, },
input: { input: {
...@@ -18,11 +18,11 @@ const translation = { ...@@ -18,11 +18,11 @@ const translation = {
testing: 'Testing', testing: 'Testing',
}, },
hit: { hit: {
title: "HIT PARAGRAPHS", title: 'RETRIEVAL PARAGRAPHS',
emptyTip: 'Hit Testing results will show here', emptyTip: 'Retrieval Testing results will show here',
}, },
noRecentTip: 'No recent query results here', noRecentTip: 'No recent query results here',
viewChart: 'View VECTOR CHART', viewChart: 'View VECTOR CHART',
}; }
export default translation; export default translation
const translation = { const translation = {
title: '命中测试', title: '召回测试',
desc: '基于给定的查询文本测试数据集的命中效果。', desc: '基于给定的查询文本测试数据集的召回效果。',
dateTimeFormat: 'YYYY-MM-DD HH:mm', dateTimeFormat: 'YYYY-MM-DD HH:mm',
recents: '最近查询', recents: '最近查询',
table: { table: {
header: { header: {
source: "数据源", source: '数据源',
text: "文本", text: '文本',
time: "时间", time: '时间',
}, },
}, },
input: { input: {
...@@ -18,8 +18,8 @@ const translation = { ...@@ -18,8 +18,8 @@ const translation = {
testing: '测试', testing: '测试',
}, },
hit: { hit: {
title: "命中段落", title: '召回段落',
emptyTip: '命中测试结果将展示在这里', emptyTip: '召回测试结果将展示在这里',
}, },
noRecentTip: '最近无查询结果', noRecentTip: '最近无查询结果',
viewChart: '查看向量图表', viewChart: '查看向量图表',
......
...@@ -20,6 +20,12 @@ const translation = { ...@@ -20,6 +20,12 @@ const translation = {
embeddingModel: 'Embedding Model', embeddingModel: 'Embedding Model',
embeddingModelTip: 'Change the embedded model, please go to ', embeddingModelTip: 'Change the embedded model, please go to ',
embeddingModelTipLink: 'Settings', embeddingModelTipLink: 'Settings',
retrievalSetting: {
title: 'Retrieval setting',
learnMore: 'Learn more',
description: ' about retrieval method.',
longDescription: ' about retrieval method, you can change this at any time in the dataset settings.',
},
save: 'Save', save: 'Save',
}, },
} }
......
...@@ -20,6 +20,12 @@ const translation = { ...@@ -20,6 +20,12 @@ const translation = {
embeddingModel: 'Embedding 模型', embeddingModel: 'Embedding 模型',
embeddingModelTip: '修改 Embedding 模型,请去', embeddingModelTip: '修改 Embedding 模型,请去',
embeddingModelTipLink: '设置', embeddingModelTipLink: '设置',
retrievalSetting: {
title: '检索设置',
learnMore: '了解更多',
description: '关于检索方法。',
longDescription: '关于检索方法,您可以随时在数据集设置中更改此设置。',
},
save: '保存', save: '保存',
}, },
} }
......
...@@ -20,6 +20,27 @@ const translation = { ...@@ -20,6 +20,27 @@ const translation = {
unavailableTip: 'Embedding model is not available, the default embedding model needs to be configured', unavailableTip: 'Embedding model is not available, the default embedding model needs to be configured',
datasets: 'DATASETS', datasets: 'DATASETS',
datasetsApi: 'API', datasetsApi: 'API',
retrieval: {
semantic_search: {
title: 'Vector Search',
description: 'Generate query embeddings and search for the text chunk most similar to its vector representation.',
},
full_text_search: {
title: 'Full-Text Search',
description: 'Index all terms in the document, allowing users to search any term and retrieve relevant text chunk containing those terms.',
},
hybrid_search: {
title: 'Hybrid Search',
description: 'Execute full-text search and vector searches simultaneously, re-rank to select the best match for the user\'s query. Configuration of the Rerank model APIis necessary.',
recommend: 'Recommend',
},
invertedIndex: {
title: 'Inverted Index',
description: 'Inverted Index is a structure used for efficient retrieval. Organized by terms, each term points to documents or web pages containing it.',
},
change: 'Change',
changeRetrievalMethod: 'Change retrieval method',
},
} }
export default translation export default translation
...@@ -20,6 +20,27 @@ const translation = { ...@@ -20,6 +20,27 @@ const translation = {
unavailableTip: '由于 embedding 模型不可用,需要配置默认 embedding 模型', unavailableTip: '由于 embedding 模型不可用,需要配置默认 embedding 模型',
datasets: '数据集', datasets: '数据集',
datasetsApi: 'API', datasetsApi: 'API',
retrieval: {
semantic_search: {
title: '向量检索',
description: '通过生成查询嵌入并查询与其向量表示最相似的文本分段',
},
full_text_search: {
title: '全文检索',
description: '索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段',
},
hybrid_search: {
title: '混合检索',
description: '同时执行全文检索和向量检索,并应用重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API',
recommend: '推荐',
},
invertedIndex: {
title: '倒排索引',
description: '倒排索引是一种用于高效检索的结构。按术语组织,每个术语指向包含它的文档或网页',
},
change: '更改',
changeRetrievalMethod: '更改检索方法',
},
} }
export default translation export default translation
import type { AppMode } from './app' import type { AppMode } from './app'
import type { DataSourceNotionPage } from './common' import type { DataSourceNotionPage } from './common'
import type { RetrievalConfig } from '@/types/app'
export enum DataSourceType { export enum DataSourceType {
FILE = 'upload_file', FILE = 'upload_file',
...@@ -25,6 +26,8 @@ export type DataSet = { ...@@ -25,6 +26,8 @@ export type DataSet = {
embedding_model: string embedding_model: string
embedding_model_provider: string embedding_model_provider: string
embedding_available: boolean embedding_available: boolean
retrieval_model_dict: RetrievalConfig
retrieval_model: RetrievalConfig
} }
export type CustomFile = File & { export type CustomFile = File & {
...@@ -193,6 +196,7 @@ export type DocumentReq = { ...@@ -193,6 +196,7 @@ export type DocumentReq = {
export type CreateDocumentReq = DocumentReq & { export type CreateDocumentReq = DocumentReq & {
data_source: DataSource data_source: DataSource
retrieval_model: RetrievalConfig
} }
export type IndexingEstimateParams = DocumentReq & Partial<DataSource> & { export type IndexingEstimateParams = DocumentReq & Partial<DataSource> & {
......
import type { ModelModeType } from '@/types/app' import type { ModelModeType, RETRIEVE_TYPE } from '@/types/app'
export type Inputs = Record<string, string | number | object> export type Inputs = Record<string, string | number | object>
export enum PromptMode { export enum PromptMode {
...@@ -107,9 +107,16 @@ export type DatasetConfigItem = { ...@@ -107,9 +107,16 @@ export type DatasetConfigItem = {
enable: boolean enable: boolean
value: number value: number
} }
export type DatasetConfigs = { export type DatasetConfigs = {
retrieval_model: RETRIEVE_TYPE
reranking_model: {
reranking_provider_name: string
reranking_model_name: string
}
top_k: number top_k: number
score_threshold: DatasetConfigItem score_threshold_enabled: boolean
score_threshold: number
} }
export type DebugRequestBody = { export type DebugRequestBody = {
......
...@@ -27,6 +27,7 @@ import type { ...@@ -27,6 +27,7 @@ import type {
ValidateOpenAIKeyResponse, ValidateOpenAIKeyResponse,
} from '@/models/app' } from '@/models/app'
import type { BackendModel, ProviderMap } from '@/app/components/header/account-setting/model-page/declarations' import type { BackendModel, ProviderMap } from '@/app/components/header/account-setting/model-page/declarations'
import type { RETRIEVE_METHOD } from '@/types/app'
export const login: Fetcher<CommonResponse & { data: string }, { url: string; body: Record<string, any> }> = ({ url, body }) => { export const login: Fetcher<CommonResponse & { data: string }, { url: string; body: Record<string, any> }> = ({ url, body }) => {
return post(url, { body }) as Promise<CommonResponse & { data: string }> return post(url, { body }) as Promise<CommonResponse & { data: string }>
...@@ -237,3 +238,10 @@ export const fetchCodeBasedExtensionList: Fetcher<CodeBasedExtension, string> = ...@@ -237,3 +238,10 @@ export const fetchCodeBasedExtensionList: Fetcher<CodeBasedExtension, string> =
export const moderate = (url: string, body: { app_id: string; text: string }) => { export const moderate = (url: string, body: { app_id: string; text: string }) => {
return post(url, { body }) as Promise<ModerateResponse> return post(url, { body }) as Promise<ModerateResponse>
} }
type RetrievalMethodsRes = {
'retrieval_method': RETRIEVE_METHOD[]
}
export const fetchSupportRetrievalMethods: Fetcher<RetrievalMethodsRes, string> = (url) => {
return get<RetrievalMethodsRes>(url)
}
...@@ -27,6 +27,7 @@ import type { ...@@ -27,6 +27,7 @@ import type {
ApikeysListResponse, ApikeysListResponse,
CreateApiKeyResponse, CreateApiKeyResponse,
} from '@/models/app' } from '@/models/app'
import type { RetrievalConfig } from '@/types/app'
// apis for documents in a dataset // apis for documents in a dataset
...@@ -48,7 +49,7 @@ export const fetchDatasetDetail: Fetcher<DataSet, string> = (datasetId: string) ...@@ -48,7 +49,7 @@ export const fetchDatasetDetail: Fetcher<DataSet, string> = (datasetId: string)
return get<DataSet>(`/datasets/${datasetId}`) return get<DataSet>(`/datasets/${datasetId}`)
} }
export const updateDatasetSetting: Fetcher<DataSet, { datasetId: string; body: Partial<Pick<DataSet, 'name' | 'description' | 'permission' | 'indexing_technique'>> }> = ({ datasetId, body }) => { export const updateDatasetSetting: Fetcher<DataSet, { datasetId: string; body: Partial<Pick<DataSet, 'name' | 'description' | 'permission' | 'indexing_technique' | 'retrieval_model'>> }> = ({ datasetId, body }) => {
return patch<DataSet>(`/datasets/${datasetId}`, { body }) return patch<DataSet>(`/datasets/${datasetId}`, { body })
} }
...@@ -182,8 +183,8 @@ export const checkSegmentBatchImportProgress: Fetcher<{ job_id: string; job_stat ...@@ -182,8 +183,8 @@ export const checkSegmentBatchImportProgress: Fetcher<{ job_id: string; job_stat
} }
// hit testing // hit testing
export const hitTesting: Fetcher<HitTestingResponse, { datasetId: string; queryText: string }> = ({ datasetId, queryText }) => { export const hitTesting: Fetcher<HitTestingResponse, { datasetId: string; queryText: string; retrieval_model: RetrievalConfig }> = ({ datasetId, queryText, retrieval_model }) => {
return post<HitTestingResponse>(`/datasets/${datasetId}/hit-testing`, { body: { query: queryText } }) return post<HitTestingResponse>(`/datasets/${datasetId}/hit-testing`, { body: { query: queryText, retrieval_model } })
} }
export const fetchTestingRecords: Fetcher<HitTestingRecordsResponse, { datasetId: string; params: { page: number; limit: number } }> = ({ datasetId, params }) => { export const fetchTestingRecords: Fetcher<HitTestingRecordsResponse, { datasetId: string; params: { page: number; limit: number } }> = ({ datasetId, params }) => {
......
...@@ -22,6 +22,18 @@ export enum ModelModeType { ...@@ -22,6 +22,18 @@ export enum ModelModeType {
'unset' = '', 'unset' = '',
} }
export enum RETRIEVE_TYPE {
oneWay = 'single',
multiWay = 'multiple',
}
export enum RETRIEVE_METHOD {
semantic = 'semantic_search',
fullText = 'full_text_search',
hybrid = 'hybrid_search',
invertedIndex = 'invertedIndex',
}
export type VariableInput = { export type VariableInput = {
key: string key: string
name: string name: string
...@@ -311,3 +323,15 @@ export type VisionFile = { ...@@ -311,3 +323,15 @@ export type VisionFile = {
url: string url: string
upload_file_id: string upload_file_id: string
} }
export type RetrievalConfig = {
search_method: RETRIEVE_METHOD
reranking_enable: boolean
reranking_model: {
reranking_provider_name: string
reranking_model_name: string
}
top_k: number
score_threshold_enable: boolean
score_threshold: number
}
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