@vowpalwabbit/vowpalwabbit

0.0.7 • Public • Published

Vowpal Wabbit

Javascript bindings for VowpalWabbit

npmjs version Vowpal Wabbit version Vowpal Wabbit tag
0.0.3 9.8.0 wasm_v0.0.3
0.0.4 9.8.0 wasm_v0.0.4
0.0.5 9.8.0 wasm_v0.0.5
0.0.6 9.8.0 wasm_v0.0.6
0.0.7 9.9.0 wasm_v0.0.7

Documentation

API documentation

Examples and How-To

@vowpalwabbit/vowpalwabbit can be used both in nodejs and in ES6 environments.

How-To include the dependency and initialize a Contextual Bandit ADF model

Full API reference here

Require returns a promise because we need to wait for the WASM module to be initialized before including and using the VowpalWabbit JS code

A VW model needs to be deleted after we are done with its usage to return the aquired memory back to the WASM runtime.

NodeJS environments

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {
    let model = new vw.CbWorkspace({ args_str: "--cb_explore_adf" });
    model.delete()
});

ES6 environments

import { vwPromise } from '@vowpalwabbit/vowpalwabbit';

let vwModule = await vwPromise;

let model = new vwModule.CbWorkspace({ args_str: "--cb_explore_adf" });
model.delete()

The rest of the examples are shown with the nodejs require but the rest of the API usage is identical for both environments.

How-To call learn and predict on a Contextual Bandit model

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {
    let model = new vw.CbWorkspace({ args_str: "--cb_explore_adf" });

    let example = {
        text_context: `shared | s_1 s_2
            | a_1 b_1 c_1
            | a_2 b_2 c_2
            | a_3 b_3 c_3`,
        };

    let pred = model.predictAndSample(example);

    # user defined cost function
    let action_cost = calculate_cost_from_action(pred["action"])

    example.labels = [{ action: pred["action"], cost: action_cost, probability: pred["score"] }];

    model.learn(example);

    model.delete()
});

predictAndSample is a convenience function that samples the probability mass function that a call to vw.predict() returns. It is possible to first predict, get the entire pmf back, and then sample from it:

    let pred = model.predictAndSample(example);
    let uuid = pred["uuid"];
    let pred2 = model.predictAndSampleWithUUID(example, uuid);

predictAndSample and samplePmf generate and use a uuid during sampling. That uuid is available in the js object returned from both function calls and can be used for reproducability. A user defined uuid can also be specified with these calls:

    let pred = model.samplePmf(pmf);
    let uuid = pred["uuid"];
    let pred2 = model.samplePmfWithUUID(pmf, uuid);

or

    let chosen = model.samplePmf(pmf);
    let uuid = chosen["uuid"];
    let chosen2 = model.samplePmfWithUUID(pmf, uuid);

How-To save/load a model

There are two ways to save/load a model

Provide a file path where the model will be saved to or loaded from

Node's fs will be used to access the file and save/loading is blocking

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {
    let model = new vw.CbWorkspace({ args_str: "--cb_explore_adf" });

    let example = {
        text_context: `shared | s_1 s_2
            | a_1 b_1 c_1
            | a_2 b_2 c_2
            | a_3 b_3 c_3`,
        labels  = [{ action: 0, cost: 1.0, probability: 1}]
        };

    model.learn(example);
    model.saveModelToFile("my_model.vw");
    model.delete();

    let model2 = new vw.CbWorkspace({ model_file: "my_model.vw" });
    console.log(model2.predict(example));
    model2.delete();
});

A model can be loaded from a file either during model construction (shown above) or as a separate function call:

    model2.loadModelFromFile("my_model.vw");

