@cascadeflow/n8n-nodes-cascadeflow 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CascadeFlow.node.d.ts","sourceRoot":"","sources":["../../../nodes/CascadeFlow/CascadeFlow.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAErB,MAAM,cAAc,CAAC;AAItB,qBAAa,WAAY,YAAW,SAAS;IAC3C,WAAW,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"CascadeFlow.node.d.ts","sourceRoot":"","sources":["../../../nodes/CascadeFlow/CascadeFlow.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAErB,MAAM,cAAc,CAAC;AAItB,qBAAa,WAAY,YAAW,SAAS;IAC3C,WAAW,EAAE,oBAAoB,CAwD/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CA+MxE"}
|
|
@@ -10,36 +10,17 @@ class CascadeFlow {
|
|
|
10
10
|
name: 'cascadeFlow',
|
|
11
11
|
icon: 'file:cascadeflow.svg',
|
|
12
12
|
group: ['transform'],
|
|
13
|
-
version:
|
|
13
|
+
version: 3,
|
|
14
14
|
subtitle: 'AI Model Cascading',
|
|
15
15
|
description: 'Smart AI model cascading with 40-85% cost savings',
|
|
16
16
|
defaults: {
|
|
17
17
|
name: 'CascadeFlow',
|
|
18
18
|
},
|
|
19
19
|
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
|
20
|
-
inputs: ['main', 'main'],
|
|
21
|
-
inputNames: ['Drafter Model', 'Verifier Model'],
|
|
20
|
+
inputs: ['main', 'main', 'main'],
|
|
21
|
+
inputNames: ['Input', 'Drafter Model', 'Verifier Model'],
|
|
22
22
|
outputs: ['main'],
|
|
23
|
-
credentials: [
|
|
24
|
-
{
|
|
25
|
-
name: 'cascadeFlowApi',
|
|
26
|
-
required: true,
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
23
|
properties: [
|
|
30
|
-
// Input message
|
|
31
|
-
{
|
|
32
|
-
displayName: 'Prompt',
|
|
33
|
-
name: 'prompt',
|
|
34
|
-
type: 'string',
|
|
35
|
-
default: '',
|
|
36
|
-
required: true,
|
|
37
|
-
typeOptions: {
|
|
38
|
-
rows: 4,
|
|
39
|
-
},
|
|
40
|
-
description: 'The message or query to send to AI models',
|
|
41
|
-
placeholder: 'What is the capital of France?',
|
|
42
|
-
},
|
|
43
24
|
// Quality Threshold
|
|
44
25
|
{
|
|
45
26
|
displayName: 'Quality Threshold',
|
|
@@ -58,13 +39,8 @@ class CascadeFlow {
|
|
|
58
39
|
displayName: 'Output',
|
|
59
40
|
name: 'output',
|
|
60
41
|
type: 'options',
|
|
61
|
-
default: '
|
|
42
|
+
default: 'contentOnly',
|
|
62
43
|
options: [
|
|
63
|
-
{
|
|
64
|
-
name: 'Full Metrics',
|
|
65
|
-
value: 'fullMetrics',
|
|
66
|
-
description: 'Return response + all cascade metrics',
|
|
67
|
-
},
|
|
68
44
|
{
|
|
69
45
|
name: 'Content Only',
|
|
70
46
|
value: 'contentOnly',
|
|
@@ -75,6 +51,11 @@ class CascadeFlow {
|
|
|
75
51
|
value: 'metricsSummary',
|
|
76
52
|
description: 'Return response + key metrics (cost, savings, model)',
|
|
77
53
|
},
|
|
54
|
+
{
|
|
55
|
+
name: 'Full Metrics',
|
|
56
|
+
value: 'fullMetrics',
|
|
57
|
+
description: 'Return response + all cascade metrics',
|
|
58
|
+
},
|
|
78
59
|
],
|
|
79
60
|
description: 'What data to return',
|
|
80
61
|
},
|
|
@@ -83,54 +64,112 @@ class CascadeFlow {
|
|
|
83
64
|
}
|
|
84
65
|
async execute() {
|
|
85
66
|
const returnData = [];
|
|
86
|
-
// Get data from
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
openai: 'openaiApiKey',
|
|
95
|
-
anthropic: 'anthropicApiKey',
|
|
96
|
-
groq: 'groqApiKey',
|
|
97
|
-
together: 'togetherApiKey',
|
|
98
|
-
huggingface: 'huggingfaceApiKey',
|
|
99
|
-
};
|
|
100
|
-
const keyName = keyMap[provider];
|
|
101
|
-
if (!keyName) {
|
|
102
|
-
return '';
|
|
67
|
+
// Get data from all three inputs
|
|
68
|
+
const inputData = this.getInputData(0); // Input (prompt/query)
|
|
69
|
+
const drafterInputData = this.getInputData(1); // Drafter model
|
|
70
|
+
const verifierInputData = this.getInputData(2); // Verifier model
|
|
71
|
+
// Helper to extract model config from provider node output
|
|
72
|
+
const extractModelConfig = (providerData, inputName) => {
|
|
73
|
+
if (!providerData || providerData.length === 0) {
|
|
74
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No data received from ${inputName} input. Please connect a provider node (OpenAI, Anthropic, vLLM, Ollama, etc.).`);
|
|
103
75
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
76
|
+
const data = providerData[0].json;
|
|
77
|
+
// Extract model information - handle various provider formats
|
|
78
|
+
// OpenAI, Anthropic, Groq typically use 'model'
|
|
79
|
+
// Some custom providers might use 'modelName' or 'name'
|
|
80
|
+
const modelName = data.model ||
|
|
81
|
+
data.modelName ||
|
|
82
|
+
data.name ||
|
|
83
|
+
data.model_name ||
|
|
84
|
+
'gpt-4o-mini';
|
|
85
|
+
// Try to detect provider from various fields
|
|
86
|
+
let providerStr = data.provider ||
|
|
87
|
+
data.providerName ||
|
|
88
|
+
'';
|
|
89
|
+
// If no explicit provider, try to infer from model name or base_url
|
|
90
|
+
if (!providerStr) {
|
|
91
|
+
if (modelName.includes('gpt') || modelName.includes('o1') || modelName.includes('o3')) {
|
|
92
|
+
providerStr = 'openai';
|
|
93
|
+
}
|
|
94
|
+
else if (modelName.includes('claude')) {
|
|
95
|
+
providerStr = 'anthropic';
|
|
96
|
+
}
|
|
97
|
+
else if (modelName.includes('llama') || modelName.includes('mixtral') || modelName.includes('qwen')) {
|
|
98
|
+
// Check for vLLM or Ollama
|
|
99
|
+
const baseUrl = data.baseUrl || data.base_url || '';
|
|
100
|
+
if (baseUrl.includes('ollama') || baseUrl.includes('11434')) {
|
|
101
|
+
providerStr = 'ollama';
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
providerStr = 'vllm';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
providerStr = 'openai'; // Default fallback
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Extract API configuration
|
|
112
|
+
const apiKey = data.apiKey ||
|
|
113
|
+
data.api_key ||
|
|
114
|
+
data.token ||
|
|
115
|
+
'';
|
|
116
|
+
const baseUrl = data.baseUrl ||
|
|
117
|
+
data.base_url ||
|
|
118
|
+
undefined;
|
|
119
|
+
// Cost estimation - use provided cost or estimate based on provider
|
|
120
|
+
let cost = data.cost || data.modelCost;
|
|
121
|
+
if (!cost) {
|
|
122
|
+
// Rough estimates per 1K tokens (blended input/output)
|
|
123
|
+
if (providerStr === 'anthropic') {
|
|
124
|
+
cost = modelName.includes('opus') ? 0.03 : 0.006;
|
|
125
|
+
}
|
|
126
|
+
else if (providerStr === 'openai') {
|
|
127
|
+
if (modelName.includes('o1') || modelName.includes('o3'))
|
|
128
|
+
cost = 0.03;
|
|
129
|
+
else if (modelName.includes('gpt-4'))
|
|
130
|
+
cost = 0.006;
|
|
131
|
+
else
|
|
132
|
+
cost = 0.0004;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
cost = 0.001; // Default for local/other providers
|
|
136
|
+
}
|
|
110
137
|
}
|
|
111
|
-
const
|
|
112
|
-
// Try to extract model information from the input
|
|
113
|
-
// This works with OpenAI node output and similar provider nodes
|
|
114
|
-
const modelName = data.model || data.modelName || 'gpt-4o-mini';
|
|
115
|
-
const providerStr = data.provider || 'openai';
|
|
116
|
-
const cost = data.cost || data.modelCost || 0.001;
|
|
117
|
-
return {
|
|
138
|
+
const config = {
|
|
118
139
|
name: modelName,
|
|
119
140
|
provider: providerStr,
|
|
120
141
|
cost,
|
|
121
|
-
apiKey
|
|
142
|
+
apiKey,
|
|
122
143
|
};
|
|
144
|
+
// Add baseUrl if provided (for vLLM, Ollama, custom endpoints)
|
|
145
|
+
if (baseUrl) {
|
|
146
|
+
config.baseUrl = baseUrl;
|
|
147
|
+
}
|
|
148
|
+
return config;
|
|
123
149
|
};
|
|
124
|
-
// Extract model configurations from inputs
|
|
125
|
-
const drafterConfig = extractModelConfig(drafterInputData, 'Drafter');
|
|
126
|
-
const verifierConfig = extractModelConfig(verifierInputData, 'Verifier');
|
|
150
|
+
// Extract model configurations from provider inputs
|
|
151
|
+
const drafterConfig = extractModelConfig(drafterInputData, 'Drafter Model');
|
|
152
|
+
const verifierConfig = extractModelConfig(verifierInputData, 'Verifier Model');
|
|
127
153
|
const modelConfigs = [drafterConfig, verifierConfig];
|
|
128
|
-
|
|
154
|
+
// Process each input item
|
|
155
|
+
for (let itemIndex = 0; itemIndex < inputData.length; itemIndex++) {
|
|
129
156
|
try {
|
|
130
157
|
// Get parameters
|
|
131
|
-
const prompt = this.getNodeParameter('prompt', itemIndex);
|
|
132
158
|
const qualityThreshold = this.getNodeParameter('qualityThreshold', itemIndex, 0.7);
|
|
133
|
-
const outputMode = this.getNodeParameter('output', itemIndex, '
|
|
159
|
+
const outputMode = this.getNodeParameter('output', itemIndex, 'contentOnly');
|
|
160
|
+
// Extract prompt from input data - support various field names
|
|
161
|
+
const item = inputData[itemIndex].json;
|
|
162
|
+
const prompt = item.prompt ||
|
|
163
|
+
item.message ||
|
|
164
|
+
item.query ||
|
|
165
|
+
item.text ||
|
|
166
|
+
item.input ||
|
|
167
|
+
JSON.stringify(item);
|
|
168
|
+
if (!prompt || prompt.length === 0) {
|
|
169
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No prompt found in input data. Connect a node that provides prompt, message, query, text, or input field.', { itemIndex });
|
|
170
|
+
}
|
|
171
|
+
// Extract tools if provided (for function calling)
|
|
172
|
+
const tools = item.tools || undefined;
|
|
134
173
|
// Create CascadeAgent
|
|
135
174
|
const agent = new core_1.CascadeAgent({
|
|
136
175
|
models: modelConfigs,
|
|
@@ -141,6 +180,9 @@ class CascadeFlow {
|
|
|
141
180
|
});
|
|
142
181
|
// Prepare run options
|
|
143
182
|
const runOptions = {};
|
|
183
|
+
if (tools) {
|
|
184
|
+
runOptions.tools = tools;
|
|
185
|
+
}
|
|
144
186
|
// Execute cascade
|
|
145
187
|
const result = await agent.run(prompt, runOptions);
|
|
146
188
|
// Format output based on outputMode
|
|
@@ -165,7 +207,6 @@ class CascadeFlow {
|
|
|
165
207
|
};
|
|
166
208
|
break;
|
|
167
209
|
case 'fullMetrics':
|
|
168
|
-
default:
|
|
169
210
|
outputData = {
|
|
170
211
|
...result,
|
|
171
212
|
// Add n8n-friendly summary
|
|
@@ -178,6 +219,8 @@ class CascadeFlow {
|
|
|
178
219
|
},
|
|
179
220
|
};
|
|
180
221
|
break;
|
|
222
|
+
default:
|
|
223
|
+
outputData = result;
|
|
181
224
|
}
|
|
182
225
|
returnData.push({
|
|
183
226
|
json: outputData,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CascadeFlow.node.js","sourceRoot":"","sources":["../../../nodes/CascadeFlow/CascadeFlow.node.ts"],"names":[],"mappings":";;;AAAA,+CAMsB;AAEtB,4CAA8D;AAE9D,MAAa,WAAW;IAAxB;QACE,gBAAW,GAAyB;YAClC,WAAW,EAAE,aAAa;YAC1B,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,CAAC,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,oBAAoB;YAC9B,WAAW,EAAE,mDAAmD;YAChE,QAAQ,EAAE;gBACR,IAAI,EAAE,aAAa;aACpB;YACD,2FAA2F;YAC3F,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"CascadeFlow.node.js","sourceRoot":"","sources":["../../../nodes/CascadeFlow/CascadeFlow.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 91.76 91.76">
|
|
2
3
|
<defs>
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #fff;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
7
9
|
</defs>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<!-- Arrow -->
|
|
16
|
-
<path d="M 50 28 L 50 40" stroke="url(#grad1)" stroke-width="2" fill="none" opacity="0.6"/>
|
|
17
|
-
<polygon points="50,40 47,35 53,35" fill="url(#grad1)" opacity="0.6"/>
|
|
18
|
-
|
|
19
|
-
<!-- Quality check diamond -->
|
|
20
|
-
<g opacity="0.8">
|
|
21
|
-
<path d="M 50 42 L 58 50 L 50 58 L 42 50 Z" fill="url(#grad1)"/>
|
|
22
|
-
<text x="50" y="53" text-anchor="middle" font-size="8" fill="white" font-weight="bold">✓</text>
|
|
23
|
-
</g>
|
|
24
|
-
|
|
25
|
-
<!-- Branch paths -->
|
|
26
|
-
<path d="M 50 58 L 30 75" stroke="url(#grad1)" stroke-width="2" fill="none" opacity="0.6" stroke-dasharray="2,2"/>
|
|
27
|
-
<path d="M 50 58 L 50 75" stroke="url(#grad1)" stroke-width="2" fill="none"/>
|
|
28
|
-
|
|
29
|
-
<!-- Bottom tier (verifier - optional) -->
|
|
30
|
-
<circle cx="30" cy="80" r="7" opacity="0.4" stroke="#764ba2" stroke-width="1" fill="none"/>
|
|
31
|
-
<text x="30" y="84" text-anchor="middle" font-size="9" fill="#764ba2" opacity="0.4">V</text>
|
|
32
|
-
|
|
33
|
-
<!-- Result -->
|
|
34
|
-
<circle cx="50" cy="80" r="8"/>
|
|
35
|
-
<text x="50" y="84" text-anchor="middle" font-size="10" fill="white" font-weight="bold">✓</text>
|
|
36
|
-
</g>
|
|
37
|
-
|
|
38
|
-
<!-- Cost savings indicator -->
|
|
39
|
-
<g opacity="0.9">
|
|
40
|
-
<rect x="65" y="75" width="30" height="14" rx="3" fill="#10b981"/>
|
|
41
|
-
<text x="80" y="84" text-anchor="middle" font-size="9" fill="white" font-weight="bold">-85%</text>
|
|
42
|
-
</g>
|
|
43
|
-
</svg>
|
|
10
|
+
<path class="cls-1" d="M38.19,54.36c-4.15-4.15-4.15-10.87,0-15.02,4.15-4.15,10.87-4.15,15.02,0,4.15,4.15,4.15,10.87,0,15.02s-10.87,4.15-15.02,0Z"/>
|
|
11
|
+
<path class="cls-1" d="M63.4,91.76H28.7c-7.93,0-14.35-6.42-14.35-14.35h49.05v14.35Z"/>
|
|
12
|
+
<path class="cls-1" d="M14.35,77.41c-7.93,0-14.35-6.42-14.35-14.35V29.8h14.35v47.61Z"/>
|
|
13
|
+
<path class="cls-1" d="M28.36,0h34.7c7.93,0,14.35,6.42,14.35,14.35H28.36V0Z"/>
|
|
14
|
+
<path class="cls-1" d="M77.41,14.35c7.93,0,14.35,6.42,14.35,14.35v33.26h-14.35V14.35Z"/>
|
|
15
|
+
</svg>
|