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

Commit 88ed691

Browse files
committed
Merge branch 'dev' of github.com:janhq/nitro into feat/format-output
2 parents 6980a95 + fa72355 commit 88ed691

File tree

7 files changed

+178
-53
lines changed

7 files changed

+178
-53
lines changed

cortex-js/src/domain/config/config.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export interface Config {
55
// todo: will remove optional when all command request api server
66
apiServerPort?: number;
77
apiServerHost?: string;
8+
logPath?: string;
89
}

cortex-js/src/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ export async function start(
2121
portNumber?: number,
2222
enginePortNumber?: number,
2323
dataFolder?: string,
24+
logPath?: string,
2425
) {
26+
if (logPath) {
27+
fileManagerService.setLogPath(logPath);
28+
}
2529
if (name) {
2630
fileManagerService.setConfigProfile(name);
2731
const isProfileConfigExists = fileManagerService.profileConfigExists(name);
@@ -49,10 +53,10 @@ export async function start(
4953
Number(enginePortNumber) || configCortexCppPort || defaultCortexCppPort;
5054
const dataFolderPath = dataFolder;
5155

52-
return startServer(dataFolderPath);
56+
return startServer(dataFolderPath, logPath);
5357
}
5458

55-
async function startServer(dataFolderPath?: string) {
59+
async function startServer(dataFolderPath?: string, logPath?: string) {
5660
const config = await fileManagerService.getConfig();
5761
try {
5862
if (dataFolderPath) {
@@ -80,6 +84,7 @@ async function startServer(dataFolderPath?: string) {
8084
apiServerHost: host,
8185
apiServerPort: port,
8286
dataFolderPath: dataFolderPath || config.dataFolderPath,
87+
logPath: logPath || config.logPath,
8388
cortexCppPort: enginePort,
8489
});
8590
return app;

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type ServeOptions = {
3434
name?: string;
3535
configPath?: string;
3636
enginePort?: string;
37+
logPath?: string;
3738
};
3839

3940
@RootCommand({
@@ -74,6 +75,9 @@ export class CortexCommand extends CommandRunner {
7475
if (options?.name) {
7576
fileManagerService.setConfigProfile(options.name);
7677
}
78+
if (options?.logPath) {
79+
fileManagerService.setLogPath(options.logPath);
80+
}
7781
if (options?.name) {
7882
const isProfileConfigExists = fileManagerService.profileConfigExists(
7983
options.name,
@@ -114,10 +118,14 @@ export class CortexCommand extends CommandRunner {
114118
console.log(chalk.blue(`Github: ${pkg.homepage}`));
115119
return;
116120
}
117-
return this.startServer(showLogs, dataFolderPath);
121+
return this.startServer(showLogs, dataFolderPath, options?.logPath);
118122
}
119123

120-
private async startServer(attach: boolean, dataFolderPath?: string) {
124+
private async startServer(
125+
attach: boolean,
126+
dataFolderPath?: string,
127+
logPath?: string,
128+
) {
121129
const config = await fileManagerService.getConfig();
122130
try {
123131
const startEngineSpinner = ora('Starting Cortex engine...');
@@ -155,11 +163,13 @@ export class CortexCommand extends CommandRunner {
155163
`API Playground available at http://${this.host}:${this.port}/api`,
156164
),
157165
);
166+
158167
await fileManagerService.writeConfigFile({
159168
...config,
160169
apiServerHost: this.host,
161170
apiServerPort: this.port,
162171
dataFolderPath: dataFolderPath || config.dataFolderPath,
172+
logPath: logPath || config.logPath,
163173
cortexCppPort: this.enginePort,
164174
});
165175
if (!attach) process.exit(0);
@@ -237,4 +247,12 @@ export class CortexCommand extends CommandRunner {
237247
parseEnginePort(value: string) {
238248
return value;
239249
}
250+
251+
@Option({
252+
flags: '-lp, --logPath <logPath>',
253+
description: 'Path to the logs folder',
254+
})
255+
parseLogPath(value: string) {
256+
return value;
257+
}
240258
}

cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ export class FileManagerService {
3535
private benchmarkFoldername = 'benchmark';
3636
private cortexEnginesFolderName = 'engines';
3737
private cortexTelemetryFolderName = 'telemetry';
38+
private logFileName = 'cortex.log';
3839
private configProfile = process.env.CORTEX_PROFILE || 'default';
3940
private configPath = process.env.CORTEX_CONFIG_PATH || os.homedir();
40-
41+
private customLogPath = process.env.CORTEX_LOG_PATH || '';
4142
/**
4243
* Get cortex configs
4344
* @returns the config object
@@ -309,7 +310,10 @@ export class FileManagerService {
309310
* @returns the path to the cortex engines folder
310311
*/
311312
async getLogPath(): Promise<string> {
312-
return join(await this.getDataFolderPath(), 'cortex.log');
313+
if (this.customLogPath) {
314+
return this.customLogPath + `/${this.logFileName}`;
315+
}
316+
return join(await this.getDataFolderPath(), this.logFileName);
313317
}
314318

315319
async createFolderIfNotExistInDataFolder(folderName: string): Promise<void> {
@@ -401,6 +405,10 @@ export class FileManagerService {
401405
public getConfigPath(): string {
402406
return this.configPath;
403407
}
408+
409+
public setLogPath(logPath: string) {
410+
this.customLogPath = logPath;
411+
}
404412
}
405413

406414
export const fileManagerService = new FileManagerService();

engine/commands/engine_init_cmd.cc

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
// clang-format on
1010
#include "utils/cuda_toolkit_utils.h"
1111
#include "utils/engine_matcher_utils.h"
12+
#if defined(_WIN32) || defined(__linux__)
13+
#include "utils/file_manager_utils.h"
14+
#endif
1215

1316
namespace commands {
1417

@@ -60,21 +63,22 @@ bool EngineInitCmd::Exec() const {
6063
variants.push_back(asset_name);
6164
}
6265

63-
auto cuda_version = system_info_utils::GetCudaVersion();
66+
auto cuda_driver_version = system_info_utils::GetCudaVersion();
6467
CTLOG_INFO("engineName_: " << engineName_);
65-
CTLOG_INFO("CUDA version: " << cuda_version);
68+
CTLOG_INFO("CUDA version: " << cuda_driver_version);
6669
std::string matched_variant = "";
70+
6771
if (engineName_ == "cortex.tensorrt-llm") {
6872
matched_variant = engine_matcher_utils::ValidateTensorrtLlm(
69-
variants, system_info.os, cuda_version);
73+
variants, system_info.os, cuda_driver_version);
7074
} else if (engineName_ == "cortex.onnx") {
7175
matched_variant = engine_matcher_utils::ValidateOnnx(
7276
variants, system_info.os, system_info.arch);
7377
} else if (engineName_ == "cortex.llamacpp") {
7478
auto suitable_avx = engine_matcher_utils::GetSuitableAvxVariant();
7579
matched_variant = engine_matcher_utils::Validate(
7680
variants, system_info.os, system_info.arch, suitable_avx,
77-
cuda_version);
81+
cuda_driver_version);
7882
}
7983
CTLOG_INFO("Matched variant: " << matched_variant);
8084
if (matched_variant.empty()) {
@@ -105,17 +109,46 @@ bool EngineInitCmd::Exec() const {
105109
}}};
106110

107111
DownloadService download_service;
108-
download_service.AddDownloadTask(downloadTask, [](const std::string&
109-
absolute_path,
110-
bool unused) {
112+
download_service.AddDownloadTask(downloadTask, [this](
113+
const std::string&
114+
absolute_path,
115+
bool unused) {
111116
// try to unzip the downloaded file
112117
std::filesystem::path downloadedEnginePath{absolute_path};
113-
CTLOG_INFO("Downloaded engine path: "
114-
<< downloadedEnginePath.string());
118+
CTLOG_INFO(
119+
"Downloaded engine path: " << downloadedEnginePath.string());
120+
121+
std::filesystem::path extract_path =
122+
downloadedEnginePath.parent_path().parent_path();
123+
124+
archive_utils::ExtractArchive(downloadedEnginePath.string(),
125+
extract_path.string());
126+
#if defined(_WIN32) || defined(__linux__)
127+
// FIXME: hacky try to copy the file. Remove this when we are able to set the library path
128+
auto engine_path = extract_path / engineName_;
129+
LOG_INFO << "Source path: " << engine_path.string();
130+
auto executable_path =
131+
file_manager_utils::GetExecutableFolderContainerPath();
132+
for (const auto& entry :
133+
std::filesystem::recursive_directory_iterator(engine_path)) {
134+
if (entry.is_regular_file() &&
135+
entry.path().extension() != ".gz") {
136+
std::filesystem::path relative_path =
137+
std::filesystem::relative(entry.path(), engine_path);
138+
std::filesystem::path destFile =
139+
executable_path / relative_path;
115140

116-
archive_utils::ExtractArchive(
117-
downloadedEnginePath.string(),
118-
downloadedEnginePath.parent_path().parent_path().string());
141+
std::filesystem::create_directories(destFile.parent_path());
142+
std::filesystem::copy_file(
143+
entry.path(), destFile,
144+
std::filesystem::copy_options::overwrite_existing);
145+
146+
std::cout << "Copied: " << entry.path().filename().string()
147+
<< " to " << destFile.string() << std::endl;
148+
}
149+
}
150+
std::cout << "DLL copying completed successfully." << std::endl;
151+
#endif
119152

120153
// remove the downloaded file
121154
// TODO(any) Could not delete file on Windows because it is currently hold by httplib(?)
@@ -128,24 +161,47 @@ bool EngineInitCmd::Exec() const {
128161
CTLOG_INFO("Finished!");
129162
});
130163
if (system_info.os == "mac" || engineName_ == "cortex.onnx") {
131-
return false;
164+
// mac and onnx engine does not require cuda toolkit
165+
return true;
132166
}
167+
133168
// download cuda toolkit
134169
const std::string jan_host = "https://catalog.jan.ai";
135170
const std::string cuda_toolkit_file_name = "cuda.tar.gz";
136171
const std::string download_id = "cuda";
137172

138-
auto gpu_driver_version = system_info_utils::GetDriverVersion();
139-
if(gpu_driver_version.empty()) return true;
173+
// TODO: we don't have API to retrieve list of cuda toolkit dependencies atm because we hosting it at jan
174+
// will have better logic after https://github.com/janhq/cortex/issues/1046 finished
175+
// for now, assume that we have only 11.7 and 12.4
176+
auto suitable_toolkit_version = "";
177+
if (engineName_ == "cortex.tensorrt-llm") {
178+
// for tensorrt-llm, we need to download cuda toolkit v12.4
179+
suitable_toolkit_version = "12.4";
180+
} else {
181+
// llamacpp
182+
auto cuda_driver_semver =
183+
semantic_version_utils::SplitVersion(cuda_driver_version);
184+
if (cuda_driver_semver.major == 11) {
185+
suitable_toolkit_version = "11.7";
186+
} else if (cuda_driver_semver.major == 12) {
187+
suitable_toolkit_version = "12.4";
188+
}
189+
}
190+
191+
// compare cuda driver version with cuda toolkit version
192+
// cuda driver version should be greater than toolkit version to ensure compatibility
193+
if (semantic_version_utils::CompareSemanticVersion(
194+
cuda_driver_version, suitable_toolkit_version) < 0) {
195+
LOG_ERROR << "Your Cuda driver version " << cuda_driver_version
196+
<< " is not compatible with cuda toolkit version "
197+
<< suitable_toolkit_version;
198+
return false;
199+
}
140200

141-
auto cuda_runtime_version =
142-
cuda_toolkit_utils::GetCompatibleCudaToolkitVersion(
143-
gpu_driver_version, system_info.os, engineName_);
144-
LOG_INFO << "abc";
145201
std::ostringstream cuda_toolkit_path;
146-
cuda_toolkit_path << "dist/cuda-dependencies/" << 11.7 << "/"
147-
<< system_info.os << "/"
148-
<< cuda_toolkit_file_name;
202+
cuda_toolkit_path << "dist/cuda-dependencies/"
203+
<< cuda_driver_version << "/" << system_info.os
204+
<< "/" << cuda_toolkit_file_name;
149205

150206
LOG_DEBUG << "Cuda toolkit download url: " << jan_host
151207
<< cuda_toolkit_path.str();

engine/utils/engine_matcher_utils.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
#include <trantor/utils/Logger.h>
12
#include <algorithm>
2-
#include <iostream>
33
#include <iterator>
44
#include <regex>
55
#include <string>
@@ -94,9 +94,19 @@ inline std::string GetSuitableCudaVariant(
9494
bestMatchMinor = variantMinor;
9595
}
9696
}
97-
} else if (cuda_version.empty() && selectedVariant.empty()) {
98-
// If no CUDA version is provided, select the variant without any CUDA in the name
99-
selectedVariant = variant;
97+
}
98+
}
99+
100+
// If no CUDA version is provided, select the variant without any CUDA in the name
101+
if (selectedVariant.empty()) {
102+
LOG_WARN
103+
<< "No suitable CUDA variant found, selecting a variant without CUDA";
104+
for (const auto& variant : variants) {
105+
if (variant.find("cuda") == std::string::npos) {
106+
selectedVariant = variant;
107+
LOG_INFO << "Found variant without CUDA: " << selectedVariant << "\n";
108+
break;
109+
}
100110
}
101111
}
102112

@@ -178,4 +188,4 @@ inline std::string Validate(const std::vector<std::string>& variants,
178188

179189
return cuda_compatible;
180190
}
181-
} // namespace engine_matcher_utils
191+
} // namespace engine_matcher_utils

0 commit comments

Comments
 (0)