p.enthalabs

GitHub - Bessouat40/chainything: Chainything is a Directed Acyclic Graph (DAG) based pipeline execution engine written in Rust. It allows you to easily chain c

![Image 1: Crates.io-chainything](https://crates.io/crates/chainything)![Image 2: Crates.io-chainything-ui](https://crates.io/crates/chainything-ui)![Image 3: ci](https://github.com/Bessouat40/chainything/actions)

![Image 4: Chainything UI](https://github.com/Bessouat40/chainything/blob/main/media/ui.png)

_Building and running a pipeline from a natural-language prompt in the visual editor:_

![Image 5: Chainything demo](https://github.com/Bessouat40/chainything/blob/main/media/demo.gif)

Chainything is a Directed Acyclic Graph (DAG) based pipeline execution engine written in Rust.

It allows you to easily chain complex operations (like image processing, data transformation, etc.) in a modular way. The engine automatically calculates the optimal execution order and handles data transfer between different nodes (processors) while maintaining strong typing for the developer.

Features

[](https://github.com/Bessouat40/chainything#features)

- **Automatic Topological Sorting:** Uses Kahn's algorithm to determine the execution order of processors and detect circular dependencies safely.

- **Strong Typing & Flexibility:** Processors strictly define their input and output types, while the pipeline manages data transfer dynamically via type erasure (Any).

- **Multiple Sources:** Nodes can receive static data (provided at startup) or dynamic data (coming from the output of another node).

- **Extensible:** Simply implement the Processor trait to create your own custom logic blocks.

Quick Start

[](https://github.com/Bessouat40/chainything#quick-start)

Programmatic Usage

[](https://github.com/Bessouat40/chainything#programmatic-usage) Here is a simple example showing how to load an image, convert it to grayscale, and save it using Chainything:

use chainything::prelude::*;

fn main() { // 1. Initialize the pipeline let mut pipeline = Pipeline::new();

// 2. Add the reader processor (static data input) let reader = ImageReaderProcessor::new("reader"); pipeline.add_processor( Box::new(reader), vec![InputSource::static_data("./cat.jpg")] );

// 3. Add the grayscale processor (connected to output 0 of "reader") let greyscale = GreyScaleProcessor::new("greyscale"); pipeline.add_processor( Box::new(greyscale), vec![InputSource::connection("reader", 0)] );

// 4. Add the saver processor (connected to output 0 of "greyscale") let saver = ImageSaveProcessor::new("saver", "./output.png"); pipeline.add_processor( Box::new(saver), vec![InputSource::connection("greyscale", 0)] );

// 5. Execute the DAG match pipeline.execute() { Ok(_) => println!("Pipeline executed successfully!"), Err(e) => eprintln!("Execution error: {:?}", e), } }

Project Structure

[](https://github.com/Bessouat40/chainything#project-structure) Chainything is split into two main parts:

- **`crates/core`** — The pipeline execution engine and processor library. Pure Rust, no UI dependencies.

- **`crates/ui`** — A visual node editor built with egui that lets you create and execute pipelines graphically.

Architecture

[](https://github.com/Bessouat40/chainything#architecture) The project is built around three core concepts:

- **Processor:** A trait you implement to define a logical unit of work (e.g., reading a file, applying a math filter).

- **InputSource:** Defines where the data comes from (Static for hardcoded values, Connection to link to another node's output slot).

- **Pipeline:** The orchestrator that registers processors, analyzes their connections, and executes them in the correct order.

Getting Started

[](https://github.com/Bessouat40/chainything#getting-started)

Using the Library (Programmatic)

[](https://github.com/Bessouat40/chainything#using-the-library-programmatic) Simply add to your `Cargo.toml` and use the Quick Start example above.

Using the UI (Visual Node Editor)

[](https://github.com/Bessouat40/chainything#using-the-ui-visual-node-editor)

From the repository root

cargo run --package chainything-ui

This launches the visual node editor where you can:

- Add nodes onto the canvas to add processors

- Connect nodes by dragging pins

- Configure processor parameters

- Click "Run" to execute the pipeline

Development

[](https://github.com/Bessouat40/chainything#development)

Prerequisites

[](https://github.com/Bessouat40/chainything#prerequisites)

- Rust 1.70+ (install via rustup)

- Cargo

Setup

[](https://github.com/Bessouat40/chainything#setup)

Clone the repository

git clone <repo-url> cd chainything

Run tests

cargo test

Format code

cargo fmt

Lint

cargo clippy --workspace --all-targets -- -D warnings

Running the UI in Development

[](https://github.com/Bessouat40/chainything#running-the-ui-in-development)

cargo run --package chainything-ui

Creating Your Own Processor

[](https://github.com/Bessouat40/chainything#creating-your-own-processor) To create a new node in the pipeline, simply implement the Processor trait:

impl Processor for MyProcessor { fn id(&self) -> &str { &self.id }

fn set_input(&mut self, inputs: Vec<Arc<dyn Any + Send + Sync>>) -> Result<(), ProcessorError> { // Downcast example : // let data = inputs[0].downcast_ref::<String>().ok_or(ProcessorError::InvalidInput("...".into()))?; Ok(()) }

fn get_output(&self) -> Vec<Arc<dyn Any + Send + Sync>> { // Return a Vec with your slots output results vec![Arc::new("Mon résultat".to_string())] }

fn process(&mut self) -> Result<(), ProcessorError> { // Your logic here Ok(()) } }

Contributing

[](https://github.com/Bessouat40/chainything#contributing) We welcome contributions! Whether you're adding new processors to the library or improving the UI, please read our CONTRIBUTING.md for detailed instructions on:

- Creating a new processor in `crates/core`

- Creating a corresponding UI node in `crates/ui`

- Testing and documentation requirements

- Submitting a pull request

Quick Contribution Checklist

[](https://github.com/Bessouat40/chainything#quick-contribution-checklist) 1. Create your processor and register it in the pipeline registry 2. Write comprehensive tests and documentation 3. Run `cargo fmt` and `cargo test` 4. (Optional) Create a UI node to expose your processor in the visual editor 5. Submit a PR with both core and UI changes (if applicable)

For detailed guidance, see CONTRIBUTING.md.