@workglow/ai 0.0.90 → 0.0.91

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/README.md CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  import { Workflow, getTaskQueueRegistry, TaskInput, TaskOutput } from "@workglow/task-graph";
38
38
  import { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from "@workglow/job-queue";
39
39
  import { InMemoryQueueStorage } from "@workglow/storage";
40
- import { HF_TRANSFORMERS_ONNX, register_HFT_InlineJobFns } from "@workglow/ai-provider";
40
+ import { HFT_TASKS, HF_TRANSFORMERS_ONNX, HuggingFaceTransformersProvider } from "@workglow/ai-provider";
41
41
 
42
42
  // 1. Set up a model repository
43
43
  const modelRepo = new InMemoryModelRepository();
@@ -55,10 +55,10 @@ await modelRepo.addModel({
55
55
  model_path: "Xenova/LaMini-Flan-T5-783M"
56
56
  });
57
57
 
58
- // 3. Register provider functions (inline, same thread)
59
- await register_HFT_InlineJobFns();
58
+ // 3. Register provider (inline mode requires HFT_TASKS via constructor, creates queue automatically)
59
+ await new HuggingFaceTransformersProvider(HFT_TASKS).register({ mode: "inline" });
60
60
 
61
- // 4. Set up job queue for the provider (optional, an in-memory queue will be setup automatically)
61
+ // 4. Or manually set up job queue (when queue.autoCreate: false)
62
62
  const queueName = HF_TRANSFORMERS_ONNX;
63
63
  const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(queueName);
64
64
 
@@ -320,10 +320,10 @@ AI providers handle the actual execution of AI tasks. You need to register provi
320
320
  ### Basic Provider Registration
321
321
 
322
322
  ```typescript
323
- import { register_HFT_InlineJobFns } from "@workglow/ai-provider";
323
+ import { HFT_TASKS, HuggingFaceTransformersProvider } from "@workglow/ai-provider";
324
324
 
325
- // Registers run functions for all supported AI tasks on the current thread
326
- await register_HFT_InlineJobFns();
325
+ // Registers run functions for all supported AI tasks on the current thread (inline mode requires HFT_TASKS)
326
+ await new HuggingFaceTransformersProvider(HFT_TASKS).register({ mode: "inline" });
327
327
  ```
328
328
 
329
329
  ### Worker-Based Provider Registration
@@ -331,9 +331,13 @@ await register_HFT_InlineJobFns();
331
331
  For compute-intensive tasks that should run in workers:
332
332
 
333
333
  ```typescript
334
- // See `@workglow/ai-provider` exports for worker/client registration helpers
335
- // - register_HFT_WorkerJobFns (in worker)
336
- // - register_HFT_ClientJobFns (in main thread)
334
+ import { HuggingFaceTransformersProvider } from "@workglow/ai-provider";
335
+
336
+ await new HuggingFaceTransformersProvider().register({
337
+ mode: "worker",
338
+ worker: new Worker(new URL("./worker_hft.ts", import.meta.url), { type: "module" }),
339
+ });
340
+ // Worker file must call HFT_WORKER_JOBRUN_REGISTER() from @workglow/ai-provider
337
341
  ```
338
342
 
339
343
  ### Job Queue Setup
@@ -428,7 +432,7 @@ The AI package provides a comprehensive set of tasks for building RAG pipelines.
428
432
  | `RerankerTask` | Reranks search results for relevance |
429
433
  | `HierarchyJoinTask` | Enriches results with parent context |
430
434
  | `ContextBuilderTask` | Builds context for LLM prompts |
431
- | `ChunkRetrievalTask` | Orchestrates end-to-end retrieval |
435
+ | `ChunkRetrievalTask` | Orchestrates end-to-end retrieval |
432
436
 
433
437
  ### Complete RAG Workflow Example
434
438
 
@@ -593,7 +597,7 @@ This resolution is handled by the input resolver system, which inspects schema `
593
597
  | --------------------------------- | ---------------------------------------- | -------------------------- |
594
598
  | `model` | Any AI model configuration | ModelRepository |
595
599
  | `model:TaskName` | Model compatible with specific task type | ModelRepository |
596
- | `repository:tabular` | Tabular data repository | TabularStorageRegistry |
600
+ | `repository:tabular` | Tabular data repository | TabularStorageRegistry |
597
601
  | `repository:document-node-vector` | Vector storage repository | VectorRepositoryRegistry |
598
602
  | `repository:document` | Document repository | DocumentRepositoryRegistry |
599
603
 
package/dist/browser.js CHANGED
@@ -11,6 +11,17 @@ import { globalServiceRegistry, WORKER_MANAGER } from "@workglow/util";
11
11
 
12
12
  class AiProviderRegistry {
13
13
  runFnRegistry = new Map;
14
+ streamFnRegistry = new Map;
15
+ providers = new Map;
16
+ registerProvider(provider) {
17
+ this.providers.set(provider.name, provider);
18
+ }
19
+ getProvider(name) {
20
+ return this.providers.get(name);
21
+ }
22
+ getProviders() {
23
+ return new Map(this.providers);
24
+ }
14
25
  registerRunFn(modelProvider, taskType, runFn) {
15
26
  if (!this.runFnRegistry.has(taskType)) {
16
27
  this.runFnRegistry.set(taskType, new Map);
@@ -28,6 +39,23 @@ class AiProviderRegistry {
28
39
  };
29
40
  this.registerRunFn(modelProvider, taskType, workerFn);
30
41
  }
42
+ registerStreamFn(modelProvider, taskType, streamFn) {
43
+ if (!this.streamFnRegistry.has(taskType)) {
44
+ this.streamFnRegistry.set(taskType, new Map);
45
+ }
46
+ this.streamFnRegistry.get(taskType).set(modelProvider, streamFn);
47
+ }
48
+ registerAsWorkerStreamFn(modelProvider, taskType) {
49
+ const streamFn = async function* (input, model, signal) {
50
+ const workerManager = globalServiceRegistry.get(WORKER_MANAGER);
51
+ yield* workerManager.callWorkerStreamFunction(modelProvider, taskType, [input, model], { signal });
52
+ };
53
+ this.registerStreamFn(modelProvider, taskType, streamFn);
54
+ }
55
+ getStreamFn(modelProvider, taskType) {
56
+ const taskTypeMap = this.streamFnRegistry.get(taskType);
57
+ return taskTypeMap?.get(modelProvider);
58
+ }
31
59
  getDirectRunFn(modelProvider, taskType) {
32
60
  const taskTypeMap = this.runFnRegistry.get(taskType);
33
61
  const runFn = taskTypeMap?.get(modelProvider);
@@ -81,6 +109,19 @@ class AiJob extends Job {
81
109
  }
82
110
  }
83
111
  }
112
+ async* executeStream(input, context) {
113
+ if (context.signal.aborted || this.status === JobStatus.ABORTING) {
114
+ throw new AbortSignalJobError("Abort signal aborted before streaming execution of job");
115
+ }
116
+ const streamFn = getAiProviderRegistry().getStreamFn(input.aiProvider, input.taskType);
117
+ if (!streamFn) {
118
+ const result = await this.execute(input, context);
119
+ yield { type: "finish", data: result };
120
+ return;
121
+ }
122
+ const model = input.taskInput.model;
123
+ yield* streamFn(input.taskInput, model, context.signal);
124
+ }
84
125
  }
85
126
  // src/model/InMemoryModelRepository.ts
86
127
  import { InMemoryTabularStorage } from "@workglow/storage";
@@ -238,6 +279,100 @@ async function resolveModelFromRegistry(id, format, registry) {
238
279
  return model;
239
280
  }
240
281
  registerInputResolver("model", resolveModelFromRegistry);
282
+ // src/provider/AiProvider.ts
283
+ import { globalServiceRegistry as globalServiceRegistry3, WORKER_MANAGER as WORKER_MANAGER2 } from "@workglow/util";
284
+
285
+ // src/queue/createDefaultQueue.ts
286
+ import { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from "@workglow/job-queue";
287
+ import { InMemoryQueueStorage } from "@workglow/storage";
288
+ import { getTaskQueueRegistry } from "@workglow/task-graph";
289
+ async function createDefaultQueue(providerName, concurrency) {
290
+ const storage = new InMemoryQueueStorage(providerName);
291
+ await storage.setupDatabase();
292
+ const server = new JobQueueServer(AiJob, {
293
+ storage,
294
+ queueName: providerName,
295
+ limiter: new ConcurrencyLimiter(concurrency, 100)
296
+ });
297
+ const client = new JobQueueClient({
298
+ storage,
299
+ queueName: providerName
300
+ });
301
+ client.attach(server);
302
+ getTaskQueueRegistry().registerQueue({ server, client, storage });
303
+ await server.start();
304
+ }
305
+
306
+ // src/provider/AiProvider.ts
307
+ class AiProvider {
308
+ tasks;
309
+ streamTasks;
310
+ constructor(tasks, streamTasks) {
311
+ this.tasks = tasks;
312
+ this.streamTasks = streamTasks;
313
+ }
314
+ get supportedTaskTypes() {
315
+ return this.taskTypes;
316
+ }
317
+ getRunFn(taskType) {
318
+ return this.tasks?.[taskType];
319
+ }
320
+ getStreamFn(taskType) {
321
+ return this.streamTasks?.[taskType];
322
+ }
323
+ async register(options = { mode: "inline" }) {
324
+ await this.onInitialize(options);
325
+ if (options.mode === "worker") {
326
+ if (!options.worker) {
327
+ throw new Error(`AiProvider "${this.name}": worker is required when mode is "worker". ` + `Pass a Web Worker instance, e.g. register({ mode: "worker", worker: new Worker(...) }).`);
328
+ }
329
+ } else {
330
+ if (!this.tasks) {
331
+ throw new Error(`AiProvider "${this.name}": tasks must be provided via the constructor for inline mode. ` + `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`);
332
+ }
333
+ }
334
+ const registry = getAiProviderRegistry();
335
+ if (options.mode === "worker" && options.worker) {
336
+ const workerManager = globalServiceRegistry3.get(WORKER_MANAGER2);
337
+ workerManager.registerWorker(this.name, options.worker);
338
+ for (const taskType of this.taskTypes) {
339
+ registry.registerAsWorkerRunFn(this.name, taskType);
340
+ registry.registerAsWorkerStreamFn(this.name, taskType);
341
+ }
342
+ } else {
343
+ for (const [taskType, fn] of Object.entries(this.tasks)) {
344
+ registry.registerRunFn(this.name, taskType, fn);
345
+ }
346
+ if (this.streamTasks) {
347
+ for (const [taskType, fn] of Object.entries(this.streamTasks)) {
348
+ registry.registerStreamFn(this.name, taskType, fn);
349
+ }
350
+ }
351
+ }
352
+ registry.registerProvider(this);
353
+ if (options.queue?.autoCreate !== false) {
354
+ await this.createQueue(options.queue?.concurrency ?? 1);
355
+ }
356
+ }
357
+ registerOnWorkerServer(workerServer) {
358
+ if (!this.tasks) {
359
+ throw new Error(`AiProvider "${this.name}": tasks must be provided via the constructor for worker server registration. ` + `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`);
360
+ }
361
+ for (const [taskType, fn] of Object.entries(this.tasks)) {
362
+ workerServer.registerFunction(taskType, fn);
363
+ }
364
+ if (this.streamTasks) {
365
+ for (const [taskType, fn] of Object.entries(this.streamTasks)) {
366
+ workerServer.registerStreamFunction(taskType, fn);
367
+ }
368
+ }
369
+ }
370
+ async onInitialize(_options) {}
371
+ async dispose() {}
372
+ async createQueue(concurrency) {
373
+ await createDefaultQueue(this.name, concurrency);
374
+ }
375
+ }
241
376
  // src/task/index.ts
242
377
  import { TaskRegistry } from "@workglow/task-graph";
243
378
 
@@ -1705,6 +1840,26 @@ Workflow9.prototype.textNamedEntityRecognition = CreateWorkflow9(TextNamedEntity
1705
1840
 
1706
1841
  // src/task/TextSummaryTask.ts
1707
1842
  import { CreateWorkflow as CreateWorkflow10, Workflow as Workflow10 } from "@workglow/task-graph";
1843
+
1844
+ // src/task/base/StreamingAiTask.ts
1845
+ class StreamingAiTask extends AiTask {
1846
+ static type = "StreamingAiTask";
1847
+ async* executeStream(input, context) {
1848
+ const jobInput = await this.getJobInput(input);
1849
+ const queueName = await this.getDefaultQueueName(input);
1850
+ const job = new AiJob({
1851
+ queueName: queueName ?? this.type,
1852
+ jobRunId: this.config.runnerId,
1853
+ input: jobInput
1854
+ });
1855
+ yield* job.executeStream(jobInput, {
1856
+ signal: context.signal,
1857
+ updateProgress: context.updateProgress.bind(this)
1858
+ });
1859
+ }
1860
+ }
1861
+
1862
+ // src/task/TextSummaryTask.ts
1708
1863
  var modelSchema4 = TypeModel("model:TextSummaryTask");
1709
1864
  var TextSummaryInputSchema = {
1710
1865
  type: "object",
@@ -1725,14 +1880,15 @@ var TextSummaryOutputSchema = {
1725
1880
  text: {
1726
1881
  type: "string",
1727
1882
  title: "Text",
1728
- description: "The summarized text"
1883
+ description: "The summarized text",
1884
+ "x-stream": "append"
1729
1885
  }
1730
1886
  },
1731
1887
  required: ["text"],
1732
1888
  additionalProperties: false
1733
1889
  };
1734
1890
 
1735
- class TextSummaryTask extends AiTask {
1891
+ class TextSummaryTask extends StreamingAiTask {
1736
1892
  static type = "TextSummaryTask";
1737
1893
  static category = "AI Text Model";
1738
1894
  static title = "Text Summary";
@@ -4493,7 +4649,8 @@ import { CreateWorkflow as CreateWorkflow31, Workflow as Workflow31 } from "@wor
4493
4649
  var generatedTextSchema2 = {
4494
4650
  type: "string",
4495
4651
  title: "Text",
4496
- description: "The generated text"
4652
+ description: "The generated text",
4653
+ "x-stream": "append"
4497
4654
  };
4498
4655
  var modelSchema18 = TypeModel("model:TextGenerationTask");
4499
4656
  var TextGenerationInputSchema = {
@@ -4558,7 +4715,7 @@ var TextGenerationOutputSchema = {
4558
4715
  additionalProperties: false
4559
4716
  };
4560
4717
 
4561
- class TextGenerationTask extends AiTask {
4718
+ class TextGenerationTask extends StreamingAiTask {
4562
4719
  static type = "TextGenerationTask";
4563
4720
  static category = "AI Text Model";
4564
4721
  static title = "Text Generation";
@@ -4661,7 +4818,8 @@ var questionSchema = {
4661
4818
  var textSchema = {
4662
4819
  type: "string",
4663
4820
  title: "Text",
4664
- description: "The generated text"
4821
+ description: "The generated text",
4822
+ "x-stream": "append"
4665
4823
  };
4666
4824
  var modelSchema20 = TypeModel("model:TextQuestionAnswerTask");
4667
4825
  var TextQuestionAnswerInputSchema = {
@@ -4683,7 +4841,7 @@ var TextQuestionAnswerOutputSchema = {
4683
4841
  additionalProperties: false
4684
4842
  };
4685
4843
 
4686
- class TextQuestionAnswerTask extends AiTask {
4844
+ class TextQuestionAnswerTask extends StreamingAiTask {
4687
4845
  static type = "TextQuestionAnswerTask";
4688
4846
  static category = "AI Text Model";
4689
4847
  static title = "Text Question Answer";
@@ -4727,14 +4885,15 @@ var TextRewriterOutputSchema = {
4727
4885
  text: {
4728
4886
  type: "string",
4729
4887
  title: "Text",
4730
- description: "The rewritten text"
4888
+ description: "The rewritten text",
4889
+ "x-stream": "append"
4731
4890
  }
4732
4891
  },
4733
4892
  required: ["text"],
4734
4893
  additionalProperties: false
4735
4894
  };
4736
4895
 
4737
- class TextRewriterTask extends AiTask {
4896
+ class TextRewriterTask extends StreamingAiTask {
4738
4897
  static type = "TextRewriterTask";
4739
4898
  static category = "AI Text Model";
4740
4899
  static title = "Text Rewriter";
@@ -4757,7 +4916,8 @@ var modelSchema22 = TypeModel("model:TextTranslationTask");
4757
4916
  var translationTextSchema = {
4758
4917
  type: "string",
4759
4918
  title: "Text",
4760
- description: "The translated text"
4919
+ description: "The translated text",
4920
+ "x-stream": "replace"
4761
4921
  };
4762
4922
  var TextTranslationInputSchema = {
4763
4923
  type: "object",
@@ -4799,7 +4959,7 @@ var TextTranslationOutputSchema = {
4799
4959
  additionalProperties: false
4800
4960
  };
4801
4961
 
4802
- class TextTranslationTask extends AiTask {
4962
+ class TextTranslationTask extends StreamingAiTask {
4803
4963
  static type = "TextTranslationTask";
4804
4964
  static category = "AI Text Model";
4805
4965
  static title = "Text Translation";
@@ -5224,8 +5384,8 @@ var outputSchema15 = {
5224
5384
 
5225
5385
  class VectorQuantizeTask extends Task15 {
5226
5386
  static type = "VectorQuantizeTask";
5227
- static category = "Vector Processing";
5228
- static title = "Quantize Vector";
5387
+ static category = "Vector";
5388
+ static title = "Quantize";
5229
5389
  static description = "Quantize vectors to reduce storage and improve performance";
5230
5390
  static cacheable = true;
5231
5391
  static inputSchema() {
@@ -5569,6 +5729,7 @@ export {
5569
5729
  TextClassificationInputSchema,
5570
5730
  TextChunkerTask,
5571
5731
  StructuralParserTask,
5732
+ StreamingAiTask,
5572
5733
  SimilarityFn,
5573
5734
  SegmentationMethod,
5574
5735
  RerankerTask,
@@ -5627,7 +5788,8 @@ export {
5627
5788
  BackgroundRemovalInputSchema,
5628
5789
  AiTask,
5629
5790
  AiProviderRegistry,
5791
+ AiProvider,
5630
5792
  AiJob
5631
5793
  };
5632
5794
 
5633
- //# debugId=31A882226780D84D64756E2164756E21
5795
+ //# debugId=F489D646426CED9764756E2164756E21