typescript bindings maintenance (#2363)

* remove outdated comments

Signed-off-by: limez <limez@protonmail.com>

* simpler build from source

Signed-off-by: limez <limez@protonmail.com>

* update unix build script to create .so runtimes correctly

Signed-off-by: limez <limez@protonmail.com>

* configure ci build type, use RelWithDebInfo for dev build script

Signed-off-by: limez <limez@protonmail.com>

* add clean script

Signed-off-by: limez <limez@protonmail.com>

* fix streamed token decoding / emoji

Signed-off-by: limez <limez@protonmail.com>

* remove deprecated nCtx

Signed-off-by: limez <limez@protonmail.com>

* update typings

Signed-off-by: jacob <jacoobes@sern.dev>

update typings

Signed-off-by: jacob <jacoobes@sern.dev>

* readme,mspell

Signed-off-by: jacob <jacoobes@sern.dev>

* cuda/backend logic changes + name napi methods like their js counterparts

Signed-off-by: limez <limez@protonmail.com>

* convert llmodel example into a test, separate test suite that can run in ci

Signed-off-by: limez <limez@protonmail.com>

* update examples / naming

Signed-off-by: limez <limez@protonmail.com>

* update deps, remove the need for binding.ci.gyp, make node-gyp-build fallback easier testable

Signed-off-by: limez <limez@protonmail.com>

* make sure the assert-backend-sources.js script is published, but not the others

Signed-off-by: limez <limez@protonmail.com>

* build correctly on windows (regression on node-gyp-build)

Signed-off-by: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com>

* codespell

Signed-off-by: limez <limez@protonmail.com>

* make sure dlhandle.cpp gets linked correctly

Signed-off-by: limez <limez@protonmail.com>

* add include for check_cxx_compiler_flag call during aarch64 builds

Signed-off-by: limez <limez@protonmail.com>

* x86 > arm64 cross compilation of runtimes and bindings

Signed-off-by: limez <limez@protonmail.com>

* default to cpu instead of kompute on arm64

Signed-off-by: limez <limez@protonmail.com>

* formatting, more minimal example

Signed-off-by: limez <limez@protonmail.com>

---------

Signed-off-by: limez <limez@protonmail.com>
Signed-off-by: jacob <jacoobes@sern.dev>
Signed-off-by: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com>
Co-authored-by: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com>
Co-authored-by: jacob <jacoobes@sern.dev>
This commit is contained in:
Andreas Obersteiner
2024-06-03 18:12:55 +02:00
committed by GitHub
parent f001897a1a
commit a602f7fde7
30 changed files with 1112 additions and 873 deletions

View File

@@ -0,0 +1,47 @@
const fs = require("fs");
const path = require("path");
// Copies the shared llmodel sources from gpt4all-backend into the backend folder.
// These are dependencies of the bindings and will be required in case node-gyp-build
// cannot find a prebuild. This script is used in the package install hook and will
// be executed BOTH when `yarn install` is run in the root folder AND when the package
// is installed as a dependency in another project.
const backendDeps = [
"llmodel.h",
"llmodel.cpp",
"llmodel_c.cpp",
"llmodel_c.h",
"sysinfo.h",
"dlhandle.h",
"dlhandle.cpp",
];
const sourcePath = path.resolve(__dirname, "../../../gpt4all-backend");
const destPath = path.resolve(__dirname, "../backend");
// Silently ignore if the backend sources are not available.
// When the package is installed as a dependency, gpt4all-backend will not be present.
if (fs.existsSync(sourcePath)) {
if (!fs.existsSync(destPath)) {
fs.mkdirSync(destPath);
}
for (const file of backendDeps) {
const sourceFile = path.join(sourcePath, file);
const destFile = path.join(destPath, file);
if (fs.existsSync(sourceFile)) {
console.info(`Copying ${sourceFile} to ${destFile}`);
fs.copyFileSync(sourceFile, destFile); // overwrite
} else {
throw new Error(`File ${sourceFile} does not exist`);
}
}
}
// assert that the backend sources are present
for (const file of backendDeps) {
const destFile = path.join(destPath, file);
if (!fs.existsSync(destFile)) {
throw new Error(`File ${destFile} does not exist`);
}
}

View File

@@ -1,12 +1,42 @@
#!/bin/sh
# Build script for Unix-like systems (Linux, macOS).
# Script assumes the current working directory is the bindings project root.
SYSNAME=$(uname -s)
PLATFORM=$(uname -m)
# Allows overriding target sysname and platform via args
# If not provided, the current system's sysname and platform will be used
while [ $# -gt 0 ]; do
case "$1" in
--sysname=*)
SYSNAME="${1#*=}"
shift
;;
--platform=*)
PLATFORM="${1#*=}"
shift
;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
if [ "$SYSNAME" = "Linux" ]; then
BASE_DIR="runtimes/linux-x64"
if [ "$PLATFORM" = "x86_64" ]; then
BASE_DIR="runtimes/linux-x64"
elif [ "$PLATFORM" = "aarch64" ]; then
BASE_DIR="runtimes/linux-arm64"
else
echo "Unsupported platform: $PLATFORM" >&2
exit 1
fi
LIB_EXT="so"
elif [ "$SYSNAME" = "Darwin" ]; then
BASE_DIR="runtimes/osx"
BASE_DIR="runtimes/darwin"
LIB_EXT="dylib"
elif [ -n "$SYSNAME" ]; then
echo "Unsupported system: $SYSNAME" >&2
@@ -22,8 +52,24 @@ BUILD_DIR="$BASE_DIR/build"
rm -rf "$BASE_DIR"
mkdir -p "$NATIVE_DIR" "$BUILD_DIR"
cmake -S ../../gpt4all-backend -B "$BUILD_DIR" &&
cmake --build "$BUILD_DIR" -j --config Release && {
if [ "$PLATFORM" = "x86_64" ]; then
echo "Building for x86_64"
cmake -S ../../gpt4all-backend -B "$BUILD_DIR" -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
if [ "$PLATFORM" = "aarch64" ]; then
if [ "$(uname -m)" != "aarch64" ]; then
echo "Cross-compiling for aarch64"
cmake -S ../../gpt4all-backend \
-B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_TOOLCHAIN_FILE="./toolchains/linux-arm64-toolchain.cmake"
else
cmake -S ../../gpt4all-backend -B "$BUILD_DIR" -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
fi
cmake --build "$BUILD_DIR" --parallel && {
cp "$BUILD_DIR"/libgptj*.$LIB_EXT "$NATIVE_DIR"/
cp "$BUILD_DIR"/libllama*.$LIB_EXT "$NATIVE_DIR"/
}
}

