SkillAgentSearch skills...

Syft.js

The official Syft worker for Web and Node, built in Javascript

Install / Use

/learn @OpenMined/Syft.js
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<img src="art/fake-logo.png" alt="syft.js logo" width="200" />

Build codecov npm GitHub OpenCollective

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

All Contributors

<!-- ALL-CONTRIBUTORS-BADGE:END -->

Syft.js

Syft.js is the “web” part of the OpenMined's open-source ecosystem for federated learning, which currently spans across web, iOS, Android, and servers/IoT.

Syft.js has following core features:

  • :hammer_and_wrench: Integration with PyGrid federated learning API.
  • :gear: Training and inference of any PySyft model written in PyTorch or TensorFlow.
  • :bust_in_silhouette: Allows all data to stay on the user's device.
  • :lock: Support for secure multi-party computation and secure aggregation protocols using peer-to-peer WebRTC connections (in progress).

The library is built on top of TensorFlow.js.

There are a variety of additional privacy-preserving protections that may be applied, including differential privacy, muliti-party computation, and secure aggregation.

If you want to know how scalable federated systems are built, Towards Federated Learning at Scale is a fantastic introduction!

Installation

Note that syft.js needs Tensorflow.js library as peer dependency.

If you're using a package manager like NPM:

npm install --save @openmined/syft.js @tensorflow/tfjs-core

Or if Yarn is your cup of tea:

yarn add @openmined/syft.js @tensorflow/tfjs-core

If you're not using a package manager, you will be able to include Syft.js within a <script> tag. In this case library classes will be available under syft global object.

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2.5/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@openmined/syft.js@latest/dist/index.min.js"></script>

<script type="text/javascript">
  // Create syft worker
  const worker = syft.Syft({...});
  ...
</script>

Quick Start

As a developer, there are few steps to building your own secure federated learning system upon the OpenMined infrastructure:

  1. :robot: Develop ML model and training procedure (aka Plan in PySyft terminology) using PySyft.
  2. :earth_americas: Host model and Plans on PyGrid, which will deal with all the federated learning components of your pipeline.
  3. :tada: Execute the training on the variety of end-user devices using the client library (syft.js, SwiftSyft, KotlinSyft, PySyft).
  4. :lock: Securely aggregate trained user models in PyGrid.

:notebook: The entire workflow and process is described in greater detail in the Web & Mobile Federated Learning project roadmap.

Syft.js provides minimalistic API to communicate with federated learning PyGrid endpoints and execute PySyft's Plans in a browser. The federated learning cycle implemented with syft.js would contain following steps:

  • Register into training cycle on PyGrid.
  • Download required model and Plans from PyGrid.
  • Execute the Plan with given model parameters and local user's data (multiple times) to create better model.
  • Submit difference between original and trained model parameters for aggregation.

These steps can be expressed in the following code:

import * as tf from '@tensorflow/tfjs-core';
import { Syft } from '@openmined/syft.js';

const gridUrl = 'ws://pygrid.myserver.com:5000';
const modelName = 'my-model';
const modelVersion = '1.0.0';

// if the model is protected with authentication token (optional)
const authToken = '...';

const worker = new Syft({ gridUrl, verbose: true });
const job = await worker.newJob({ modelName, modelVersion, authToken });
job.request();

job.on('accepted', async ({ model, clientConfig }) => {
  const batchSize = clientConfig.batch_size;
  const lr = clientConfig.lr;

  // Load data.
  const [data, target] = LOAD_DATA();
  const batches = MAKE_BATCHES(data, target, batchSize);

  // Load model parameters.
  let modelParams = model.params.map((p) => p.clone());

  // Main training loop.
  for (let [dataBatch, targetBatch] of batches) {
    // NOTE: this is just one possible example.
    // Plan name (e.g. 'training_plan'), its input arguments and outputs depends on FL configuration and actual Plan implementation.
    let updatedModelParams = await job.plans['training_plan'].execute(
      job.worker,
      dataBatch,
      targetBatch,
      batchSize,
      lr,
      ...modelParams
    );

    // Use updated model params in the next iteration.
    for (let i = 0; i < modelParams.length; i++) {
      modelParams[i].dispose();
      modelParams[i] = updatedModelParams[i];
    }
  }

  // Calculate & send model diff.
  const modelDiff = await model.createSerializedDiff(modelParams);
  await job.report(modelDiff);
});

