Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline

This commit is contained in:
twwu 2025-05-19 16:26:24 +08:00
commit 7898dbd5bf
15 changed files with 223 additions and 142 deletions

View File

@ -1,25 +1,35 @@
import {
memo,
useCallback,
useMemo,
} from 'react'
import type { HeaderProps } from '@/app/components/workflow/header'
import Header from '@/app/components/workflow/header'
import { fetchWorkflowRunHistory } from '@/service/workflow'
import { useStore } from '@/app/components/workflow/store'
import {
useStore,
useWorkflowStore,
} from '@/app/components/workflow/store'
import InputFieldButton from './input-field-button'
import Publisher from './publisher'
const RagPipelineHeader = () => {
const workflowStore = useWorkflowStore()
const pipelineId = useStore(s => s.pipelineId)
const showDebugAndPreviewPanel = useStore(s => s.showDebugAndPreviewPanel)
const viewHistoryProps = useMemo(() => {
return {
historyUrl: '',
// historyUrl: `/rag/pipeline/${pipelineId}/workflow-runs`,
historyUrl: `/rag/pipelines/${pipelineId}/workflow-runs`,
historyFetcher: fetchWorkflowRunHistory,
}
}, [pipelineId])
const handleStopRun = useCallback(() => {
const { setShowDebugAndPreviewPanel } = workflowStore.getState()
setShowDebugAndPreviewPanel(false)
}, [workflowStore])
const headerProps: HeaderProps = useMemo(() => {
return {
normal: {
@ -31,13 +41,15 @@ const RagPipelineHeader = () => {
showRunButton: true,
runButtonText: 'Test Run',
viewHistoryProps,
isRunning: showDebugAndPreviewPanel,
onStopRun: handleStopRun,
},
},
viewHistory: {
viewHistoryProps,
},
}
}, [viewHistoryProps])
}, [viewHistoryProps, showDebugAndPreviewPanel, handleStopRun])
return (
<Header {...headerProps} />

View File

@ -93,8 +93,8 @@ export const useNodesSyncDraft = () => {
) => {
if (getNodesReadOnly())
return
const postParams = getPostParams()
const postParams = getPostParams()
if (postParams) {
const {
setSyncWorkflowDraftHash,

View File

@ -1,21 +1,16 @@
import { useCallback } from 'react'
import { useStoreApi } from 'reactflow'
import { useWorkflowStore } from '@/app/components/workflow/store'
import {
BlockEnum,
WorkflowRunningStatus,
} from '@/app/components/workflow/types'
import { useWorkflowInteractions } from '@/app/components/workflow/hooks'
import {
useNodesSyncDraft,
usePipelineRun,
} from '.'
export const usePipelineStartRun = () => {
const store = useStoreApi()
const workflowStore = useWorkflowStore()
const { handleCancelDebugAndPreviewPanel } = useWorkflowInteractions()
const { handleRun } = usePipelineRun()
const { doSyncWorkflowDraft } = useNodesSyncDraft()
const handleWorkflowStartRunInWorkflow = useCallback(async () => {
@ -26,13 +21,8 @@ export const usePipelineStartRun = () => {
if (workflowRunningData?.result.status === WorkflowRunningStatus.Running)
return
const { getNodes } = store.getState()
const nodes = getNodes()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startVariables = startNode?.data.variables || []
const {
showDebugAndPreviewPanel,
setShowInputsPanel,
setShowEnvPanel,
setShowDebugAndPreviewPanel,
} = workflowStore.getState()
@ -44,17 +34,9 @@ export const usePipelineStartRun = () => {
return
}
if (!startVariables.length) {
await doSyncWorkflowDraft()
handleRun({ inputs: {}, files: [] })
setShowDebugAndPreviewPanel(true)
setShowInputsPanel(false)
}
else {
setShowDebugAndPreviewPanel(true)
setShowInputsPanel(true)
}
}, [store, workflowStore, handleCancelDebugAndPreviewPanel, handleRun, doSyncWorkflowDraft])
await doSyncWorkflowDraft()
setShowDebugAndPreviewPanel(true)
}, [workflowStore, handleCancelDebugAndPreviewPanel, doSyncWorkflowDraft])
const handleStartWorkflowRun = useCallback(() => {
handleWorkflowStartRunInWorkflow()

View File

@ -21,30 +21,36 @@ import {
type RunModeProps = {
text?: string
isRunning?: boolean
onStopRun?: () => void
}
const RunMode = memo(({
text,
isRunning: running,
onStopRun,
}: RunModeProps) => {
const { t } = useTranslation()
const { handleWorkflowStartRunInWorkflow } = useWorkflowStartRun()
const { handleStopRun } = useWorkflowRun()
const workflowRunningData = useStore(s => s.workflowRunningData)
const isRunning = workflowRunningData?.result.status === WorkflowRunningStatus.Running
const mergedRunning = isRunning || running
return (
<>
<div
className={cn(
'flex h-7 items-center rounded-md px-2.5 text-[13px] font-medium text-components-button-secondary-accent-text',
'flex h-7 items-center px-2.5 text-[13px] font-medium text-components-button-secondary-accent-text',
'cursor-pointer hover:bg-state-accent-hover',
isRunning && '!cursor-not-allowed bg-state-accent-hover',
mergedRunning && 'cursor-not-allowed bg-state-accent-hover',
mergedRunning ? 'rounded-l-md' : 'rounded-md',
)}
onClick={() => {
handleWorkflowStartRunInWorkflow()
}}
>
{
isRunning
mergedRunning
? (
<>
<RiLoader2Line className='mr-1 h-4 w-4 animate-spin' />
@ -60,12 +66,14 @@ const RunMode = memo(({
}
</div>
{
isRunning && (
mergedRunning && (
<div
className='ml-0.5 flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-black/5'
onClick={() => handleStopRun(workflowRunningData?.task_id || '')}
className={cn(
'ml-[1px] flex h-7 w-7 cursor-pointer items-center justify-center rounded-r-md bg-state-accent-active',
)}
onClick={() => onStopRun ? onStopRun() : handleStopRun(workflowRunningData?.task_id || '')}
>
<StopCircle className='h-4 w-4 text-components-button-ghost-text' />
<StopCircle className='h-4 w-4 text-text-accent' />
</div>
)
}
@ -94,12 +102,16 @@ const PreviewMode = memo(() => {
export type RunAndHistoryProps = {
showRunButton?: boolean
runButtonText?: string
isRunning?: boolean
onStopRun?: () => void
showPreviewButton?: boolean
viewHistoryProps?: ViewHistoryProps
}
const RunAndHistory = ({
showRunButton,
runButtonText,
isRunning,
onStopRun,
showPreviewButton,
viewHistoryProps,
}: RunAndHistoryProps) => {
@ -108,7 +120,7 @@ const RunAndHistory = ({
return (
<div className='flex h-8 items-center rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-0.5 shadow-xs'>
{
showRunButton && <RunMode text={runButtonText} />
showRunButton && <RunMode text={runButtonText} isRunning={isRunning} onStopRun={onStopRun} />
}
{
showPreviewButton && <PreviewMode />

View File

@ -3,25 +3,37 @@ import {
ParentChildChunk,
QuestionAndAnswer,
} from '@/app/components/base/icons/src/vender/knowledge'
import cn from '@/utils/classnames'
import { ChunkStructureEnum } from '../../types'
import type { Option } from './type'
export const useChunkStructure = () => {
const GeneralOption: Option = {
id: ChunkStructureEnum.general,
icon: <GeneralChunk className='h-[18px] w-[18px] text-util-colors-indigo-indigo-600' />,
icon: (isActive: boolean) => (
<GeneralChunk
className={cn(
'h-[18px] w-[18px] text-text-tertiary group-hover:text-util-colors-indigo-indigo-600',
isActive && 'text-util-colors-indigo-indigo-600',
)} />
),
title: 'General',
description: 'General text chunking mode, the chunks retrieved and recalled are the same.',
effectColor: 'blue',
showEffectColor: true,
}
const ParentChildOption: Option = {
id: ChunkStructureEnum.parent_child,
icon: <ParentChildChunk className='h-[18px] w-[18px] text-util-colors-blue-light-blue-light-500' />,
icon: (isActive: boolean) => (
<ParentChildChunk
className={cn(
'h-[18px] w-[18px] text-text-tertiary group-hover:text-util-colors-blue-light-blue-light-500',
isActive && 'text-util-colors-blue-light-blue-light-500',
)}
/>
),
title: 'Parent-Child',
description: 'Parent-child text chunking mode, the chunks retrieved and recalled are different.',
effectColor: 'blue-light',
showEffectColor: true,
}
const QuestionAnswerOption: Option = {
id: ChunkStructureEnum.question_answer,
@ -39,7 +51,7 @@ export const useChunkStructure = () => {
const options = [
GeneralOption,
ParentChildOption,
QuestionAnswerOption,
// QuestionAnswerOption,
]
return {

View File

@ -35,7 +35,12 @@ const ChunkStructure = ({
),
}}
>
<OptionCard {...optionMap[chunkStructure]} />
<OptionCard
{...optionMap[chunkStructure]}
selectedId={chunkStructure}
enableSelect={false}
enableHighlightBorder={false}
/>
</Field>
)
}

View File

@ -1,4 +1,4 @@
import { useState } from 'react'
import { useCallback, useState } from 'react'
import {
PortalToFollowElem,
PortalToFollowElemContent,
@ -23,6 +23,11 @@ const Selector = ({
}: SelectorProps) => {
const [open, setOpen] = useState(false)
const handleSelect = useCallback((optionId: ChunkStructureEnum) => {
onChange(optionId)
setOpen(false)
}, [onChange])
return (
<PortalToFollowElem
placement='bottom-end'
@ -56,16 +61,13 @@ const Selector = ({
<OptionCard
key={option.id}
id={option.id}
selectedId={value}
icon={option.icon}
title={option.title}
description={option.description}
onClick={() => {
if (readonly)
return
onChange(option.id)
setOpen(false)
}}
showHighlightBorder={value === option.id}
readonly={readonly}
onClick={handleSelect}
effectColor={option.effectColor}
></OptionCard>
))
}

View File

@ -3,9 +3,8 @@ import type { ChunkStructureEnum } from '../../types'
export type Option = {
id: ChunkStructureEnum
icon: ReactNode
icon: ReactNode | ((isActive: boolean) => ReactNode)
title: string
description: string
effectColor?: string
showEffectColor?: boolean,
}

View File

@ -14,9 +14,13 @@ import Input from '@/app/components/base/input'
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
import OptionCard from './option-card'
import cn from '@/utils/classnames'
import { IndexMethodEnum } from '../types'
import {
ChunkStructureEnum,
IndexMethodEnum,
} from '../types'
type IndexMethodProps = {
chunkStructure: ChunkStructureEnum
indexMethod: IndexMethodEnum
onIndexMethodChange: (value: IndexMethodEnum) => void
keywordNumber: number
@ -24,6 +28,7 @@ type IndexMethodProps = {
readonly?: boolean
}
const IndexMethod = ({
chunkStructure,
indexMethod,
onIndexMethodChange,
keywordNumber,
@ -53,65 +58,68 @@ const IndexMethod = ({
<div className='space-y-1'>
<OptionCard<IndexMethodEnum>
id={IndexMethodEnum.QUALIFIED}
selectedId={indexMethod}
icon={
<HighQuality
className={cn(
'h-[15px] w-[15px] text-text-tertiary',
'h-[15px] w-[15px] text-text-tertiary group-hover:text-util-colors-orange-orange-500',
isHighQuality && 'text-util-colors-orange-orange-500',
)}
/>
}
title={t('datasetCreation.stepTwo.qualified')}
description={t('datasetSettings.form.indexMethodHighQualityTip')}
showHighlightBorder={isHighQuality}
onClick={handleIndexMethodChange}
isRecommended
effectColor='orange'
></OptionCard>
<OptionCard
id={IndexMethodEnum.ECONOMICAL}
icon={
<Economic
className={cn(
'h-[15px] w-[15px] text-text-tertiary',
isEconomy && 'text-util-colors-indigo-indigo-500',
)}
/>
}
title={t('datasetSettings.form.indexMethodEconomy')}
description={t('datasetSettings.form.indexMethodEconomyTip')}
showChildren={isEconomy}
showHighlightBorder={isEconomy}
onClick={handleIndexMethodChange}
effectColor='blue'
showEffectColor={isEconomy}
>
<div className='flex items-center'>
<div className='flex grow items-center'>
<div className='system-xs-medium truncate text-text-secondary'>
Number of Keywords
{
chunkStructure !== ChunkStructureEnum.parent_child && (
<OptionCard
id={IndexMethodEnum.ECONOMICAL}
selectedId={indexMethod}
icon={
<Economic
className={cn(
'h-[15px] w-[15px] text-text-tertiary group-hover:text-util-colors-indigo-indigo-500',
isEconomy && 'text-util-colors-indigo-indigo-500',
)}
/>
}
title={t('datasetSettings.form.indexMethodEconomy')}
description={t('datasetSettings.form.indexMethodEconomyTip')}
onClick={handleIndexMethodChange}
effectColor='blue'
>
<div className='flex items-center'>
<div className='flex grow items-center'>
<div className='system-xs-medium truncate text-text-secondary'>
Number of Keywords
</div>
<Tooltip
popupContent='number of keywords'
>
<RiQuestionLine className='ml-0.5 h-3.5 w-3.5 text-text-quaternary' />
</Tooltip>
</div>
<Slider
disabled={readonly}
className='mr-3 w-24 shrink-0'
value={keywordNumber}
onChange={onKeywordNumberChange}
/>
<Input
disabled={readonly}
className='shrink-0'
wrapperClassName='shrink-0 w-[72px]'
type='number'
value={keywordNumber}
onChange={handleInputChange}
/>
</div>
<Tooltip
popupContent='number of keywords'
>
<RiQuestionLine className='ml-0.5 h-3.5 w-3.5 text-text-quaternary' />
</Tooltip>
</div>
<Slider
disabled={readonly}
className='mr-3 w-24 shrink-0'
value={keywordNumber}
onChange={onKeywordNumberChange}
/>
<Input
disabled={readonly}
className='shrink-0'
wrapperClassName='shrink-0 w-[72px]'
type='number'
value={keywordNumber}
onChange={handleInputChange}
/>
</div>
</OptionCard>
</OptionCard>
)
}
</div>
</Field>
)

View File

@ -1,5 +1,8 @@
import type { ReactNode } from 'react'
import { memo } from 'react'
import {
memo,
useMemo,
} from 'react'
import cn from '@/utils/classnames'
import Badge from '@/app/components/base/badge'
import {
@ -17,63 +20,79 @@ const HEADER_EFFECT_MAP: Record<string, ReactNode> = {
'purple': <OptionCardEffectPurple />,
}
type OptionCardProps<T> = {
id: T
className?: string
showHighlightBorder?: boolean
showRadio?: boolean
radioIsActive?: boolean
icon?: ReactNode
id?: T
selectedId?: T
enableSelect?: boolean
enableHighlightBorder?: boolean
enableRadio?: boolean
wrapperClassName?: string | ((isActive: boolean) => string)
className?: string | ((isActive: boolean) => string)
icon?: ReactNode | ((isActive: boolean) => ReactNode)
title: string
description?: string
isRecommended?: boolean
children?: ReactNode
showChildren?: boolean
effectColor?: string
showEffectColor?: boolean
onClick?: (id: T) => void
readonly?: boolean
}
const OptionCard = memo(({
id,
selectedId,
enableSelect = true,
enableHighlightBorder = true,
enableRadio,
wrapperClassName,
className,
showHighlightBorder,
showRadio,
radioIsActive,
icon,
title,
description,
isRecommended,
children,
showChildren,
effectColor,
showEffectColor,
onClick,
readonly,
}) => {
const isActive = useMemo(() => {
return id === selectedId
}, [id, selectedId])
const effectElement = useMemo(() => {
if (effectColor) {
return (
<div className={cn(
'absolute left-[-2px] top-[-2px] hidden h-14 w-14 rounded-full',
'group-hover:block',
isActive && 'block',
)}>
{HEADER_EFFECT_MAP[effectColor]}
</div>
)
}
return null
}, [effectColor, isActive])
return (
<div
className={cn(
'cursor-pointer rounded-xl border border-components-option-card-option-border bg-components-option-card-option-bg',
showHighlightBorder && 'border-[2px] border-components-option-card-option-selected-border',
'group overflow-hidden rounded-xl border border-components-option-card-option-border bg-components-option-card-option-bg',
isActive && enableHighlightBorder && 'border-[1.5px] border-components-option-card-option-selected-border',
enableSelect && 'cursor-pointer hover:shadow-xs',
readonly && 'cursor-not-allowed',
wrapperClassName && (typeof wrapperClassName === 'function' ? wrapperClassName(isActive) : wrapperClassName),
)}
onClick={() => !readonly && onClick?.(id)}
onClick={() => !readonly && enableSelect && id && onClick?.(id)}
>
<div className={cn(
'relative flex rounded-t-xl p-2',
className,
className && (typeof className === 'function' ? className(isActive) : className),
)}>
{
effectColor && showEffectColor && (
<div className='absolute left-[-2px] top-[-2px] h-14 w-14 rounded-full'>
{HEADER_EFFECT_MAP[effectColor]}
</div>
)
}
{effectElement}
{
icon && (
<div className='mr-1 flex h-[18px] w-[18px] shrink-0 items-center justify-center'>
{icon}
{typeof icon === 'function' ? icon(isActive) : icon}
</div>
)
}
@ -90,10 +109,10 @@ const OptionCard = memo(({
}
</div>
{
showRadio && (
enableRadio && (
<div className={cn(
'ml-2 h-4 w-4 shrink-0 rounded-full border border-components-radio-border bg-components-radio-bg',
radioIsActive && 'border-[5px] border-components-radio-border-checked',
isActive && 'border-[5px] border-components-radio-border-checked',
)}>
</div>
)
@ -109,7 +128,7 @@ const OptionCard = memo(({
</div>
</div>
{
children && showChildren && (
children && isActive && (
<div className='relative rounded-b-xl bg-components-panel-bg p-3'>
<ArrowShape className='absolute left-[14px] top-[-11px] h-4 w-4 text-components-panel-bg' />
{children}

View File

@ -6,6 +6,7 @@ import {
} from '@/app/components/base/icons/src/vender/knowledge'
import {
HybridSearchModeEnum,
IndexMethodEnum,
RetrievalSearchMethodEnum,
} from '../../types'
import type {
@ -13,7 +14,7 @@ import type {
Option,
} from './type'
export const useRetrievalSetting = () => {
export const useRetrievalSetting = (indexMethod: IndexMethodEnum) => {
const VectorSearchOption: Option = useMemo(() => {
return {
id: RetrievalSearchMethodEnum.semantic,
@ -41,6 +42,15 @@ export const useRetrievalSetting = () => {
effectColor: 'purple',
}
}, [])
const InvertedIndexOption: Option = useMemo(() => {
return {
id: RetrievalSearchMethodEnum.invertedIndex,
icon: HybridSearch as any,
title: 'Inverted Index',
description: 'Use inverted index to search for the most relevant text chunks.',
effectColor: 'purple',
}
}, [])
const WeightedScoreModeOption: HybridSearchModeOption = useMemo(() => {
return {
@ -58,7 +68,9 @@ export const useRetrievalSetting = () => {
}, [])
return useMemo(() => ({
options: [
options: indexMethod === IndexMethodEnum.ECONOMICAL ? [
InvertedIndexOption,
] : [
VectorSearchOption,
FullTextSearchOption,
HybridSearchOption,
@ -71,6 +83,8 @@ export const useRetrievalSetting = () => {
VectorSearchOption,
FullTextSearchOption,
HybridSearchOption,
InvertedIndexOption,
indexMethod,
WeightedScoreModeOption,
RerankModelModeOption,
])

View File

@ -7,6 +7,7 @@ import type {
RetrievalSearchMethodEnum,
} from '../../types'
import type {
IndexMethodEnum,
WeightedScore,
} from '../../types'
import { useRetrievalSetting } from './hooks'
@ -15,6 +16,7 @@ import type { RerankingModelSelectorProps } from './reranking-model-selector'
import SearchMethodOption from './search-method-option'
type RetrievalSettingProps = {
indexMethod: IndexMethodEnum
readonly?: boolean
searchMethod: RetrievalSearchMethodEnum
onRetrievalSearchMethodChange: (value: RetrievalSearchMethodEnum) => void
@ -25,6 +27,7 @@ type RetrievalSettingProps = {
} & RerankingModelSelectorProps & TopKAndScoreThresholdProps
const RetrievalSetting = ({
indexMethod,
readonly,
searchMethod,
onRetrievalSearchMethodChange,
@ -44,7 +47,7 @@ const RetrievalSetting = ({
const {
options,
hybridSearchModeOptions,
} = useRetrievalSetting()
} = useRetrievalSetting(indexMethod)
return (
<Field

View File

@ -1,5 +1,6 @@
import {
memo,
useCallback,
useMemo,
} from 'react'
import cn from '@/utils/classnames'
@ -53,7 +54,6 @@ const SearchMethodOption = ({
onScoreThresholdEnabledChange,
}: SearchMethodOptionProps) => {
const Icon = option.icon
const isActive = searchMethod === option.id
const isHybridSearch = option.id === RetrievalSearchMethodEnum.hybrid
const isHybridSearchWeightedScoreMode = hybridSearchMode === HybridSearchModeEnum.WeightedScore
@ -67,30 +67,32 @@ const SearchMethodOption = ({
}
}, [weightedScore])
const icon = useMemo(() => {
const icon = useCallback((isActive: boolean) => {
return (
<Icon
className={cn(
'h-[15px] w-[15px] text-text-tertiary',
'h-[15px] w-[15px] text-text-tertiary group-hover:text-util-colors-purple-purple-600',
isActive && 'text-util-colors-purple-purple-600',
)}
/>
)
}, [isActive, Icon])
}, [Icon])
const hybridSearchModeWrapperClassName = useCallback((isActive: boolean) => {
return isActive ? 'border-[1.5px] bg-components-option-card-option-selected-bg' : ''
}, [])
return (
<OptionCard
key={option.id}
id={option.id}
selectedId={searchMethod}
icon={icon}
title={option.title}
description={option.description}
effectColor={option.effectColor}
isRecommended={option.id === RetrievalSearchMethodEnum.hybrid}
onClick={onRetrievalSearchMethodChange}
showChildren={isActive}
showHighlightBorder={isActive}
showEffectColor={isActive}
readonly={readonly}
>
<div className='space-y-3'>
@ -102,11 +104,13 @@ const SearchMethodOption = ({
<OptionCard
key={hybridOption.id}
id={hybridOption.id}
selectedId={hybridSearchMode}
enableHighlightBorder={false}
enableRadio
wrapperClassName={hybridSearchModeWrapperClassName}
className='p-3'
title={hybridOption.title}
description={hybridOption.description}
showRadio
radioIsActive={hybridOption.id === hybridSearchMode}
onClick={onHybridSearchModeChange}
readonly={readonly}
/>

View File

@ -4,10 +4,12 @@ import {
import { useStoreApi } from 'reactflow'
import { useNodeDataUpdate } from '@/app/components/workflow/hooks'
import type { ValueSelector } from '@/app/components/workflow/types'
import type {
import {
ChunkStructureEnum,
HybridSearchModeEnum,
IndexMethodEnum,
} from '../types'
import type {
HybridSearchModeEnum,
KnowledgeBaseNodeType,
RerankingModel,
RetrievalSearchMethodEnum,
@ -32,8 +34,13 @@ export const useConfig = (id: string) => {
}, [id, handleNodeDataUpdateWithSyncDraft])
const handleChunkStructureChange = useCallback((chunkStructure: ChunkStructureEnum) => {
handleNodeDataUpdate({ chunk_structure: chunkStructure })
}, [handleNodeDataUpdate])
const nodeData = getNodeData()
const { indexing_technique } = nodeData?.data
handleNodeDataUpdate({
chunk_structure: chunkStructure,
indexing_technique: chunkStructure === ChunkStructureEnum.parent_child ? IndexMethodEnum.QUALIFIED : indexing_technique,
})
}, [handleNodeDataUpdate, getNodeData])
const handleIndexMethodChange = useCallback((indexMethod: IndexMethodEnum) => {
handleNodeDataUpdate({ indexing_technique: indexMethod })

View File

@ -63,6 +63,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
<GroupWithBox>
<div className='space-y-3'>
<IndexMethod
chunkStructure={data.chunk_structure}
indexMethod={data.indexing_technique}
onIndexMethodChange={handleIndexMethodChange}
keywordNumber={data.keyword_number}
@ -83,6 +84,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
<Split className='h-[1px]' />
</div>
<RetrievalSetting
indexMethod={data.indexing_technique}
searchMethod={data.retrieval_model.search_method}
onRetrievalSearchMethodChange={handleRetrievalSearchMethodChange}
hybridSearchMode={data.retrieval_model.hybridSearchMode}