View File

@@ -1,22 +1,21 @@
const prebuildify = require("prebuildify");
async function createPrebuilds(combinations) {
for (const { platform, arch } of combinations) {
async function createPrebuilds(configs) {
for (const config of configs) {
const opts = {
platform,
arch,
napi: true,
targets: ["18.16.0"]
targets: ["18.16.0"],
...config,
};
try {
await createPrebuild(opts);
console.log(
`Build succeeded for platform ${opts.platform} and architecture ${opts.arch}`
`Build succeeded for platform ${opts.platform} and architecture ${opts.arch}`,
);
} catch (err) {
console.error(
`Error building for platform ${opts.platform} and architecture ${opts.arch}:`,
err
err,
);
}
}
@@ -24,6 +23,17 @@ async function createPrebuilds(combinations) {
function createPrebuild(opts) {
return new Promise((resolve, reject) => {
// if this prebuild is cross-compiling for arm64 on a non-arm64 machine,
// set the CXX and CC environment variables to the cross-compilers
if (
opts.arch === "arm64" &&
process.arch !== "arm64" &&
process.platform === "linux"
) {
process.env.CXX = "aarch64-linux-gnu-g++-12";
process.env.CC = "aarch64-linux-gnu-gcc-12";
}
prebuildify(opts, (err) => {
if (err) {
reject(err);
@@ -35,22 +45,18 @@ function createPrebuild(opts) {
}
let prebuildConfigs;
if(process.platform === 'win32') {
prebuildConfigs = [
{ platform: "win32", arch: "x64" }
];
} else if(process.platform === 'linux') {
//Unsure if darwin works, need mac tester!
prebuildConfigs = [
{ platform: "linux", arch: "x64" },
//{ platform: "linux", arch: "arm64" },
//{ platform: "linux", arch: "armv7" },
]
} else if(process.platform === 'darwin') {
if (process.platform === "win32") {
prebuildConfigs = [{ platform: "win32", arch: "x64" }];
} else if (process.platform === "linux") {
prebuildConfigs = [
{ platform: "darwin", arch: "x64" },
{ platform: "darwin", arch: "arm64" },
]
{ platform: "linux", arch: "x64" },
{ platform: "linux", arch: "arm64" },
];
} else if (process.platform === "darwin") {
prebuildConfigs = [
{ platform: "darwin", arch: "x64" },
{ platform: "darwin", arch: "arm64" },
];
}
createPrebuilds(prebuildConfigs)