llmjs2 1.3.8 → 1.6.1

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.
Files changed (49) hide show
  1. package/README.md +31 -476
  2. package/chain/AGENT_STEP_README.md +102 -0
  3. package/chain/README.md +257 -0
  4. package/chain/WORKFLOW_README.md +85 -0
  5. package/chain/agent-step-example.js +232 -0
  6. package/chain/docs/AGENT.md +126 -0
  7. package/chain/docs/GRAPH.md +490 -0
  8. package/chain/examples.js +314 -0
  9. package/chain/index.js +31 -0
  10. package/chain/lib/agent.js +338 -0
  11. package/chain/lib/flow/agent-step.js +119 -0
  12. package/chain/lib/flow/edge.js +24 -0
  13. package/chain/lib/flow/flow.js +76 -0
  14. package/chain/lib/flow/graph.js +331 -0
  15. package/chain/lib/flow/index.js +7 -0
  16. package/chain/lib/flow/step.js +63 -0
  17. package/chain/lib/memory/in-memory.js +117 -0
  18. package/chain/lib/memory/index.js +36 -0
  19. package/chain/lib/memory/lance-memory.js +225 -0
  20. package/chain/lib/memory/sqlite-memory.js +309 -0
  21. package/chain/simple-agent-step-example.js +168 -0
  22. package/chain/workflow-example-usage.js +70 -0
  23. package/chain/workflow-example.json +59 -0
  24. package/core/README.md +485 -0
  25. package/core/cli.js +275 -0
  26. package/core/docs/BASIC_USAGE.md +62 -0
  27. package/core/docs/CLI.md +104 -0
  28. package/{docs → core/docs}/GET_STARTED.md +129 -129
  29. package/{docs → core/docs}/GUARDRAILS_GUIDE.md +734 -734
  30. package/{docs → core/docs}/README.md +47 -47
  31. package/core/docs/ROUTER_GUIDE.md +199 -0
  32. package/{docs → core/docs}/SERVER_MODE.md +358 -350
  33. package/core/index.js +115 -0
  34. package/{providers → core/providers}/ollama.js +14 -6
  35. package/{providers → core/providers}/openai.js +14 -6
  36. package/{providers → core/providers}/openrouter.js +14 -6
  37. package/core/router.js +252 -0
  38. package/{server.js → core/server.js} +15 -5
  39. package/package.json +43 -27
  40. package/cli.js +0 -195
  41. package/docs/BASIC_USAGE.md +0 -296
  42. package/docs/CLI.md +0 -455
  43. package/docs/ROUTER_GUIDE.md +0 -402
  44. package/index.js +0 -265
  45. package/router.js +0 -273
  46. package/test-completion.js +0 -99
  47. package/test.js +0 -246
  48. /package/{config.yaml → core/config.yaml} +0 -0
  49. /package/{logger.js → core/logger.js} +0 -0
