Skip to content

Commit

Permalink
[JS] Add GenAI Node.js bindings (#1193)
Browse files Browse the repository at this point in the history
Adding Node.js bindings for GenAI pipelines.

- 155187
- 158132

## Limitations
Current version it's primary backbone of future development. Supports
bindings of `LLMPipeline` only.

## TODO
- [x] Test build configuration
- [x] Integrate unit tests run into GHA
- [ ] Add script to download runtime binaries (after binaries
publication)

---------

Co-authored-by: Vladimir Zlobin <[email protected]>
  • Loading branch information
vishniakov-nikolai and Wovchena authored Jan 28, 2025
1 parent 4521bb6 commit 4fb48de
Show file tree
Hide file tree
Showing 39 changed files with 2,062 additions and 37 deletions.
148 changes: 116 additions & 32 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
runs-on: aks-linux-2-cores-8gb
container:
image: 'openvinogithubactions.azurecr.io/openvino_provider:0.1.0'
volumes:
volumes:
- /mount:/mount
- ${{ github.workspace }}:${{ github.workspace }}

Expand Down Expand Up @@ -114,11 +114,11 @@ jobs:
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -S ${{ env.SRC_DIR}} -B ${{ env.BUILD_DIR }}
cmake --build ${{ env.BUILD_DIR}} --config ${{ matrix.build-type }} --parallel $(nproc) --verbose
cmake --install ${{ env.BUILD_DIR }} --config ${{ matrix.build-type }} --prefix ${{ env.INSTALL_DIR }}
- name: Pack Artifacts
run: tar -cvf - * | pigz > ${{ env.BUILD_DIR }}/${{ env.GENAI_ARCHIVE_NAME }}
working-directory: ${{ env.INSTALL_DIR }}

- name: Upload Archive Distribution Package
if: ${{ always() }}
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
Expand All @@ -137,7 +137,7 @@ jobs:
runs-on: aks-linux-4-cores-16gb
container:
image: openvinogithubactions.azurecr.io/ov_build/ubuntu_22_04_x64:${{ needs.openvino_download.outputs.docker_tag }}
volumes:
volumes:
- /mount:/mount
- ${{ github.workspace }}:${{ github.workspace }}
options: -e SCCACHE_AZURE_BLOB_CONTAINER -e SCCACHE_AZURE_CONNECTION_STRING
Expand All @@ -161,35 +161,35 @@ jobs:
name: ${{ needs.openvino_download.outputs.ov_artifact_name }}
path: ${{ env.OV_INSTALL_DIR }}
merge-multiple: true

- name: Build Tokenizers Wheel
run: |
python -m pip wheel -v --no-deps --wheel-dir ${{ env.WHEELS_DIR }} \
--config-settings=override=cross.arch="manylinux_2_31_x86_64" \
${{ needs.openvino_download.outputs.ov_wheel_source }} \
${{ env.SRC_DIR }}/thirdparty/openvino_tokenizers
working-directory: ${{ env.OV_INSTALL_DIR }}

- name: Build GenAI Wheel
run: |
python -m pip wheel -v --no-deps --wheel-dir ${{ env.WHEELS_DIR }} \
--config-settings=override=cross.arch="manylinux_2_31_x86_64" \
${{ needs.openvino_download.outputs.ov_wheel_source }} \
${{ env.SRC_DIR }}
working-directory: ${{ env.OV_INSTALL_DIR }}

- name: Build WWB Wheel
run: python -m pip wheel -v --no-deps --wheel-dir ${{ env.WHEELS_DIR }} ${{ env.SRC_DIR }}/tools/who_what_benchmark
working-directory: ${{ env.OV_INSTALL_DIR }}

- name: Upload Wheels
if: ${{ always() }}
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: genai_wheels
path: ${{ env.INSTALL_DIR }}
if-no-files-found: 'error'

genai_build_samples:
name: Build Samples - ${{ matrix.build-type }}
strategy:
Expand All @@ -204,7 +204,7 @@ jobs:
runs-on: aks-linux-2-cores-8gb
container:
image: openvinogithubactions.azurecr.io/ov_build/ubuntu_22_04_x64:${{ needs.openvino_download.outputs.docker_tag }}
volumes:
volumes:
- /mount:/mount
- ${{ github.workspace }}:${{ github.workspace }}
options: -e SCCACHE_AZURE_BLOB_CONTAINER -e SCCACHE_AZURE_CONNECTION_STRING
Expand All @@ -228,25 +228,25 @@ jobs:
pattern: "{${{ needs.openvino_download.outputs.ov_artifact_name }},genai_archive_${{ matrix.build-type }}}"
path: ${{ env.OV_INSTALL_DIR }}
merge-multiple: true

- name: Extract Artifacts
run: pigz -dc ${{ env.GENAI_ARCHIVE_NAME }} | tar -xf - -C ${{ env.OV_INSTALL_DIR }}
working-directory: ${{ env.OV_INSTALL_DIR }}

- name: Build Samples (Release)
if: ${{ 'Release' == matrix.build-type }}
run: |
chmod +x ${{ env.OV_INSTALL_DIR }}/samples/cpp/build_samples.sh
${{ env.OV_INSTALL_DIR }}/samples/cpp/build_samples.sh -i ${{ env.INSTALL_DIR }}
- name: Build Samples (${{ matrix.build-type }})
if: ${{ 'Release' != matrix.build-type }}
run: |
source ${{ env.OV_INSTALL_DIR }}/setupvars.sh
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -S ${{ env.OV_INSTALL_DIR }}/samples/cpp/ -B ${{ env.BUILD_DIR }}
cmake --build ${{ env.BUILD_DIR }} --config ${{ matrix.build-type }} --parallel $(nproc)
cmake --install ${{ env.BUILD_DIR }} --config ${{ matrix.build-type }} --component samples_bin --prefix ${{ env.INSTALL_DIR }}
- name: Pack Artifacts
run: tar -cvf - * | pigz > ${{ env.INSTALL_DIR }}/${{ env.GENAI_SAMPLES_NAME }}
working-directory: ${{ env.INSTALL_DIR }}
Expand All @@ -258,7 +258,7 @@ jobs:
name: genai_samples_${{ matrix.build-type }}
path: ${{ env.INSTALL_DIR }}/*.tar.gz
if-no-files-found: 'error'

genai_tests_wheel:
name: Python (${{ matrix.test.name}}) Tests (wheel)
needs: [ openvino_download, genai_build_wheel ]
Expand All @@ -279,7 +279,7 @@ jobs:
runs-on: aks-linux-4-cores-16gb
container:
image: openvinogithubactions.azurecr.io/ov_test/ubuntu_22_04_x64:${{ needs.openvino_download.outputs.docker_tag }}
volumes:
volumes:
- /mount:/mount
- ${{ github.workspace }}:${{ github.workspace }}

Expand All @@ -289,47 +289,47 @@ jobs:
BUILD_DIR: ${{ github.workspace }}/build
TRANSFORMERS_CACHE: ${{ github.workspace }}/models # Hugging Face transformers cache
HF_HOME: ${{ github.workspace }}/datasets # Hugging Face datasets cache

steps:
- name: Clone openvino.genai
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: ${{ env.SRC_DIR }}
submodules: recursive

- name: Download Build Artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
pattern: "{${{ needs.openvino_download.outputs.ov_artifact_name }},genai_wheels}"
path: ${{ env.INSTALL_DIR }}
merge-multiple: true

- name: Install GenAI Wheels
uses: ./src/.github/actions/install_wheel
with:
packages: "openvino;openvino_tokenizers[transformers];openvino_genai;whowhatbench"
requirements_files: "${{ env.SRC_DIR }}/tests/python_tests/requirements.txt"
local_wheel_dir: ${{ env.INSTALL_DIR }}/wheels

- name: Tests
run: python -m pytest -v ./${{ matrix.test.cmd }}
working-directory: ${{ env.SRC_DIR }}

genai_samples_tests:
name: Samples Tests - ${{ matrix.build-type }}
strategy:
fail-fast: false
matrix:
build-type: [Release]
needs: [ openvino_download, genai_build_cmake, genai_build_wheel, genai_build_samples ]
needs: [ openvino_download, genai_build_cmake, genai_build_wheel, genai_build_samples ]
timeout-minutes: 45
defaults:
run:
shell: bash
runs-on: aks-linux-2-cores-8gb
container:
image: openvinogithubactions.azurecr.io/ov_test/ubuntu_22_04_x64:${{ needs.openvino_download.outputs.docker_tag }}
volumes:
volumes:
- /mount:/mount
- ${{ github.workspace }}:${{ github.workspace }}

Expand All @@ -338,41 +338,41 @@ jobs:
SRC_DIR: ${{ github.workspace }}/src
BUILD_DIR: ${{ github.workspace }}/build
MODELS_DIR: ${{ github.workspace }}/models

steps:
- name: Clone openvino.genai
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: ${{ env.SRC_DIR }}
submodules: recursive

- name: Download Build Artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
pattern: "{${{ needs.openvino_download.outputs.ov_artifact_name }},genai_archive_${{ matrix.build-type }},genai_samples_${{ matrix.build-type }},genai_wheels}"
path: ${{ env.INSTALL_DIR }}
merge-multiple: true

- name: Extract Artifacts
run: |
pigz -dc ${{ env.GENAI_ARCHIVE_NAME }} | tar -xf - -C ${{ env.INSTALL_DIR }}
pigz -dc ${{ env.GENAI_SAMPLES_NAME }} | tar -xf - -C ${{ env.INSTALL_DIR }}
working-directory: ${{ env.INSTALL_DIR }}

- name: Install Wheels
uses: ./src/.github/actions/install_wheel
with:
packages: "openvino;openvino_tokenizers[transformers];openvino_genai"
requirements_files: "${{ env.SRC_DIR }}/samples/requirements.txt"
local_wheel_dir: ${{ env.INSTALL_DIR }}/wheels

- name: Download & convert Models and data
run: |
mkdir -p ${{ env.MODELS_DIR }}
optimum-cli export openvino --trust-remote-code --model TinyLlama/TinyLlama-1.1B-Chat-v1.0 ${{ env.MODELS_DIR }}/TinyLlama-1.1B-Chat-v1.0
optimum-cli export openvino --trust-remote-code --model openai/whisper-tiny ${{ env.MODELS_DIR }}/whisper-tiny
wget https://storage.openvinotoolkit.org/models_contrib/speech/2021.2/librispeech_s5/how_are_you_doing_today.wav -O ${{ env.MODELS_DIR }}/how_are_you_doing_today.wav
- name: Test multinomial_causal_lm.py
if: ${{ 'Release' == matrix.build-type }} # Python bindings can be built in Release only
timeout-minutes: 1
Expand All @@ -384,10 +384,10 @@ jobs:
timeout-minutes: 1
run: ${{ env.INSTALL_DIR }}/samples/python/whisper_speech_recognition/whisper_speech_recognition.py ./whisper-tiny/ how_are_you_doing_today.wav
working-directory: ${{ env.MODELS_DIR }}

- name: C++ Tests Prerequisites
run: python -m pip uninstall openvino openvino-tokenizers openvino-genai -y

- name: Test greedy_causal_lm
run: |
source ${{ env.INSTALL_DIR }}/setupvars.sh
Expand All @@ -400,9 +400,93 @@ jobs:
${{ env.INSTALL_DIR }}/samples_bin/whisper_speech_recognition ./whisper-tiny/ how_are_you_doing_today.wav
working-directory: ${{ env.MODELS_DIR }}

genai_build_nodejs_bindings:
name: Build Node.js bindings
strategy:
fail-fast: false
matrix:
build-type: [Release]
needs: [ openvino_download ]
timeout-minutes: 20
defaults:
run:
shell: bash
runs-on: aks-linux-4-cores-16gb
container:
image: openvinogithubactions.azurecr.io/ov_build/ubuntu_22_04_x64:${{ needs.openvino_download.outputs.docker_tag }}
volumes:
- /mount:/mount
options: -e SCCACHE_AZURE_BLOB_CONTAINER -e SCCACHE_AZURE_CONNECTION_STRING -v ${{ github.workspace }}:${{ github.workspace }}
env:
CMAKE_GENERATOR: Unix Makefiles
OV_INSTALL_DIR: ${{ github.workspace }}/ov
BUILD_DIR: ${{ github.workspace }}/build
SRC_DIR: ${{ github.workspace }}/src

steps:
- name: Clone openvino.genai
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: ${{ env.SRC_DIR }}
submodules: recursive

- name: Download OpenVINO package
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: ${{ needs.openvino_download.outputs.ov_artifact_name }}
path: ${{ env.OV_INSTALL_DIR }}
merge-multiple: true

- name: Build with ENABLE_JS=ON
run: |
source ${{ env.OV_INSTALL_DIR }}/setupvars.sh
cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DENABLE_JS=ON -S ${{ env.SRC_DIR }} -B ${{ env.BUILD_DIR }}
cmake --build ${{ env.BUILD_DIR }} --config ${{ matrix.build-type }} --parallel $(nproc) --verbose
cmake --install ${{ env.BUILD_DIR }} --config ${{ matrix.build-type }} --prefix ${{ env.OV_INSTALL_DIR }}
- name: Combine binaries for Node.js package
run: |
mkdir -p nodejs
cp -r runtime/lib/intel64/* nodejs
cp -r runtime/3rdparty/tbb/lib/* nodejs
cp genai_node_addon.node nodejs
GENAI_VERSION=$(grep -oP '(?<=CMAKE_PROJECT_VERSION:STATIC=)[^"]*' ${{ env.BUILD_DIR }}/CMakeCache.txt)
OV_VERSION=$(echo $GENAI_VERSION | sed 's/..$//')
patchelf --set-rpath '$ORIGIN' nodejs/libopenvino.so.$OV_VERSION nodejs/libopenvino_genai.so.$GENAI_VERSION
working-directory: ${{ env.OV_INSTALL_DIR }}

- name: Pack Node.js bindings libs
run: tar -cvf - * | pigz > ${{ env.BUILD_DIR }}/genai_nodejs_bindings.tar.gz
working-directory: ${{ env.OV_INSTALL_DIR }}/nodejs

- name: Upload Archive Package with Node.js bindings
if: ${{ always() }}
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: genai_nodejs_bindings
path: ${{ env.BUILD_DIR }}/genai_nodejs_bindings.tar.gz
if-no-files-found: 'error'

- name: Run npm package tests
working-directory: ${{ env.SRC_DIR }}/src/js
run: |
cp -R ${{ env.OV_INSTALL_DIR }}/nodejs bin
npm install
npm test
- name: Install genai-node samples dependencies
run: npm install
working-directory: ${{ env.SRC_DIR }}/samples/js/text_generation

- name: Run samples tests
run: npm test
env:
MODEL_PATH: ${{ env.SRC_DIR }}/src/js/tests/models/Llama-3.1-8B-Instruct-FastDraft-150M-int8-ov
working-directory: ${{ env.SRC_DIR }}/samples/js/text_generation

Overall_Status:
name: ci/gha_overall_status_linux
needs: [openvino_download, genai_build_cmake, genai_build_wheel, genai_build_samples, genai_tests_wheel, genai_samples_tests]
needs: [openvino_download, genai_build_cmake, genai_build_wheel, genai_build_samples, genai_tests_wheel, genai_samples_tests, genai_build_nodejs_bindings]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
Expand Down
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ endif()

add_subdirectory(thirdparty)
add_subdirectory(src)
if(EXISTS "${OpenVINOGenAI_SOURCE_DIR}/samples")
if(EXISTS "${OpenVINOGenAI_SOURCE_DIR}/samples" AND ENABLE_SAMPLES)
add_subdirectory(samples)
endif()
if(EXISTS "${OpenVINOGenAI_SOURCE_DIR}/tools/continuous_batching")
Expand All @@ -109,6 +109,9 @@ set(CPACK_COMPONENTS_ALL core_genai core_genai_dev cpp_samples_genai licensing_g
if(ENABLE_PYTHON)
list(APPEND CPACK_COMPONENTS_ALL pygenai_${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR})
endif()
if(ENABLE_JS)
list(APPEND CPACK_COMPONENTS_ALL genai_node_addon)
endif()
if(WIN32 AND NOT DEFINED CPACK_GENERATOR)
set(CPACK_GENERATOR "ZIP")
endif()
Expand Down
7 changes: 7 additions & 0 deletions cmake/features.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@
#

option(ENABLE_PYTHON "Enable Python API build" ON)
option(ENABLE_JS "Enable JS API build" OFF)
option(ENABLE_SAMPLES "Enable samples build" ON)

# Disable building samples for NPM package
if(CPACK_GENERATOR STREQUAL "NPM")
set(ENABLE_SAMPLES OFF)
endif()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ find_python3 = true
build_args = ["--parallel", "--target", "py_openvino_genai_stub"]
install_args = ["--strip"]
install_components = ["wheel_genai"]
options = {"BUILD_TOKENIZERS" = "OFF"}
options = {"BUILD_TOKENIZERS" = "OFF", "ENABLE_SAMPLES" = "OFF"}

[build-system]
requires = [
Expand Down
1 change: 1 addition & 0 deletions samples/js/text_generation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
Loading

0 comments on commit 4fb48de

Please sign in to comment.