diff --git a/.github/workflows/cortex-build.yml b/.github/workflows/cortex-build.yml index 2ba76a72..9b22dc1b 100644 --- a/.github/workflows/cortex-build.yml +++ b/.github/workflows/cortex-build.yml @@ -392,14 +392,7 @@ jobs: node-version: "20.x" registry-url: "https://registry.npmjs.org" - - uses: actions/setup-python@v3 - with: - python-version: "3.10" - - - run: pip3 install --upgrade setuptools - if: runner.os == 'macOS' - - - run: yarn install && yarn build:binary + - run: yarn install && yarn build && yarn build:binary working-directory: ./cortex-js - name: Get Cer for code signing @@ -415,16 +408,11 @@ jobs: p12-file-base64: ${{ secrets.CODE_SIGN_P12_BASE64 }} p12-password: ${{ secrets.CODE_SIGN_P12_PASSWORD }} - - name: update app info - run: | - cd cortex-js - make update-app-info - - name: Code Signing macOS if: runner.os == 'macOS' run: | cd cortex-js - make codesign-binary CODE_SIGN=true DEVELOPER_ID="${{ secrets.DEVELOPER_ID }}" + make codesign CODE_SIGN=true DEVELOPER_ID="${{ secrets.DEVELOPER_ID }}" - name: Create MacOS PKG Installer if: runner.os == 'macOS' @@ -433,7 +421,6 @@ jobs: mkdir installer cp cortex installer/cortex pkgbuild --identifier ai.cortex.pkg --install-location ./usr/local/bin/ --root ./installer cortex-installer.pkg - make codesign-installer CODE_SIGN=true DEVELOPER_ID="${{ secrets.DEVELOPER_ID }}" - name: Create MacOS PKG Installer if: runner.os == 'Linux' @@ -445,20 +432,6 @@ jobs: cp cortex cortexso/usr/local/bin/cortex dpkg-deb --build cortexso - - uses: nick-fields/retry@v3 - with: - continue_on_error: true - retry_wait_seconds: 10 - timeout_minutes: 10 - max_attempts: 3 - shell: cmd - command: | - cd cortex-js - set PATH=%PATH%;%USERPROFILE%\.dotnet\tools - make codesign-binary CODE_SIGN=true CORTEX_VERSION="0.${{ needs.create-draft-release.outputs.version }}" AZURE_KEY_VAULT_URI="${{ secrets.AZURE_KEY_VAULT_URI }}" AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" AZURE_CERT_NAME="${{ secrets.AZURE_CERT_NAME }}" - name: Code Signing Windows - if: runner.os == 'Windows' - - name: Compile .ISS to .EXE Installer uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 if: runner.os == 'Windows' @@ -476,7 +449,7 @@ jobs: command: | cd cortex-js set PATH=%PATH%;%USERPROFILE%\.dotnet\tools - make codesign-installer CODE_SIGN=true CORTEX_VERSION="0.${{ needs.create-draft-release.outputs.version }}" AZURE_KEY_VAULT_URI="${{ secrets.AZURE_KEY_VAULT_URI }}" AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" AZURE_CERT_NAME="${{ secrets.AZURE_CERT_NAME }}" + make codesign CODE_SIGN=true AZURE_KEY_VAULT_URI="${{ secrets.AZURE_KEY_VAULT_URI }}" AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" AZURE_CERT_NAME="${{ secrets.AZURE_CERT_NAME }}" name: Code Signing Windows if: runner.os == 'Windows' diff --git a/.gitignore b/.gitignore index d3c4ef22..154cd292 100644 --- a/.gitignore +++ b/.gitignore @@ -4,17 +4,10 @@ dist *.lock node_modules .turbo -package-lock.json # CI - Test - Coverage cortex.log api.log prism.log api.json -openai-python/* -build -cortex-js/cortex.exe -cortex-js/package-lock.json -.vscode -cortex-js/command -cortex-js/src/infrastructure/commanders/test/test_data +openai-python/* \ No newline at end of file diff --git a/cortex-js/Makefile b/cortex-js/Makefile index 70468c6d..aa0c3062 100644 --- a/cortex-js/Makefile +++ b/cortex-js/Makefile @@ -5,36 +5,26 @@ AZURE_TENANT_ID ?= xxxx AZURE_CLIENT_SECRET ?= xxxx AZURE_CERT_NAME ?= xxxx DEVELOPER_ID ?= xxxx -CORTEX_EXE_IN ?= "dist/cortexso-win.exe" -CORTEX_EXE_OUT ?= "cortex.exe" -CORTEX_VERSION ?= "0.0.0.1" -update-app-info: -ifeq ($(OS),Windows_NT) - @powershell -Command 'npx resedit --in $(CORTEX_EXE_IN) --out $(CORTEX_EXE_OUT) --icon "1,cortex.ico" --no-grow --company-name "Homebrew Computer Pte Ltd" --file-description "cortex cli" --file-version "$(CORTEX_VERSION)" --internal-name "cortex" --product-name "cortex" --product-version "$(CORTEX_VERSION)"' -else ifeq ($(shell uname -s),Linux) - @cp ./dist/cortexso-linux ./cortex -else - @cp ./dist/cortexso-macos ./cortex -endif - -codesign-binary: -ifeq ($(CODE_SIGN),false) - @echo "Skipping Code Sign" +postbundle: +ifeq ($(RUN_TESTS),false) + @echo "Skipping tests" @exit 0 endif - ifeq ($(OS),Windows_NT) - @powershell -Command "dotnet tool install --global AzureSignTool;" - @powershell -Command 'azuresigntool.exe sign -kvu "$(AZURE_KEY_VAULT_URI)" -kvi "$(AZURE_CLIENT_ID)" -kvt "$(AZURE_TENANT_ID)" -kvs "$(AZURE_CLIENT_SECRET)" -kvc "$(AZURE_CERT_NAME)" -tr http://timestamp.globalsign.com/tsa/r6advanced1 -v ".\cortex-js\cortex.exe";' + @powershell -Command "7z a -ttar temp.tar cortex.exe; 7z a -tgzip cortex.tar.gz temp.tar;" + @powershell -Command "7z a -ttar temp2.tar setup.exe; 7z a -tgzip cortex-installer.tar.gz temp2.tar;" else ifeq ($(shell uname -s),Linux) - @echo "Skipping Code Sign for linux" - @exit 0 + @chmod +x cortex; + tar -czvf cortex.tar.gz cortex; else - find "cortex" -type f -exec codesign --force -s "$(DEVELOPER_ID)" --options=runtime {} \; + @chmod +x cortex; + tar -czvf cortex.tar.gz cortex; + tar -czvf cortex-installer.tar.gz cortex-installer.pkg; endif -codesign-installer: + +codesign: ifeq ($(CODE_SIGN),false) @echo "Skipping Code Sign" @exit 0 @@ -42,27 +32,11 @@ endif ifeq ($(OS),Windows_NT) @powershell -Command "dotnet tool install --global AzureSignTool;" + @powershell -Command 'azuresigntool.exe sign -kvu "$(AZURE_KEY_VAULT_URI)" -kvi "$(AZURE_CLIENT_ID)" -kvt "$(AZURE_TENANT_ID)" -kvs "$(AZURE_CLIENT_SECRET)" -kvc "$(AZURE_CERT_NAME)" -tr http://timestamp.globalsign.com/tsa/r6advanced1 -v ".\cortex-js\cortex.exe";' @powershell -Command 'azuresigntool.exe sign -kvu "$(AZURE_KEY_VAULT_URI)" -kvi "$(AZURE_CLIENT_ID)" -kvt "$(AZURE_TENANT_ID)" -kvs "$(AZURE_CLIENT_SECRET)" -kvc "$(AZURE_CERT_NAME)" -tr http://timestamp.globalsign.com/tsa/r6advanced1 -v ".\cortex-js\setup.exe";' else ifeq ($(shell uname -s),Linux) @echo "Skipping Code Sign for linux" @exit 0 else find "cortex" -type f -exec codesign --force -s "$(DEVELOPER_ID)" --options=runtime {} \; -endif - -postbundle: -ifeq ($(RUN_TESTS),false) - @echo "Skipping tests" - @exit 0 -endif -ifeq ($(OS),Windows_NT) - @powershell -Command "7z a -ttar temp.tar cortex.exe; 7z a -tgzip cortex.tar.gz temp.tar;" - @powershell -Command "7z a -ttar temp2.tar setup.exe; 7z a -tgzip cortex-installer.tar.gz temp2.tar;" -else ifeq ($(shell uname -s),Linux) - @chmod +x cortex; - tar -czvf cortex.tar.gz cortex; -else - @chmod +x cortex; - tar -czvf cortex.tar.gz cortex; - tar -czvf cortex-installer.tar.gz cortex-installer.pkg; endif \ No newline at end of file diff --git a/cortex-js/cpuinfo/bin/cpuinfo b/cortex-js/cpuinfo/bin/cpuinfo new file mode 100644 index 00000000..a4e172c3 Binary files /dev/null and b/cortex-js/cpuinfo/bin/cpuinfo differ diff --git a/cortex-js/cpuinfo/bin/cpuinfo.exe b/cortex-js/cpuinfo/bin/cpuinfo.exe new file mode 100644 index 00000000..c96c8192 Binary files /dev/null and b/cortex-js/cpuinfo/bin/cpuinfo.exe differ diff --git a/cortex-js/cpuinfo/binding.gyp b/cortex-js/cpuinfo/binding.gyp deleted file mode 100644 index 652246b5..00000000 --- a/cortex-js/cpuinfo/binding.gyp +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": [ - { - "target_name": "cpuinfo", - "sources": ["src/cpuinfo.cpp"], - "include_dirs": [ " -export type InstructionSet = 'AVX' | 'AVX2' | 'AVX512'; // Add more as needed later -declare module "cpuinfo" { - declare const cpuInfo: { - cpuInfo: () => InstructionSet[]; - } -} \ No newline at end of file diff --git a/cortex-js/cpuinfo/index.js b/cortex-js/cpuinfo/index.js deleted file mode 100644 index 2018ed99..00000000 --- a/cortex-js/cpuinfo/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = exports = { cpuInfo: require('./build/Release/cpuinfo.node') } diff --git a/cortex-js/cpuinfo/package.json b/cortex-js/cpuinfo/package.json deleted file mode 100644 index fc37fc89..00000000 --- a/cortex-js/cpuinfo/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "cpuinfo", - "version": "1.0.0", - "description": "Get CPU instructions", - "main": "index.js", - "types": "./index.d.ts", - "scripts": { - "install": "prebuild-install -r napi || node-gyp rebuild" - }, - "author": "", - "license": "ISC", - "gypfile": true, - "binary": { - "napi_versions": [ - 3, - 6 - ] - }, - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1" - }, - "devDependencies": { - "@types/node": "^20.14.9", - "typescript": "^5.5.3" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "files": [ - "binding.gyp", - "deps/", - "*.js", - "*.d.ts", - "src/" - ] -} diff --git a/cortex-js/cpuinfo/src/cpuinfo.cpp b/cortex-js/cpuinfo/src/cpuinfo.cpp index b0b947c1..9ba181ca 100644 --- a/cortex-js/cpuinfo/src/cpuinfo.cpp +++ b/cortex-js/cpuinfo/src/cpuinfo.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,88 +5,85 @@ #ifdef _WIN32 #include #include -typedef unsigned __int32 uint32_t; +typedef unsigned __int32 uint32_t; #else #include #endif using namespace std; -#if defined(_WIN32) || defined(LINUX) #define MAX_INTEL_TOP_LVL 4 -class CPUID -{ +class CPUID { uint32_t regs[4]; -public: - explicit CPUID(unsigned funcId, unsigned subFuncId) - { + public: + explicit CPUID(unsigned funcId, unsigned subFuncId) { #ifdef _WIN32 __cpuidex((int *)regs, (int)funcId, (int)subFuncId); #else - asm volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) - : "a"(funcId), "c"(subFuncId)); + asm volatile + ("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) + : "a" (funcId), "c" (subFuncId)); // ECX is set to zero for CPUID function 4 #endif } - const uint32_t &EAX() const { return regs[0]; } - const uint32_t &EBX() const { return regs[1]; } - const uint32_t &ECX() const { return regs[2]; } - const uint32_t &EDX() const { return regs[3]; } + const uint32_t &EAX() const {return regs[0];} + const uint32_t &EBX() const {return regs[1];} + const uint32_t &ECX() const {return regs[2];} + const uint32_t &EDX() const {return regs[3];} }; -class CPUInfo -{ -public: - CPUInfo(); - string vendor() const { return mVendorId; } - string model() const { return mModelName; } - int cores() const { return mNumCores; } - float cpuSpeedInMHz() const { return mCPUMHz; } - bool isSSE() const { return mIsSSE; } - bool isSSE2() const { return mIsSSE2; } - bool isSSE3() const { return mIsSSE3; } - bool isSSE41() const { return mIsSSE41; } - bool isSSE42() const { return mIsSSE42; } - bool isAVX() const { return mIsAVX; } - bool isAVX2() const { return mIsAVX2; } - bool isAVX512() const { return mIsAVX512; } - bool isHyperThreaded() const { return mIsHTT; } - int logicalCpus() const { return mNumLogCpus; } - -private: - // Bit positions for data extractions - static const uint32_t SSE_POS = 0x02000000; - static const uint32_t SSE2_POS = 0x04000000; - static const uint32_t SSE3_POS = 0x00000001; - static const uint32_t SSE41_POS = 0x00080000; - static const uint32_t SSE42_POS = 0x00100000; - static const uint32_t AVX_POS = 0x10000000; - static const uint32_t AVX2_POS = 0x00000020; - static const uint32_t AVX512_POS = 0x00010000; // AVX-512F bit in EBX from CPUID function 7 - static const uint32_t LVL_NUM = 0x000000FF; - static const uint32_t LVL_TYPE = 0x0000FF00; - static const uint32_t LVL_CORES = 0x0000FFFF; - - // Attributes - string mVendorId; - string mModelName; - int mNumSMT; - int mNumCores; - int mNumLogCpus; - float mCPUMHz; - bool mIsHTT; - bool mIsSSE; - bool mIsSSE2; - bool mIsSSE3; - bool mIsSSE41; - bool mIsSSE42; - bool mIsAVX; - bool mIsAVX2; - bool mIsAVX512; +class CPUInfo { + public: + CPUInfo(); + string vendor() const { return mVendorId; } + string model() const { return mModelName; } + int cores() const { return mNumCores; } + float cpuSpeedInMHz() const { return mCPUMHz; } + bool isSSE() const { return mIsSSE; } + bool isSSE2() const { return mIsSSE2; } + bool isSSE3() const { return mIsSSE3; } + bool isSSE41() const { return mIsSSE41; } + bool isSSE42() const { return mIsSSE42; } + bool isAVX() const { return mIsAVX; } + bool isAVX2() const { return mIsAVX2; } + bool isAVX512() const { return mIsAVX512; } + bool isHyperThreaded() const { return mIsHTT; } + int logicalCpus() const { return mNumLogCpus; } + + private: + // Bit positions for data extractions + static const uint32_t SSE_POS = 0x02000000; + static const uint32_t SSE2_POS = 0x04000000; + static const uint32_t SSE3_POS = 0x00000001; + static const uint32_t SSE41_POS = 0x00080000; + static const uint32_t SSE42_POS = 0x00100000; + static const uint32_t AVX_POS = 0x10000000; + static const uint32_t AVX2_POS = 0x00000020; + static const uint32_t AVX512_POS = 0x00010000; // AVX-512F bit in EBX from CPUID function 7 + static const uint32_t LVL_NUM = 0x000000FF; + static const uint32_t LVL_TYPE = 0x0000FF00; + static const uint32_t LVL_CORES = 0x0000FFFF; + + // Attributes + string mVendorId; + string mModelName; + int mNumSMT; + int mNumCores; + int mNumLogCpus; + float mCPUMHz; + bool mIsHTT; + bool mIsSSE; + bool mIsSSE2; + bool mIsSSE3; + bool mIsSSE41; + bool mIsSSE42; + bool mIsAVX; + bool mIsAVX2; + bool mIsAVX512; }; CPUInfo::CPUInfo() @@ -100,139 +96,99 @@ CPUInfo::CPUInfo() mVendorId += string((const char *)&cpuID0.ECX(), 4); // Get SSE instructions availability CPUID cpuID1(1, 0); - mIsHTT = cpuID1.EDX() & AVX_POS; - mIsSSE = cpuID1.EDX() & SSE_POS; - mIsSSE2 = cpuID1.EDX() & SSE2_POS; - mIsSSE3 = cpuID1.ECX() & SSE3_POS; + mIsHTT = cpuID1.EDX() & AVX_POS; + mIsSSE = cpuID1.EDX() & SSE_POS; + mIsSSE2 = cpuID1.EDX() & SSE2_POS; + mIsSSE3 = cpuID1.ECX() & SSE3_POS; mIsSSE41 = cpuID1.ECX() & SSE41_POS; mIsSSE42 = cpuID1.ECX() & SSE41_POS; - mIsAVX = cpuID1.ECX() & AVX_POS; + mIsAVX = cpuID1.ECX() & AVX_POS; // Get AVX2 and AVX512 instructions availability CPUID cpuID7(7, 0); - mIsAVX2 = cpuID7.EBX() & AVX2_POS; + mIsAVX2 = cpuID7.EBX() & AVX2_POS; mIsAVX512 = cpuID7.EBX() & AVX512_POS; string upVId = mVendorId; - for_each(upVId.begin(), upVId.end(), [](char &in) - { in = ::toupper(in); }); + for_each(upVId.begin(), upVId.end(), [](char& in) { in = ::toupper(in); }); // Get num of cores - if (upVId.find("INTEL") != std::string::npos) - { - if (HFS >= 11) - { - for (int lvl = 0; lvl < MAX_INTEL_TOP_LVL; ++lvl) - { - CPUID cpuID4(0x0B, lvl); - uint32_t currLevel = (LVL_TYPE & cpuID4.ECX()) >> 8; - switch (currLevel) - { - case 0x01: - mNumSMT = LVL_CORES & cpuID4.EBX(); - break; - case 0x02: - mNumLogCpus = LVL_CORES & cpuID4.EBX(); - break; - default: - break; - } + if (upVId.find("INTEL") != std::string::npos) { + if(HFS >= 11) { + for (int lvl=0; lvl>8; + switch(currLevel) { + case 0x01: mNumSMT = LVL_CORES & cpuID4.EBX(); break; + case 0x02: mNumLogCpus = LVL_CORES & cpuID4.EBX(); break; + default: break; + } } - mNumCores = mNumLogCpus / mNumSMT; - } - else - { - if (HFS >= 1) - { + mNumCores = mNumLogCpus/mNumSMT; + } else { + if (HFS>=1) { mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; - if (HFS >= 4) - { + if (HFS>=4) { mNumCores = 1 + (CPUID(4, 0).EAX() >> 26) & 0x3F; } } - if (mIsHTT) - { - if (!(mNumCores > 1)) - { + if (mIsHTT) { + if (!(mNumCores>1)) { mNumCores = 1; mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); } - } - else - { + } else { mNumCores = mNumLogCpus = 1; } } - } - else if (upVId.find("AMD") != std::string::npos) - { - if (HFS >= 1) - { + } else if (upVId.find("AMD") != std::string::npos) { + if (HFS>=1) { mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; - if (CPUID(0x80000000, 0).EAX() >= 8) - { + if (CPUID(0x80000000, 0).EAX() >=8) { mNumCores = 1 + (CPUID(0x80000008, 0).ECX() & 0xFF); } } - if (mIsHTT) - { - if (!(mNumCores > 1)) - { + if (mIsHTT) { + if (!(mNumCores>1)) { mNumCores = 1; mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); } - } - else - { + } else { mNumCores = mNumLogCpus = 1; } - } - else - { - cout << "Unexpected vendor id" << endl; + } else { + cout<< "Unexpected vendor id" </$1", "@commanders/(.*)$": "/../src/infrastructure/commanders/$1" } - }, - "pkg": { - "scripts": "command/**/*.js", - "assets": ["command/*.node", "**/package.json", "node_modules/axios/**/*", "cpuinfo/**/*"], - "outputPath": "dist" } } diff --git a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts index 0297fa0b..c9e1e701 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts @@ -1,5 +1,5 @@ import { cpSync, createWriteStream, existsSync, readdirSync, rmSync } from 'fs'; -import { join } from 'path'; +import { delimiter, join } from 'path'; import { HttpService } from '@nestjs/axios'; import { Presets, SingleBar } from 'cli-progress'; import decompress from 'decompress'; @@ -9,6 +9,8 @@ import { Injectable } from '@nestjs/common'; import { firstValueFrom } from 'rxjs'; import { FileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; import { rm } from 'fs/promises'; +import { exec } from 'child_process'; +import { appPath } from '@/utils/app-path'; import { CORTEX_ENGINE_RELEASES_URL, CORTEX_RELEASES_URL, @@ -16,8 +18,7 @@ import { } from '@/infrastructure/constants/cortex'; import { checkNvidiaGPUExist, cudaVersion } from '@/utils/cuda'; import { Engines } from '../types/engine.interface'; - -import { cpuInfo } from 'cpuinfo'; +import { checkModelCompatibility } from '@/utils/model-check'; @Injectable() export class InitCliUsecases { @@ -271,9 +272,35 @@ export class InitCliUsecases { private detectInstructions = (): Promise< 'AVX' | 'AVX2' | 'AVX512' | undefined > => { - const cpuInstruction = cpuInfo.cpuInfo()[0]?? 'AVX' - console.log(cpuInstruction, 'CPU instructions detected'); - return Promise.resolve(cpuInstruction); + return new Promise<'AVX' | 'AVX2' | 'AVX512' | undefined>((res) => { + // Execute the cpuinfo command + + exec( + join( + appPath, + `bin/cpuinfo${process.platform !== 'linux' ? '.exe' : ''}`, + ), + (error, stdout) => { + if (error) { + // If there's an error, it means lscpu is not installed + console.log('CPUInfo is not installed.'); + res('AVX'); + } else { + // If the command executes successfully, parse the output to detect CPU instructions + if (stdout.includes('"AVX512": "true"')) { + console.log('AVX-512 instructions detected.'); + res('AVX512'); + } else if ('"AVX2": "true"') { + console.log('AVX2 instructions detected.'); + res('AVX2'); + } else { + console.log('AVXs instructions detected.'); + res('AVX'); + } + } + }, + ); + }); }; /**