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

Commit 62f8ddb

Browse files
authored
fix: cli commands (#556)
1 parent d2c83b4 commit 62f8ddb

File tree

14 files changed

+279
-156
lines changed

14 files changed

+279
-156
lines changed

cortex-js/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
"node-fetch": "2",
4242
"readline": "^1.3.0",
4343
"reflect-metadata": "^0.2.0",
44-
"request": "^2.88.2",
45-
"request-progress": "^3.0.0",
4644
"rxjs": "^7.8.1",
4745
"sqlite": "^5.1.1",
4846
"sqlite3": "^5.1.7",

cortex-js/src/command.module.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { CortexModule } from './usecases/cortex/cortex.module';
77
import { ServeCommand } from './infrastructure/commanders/serve.command';
88
import { PullCommand } from './infrastructure/commanders/pull.command';
99
import { InferenceCommand } from './infrastructure/commanders/inference.command';
10+
import { ModelsCommand } from './infrastructure/commanders/models.command';
11+
import { StartCommand } from './infrastructure/commanders/start.command';
1012

1113
@Module({
1214
imports: [
@@ -19,6 +21,13 @@ import { InferenceCommand } from './infrastructure/commanders/inference.command'
1921
ModelsModule,
2022
CortexModule,
2123
],
22-
providers: [BasicCommand, PullCommand, ServeCommand, InferenceCommand],
24+
providers: [
25+
BasicCommand,
26+
ModelsCommand,
27+
PullCommand,
28+
ServeCommand,
29+
InferenceCommand,
30+
StartCommand,
31+
],
2332
})
2433
export class CommandModule {}

cortex-js/src/domain/abstracts/engine.abstract.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export abstract class EngineExtension extends Extension {
44
abstract provider: string;
55
abstract inference(completion: any, req: any, res: any): void;
66
abstract loadModel(loadModel: any): Promise<void>;
7+
abstract unloadModel(modelId: string): Promise<void>;
78
}

cortex-js/src/domain/abstracts/oai.abstract.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
12
import { EngineExtension } from './engine.abstract';
23

34
export abstract class OAIEngineExtension extends EngineExtension {
@@ -32,6 +33,6 @@ export abstract class OAIEngineExtension extends EngineExtension {
3233
response.body.pipe(res);
3334
}
3435

35-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
3636
async loadModel(loadModel: any): Promise<void> {}
37+
async unloadModel(modelId: string): Promise<void> {}
3738
}
Lines changed: 28 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,52 @@
1-
import { RootCommand, CommandRunner } from 'nest-commander';
2-
import { ModelsUsecases } from 'src/usecases/models/models.usecases';
3-
import { LoadModelDto } from '../dtos/models/load-model.dto';
4-
import { CortexUsecases } from 'src/usecases/cortex/cortex.usecases';
1+
import { RootCommand, CommandRunner, Option } from 'nest-commander';
52
import { PullCommand } from './pull.command';
63
import { ServeCommand } from './serve.command';
74
import { InferenceCommand } from './inference.command';
5+
import { ModelsCommand } from './models.command';
6+
import { CortexUsecases } from '@/usecases/cortex/cortex.usecases';
7+
import { defaultCortexJsHost, defaultCortexJsPort } from 'constant';
88

99
@RootCommand({
10-
subCommands: [PullCommand, ServeCommand, InferenceCommand],
10+
subCommands: [ModelsCommand, PullCommand, ServeCommand, InferenceCommand],
1111
})
1212
export class BasicCommand extends CommandRunner {
13-
constructor(
14-
private readonly modelsUsecases: ModelsUsecases,
15-
private readonly cortexUsecases: CortexUsecases,
16-
) {
13+
constructor(private readonly cortexUsecases: CortexUsecases) {
1714
super();
1815
}
1916

20-
async run(input: string[]): Promise<void> {
17+
async run(input: string[], options?: any): Promise<void> {
2118
const command = input[0];
2219

2320
switch (command) {
24-
case 'models':
25-
this.modelsUsecases.findAll().then((e: any) => console.log(e));
26-
return;
27-
2821
case 'start':
29-
return this.startCortex();
30-
31-
case 'load':
32-
return this.loadModel(input);
33-
22+
const host = options?.host || defaultCortexJsHost;
23+
const port = options?.port || defaultCortexJsPort;
24+
return this.cortexUsecases
25+
.startCortex(host, port)
26+
.then((e) => console.log(e));
27+
case 'stop':
28+
return this.cortexUsecases
29+
.stopCortex(defaultCortexJsHost, defaultCortexJsPort)
30+
.then((e) => console.log(e));
3431
default:
3532
console.error(`Command ${command} is not supported`);
3633
return;
3734
}
3835
}
3936

40-
private async startCortex(): Promise<void> {
41-
const host = '127.0.0.1';
42-
const port = '3928';
43-
const result = await this.cortexUsecases.startCortex(host, port);
44-
console.log(result);
37+
@Option({
38+
flags: '--host <host>',
39+
description: 'Host to serve the application',
40+
})
41+
parseHost(value: string) {
42+
return value;
4543
}
4644

47-
private async loadModel(input: string[]): Promise<void> {
48-
if (input.length < 2) {
49-
return Promise.reject('Model ID is required');
50-
}
51-
const settings = {
52-
cpu_threads: 10,
53-
ctx_len: 2048,
54-
embedding: false,
55-
prompt_template:
56-
'{system_message}\n### Instruction: {prompt}\n### Response:',
57-
system_prompt: '',
58-
user_prompt: '\n### Instruction: ',
59-
ai_prompt: '\n### Response:',
60-
ngl: 100,
61-
};
62-
const loadModelDto: LoadModelDto = { modelId: input[1], settings };
63-
await this.modelsUsecases
64-
.loadModel(loadModelDto)
65-
.then((e) => console.log(e));
45+
@Option({
46+
flags: '--port <port>',
47+
description: 'Port to serve the application',
48+
})
49+
parsePort(value: string) {
50+
return parseInt(value, 10);
6651
}
6752
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { CommandRunner, SubCommand } from 'nest-commander';
22

3-
// TODO: might need to change the name of the command. Inference seems a bit hard to type lol
4-
@SubCommand({ name: 'inference' })
3+
@SubCommand({ name: 'chat' })
54
export class InferenceCommand extends CommandRunner {
65
constructor() {
76
super();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ModelsUsecases } from '@/usecases/models/models.usecases';
2+
import { CommandRunner, SubCommand } from 'nest-commander';
3+
import { PullCommand } from './pull.command';
4+
import { StartCommand } from './start.command';
5+
6+
@SubCommand({ name: 'models', subCommands: [PullCommand, StartCommand] })
7+
export class ModelsCommand extends CommandRunner {
8+
constructor(private readonly modelsUsecases: ModelsUsecases) {
9+
super();
10+
}
11+
12+
async run(input: string[]): Promise<void> {
13+
const command = input[0];
14+
const modelId = input[1];
15+
16+
if (command !== 'list') {
17+
if (!modelId) {
18+
console.log('Model ID is required');
19+
return;
20+
}
21+
}
22+
23+
switch (command) {
24+
case 'list':
25+
this.modelsUsecases.findAll().then(console.log);
26+
return;
27+
case 'get':
28+
this.modelsUsecases.findOne(modelId).then(console.log);
29+
return;
30+
case 'remove':
31+
this.modelsUsecases.remove(modelId).then(console.log);
32+
return;
33+
34+
case 'stop':
35+
return this.modelsUsecases
36+
.stopModel(modelId)
37+
.then(console.log)
38+
.catch(console.error);
39+
40+
case 'stats':
41+
case 'fetch':
42+
case 'build': {
43+
console.log('Command is not supported yet');
44+
return;
45+
}
46+
47+
default:
48+
console.error(`Command ${command} is not supported`);
49+
return;
50+
}
51+
}
52+
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ModelsUsecases } from '@/usecases/models/models.usecases';
22
import { CommandRunner, SubCommand } from 'nest-commander';
33
import { CreateModelDto } from '../dtos/models/create-model.dto';
44
import { ModelFormat } from '@/domain/models/model.interface';
5+
import { Presets, SingleBar } from 'cli-progress';
56

67
const AllQuantizations = [
78
'Q3_K_S',
@@ -26,30 +27,29 @@ const AllQuantizations = [
2627
'COPY',
2728
];
2829

29-
@SubCommand({ name: 'pull' })
30+
@SubCommand({ name: 'pull', aliases: ['download'] })
3031
export class PullCommand extends CommandRunner {
3132
constructor(private readonly modelsUsecases: ModelsUsecases) {
3233
super();
3334
}
3435

3536
async run(input: string[]): Promise<void> {
36-
if (input.length < 2) {
37+
if (input.length < 1) {
3738
return Promise.reject('Model ID is required');
3839
}
3940

4041
const modelId = input[0];
4142
if (modelId.includes('/')) {
4243
await this.pullHuggingFaceModel(modelId);
4344
}
44-
this.modelsUsecases.downloadModel({ modelId });
45-
46-
// const bar = new SingleBar({}, Presets.shades_classic);
47-
// bar.start(100, 0);
48-
// await this.modelsUsecases.downloadModelProgress({ modelId }, (progress) => {
49-
// bar.update(progress);
50-
// });
51-
// console.log('\nDownload complete!');
52-
// process.exit(0);
45+
46+
const bar = new SingleBar({}, Presets.shades_classic);
47+
bar.start(100, 0);
48+
await this.modelsUsecases.downloadModel({ modelId }, (progress) => {
49+
bar.update(progress);
50+
});
51+
console.log('\nDownload complete!');
52+
process.exit(0);
5353
}
5454

5555
async pullHuggingFaceModel(modelId: string) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { spawn } from 'child_process';
2-
import { defaultCortexJsHost } from 'constant';
2+
import { defaultCortexJsHost, defaultCortexJsPort } from 'constant';
33
import { CommandRunner, SubCommand, Option } from 'nest-commander';
44
import { join } from 'path';
55

@@ -16,7 +16,7 @@ export class ServeCommand extends CommandRunner {
1616

1717
async run(_input: string[], options?: ServeOptions): Promise<void> {
1818
const host = options?.host || defaultCortexJsHost;
19-
const port = options?.port || defaultCortexJsHost;
19+
const port = options?.port || defaultCortexJsPort;
2020

2121
spawn('node', [join(__dirname, '../../main.js')], {
2222
env: {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { CortexUsecases } from '@/usecases/cortex/cortex.usecases';
2+
import { ModelsUsecases } from '@/usecases/models/models.usecases';
3+
import { CommandRunner, SubCommand } from 'nest-commander';
4+
import { LoadModelDto } from '../dtos/models/load-model.dto';
5+
6+
@SubCommand({ name: 'start', aliases: ['run'] })
7+
export class StartCommand extends CommandRunner {
8+
constructor(
9+
private readonly modelsUsecases: ModelsUsecases,
10+
private readonly cortexUsecases: CortexUsecases,
11+
) {
12+
super();
13+
}
14+
15+
async run(input: string[]): Promise<void> {
16+
const modelId = input[0];
17+
18+
if (!modelId) {
19+
console.log('Model ID is required');
20+
return;
21+
}
22+
return this.startCortex()
23+
.then(() => this.startModel(modelId))
24+
.then(console.log)
25+
.catch(console.error);
26+
}
27+
28+
private async startCortex() {
29+
const host = '127.0.0.1';
30+
const port = '3928';
31+
return this.cortexUsecases.startCortex(host, port);
32+
}
33+
private async startModel(modelId: string) {
34+
const settings = {
35+
cpu_threads: 10,
36+
ctx_len: 2048,
37+
embedding: false,
38+
prompt_template:
39+
'{system_message}\n### Instruction: {prompt}\n### Response:',
40+
system_prompt: '',
41+
user_prompt: '\n### Instruction: ',
42+
ai_prompt: '\n### Response:',
43+
ngl: 100,
44+
};
45+
const loadModelDto: LoadModelDto = { modelId, settings };
46+
return this.modelsUsecases.startModel(loadModelDto);
47+
}
48+
}

0 commit comments

Comments
 (0)