@@ -16,6 +16,7 @@ import {
1616 CORTEX_RELEASES_URL ,
1717 CUDA_DOWNLOAD_URL ,
1818} from '@/infrastructure/constants/cortex' ;
19+ import { checkNvidiaGPUExist , cudaVersion } from '@/utils/cuda' ;
1920
2021@Injectable ( )
2122export class InitCliUsecases {
@@ -24,10 +25,41 @@ export class InitCliUsecases {
2425 private readonly fileManagerService : FileManagerService ,
2526 ) { }
2627
28+ /**
29+ * Default installation options base on the system
30+ * @returns
31+ */
32+ defaultInstallationOptions = async ( ) : Promise < InitOptions > => {
33+ let options : InitOptions = { } ;
34+
35+ // Skip check if darwin
36+ if ( process . platform === 'darwin' ) {
37+ return options ;
38+ }
39+ // If Nvidia Driver is installed -> GPU
40+ options . runMode = ( await checkNvidiaGPUExist ( ) ) ? 'GPU' : 'CPU' ;
41+ options . gpuType = 'Nvidia' ;
42+ //CPU Instructions detection
43+ options . instructions = await this . detectInstructions ( ) ;
44+ return options ;
45+ } ;
46+
47+ /**
48+ * Install Engine and Dependencies with given options
49+ * @param engineFileName
50+ * @param version
51+ */
2752 installEngine = async (
28- engineFileName : string ,
53+ options : InitOptions ,
2954 version : string = 'latest' ,
55+ force : boolean = true ,
3056 ) : Promise < any > => {
57+ const configs = await this . fileManagerService . getConfig ( ) ;
58+
59+ if ( configs . initialized && ! force ) return ;
60+
61+ const engineFileName = this . parseEngineFileName ( options ) ;
62+
3163 const res = await firstValueFrom (
3264 this . httpService . get (
3365 CORTEX_RELEASES_URL + `${ version === 'latest' ? '/latest' : '' } ` ,
@@ -40,14 +72,14 @@ export class InitCliUsecases {
4072 ) ,
4173 ) ;
4274
43- if ( ! res ? .data ) {
75+ if ( ! res . data ) {
4476 console . log ( 'Failed to fetch releases' ) ;
4577 exit ( 1 ) ;
4678 }
4779
48- let release = res ? .data ;
49- if ( Array . isArray ( res ? .data ) ) {
50- release = Array ( res ? .data ) [ 0 ] . find (
80+ let release = res . data ;
81+ if ( Array . isArray ( res . data ) ) {
82+ release = Array ( res . data ) [ 0 ] . find (
5183 ( e ) => e . name === version . replace ( 'v' , '' ) ,
5284 ) ;
5385 }
@@ -109,13 +141,28 @@ export class InitCliUsecases {
109141 console . error ( 'Error decompressing file' , e ) ;
110142 exit ( 1 ) ;
111143 }
144+
112145 await rm ( destination , { force : true } ) ;
113146
147+ // If the user selected GPU mode and Nvidia GPU, install CUDA Toolkit dependencies
148+ if ( options . runMode === 'GPU' && ! ( await cudaVersion ( ) ) ) {
149+ await this . installCudaToolkitDependency ( options . cudaVersion ) ;
150+ }
151+
114152 // Ship ONNX Runtime on Windows by default
115153 if ( process . platform === 'win32' ) await this . installONNXEngine ( ) ;
154+
155+ configs . initialized = true ;
156+ await this . fileManagerService . writeConfigFile ( configs ) ;
116157 } ;
117158
118- parseEngineFileName = ( options ?: InitOptions ) => {
159+ /**
160+ * Parse the engine file name based on the options
161+ * Please check cortex-cpp release artifacts for the available engine files
162+ * @param options
163+ * @returns
164+ */
165+ private parseEngineFileName = ( options ?: InitOptions ) => {
119166 const platform =
120167 process . platform === 'win32'
121168 ? 'windows'
@@ -136,58 +183,17 @@ export class InitCliUsecases {
136183 return `${ engineName } .tar.gz` ;
137184 } ;
138185
139- cudaVersion = async ( ) => {
140- let filesCuda12 : string [ ] ;
141- let filesCuda11 : string [ ] ;
142- let paths : string [ ] ;
143-
144- if ( process . platform === 'win32' ) {
145- filesCuda12 = [ 'cublas64_12.dll' , 'cudart64_12.dll' , 'cublasLt64_12.dll' ] ;
146- filesCuda11 = [
147- 'cublas64_11.dll' ,
148- 'cudart64_110.dll' ,
149- 'cublasLt64_11.dll' ,
150- ] ;
151- paths = process . env . PATH ? process . env . PATH . split ( delimiter ) : [ ] ;
152- } else {
153- filesCuda12 = [ 'libcudart.so.12' , 'libcublas.so.12' , 'libcublasLt.so.12' ] ;
154- filesCuda11 = [
155- 'libcudart.so.11.0' ,
156- 'libcublas.so.11' ,
157- 'libcublasLt.so.11' ,
158- ] ;
159- paths = process . env . LD_LIBRARY_PATH
160- ? process . env . LD_LIBRARY_PATH . split ( delimiter )
161- : [ ] ;
162- paths . push ( '/usr/lib/x86_64-linux-gnu/' ) ;
163- }
164-
165- if (
166- filesCuda12 . every (
167- ( file ) =>
168- existsSync ( file ) || this . checkFileExistenceInPaths ( file , paths ) ,
169- )
170- )
171- return '12' ;
172-
173- if (
174- filesCuda11 . every (
175- ( file ) =>
176- existsSync ( file ) || this . checkFileExistenceInPaths ( file , paths ) ,
177- )
178- )
179- return '11' ;
180-
181- return undefined ; // No CUDA Toolkit found
182- } ;
183-
184- installCudaToolkitDependency = async ( options : InitOptions ) => {
186+ /**
187+ * Install CUDA Toolkit dependency (dll/so files)
188+ * @param options
189+ */
190+ private installCudaToolkitDependency = async ( cudaVersion ?: string ) => {
185191 const platform = process . platform === 'win32' ? 'windows' : 'linux' ;
186192
187193 const dataFolderPath = await this . fileManagerService . getDataFolderPath ( ) ;
188194 const url = CUDA_DOWNLOAD_URL . replace (
189195 '<version>' ,
190- options . cudaVersion === '11' ? '11.7' : '12.0' ,
196+ cudaVersion === '11' ? '11.7' : '12.0' ,
191197 ) . replace ( '<platform>' , platform ) ;
192198 const destination = join ( dataFolderPath , 'cuda-toolkit.tar.gz' ) ;
193199
@@ -238,25 +244,9 @@ export class InitCliUsecases {
238244 await rm ( destination , { force : true } ) ;
239245 } ;
240246
241- // Function to check for NVIDIA GPU
242- checkNvidiaGPUExist = ( ) : Promise < boolean > => {
243- return new Promise < boolean > ( ( resolve ) => {
244- // Execute the nvidia-smi command
245- exec ( 'nvidia-smi' , ( error ) => {
246- if ( error ) {
247- // If there's an error, it means nvidia-smi is not installed or there's no NVIDIA GPU
248- console . log ( 'NVIDIA GPU not detected or nvidia-smi not installed.' ) ;
249- resolve ( false ) ;
250- } else {
251- // If the command executes successfully, NVIDIA GPU is present
252- console . log ( 'NVIDIA GPU detected.' ) ;
253- resolve ( true ) ;
254- }
255- } ) ;
256- } ) ;
257- } ;
258-
259- detectInstructions = ( ) : Promise < 'AVX' | 'AVX2' | 'AVX512' | undefined > => {
247+ private detectInstructions = ( ) : Promise <
248+ 'AVX' | 'AVX2' | 'AVX512' | undefined
249+ > => {
260250 return new Promise < 'AVX' | 'AVX2' | 'AVX512' | undefined > ( ( res ) => {
261251 // Execute the cpuinfo command
262252
@@ -293,7 +283,7 @@ export class InitCliUsecases {
293283 * @param version
294284 * @param engineFileName
295285 */
296- async installONNXEngine (
286+ private async installONNXEngine (
297287 version : string = 'latest' ,
298288 engineFileName : string = 'windows-amd64' ,
299289 ) {
@@ -390,11 +380,4 @@ export class InitCliUsecases {
390380 }
391381 }
392382 }
393-
394- private checkFileExistenceInPaths = (
395- file : string ,
396- paths : string [ ] ,
397- ) : boolean => {
398- return paths . some ( ( p ) => existsSync ( join ( p , file ) ) ) ;
399- } ;
400383}
0 commit comments