From 6955de37e9e3222a577bcf574041878a6946ac2a Mon Sep 17 00:00:00 2001 From: Pratyush Tiwary <36852896+pratyushtiwary@users.noreply.github.com> Date: Wed, 26 Apr 2023 21:44:56 +0530 Subject: [PATCH] Added `ctx_size` to the config --- bin/web/views/index.ejs | 3 +- index.js | 712 ++++++++++++++++++++++------------------ 2 files changed, 400 insertions(+), 315 deletions(-) diff --git a/bin/web/views/index.ejs b/bin/web/views/index.ejs index ffbddee..ca26545 100644 --- a/bin/web/views/index.ejs +++ b/bin/web/views/index.ejs @@ -230,6 +230,7 @@ repeat_last_n: 64, repeat_penalty: 1.3, debug: false, + ctx_size: 2048, models: [] } } @@ -241,7 +242,7 @@ const fields = [{ key: "debug", type: "checkbox" - }, "n_predict", "repeat_last_n", "repeat_penalty", "top_k", "top_p", "temp", "seed", "threads"].map((key) => { + }, "n_predict", "repeat_last_n", "repeat_penalty", "top_k", "top_p", "temp", "seed", "threads","ctx_size"].map((key) => { if (typeof key === "string") { return `
diff --git a/index.js b/index.js index ea1cf3a..6144677 100644 --- a/index.js +++ b/index.js @@ -1,46 +1,53 @@ -const os = require('os'); -const pty = require('node-pty'); +const os = require("os"); +const pty = require("node-pty"); //const pty = require('@cdktf/node-pty-prebuilt-multiarch'); -const git = require('isomorphic-git'); -const http = require('isomorphic-git/http/node'); -const Http = require("http") -const path = require('path'); +const git = require("isomorphic-git"); +const http = require("isomorphic-git/http/node"); +const Http = require("http"); +const path = require("path"); const fs = require("fs"); -const tar = require('tar'); +const tar = require("tar"); const { createServer } = require("http"); const { Server } = require("socket.io"); const { io } = require("socket.io-client"); -const term = require( 'terminal-kit' ).terminal; +const term = require("terminal-kit").terminal; const Downloader = require("nodejs-file-downloader"); -const semver = require('semver'); +const semver = require("semver"); //const _7z = require('7zip-min'); -const axios = require('axios') -const platform = os.platform() -const shell = platform === 'win32' ? 'powershell.exe' : 'bash'; -const L = require("./llama") -const A = require("./alpaca") -const TorrentDownloader = require("./torrent") -const exists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e))) -const escapeNewLine = (platform, arg) => platform === 'win32' ? arg.replaceAll(/\n/g, "\\n").replaceAll(/\r/g, "\\r") : arg -const escapeDoubleQuotes = (platform, arg) => platform === 'win32' ? arg.replaceAll(/"/g, '`"') : arg.replaceAll(/"/g, '\\"') +const axios = require("axios"); +const platform = os.platform(); +const shell = platform === "win32" ? "powershell.exe" : "bash"; +const L = require("./llama"); +const A = require("./alpaca"); +const TorrentDownloader = require("./torrent"); +const exists = (s) => + new Promise((r) => fs.access(s, fs.constants.F_OK, (e) => r(!e))); +const escapeNewLine = (platform, arg) => + platform === "win32" + ? arg.replaceAll(/\n/g, "\\n").replaceAll(/\r/g, "\\r") + : arg; +const escapeDoubleQuotes = (platform, arg) => + platform === "win32" + ? arg.replaceAll(/"/g, '`"') + : arg.replaceAll(/"/g, '\\"'); const stripAnsi = (str) => { const pattern = [ - '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', - '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))' - ].join('|'); + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))", + ].join("|"); - const regex = new RegExp(pattern, 'g') - return str.replace(regex, ''); -} + const regex = new RegExp(pattern, "g"); + return str.replace(regex, ""); +}; const winEscape = (str) => { return str - .replaceAll(/\\n/g, "\n") - .replaceAll(/\\r/g, "\r") - .replaceAll(/\\t/g, "\t") - .replaceAll(/\\b/g, "\b") - .replaceAll(/\\f/g, "\f") - .replaceAll(/\\/g, "") -} + .replaceAll(/\\n/g, "\n") + .replaceAll(/\\r/g, "\r") + .replaceAll(/\\t/g, "\t") + .replaceAll(/\\b/g, "\b") + .replaceAll(/\\f/g, "\f") + .replaceAll(/\\/g, ""); +}; class Dalai { constructor(home) { @@ -58,42 +65,63 @@ class Dalai { // Otherwise if you want to customize the path you can just pass in the "home" attribute to manually set it. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// - this.home = home ? path.resolve(home) : path.resolve(os.homedir(), "dalai") + this.home = home ? path.resolve(home) : path.resolve(os.homedir(), "dalai"); try { - console.log("mkdir", this.home) - fs.mkdirSync(this.home, { recursive: true }) + console.log("mkdir", this.home); + fs.mkdirSync(this.home, { recursive: true }); } catch (e) { - console.log("E", e) + console.log("E", e); } - this.torrent = new TorrentDownloader() + this.torrent = new TorrentDownloader(); this.config = { - name: 'xterm-color', + name: "xterm-color", cols: 1000, rows: 30, - } + }; this.cores = { llama: new L(this), alpaca: new A(this), - } + }; } - htmlencode (str) { - let encodedStr = ''; + htmlencode(str) { + let encodedStr = ""; for (let i = 0; i < str.length; i++) { let charCode = str.charCodeAt(i); if (charCode < 128) { // ASCII characters switch (str[i]) { - case '<': encodedStr += '<'; break; - case '>': encodedStr += '>'; break; - case '&': encodedStr += '&'; break; - case '"': encodedStr += '"'; break; - case '\'': encodedStr += '''; break; - case '\n': encodedStr += '
'; break; - case '\r': break; // ignore - case '\t': encodedStr += '    '; break; - case '\b': encodedStr += ' '; break; - case '\f': encodedStr += ' '; break; - default: encodedStr += String.fromCharCode(charCode); break; + case "<": + encodedStr += "<"; + break; + case ">": + encodedStr += ">"; + break; + case "&": + encodedStr += "&"; + break; + case '"': + encodedStr += """; + break; + case "'": + encodedStr += "'"; + break; + case "\n": + encodedStr += "
"; + break; + case "\r": + break; // ignore + case "\t": + encodedStr += "    "; + break; + case "\b": + encodedStr += " "; + break; + case "\f": + encodedStr += " "; + break; + default: + encodedStr += String.fromCharCode(charCode); + break; } } else { // Non-ASCII characters @@ -104,377 +132,419 @@ class Dalai { } down(url, dest, headers) { return new Promise((resolve, reject) => { - const task = path.basename(dest) - this.startProgress(task) + const task = path.basename(dest); + this.startProgress(task); axios({ url, - method: 'GET', - responseType: 'stream', + method: "GET", + responseType: "stream", maxContentLength: Infinity, headers, - onDownloadProgress: progressEvent => { + onDownloadProgress: (progressEvent) => { const progress = (progressEvent.loaded / progressEvent.total) * 100; - this.progress(task, progress) - } - - }).then(response => { - const writer = fs.createWriteStream(dest); - response.data.pipe(writer); - writer.on('finish', () => { - this.progressBar.update(1); - term("\n") - resolve() + this.progress(task, progress); + }, + }) + .then((response) => { + const writer = fs.createWriteStream(dest); + response.data.pipe(writer); + writer.on("finish", () => { + this.progressBar.update(1); + term("\n"); + resolve(); + }); + }) + .catch((error) => { + reject(error); }); - }).catch(error => { - reject(error) - }); - }) + }); } - async python () { + async python() { // install self-contained python => only for windows for now // 1. download // 2. unzip - const filename = "cpython-3.10.9+20230116-x86_64-pc-windows-msvc-shared-install_only.tar.gz" - const task = "downloading self contained python" + const filename = + "cpython-3.10.9+20230116-x86_64-pc-windows-msvc-shared-install_only.tar.gz"; + const task = "downloading self contained python"; const downloader = new Downloader({ url: `https://github.com/indygreg/python-build-standalone/releases/download/20230116/${filename}`, directory: this.home, onProgress: (percentage, chunk, remainingSize) => { - this.progress(task, percentage) + this.progress(task, percentage); }, }); try { - await this.startProgress(task) + await this.startProgress(task); await downloader.download(); } catch (error) { console.log(error); } this.progressBar.update(1); - console.log("extracting python") + console.log("extracting python"); await tar.x({ file: path.resolve(this.home, filename), C: this.home, - strict: true - }) - console.log("cleaning up temp files") - await fs.promises.rm(path.resolve(this.home, filename)) + strict: true, + }); + console.log("cleaning up temp files"); + await fs.promises.rm(path.resolve(this.home, filename)); } -// async mingw() { -// const mingw = "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z" -// const downloader = new Downloader({ -// url: mingw, -// directory: this.home, -// onProgress: (percentage, chunk, remainingSize) => { -// this.progress("download mingw", percentage) -// }, -// }); -// try { -// await this.startProgress("download mingw") -// await downloader.download(); -// } catch (error) { -// console.log(error); -// } -// this.progressBar.update(1); -// await new Promise((resolve, reject) => { -// _7z.unpack(path.resolve(this.home, "x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z"), this.home, (err) => { -// if (err) { -// reject(err) -// } else { -// resolve() -// } -// }) -// }) -// console.log("cleaning up temp files") -// await fs.promises.rm(path.resolve(this.home, "x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z")) -// } + // async mingw() { + // const mingw = "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z" + // const downloader = new Downloader({ + // url: mingw, + // directory: this.home, + // onProgress: (percentage, chunk, remainingSize) => { + // this.progress("download mingw", percentage) + // }, + // }); + // try { + // await this.startProgress("download mingw") + // await downloader.download(); + // } catch (error) { + // console.log(error); + // } + // this.progressBar.update(1); + // await new Promise((resolve, reject) => { + // _7z.unpack(path.resolve(this.home, "x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z"), this.home, (err) => { + // if (err) { + // reject(err) + // } else { + // resolve() + // } + // }) + // }) + // console.log("cleaning up temp files") + // await fs.promises.rm(path.resolve(this.home, "x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z")) + // } async query(req, cb) { - - console.log(`> query:`, req) + console.log(`> query:`, req); if (req.method === "installed") { - let models = await this.installed() - for(let model of models) { - cb(model) + let models = await this.installed(); + for (let model of models) { + cb(model); } - cb('\n\n') - return + cb("\n\n"); + return; } if (req.prompt && req.prompt.startsWith("/")) { try { - const mod = require(`./cmds/${req.prompt.slice(1)}`) + const mod = require(`./cmds/${req.prompt.slice(1)}`); if (mod) { - mod(this) - return + mod(this); + return; } } catch (e) { - console.log("require log", e) + console.log("require log", e); } } if (!req.prompt) { - return + return; } - let [Core, Model] = req.model.split(".") - Model = Model.toUpperCase() + let [Core, Model] = req.model.split("."); + Model = Model.toUpperCase(); - console.log( { Core, Model } ) + console.log({ Core, Model }); let o = { seed: req.seed || -1, threads: req.threads || 8, n_predict: req.n_predict || 128, model: `models/${Model || "7B"}/ggml-model-q4_0.bin`, - } + }; - let e = await exists(path.resolve(this.home, Core, "models", Model)) + let e = await exists(path.resolve(this.home, Core, "models", Model)); if (!e) { - cb(`File does not exist: ${Model}. Try "dalai ${Core} get ${Model}" first.`) - return + cb( + `File does not exist: ${Model}. Try "dalai ${Core} get ${Model}" first.` + ); + return; } - if (req.top_k) o.top_k = req.top_k - if (req.top_p) o.top_p = req.top_p - if (req.temp) o.temp = req.temp - if (req.batch_size) o.batch_size = req.batch_size - if (req.repeat_last_n) o.repeat_last_n = req.repeat_last_n - if (req.repeat_penalty) o.repeat_penalty = req.repeat_penalty - if (typeof req.interactive !== "undefined") o.interactive = req.interactive - - let chunks = [] - for(let key in o) { - chunks.push(`--${key} ${escapeDoubleQuotes(platform, o[key].toString())}`) + if (req.top_k) o.top_k = req.top_k; + if (req.top_p) o.top_p = req.top_p; + if (req.temp) o.temp = req.temp; + if (req.batch_size) o.batch_size = req.batch_size; + if (req.repeat_last_n) o.repeat_last_n = req.repeat_last_n; + if (req.repeat_penalty) o.repeat_penalty = req.repeat_penalty; + if (req.ctx_size) o.ctx_size = req.ctx_size; + if (typeof req.interactive !== "undefined") o.interactive = req.interactive; + + let chunks = []; + for (let key in o) { + chunks.push( + `--${key} ${escapeDoubleQuotes(platform, o[key].toString())}` + ); } - const escaped = escapeNewLine(platform, req.prompt) - const prompt = `"${escapeDoubleQuotes(platform, escaped)}"` + const escaped = escapeNewLine(platform, req.prompt); + const prompt = `"${escapeDoubleQuotes(platform, escaped)}"`; - chunks.push(`-p ${prompt}`) + chunks.push(`-p ${prompt}`); - const main_bin_path = platform === "win32" ? path.resolve(this.home, Core, "build", "Release", "main") : path.resolve(this.home, Core, "main") + const main_bin_path = + platform === "win32" + ? path.resolve(this.home, Core, "build", "Release", "main") + : path.resolve(this.home, Core, "main"); this.sessionBuffer = ""; this.bufferStarted = false; if (req.full) { - await this.exec(`${main_bin_path} ${chunks.join(" ")}`, this.cores[Core].home, cb) + await this.exec( + `${main_bin_path} ${chunks.join(" ")}`, + this.cores[Core].home, + cb + ); } else { - const startpattern = /.*sampling parameters:.*/g - const endpattern = /.*mem per token.*/g - let started = req.debug - let ended = false - let writeEnd = !req.skip_end - await this.exec(`${main_bin_path} ${chunks.join(" ")}`, this.cores[Core].home, (proc, msg) => { - if (endpattern.test(msg)) ended = true - if (started && !ended) { - this.buffer(req, msg, cb) - } else if (ended && writeEnd) { - cb('\n\n') - writeEnd = false + const startpattern = /.*sampling parameters:.*/g; + const endpattern = /.*mem per token.*/g; + let started = req.debug; + let ended = false; + let writeEnd = !req.skip_end; + await this.exec( + `${main_bin_path} ${chunks.join(" ")}`, + this.cores[Core].home, + (proc, msg) => { + if (endpattern.test(msg)) ended = true; + if (started && !ended) { + this.buffer(req, msg, cb); + } else if (ended && writeEnd) { + cb("\n\n"); + writeEnd = false; + } + if (startpattern.test(msg)) started = true; } - if (startpattern.test(msg)) started = true - }) + ); } } buffer(req, msg, cb) { - if (!this.queue) this.queue = [] + if (!this.queue) this.queue = []; if (platform === "win32") { - for(let i=0;i 0) { // delete the model folder - const modelsPath = path.resolve(this.home, core, "models") - for(let model of models) { - const modelPath = path.resolve(modelsPath, model) - console.log("rm", modelPath) - await fs.promises.rm(modelPath, { recursive: true, force: true }).catch((e) => { - console.log("rm", modelPath, e) - }) + const modelsPath = path.resolve(this.home, core, "models"); + for (let model of models) { + const modelPath = path.resolve(modelsPath, model); + console.log("rm", modelPath); + await fs.promises + .rm(modelPath, { recursive: true, force: true }) + .catch((e) => { + console.log("rm", modelPath, e); + }); } } } async install(core, ...models) { + let engine = this.cores[core]; - let engine = this.cores[core] - - const venv_path = path.join(this.home, "venv") - let ve = await exists(venv_path) + const venv_path = path.join(this.home, "venv"); + let ve = await exists(venv_path); if (!ve) { - await this.setup() + await this.setup(); } // temporary - let models_path = path.resolve(engine.home, "models") - let temp_path = path.resolve(this.home, "tmp") - let temp_models_path = path.resolve(temp_path, "models") - await fs.promises.mkdir(temp_path, { recursive: true }).catch((e) => { console.log("1", e) }) + let models_path = path.resolve(engine.home, "models"); + let temp_path = path.resolve(this.home, "tmp"); + let temp_models_path = path.resolve(temp_path, "models"); + await fs.promises.mkdir(temp_path, { recursive: true }).catch((e) => { + console.log("1", e); + }); // 1. move the models folder to ../tmp - await fs.promises.rename(models_path, temp_models_path).catch((e) => { console.log("2", e) }) + await fs.promises.rename(models_path, temp_models_path).catch((e) => { + console.log("2", e); + }); // 2. wipe out the folder - await fs.promises.rm(engine.home, { recursive: true }).catch((e) => { console.log("3", e) }) + await fs.promises.rm(engine.home, { recursive: true }).catch((e) => { + console.log("3", e); + }); // 3. install engine - await this.add(core) + await this.add(core); // 4. move back the files inside /tmp - await fs.promises.rename(temp_models_path, models_path).catch((e) => { console.log("4", e) }) + await fs.promises.rename(temp_models_path, models_path).catch((e) => { + console.log("4", e); + }); // next add the models - let res = await this.cores[core].add(...models) - return res + let res = await this.cores[core].add(...models); + return res; } async installed() { // get cores - const modelNames = [] - for(let core of ["alpaca", "llama"]) { - const modelsPath = path.resolve(this.home, core, "models") - console.log("modelsPath", modelsPath) - let modelFolders = [] + const modelNames = []; + for (let core of ["alpaca", "llama"]) { + const modelsPath = path.resolve(this.home, core, "models"); + console.log("modelsPath", modelsPath); + let modelFolders = []; try { - modelFolders = (await fs.promises.readdir(modelsPath, { withFileTypes: true })) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name) - } catch (e) { - } - - console.log({ modelFolders }) - for(let modelFolder of modelFolders) { - let e = await exists(path.resolve(modelsPath, modelFolder, 'ggml-model-q4_0.bin')) + modelFolders = ( + await fs.promises.readdir(modelsPath, { withFileTypes: true }) + ) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name); + } catch (e) {} + + console.log({ modelFolders }); + for (let modelFolder of modelFolders) { + let e = await exists( + path.resolve(modelsPath, modelFolder, "ggml-model-q4_0.bin") + ); if (e) { - modelNames.push(`${core}.${modelFolder}`) - console.log("exists", modelFolder) + modelNames.push(`${core}.${modelFolder}`); + console.log("exists", modelFolder); } } } - return modelNames + return modelNames; } - async add (core) { + async add(core) { /************************************************************************************************************** - * - * 2. Download Core - * - **************************************************************************************************************/ - let engine = this.cores[core] + * + * 2. Download Core + * + **************************************************************************************************************/ + let engine = this.cores[core]; let e = await exists(path.resolve(engine.home)); - console.log("mkdir", path.resolve(engine.home)) - await fs.promises.mkdir(path.resolve(engine.home), { recursive: true }).catch((e) => { - console.log("ERROR" ,e) - }) + console.log("mkdir", path.resolve(engine.home)); + await fs.promises + .mkdir(path.resolve(engine.home), { recursive: true }) + .catch((e) => { + console.log("ERROR", e); + }); try { - console.log("try fetching", engine.home, engine.url) - await git.pull({ fs, http, dir: engine.home, url: engine.url }) + console.log("try fetching", engine.home, engine.url); + await git.pull({ fs, http, dir: engine.home, url: engine.url }); } catch (e) { - console.log("[E] Pull", e) + console.log("[E] Pull", e); try { - console.log("try cloning", engine.home, engine.url) - await git.clone({ fs, http, dir: engine.home, url: engine.url }) + console.log("try cloning", engine.home, engine.url); + await git.clone({ fs, http, dir: engine.home, url: engine.url }); } catch (e2) { - console.log("[E] Clone", e2) + console.log("[E] Clone", e2); } } console.log("next", core, engine.make); /************************************************************************************************************** - * - * 4. Compile & Build - * - make: linux + mac - * - cmake: windows - * - **************************************************************************************************************/ - await engine.make() + * + * 4. Compile & Build + * - make: linux + mac + * - cmake: windows + * + **************************************************************************************************************/ + await engine.make(); } async setup() { - let success; /************************************************************************************************************** - * - * 1. Validate - * - **************************************************************************************************************/ + * + * 1. Validate + * + **************************************************************************************************************/ // Check if current version is greater than or equal to 18 const node_version = process.version; - if (!semver.gte(node_version, '18.0.0')) { - throw new Error("outdated Node version, please install Node 18 or newer") + if (!semver.gte(node_version, "18.0.0")) { + throw new Error("outdated Node version, please install Node 18 or newer"); } /************************************************************************************************************** - * - * 3. Download Global Dependencies - * - Python (windows only) - * - build-essential (linux only) - * - virtualenv - * - torch, numpy, etc. - * - **************************************************************************************************************/ + * + * 3. Download Global Dependencies + * - Python (windows only) + * - build-essential (linux only) + * - virtualenv + * - torch, numpy, etc. + * + **************************************************************************************************************/ // 3.1. Python: Windows doesn't ship with python, so install a dedicated self-contained python if (platform === "win32") { - await this.python() + await this.python(); } - const root_python_paths = (platform === "win32" ? ["python3", "python", path.resolve(this.home, "python", "python.exe")] : ["python3", "python"]) - const root_pip_paths = (platform === "win32" ? ["pip3", "pip", path.resolve(this.home, "python", "python -m pip")] : ["pip3", "pip"]) + const root_python_paths = + platform === "win32" + ? ["python3", "python", path.resolve(this.home, "python", "python.exe")] + : ["python3", "python"]; + const root_pip_paths = + platform === "win32" + ? ["pip3", "pip", path.resolve(this.home, "python", "python -m pip")] + : ["pip3", "pip"]; // 3.2. Build tools if (platform === "linux") { // ubuntu debian - success = await this.exec("apt-get install build-essential python3-venv -y") + success = await this.exec( + "apt-get install build-essential python3-venv -y" + ); if (!success) { // fefdora - success = await this.exec("dnf install make automake gcc gcc-c++ kernel-devel python3-virtualenv -y") + success = await this.exec( + "dnf install make automake gcc gcc-c++ kernel-devel python3-virtualenv -y" + ); } } else { // for win32 / darwin - for(let root_pip_path of root_pip_paths) { - success = await this.exec(`${root_pip_path} install --user virtualenv`) + for (let root_pip_path of root_pip_paths) { + success = await this.exec(`${root_pip_path} install --user virtualenv`); if (success) { break; } - success = await this.exec(`${root_pip_path} install virtualenv`) + success = await this.exec(`${root_pip_path} install virtualenv`); if (success) { break; } } if (!success) { - throw new Error("cannot install virtualenv") + throw new Error("cannot install virtualenv"); } - } // 3.3. virtualenv - const venv_path = path.join(this.home, "venv") - for(let root_python_path of root_python_paths) { - console.log("trying with", root_python_path) - let code = await this.exec(`${root_python_path} -m venv ${venv_path}`) - console.log({ code }) + const venv_path = path.join(this.home, "venv"); + for (let root_python_path of root_python_paths) { + console.log("trying with", root_python_path); + let code = await this.exec(`${root_python_path} -m venv ${venv_path}`); + console.log({ code }); } /* if (!success) { @@ -484,86 +554,98 @@ class Dalai { */ // 3.4. Python libraries - const pip_path = platform === "win32" ? path.join(venv_path, "Scripts", "pip.exe") : path.join(venv_path, "bin", "pip") - const python_path = platform == "win32" ? path.join(venv_path, "Scripts", "python.exe") : path.join(venv_path, 'bin', 'python') + const pip_path = + platform === "win32" + ? path.join(venv_path, "Scripts", "pip.exe") + : path.join(venv_path, "bin", "pip"); + const python_path = + platform == "win32" + ? path.join(venv_path, "Scripts", "python.exe") + : path.join(venv_path, "bin", "python"); // cmake (only on windows. the rest platforms use make) if (platform === "win32") { - success = await this.exec(`${pip_path} install cmake`) + success = await this.exec(`${pip_path} install cmake`); if (!success) { - throw new Error("cmake installation failed") - return + throw new Error("cmake installation failed"); + return; } } - success = await this.exec(`${pip_path} install --upgrade pip setuptools wheel`) + success = await this.exec( + `${pip_path} install --upgrade pip setuptools wheel` + ); if (!success) { - success = await this.exec(`${pip_path} install --user --upgrade pip setuptools wheel`) + success = await this.exec( + `${pip_path} install --user --upgrade pip setuptools wheel` + ); if (!success) { - throw new Error("pip setuptools wheel upgrade failed") - return + throw new Error("pip setuptools wheel upgrade failed"); + return; } } - success = await this.exec(`${pip_path} install torch torchvision torchaudio sentencepiece numpy`) + success = await this.exec( + `${pip_path} install torch torchvision torchaudio sentencepiece numpy` + ); //success = await this.exec(`${pip_path} install torch torchvision torchaudio sentencepiece numpy wget`) if (!success) { - success = await this.exec(`${pip_path} install --user torch torchvision torchaudio sentencepiece numpy`) + success = await this.exec( + `${pip_path} install --user torch torchvision torchaudio sentencepiece numpy` + ); if (!success) { - throw new Error("dependency installation failed") - return + throw new Error("dependency installation failed"); + return; } } - - } serve(port, options) { const httpServer = createServer(); - const io = new Server(httpServer) + const io = new Server(httpServer); io.on("connection", (socket) => { - socket.on('request', async (req) => { + socket.on("request", async (req) => { await this.query(req, (str) => { - io.emit("result", { response: str, request: req }) - }) + io.emit("result", { response: str, request: req }); + }); }); }); - httpServer.listen(port) + httpServer.listen(port); } http(httpServer) { - const io = new Server(httpServer) + const io = new Server(httpServer); io.on("connection", (socket) => { - socket.on('request', async (req) => { - req.models = Array.from(new Set(req.models)) + socket.on("request", async (req) => { + req.models = Array.from(new Set(req.models)); await this.query(req, (str) => { - io.emit("result", { response: str, request: req }) - }) + io.emit("result", { response: str, request: req }); + }); }); }); } async request(req, cb) { if (req.url) { - await this.connect(req, cb) + await this.connect(req, cb); } else { - await this.query(req, cb) + await this.query(req, cb); } } connect(req, cb) { - const socket = io(req.url) - socket.emit('request', req) - socket.on('response', cb) - socket.on('error', function(e) { - throw e + const socket = io(req.url); + socket.emit("request", req); + socket.on("response", cb); + socket.on("error", function (e) { + throw e; }); } exec(cmd, cwd, cb) { return new Promise((resolve, reject) => { try { - const config = Object.assign({}, this.config) + const config = Object.assign({}, this.config); if (cwd) { - config.cwd = path.resolve(cwd) + config.cwd = path.resolve(cwd); } - console.log(`exec: ${cmd} in ${config.cwd}`) - this.ptyProcess = pty.spawn(shell, [], config) + console.log(`exec: ${cmd} in ${config.cwd}`); + this.ptyProcess = pty.spawn(shell, [], config); this.ptyProcess.onData((data) => { if (cb) { - cb(this.ptyProcess, stripAnsi(data)) + cb(this.ptyProcess, stripAnsi(data)); } else { process.stdout.write(data); } @@ -571,28 +653,30 @@ class Dalai { this.ptyProcess.onExit((res) => { if (res.exitCode === 0) { // successful - resolve(true) + resolve(true); } else { // something went wrong - resolve(false) + resolve(false); } }); if (platform === "win32") { - this.ptyProcess.write(`[System.Console]::OutputEncoding=[System.Console]::InputEncoding=[System.Text.Encoding]::UTF8; ${cmd}\r`) + this.ptyProcess.write( + `[System.Console]::OutputEncoding=[System.Console]::InputEncoding=[System.Text.Encoding]::UTF8; ${cmd}\r` + ); } else { - this.ptyProcess.write(`${cmd}\r`) + this.ptyProcess.write(`${cmd}\r`); } - this.ptyProcess.write("exit\r") + this.ptyProcess.write("exit\r"); } catch (e) { - console.log("caught error", e) - this.ptyProcess.kill() + console.log("caught error", e); + this.ptyProcess.kill(); // ptyProcess.write("exit\r") } - }) + }); } progress(task, percent) { - this.progressBar.update(percent/100); + this.progressBar.update(percent / 100); //if (percent >= 100) { // setTimeout(() => { // term("\n") @@ -603,9 +687,9 @@ class Dalai { this.progressBar = term.progressBar({ width: 120, title, - eta: true , - percent: true + eta: true, + percent: true, }); } } -module.exports = Dalai +module.exports = Dalai;