@minded-ai/mindedjs 2.0.14 → 2.0.15
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.
- package/dist/nodes/addRpaNode.d.ts.map +1 -1
- package/dist/nodes/addRpaNode.js +12 -1
- package/dist/nodes/addRpaNode.js.map +1 -1
- package/dist/toolsLibrary/classifier.d.ts +12 -20
- package/dist/toolsLibrary/classifier.d.ts.map +1 -1
- package/dist/toolsLibrary/classifier.js +114 -74
- package/dist/toolsLibrary/classifier.js.map +1 -1
- package/package.json +1 -1
- package/src/nodes/addRpaNode.ts +13 -2
- package/src/toolsLibrary/classifier.ts +146 -87
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addRpaNode.d.ts","sourceRoot":"","sources":["../../src/nodes/addRpaNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,OAAO,EAAiB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"addRpaNode.d.ts","sourceRoot":"","sources":["../../src/nodes/addRpaNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,OAAO,EAAiB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAe,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOlD,KAAK,gBAAgB,GAAG;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IACxB,IAAI,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;CACvD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,6BAA6B,gBAAgB,kBAuL7E,CAAC"}
|
package/dist/nodes/addRpaNode.js
CHANGED
|
@@ -8,17 +8,28 @@ const playwright_1 = require("playwright");
|
|
|
8
8
|
const messages_1 = require("@langchain/core/messages");
|
|
9
9
|
const uuid_1 = require("uuid");
|
|
10
10
|
const rpaStepsExecutor_1 = require("./rpaStepsExecutor");
|
|
11
|
+
const executeBrowserTask_1 = require("../browserTask/executeBrowserTask");
|
|
12
|
+
const config_1 = require("../platform/config");
|
|
11
13
|
const addRpaNode = async ({ graph, node, agent, llm }) => {
|
|
12
14
|
const callback = async (state) => {
|
|
13
15
|
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
|
|
14
16
|
logger_1.logger.info({ msg: `[Node] Executing RPA node`, node: node.displayName, sessionId: state.sessionId });
|
|
15
17
|
let browser = null;
|
|
16
18
|
let page = null;
|
|
19
|
+
const { browserTaskMode } = (0, config_1.getConfig)();
|
|
20
|
+
const session = await (0, executeBrowserTask_1.createBrowserSession)({
|
|
21
|
+
sessionId: state.sessionId,
|
|
22
|
+
browserTaskMode,
|
|
23
|
+
});
|
|
24
|
+
if (!session.sessionId || !session.cdpUrl) {
|
|
25
|
+
throw new Error('Failed to create browser session: missing session details');
|
|
26
|
+
}
|
|
17
27
|
// Create tool call for RPA execution
|
|
18
28
|
const toolCallId = (0, uuid_1.v4)();
|
|
19
29
|
const aiMessageId = (0, uuid_1.v4)();
|
|
30
|
+
state.cdpUrl = session.cdpUrl;
|
|
20
31
|
// Get CDP URL from state
|
|
21
|
-
const cdpUrl =
|
|
32
|
+
const cdpUrl = session.cdpUrl;
|
|
22
33
|
const toolCall = {
|
|
23
34
|
id: toolCallId,
|
|
24
35
|
name: 'rpa-task',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addRpaNode.js","sourceRoot":"","sources":["../../src/nodes/addRpaNode.ts"],"names":[],"mappings":";;;AACA,sDAAwE;AAMxE,4CAAyC;AACzC,8CAAqD;AACrD,2CAAqD;AAErD,uDAAkE;AAClE,+BAAoC;AACpC,yDAAoD;
|
|
1
|
+
{"version":3,"file":"addRpaNode.js","sourceRoot":"","sources":["../../src/nodes/addRpaNode.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,15 +8,13 @@ export interface ClassDefinition {
|
|
|
8
8
|
export interface ClassifierConfig {
|
|
9
9
|
classes: ClassDefinition[];
|
|
10
10
|
systemPrompt?: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
defaultClass?: string;
|
|
14
|
-
defaultReason?: string;
|
|
11
|
+
defaultClass: string;
|
|
12
|
+
defaultReason: string;
|
|
15
13
|
}
|
|
16
14
|
export interface ClassificationResult {
|
|
17
15
|
class: string;
|
|
18
|
-
reason
|
|
19
|
-
confidence
|
|
16
|
+
reason: string;
|
|
17
|
+
confidence: number;
|
|
20
18
|
[key: string]: any;
|
|
21
19
|
}
|
|
22
20
|
/**
|
|
@@ -30,10 +28,10 @@ export declare function classify(content: string, config: ClassifierConfig, llm:
|
|
|
30
28
|
/**
|
|
31
29
|
* Create a classifier from a simple class list
|
|
32
30
|
* @param classes Array of class names or [name, description] tuples
|
|
33
|
-
* @param options
|
|
31
|
+
* @param options Configuration options (includeReason, defaultClass, defaultReason are required)
|
|
34
32
|
* @returns A configured classify function
|
|
35
33
|
*/
|
|
36
|
-
export declare function createClassifier(classes: string[] | [string, string][], options
|
|
34
|
+
export declare function createClassifier(classes: string[] | [string, string][], options: Omit<ClassifierConfig, 'classes'>): (content: string, llm: BaseLanguageModel) => Promise<ClassificationResult>;
|
|
37
35
|
export declare const schema: z.ZodObject<{
|
|
38
36
|
content: z.ZodString;
|
|
39
37
|
classes: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodTuple<[z.ZodString, z.ZodString], null>, z.ZodObject<{
|
|
@@ -47,32 +45,26 @@ export declare const schema: z.ZodObject<{
|
|
|
47
45
|
description: string;
|
|
48
46
|
}>]>, "many">>;
|
|
49
47
|
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
defaultClass: z.ZodOptional<z.ZodString>;
|
|
53
|
-
defaultReason: z.ZodOptional<z.ZodString>;
|
|
48
|
+
defaultClass: z.ZodString;
|
|
49
|
+
defaultReason: z.ZodString;
|
|
54
50
|
}, "strip", z.ZodTypeAny, {
|
|
55
51
|
content: string;
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
defaultClass: string;
|
|
53
|
+
defaultReason: string;
|
|
58
54
|
systemPrompt?: string | undefined;
|
|
59
55
|
classes?: (string | [string, string] | {
|
|
60
56
|
name: string;
|
|
61
57
|
description: string;
|
|
62
58
|
})[] | undefined;
|
|
63
|
-
defaultClass?: string | undefined;
|
|
64
|
-
defaultReason?: string | undefined;
|
|
65
59
|
}, {
|
|
66
60
|
content: string;
|
|
61
|
+
defaultClass: string;
|
|
62
|
+
defaultReason: string;
|
|
67
63
|
systemPrompt?: string | undefined;
|
|
68
64
|
classes?: (string | [string, string] | {
|
|
69
65
|
name: string;
|
|
70
66
|
description: string;
|
|
71
67
|
})[] | undefined;
|
|
72
|
-
outputFormat?: "text" | "json" | undefined;
|
|
73
|
-
includeReason?: boolean | undefined;
|
|
74
|
-
defaultClass?: string | undefined;
|
|
75
|
-
defaultReason?: string | undefined;
|
|
76
68
|
}>;
|
|
77
69
|
declare const classifierTool: Tool<typeof schema, any>;
|
|
78
70
|
export default classifierTool;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/toolsLibrary/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/toolsLibrary/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAG5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAYzE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA0BD;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4E/H;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,IAazG,SAAS,MAAM,EAAE,KAAK,iBAAiB,mCAChD;AAGD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBjB,CAAC;AAEH,QAAA,MAAM,cAAc,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,GAAG,CA2E5C,CAAC;AAEF,eAAe,cAAc,CAAC;AAG9B,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAsDjC"}
|
|
@@ -6,15 +6,29 @@ exports.createClassifier = createClassifier;
|
|
|
6
6
|
exports.multiClassify = multiClassify;
|
|
7
7
|
const zod_1 = require("zod");
|
|
8
8
|
const logger_1 = require("../utils/logger");
|
|
9
|
-
const output_parsers_1 = require("@langchain/core/output_parsers");
|
|
10
9
|
const messages_1 = require("@langchain/core/messages");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
function supportsStructuredOutput(llm) {
|
|
11
|
+
return 'withStructuredOutput' in llm && typeof llm.withStructuredOutput === 'function';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a dynamic Zod schema for classification result based on valid classes
|
|
15
|
+
*/
|
|
16
|
+
function createClassificationSchema(config) {
|
|
17
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
18
|
+
// Validate that we have at least one class (z.enum requires at least one value)
|
|
19
|
+
if (validClassNames.length === 0) {
|
|
20
|
+
throw new Error('Cannot create classification schema with empty classes array');
|
|
21
|
+
}
|
|
22
|
+
// Create a union type for valid class names
|
|
23
|
+
const classEnum = zod_1.z.enum(validClassNames);
|
|
24
|
+
// Build the schema - always include all fields
|
|
25
|
+
const schemaShape = {
|
|
26
|
+
class: classEnum.describe('The selected classification category'),
|
|
27
|
+
reason: zod_1.z.string().describe('Explanation for the classification'),
|
|
28
|
+
confidence: zod_1.z.number().min(0).max(1).describe('Confidence score between 0 and 1'),
|
|
29
|
+
};
|
|
30
|
+
return zod_1.z.object(schemaShape);
|
|
31
|
+
}
|
|
18
32
|
/**
|
|
19
33
|
* Generic classifier utility that can be used standalone
|
|
20
34
|
* @param content The content to classify
|
|
@@ -23,49 +37,73 @@ const DEFAULT_CONFIG = {
|
|
|
23
37
|
* @returns The classification result
|
|
24
38
|
*/
|
|
25
39
|
async function classify(content, config, llm) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
const MAX_RETRIES = 3;
|
|
41
|
+
let lastError = null;
|
|
42
|
+
// Validate that classes array is not empty
|
|
43
|
+
if (!config.classes || config.classes.length === 0) {
|
|
44
|
+
throw new Error('At least one class must be provided for classification');
|
|
45
|
+
}
|
|
46
|
+
// Check if LLM supports structured output upfront
|
|
47
|
+
if (!supportsStructuredOutput(llm)) {
|
|
48
|
+
throw new Error('LLM does not support structured output, which is required for classification');
|
|
49
|
+
}
|
|
50
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
// Build the classification prompt
|
|
53
|
+
const classesDescription = config.classes.map((c) => `${c.name}: ${c.description}`).join('\n');
|
|
54
|
+
const basePrompt = config.systemPrompt || 'You are a classifier. Your task is to classify the given content into one of the following categories:';
|
|
55
|
+
let prompt = `${basePrompt}\n\n${classesDescription}\n\n`;
|
|
56
|
+
// Add retry feedback if this is not the first attempt
|
|
57
|
+
if (attempt > 1) {
|
|
58
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
59
|
+
prompt += `\n⚠️ IMPORTANT: Your previous classification attempt failed. `;
|
|
60
|
+
prompt += `You MUST select ONLY from these valid classes:\n${validClassNames.join(', ')}\n\n`;
|
|
61
|
+
}
|
|
62
|
+
// Create dynamic schema based on valid classes
|
|
63
|
+
const classificationSchema = createClassificationSchema(config);
|
|
64
|
+
// Add content to classify to the prompt
|
|
65
|
+
prompt += `\n\nContent to classify:\n${content}`;
|
|
66
|
+
// Use structured output for guaranteed compliance
|
|
67
|
+
const structuredLLM = llm.withStructuredOutput(classificationSchema);
|
|
68
|
+
const messages = [new messages_1.SystemMessage(prompt)];
|
|
69
|
+
const result = (await structuredLLM.invoke(messages));
|
|
70
|
+
// The result is already validated by withStructuredOutput
|
|
71
|
+
logger_1.logger.debug({
|
|
72
|
+
message: 'Classification successful with structured output',
|
|
73
|
+
attempt,
|
|
74
|
+
class: result.class,
|
|
75
|
+
});
|
|
47
76
|
return result;
|
|
48
77
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
catch (err) {
|
|
79
|
+
lastError = err;
|
|
80
|
+
logger_1.logger.warn({
|
|
81
|
+
message: `Classification attempt ${attempt} failed`,
|
|
82
|
+
attempt,
|
|
83
|
+
maxRetries: MAX_RETRIES,
|
|
84
|
+
error: lastError.message,
|
|
85
|
+
});
|
|
53
86
|
}
|
|
54
87
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
88
|
+
// All retries exhausted - fallback to default
|
|
89
|
+
logger_1.logger.warn({
|
|
90
|
+
message: 'Classification failed after max retries, using default class',
|
|
91
|
+
maxRetries: MAX_RETRIES,
|
|
92
|
+
lastError: lastError === null || lastError === void 0 ? void 0 : lastError.message,
|
|
93
|
+
defaultClass: config.defaultClass,
|
|
94
|
+
defaultReason: config.defaultReason,
|
|
95
|
+
});
|
|
96
|
+
// Return default classification
|
|
97
|
+
return {
|
|
98
|
+
class: config.defaultClass,
|
|
99
|
+
reason: config.defaultReason,
|
|
100
|
+
confidence: 0,
|
|
101
|
+
};
|
|
64
102
|
}
|
|
65
103
|
/**
|
|
66
104
|
* Create a classifier from a simple class list
|
|
67
105
|
* @param classes Array of class names or [name, description] tuples
|
|
68
|
-
* @param options
|
|
106
|
+
* @param options Configuration options (includeReason, defaultClass, defaultReason are required)
|
|
69
107
|
* @returns A configured classify function
|
|
70
108
|
*/
|
|
71
109
|
function createClassifier(classes, options) {
|
|
@@ -96,19 +134,17 @@ exports.schema = zod_1.z.object({
|
|
|
96
134
|
.optional()
|
|
97
135
|
.describe('Classes to classify into. Can be strings, [name, description] tuples, or objects with name and description'),
|
|
98
136
|
systemPrompt: zod_1.z.string().optional().describe('Custom system prompt for classification'),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
defaultClass: zod_1.z.string().optional().describe('Default class to use if classification fails'),
|
|
102
|
-
defaultReason: zod_1.z.string().optional().describe('Default reason to use if classification fails'),
|
|
137
|
+
defaultClass: zod_1.z.string().describe('Default class to use if classification fails'),
|
|
138
|
+
defaultReason: zod_1.z.string().describe('Default reason to use if classification fails'),
|
|
103
139
|
});
|
|
104
140
|
const classifierTool = {
|
|
105
141
|
name: 'minded-classifier',
|
|
106
|
-
description: 'Classify content into predefined categories using AI. Supports custom classes
|
|
142
|
+
description: 'Classify content into predefined categories using AI. Supports custom classes and system prompts. Uses structured output for guaranteed schema compliance. Requires default fallback values.',
|
|
107
143
|
input: exports.schema,
|
|
108
144
|
isGlobal: false,
|
|
109
145
|
execute: async ({ input, state, agent }) => {
|
|
110
146
|
var _a, _b;
|
|
111
|
-
const { content, classes, systemPrompt,
|
|
147
|
+
const { content, classes, systemPrompt, defaultClass, defaultReason } = input;
|
|
112
148
|
logger_1.logger.info({
|
|
113
149
|
message: 'Classifying content',
|
|
114
150
|
sessionId: state.sessionId,
|
|
@@ -140,8 +176,6 @@ const classifierTool = {
|
|
|
140
176
|
const config = {
|
|
141
177
|
classes: classDefinitions,
|
|
142
178
|
systemPrompt,
|
|
143
|
-
includeReason,
|
|
144
|
-
outputFormat,
|
|
145
179
|
defaultClass,
|
|
146
180
|
defaultReason,
|
|
147
181
|
};
|
|
@@ -175,39 +209,45 @@ const classifierTool = {
|
|
|
175
209
|
exports.default = classifierTool;
|
|
176
210
|
// Export utility for multi-label classification
|
|
177
211
|
async function multiClassify(content, config, llm) {
|
|
178
|
-
const
|
|
179
|
-
|
|
212
|
+
const maxClasses = config.maxClasses || 3;
|
|
213
|
+
// Validate that classes array is not empty
|
|
214
|
+
if (!config.classes || config.classes.length === 0) {
|
|
215
|
+
throw new Error('At least one class must be provided for multi-classification');
|
|
216
|
+
}
|
|
217
|
+
// Check if LLM supports structured output
|
|
218
|
+
if (!supportsStructuredOutput(llm)) {
|
|
219
|
+
throw new Error('LLM does not support structured output, which is required for multi-classification');
|
|
220
|
+
}
|
|
180
221
|
try {
|
|
181
|
-
const classesDescription =
|
|
182
|
-
const
|
|
222
|
+
const classesDescription = config.classes.map((c) => `${c.name}: ${c.description}`).join('\n');
|
|
223
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
224
|
+
const basePrompt = config.systemPrompt || 'You are a multi-label classifier. Select all applicable categories for the given content:';
|
|
183
225
|
const prompt = `${basePrompt}\n\n${classesDescription}\n\n
|
|
184
|
-
|
|
185
|
-
[
|
|
186
|
-
{
|
|
187
|
-
"class": "<class name>",
|
|
188
|
-
${mergedConfig.includeReason ? '"reason": "<explanation>",' : ''}
|
|
189
|
-
"confidence": <confidence score between 0 and 1>
|
|
190
|
-
},
|
|
191
|
-
...
|
|
192
|
-
]
|
|
193
|
-
Return JSON and nothing more.
|
|
226
|
+
Select up to ${maxClasses} classifications, ordered by relevance.
|
|
194
227
|
|
|
195
228
|
Content to classify:
|
|
196
229
|
${content}`;
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
230
|
+
// Create schema for array of classifications
|
|
231
|
+
const classEnum = zod_1.z.enum(validClassNames);
|
|
232
|
+
const multiClassSchema = zod_1.z
|
|
233
|
+
.array(zod_1.z.object({
|
|
234
|
+
class: classEnum.describe('The selected classification category'),
|
|
235
|
+
reason: zod_1.z.string().describe('Explanation for the classification'),
|
|
236
|
+
confidence: zod_1.z.number().min(0).max(1).describe('Confidence score between 0 and 1'),
|
|
237
|
+
}))
|
|
238
|
+
.min(1)
|
|
239
|
+
.max(maxClasses);
|
|
240
|
+
const structuredLLM = llm.withStructuredOutput(multiClassSchema);
|
|
241
|
+
const messages = [new messages_1.SystemMessage(prompt)];
|
|
242
|
+
const result = (await structuredLLM.invoke(messages));
|
|
243
|
+
return result;
|
|
204
244
|
}
|
|
205
245
|
catch (err) {
|
|
206
246
|
logger_1.logger.error({ message: 'Multi-classification failed', err });
|
|
207
247
|
return [
|
|
208
248
|
{
|
|
209
|
-
class:
|
|
210
|
-
reason:
|
|
249
|
+
class: config.defaultClass,
|
|
250
|
+
reason: config.defaultReason,
|
|
211
251
|
confidence: 0,
|
|
212
252
|
},
|
|
213
253
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/toolsLibrary/classifier.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/toolsLibrary/classifier.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/nodes/addRpaNode.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { LLMProviders } from '../types/LLM.types';
|
|
|
12
12
|
import { AIMessage, ToolMessage } from '@langchain/core/messages';
|
|
13
13
|
import { v4 as uuidv4 } from 'uuid';
|
|
14
14
|
import { executeRpaStep } from './rpaStepsExecutor';
|
|
15
|
+
import { createBrowserSession } from '../browserTask/executeBrowserTask';
|
|
16
|
+
import { getConfig } from '../platform/config';
|
|
15
17
|
|
|
16
18
|
type AddRpaNodeParams = {
|
|
17
19
|
graph: PreCompiledGraph;
|
|
@@ -29,13 +31,22 @@ export const addRpaNode = async ({ graph, node, agent, llm }: AddRpaNodeParams)
|
|
|
29
31
|
|
|
30
32
|
let browser: Browser | null = null;
|
|
31
33
|
let page: Page | null = null;
|
|
34
|
+
const { browserTaskMode } = getConfig();
|
|
32
35
|
|
|
36
|
+
const session = await createBrowserSession({
|
|
37
|
+
sessionId: state.sessionId,
|
|
38
|
+
browserTaskMode,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!session.sessionId || !session.cdpUrl) {
|
|
42
|
+
throw new Error('Failed to create browser session: missing session details');
|
|
43
|
+
}
|
|
33
44
|
// Create tool call for RPA execution
|
|
34
45
|
const toolCallId = uuidv4();
|
|
35
46
|
const aiMessageId = uuidv4();
|
|
36
|
-
|
|
47
|
+
state.cdpUrl = session.cdpUrl;
|
|
37
48
|
// Get CDP URL from state
|
|
38
|
-
const cdpUrl =
|
|
49
|
+
const cdpUrl = session.cdpUrl;
|
|
39
50
|
|
|
40
51
|
const toolCall = {
|
|
41
52
|
id: toolCallId,
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { Tool } from '../types/Tools.types';
|
|
3
3
|
import { logger } from '../utils/logger';
|
|
4
|
-
import { JsonOutputParser } from '@langchain/core/output_parsers';
|
|
5
4
|
import { SystemMessage } from '@langchain/core/messages';
|
|
6
5
|
import { BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
7
6
|
|
|
7
|
+
// Type guard for checking if LLM supports structured output
|
|
8
|
+
interface StructuredOutputLLM extends BaseLanguageModel {
|
|
9
|
+
withStructuredOutput<T extends z.ZodType>(schema: T): BaseLanguageModel;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function supportsStructuredOutput(llm: BaseLanguageModel): llm is StructuredOutputLLM {
|
|
13
|
+
return 'withStructuredOutput' in llm && typeof (llm as any).withStructuredOutput === 'function';
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
// Type definitions for classifier configuration
|
|
9
17
|
export interface ClassDefinition {
|
|
10
18
|
name: string;
|
|
@@ -14,26 +22,40 @@ export interface ClassDefinition {
|
|
|
14
22
|
export interface ClassifierConfig {
|
|
15
23
|
classes: ClassDefinition[];
|
|
16
24
|
systemPrompt?: string;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
defaultClass?: string;
|
|
20
|
-
defaultReason?: string;
|
|
25
|
+
defaultClass: string;
|
|
26
|
+
defaultReason: string;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
export interface ClassificationResult {
|
|
24
30
|
class: string;
|
|
25
|
-
reason
|
|
26
|
-
confidence
|
|
31
|
+
reason: string;
|
|
32
|
+
confidence: number;
|
|
27
33
|
[key: string]: any; // Allow additional fields
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Create a dynamic Zod schema for classification result based on valid classes
|
|
38
|
+
*/
|
|
39
|
+
function createClassificationSchema(config: ClassifierConfig): z.ZodSchema {
|
|
40
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
41
|
+
|
|
42
|
+
// Validate that we have at least one class (z.enum requires at least one value)
|
|
43
|
+
if (validClassNames.length === 0) {
|
|
44
|
+
throw new Error('Cannot create classification schema with empty classes array');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create a union type for valid class names
|
|
48
|
+
const classEnum = z.enum(validClassNames as [string, ...string[]]);
|
|
49
|
+
|
|
50
|
+
// Build the schema - always include all fields
|
|
51
|
+
const schemaShape: Record<string, z.ZodTypeAny> = {
|
|
52
|
+
class: classEnum.describe('The selected classification category'),
|
|
53
|
+
reason: z.string().describe('Explanation for the classification'),
|
|
54
|
+
confidence: z.number().min(0).max(1).describe('Confidence score between 0 and 1'),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return z.object(schemaShape);
|
|
58
|
+
}
|
|
37
59
|
|
|
38
60
|
/**
|
|
39
61
|
* Generic classifier utility that can be used standalone
|
|
@@ -43,58 +65,90 @@ const DEFAULT_CONFIG: Partial<ClassifierConfig> = {
|
|
|
43
65
|
* @returns The classification result
|
|
44
66
|
*/
|
|
45
67
|
export async function classify(content: string, config: ClassifierConfig, llm: BaseLanguageModel): Promise<ClassificationResult> {
|
|
46
|
-
const
|
|
68
|
+
const MAX_RETRIES = 3;
|
|
69
|
+
let lastError: Error | null = null;
|
|
47
70
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const basePrompt =
|
|
53
|
-
mergedConfig.systemPrompt || 'You are a classifier. Your task is to classify the given content into one of the following categories:';
|
|
54
|
-
|
|
55
|
-
let prompt = `${basePrompt}\n\n${classesDescription}\n\n`;
|
|
56
|
-
|
|
57
|
-
if (mergedConfig.outputFormat === 'json') {
|
|
58
|
-
prompt += `You should output the result in the following JSON format: {
|
|
59
|
-
"class": "<selected class name>",
|
|
60
|
-
${mergedConfig.includeReason ? '"reason": "<explanation for the classification>",' : ''}
|
|
61
|
-
"confidence": <confidence score between 0 and 1>
|
|
62
|
-
}.\nReturn JSON and nothing more.`;
|
|
63
|
-
} else {
|
|
64
|
-
prompt += 'Return only the class name.';
|
|
65
|
-
}
|
|
71
|
+
// Validate that classes array is not empty
|
|
72
|
+
if (!config.classes || config.classes.length === 0) {
|
|
73
|
+
throw new Error('At least one class must be provided for classification');
|
|
74
|
+
}
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const parser = new JsonOutputParser();
|
|
72
|
-
const result = await llm.pipe(parser).invoke([new SystemMessage(prompt)]);
|
|
73
|
-
return result as ClassificationResult;
|
|
74
|
-
} else {
|
|
75
|
-
const result = await llm.invoke([new SystemMessage(prompt)]);
|
|
76
|
-
const classText = typeof result.content === 'string' ? result.content.trim() : '';
|
|
77
|
-
return { class: classText };
|
|
78
|
-
}
|
|
79
|
-
} catch (err) {
|
|
80
|
-
logger.error({ message: 'Classification failed, using default', err });
|
|
76
|
+
// Check if LLM supports structured output upfront
|
|
77
|
+
if (!supportsStructuredOutput(llm)) {
|
|
78
|
+
throw new Error('LLM does not support structured output, which is required for classification');
|
|
79
|
+
}
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
82
|
+
try {
|
|
83
|
+
// Build the classification prompt
|
|
84
|
+
const classesDescription = config.classes.map((c) => `${c.name}: ${c.description}`).join('\n');
|
|
85
|
+
|
|
86
|
+
const basePrompt =
|
|
87
|
+
config.systemPrompt || 'You are a classifier. Your task is to classify the given content into one of the following categories:';
|
|
88
|
+
|
|
89
|
+
let prompt = `${basePrompt}\n\n${classesDescription}\n\n`;
|
|
90
|
+
|
|
91
|
+
// Add retry feedback if this is not the first attempt
|
|
92
|
+
if (attempt > 1) {
|
|
93
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
94
|
+
prompt += `\n⚠️ IMPORTANT: Your previous classification attempt failed. `;
|
|
95
|
+
prompt += `You MUST select ONLY from these valid classes:\n${validClassNames.join(', ')}\n\n`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Create dynamic schema based on valid classes
|
|
99
|
+
const classificationSchema = createClassificationSchema(config);
|
|
100
|
+
|
|
101
|
+
// Add content to classify to the prompt
|
|
102
|
+
prompt += `\n\nContent to classify:\n${content}`;
|
|
103
|
+
|
|
104
|
+
// Use structured output for guaranteed compliance
|
|
105
|
+
const structuredLLM = llm.withStructuredOutput(classificationSchema);
|
|
106
|
+
const messages = [new SystemMessage(prompt)];
|
|
107
|
+
const result = (await structuredLLM.invoke(messages)) as ClassificationResult;
|
|
108
|
+
|
|
109
|
+
// The result is already validated by withStructuredOutput
|
|
110
|
+
logger.debug({
|
|
111
|
+
message: 'Classification successful with structured output',
|
|
112
|
+
attempt,
|
|
113
|
+
class: result.class,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return result;
|
|
117
|
+
} catch (err) {
|
|
118
|
+
lastError = err as Error;
|
|
119
|
+
logger.warn({
|
|
120
|
+
message: `Classification attempt ${attempt} failed`,
|
|
121
|
+
attempt,
|
|
122
|
+
maxRetries: MAX_RETRIES,
|
|
123
|
+
error: lastError.message,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
88
126
|
}
|
|
127
|
+
|
|
128
|
+
// All retries exhausted - fallback to default
|
|
129
|
+
logger.warn({
|
|
130
|
+
message: 'Classification failed after max retries, using default class',
|
|
131
|
+
maxRetries: MAX_RETRIES,
|
|
132
|
+
lastError: lastError?.message,
|
|
133
|
+
defaultClass: config.defaultClass,
|
|
134
|
+
defaultReason: config.defaultReason,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Return default classification
|
|
138
|
+
return {
|
|
139
|
+
class: config.defaultClass,
|
|
140
|
+
reason: config.defaultReason,
|
|
141
|
+
confidence: 0,
|
|
142
|
+
};
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
/**
|
|
92
146
|
* Create a classifier from a simple class list
|
|
93
147
|
* @param classes Array of class names or [name, description] tuples
|
|
94
|
-
* @param options
|
|
148
|
+
* @param options Configuration options (includeReason, defaultClass, defaultReason are required)
|
|
95
149
|
* @returns A configured classify function
|
|
96
150
|
*/
|
|
97
|
-
export function createClassifier(classes: string[] | [string, string][], options
|
|
151
|
+
export function createClassifier(classes: string[] | [string, string][], options: Omit<ClassifierConfig, 'classes'>) {
|
|
98
152
|
const classDefinitions: ClassDefinition[] = classes.map((c) => {
|
|
99
153
|
if (typeof c === 'string') {
|
|
100
154
|
return { name: c, description: '' };
|
|
@@ -127,20 +181,18 @@ export const schema = z.object({
|
|
|
127
181
|
.optional()
|
|
128
182
|
.describe('Classes to classify into. Can be strings, [name, description] tuples, or objects with name and description'),
|
|
129
183
|
systemPrompt: z.string().optional().describe('Custom system prompt for classification'),
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
defaultClass: z.string().optional().describe('Default class to use if classification fails'),
|
|
133
|
-
defaultReason: z.string().optional().describe('Default reason to use if classification fails'),
|
|
184
|
+
defaultClass: z.string().describe('Default class to use if classification fails'),
|
|
185
|
+
defaultReason: z.string().describe('Default reason to use if classification fails'),
|
|
134
186
|
});
|
|
135
187
|
|
|
136
188
|
const classifierTool: Tool<typeof schema, any> = {
|
|
137
189
|
name: 'minded-classifier',
|
|
138
190
|
description:
|
|
139
|
-
'Classify content into predefined categories using AI. Supports custom classes
|
|
191
|
+
'Classify content into predefined categories using AI. Supports custom classes and system prompts. Uses structured output for guaranteed schema compliance. Requires default fallback values.',
|
|
140
192
|
input: schema,
|
|
141
193
|
isGlobal: false,
|
|
142
194
|
execute: async ({ input, state, agent }) => {
|
|
143
|
-
const { content, classes, systemPrompt,
|
|
195
|
+
const { content, classes, systemPrompt, defaultClass, defaultReason } = input;
|
|
144
196
|
|
|
145
197
|
logger.info({
|
|
146
198
|
message: 'Classifying content',
|
|
@@ -175,8 +227,6 @@ const classifierTool: Tool<typeof schema, any> = {
|
|
|
175
227
|
const config: ClassifierConfig = {
|
|
176
228
|
classes: classDefinitions,
|
|
177
229
|
systemPrompt,
|
|
178
|
-
includeReason,
|
|
179
|
-
outputFormat,
|
|
180
230
|
defaultClass,
|
|
181
231
|
defaultReason,
|
|
182
232
|
};
|
|
@@ -220,46 +270,55 @@ export async function multiClassify(
|
|
|
220
270
|
config: ClassifierConfig & { maxClasses?: number },
|
|
221
271
|
llm: BaseLanguageModel,
|
|
222
272
|
): Promise<ClassificationResult[]> {
|
|
223
|
-
const
|
|
224
|
-
|
|
273
|
+
const maxClasses = config.maxClasses || 3;
|
|
274
|
+
|
|
275
|
+
// Validate that classes array is not empty
|
|
276
|
+
if (!config.classes || config.classes.length === 0) {
|
|
277
|
+
throw new Error('At least one class must be provided for multi-classification');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Check if LLM supports structured output
|
|
281
|
+
if (!supportsStructuredOutput(llm)) {
|
|
282
|
+
throw new Error('LLM does not support structured output, which is required for multi-classification');
|
|
283
|
+
}
|
|
225
284
|
|
|
226
285
|
try {
|
|
227
|
-
const classesDescription =
|
|
286
|
+
const classesDescription = config.classes.map((c) => `${c.name}: ${c.description}`).join('\n');
|
|
287
|
+
const validClassNames = config.classes.map((c) => c.name);
|
|
228
288
|
|
|
229
|
-
const basePrompt =
|
|
230
|
-
mergedConfig.systemPrompt || 'You are a multi-label classifier. Select all applicable categories for the given content:';
|
|
289
|
+
const basePrompt = config.systemPrompt || 'You are a multi-label classifier. Select all applicable categories for the given content:';
|
|
231
290
|
|
|
232
291
|
const prompt = `${basePrompt}\n\n${classesDescription}\n\n
|
|
233
|
-
|
|
234
|
-
[
|
|
235
|
-
{
|
|
236
|
-
"class": "<class name>",
|
|
237
|
-
${mergedConfig.includeReason ? '"reason": "<explanation>",' : ''}
|
|
238
|
-
"confidence": <confidence score between 0 and 1>
|
|
239
|
-
},
|
|
240
|
-
...
|
|
241
|
-
]
|
|
242
|
-
Return JSON and nothing more.
|
|
292
|
+
Select up to ${maxClasses} classifications, ordered by relevance.
|
|
243
293
|
|
|
244
294
|
Content to classify:
|
|
245
295
|
${content}`;
|
|
246
296
|
|
|
247
|
-
|
|
248
|
-
const
|
|
297
|
+
// Create schema for array of classifications
|
|
298
|
+
const classEnum = z.enum(validClassNames as [string, ...string[]]);
|
|
299
|
+
const multiClassSchema = z
|
|
300
|
+
.array(
|
|
301
|
+
z.object({
|
|
302
|
+
class: classEnum.describe('The selected classification category'),
|
|
303
|
+
reason: z.string().describe('Explanation for the classification'),
|
|
304
|
+
confidence: z.number().min(0).max(1).describe('Confidence score between 0 and 1'),
|
|
305
|
+
}),
|
|
306
|
+
)
|
|
307
|
+
.min(1)
|
|
308
|
+
.max(maxClasses);
|
|
249
309
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
310
|
+
const structuredLLM = llm.withStructuredOutput(multiClassSchema);
|
|
311
|
+
const messages = [new SystemMessage(prompt)];
|
|
312
|
+
const result = (await structuredLLM.invoke(messages)) as ClassificationResult[];
|
|
253
313
|
|
|
254
|
-
|
|
255
|
-
return [result as ClassificationResult];
|
|
314
|
+
return result;
|
|
256
315
|
} catch (err) {
|
|
257
316
|
logger.error({ message: 'Multi-classification failed', err });
|
|
258
317
|
|
|
259
318
|
return [
|
|
260
319
|
{
|
|
261
|
-
class:
|
|
262
|
-
reason:
|
|
320
|
+
class: config.defaultClass,
|
|
321
|
+
reason: config.defaultReason,
|
|
263
322
|
confidence: 0,
|
|
264
323
|
},
|
|
265
324
|
];
|