Skip to content

Commit b5e71ef

Browse files
committed
[feat] Introduce Loop tasks: Map, Reduce, and While
- Introduced MapTask for transforming arrays with configurable result collection and order preservation. - Added ReduceTask for processing array elements with an accumulator, allowing for complex reductions. - Implemented WhileTask for looping until a specified condition is met, with configurable maximum iterations and chaining of outputs. - ConditionTask and WhileTask share auto-generation of condition function based on config - Enhanced Workflow interface to support new loop tasks, improving task graph management and execution flow. - Updated tests to validate the functionality of new tasks and their integration within workflows.
1 parent b567b4d commit b5e71ef

38 files changed

Lines changed: 6859 additions & 1560 deletions

TODO.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ TODO.md
99
- [ ] Datasets Package
1010
- [x] Documents dataset (mabye rename to DocumentDataset)
1111
- [ ] Chunks Package (or part of DocumentDataset?)
12-
- [ ] Move Model repository to datasets package.
13-
- [ ] Chunks and nodes are not always the same.
14-
- [ ] And we may need to save the chunk's node path. Or paths? or document range? Standard metadata?
15-
- [ ] Instead of passing doc_id around, pass a document key that is unknonwn (string or object)
12+
- [x] Move Model repository to datasets package.
13+
- [x] Chunks and nodes are not always the same.
14+
- [x] And we may need to save the chunk's node path. Or paths? or document range? Standard metadata?
15+
- [ ] Instead of passing doc_id around, pass a document key that is of type unknonwn (string or object)
1616

1717
- [ ] Get a better model for question answering.
1818
- [ ] Get a better model for named entity recognition, the current one recognized everything as a token, not helpful.
@@ -25,16 +25,11 @@ TODO.md
2525
- [ ] rename the registration stuff to not look ugly: registerHuggingfaceTransformers() and registerHuggingfaceTransformersUsingWorkers() and registerHuggingfaceTransformersInsideWorker()
2626
- [ ] fix image transferables
2727

28-
onnx-community/ModernBERT-finetuned-squad-ONNX - summarization
28+
- [ ] Consider different ways to connect tasks to queues. What is a task? What is a job?
29+
30+
- [ ] Input and outputs are all scalar, arrays, or unions. But what about streams? Stream of items in an array, stream of content for a scalar like a string, etc.
2931

30-
- [x] Auto-generated primary keys for TabularStorage
31-
- [x] Schema annotation with `x-auto-generated: true`
32-
- [x] Type system with `InsertEntity` for optional auto-generated keys
33-
- [x] Support for autoincrement (integer) and UUID (string) strategies
34-
- [x] Configurable client-provided keys: "never", "if-missing", "always"
35-
- [x] Implementations: InMemory, SQLite, Postgres, Supabase, IndexedDB, FsFolder
36-
- [x] Comprehensive test suite (342 tests pass)
37-
- [x] Documentation updated
32+
onnx-community/ModernBERT-finetuned-squad-ONNX - summarization
3833

3934
Rework the Document Dataset. Currently there is a Document storage of tabular storage type, and that should be registered as a "dataset:document:source" meaning the source material in node format. And there is already a "dataset:document-chunk" for the chunk/vector storage which should be registered as a "dataset:document:chunk" with a well defined metadata schema. The two combined should be registered as a "dataset:document" which is the complete document with its source and all its chunks and metadata. This is for convenience but not used by tasks or ai tasks.
4035

examples/cli/src/TaskCLI.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import { DownloadModelTask, getGlobalModelRepository, type ModelConfig } from "@workglow/ai";
7+
import {
8+
DownloadModelTask,
9+
getGlobalModelRepository,
10+
registerAiTasks,
11+
type ModelConfig,
12+
} from "@workglow/ai";
813
import { HF_TRANSFORMERS_ONNX } from "@workglow/ai-provider";
9-
import { JsonTaskItem, TaskGraph, Workflow } from "@workglow/task-graph";
10-
import { DelayTask, JsonTask } from "@workglow/tasks";
14+
import { JsonTaskItem, registerBaseTasks, TaskGraph, Workflow } from "@workglow/task-graph";
15+
import { DelayTask, JsonTask, registerCommonTasks } from "@workglow/tasks";
1116
import type { Command } from "commander";
1217
import { readFile, writeFile } from "fs/promises";
1318
import { runTasks } from "./TaskGraphToUI";
14-
1519
/**
1620
* Read image input from file or stdin
1721
*/
@@ -539,8 +543,18 @@ export function AddBaseCommands(program: Command) {
539543
program
540544
.command("json")
541545
.description("run based on json input")
542-
.argument("[json]", "json text to rewrite and vectorize")
543-
.action(async (json) => {
546+
.argument("[json]", "json text")
547+
.option("--file <path>", "read JSON from file")
548+
.action(async (jsonArg, options) => {
549+
registerBaseTasks();
550+
registerCommonTasks();
551+
registerAiTasks();
552+
let json = jsonArg;
553+
if (!json && options.file) {
554+
json = (await readFile(options.file, "utf-8")).trim();
555+
} else if (!json && !process.stdin.isTTY) {
556+
json = await readTextInput();
557+
}
544558
if (!json) {
545559
const exampleJson: JsonTaskItem[] = [
546560
{

examples/cli/src/components/TaskUI.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ export const TaskUI: FC<{
144144
setError((prevErr) => (prevErr ? `${prevErr}\nAborted` : "Aborted"));
145145
};
146146
onRegenerate();
147-
setDependantChildren(graph.getTargetTasks(task.config.id));
147+
const targets = graph.getTargetTasks(task.config.id);
148+
const unique = [...new Map(targets.map((t) => [t.config.id, t])).values()];
149+
setDependantChildren(unique);
148150

149151
task.on("start", onStart);
150152
task.on("progress", onProgress);

packages/ai/src/model/ModelRepository.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export class ModelRepository {
168168
* Enumerates all models in the repository
169169
* @returns Promise resolving to an array of model instances
170170
*/
171-
async enumerateAllModels() {
171+
async enumerateAllModels(): Promise<ModelRecord[] | undefined> {
172172
const models = await this.modelTabularRepository.getAll();
173173
if (!models || models.length === 0) return undefined;
174174
return models;
@@ -179,7 +179,7 @@ export class ModelRepository {
179179
* @param modelId - The model_id of the model to find
180180
* @returns Promise resolving to the found model or undefined if not found
181181
*/
182-
async findByName(model_id: string) {
182+
async findByName(model_id: string): Promise<ModelRecord | undefined> {
183183
if (typeof model_id != "string") return undefined;
184184
const model = await this.modelTabularRepository.get({ model_id });
185185
return model ?? undefined;

0 commit comments

Comments
 (0)