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

Commit 83eaf01

Browse files
committed
Merge branch 'dev' of github.com:janhq/nitro into feat/cortex-engine
2 parents 2d09448 + ab128f5 commit 83eaf01

File tree

7 files changed

+107
-16
lines changed

7 files changed

+107
-16
lines changed

cortex-js/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"scripts": {
1414
"dev": "nest dev",
1515
"compile": "npx ncc build ./dist/src/command.js -o command",
16-
"build": "nest build",
16+
"build": "yarn add sqlite3 --build-from-source && nest build",
1717
"build:binary": "yarn build && yarn compile && npx -q patch-package && run-script-os",
1818
"build:binary:windows": "npx @yao-pkg/pkg . --targets node20-win",
1919
"build:binary:linux": "npx @yao-pkg/pkg . --targets node20-linux",
@@ -58,7 +58,7 @@
5858
"class-transformer": "^0.5.1",
5959
"class-validator": "^0.14.1",
6060
"cli-progress": "^3.12.0",
61-
"cortex-cpp": "0.5.0-44",
61+
"cortex-cpp": "0.5.0-46",
6262
"decompress": "^4.2.1",
6363
"hyllama": "^0.2.2",
6464
"js-yaml": "^4.1.0",

cortex-js/src/domain/models/model.interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ export interface ModelSettingParams {
126126
* Model type we want to use: llm or embedding, default value is llm (latest llama.cpp update)
127127
*/
128128
model_type?: string;
129+
130+
/**
131+
* The model path.
132+
*/
133+
model_path?: string;
129134
}
130135

131136
/**
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { Model } from '@/domain/models/model.interface';
22
import { Repository } from './repository.interface';
33

4-
export abstract class ModelRepository extends Repository<Model> {}
4+
export abstract class ModelRepository extends Repository<Model> {
5+
abstract loadModelByFile(
6+
modelId: string,
7+
filePath: string,
8+
modelFile: string,
9+
): Promise<Model | null>;
10+
}

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import ora from 'ora';
55
import { existsSync } from 'fs';
66
import { join } from 'path';
77
import { Engines } from './types/engine.interface';
8-
import { checkModelCompatibility, checkRequiredVersion } from '@/utils/model-check';
8+
import {
9+
checkModelCompatibility,
10+
checkRequiredVersion,
11+
} from '@/utils/model-check';
912
import { BaseCommand } from './base.command';
1013
import { isRemoteEngine } from '@/utils/normalize-model-id';
1114
import { ChatClient } from './services/chat-client';
@@ -98,9 +101,15 @@ export class RunCommand extends BaseCommand {
98101
await this.cortex.engines.init(engine);
99102
await downloadProgress(this.cortex, undefined, DownloadType.Engine);
100103
}
101-
const { version: engineVersion } = await this.cortex.engines.retrieve(engine);
102-
if(existingModel.engine_version && !checkRequiredVersion(existingModel.engine_version, engineVersion)) {
103-
console.log(`Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`);
104+
const { version: engineVersion } =
105+
await this.cortex.engines.retrieve(engine);
106+
if (
107+
existingModel.engine_version &&
108+
!checkRequiredVersion(existingModel.engine_version, engineVersion)
109+
) {
110+
console.log(
111+
`Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`,
112+
);
104113
process.exit(1);
105114
}
106115

cortex-js/src/infrastructure/controllers/models.controller.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,37 @@ export class ModelsController {
7575
return this.modelsUsecases.startModel(modelId, params);
7676
}
7777

78+
@HttpCode(200)
79+
@ApiResponse({
80+
status: 200,
81+
description: 'The model has been successfully started.',
82+
type: StartModelSuccessDto,
83+
})
84+
@ApiOperation({
85+
summary: 'Start model by file path',
86+
description:
87+
'Starts a model operation defined by a model `id` with a file path.',
88+
})
89+
@ApiParam({
90+
name: 'modelId',
91+
required: true,
92+
description: 'The unique identifier of the model.',
93+
})
94+
@Post(':modelId(*)/start-by-file')
95+
startModelByFilePath(
96+
@Param('modelId') modelId: string,
97+
@Body()
98+
params: ModelSettingsDto & { filePath: string; metadataPath: string },
99+
) {
100+
const { filePath, metadataPath, ...settings } = params;
101+
return this.modelsUsecases.startModel(
102+
modelId,
103+
settings,
104+
filePath,
105+
metadataPath,
106+
);
107+
}
108+
78109
@HttpCode(200)
79110
@ApiResponse({
80111
status: 200,

cortex-js/src/infrastructure/repositories/models/model.repository.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,36 @@ export class ModelRepositoryImpl implements ModelRepository {
159159
this.loaded = true;
160160
return Array.from(this.models.values());
161161
}
162+
163+
/**
164+
* Load a model by file
165+
* This would load a model from a file
166+
* @returns the model
167+
*/
168+
async loadModelByFile(
169+
modelId: string,
170+
modelPath: string,
171+
modelFile: string,
172+
): Promise<Model | null> {
173+
const checkExists = await this.findOne(modelId);
174+
if (checkExists) return checkExists;
175+
if (!existsSync(modelPath)) return null;
176+
177+
const model = readFileSync(modelPath, 'utf8');
178+
const yamlObject = load(model) as Model;
179+
const fileName = basename(modelId);
180+
const modelObject = {
181+
...yamlObject,
182+
model: modelId,
183+
llama_model_path: modelFile,
184+
model_path: modelFile,
185+
files: [modelFile],
186+
};
187+
if (modelObject) {
188+
this.fileModel.set(modelId, fileName);
189+
this.models.set(modelId, modelObject);
190+
}
191+
this.loaded = true;
192+
return modelObject;
193+
}
162194
}

