mirror of
https://github.com/langgenius/dify.git
synced 2025-11-03 12:23:07 +00:00
Merge branch 'feat/rag-pipeline' of https://github.com/langgenius/dify into feat/rag-pipeline
This commit is contained in:
commit
df928772c0
@ -21,10 +21,12 @@ type Value = {
|
||||
type WeightedScoreProps = {
|
||||
value: Value
|
||||
onChange: (value: Value) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const WeightedScore = ({
|
||||
value,
|
||||
onChange = noop,
|
||||
readonly = false,
|
||||
}: WeightedScoreProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -37,7 +39,7 @@ const WeightedScore = ({
|
||||
min={0}
|
||||
step={0.1}
|
||||
value={value.value[0]}
|
||||
onChange={v => onChange({ value: [v, (10 - v * 10) / 10] })}
|
||||
onChange={v => !readonly && onChange({ value: [v, (10 - v * 10) / 10] })}
|
||||
trackClassName='weightedScoreSliderTrack'
|
||||
/>
|
||||
<div className='mt-3 flex justify-between'>
|
||||
|
||||
@ -18,3 +18,4 @@ export * from './use-format-time-from-now'
|
||||
export * from './use-nodes-meta-data'
|
||||
export * from './use-available-blocks'
|
||||
export * from './use-workflow-refresh-draft'
|
||||
export * from './use-tool-icon'
|
||||
|
||||
34
web/app/components/workflow/hooks/use-tool-icon.ts
Normal file
34
web/app/components/workflow/hooks/use-tool-icon.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import {
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import type {
|
||||
Node,
|
||||
} from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '../types'
|
||||
import {
|
||||
useStore,
|
||||
} from '../store'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { canFindTool } from '@/utils'
|
||||
|
||||
export const useToolIcon = (data: Node['data']) => {
|
||||
const buildInTools = useStore(s => s.buildInTools)
|
||||
const customTools = useStore(s => s.customTools)
|
||||
const workflowTools = useStore(s => s.workflowTools)
|
||||
const toolIcon = useMemo(() => {
|
||||
if (data.type === BlockEnum.Tool) {
|
||||
let targetTools = buildInTools
|
||||
if (data.provider_type === CollectionType.builtIn)
|
||||
targetTools = buildInTools
|
||||
else if (data.provider_type === CollectionType.custom)
|
||||
targetTools = customTools
|
||||
else
|
||||
targetTools = workflowTools
|
||||
return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon
|
||||
}
|
||||
}, [data, buildInTools, customTools, workflowTools])
|
||||
|
||||
return toolIcon
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
import {
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -39,11 +38,9 @@ import {
|
||||
fetchAllCustomTools,
|
||||
fetchAllWorkflowTools,
|
||||
} from '@/service/tools'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
|
||||
import { CUSTOM_LOOP_START_NODE } from '@/app/components/workflow/nodes/loop-start/constants'
|
||||
import { basePath } from '@/utils/var'
|
||||
import { canFindTool } from '@/utils'
|
||||
|
||||
export const useIsChatMode = () => {
|
||||
const appDetail = useAppStore(s => s.appDetail)
|
||||
@ -489,26 +486,6 @@ export const useNodesReadOnly = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const useToolIcon = (data: Node['data']) => {
|
||||
const buildInTools = useStore(s => s.buildInTools)
|
||||
const customTools = useStore(s => s.customTools)
|
||||
const workflowTools = useStore(s => s.workflowTools)
|
||||
const toolIcon = useMemo(() => {
|
||||
if (data.type === BlockEnum.Tool) {
|
||||
let targetTools = buildInTools
|
||||
if (data.provider_type === CollectionType.builtIn)
|
||||
targetTools = buildInTools
|
||||
else if (data.provider_type === CollectionType.custom)
|
||||
targetTools = customTools
|
||||
else
|
||||
targetTools = workflowTools
|
||||
return targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.icon
|
||||
}
|
||||
}, [data, buildInTools, customTools, workflowTools])
|
||||
|
||||
return toolIcon
|
||||
}
|
||||
|
||||
export const useIsNodeInIteration = (iterationId: string) => {
|
||||
const store = useStoreApi()
|
||||
|
||||
|
||||
@ -8,10 +8,12 @@ import { useChunkStructure } from './hooks'
|
||||
type ChunkStructureProps = {
|
||||
chunkStructure: ChunkStructureEnum
|
||||
onChunkStructureChange: (value: ChunkStructureEnum) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const ChunkStructure = ({
|
||||
chunkStructure,
|
||||
onChunkStructureChange,
|
||||
readonly = false,
|
||||
}: ChunkStructureProps) => {
|
||||
const {
|
||||
options,
|
||||
@ -28,6 +30,7 @@ const ChunkStructure = ({
|
||||
options={options}
|
||||
value={chunkStructure}
|
||||
onChange={onChunkStructureChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
|
||||
@ -13,11 +13,13 @@ type SelectorProps = {
|
||||
options: Option[]
|
||||
value: ChunkStructureEnum
|
||||
onChange: (key: ChunkStructureEnum) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const Selector = ({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
readonly,
|
||||
}: SelectorProps) => {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
@ -31,7 +33,11 @@ const Selector = ({
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={() => setOpen(!open)}>
|
||||
<PortalToFollowElemTrigger onClick={() => {
|
||||
if (readonly)
|
||||
return
|
||||
setOpen(!open)
|
||||
}}>
|
||||
<Button
|
||||
size='small'
|
||||
variant='ghost-accent'
|
||||
@ -54,6 +60,8 @@ const Selector = ({
|
||||
title={option.title}
|
||||
description={option.description}
|
||||
onClick={() => {
|
||||
if (readonly)
|
||||
return
|
||||
onChange(option.id)
|
||||
setOpen(false)
|
||||
}}
|
||||
|
||||
@ -15,11 +15,13 @@ type EmbeddingModelProps = {
|
||||
embeddingModel: string
|
||||
embeddingModelProvider: string
|
||||
}) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const EmbeddingModel = ({
|
||||
embeddingModel,
|
||||
embeddingModelProvider,
|
||||
onEmbeddingModelChange,
|
||||
readonly = false,
|
||||
}: EmbeddingModelProps) => {
|
||||
const {
|
||||
modelList: embeddingModelList,
|
||||
@ -51,6 +53,7 @@ const handleRerankingModelChange = (model: DefaultModel) => {
|
||||
defaultModel={embeddingModelConfig && { provider: embeddingModelConfig.providerName, model: embeddingModelConfig.modelName }}
|
||||
modelList={embeddingModelList}
|
||||
onSelect={handleRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
</Field>
|
||||
)
|
||||
|
||||
@ -21,12 +21,14 @@ type IndexMethodProps = {
|
||||
onIndexMethodChange: (value: IndexMethodEnum) => void
|
||||
keywordNumber: number
|
||||
onKeywordNumberChange: (value: number) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const IndexMethod = ({
|
||||
indexMethod,
|
||||
onIndexMethodChange,
|
||||
keywordNumber,
|
||||
onKeywordNumberChange,
|
||||
readonly = false,
|
||||
}: IndexMethodProps) => {
|
||||
const { t } = useTranslation()
|
||||
const isHighQuality = indexMethod === IndexMethodEnum.QUALIFIED
|
||||
@ -95,11 +97,13 @@ const IndexMethod = ({
|
||||
</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'
|
||||
|
||||
@ -7,11 +7,13 @@ type InputVariableProps = {
|
||||
nodeId: string
|
||||
inputVariable?: string[]
|
||||
onInputVariableChange: (inputVariable: string | ValueSelector) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const InputVariable = ({
|
||||
nodeId,
|
||||
inputVariable = [],
|
||||
onInputVariableChange,
|
||||
readonly = false,
|
||||
}: InputVariableProps) => {
|
||||
return (
|
||||
<Field
|
||||
@ -25,7 +27,7 @@ const InputVariable = ({
|
||||
isShowNodeName
|
||||
value={inputVariable}
|
||||
onChange={onInputVariableChange}
|
||||
readonly={false}
|
||||
readonly={readonly}
|
||||
/>
|
||||
</Field>
|
||||
)
|
||||
|
||||
@ -31,6 +31,7 @@ type OptionCardProps<T> = {
|
||||
effectColor?: string
|
||||
showEffectColor?: boolean
|
||||
onClick?: (id: T) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const OptionCard = memo(({
|
||||
id,
|
||||
@ -47,14 +48,16 @@ const OptionCard = memo(({
|
||||
effectColor,
|
||||
showEffectColor,
|
||||
onClick,
|
||||
readonly,
|
||||
}) => {
|
||||
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',
|
||||
readonly && 'cursor-not-allowed',
|
||||
)}
|
||||
onClick={() => onClick?.(id)}
|
||||
onClick={() => !readonly && onClick?.(id)}
|
||||
>
|
||||
<div className={cn(
|
||||
'relative flex rounded-t-xl p-2',
|
||||
|
||||
@ -15,6 +15,7 @@ import type { RerankingModelSelectorProps } from './reranking-model-selector'
|
||||
import SearchMethodOption from './search-method-option'
|
||||
|
||||
type RetrievalSettingProps = {
|
||||
readonly?: boolean
|
||||
searchMethod: RetrievalSearchMethodEnum
|
||||
onRetrievalSearchMethodChange: (value: RetrievalSearchMethodEnum) => void
|
||||
hybridSearchMode: HybridSearchModeEnum
|
||||
@ -24,6 +25,7 @@ type RetrievalSettingProps = {
|
||||
} & RerankingModelSelectorProps & TopKAndScoreThresholdProps
|
||||
|
||||
const RetrievalSetting = ({
|
||||
readonly,
|
||||
searchMethod,
|
||||
onRetrievalSearchMethodChange,
|
||||
hybridSearchMode,
|
||||
@ -84,6 +86,7 @@ const RetrievalSetting = ({
|
||||
onScoreThresholdEnabledChange={onScoreThresholdEnabledChange}
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@ -11,10 +11,12 @@ import type { RerankingModel } from '../../types'
|
||||
export type RerankingModelSelectorProps = {
|
||||
rerankingModel?: RerankingModel
|
||||
onRerankingModelChange?: (model: RerankingModel) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const RerankingModelSelector = ({
|
||||
rerankingModel,
|
||||
onRerankingModelChange,
|
||||
readonly = false,
|
||||
}: RerankingModelSelectorProps) => {
|
||||
const {
|
||||
modelList: rerankModelList,
|
||||
@ -41,6 +43,7 @@ const RerankingModelSelector = ({
|
||||
defaultModel={rerankModel && { provider: rerankModel.providerName, model: rerankModel.modelName }}
|
||||
modelList={rerankModelList}
|
||||
onSelect={handleRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import type { RerankingModelSelectorProps } from './reranking-model-selector'
|
||||
import RerankingModelSelector from './reranking-model-selector'
|
||||
|
||||
type SearchMethodOptionProps = {
|
||||
readonly?: boolean
|
||||
option: Option
|
||||
hybridSearchModeOptions: HybridSearchModeOption[]
|
||||
searchMethod: RetrievalSearchMethodEnum
|
||||
@ -33,6 +34,7 @@ type SearchMethodOptionProps = {
|
||||
onWeightedScoreChange: (value: { value: number[] }) => void
|
||||
} & RerankingModelSelectorProps & TopKAndScoreThresholdProps
|
||||
const SearchMethodOption = ({
|
||||
readonly,
|
||||
option,
|
||||
hybridSearchModeOptions,
|
||||
searchMethod,
|
||||
@ -89,6 +91,7 @@ const SearchMethodOption = ({
|
||||
showChildren={isActive}
|
||||
showHighlightBorder={isActive}
|
||||
showEffectColor={isActive}
|
||||
readonly={readonly}
|
||||
>
|
||||
<div className='space-y-3'>
|
||||
{
|
||||
@ -105,6 +108,7 @@ const SearchMethodOption = ({
|
||||
showRadio
|
||||
radioIsActive={hybridOption.id === hybridSearchMode}
|
||||
onClick={onHybridSearchModeChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
))
|
||||
}
|
||||
@ -116,6 +120,7 @@ const SearchMethodOption = ({
|
||||
<WeightedScoreComponent
|
||||
value={weightedScoreValue}
|
||||
onChange={onWeightedScoreChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -124,6 +129,7 @@ const SearchMethodOption = ({
|
||||
<RerankingModelSelector
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -134,6 +140,7 @@ const SearchMethodOption = ({
|
||||
onScoreThresholdChange={onScoreThresholdChange}
|
||||
isScoreThresholdEnabled={isScoreThresholdEnabled}
|
||||
onScoreThresholdEnabledChange={onScoreThresholdEnabledChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
</div>
|
||||
</OptionCard>
|
||||
|
||||
@ -10,6 +10,7 @@ export type TopKAndScoreThresholdProps = {
|
||||
onScoreThresholdChange?: (value: number) => void
|
||||
isScoreThresholdEnabled?: boolean
|
||||
onScoreThresholdEnabledChange?: (value: boolean) => void
|
||||
readonly?: boolean
|
||||
}
|
||||
const TopKAndScoreThreshold = ({
|
||||
topK,
|
||||
@ -18,6 +19,7 @@ const TopKAndScoreThreshold = ({
|
||||
onScoreThresholdChange,
|
||||
isScoreThresholdEnabled,
|
||||
onScoreThresholdEnabledChange,
|
||||
readonly,
|
||||
}: TopKAndScoreThresholdProps) => {
|
||||
const handleTopKChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = Number(e.target.value)
|
||||
@ -47,6 +49,7 @@ const TopKAndScoreThreshold = ({
|
||||
type='number'
|
||||
value={topK}
|
||||
onChange={handleTopKChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -55,6 +58,7 @@ const TopKAndScoreThreshold = ({
|
||||
className='mr-2'
|
||||
defaultValue={isScoreThresholdEnabled}
|
||||
onChange={onScoreThresholdEnabledChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
<div className='system-sm-medium grow truncate text-text-secondary'>
|
||||
Score Threshold
|
||||
@ -68,6 +72,7 @@ const TopKAndScoreThreshold = ({
|
||||
type='number'
|
||||
value={scoreThreshold}
|
||||
onChange={handleScoreThresholdChange}
|
||||
disabled={readonly}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,11 +18,13 @@ import {
|
||||
GroupWithBox,
|
||||
} from '@/app/components/workflow/nodes/_base/components/layout'
|
||||
import Split from '../_base/components/split'
|
||||
import { useNodesReadOnly } from '@/app/components/workflow/hooks'
|
||||
|
||||
const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
id,
|
||||
data,
|
||||
}) => {
|
||||
const { nodesReadOnly } = useNodesReadOnly()
|
||||
const {
|
||||
handleChunkStructureChange,
|
||||
handleIndexMethodChange,
|
||||
@ -45,6 +47,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
nodeId={id}
|
||||
inputVariable={data.index_chunk_variable_selector}
|
||||
onInputVariableChange={handleInputVariableChange}
|
||||
readonly={nodesReadOnly}
|
||||
/>
|
||||
</GroupWithBox>
|
||||
<Group
|
||||
@ -54,6 +57,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
<ChunkStructure
|
||||
chunkStructure={data.chunk_structure}
|
||||
onChunkStructureChange={handleChunkStructureChange}
|
||||
readonly={nodesReadOnly}
|
||||
/>
|
||||
</Group>
|
||||
<GroupWithBox>
|
||||
@ -63,6 +67,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
onIndexMethodChange={handleIndexMethodChange}
|
||||
keywordNumber={data.keyword_number}
|
||||
onKeywordNumberChange={handleKeywordNumberChange}
|
||||
readonly={nodesReadOnly}
|
||||
/>
|
||||
{
|
||||
data.indexing_technique === IndexMethodEnum.QUALIFIED && (
|
||||
@ -70,6 +75,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
embeddingModel={data.embedding_model}
|
||||
embeddingModelProvider={data.embedding_model_provider}
|
||||
onEmbeddingModelChange={handleEmbeddingModelChange}
|
||||
readonly={nodesReadOnly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -91,6 +97,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
||||
onScoreThresholdChange={handleScoreThresholdChange}
|
||||
isScoreThresholdEnabled={data.retrieval_model.score_threshold_enabled}
|
||||
onScoreThresholdEnabledChange={handleScoreThresholdEnabledChange}
|
||||
readonly={nodesReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</GroupWithBox>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user