diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts
index fd5c0f016..c990b8b8d 100644
--- a/web/src/locales/en.ts
+++ b/web/src/locales/en.ts
@@ -1710,12 +1710,12 @@ This delimiter is used to split the input text into several text pieces echo of
tokenizerRequired: 'Please add the Indexer node first',
tokenizerDescription:
'Transforms text into the required data structure (e.g., vector embeddings for Embedding Search) depending on the chosen search method.',
- splitter: 'Token Splitter',
+ splitter: 'Token',
splitterDescription:
'Split text into chunks by token length with optional delimiters and overlap.',
hierarchicalMergerDescription:
'Split documents into sections by title hierarchy with regex rules for finer control.',
- hierarchicalMerger: 'Title Splitter',
+ hierarchicalMerger: 'Title',
extractor: 'Transformer',
extractorDescription:
'Use an LLM to extract structured insights from document chunks—such as summaries, classifications, etc.',
diff --git a/web/src/pages/data-flow/canvas/node/dropdown/next-step-dropdown.tsx b/web/src/pages/data-flow/canvas/node/dropdown/next-step-dropdown.tsx
index 2450de579..2e8c8c30f 100644
--- a/web/src/pages/data-flow/canvas/node/dropdown/next-step-dropdown.tsx
+++ b/web/src/pages/data-flow/canvas/node/dropdown/next-step-dropdown.tsx
@@ -1,3 +1,9 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from '@/components/ui/accordion';
import {
DropdownMenu,
DropdownMenuContent,
@@ -19,12 +25,13 @@ import {
PropsWithChildren,
createContext,
memo,
+ useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from 'react';
-import { Operator, SingleOperators } from '../../../constant';
+import { Operator } from '../../../constant';
import { AgentInstanceContext, HandleContext } from '../../../context';
import OperatorIcon from '../../../operator-icon';
@@ -116,16 +123,22 @@ function OperatorItemList({
// Limit the number of operators of a certain type on the canvas to only one
function useRestrictSingleOperatorOnCanvas() {
- const list: Operator[] = [];
const { findNodeByName } = useGraphStore((state) => state);
- SingleOperators.forEach((operator) => {
- if (!findNodeByName(operator)) {
- list.push(operator);
- }
- });
+ const restrictSingleOperatorOnCanvas = useCallback(
+ (singleOperators: Operator[]) => {
+ const list: Operator[] = [];
+ singleOperators.forEach((operator) => {
+ if (!findNodeByName(operator)) {
+ list.push(operator);
+ }
+ });
+ return list;
+ },
+ [findNodeByName],
+ );
- return list;
+ return restrictSingleOperatorOnCanvas;
}
function AccordionOperators({
@@ -137,25 +150,60 @@ function AccordionOperators({
mousePosition?: { x: number; y: number };
nodeId?: string;
}) {
- const singleOperators = useRestrictSingleOperatorOnCanvas();
+ const restrictSingleOperatorOnCanvas = useRestrictSingleOperatorOnCanvas();
const { getOperatorTypeFromId } = useGraphStore((state) => state);
const operators = useMemo(() => {
- let list = [...singleOperators];
- if (getOperatorTypeFromId(nodeId) === Operator.Extractor) {
- const Splitters = [Operator.HierarchicalMerger, Operator.Splitter];
- list = list.filter((x) => !Splitters.includes(x)); // The Context Generator node can only be followed by a Tokenizer and a Context Generator.
- }
+ let list = [
+ ...restrictSingleOperatorOnCanvas([Operator.Parser, Operator.Tokenizer]),
+ ];
list.push(Operator.Extractor);
return list;
- }, [getOperatorTypeFromId, nodeId, singleOperators]);
+ }, [restrictSingleOperatorOnCanvas]);
+
+ const chunkerOperators = useMemo(() => {
+ return [
+ ...restrictSingleOperatorOnCanvas([
+ Operator.Splitter,
+ Operator.HierarchicalMerger,
+ ]),
+ ];
+ }, [restrictSingleOperatorOnCanvas]);
+
+ const showChunker = useMemo(() => {
+ return (
+ getOperatorTypeFromId(nodeId) !== Operator.Extractor &&
+ chunkerOperators.length > 0
+ );
+ }, [chunkerOperators.length, getOperatorTypeFromId, nodeId]);
return (
-
+ <>
+
+ {showChunker && (
+
+
+ Chunker
+
+
+
+
+
+ )}
+ >
);
}