cortex-js/src/usecases/models/models.usecases.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,8 @@ import { TelemetryUsecases } from '../telemetry/telemetry.usecases';
1616
import { TelemetrySource } from '@/domain/telemetry/telemetry.interface';
1717
import { ModelRepository } from '@/domain/repositories/model.interface';
1818
import { ModelParameterParser } from '@/utils/model-parameter.parser';
19-
import {
20-
HuggingFaceRepoSibling,
21-
} from '@/domain/models/huggingface.interface';
22-
import {
23-
fetchJanRepoData,
24-
getHFModelMetadata,
25-
} from '@/utils/huggingface';
19+
import { HuggingFaceRepoSibling } from '@/domain/models/huggingface.interface';
20+
import { fetchJanRepoData, getHFModelMetadata } from '@/utils/huggingface';
2621
import {
2722
DownloadStatus,
2823
DownloadType,
@@ -162,8 +157,22 @@ export class ModelsUsecases {
162157
async startModel(
163158
modelId: string,
164159
settings?: ModelSettingParams,
160+
filePath?: string,
161+
metadataPath?: string,
165162
): Promise<StartModelSuccessDto> {
166-
const model = await this.getModelOrThrow(modelId);
163+
let model: Model | null;
164+
if (filePath) {
165+
model = await this.modelRepository.loadModelByFile(
166+
modelId,
167+
metadataPath!,
168+
filePath,
169+
);
170+
if (!existsSync(filePath) || !model) {
171+
throw new ModelNotFoundException(model?.id ?? filePath);
172+
}
173+
} else {
174+
model = await this.getModelOrThrow(modelId);
175+
}
167176
const engine = (await this.extensionRepository.findOne(
168177
model!.engine ?? Engines.llamaCPP,
169178
)) as EngineExtension | undefined;
@@ -209,7 +218,6 @@ export class ModelsUsecases {
209218
...parser.parseModelEngineSettings(model),
210219
...parser.parseModelEngineSettings(settings ?? {}),
211220
};
212-
213221
return engine
214222
.loadModel(model, loadModelSettings)
215223
.catch((e) => {

0 commit comments

Comments
 (0)