Ai provider - #179
Conversation
…e and TensorFlow MediaPipe providers - Replaced `register_HFT_InlineJobFns` and `register_HFT_ClientJobFns` with `HuggingFaceTransformersProvider` and `TensorFlowMediaPipeProvider` for improved modularity and clarity. - Updated documentation and examples to reflect the new provider registration methods. - Enhanced worker registration for HuggingFace and TensorFlow MediaPipe tasks, streamlining the integration of AI models. - Removed deprecated registration functions to clean up the codebase.
- Replaced the manual queue setup process in the createQueue method with a call to createDefaultQueue for improved readability and maintainability. - This change reduces complexity by leveraging a dedicated function for queue creation, streamlining the overall implementation.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new AiProvider abstraction in @workglow/ai and migrates @workglow/ai-provider integrations (HuggingFace Transformers + TensorFlow MediaPipe) from standalone register_* helper functions to provider classes with injected task maps.
Changes:
- Added
AiProviderbase class + lifecycle/registry support (AiProviderRegistry.registerProvider/getProvider/getProviders) and a shared default queue creator. - Reworked ai-provider exports to provider classes (
HuggingFaceTransformersProvider,TensorFlowMediaPipeProvider) and exported task maps (HFT_TASKS,TFMP_TASKS), removing the old inline/client/worker register modules. - Updated tests, examples, and docs to use the new provider registration approach.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/ai/src/provider/AiProvider.ts | New provider base class with inline/worker registration + queue auto-creation |
| packages/ai/src/provider/AiProviderRegistry.ts | Adds provider instance registry (for lifecycle/introspection) |
| packages/ai/src/queue/createDefaultQueue.ts | New shared helper to create/register default in-memory queues |
| packages/ai/src/common.ts | Exports AiProvider from @workglow/ai |
| packages/ai-provider/src/hf-transformers/* | Adds HuggingFaceTransformersProvider, HFT_TASKS, and new worker registration entrypoint |
| packages/ai-provider/src/tf-mediapipe/* | Adds TensorFlowMediaPipeProvider, TFMP_TASKS, and new worker registration entrypoint |
| packages/test/src/test/**/* | Updates test suites to use provider classes + task maps |
| examples/web/src/* | Updates worker/main-thread registration to provider-based worker mode |
| examples/cli/src/* | Updates inline/worker registration to provider-based API |
| packages/ai/README.md | Updates docs to provider-based registration (but has inline examples missing task injection) |
| packages/ai-provider/README.md | Updates docs to provider-based registration (but has inline examples missing task injection) |
| docs/developers/01_getting_started.md | Updates getting started docs (but has inline example missing task injection) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // Register AI providers | ||
| await register_HFT_InlineJobFns(); | ||
| await register_TFMP_InlineJobFns(); | ||
| await new HuggingFaceTransformersProvider().register({ mode: "inline" }); | ||
| await new TensorFlowMediaPipeProvider().register({ mode: "inline" }); |
There was a problem hiding this comment.
This README snippet registers providers in inline mode without passing the task maps (HFT_TASKS / TFMP_TASKS). With the new provider API, inline mode requires tasks injected via the constructor, so this example will throw at runtime if copied. Update the snippet to pass the task maps (or switch it to worker mode).
| if (options.mode === "worker" && options.worker) { | ||
| const workerManager = globalServiceRegistry.get(WORKER_MANAGER); | ||
| workerManager.registerWorker(this.name, options.worker); | ||
| for (const taskType of this.taskTypes) { | ||
| registry.registerAsWorkerRunFn(this.name, taskType); |
There was a problem hiding this comment.
In register(), when mode is set to "worker" but options.worker is undefined, this code falls through to the inline-registration branch and throws the "tasks must be provided" error, which is misleading. Add an explicit validation/throw for mode === "worker" && !worker before this conditional so callers get a clear error and you don’t accidentally attempt inline registration.
| async function main() { | ||
| // 1. Register the AI provider | ||
| await register_HFT_InlineJobFns(); | ||
| await new HuggingFaceTransformersProvider().register({ mode: "inline" }); | ||
|
|
There was a problem hiding this comment.
This example registers HuggingFaceTransformersProvider in inline mode without injecting HFT_TASKS. With the new AiProvider contract, inline mode requires tasks via the constructor, so the snippet will throw. Update the example to pass HFT_TASKS (or demonstrate worker mode).
| // Register with custom queue concurrency (provider creates queue with concurrency: 2) | ||
| await new HuggingFaceTransformersProvider().register({ | ||
| mode: "inline", | ||
| queue: { concurrency: 2 }, | ||
| }); |
There was a problem hiding this comment.
In the "Custom Job Queue Configuration" section, this snippet calls new HuggingFaceTransformersProvider().register({ mode: "inline", ... }) without injecting HFT_TASKS. Inline mode will throw unless the tasks record is provided via the constructor. Update the snippet to pass HFT_TASKS (or make it a worker-mode example).
| import { HF_TRANSFORMERS_ONNX, HuggingFaceTransformersProvider } from "@workglow/ai-provider"; | ||
|
|
||
| // Provider run functions on this thread | ||
| await register_HFT_InlineJobFns(); | ||
| await new HuggingFaceTransformersProvider().register({ mode: "inline" }); |
There was a problem hiding this comment.
This getting-started snippet registers HuggingFaceTransformersProvider in inline mode without passing the task map (HFT_TASKS). With the new provider API, inline mode requires tasks injected via the constructor. Update the snippet to pass HFT_TASKS (or change the doc to demonstrate worker-mode registration).
| const registry = getAiProviderRegistry(); | ||
| registry.registerProvider(this); | ||
|
|
There was a problem hiding this comment.
registry.registerProvider(this) happens before validating that registration will succeed (e.g., tasks present for inline mode, worker present for worker mode). If registration throws afterward, the registry can retain a partially-registered provider instance. Consider deferring registerProvider() until after validation/registration completes (or rolling back on error).
| const server = new JobQueueServer(AiJob as any, { | ||
| storage, | ||
| queueName: providerName, | ||
| limiter: new ConcurrencyLimiter(concurrency, 100), | ||
| }); |
There was a problem hiding this comment.
createDefaultQueue uses AiJob as any when constructing JobQueueServer, which drops type safety and can hide wiring errors. Consider typing the queue with AiJobInput<TaskInput> / TaskOutput and passing AiJob without as any (or using an explicit JobClass<...> cast) so this stays compile-time checked.
| // 3. Register provider (inline mode, creates queue automatically) | ||
| await new HuggingFaceTransformersProvider().register({ mode: "inline" }); | ||
|
|
There was a problem hiding this comment.
This README example registers the provider in inline mode without passing the injected task map (e.g. HFT_TASKS). With the new AiProvider base class, inline mode requires tasks via the constructor and will throw at runtime. Update the snippet to either pass HFT_TASKS for inline mode or switch the example to mode: "worker".
| import { HuggingFaceTransformersProvider } from "@workglow/ai-provider"; | ||
|
|
||
| // Registers run functions for all supported AI tasks on the current thread | ||
| await register_HFT_InlineJobFns(); | ||
| await new HuggingFaceTransformersProvider().register({ mode: "inline" }); | ||
| ``` |
There was a problem hiding this comment.
This later README snippet also uses new HuggingFaceTransformersProvider().register({ mode: "inline" }) without passing HFT_TASKS. Since inline mode now requires tasks via the constructor, the example will fail if copied. Adjust the snippet to provide HFT_TASKS (or demonstrate worker mode).
Note
Medium Risk
Touches core provider registration and queue startup behavior across inline/worker modes, so regressions could break task execution or worker wiring. Changes are mostly API refactors with added tests, but impact is broad across providers, examples, and docs.
Overview
Introduces a new
AiProviderbase class (exported from@workglow/ai) that centralizes provider registration for inline vs worker execution, registers provider instances inAiProviderRegistry, and auto-creates an in-memory job queue via a newcreateDefaultQueue()helper (with options to configure concurrency or disable auto-creation).Refactors the HuggingFace Transformers and TensorFlow MediaPipe implementations to provider classes (
HuggingFaceTransformersProvider,TensorFlowMediaPipeProvider) with injected task maps (HFT_TASKS,TFMP_TASKS) and new worker entrypoints (HFT_WORKER_JOBRUN_REGISTER,TFMP_WORKER_JOBRUN_REGISTER), removing the olderregister_*_*JobFnshelper modules.Updates all docs, examples (CLI/web), and tests to use
new ...Provider().register(...)/worker registration APIs, including safer ONNXenvproxy setup in workers and revised guidance around queue creation.Written by Cursor Bugbot for commit e5d23bf. This will update automatically on new commits. Configure here.