UNPKG

@vowpalwabbit/vowpalwabbit

Version:
200 lines (199 loc) 9.23 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const vwModule = require('./vw.js').default; /** * A class that helps facilitate the stringification of Vowpal Wabbit examples, and the logging of Vowpal Wabbit examples to a file. * Currently available for use in nodejs environments only. * @class */ class VWExampleLogger { constructor() { this._outputLogStream = null; this._log_file = null; } /** * * Starts a log stream to the specified file. Any new logs will be appended to the file. * * @param {string} log_file the path to the file where the log will be appended to * @throws {Error} Throws an error if another logging stream has already been started */ startLogStream(log_file) { if (this._outputLogStream !== null) { throw new Error("Can not start log stream, another log stream is currently active. Call endLogStream first if you want to change the log file. Current log file: " + this._log_file); } else { this._log_file = log_file; this._outputLogStream = fs_1.default.createWriteStream(log_file, { flags: 'a' }); } } /** * Takes a string and appends it to the log file. Line is logged in an asynchronous manner. * * @param {string} line the line to be appended to the log file * @throws {Error} Throws an error if no logging stream has been started */ logLineToStream(line) { if (this._outputLogStream !== null) { this._outputLogStream.write(line); } else { throw new Error("Can not log line, log file is not specified. Call startLogStream first."); } } /** * Closes the logging stream. Logs a warning to the console if there is no logging stream active, but does not throw */ endLogStream() { if (this._outputLogStream !== null) { this._outputLogStream.end(); this._outputLogStream = null; this._log_file = null; } else { console.warn("Can not close log, log file is not specified"); } } /** * * Takes a string and appends it to the log file. Line is logged in a synchronous manner. * Every call to this function will open a new file handle, append the line and close the file handle. * * @param {string} log_file the path to the file where the log will be appended to * @param {string} line the line to be appended to the log file * @throws {Error} Throws an error if another logging stream has already been started */ logLineSync(log_file, line) { if (this._outputLogStream !== null && this._log_file === log_file) { throw new Error("Can not call logLineSync on log file while the same file has an async log writer active. Call endLogStream first. Log file: " + log_file); } fs_1.default.appendFileSync(log_file, line); } /** * * Takes a CB example and returns the string representation of it * * @param {object} example a CB example that will be stringified * @returns {string} the string representation of the CB example * @throws {Error} Throws an error if the example is malformed */ CBExampleToString(example) { let context = ""; if (example.hasOwnProperty('text_context')) { context = example.text_context; } else { throw new Error("Can not log example, there is no context available"); } const lines = context.trim().split("\n").map((substr) => substr.trim()); lines.push(""); lines.push(""); if (example.hasOwnProperty("labels") && example["labels"].length > 0) { let indexOffset = 0; if (context.includes("shared")) { indexOffset = 1; } for (let i = 0; i < example["labels"].length; i++) { let label = example["labels"][i]; if (label.action + indexOffset >= lines.length) { throw new Error("action index out of bounds: " + label.action); } lines[label.action + indexOffset] = label.action + ":" + label.cost + ":" + label.probability + " " + lines[label.action + indexOffset]; } } return lines.join("\n"); } /** * * Takes a CB example, stringifies it by calling CBExampleToString, and appends it to the log file. Line is logged in an asynchronous manner. * * @param {object} example a CB example that will be stringified and appended to the log file * @throws {Error} Throws an error if no logging stream has been started */ logCBExampleToStream(example) { let ex_str = this.CBExampleToString(example); this.logLineToStream(ex_str); } /** * * Takes a CB example, stringifies it by calling CBExampleToString, and appends it to the log file. Example is logged in a synchronous manner. * Every call to this function will open a new file handle, append the line and close the file handle. * * @param {string} log_file the path to the file where the log will be appended to * @param {object} example a CB example that will be stringified and appended to the log file * @throws {Error} Throws an error if another logging stream has already been started */ logCBExampleSync(log_file, example) { let ex_str = this.CBExampleToString(example); this.logLineSync(log_file, ex_str); } } ; module.exports = new Promise((resolve) => { vwModule.then((vw) => { /** * Nodejs wrapper around the Vowpal Wabbit C++ library. * @class * @extends vw.CbWorkspace */ class CbWorkspace extends vw.CbWorkspace { /** * Creates a new Vowpal Wabbit workspace for Contextual Bandit exploration algorithms. * Can accept either or both string arguments and a model file. * * @constructor * @param {string} [args_str] - The arguments that are used to initialize Vowpal Wabbit (optional) * @param {string} [model_file] - The path to the file where the model will be loaded from (optional) * @param {tuple} [model_array] - The pre-loaded model's array pointer and length (optional). * The memory must be allocated via the WebAssembly module's _malloc function and should later be freed via the _free function. * @throws {Error} Throws an error if: * - no argument is provided * - both string arguments and a model file are provided, and the string arguments and arguments defined in the model clash * - both string arguments and a model array are provided, and the string arguments and arguments defined in the model clash * - both a model file and a model array are provided */ constructor({ args_str, model_file, model_array } = {}) { super(fs_1.default.readFileSync, fs_1.default.writeFileSync, { args_str, model_file, model_array }); } } ; /** * Nodejs wrapper around the Vowpal Wabbit C++ library. * @class * @extends vw.Workspace */ class Workspace extends vw.Workspace { /** * Creates a new Vowpal Wabbit workspace. * Can accept either or both string arguments and a model file. * * @constructor * @param {string} [args_str] - The arguments that are used to initialize Vowpal Wabbit (optional) * @param {string} [model_file] - The path to the file where the model will be loaded from (optional) * @param {tuple} [model_array] - The pre-loaded model's array pointer and length (optional). * The memory must be allocated via the WebAssembly module's _malloc function and should later be freed via the _free function. * @throws {Error} Throws an error if: * - no argument is provided * - both string arguments and a model file are provided, and the string arguments and arguments defined in the model clash * - both string arguments and a model array are provided, and the string arguments and arguments defined in the model clash * - both a model file and a model array are provided */ constructor({ args_str, model_file, model_array } = {}) { super(fs_1.default.readFileSync, fs_1.default.writeFileSync, { args_str, model_file, model_array }); } } ; resolve({ Workspace: Workspace, CbWorkspace: CbWorkspace, Prediction: vw.Prediction, VWExampleLogger: VWExampleLogger, getExceptionMessage: vw.getExceptionMessage, wasmModule: vw.wasmModule, }); }); });