answer node

This commit is contained in:
StyleZhang 2024-03-19 14:50:07 +08:00
parent 0b7cdd1e5d
commit ced6a5c18b
19 changed files with 68 additions and 41 deletions

View File

@ -4,6 +4,8 @@ import type {
VisionSettings,
} from '@/types/app'
import type { IChatItem } from '@/app/components/app/chat/type'
import type { NodeTracing } from '@/types/workflow'
import type { WorkflowRunningStatus } from '@/app/components/workflow/types'
export type { VisionFile } from '@/types/app'
export { TransferMethod } from '@/types/app'
@ -48,7 +50,14 @@ export type ChatConfig = Omit<ModelConfig, 'model'> & {
supportCitationHitInfo?: boolean
}
export type ChatItem = IChatItem
export type WorkflowProcess = {
status: WorkflowRunningStatus
nodes: NodeTracing[]
}
export type ChatItem = IChatItem & {
workflowProcess?: WorkflowProcess
}
export type OnSend = (message: string, files?: VisionFile[]) => void

View File

@ -3,7 +3,7 @@ import {
useCallback,
useState,
} from 'react'
import { union } from 'lodash-es'
import { intersection } from 'lodash-es'
import type { EdgeProps } from 'reactflow'
import {
BaseEdge,
@ -49,8 +49,8 @@ const CustomEdge = ({
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const nodesExtraData = useNodesExtraData()
const availablePrevNodes = nodesExtraData[(data as Edge['data'])?.targetType]?.availablePrevNodes || []
const availableNextNodes = nodesExtraData[(data as Edge['data'])?.sourceType]?.availableNextNodes || []
const availablePrevNodes = nodesExtraData[(data as Edge['data'])!.targetType]?.availablePrevNodes || []
const availableNextNodes = nodesExtraData[(data as Edge['data'])!.sourceType]?.availableNextNodes || []
const handleOpenChange = useCallback((v: boolean) => {
setOpen(v)
}, [])
@ -98,7 +98,7 @@ const CustomEdge = ({
onOpenChange={handleOpenChange}
asChild
onSelect={handleInsert}
availableBlocksTypes={union(availablePrevNodes, availableNextNodes)}
availableBlocksTypes={intersection(availablePrevNodes, availableNextNodes)}
/>
</div>
</EdgeLabelRenderer>

View File

@ -8,7 +8,10 @@ import {
useStore,
useWorkflowStore,
} from '../store'
import { useWorkflow } from '../hooks'
import {
useNodesSyncDraft,
useWorkflow,
} from '../hooks'
import Button from '@/app/components/base/button'
import {
PortalToFollowElem,
@ -23,6 +26,7 @@ const Publish = () => {
const [published, setPublished] = useState(false)
const workflowStore = useWorkflowStore()
const { formatTimeFromNow } = useWorkflow()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const runningStatus = useStore(s => s.runningStatus)
const draftUpdatedAt = useStore(s => s.draftUpdatedAt)
const publishedAt = useStore(s => s.publishedAt)
@ -56,10 +60,11 @@ const Publish = () => {
setOpen(false)
if (!open) {
handleSyncWorkflowDraft(true)
setOpen(true)
setPublished(false)
}
}, [runningStatus, open])
}, [runningStatus, open, handleSyncWorkflowDraft])
return (
<PortalToFollowElem

View File

@ -15,6 +15,7 @@ import {
} from 'reactflow'
import type { ToolDefaultValue } from '../block-selector/types'
import type {
Edge,
Node,
OnNodeAdd,
} from '../types'
@ -540,23 +541,26 @@ export const useNodesInteractions = () => {
targetType: newNode.data.type,
},
}
const newNextEdge = {
id: `${newNode.id}-${nextNodeId}`,
type: 'custom',
source: newNode.id,
sourceHandle,
target: nextNodeId,
targetHandle: nextNodeTargetHandle,
data: {
sourceType: newNode.data.type,
targetType: nextNode.data.type,
},
let newNextEdge: Edge | null = null
if (nodeType !== BlockEnum.IfElse && nodeType !== BlockEnum.QuestionClassifier) {
newNextEdge = {
id: `${newNode.id}-${nextNodeId}`,
type: 'custom',
source: newNode.id,
sourceHandle,
target: nextNodeId,
targetHandle: nextNodeTargetHandle,
data: {
sourceType: newNode.data.type,
targetType: nextNode.data.type,
},
}
}
const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap(
[
{ type: 'remove', edge: edges[currentEdgeIndex] },
{ type: 'add', edge: newPrevEdge },
{ type: 'add', edge: newNextEdge },
...(newNextEdge ? [{ type: 'add', edge: newNextEdge }] : []),
],
nodes,
)
@ -582,7 +586,9 @@ export const useNodesInteractions = () => {
const newEdges = produce(edges, (draft) => {
draft.splice(currentEdgeIndex, 1)
draft.push(newPrevEdge)
draft.push(newNextEdge)
if (newNextEdge)
draft.push(newNextEdge)
})
setEdges(newEdges)
}

View File

@ -4,7 +4,7 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import { union } from 'lodash-es'
import { intersection } from 'lodash-es'
import type {
CommonNodeType,
OnSelectBlock,
@ -86,7 +86,7 @@ const Item = ({
}}
trigger={renderTrigger}
popupClassName='!w-[328px]'
availableBlocksTypes={union(availablePrevNodes, availableNextNodes)}
availableBlocksTypes={intersection(availablePrevNodes, availableNextNodes)}
/>
</div>
)

View File

@ -3,7 +3,7 @@ import {
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import { union } from 'lodash-es'
import { intersection } from 'lodash-es'
import BlockSelector from '@/app/components/workflow/block-selector'
import {
useNodesExtraData,
@ -51,7 +51,7 @@ const ChangeBlock = ({
}}
onSelect={handleSelect}
trigger={renderTrigger}
availableBlocksTypes={union(availablePrevNodes, availableNextNodes)}
availableBlocksTypes={intersection(availablePrevNodes, availableNextNodes)}
/>
)
}

View File

@ -1,4 +1,5 @@
import { BlockEnum, type NodeDefault } from '../../types'
import { BlockEnum } from '../../types'
import type { NodeDefault } from '../../types'
import type { AnswerNodeType } from './types'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
@ -9,12 +10,15 @@ const nodeDefault: NodeDefault<AnswerNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},
getAvailableNextNodes() {
return []
getAvailableNextNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS
return nodes
},
checkValid(payload: AnswerNodeType) {
let isValid = true

View File

@ -14,7 +14,7 @@ const nodeDefault: NodeDefault<CodeNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -9,7 +9,7 @@ const nodeDefault: NodeDefault<EndNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -21,7 +21,7 @@ const nodeDefault: NodeDefault<HttpNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -19,7 +19,7 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -14,7 +14,7 @@ const nodeDefault: NodeDefault<KnowledgeRetrievalNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -37,7 +37,7 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -18,7 +18,7 @@ const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -6,9 +6,8 @@ const nodeDefault: NodeDefault<StartNodeType> = {
defaultValue: {
variables: [],
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
return nodes
getAvailablePrevNodes() {
return []
},
getAvailableNextNodes(isChatMode: boolean) {
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS

View File

@ -9,7 +9,7 @@ const nodeDefault: NodeDefault<TemplateTransformNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -10,7 +10,7 @@ const nodeDefault: NodeDefault<ToolNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes
},

View File

@ -10,7 +10,7 @@ const nodeDefault: NodeDefault<VariableAssignerNodeType> = {
},
getAvailablePrevNodes(isChatMode: boolean) {
const nodes = isChatMode
? ALL_CHAT_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.Answer)
? ALL_CHAT_AVAILABLE_BLOCKS
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
return nodes.filter(type => type !== BlockEnum.IfElse && type !== BlockEnum.QuestionClassifier)
},

View File

@ -224,6 +224,10 @@ export const useChat = (
})
handleUpdateChatList(newChatList)
},
onWorkflowStarted: () => {},
onWorkflowFinished: () => {},
onNodeStarted: () => {},
onNodeFinished: () => {},
},
)
}, [handleRun, handleResponding, handleUpdateChatList, notify, t, updateCurrentQA, config.suggested_questions_after_answer?.enabled])