Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit d627265

Browse files
committed
refactor: shorten cortex setup - save cortex cpp serve configs
1 parent 731d912 commit d627265

File tree

14 files changed

+208
-204
lines changed

14 files changed

+208
-204
lines changed

cortex-js/src/command.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { ModelStopCommand } from './infrastructure/commanders/models/model-stop.
1818
import { ModelGetCommand } from './infrastructure/commanders/models/model-get.command';
1919
import { ModelRemoveCommand } from './infrastructure/commanders/models/model-remove.command';
2020
import { RunCommand } from './infrastructure/commanders/shortcuts/run.command';
21-
import { InitCudaQuestions } from './infrastructure/commanders/questions/cuda.questions';
2221
import { ModelUpdateCommand } from './infrastructure/commanders/models/model-update.command';
2322
import { AssistantsModule } from './usecases/assistants/assistants.module';
2423
import { CliUsecasesModule } from './infrastructure/commanders/usecases/cli.usecases.module';
@@ -71,7 +70,6 @@ import { ServeStopCommand } from './infrastructure/commanders/sub-commands/serve
7170

7271
// Questions
7372
InitRunModeQuestions,
74-
InitCudaQuestions,
7573

7674
// Model commands
7775
ModelStartCommand,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
export interface Config {
22
dataFolderPath: string;
3+
initialized: boolean;
4+
cortexCppHost: string;
5+
cortexCppPort: number;
36
}

cortex-js/src/infrastructure/commanders/init.command.ts

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
import { InitCliUsecases } from './usecases/init.cli.usecases';
88
import { InitOptions } from './types/init-options.interface';
99
import { SetCommandContext } from './decorators/CommandContext';
10-
import { ContextService } from '@/util/context.service';
1110

1211
@SubCommand({
1312
name: 'init',
@@ -23,66 +22,26 @@ export class InitCommand extends CommandRunner {
2322
constructor(
2423
private readonly inquirerService: InquirerService,
2524
private readonly initUsecases: InitCliUsecases,
26-
readonly contextService: ContextService,
2725
) {
2826
super();
2927
}
3028

3129
async run(passedParams: string[], options?: InitOptions): Promise<void> {
3230
if (options?.silent) {
33-
return this.initSilently(passedParams);
31+
const installationOptions =
32+
await this.initUsecases.defaultInstallationOptions();
33+
return this.initUsecases.installEngine(installationOptions);
3434
} else {
35-
return this.initPrompts(passedParams, options);
36-
}
37-
}
35+
options = await this.inquirerService.ask(
36+
'init-run-mode-questions',
37+
options,
38+
);
3839

39-
private initSilently = async (
40-
passedParams: string[],
41-
options: InitOptions = {},
42-
) => {
43-
const version = passedParams[0] ?? 'latest';
44-
if (process.platform === 'darwin') {
45-
const engineFileName = this.initUsecases.parseEngineFileName(options);
46-
return this.initUsecases.installEngine(engineFileName, version);
47-
}
48-
// If Nvidia Driver is installed -> GPU
49-
options.runMode = (await this.initUsecases.checkNvidiaGPUExist())
50-
? 'GPU'
51-
: 'CPU';
52-
// CPU Instructions detection
53-
options.gpuType = 'Nvidia';
54-
options.instructions = await this.initUsecases.detectInstructions();
55-
const engineFileName = this.initUsecases.parseEngineFileName(options);
56-
return this.initUsecases
57-
.installEngine(engineFileName, version)
58-
.then(() => this.initUsecases.installCudaToolkitDependency(options));
59-
};
40+
const version = passedParams[0] ?? 'latest';
6041

61-
/**
62-
* Manual initalization
63-
* To setup cortex's dependencies
64-
* @param input
65-
* @param options GPU | CPU / Nvidia | Others (Vulkan) / AVX | AVX2 | AVX512
66-
*/
67-
private initPrompts = async (input: string[], options?: InitOptions) => {
68-
options = await this.inquirerService.ask(
69-
'init-run-mode-questions',
70-
options,
71-
);
72-
73-
if (options.runMode === 'GPU' && !(await this.initUsecases.cudaVersion())) {
74-
options = await this.inquirerService.ask('init-cuda-questions', options);
42+
await this.initUsecases.installEngine(options, version);
7543
}
76-
77-
const version = input[0] ?? 'latest';
78-
79-
const engineFileName = this.initUsecases.parseEngineFileName(options);
80-
await this.initUsecases.installEngine(engineFileName, version);
81-
82-
if (options.installCuda === 'Yes') {
83-
await this.initUsecases.installCudaToolkitDependency(options);
84-
}
85-
};
44+
}
8645

8746
@Option({
8847
flags: '-s, --silent',

cortex-js/src/infrastructure/commanders/questions/cuda.questions.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

cortex-js/src/infrastructure/commanders/shortcuts/run.command.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ import {
77
} from 'nest-commander';
88
import { exit } from 'node:process';
99
import { ChatCliUsecases } from '@commanders/usecases/chat.cli.usecases';
10-
import {
11-
defaultCortexCppHost,
12-
defaultCortexCppPort,
13-
} from '@/infrastructure/constants/cortex';
1410
import { ModelsCliUsecases } from '@commanders/usecases/models.cli.usecases';
1511
import { ModelNotFoundException } from '@/infrastructure/exception/model-not-found.exception';
1612

@@ -62,7 +58,7 @@ export class RunCommand extends CommandRunner {
6258
}
6359

6460
return this.cortexUsecases
65-
.startCortex(false, defaultCortexCppHost, defaultCortexCppPort)
61+
.startCortex(false)
6662
.then(() => this.modelsCliUsecases.startModel(modelId, options.preset))
6763
.then(() => this.chatCliUsecases.chat(modelId, options.threadId));
6864
}

cortex-js/src/infrastructure/commanders/types/init-options.interface.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ export interface InitOptions {
33
gpuType?: 'Nvidia' | 'Others (Vulkan)';
44
instructions?: 'AVX' | 'AVX2' | 'AVX512' | undefined;
55
cudaVersion?: '11' | '12';
6-
installCuda?: 'Yes' | string;
76
silent?: boolean;
87
}

cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts

Lines changed: 63 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -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()
2122
export 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

Comments
 (0)