mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 01:48:04 +08:00
Merge branch 'feat/queue-based-graph-engine' into feat/rag-2
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||
import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStickyScroll, { ScrollPosition } from '../use-sticky-scroll'
|
||||
import Item from './item'
|
||||
@ -17,18 +17,20 @@ export type ListProps = {
|
||||
tags: string[]
|
||||
toolContentClassName?: string
|
||||
disableMaxWidth?: boolean
|
||||
ref?: React.Ref<ListRef>
|
||||
}
|
||||
|
||||
export type ListRef = { handleScroll: () => void }
|
||||
|
||||
const List = forwardRef<ListRef, ListProps>(({
|
||||
const List = ({
|
||||
wrapElemRef,
|
||||
searchText,
|
||||
tags,
|
||||
list,
|
||||
toolContentClassName,
|
||||
disableMaxWidth = false,
|
||||
}, ref) => {
|
||||
ref,
|
||||
}: ListProps) => {
|
||||
const { t } = useTranslation()
|
||||
const noFilter = !searchText && tags.length === 0
|
||||
const hasRes = list.length > 0
|
||||
@ -125,7 +127,7 @@ const List = forwardRef<ListRef, ListProps>(({
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
List.displayName = 'List'
|
||||
|
||||
|
||||
@ -77,6 +77,10 @@ export const LLM_OUTPUT_STRUCT: Var[] = [
|
||||
variable: 'text',
|
||||
type: VarType.string,
|
||||
},
|
||||
{
|
||||
variable: 'reasoning_content',
|
||||
type: VarType.string,
|
||||
},
|
||||
{
|
||||
variable: 'usage',
|
||||
type: VarType.object,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useMemo } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -13,7 +13,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: AgentNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types'
|
||||
import { useMemo } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -9,7 +9,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: AssignerNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -8,7 +8,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: CodeNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import type { DocExtractorNodeType } from './types'
|
||||
@ -11,7 +11,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: DocExtractorNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -8,7 +8,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: HttpNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback } from 'react'
|
||||
import type { CaseItem, Condition, IfElseNodeType } from './types'
|
||||
@ -7,7 +7,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: IfElseNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import type { IterationNodeType } from './types'
|
||||
@ -16,7 +16,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: IterationNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
@ -11,7 +11,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: KnowledgeRetrievalNodeType
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
|
||||
type ReasoningFormatConfigProps = {
|
||||
value?: 'tagged' | 'separated'
|
||||
onChange: (value: 'tagged' | 'separated') => void
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
const ReasoningFormatConfig: FC<ReasoningFormatConfigProps> = ({
|
||||
value = 'tagged',
|
||||
onChange,
|
||||
readonly = false,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Field
|
||||
title={t('workflow.nodes.llm.reasoningFormat.title')}
|
||||
tooltip={t('workflow.nodes.llm.reasoningFormat.tooltip')}
|
||||
operations={
|
||||
// ON = separated, OFF = tagged
|
||||
<Switch
|
||||
defaultValue={value === 'separated'}
|
||||
onChange={enabled => onChange(enabled ? 'separated' : 'tagged')}
|
||||
size='md'
|
||||
disabled={readonly}
|
||||
key={value}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div />
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReasoningFormatConfig
|
||||
@ -17,6 +17,7 @@ import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import StructureOutput from './components/structure-output'
|
||||
import ReasoningFormatConfig from './components/reasoning-format-config'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import { RiAlertFill, RiQuestionLine } from '@remixicon/react'
|
||||
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
|
||||
@ -61,6 +62,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
handleStructureOutputEnableChange,
|
||||
handleStructureOutputChange,
|
||||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
} = useConfig(id, data)
|
||||
|
||||
const model = inputs.model
|
||||
@ -239,6 +241,14 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
config={inputs.vision?.configs}
|
||||
onConfigChange={handleVisionResolutionChange}
|
||||
/>
|
||||
|
||||
{/* Reasoning Format */}
|
||||
<ReasoningFormatConfig
|
||||
// Default to tagged for backward compatibility
|
||||
value={inputs.reasoning_format || 'tagged'}
|
||||
onChange={handleReasoningFormatChange}
|
||||
readonly={readOnly}
|
||||
/>
|
||||
</div>
|
||||
<Split />
|
||||
<OutputVars
|
||||
|
||||
@ -17,6 +17,7 @@ export type LLMNodeType = CommonNodeType & {
|
||||
}
|
||||
structured_output_enabled?: boolean
|
||||
structured_output?: StructuredOutput
|
||||
reasoning_format?: 'tagged' | 'separated'
|
||||
}
|
||||
|
||||
export enum Type {
|
||||
|
||||
@ -315,6 +315,14 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
||||
return [VarType.arrayObject, VarType.array, VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||
}, [])
|
||||
|
||||
// reasoning format
|
||||
const handleReasoningFormatChange = useCallback((reasoningFormat: 'tagged' | 'separated') => {
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.reasoning_format = reasoningFormat
|
||||
})
|
||||
setInputs(newInputs)
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const {
|
||||
availableVars,
|
||||
availableNodesWithParent,
|
||||
@ -355,6 +363,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
||||
setStructuredOutputCollapsed,
|
||||
handleStructureOutputEnableChange,
|
||||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||
import type { InputVar, PromptItem, Var, Variable } from '@/app/components/workflow/types'
|
||||
@ -18,7 +18,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: LLMNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||
import type { InputVar, Var, Variable } from '@/app/components/workflow/types'
|
||||
@ -17,7 +17,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: ParameterExtractorNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||
import type { InputVar, Var, Variable } from '@/app/components/workflow/types'
|
||||
@ -17,7 +17,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: QuestionClassifierNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||
import type { ValueSelector } from '@/app/components/workflow/types'
|
||||
@ -10,7 +10,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: StartNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -8,7 +8,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: TemplateTransformNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
@ -15,7 +15,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: ToolNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MutableRefObject } from 'react'
|
||||
import type { RefObject } from 'react'
|
||||
import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types'
|
||||
import { useCallback } from 'react'
|
||||
import type { VariableAssignerNodeType } from './types'
|
||||
@ -7,7 +7,7 @@ type Params = {
|
||||
id: string,
|
||||
payload: VariableAssignerNodeType,
|
||||
runInputData: Record<string, any>
|
||||
runInputDataRef: MutableRefObject<Record<string, any>>
|
||||
runInputDataRef: RefObject<Record<string, any>>
|
||||
getInputVars: (textList: string[]) => InputVar[]
|
||||
setRunInputData: (data: Record<string, any>) => void
|
||||
toVarInputs: (variables: Variable[]) => InputVar[]
|
||||
|
||||
@ -33,7 +33,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const treeNodes = formatNodeList(list, t)
|
||||
const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(new Set())
|
||||
const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(() => new Set())
|
||||
const [hoveredParallel, setHoveredParallel] = useState<string | null>(null)
|
||||
|
||||
const toggleCollapse = (id: string) => {
|
||||
|
||||
@ -72,22 +72,18 @@ const ValueContent = ({
|
||||
const [fileValue, setFileValue] = useState<any>(formatFileValue(currentVar))
|
||||
|
||||
const { run: debounceValueChange } = useDebounceFn(handleValueChange, { wait: 500 })
|
||||
if (showTextEditor) {
|
||||
if (currentVar.value_type === 'number')
|
||||
setValue(JSON.stringify(currentVar.value))
|
||||
if (!currentVar.value)
|
||||
setValue('')
|
||||
setValue(currentVar.value)
|
||||
}
|
||||
if (showJSONEditor)
|
||||
setJson(currentVar.value ? JSON.stringify(currentVar.value, null, 2) : '')
|
||||
|
||||
// update default value when id changed
|
||||
useEffect(() => {
|
||||
if (showTextEditor) {
|
||||
if (currentVar.value_type === 'number')
|
||||
return setValue(JSON.stringify(currentVar.value))
|
||||
if (!currentVar.value)
|
||||
return setValue('')
|
||||
setValue(currentVar.value)
|
||||
}
|
||||
if (showJSONEditor)
|
||||
setJson(currentVar.value ? JSON.stringify(currentVar.value, null, 2) : '')
|
||||
|
||||
if (showFileEditor)
|
||||
setFileValue(formatFileValue(currentVar))
|
||||
}, [currentVar.id, currentVar.value])
|
||||
if (showFileEditor)
|
||||
setFileValue(formatFileValue(currentVar))
|
||||
|
||||
const handleTextChange = (value: string) => {
|
||||
if (isTruncated)
|
||||
|
||||
Reference in New Issue
Block a user