Feat: Handling abnormal anchor points of agent operators #3221 (#9121)

### What problem does this PR solve?
Feat: Handling abnormal anchor points of agent operators #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-07-30 19:14:33 +08:00
committed by GitHub
parent db6d4307f2
commit 07e37560fc
10 changed files with 125 additions and 277 deletions

View File

@ -6,91 +6,28 @@ import {
} from '@/interfaces/database/agent';
import { DSLComponents, RAGFlowNodeType } from '@/interfaces/database/flow';
import { removeUselessFieldsFromValues } from '@/utils/form';
import { Edge, Node, Position, XYPosition } from '@xyflow/react';
import { Edge, Node, XYPosition } from '@xyflow/react';
import { FormInstance, FormListFieldData } from 'antd';
import { humanId } from 'human-id';
import { curry, get, intersectionWith, isEqual, omit, sample } from 'lodash';
import pipe from 'lodash/fp/pipe';
import isObject from 'lodash/isObject';
import { v4 as uuidv4 } from 'uuid';
import {
CategorizeAnchorPointPositions,
NoDebugOperatorsList,
NodeHandleId,
NodeMap,
Operator,
} from './constant';
import { BeginQuery, IPosition } from './interface';
const buildEdges = (
operatorIds: string[],
currentId: string,
allEdges: Edge[],
isUpstream = false,
componentName: string,
nodeParams: Record<string, unknown>,
) => {
operatorIds.forEach((cur) => {
const source = isUpstream ? cur : currentId;
const target = isUpstream ? currentId : cur;
if (!allEdges.some((e) => e.source === source && e.target === target)) {
const edge: Edge = {
id: uuidv4(),
label: '',
// type: 'step',
source: source,
target: target,
// markerEnd: {
// type: MarkerType.ArrowClosed,
// color: 'rgb(157 149 225)',
// width: 20,
// height: 20,
// },
};
if (componentName === Operator.Categorize && !isUpstream) {
const categoryDescription =
nodeParams.category_description as ICategorizeItemResult;
function buildAgentExceptionGoto(edges: Edge[], nodeId: string) {
const exceptionEdges = edges.filter(
(x) =>
x.source === nodeId && x.sourceHandle === NodeHandleId.AgentException,
);
const name = Object.keys(categoryDescription).find(
(x) => categoryDescription[x].to === target,
);
if (name) {
edge.sourceHandle = name;
}
}
allEdges.push(edge);
}
});
};
export const buildNodesAndEdgesFromDSLComponents = (data: DSLComponents) => {
const nodes: Node[] = [];
let edges: Edge[] = [];
Object.entries(data).forEach(([key, value]) => {
const downstream = [...value.downstream];
const upstream = [...value.upstream];
const { component_name: componentName, params } = value.obj;
nodes.push({
id: key,
type: NodeMap[value.obj.component_name as Operator] || 'ragNode',
position: { x: 0, y: 0 },
data: {
label: componentName,
name: humanId(),
form: params,
},
sourcePosition: Position.Left,
targetPosition: Position.Right,
});
buildEdges(upstream, key, edges, true, componentName, params);
buildEdges(downstream, key, edges, false, componentName, params);
});
return { nodes, edges };
};
return exceptionEdges.map((x) => x.target);
}
const buildComponentDownstreamOrUpstream = (
edges: Edge[],
@ -103,7 +40,9 @@ const buildComponentDownstreamOrUpstream = (
const node = nodes.find((x) => x.id === nodeId);
let isNotUpstreamTool = true;
let isNotUpstreamAgent = true;
let isNotExceptionGoto = true;
if (isBuildDownstream && node?.data.label === Operator.Agent) {
isNotExceptionGoto = y.sourceHandle !== NodeHandleId.AgentException;
// Exclude the tool operator downstream of the agent operator
isNotUpstreamTool = !y.target.startsWith(Operator.Tool);
// Exclude the agent operator downstream of the agent operator
@ -115,7 +54,8 @@ const buildComponentDownstreamOrUpstream = (
return (
y[isBuildDownstream ? 'source' : 'target'] === nodeId &&
isNotUpstreamTool &&
isNotUpstreamAgent
isNotUpstreamAgent &&
isNotExceptionGoto
);
})
.map((y) => y[isBuildDownstream ? 'target' : 'source']);
@ -234,7 +174,10 @@ export const buildDslComponentsByGraph = (
switch (operatorName) {
case Operator.Agent: {
const { params: formData } = buildAgentTools(edges, nodes, id);
params = formData;
params = {
...formData,
exception_goto: buildAgentExceptionGoto(edges, id),
};
break;
}
case Operator.Categorize:
@ -559,7 +502,7 @@ export const buildCategorizeObjectFromList = (list: Array<ICategorizeItem>) => {
if (cur?.name) {
pre[cur.name] = {
...omit(cur, 'name', 'examples'),
examples: convertToStringArray(cur.examples),
examples: convertToStringArray(cur.examples) as string[],
};
}
return pre;