job.on('rejected', ({ timeout }) => {
  // Handle the job rejection, e.g. re-try after timeout.
});

job.on('error', (err) => {
  // Handle errors.
});

Model Training API

The Plan execution and Model training can be implemented easier using training helper that will do training loop for you (model, batch size, etc. are automatically taken from Job):

  // Main training loop.
  const training = job.train('training_plan', {
    inputs: [/* ... */],
    outputs: [/* ... */],
    data,
    target,
  });

  training.on('end', async () => {
      // Calculate & send model diff.
      const modelDiff = await model.createSerializedDiff(modelParams);
      await job.report(modelDiff);
  });

inputs and outputs need to be specified using PlanInputSpec and PlanOutputSpec and need to match with Plan's arguments and outputs. For example, if the Plan has following arguments and outputs:

loss, accuracy, modelParams1, modelParams2, modelParams3, modelParams4 = 
    plan(dataBatch, targetBatch, batchSize, lr, modelParams1, modelParams2, modelParams3, modelParams4)

Corresponding inputs, outputs in job.train will be:

const inputs = [
    new PlanInputSpec(PlanInputSpec.TYPE_DATA),
    new PlanInputSpec(PlanInputSpec.TYPE_TARGET),
    new PlanInputSpec(PlanInputSpec.TYPE_BATCH_SIZE),
    new PlanInputSpec(PlanInputSpec.TYPE_CLIENT_CONFIG_PARAM, 'lr'),
    new PlanInputSpec(PlanInputSpec.TYPE_MODEL_PARAM, 'param1', 0),
    new PlanInputSpec(PlanInputSpec.TYPE_MODEL_PARAM, 'param2', 1),
    new PlanInputSpec(PlanInputSpec.TYPE_MODEL_PARAM, 'param3', 2),
    new PlanInputSpec(PlanInputSpec.TYPE_MODEL_PARAM, 'param4', 3),
];

const outputs = [
    new PlanOutputSpec(PlanOutputSpec.TYPE_LOSS),
    new PlanOutputSpec(PlanOutputSpec.TYPE_METRIC, 'accuracy'),
    new PlanOutputSpec(PlanOutputSpec.TYPE_MODEL_PARAM, 'param1', 0),
    new PlanOutputSpec(PlanOutputSpec.TYPE_MODEL_PARAM, 'param2', 1),
    new PlanOutputSpec(PlanOutputSpec.TYPE_MODEL_PARAM, 'param3', 2),
    new PlanOutputSpec(PlanOutputSpec.TYPE_MODEL_PARAM, 'param4', 3),
];

Stop & Resume

PlanTrainer allows stopping and resuming the training using stop and resume methods:

  // Main training loop.
  const training = job.train('training_plan', {
    inputs: [/* ... */],
    outputs: [/* ... */],
    data,
    target,
  });

  training.on('start', () => {
    // training is started!
  });

  training.on('stop', () => {
    // training is stopped!
  });

  document.getElementById('stop-button').onclick = () => {
    training.stop();
  };

  document.getElementById('resume-button').onclick = () => {
    training.resume();
  };

Checkpointing

stop method returns current training state as PlanTrainerCheckpoint object, which can be serialized to JSON to restored from JSON later to continue the training:

const checkpoint = await training.stop();
const checkpointJson = await checkpoint.toJSON();
const checkpointJsonString = JSON.stringify(checkpointJson);
localStorage.setItem('checkpoint', checkpointJsonString);

// ... checkpoint can survive page reload ...

const checkpointJsonString = localStorage.getItem('checkpoint');
const checkpointJson = JSON.parse(checkpointJsonString);
const checkpoint = PlanTrainerCheckpoint.fromJSON(worker, checkpointJson);
    
// Main training loop.
const training = job.train('training_plan', {
  // Pass checkpoint into train method to resume from it
  // NOTE: checkpoint doesn't store Plan and training data, these still need to be supplied
  checkpoint,
  inputs: [/* ... */],
  outputs: [/* ... */],
  data,
  target,
});

Checkpoint can be created directly from PlanTrainer object using createCheckpoint method and applied back using applyCheckpoint:

const checkpoint = training.createCheckpoint();
// ...
training.applyCheckpoint(checkpoint);
training.resume();

Datase

View on GitHub
GitHub Stars150
CategoryEducation
Updated6mo ago
Forks53

Languages

JavaScript

Security Score

92/100

Audited on Sep 13, 2025

No findings