Get the model or supply the model as a Uint8Array for user-handled storing

    # get model as Uint8Array and store it using fs
    let modelarray = model4.getModelAsArray();
    let filePath = path.join(__dirname, "my_model.vw");
    fs.writeFileSync(filePath, Buffer.from(modelarray));

    # load model as a Uint8Array and call load with it
    {
        let modelBuffer = fs.readFileSync(filePath);
        let ptr = vw.wasmModule._malloc(modelBuffer.byteLength);
        let heapBytes = new Uint8Array(vw.wasmModule.HEAPU8.buffer, ptr, modelBuffer.byteLength);
        heapBytes.set(new Uint8Array(modelBuffer));
        model.loadModelFromArray(ptr, modelBuffer.byteLength);
        vw.wasmModule._free(ptr);
    }

    # load model as Uint8Array and construct a new vw model with it
    {
        let modelBuffer = fs.readFileSync(filePath);
        let ptr = vw.wasmModule._malloc(modelBuffer.byteLength);
        let heapBytes = new Uint8Array(vw.wasmModule.HEAPU8.buffer, ptr, modelBuffer.byteLength);
        heapBytes.set(new Uint8Array(modelBuffer));
        let model = new vw.CbWorkspace({ model_array: [ptr, modelBuffer.byteLength] });
        vw.wasmModule._free(ptr);
        model.delete();
    }

How-To log examples into a file or stringify examples for user-handled logging (currently available for nodejs environments only)

A log stream can be started which will create and use a fs write stream:

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {

    let example = {
        text_context: `shared | s_1 s_2
            | a_1 b_1 c_1
            | a_2 b_2 c_2
            | a_3 b_3 c_3`,
        labels  = [{ action: 0, cost: 1.0, probability: 1}]
        };

    let model = new vw.CbWorkspace({ args_str: "--cb_explore_adf" });
    let vwLogger = new vw.VWExampleLogger();
    vwLogger.startLogStream("mylogfile.txt");
    vwLogger.logCBExampleToStream(example);
    vwLogger.endLogStream();
    model.delete();
});

There is also the option of stringifying an example for user-handled logging:

    let cbAsString = CBExampleToString(example);

Synchronous logging options are also available see API documentation

How-To train a model with data from a file

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {

    let model = new vw.CbWorkspace({ args_str: "--cb_explore_adf" });
    const fileStream = fs.createReadStream(filePath);
    const rl = readline.createInterface({
        input: fileStream,
        crlfDelay: Infinity,
        output: process.stdout,
        terminal: false,
    });


    rl.on('line', model.addLine.bind(model));

    rl.on('close', () => {
        assert(model.sumLoss() > 0);
        model.delete();
    });
});

How-To handle errors

Some function calls with throw if something went wrong or if they were called incorrectly. There are two type of errors that can be thrown: native JavaScript errors and WebAssembly runtime errors, the latter which are wrapped in a VWError object.

When logging an error to the console there needs to be a check of the error type and the logging needs to be handled accordingly:

try {}
catch (e)
{
    if (e.name === 'VWError') {
            console.error(vw.getExceptionMessage(e));
    }
    else {
        console.error(e);
    }
}

How-To use a generic VW model (non Contextual Bandit specific functionality)

Full API reference here

Simple regression example

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {

    let model = new vw.Workspace({ args_str: "" });
    let example = model.parse("|f 6:6.8953723e-02");
    let prediction = model.predict(example);
    model.finishExample(example);
    example.delete();
    model.delete();
});

CCB example

const vwPromise = require('@vowpalwabbit/vowpalwabbit');

vwPromise.then((vw) => {

    let model = new vw.Workspace({ args_str: "--ccb_explore_adf" });

    let example = model.parse(`
        ccb shared |User b
        ccb action |Action d
        ccb action |Action e
        ccb action |Action f
        ccb action |Action ff
        ccb action |Action fff
        ccb slot 0:0:0.2 |Slot h
        ccb slot 1:0:0.25 |Slot i
        ccb slot 2:0:0.333333 |Slot j
    `);

    let prediction = model.predict(example);

    assert(prediction[0][0].hasOwnProperty('action'));
    assert(prediction[0][0].hasOwnProperty('score'));

    model.finishExample(example);
    example.delete();
    model.delete();
});

Package Sidebar

Install

npm i @vowpalwabbit/vowpalwabbit

Weekly Downloads

5

Version

0.0.7

License

BSD-3-Clause

Unpacked Size

4.26 MB

Total Files

9

Last publish

Collaborators

  • jackgerrits
  • ataymano
  • olgavrou1
  • edums