gpt4all-ts-client
Version:
GPT4All Typescript Client
202 lines (200 loc) • 7.24 kB
JavaScript
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/gpt4all.ts
import { exec, spawn } from "child_process";
import { promisify } from "util";
import * as fs from "fs";
import * as os from "os";
import cliProgress from "cli-progress";
import got from "got";
import debug from "debug";
var debugging = debug("gpt4all");
var downloadFile = (url, path) => __async(void 0, null, function* () {
debugging(`Downloading ${url} to ${path}`);
const stream = fs.createWriteStream(path);
const progressBar = new cliProgress.SingleBar(
{},
cliProgress.Presets.shades_classic
);
progressBar.start(100, 0);
const response = got.stream(url);
let totalLength = 0;
let downloadedLength = 0;
response.on("downloadProgress", (progress) => {
downloadedLength = progress.transferred;
totalLength = progress.total;
if (totalLength === 0)
return;
const progressPercent = downloadedLength / totalLength * 100;
progressBar.update(progressPercent);
});
response.pipe(stream);
return new Promise((resolve, reject) => {
stream.on("finish", () => {
progressBar.stop();
resolve(url);
});
stream.on("error", reject);
});
});
var GPT4All = class {
constructor(model = "gpt4all-lora-quantized", decoderConfig = {}) {
this.bot = null;
this.model = model;
this.decoderConfig = decoderConfig;
if ("gpt4all-lora-quantized" !== model && "gpt4all-lora-unfiltered-quantized" !== model) {
throw new Error(`Model ${model} is not supported. Current models supported are:
gpt4all-lora-quantized
gpt4all-lora-unfiltered-quantized`);
}
this.executablePath = os.platform() === "win32" ? `${os.homedir()}/.nomic/gpt4all.exe` : `${os.homedir()}/.nomic/gpt4all`;
this.modelPath = `${os.homedir()}/.nomic/${model}.bin`;
}
init(forceDownload = false) {
return __async(this, null, function* () {
debugging("Initializing GPT4All");
if (forceDownload || !fs.existsSync(this.executablePath)) {
yield this.downloadExecutable();
}
if (forceDownload || !fs.existsSync(this.modelPath)) {
yield this.downloadModel();
}
});
}
open() {
return __async(this, null, function* () {
debugging("Opening GPT4All");
if (this.bot !== null) {
this.close();
}
let spawnArgs = [this.executablePath, "--model", this.modelPath];
for (let [key, value] of Object.entries(this.decoderConfig)) {
spawnArgs.push(`--${key}`, value.toString());
}
this.bot = spawn(spawnArgs[0], spawnArgs.slice(1), {
stdio: ["pipe", "pipe", "ignore"]
});
yield new Promise((resolve) => {
var _a, _b;
(_b = (_a = this.bot) == null ? void 0 : _a.stdout) == null ? void 0 : _b.on("data", (data) => {
if (data.toString().includes(">")) {
resolve(true);
}
});
});
});
}
close() {
debugging("Closing GPT4All");
if (this.bot !== null) {
this.bot.kill();
this.bot = null;
}
}
downloadExecutable() {
return __async(this, null, function* () {
debugging("Downloading GPT4All executable");
let upstream;
const platform2 = os.platform();
if (platform2 === "darwin") {
const { stdout } = yield promisify(exec)("uname -m");
if (stdout.trim() === "arm64") {
upstream = "https://github.com/nomic-ai/gpt4all/blob/main/chat/gpt4all-lora-quantized-OSX-m1?raw=true";
} else {
upstream = "https://github.com/nomic-ai/gpt4all/blob/main/chat/gpt4all-lora-quantized-OSX-intel?raw=true";
}
} else if (platform2 === "linux") {
upstream = "https://github.com/nomic-ai/gpt4all/blob/main/chat/gpt4all-lora-quantized-linux-x86?raw=true";
} else if (platform2 === "win32") {
upstream = "https://github.com/nomic-ai/gpt4all/blob/main/chat/gpt4all-lora-quantized-win64.exe?raw=true";
} else {
throw new Error(
`Your platform is not supported: ${platform2}. Current binaries supported are for OSX (ARM and Intel), Linux and Windows.`
);
}
yield downloadFile(upstream, this.executablePath);
fs.chmod(this.executablePath, 493, (err) => {
if (err) {
throw err;
}
});
});
}
// TODO: support GPT4All community models
downloadModel() {
return __async(this, null, function* () {
debugging("Downloading GPT4All model");
const modelUrl = `https://the-eye.eu/public/AI/models/nomic-ai/gpt4all/${this.model}.bin`;
return downloadFile(modelUrl, this.modelPath);
});
}
prompt(prompt) {
var _a, _b;
debugging("Prompting GPT4All with:", prompt);
if (this.bot === null) {
throw new Error("Bot is not initialized.");
}
(_b = (_a = this.bot) == null ? void 0 : _a.stdin) == null ? void 0 : _b.write(prompt + "\n");
return new Promise((resolve, reject) => {
var _a2, _b2, _c, _d;
let response = "";
let timeoutId;
const onStdoutData = (data) => {
const text = data.toString();
if (timeoutId) {
clearTimeout(timeoutId);
}
if (text.includes(">")) {
debugging("Response starts with >, end of message - Resolving...");
terminateAndResolve(response);
} else {
timeoutId = setTimeout(() => {
debugging("Timeout reached - Resolving...");
terminateAndResolve(response);
}, 4e3);
}
debugging("Received text:", text);
response += text;
debugging("Updated response:", response);
};
const onStdoutError = (err) => {
var _a3, _b3, _c2, _d2;
(_b3 = (_a3 = this.bot) == null ? void 0 : _a3.stdout) == null ? void 0 : _b3.removeListener("data", onStdoutData);
(_d2 = (_c2 = this.bot) == null ? void 0 : _c2.stdout) == null ? void 0 : _d2.removeListener("error", onStdoutError);
reject(err);
};
const terminateAndResolve = (finalResponse) => {
var _a3, _b3, _c2, _d2;
(_b3 = (_a3 = this.bot) == null ? void 0 : _a3.stdout) == null ? void 0 : _b3.removeListener("data", onStdoutData);
(_d2 = (_c2 = this.bot) == null ? void 0 : _c2.stdout) == null ? void 0 : _d2.removeListener("error", onStdoutError);
if (finalResponse.endsWith(">")) {
finalResponse = finalResponse.slice(0, -1);
}
resolve(finalResponse);
};
(_b2 = (_a2 = this.bot) == null ? void 0 : _a2.stdout) == null ? void 0 : _b2.on("data", onStdoutData);
(_d = (_c = this.bot) == null ? void 0 : _c.stdout) == null ? void 0 : _d.on("error", onStdoutError);
});
}
};
export {
GPT4All
};