@@ -0,0 +1,490 @@
1
+ # Graph & Flow Usage Guide
2
+
3
+ The Graph class enables complex execution flows with branching and parallelism using a fluent API or JSON configuration.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Step Class](#step-class)
8
+ - [Graph Class](#graph-class)
9
+ - [Basic Usage](#basic-graph-usage)
10
+ - [JSON Configuration](#json-configuration)
11
+ - [Conditional Edges](#conditional-edges)
12
+ - [Parallel Execution](#parallel-execution)
13
+ - [Complex Workflows](#complex-workflows)
14
+
15
+ ## Step Classes
16
+
17
+ ### Basic Step
18
+
19
+ The Step class represents a node in the graph that executes a function with the current context.
20
+
21
+ ```javascript
22
+ const { Step } = require('llmjs-chain');
23
+
24
+ // Create a step with custom execute function
25
+ const plusStep = new Step({
26
+ name: 'plus',
27
+ execute: async (context) => {
28
+ const a = context.a;
29
+ const b = context.b;
30
+ return a + b;
31
+ }
32
+ });
33
+
34
+ // Execute the step directly
35
+ const result = await plusStep.run({ a: 5, b: 3 });
36
+ console.log(result); // 8
37
+ ```
38
+
39
+ ### AgentStep
40
+
41
+ The AgentStep class integrates AI agents directly into workflows as specialized steps.
42
+
43
+ ```javascript
44
+ const { Agent, AgentStep, Graph } = require('llmjs-chain');
45
+
46
+ // Create an AI agent
47
+ const analyzerAgent = new Agent({
48
+ instruction: 'You are a data analyst. Analyze provided data and provide insights.',
49
+ tools: [
50
+ {
51
+ name: 'calculate_average',
52
+ description: 'Calculate average of numbers',
53
+ parameters: { numbers: { type: 'array', required: true } },
54
+ execute: async ({ numbers }) => {
55
+ const avg = numbers.reduce((a, b) => a + b, 0) / numbers.length;
56
+ return `Average: ${avg}`;
57
+ }
58
+ }
59
+ ]
60
+ });
61
+
62
+ // Create agent step with custom input/output mapping
63
+ const analyzeStep = new AgentStep({
64
+ name: 'analyze-data',
65
+ agent: analyzerAgent,
66
+ inputMapper: (context) => {
67
+ const data = context.previousStep?.data || [];
68
+ return `Analyze this data: ${JSON.stringify(data)}`;
69
+ },
70
+ outputMapper: (response, context) => ({
71
+ analysis: response,
72
+ analyzedAt: new Date().toISOString(),
73
+ dataSize: context.previousStep?.data?.length || 0
74
+ })
75
+ });
76
+
77
+ // Use in workflow
78
+ const workflow = new Graph({ name: 'ai-workflow' })
79
+ .step(analyzeStep)
80
+ .compile();
81
+
82
+ const result = await workflow.run({ previousStep: { data: [1, 2, 3, 4, 5] } });
83
+ ```
84
+
85
+ #### AgentStep Configuration Options
86
+
87
+ - **`name`**: Step identifier in the workflow
88
+ - **`agent`**: AI Agent instance to execute
89
+ - **`inputMapper`**: Function or template to transform workflow context to agent input
90
+ - **`outputMapper`**: Function to transform agent response to workflow context
91
+
92
+ #### Input Mapping Examples
93
+
94
+ ```javascript
95
+ // Function mapper
96
+ inputMapper: (context) => `Process: ${context.data.join(', ')}`
97
+
98
+ // Template mapper (simple string interpolation)
99
+ inputMapper: 'Analyze data: {{data}} from step: {{stepName}}'
100
+
101
+ // Default: converts entire context to readable string
102
+ ```
103
+
104
+ #### Output Mapping Examples
105
+
106
+ ```javascript
107
+ // Custom output transformation
108
+ outputMapper: (agentResponse, context) => ({
109
+ result: agentResponse,
110
+ confidence: 0.95,
111
+ processingTime: Date.now() - context.startTime
112
+ })
113
+
114
+ // Default: returns { response, agent, timestamp }
115
+ ```
116
+
117
+ ## Graph Class
118
+
119
+ The Graph class enables complex execution flows with branching and parallelism using a fluent API.
120
+
121
+ ### Basic Graph Usage
122
+
123
+ ```javascript
124
+ const { Graph, Step } = require('llmjs-chain');
125
+
126
+ // Create steps
127
+ const validateStep = new Step({
128
+ name: 'validate',
129
+ execute: async (context) => {
130
+ if (!context.data) throw new Error('No data provided');
131
+ return { validated: true, data: context.data };
132
+ }
133
+ });
134
+
135
+ const processStep = new Step({
136
+ name: 'process',
137
+ execute: async (context) => {
138
+ const processed = context.validate.data.map(item => item * 2);
139
+ return { processed };
140
+ }
141
+ });
142
+
143
+ const saveStep = new Step({
144
+ name: 'save',
145
+ execute: async (context) => {
146
+ console.log('Saving:', context.process.processed);
147
+ return { saved: true };
148
+ }
149
+ });
150
+
151
+ // Create and configure graph using fluent API
152
+ const flow = new Graph({ name: 'data-processing-pipeline' })
153
+ .step(validateStep) // Add single step
154
+ .step(processStep, saveStep) // Add multiple steps
155
+ .edge(validateStep, processStep) // Connect steps
156
+ .edge(processStep, saveStep)
157
+ .compile();
158
+
159
+ // Execute the graph
160
+ const result = await flow.run({ data: [1, 2, 3, 4] });
161
+ console.log('Graph execution result:', result);
162
+ ```
163
+
164
+ ### JSON Configuration
165
+
166
+ Load graphs from JSON configuration for dynamic workflow definition:
167
+
168
+ ```javascript
169
+ const { Graph } = require('llmjs-chain');
170
+
171
+ // Define workflow as JSON
172
+ const workflowConfig = {
173
+ name: 'data-processing-pipeline',
174
+ steps: [
175
+ {
176
+ name: 'validate',
177
+ execute: `async (context) => {
178
+ if (!context.data) throw new Error('No data provided');
179
+ return { validated: true, data: context.data };
180
+ }`
181
+ },
182
+ {
183
+ name: 'process',
184
+ execute: `async (context) => {
185
+ const processed = context.validate.data.map(item => item * 2);
186
+ return { processed };
187
+ }`
188
+ },
189
+ {
190
+ name: 'save',
191
+ execute: `async (context) => {
192
+ console.log('Saving:', context.process.processed);
193
+ return { saved: true };
194
+ }`
195
+ }
196
+ ],
197
+ edges: [
198
+ { from: 'validate', to: 'process' },
199
+ { from: 'process', to: 'save' }
200
+ ]
201
+ };
202
+
203
+ // Load and compile graph from JSON
204
+ const flow = Graph.load(workflowConfig).compile();
205
+
206
+ // Execute the loaded graph
207
+ const result = await flow.run({ data: [1, 2, 3, 4] });
208
+ console.log('Loaded graph result:', result);
209
+ ```
210
+
211
+ ### Conditional Edges in JSON
212
+
213
+ ```javascript
214
+ const conditionalConfig = {
215
+ name: 'decision-workflow',
216
+ steps: [
217
+ {
218
+ name: 'evaluate',
219
+ execute: `async (context) => {
220
+ return { score: context.input, approved: context.input > 70 };
221
+ }`
222
+ },
223
+ {
224
+ name: 'approve',
225
+ execute: `async (context) => ({ status: 'approved', message: 'High score!' })`
226
+ },
227
+ {
228
+ name: 'reject',
229
+ execute: `async (context) => ({ status: 'rejected', message: 'Try again' })`
230
+ }
231
+ ],
232
+ edges: [
233
+ { from: 'evaluate', to: 'approve', condition: '(result) => result.approved' },
234
+ { from: 'evaluate', to: 'reject', condition: '(result) => !result.approved' }
235
+ ]
236
+ };
237
+
238
+ const conditionalFlow = Graph.load(conditionalConfig).compile();
239
+ const result = await conditionalFlow.run({ input: 85 }); // Goes to 'approve'
240
+ ```
241
+
242
+ ### Parallel Execution
243
+
244
+ Connect a single step to multiple steps for parallel execution:
245
+
246
+ ```javascript
247
+ const { Graph, Step } = require('llmjs-chain');
248
+
249
+ const startStep = new Step({
250
+ name: 'start',
251
+ execute: async (context) => ({ started: true })
252
+ });
253
+
254
+ const taskA = new Step({
255
+ name: 'taskA',
256
+ execute: async (context) => {
257
+ await new Promise(resolve => setTimeout(resolve, 100));
258
+ return { result: 'Task A completed' };
259
+ }
260
+ });
261
+
262
+ const taskB = new Step({
263
+ name: 'taskB',
264
+ execute: async (context) => {
265
+ await new Promise(resolve => setTimeout(resolve, 150));
266
+ return { result: 'Task B completed' };
267
+ }
268
+ });
269
+
270
+ const combineStep = new Step({
271
+ name: 'combine',
272
+ execute: async (context) => ({
273
+ final: [context.taskA.result, context.taskB.result]
274
+ })
275
+ });
276
+
277
+ // Use array syntax for parallel execution
278
+ const parallelFlow = new Graph({ name: 'parallel-workflow' })
279
+ .step(startStep, taskA, taskB, combineStep)
280
+ .edge(startStep, [taskA, taskB]) // Both taskA and taskB run in parallel
281
+ .edge(taskA, combineStep)
282
+ .edge(taskB, combineStep)
283
+ .compile();
284
+
285
+ const result = await parallelFlow.run();
286
+ console.log('Parallel result:', result);
287
+ ```
288
+
289
+ ### Conditional Edges
290
+
291
+ Edges can include conditions to control execution flow using the `{when: condition}` syntax:
292
+
293
+ ```javascript
294
+ const { Graph, Step } = require('llmjs-chain');
295
+
296
+ // Create decision step
297
+ const checkValue = new Step({
298
+ name: 'check',
299
+ execute: async (context) => {
300
+ const isLarge = context.value > 100;
301
+ return { value: context.value, isLarge };
302
+ }
303
+ });
304
+
305
+ const largeProcessor = new Step({
306
+ name: 'large',
307
+ execute: async (context) => {
308
+ return { result: `Large value: ${context.check.value}`, category: 'large' };
309
+ }
310
+ });
311
+
312
+ const smallProcessor = new Step({
313
+ name: 'small',
314
+ execute: async (context) => {
315
+ return { result: `Small value: ${context.check.value}`, category: 'small' };
316
+ }
317
+ });
318
+
319
+ // Create graph with conditional edges
320
+ const flow = new Graph({ name: 'conditional-workflow' })
321
+ .step(checkValue, largeProcessor, smallProcessor)
322
+ .edge(checkValue, largeProcessor, { when: (result, context) => result.isLarge })
323
+ .edge(checkValue, smallProcessor, { when: (result, context) => !result.isLarge })
324
+ .compile();
325
+
326
+ // Execute - will follow different paths based on input value
327
+ const result1 = await flow.run({ value: 150 }); // Goes to 'large'
328
+ console.log('Large value result:', result1);
329
+
330
+ const result2 = await flow.run({ value: 50 }); // Goes to 'small'
331
+ console.log('Small value result:', result2);
332
+ ```
333
+
334
+ ### Complex Workflows
335
+
336
+ Create sophisticated workflows with multiple paths, loops, and integrations:
337
+
338
+ ```javascript
339
+ const { Graph, Step, Agent } = require('llmjs-chain');
340
+
341
+ // Create a graph that combines AI analysis with processing steps
342
+ const analyzeStep = new Step({
343
+ name: 'analyze',
344
+ execute: async (context) => {
345
+ const agent = new Agent({
346
+ instruction: 'Analyze the provided data and provide insights.',
347
+ model: 'openai/gpt-4'
348
+ });
349
+
350
+ const analysis = await agent.generate(
351
+ `Analyze this data: ${JSON.stringify(context.data)}`
352
+ );
353
+
354
+ return { analysis, status: 'completed' };
355
+ }
356
+ });
357
+
358
+ const validateStep = new Step({
359
+ name: 'validate',
360
+ execute: async (context) => {
361
+ // Validation logic
362
+ return { valid: true, data: context.data };
363
+ }
364
+ });
365
+
366
+ const reportStep = new Step({
367
+ name: 'report',
368
+ execute: async (context) => {
369
+ return {
370
+ report: `Analysis Report:\n${context.analyze.analysis}\nData validated: ${context.validate.valid}`
371
+ };
372
+ }
373
+ });
374
+
375
+ const errorStep = new Step({
376
+ name: 'error',
377
+ execute: async (context) => {
378
+ console.error('Analysis failed');
379
+ return { error: 'Analysis failed' };
380
+ }
381
+ });
382
+
383
+ // Create complex workflow with conditional branching
384
+ const workflow = new Graph({ name: 'ai-analysis-workflow' })
385
+ .step(validateStep, analyzeStep, reportStep, errorStep)
386
+ .edge(validateStep, analyzeStep)
387
+ .edge(analyzeStep, reportStep, { when: (result) => result.status === 'completed' })
388
+ .edge(analyzeStep, errorStep, { when: (result) => result.status === 'failed' })
389
+ .compile();
390
+
391
+ // Execute the workflow
392
+ const result = await workflow.run({
393
+ data: { metrics: [1, 2, 3], status: 'active' }
394
+ });
395
+
396
+ console.log('Workflow result:', result);
397
+ ```
398
+
399
+ ## Integration Examples
400
+
401
+ ### Agent as a Graph Step
402
+
403
+ Integrate AI agents directly into your workflow as steps:
404
+
405
+ ```javascript
406
+ const { Agent, Graph, Step } = require('llmjs-chain');
407
+
408
+ // Create an AI agent
409
+ const analyzerAgent = new Agent({
410
+ instruction: 'You are a data analyst. Analyze the provided data and provide insights.',
411
+ tools: [
412
+ {
413
+ name: 'calculate_average',
414
+ description: 'Calculate the average of a list of numbers',
415
+ parameters: {
416
+ numbers: { type: 'array', description: 'Array of numbers', required: true }
417
+ },
418
+ execute: async ({ numbers }) => {
419
+ const avg = numbers.reduce((a, b) => a + b, 0) / numbers.length;
420
+ return JSON.stringify({ average: avg });
421
+ }
422
+ }
423
+ ]
424
+ });
425
+
426
+ // Create agent as a step in the workflow
427
+ const agentStep = new Step({
428
+ name: 'analyze',
429
+ execute: async (context) => {
430
+ const data = context.prepare.data;
431
+ const prompt = `Analyze this dataset: ${JSON.stringify(data)}`;
432
+ const analysis = await analyzerAgent.generate(prompt);
433
+ return { analysis, analyzed: true };
434
+ }
435
+ });
436
+
437
+ // Build workflow with agent step
438
+ const workflow = new Graph({ name: 'data-analysis-workflow' })
439
+ .step(prepareStep, agentStep, reportStep)
440
+ .edge(prepareStep, agentStep)
441
+ .edge(agentStep, reportStep)
442
+ .compile();
443
+
444
+ // Execute workflow
445
+ const result = await workflow.run({ rawData: [1, 2, 3, 4, 5] });
446
+ ```
447
+
448
+ ### Multiple Agents in Workflow
449
+
450
+ Use different specialized agents for different workflow stages:
451
+
452
+ ```javascript
453
+ const validationAgent = new Agent({
454
+ instruction: 'Validate data quality and completeness.',
455
+ // validation tools...
456
+ });
457
+
458
+ const processingAgent = new Agent({
459
+ instruction: 'Process and transform validated data.',
460
+ // processing tools...
461
+ });
462
+
463
+ const reportingAgent = new Agent({
464
+ instruction: 'Generate reports from processed data.',
465
+ // reporting tools...
466
+ });
467
+
468
+ // Create agent steps
469
+ const validateStep = new Step({
470
+ name: 'validate',
471
+ execute: async (context) => validationAgent.generate(context.rawData)
472
+ });
473
+
474
+ const processStep = new Step({
475
+ name: 'process',
476
+ execute: async (context) => processingAgent.generate(context.validate)
477
+ });
478
+
479
+ const reportStep = new Step({
480
+ name: 'report',
481
+ execute: async (context) => reportingAgent.generate(context.process)
482
+ });
483
+
484
+ // Orchestrate multi-agent workflow
485
+ const multiAgentWorkflow = new Graph({ name: 'multi-agent-pipeline' })
486
+ .step(validateStep, processStep, reportStep)
487
+ .edge(validateStep, processStep)
488
+ .edge(processStep, reportStep)
489
+ .compile();
490
+ ```