diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx
index 02479e2198..d614ac8173 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx
@@ -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 (
diff --git a/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts b/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
index 798bda4dda..eb2a862be6 100644
--- a/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
@@ -93,8 +93,8 @@ export const useNodesSyncDraft = () => {
) => {
if (getNodesReadOnly())
return
- const postParams = getPostParams()
+ const postParams = getPostParams()
if (postParams) {
const {
setSyncWorkflowDraftHash,
diff --git a/web/app/components/rag-pipeline/hooks/use-pipeline-start-run.tsx b/web/app/components/rag-pipeline/hooks/use-pipeline-start-run.tsx
index ea1add4233..38538109e4 100644
--- a/web/app/components/rag-pipeline/hooks/use-pipeline-start-run.tsx
+++ b/web/app/components/rag-pipeline/hooks/use-pipeline-start-run.tsx
@@ -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()
diff --git a/web/app/components/workflow/header/run-and-history.tsx b/web/app/components/workflow/header/run-and-history.tsx
index cf894052e7..54704cbb30 100644
--- a/web/app/components/workflow/header/run-and-history.tsx
+++ b/web/app/components/workflow/header/run-and-history.tsx
@@ -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 (
<>
{
handleWorkflowStartRunInWorkflow()
}}
>
{
- isRunning
+ mergedRunning
? (
<>
@@ -60,12 +66,14 @@ const RunMode = memo(({
}
{
- isRunning && (
+ mergedRunning && (
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 || '')}
>
-
+
)
}
@@ -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 (
{
- showRunButton &&
+ showRunButton &&
}
{
showPreviewButton &&
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/hooks.tsx b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/hooks.tsx
index 2b9c1e7fd5..3c5189b49f 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/hooks.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/hooks.tsx
@@ -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:
,
+ icon: (isActive: boolean) => (
+
+ ),
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:
,
+ icon: (isActive: boolean) => (
+
+ ),
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 {
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/index.tsx b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/index.tsx
index 6e4555d56a..b4e2e59ede 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/index.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/index.tsx
@@ -35,7 +35,12 @@ const ChunkStructure = ({
),
}}
>
-
+
)
}
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/selector.tsx b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/selector.tsx
index 99dc49f6e3..99c4ca5e33 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/selector.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/selector.tsx
@@ -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 (
{
- if (readonly)
- return
- onChange(option.id)
- setOpen(false)
- }}
- showHighlightBorder={value === option.id}
+ readonly={readonly}
+ onClick={handleSelect}
+ effectColor={option.effectColor}
>
))
}
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/type.ts b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/type.ts
index c8a6f8f821..94afc22dc9 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/type.ts
+++ b/web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/type.ts
@@ -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,
}
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
index d0783168f0..1be9cb87b7 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
@@ -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 = ({
id={IndexMethodEnum.QUALIFIED}
+ selectedId={indexMethod}
icon={
}
title={t('datasetCreation.stepTwo.qualified')}
description={t('datasetSettings.form.indexMethodHighQualityTip')}
- showHighlightBorder={isHighQuality}
onClick={handleIndexMethodChange}
isRecommended
+ effectColor='orange'
>
-
- }
- title={t('datasetSettings.form.indexMethodEconomy')}
- description={t('datasetSettings.form.indexMethodEconomyTip')}
- showChildren={isEconomy}
- showHighlightBorder={isEconomy}
- onClick={handleIndexMethodChange}
- effectColor='blue'
- showEffectColor={isEconomy}
- >
-
-
-
- Number of Keywords
+ {
+ chunkStructure !== ChunkStructureEnum.parent_child && (
+
+ }
+ title={t('datasetSettings.form.indexMethodEconomy')}
+ description={t('datasetSettings.form.indexMethodEconomyTip')}
+ onClick={handleIndexMethodChange}
+ effectColor='blue'
+ >
+
+
+
+ Number of Keywords
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+ )
+ }
)
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx b/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
index 7ba7a28154..59e3e5cee2 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
@@ -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
= {
'purple': ,
}
type OptionCardProps = {
- 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 (
+
+ {HEADER_EFFECT_MAP[effectColor]}
+
+ )
+ }
+
+ return null
+ }, [effectColor, isActive])
+
return (
!readonly && onClick?.(id)}
+ onClick={() => !readonly && enableSelect && id && onClick?.(id)}
>
- {
- effectColor && showEffectColor && (
-
- {HEADER_EFFECT_MAP[effectColor]}
-
- )
- }
+ {effectElement}
{
icon && (
- {icon}
+ {typeof icon === 'function' ? icon(isActive) : icon}
)
}
@@ -90,10 +109,10 @@ const OptionCard = memo(({
}
{
- showRadio && (
+ enableRadio && (
)
@@ -109,7 +128,7 @@ const OptionCard = memo(({
{
- children && showChildren && (
+ children && isActive && (
{children}
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx
index c426313605..53d16be61a 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx
@@ -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,
])
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/index.tsx b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/index.tsx
index 40808a3b99..8bc82509c1 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/index.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/index.tsx
@@ -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 (
{
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 (
)
- }, [isActive, Icon])
+ }, [Icon])
+
+ const hybridSearchModeWrapperClassName = useCallback((isActive: boolean) => {
+ return isActive ? 'border-[1.5px] bg-components-option-card-option-selected-bg' : ''
+ }, [])
return (
@@ -102,11 +104,13 @@ const SearchMethodOption = ({
diff --git a/web/app/components/workflow/nodes/knowledge-base/hooks/use-config.ts b/web/app/components/workflow/nodes/knowledge-base/hooks/use-config.ts
index 55cf8e0cb9..670bde7418 100644
--- a/web/app/components/workflow/nodes/knowledge-base/hooks/use-config.ts
+++ b/web/app/components/workflow/nodes/knowledge-base/hooks/use-config.ts
@@ -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 })
diff --git a/web/app/components/workflow/nodes/knowledge-base/panel.tsx b/web/app/components/workflow/nodes/knowledge-base/panel.tsx
index a0d24d713a..e47f6d3ebb 100644
--- a/web/app/components/workflow/nodes/knowledge-base/panel.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/panel.tsx
@@ -63,6 +63,7 @@ const Panel: FC
> = ({
> = ({