Commit 328a3e2e authored by StyleZhang's avatar StyleZhang

node about author

parent 597053c3
...@@ -42,7 +42,7 @@ const nodes = [ ...@@ -42,7 +42,7 @@ const nodes = [
type: 'custom', type: 'custom',
position: { x: 330, y: 30 + i * 300 }, position: { x: 330, y: 30 + i * 300 },
data: { data: {
_selected: i === 0, // for test: always select the first node selected: i === 0, // for test: always select the first node
name: item, name: item,
...payload, ...payload,
}, },
......
import type { FC } from 'react' import type { FC } from 'react'
import { memo } from 'react' import { memo } from 'react'
import { BlockEnum } from './types' import { BlockEnum } from './types'
import { useStore } from './store'
import { import {
Code, Code,
DirectAnswer, DirectAnswer,
...@@ -20,7 +21,7 @@ type BlockIconProps = { ...@@ -20,7 +21,7 @@ type BlockIconProps = {
type: BlockEnum type: BlockEnum
size?: string size?: string
className?: string className?: string
icon?: any toolProviderId?: string
} }
const ICON_CONTAINER_CLASSNAME_SIZE_MAP: Record<string, string> = { const ICON_CONTAINER_CLASSNAME_SIZE_MAP: Record<string, string> = {
sm: 'w-5 h-5 rounded-md shadow-xs', sm: 'w-5 h-5 rounded-md shadow-xs',
...@@ -59,8 +60,11 @@ const BlockIcon: FC<BlockIconProps> = ({ ...@@ -59,8 +60,11 @@ const BlockIcon: FC<BlockIconProps> = ({
type, type,
size = 'sm', size = 'sm',
className, className,
icon, toolProviderId,
}) => { }) => {
const toolsets = useStore(s => s.toolsets)
const icon = toolsets.find(toolset => toolset.id === toolProviderId)?.icon
return ( return (
<div className={` <div className={`
flex items-center justify-center border-[0.5px] border-white/[0.02] text-white flex items-center justify-center border-[0.5px] border-white/[0.02] text-white
......
...@@ -39,7 +39,7 @@ const Tools = ({ ...@@ -39,7 +39,7 @@ const Tools = ({
setToolsets(produce(toolsets, (draft) => { setToolsets(produce(toolsets, (draft) => {
const index = draft.findIndex(toolset => toolset.id === toolId) const index = draft.findIndex(toolset => toolset.id === toolId)
if (!toolsMap[toolId].length && !currentToolset.fetching) if (!toolsMap[toolId]?.length && !currentToolset.fetching)
draft[index].fetching = true draft[index].fetching = true
draft[index].expanded = true draft[index].expanded = true
......
...@@ -106,9 +106,6 @@ const Item = ({ ...@@ -106,9 +106,6 @@ const Item = ({
provider_type: data.type, provider_type: data.type,
tool_name: tool.name, tool_name: tool.name,
title: tool.label[language], title: tool.label[language],
_icon: data.icon,
_about: tool.description[language],
_author: data.author,
})} })}
> >
<div className='absolute left-[22px] w-[1px] h-8 bg-black/5' /> <div className='absolute left-[22px] w-[1px] h-8 bg-black/5' />
......
...@@ -30,7 +30,4 @@ export type ToolDefaultValue = { ...@@ -30,7 +30,4 @@ export type ToolDefaultValue = {
provider_type: string provider_type: string
tool_name: string tool_name: string
title: string title: string
_icon: Collection['icon']
_about: string
_author: string
} }
...@@ -12,30 +12,77 @@ import ToolDefault from './nodes/tool/default' ...@@ -12,30 +12,77 @@ import ToolDefault from './nodes/tool/default'
import VariableAssignerDefault from './nodes/variable-assigner/default' import VariableAssignerDefault from './nodes/variable-assigner/default'
import EndNodeDefault from './nodes/end/default' import EndNodeDefault from './nodes/end/default'
export const NODES_EXTRA_DATA = {
[BlockEnum.Start]: {
author: 'Dify',
about: '',
},
[BlockEnum.End]: {
author: 'Dify',
about: '',
},
[BlockEnum.DirectAnswer]: {
author: 'Dify',
about: '',
},
[BlockEnum.LLM]: {
author: 'Dify',
about: '',
},
[BlockEnum.KnowledgeRetrieval]: {
author: 'Dify',
about: '',
},
[BlockEnum.IfElse]: {
author: 'Dify',
about: '',
},
[BlockEnum.Code]: {
author: 'Dify',
about: '',
},
[BlockEnum.TemplateTransform]: {
author: 'Dify',
about: '',
},
[BlockEnum.QuestionClassifier]: {
author: 'Dify',
about: '',
},
[BlockEnum.HttpRequest]: {
author: 'Dify',
about: '',
},
[BlockEnum.VariableAssigner]: {
author: 'Dify',
about: '',
},
[BlockEnum.Tool]: {
author: 'Dify',
about: '',
},
}
export const NODES_INITIAL_DATA = { export const NODES_INITIAL_DATA = {
[BlockEnum.Start]: { [BlockEnum.Start]: {
_author: 'Dify',
type: BlockEnum.Start, type: BlockEnum.Start,
title: '', title: '',
desc: '', desc: '',
...StartNodeDefault.defaultValue, ...StartNodeDefault.defaultValue,
}, },
[BlockEnum.End]: { [BlockEnum.End]: {
_author: 'Dify',
type: BlockEnum.End, type: BlockEnum.End,
title: '', title: '',
desc: '', desc: '',
...EndNodeDefault.defaultValue, ...EndNodeDefault.defaultValue,
}, },
[BlockEnum.DirectAnswer]: { [BlockEnum.DirectAnswer]: {
_author: 'Dify',
type: BlockEnum.DirectAnswer, type: BlockEnum.DirectAnswer,
title: '', title: '',
desc: '', desc: '',
...DirectAnswerDefault.defaultValue, ...DirectAnswerDefault.defaultValue,
}, },
[BlockEnum.LLM]: { [BlockEnum.LLM]: {
_author: 'Dify',
type: BlockEnum.LLM, type: BlockEnum.LLM,
title: '', title: '',
desc: '', desc: '',
...@@ -43,7 +90,6 @@ export const NODES_INITIAL_DATA = { ...@@ -43,7 +90,6 @@ export const NODES_INITIAL_DATA = {
...LLMDefault.defaultValue, ...LLMDefault.defaultValue,
}, },
[BlockEnum.KnowledgeRetrieval]: { [BlockEnum.KnowledgeRetrieval]: {
_author: 'Dify',
type: BlockEnum.KnowledgeRetrieval, type: BlockEnum.KnowledgeRetrieval,
title: '', title: '',
desc: '', desc: '',
...@@ -53,14 +99,12 @@ export const NODES_INITIAL_DATA = { ...@@ -53,14 +99,12 @@ export const NODES_INITIAL_DATA = {
...KnowledgeRetrievalDefault.defaultValue, ...KnowledgeRetrievalDefault.defaultValue,
}, },
[BlockEnum.IfElse]: { [BlockEnum.IfElse]: {
_author: 'Dify',
type: BlockEnum.IfElse, type: BlockEnum.IfElse,
title: '', title: '',
desc: '', desc: '',
...IfElseDefault.defaultValue, ...IfElseDefault.defaultValue,
}, },
[BlockEnum.Code]: { [BlockEnum.Code]: {
_author: 'Dify',
type: BlockEnum.Code, type: BlockEnum.Code,
title: '', title: '',
desc: '', desc: '',
...@@ -71,7 +115,6 @@ export const NODES_INITIAL_DATA = { ...@@ -71,7 +115,6 @@ export const NODES_INITIAL_DATA = {
...CodeDefault.defaultValue, ...CodeDefault.defaultValue,
}, },
[BlockEnum.TemplateTransform]: { [BlockEnum.TemplateTransform]: {
_author: 'Dify',
type: BlockEnum.TemplateTransform, type: BlockEnum.TemplateTransform,
title: '', title: '',
desc: '', desc: '',
...@@ -80,7 +123,6 @@ export const NODES_INITIAL_DATA = { ...@@ -80,7 +123,6 @@ export const NODES_INITIAL_DATA = {
...TemplateTransformDefault.defaultValue, ...TemplateTransformDefault.defaultValue,
}, },
[BlockEnum.QuestionClassifier]: { [BlockEnum.QuestionClassifier]: {
_author: 'Dify',
type: BlockEnum.QuestionClassifier, type: BlockEnum.QuestionClassifier,
title: '', title: '',
desc: '', desc: '',
...@@ -89,7 +131,6 @@ export const NODES_INITIAL_DATA = { ...@@ -89,7 +131,6 @@ export const NODES_INITIAL_DATA = {
...QuestionClassifierDefault.defaultValue, ...QuestionClassifierDefault.defaultValue,
}, },
[BlockEnum.HttpRequest]: { [BlockEnum.HttpRequest]: {
_author: 'Dify',
type: BlockEnum.HttpRequest, type: BlockEnum.HttpRequest,
title: '', title: '',
desc: '', desc: '',
...@@ -97,7 +138,6 @@ export const NODES_INITIAL_DATA = { ...@@ -97,7 +138,6 @@ export const NODES_INITIAL_DATA = {
...HttpRequestDefault.defaultValue, ...HttpRequestDefault.defaultValue,
}, },
[BlockEnum.VariableAssigner]: { [BlockEnum.VariableAssigner]: {
_author: 'Dify',
type: BlockEnum.VariableAssigner, type: BlockEnum.VariableAssigner,
title: '', title: '',
desc: '', desc: '',
......
import { useCallback } from 'react' import { useCallback } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import produce from 'immer' import produce from 'immer'
import { debounce } from 'lodash-es' import { useDebounceFn } from 'ahooks'
import type { import type {
EdgeMouseHandler, EdgeMouseHandler,
NodeDragHandler, NodeDragHandler,
...@@ -21,7 +21,10 @@ import type { ...@@ -21,7 +21,10 @@ import type {
BlockEnum, BlockEnum,
Node, Node,
} from './types' } from './types'
import { NODES_INITIAL_DATA } from './constants' import {
NODES_EXTRA_DATA,
NODES_INITIAL_DATA,
} from './constants'
import { getLayoutByDagre } from './utils' import { getLayoutByDagre } from './utils'
import { useStore } from './store' import { useStore } from './store'
import type { ToolDefaultValue } from './block-selector/types' import type { ToolDefaultValue } from './block-selector/types'
...@@ -45,13 +48,23 @@ export const useNodesInitialData = () => { ...@@ -45,13 +48,23 @@ export const useNodesInitialData = () => {
}) })
} }
export const useNodesExtraData = () => {
const { t } = useTranslation()
return produce(NODES_EXTRA_DATA, (draft) => {
Object.keys(draft).forEach((key) => {
draft[key as BlockEnum].about = t(`workflow.blocksAbout.${key}`)
})
})
}
export const useWorkflow = () => { export const useWorkflow = () => {
const store = useStoreApi() const store = useStoreApi()
const reactFlow = useReactFlow() const reactFlow = useReactFlow()
const nodesInitialData = useNodesInitialData() const nodesInitialData = useNodesInitialData()
const featuresStore = useFeaturesStore() const featuresStore = useFeaturesStore()
const handleSyncWorkflowDraft = useCallback(debounce(() => { const shouldDebouncedSyncWorkflowDraft = () => {
const { const {
getNodes, getNodes,
edges, edges,
...@@ -84,7 +97,12 @@ export const useWorkflow = () => { ...@@ -84,7 +97,12 @@ export const useWorkflow = () => {
useStore.setState({ draftUpdatedAt: res.updated_at }) useStore.setState({ draftUpdatedAt: res.updated_at })
}) })
} }
}, 2000, { trailing: true }), [store, reactFlow, featuresStore]) }
const { run: handleSyncWorkflowDraft } = useDebounceFn(shouldDebouncedSyncWorkflowDraft, {
wait: 2000,
trailing: true,
})
const handleLayout = useCallback(async () => { const handleLayout = useCallback(async () => {
const { const {
...@@ -203,17 +221,17 @@ export const useWorkflow = () => { ...@@ -203,17 +221,17 @@ export const useWorkflow = () => {
} = store.getState() } = store.getState()
const nodes = getNodes() const nodes = getNodes()
const selectedNode = nodes.find(node => node.data._selected) const selectedNode = nodes.find(node => node.data.selected)
if (!cancelSelection && selectedNode?.id === nodeId) if (!cancelSelection && selectedNode?.id === nodeId)
return return
const newNodes = produce(getNodes(), (draft) => { const newNodes = produce(getNodes(), (draft) => {
draft.forEach(node => node.data._selected = false) draft.forEach(node => node.data.selected = false)
const selectedNode = draft.find(node => node.id === nodeId)! const selectedNode = draft.find(node => node.id === nodeId)!
if (!cancelSelection) if (!cancelSelection)
selectedNode.data._selected = true selectedNode.data.selected = true
}) })
setNodes(newNodes) setNodes(newNodes)
handleSyncWorkflowDraft() handleSyncWorkflowDraft()
...@@ -312,7 +330,7 @@ export const useWorkflow = () => { ...@@ -312,7 +330,7 @@ export const useWorkflow = () => {
data: { data: {
...nodesInitialData[nodeType], ...nodesInitialData[nodeType],
...(toolDefaultValue || {}), ...(toolDefaultValue || {}),
_selected: true, selected: true,
}, },
position: { position: {
x: currentNode.position.x + 304, x: currentNode.position.x + 304,
...@@ -330,7 +348,7 @@ export const useWorkflow = () => { ...@@ -330,7 +348,7 @@ export const useWorkflow = () => {
} }
const newNodes = produce(nodes, (draft) => { const newNodes = produce(nodes, (draft) => {
draft.forEach((node) => { draft.forEach((node) => {
node.data._selected = false node.data.selected = false
}) })
draft.push(nextNode) draft.push(nextNode)
}) })
...@@ -364,7 +382,7 @@ export const useWorkflow = () => { ...@@ -364,7 +382,7 @@ export const useWorkflow = () => {
data: { data: {
...nodesInitialData[nodeType], ...nodesInitialData[nodeType],
...(toolDefaultValue || {}), ...(toolDefaultValue || {}),
_selected: currentNode.data._selected, selected: currentNode.data.selected,
}, },
position: { position: {
x: currentNode.position.x, x: currentNode.position.x,
......
...@@ -40,7 +40,7 @@ const NextStep = ({ ...@@ -40,7 +40,7 @@ const NextStep = ({
<div className='shrink-0 relative flex items-center justify-center w-9 h-9 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'> <div className='shrink-0 relative flex items-center justify-center w-9 h-9 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'>
<BlockIcon <BlockIcon
type={selectedNode!.data.type} type={selectedNode!.data.type}
icon={selectedNode!.data._icon} toolProviderId={selectedNode!.data.provider_id}
/> />
</div> </div>
<Line linesNumber={branches ? branches.length : 1} /> <Line linesNumber={branches ? branches.length : 1} />
......
...@@ -55,7 +55,7 @@ const Item = ({ ...@@ -55,7 +55,7 @@ const Item = ({
} }
<BlockIcon <BlockIcon
type={data.type} type={data.type}
icon={data._icon} toolProviderId={data.provider_id}
className='shrink-0 mr-1.5' className='shrink-0 mr-1.5'
/> />
<div className='grow'>{data.title}</div> <div className='grow'>{data.title}</div>
......
import { import {
memo, memo,
useCallback,
useEffect,
useMemo,
useState, useState,
} from 'react' } from 'react'
import produce from 'immer'
import { useContext } from 'use-context-selector'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useEdges } from 'reactflow' import { useEdges } from 'reactflow'
import ChangeBlock from './change-block' import ChangeBlock from './change-block'
import { useWorkflow } from '@/app/components/workflow/hooks' import { useStore } from '@/app/components/workflow/store'
import {
useNodesExtraData,
useWorkflow,
} from '@/app/components/workflow/hooks'
import { DotsHorizontal } from '@/app/components/base/icons/src/vender/line/general' import { DotsHorizontal } from '@/app/components/base/icons/src/vender/line/general'
import { import {
PortalToFollowElem, PortalToFollowElem,
...@@ -14,6 +23,12 @@ import { ...@@ -14,6 +23,12 @@ import {
} from '@/app/components/base/portal-to-follow-elem' } from '@/app/components/base/portal-to-follow-elem'
import type { Node } from '@/app/components/workflow/types' import type { Node } from '@/app/components/workflow/types'
import { BlockEnum } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types'
import I18n from '@/context/i18n'
import { getLanguage } from '@/i18n/language'
import {
fetchBuiltInToolList,
fetchCustomToolList,
} from '@/service/tools'
type PanelOperatorProps = { type PanelOperatorProps = {
id: string id: string
...@@ -24,12 +39,53 @@ const PanelOperator = ({ ...@@ -24,12 +39,53 @@ const PanelOperator = ({
data, data,
}: PanelOperatorProps) => { }: PanelOperatorProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const language = getLanguage(locale)
const edges = useEdges() const edges = useEdges()
const { handleNodeDelete } = useWorkflow() const { handleNodeDelete } = useWorkflow()
const nodesExtraData = useNodesExtraData()
const toolsets = useStore(s => s.toolsets)
const toolsMap = useStore(s => s.toolsMap)
const setToolsMap = useStore(s => s.setToolsMap)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const fetchToolList = useMemo(() => {
const toolset = toolsets.find(toolset => toolset.id === data.provider_id)
return toolset?.type === 'api' ? fetchCustomToolList : fetchBuiltInToolList
}, [toolsets, data.provider_id])
const handleGetAbout = useCallback(() => {
if (data.provider_id && !toolsMap[data.provider_id]?.length) {
fetchToolList(data.provider_id).then((list: any) => {
setToolsMap(produce(toolsMap, (draft) => {
draft[data.provider_id as string] = list
}))
})
}
}, [data, toolsMap, fetchToolList, setToolsMap])
useEffect(() => {
handleGetAbout()
}, [handleGetAbout])
const edge = edges.find(edge => edge.target === id) const edge = edges.find(edge => edge.target === id)
const author = useMemo(() => {
if (data.type !== BlockEnum.Tool)
return nodesExtraData[data.type].author
const toolset = toolsets.find(toolset => toolset.id === data.provider_id)
return toolset?.author
}, [data, nodesExtraData, toolsets])
const about = useMemo(() => {
if (data.type !== BlockEnum.Tool)
return nodesExtraData[data.type].about
const tool = toolsMap[data.provider_id as string]?.find(tool => tool.name === data.tool_name)
return tool?.description[language] || ''
}, [data, nodesExtraData, toolsMap, language])
return ( return (
<PortalToFollowElem <PortalToFollowElem
placement='bottom-end' placement='bottom-end'
...@@ -83,10 +139,10 @@ const PanelOperator = ({ ...@@ -83,10 +139,10 @@ const PanelOperator = ({
<div className='flex items-center mb-1 h-[22px] font-medium'> <div className='flex items-center mb-1 h-[22px] font-medium'>
{t('workflow.panel.about')} {t('workflow.panel.about')}
</div> </div>
<div className='text-gray-500 leading-[18px]'>{data._about}</div> <div className='text-gray-500 leading-[18px]'>{about}</div>
<div className='my-2 h-[0.5px] bg-black/5'></div> <div className='my-2 h-[0.5px] bg-black/5'></div>
<div className='leading-[18px]'> <div className='leading-[18px]'>
{t('workflow.panel.createdBy')} {data._author} {t('workflow.panel.createdBy')} {author}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -29,7 +29,7 @@ const BaseNode: FC<BaseNodeProps> = ({ ...@@ -29,7 +29,7 @@ const BaseNode: FC<BaseNodeProps> = ({
<div <div
className={` className={`
flex border-[2px] rounded-2xl flex border-[2px] rounded-2xl
${data._selected ? 'border-primary-600' : 'border-transparent'} ${data.selected ? 'border-primary-600' : 'border-transparent'}
`} `}
> >
<div <div
...@@ -75,7 +75,7 @@ const BaseNode: FC<BaseNodeProps> = ({ ...@@ -75,7 +75,7 @@ const BaseNode: FC<BaseNodeProps> = ({
className='shrink-0 mr-2' className='shrink-0 mr-2'
type={data.type} type={data.type}
size='md' size='md'
icon={data._icon} toolProviderId={data.provider_id}
/> />
<div <div
title={data.title} title={data.title}
......
...@@ -54,7 +54,7 @@ const BasePanel: FC<BasePanelProps> = ({ ...@@ -54,7 +54,7 @@ const BasePanel: FC<BasePanelProps> = ({
<BlockIcon <BlockIcon
className='shrink-0 mr-1' className='shrink-0 mr-1'
type={data.type} type={data.type}
icon={data._icon} toolProviderId={data.provider_id}
size='md' size='md'
/> />
<TitleInput <TitleInput
......
...@@ -17,7 +17,7 @@ const Panel: FC = () => { ...@@ -17,7 +17,7 @@ const Panel: FC = () => {
const isChatMode = useIsChatMode() const isChatMode = useIsChatMode()
const runTaskId = useStore(state => state.runTaskId) const runTaskId = useStore(state => state.runTaskId)
const nodes = useNodes<CommonNodeType>() const nodes = useNodes<CommonNodeType>()
const selectedNode = nodes.find(node => node.data._selected) const selectedNode = nodes.find(node => node.data.selected)
const showRunHistory = useStore(state => state.showRunHistory) const showRunHistory = useStore(state => state.showRunHistory)
const { const {
showWorkflowInfoPanel, showWorkflowInfoPanel,
......
...@@ -2,7 +2,6 @@ import type { ...@@ -2,7 +2,6 @@ import type {
Edge as ReactFlowEdge, Edge as ReactFlowEdge,
Node as ReactFlowNode, Node as ReactFlowNode,
} from 'reactflow' } from 'reactflow'
import type { Collection } from '@/app/components/tools/types'
import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types' import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types'
export enum BlockEnum { export enum BlockEnum {
...@@ -26,16 +25,13 @@ export type Branch = { ...@@ -26,16 +25,13 @@ export type Branch = {
} }
export type CommonNodeType<T = {}> = { export type CommonNodeType<T = {}> = {
_selected?: boolean
_targetBranches?: Branch[] _targetBranches?: Branch[]
_isSingleRun?: boolean _isSingleRun?: boolean
_icon?: Collection['icon'] selected?: boolean
_about?: string
_author?: string
title: string title: string
desc: string desc: string
type: BlockEnum type: BlockEnum
} & T } & T & Partial<Pick<ToolDefaultValue, 'provider_id' | 'provider_type' | 'tool_name'>>
export type CommonEdgeType = { export type CommonEdgeType = {
_hovering: boolean _hovering: boolean
......
...@@ -50,6 +50,19 @@ const translation = { ...@@ -50,6 +50,19 @@ const translation = {
'http-request': 'HTTP Request', 'http-request': 'HTTP Request',
'variable-assigner': 'Variable Assigner', 'variable-assigner': 'Variable Assigner',
}, },
blocksAbout: {
'start': 'Define the initial parameters for launching a workflow',
'end': 'Define the end and result type of a workflow',
'direct-answer': 'Specify a custom text reply',
'llm': 'Invoking large language models to answer questions or process natural language',
'knowledge-retrieval': 'Allows you to query text content related to user questions from the Knowledge',
'question-classifier': 'Define the classification conditions of user questions, LLM can define how the conversation progresses based on the classification description',
'if-else': 'Allows you to split the workflow into two branches based on if/else conditions',
'code': 'Execute a piece of Python or NodeJS code to implement custom logic',
'template-transform': 'Convert data to string using Jinja template syntax',
'http-request': 'Allow server requests to be sent over the HTTP protocol',
'variable-assigner': 'Assign variables in different branches to the same variable to achieve unified configuration of post-nodes',
},
operator: { operator: {
zoomIn: 'Zoom In', zoomIn: 'Zoom In',
zoomOut: 'Zoom Out', zoomOut: 'Zoom Out',
......
...@@ -50,6 +50,19 @@ const translation = { ...@@ -50,6 +50,19 @@ const translation = {
'http-request': 'HTTP 请求', 'http-request': 'HTTP 请求',
'variable-assigner': '变量赋值', 'variable-assigner': '变量赋值',
}, },
blocksAbout: {
'start': '定义一个 workflow 流程启动的初始参数',
'end': '定义一个 workflow 流程的结束和结果类型',
'direct-answer': '指定一段自定义的文本回复',
'llm': '调用大语言模型回答问题或者对自然语言进行处理',
'knowledge-retrieval': '允许你从知识库中查询与用户问题相关的文本内容',
'question-classifier': '定义用户问题的分类条件,LLM 能够根据分类描述定义对话的进展方式',
'if-else': '允许你根据 if/else 条件将 workflow 拆分成两个分支',
'code': '执行一段 Python 或 NodeJS 代码实现自定义逻辑',
'template-transform': '使用 Jinja 模板语法将数据转换为字符串',
'http-request': '允许通过 HTTP 协议发送服务器请求',
'variable-assigner': '将不同分支中的变量指派给同一个变量,以实现后置节点统一配置',
},
operator: { operator: {
zoomIn: '放大', zoomIn: '放大',
zoomOut: '缩小', zoomOut: '缩小',
......
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