mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### 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:
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user