Feat: Construct the to field of the classification operator when saving data #3221 (#8610)

### What problem does this PR solve?

Feat: Construct the to field of the classification operator when saving
data #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-07-02 09:49:42 +08:00
committed by GitHub
parent 0b40eb3e90
commit 212d5ce7ff
3 changed files with 44 additions and 46 deletions

View File

@ -3,6 +3,7 @@ export interface ICategorizeItem {
description?: string;
examples?: { value: string }[];
index: number;
to: string[];
}
export type ICategorizeItemResult = Record<

View File

@ -66,7 +66,6 @@ export type RFState = {
target?: string | null,
isConnecting?: boolean,
) => void;
deletePreviousEdgeOfClassificationNode: (connection: Connection) => void;
duplicateNode: (id: string, name: string) => void;
duplicateIterationNode: (id: string, name: string) => void;
deleteEdge: () => void;
@ -122,14 +121,10 @@ const useGraphStore = create<RFState>()(
setEdges(mapEdgeMouseEvent(edges, edgeId, false));
},
onConnect: (connection: Connection) => {
const {
deletePreviousEdgeOfClassificationNode,
updateFormDataOnConnect,
} = get();
const { updateFormDataOnConnect } = get();
set({
edges: addEdge(connection, get().edges),
});
deletePreviousEdgeOfClassificationNode(connection);
updateFormDataOnConnect(connection);
},
onSelectionChange: ({ nodes, edges }: OnSelectionChangeParams) => {
@ -216,7 +211,6 @@ const useGraphStore = create<RFState>()(
set({
edges: addEdge(connection, get().edges),
});
get().deletePreviousEdgeOfClassificationNode(connection);
// TODO: This may not be reasonable. You need to choose between listening to changes in the form.
get().updateFormDataOnConnect(connection);
},
@ -224,23 +218,11 @@ const useGraphStore = create<RFState>()(
return get().edges.find((x) => x.id === id);
},
updateFormDataOnConnect: (connection: Connection) => {
const { getOperatorTypeFromId, updateNodeForm, updateSwitchFormData } =
get();
const { getOperatorTypeFromId, updateSwitchFormData } = get();
const { source, target, sourceHandle } = connection;
const operatorType = getOperatorTypeFromId(source);
if (source) {
switch (operatorType) {
case Operator.Relevant:
updateNodeForm(source, { [sourceHandle as string]: target });
break;
case Operator.Categorize:
if (sourceHandle)
updateNodeForm(source, target, [
'category_description',
sourceHandle,
'to',
]);
break;
case Operator.Switch: {
updateSwitchFormData(source, sourceHandle, target, true);
break;
@ -250,31 +232,6 @@ const useGraphStore = create<RFState>()(
}
}
},
deletePreviousEdgeOfClassificationNode: (connection: Connection) => {
// Delete the edge on the classification node or relevant node anchor when the anchor is connected to other nodes
const { edges, getOperatorTypeFromId, deleteEdgeById } = get();
// the node containing the anchor
const anchoredNodes = [
Operator.Categorize,
Operator.Relevant,
// Operator.Switch,
];
if (
anchoredNodes.some(
(x) => x === getOperatorTypeFromId(connection.source),
)
) {
const previousEdge = edges.find(
(x) =>
x.source === connection.source &&
x.sourceHandle === connection.sourceHandle &&
x.target !== connection.target,
);
if (previousEdge) {
deleteEdgeById(previousEdge.id);
}
}
},
duplicateNode: (id: string, name: string) => {
const { getNode, addNode, generateNodeName, duplicateIterationNode } =
get();

View File

@ -1,5 +1,6 @@
import {
IAgentForm,
ICategorizeForm,
ICategorizeItem,
ICategorizeItemResult,
} from '@/interfaces/database/agent';
@ -158,6 +159,33 @@ function buildAgentTools(edges: Edge[], nodes: Node[], nodeId: string) {
return params;
}
function filterTargetsBySourceHandleId(edges: Edge[], handleId: string) {
return edges.filter((x) => x.sourceHandle === handleId).map((x) => x.target);
}
function buildCategorizeTos(edges: Edge[], nodes: Node[], nodeId: string) {
const node = nodes.find((x) => x.id === nodeId);
const params = { ...(node?.data.form ?? {}) } as ICategorizeForm;
if (node && node.data.label === Operator.Categorize) {
const subEdges = edges.filter((x) => x.source === nodeId);
const categoryDescription = params.category_description || {};
const nextCategoryDescription = Object.entries(categoryDescription).reduce<
ICategorizeForm['category_description']
>((pre, [key, val]) => {
pre[key] = {
...val,
to: filterTargetsBySourceHandleId(subEdges, key),
};
return pre;
}, {});
params.category_description = nextCategoryDescription;
}
return params;
}
const buildOperatorParams = (operatorName: string) =>
pipe(
removeUselessDataInTheOperator(operatorName),
@ -190,8 +218,20 @@ export const buildDslComponentsByGraph = (
.forEach((x) => {
const id = x.id;
const operatorName = x.data.label;
let params = x?.data.form ?? {};
switch (operatorName) {
case Operator.Agent:
params = buildAgentTools(edges, nodes, id);
break;
case Operator.Categorize:
params = buildCategorizeTos(edges, nodes, id);
break;
default:
break;
}
const params = buildAgentTools(edges, nodes, id);
components[id] = {
obj: {
...(oldDslComponents[id]?.obj ?? {}),