Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/janhq/cortex into readme
Browse files Browse the repository at this point in the history
  • Loading branch information
irfanpena committed May 30, 2024
2 parents 8c51521 + c08c797 commit 862ccba
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 128 deletions.
2 changes: 1 addition & 1 deletion cortex-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.12.9",
"@types/supertest": "^6.0.2",
"@types/update-notifier": "^5.0.8",
"@types/update-notifier": "^6.0.8",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
Expand Down
52 changes: 44 additions & 8 deletions cortex-js/src/infrastructure/commanders/chat.command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { CommandRunner, SubCommand, Option } from 'nest-commander';
import {
CommandRunner,
SubCommand,
Option,
InquirerService,
} from 'nest-commander';
import { ChatCliUsecases } from './usecases/chat.cli.usecases';
import { exit } from 'node:process';
import { PSCliUsecases } from './usecases/ps.cli.usecases';
import { ModelsUsecases } from '@/usecases/models/models.usecases';

type ChatOptions = {
threadId?: string;
Expand All @@ -10,22 +17,52 @@ type ChatOptions = {

@SubCommand({ name: 'chat', description: 'Send a chat request to a model' })
export class ChatCommand extends CommandRunner {
constructor(private readonly chatCliUsecases: ChatCliUsecases) {
constructor(
private readonly inquirerService: InquirerService,
private readonly chatCliUsecases: ChatCliUsecases,
private readonly modelsUsecases: ModelsUsecases,
private readonly psCliUsecases: PSCliUsecases,
) {
super();
}

async run(_input: string[], options: ChatOptions): Promise<void> {
const modelId = _input[0];
if (!modelId) {
console.error('Model ID is required');
exit(1);
let modelId = _input[0];
// First attempt to get message from input or options
let message = _input[1] ?? options.message;

// Check for model existing
if (!modelId || !(await this.modelsUsecases.findOne(modelId))) {
// Model ID is not provided
// first input might be message input
message = _input[0] ?? options.message;
// If model ID is not provided, prompt user to select from running models
const models = await this.psCliUsecases.getModels();
if (models.length === 1) {
modelId = models[0].modelId;
} else if (models.length > 0) {
const { model } = await this.inquirerService.inquirer.prompt({
type: 'list',
name: 'model',
message: 'Select running model to chat with:',
choices: models.map((e) => ({
name: e.modelId,
value: e.modelId,
})),
});
modelId = model;
} else {
console.error('Model ID is required');
exit(1);
}
}

return this.chatCliUsecases.chat(
modelId,
options.threadId,
options.message,
message, // Accept both message from inputs or arguments
options.attach,
false, // Do not stop cortex session or loaded model
);
}

Expand All @@ -40,7 +77,6 @@ export class ChatCommand extends CommandRunner {
@Option({
flags: '-m, --message <message>',
description: 'Message to send to the model',
required: true,
})
parseModelId(value: string) {
return value;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import { CommandRunner, SubCommand } from 'nest-commander';
import { CommandRunner, SubCommand, Option } from 'nest-commander';
import { ModelsCliUsecases } from '../usecases/models.cli.usecases';

interface ModelListOptions {
format: 'table' | 'json';
}
@SubCommand({ name: 'list', description: 'List all models locally.' })
export class ModelListCommand extends CommandRunner {
constructor(private readonly modelsCliUsecases: ModelsCliUsecases) {
super();
}

async run(): Promise<void> {
async run(_input: string[], option: ModelListOptions): Promise<void> {
const models = await this.modelsCliUsecases.listAllModels();
console.log(models);
option.format === 'table' ? console.table(models) : console.log(models);
}

@Option({
flags: '-f, --format <format>',
defaultValue: 'json',
description: 'Print models list in table or json format',
})
parseModelId(value: string) {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class ModelPullCommand extends CommandRunner {
name: sanitizedInput,
};

// eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const _fileInfo of listFiles({ repo })) {
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export class ModelRemoveCommand extends CommandRunner {
exit(1);
}

const result = await this.modelsCliUsecases.removeModel(input[0]);
console.log(result);
await this.modelsCliUsecases.removeModel(input[0]).then(console.log);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { CommandRunner, SubCommand } from 'nest-commander';
import { exit } from 'node:process';
import { ModelsCliUsecases } from '../usecases/models.cli.usecases';
import { CortexUsecases } from '@/usecases/cortex/cortex.usecases';

@SubCommand({ name: 'stop', description: 'Stop a model by ID.' })
export class ModelStopCommand extends CommandRunner {
constructor(
private readonly cortexUsecases: CortexUsecases,
private readonly modelsCliUsecases: ModelsCliUsecases,
) {
constructor(private readonly modelsCliUsecases: ModelsCliUsecases) {
super();
}

Expand All @@ -20,7 +16,7 @@ export class ModelStopCommand extends CommandRunner {

await this.modelsCliUsecases
.stopModel(input[0])
.then(() => this.cortexUsecases.stopCortex())
.then(() => this.modelsCliUsecases.stopModel(input[0]))
.then(console.log);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,12 @@ export class ChatCliUsecases {
private readonly messagesUsecases: MessagesUsecases,
) {}

private async getOrCreateNewThread(
modelId: string,
threadId?: string,
): Promise<Thread> {
if (threadId) {
const thread = await this.threadUsecases.findOne(threadId);
if (!thread) throw new Error(`Cannot find thread with id: ${threadId}`);
return thread;
}

const model = await this.modelsUsecases.findOne(modelId);
if (!model) throw new Error(`Cannot find model with id: ${modelId}`);

const assistant = await this.assistantUsecases.findOne('jan');
if (!assistant) throw new Error('No assistant available');

const createThreadModel: CreateThreadModelInfoDto = {
id: modelId,
settings: model.settings,
parameters: model.parameters,
};

const assistantDto: CreateThreadAssistantDto = {
assistant_id: assistant.id,
assistant_name: assistant.name,
model: createThreadModel,
};

const createThreadDto: CreateThreadDto = {
title: 'New Thread',
assistants: [assistantDto],
};

return this.threadUsecases.create(createThreadDto);
}

async chat(
modelId: string,
threadId?: string,
message?: string,
attach: boolean = true,
stopModel: boolean = true,
): Promise<void> {
if (attach) console.log(`Inorder to exit, type '${this.exitClause}'.`);
const thread = await this.getOrCreateNewThread(modelId, threadId);
Expand All @@ -95,11 +60,10 @@ export class ChatCliUsecases {
if (message) sendCompletionMessage.bind(this)(message);
if (attach) rl.prompt();

rl.on('close', () => {
this.cortexUsecases.stopCortex().then(() => {
if (attach) console.log(this.exitMessage);
exit(0);
});
rl.on('close', async () => {
if (stopModel) await this.modelsUsecases.stopModel(modelId);
if (attach) console.log(this.exitMessage);
exit(0);
});

rl.on('line', sendCompletionMessage.bind(this));
Expand Down Expand Up @@ -213,4 +177,40 @@ export class ChatCliUsecases {
});
}
}

private async getOrCreateNewThread(
modelId: string,
threadId?: string,
): Promise<Thread> {
if (threadId) {
const thread = await this.threadUsecases.findOne(threadId);
if (!thread) throw new Error(`Cannot find thread with id: ${threadId}`);
return thread;
}

const model = await this.modelsUsecases.findOne(modelId);
if (!model) throw new Error(`Cannot find model with id: ${modelId}`);

const assistant = await this.assistantUsecases.findOne('jan');
if (!assistant) throw new Error('No assistant available');

const createThreadModel: CreateThreadModelInfoDto = {
id: modelId,
settings: model.settings,
parameters: model.parameters,
};

const assistantDto: CreateThreadAssistantDto = {
assistant_id: assistant.id,
assistant_name: assistant.name,
model: createThreadModel,
};

const createThreadDto: CreateThreadDto = {
title: 'New Thread',
assistants: [assistantDto],
};

return this.threadUsecases.create(createThreadDto);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { InitOptions } from '../types/init-options.interface';
import { Injectable } from '@nestjs/common';
import { firstValueFrom } from 'rxjs';
import { FileManagerService } from '@/file-manager/file-manager.service';
import { rm } from 'fs/promises';

@Injectable()
export class InitCliUsecases {
Expand Down Expand Up @@ -105,6 +106,7 @@ export class InitCliUsecases {
console.error('Error decompressing file', e);
exit(1);
}
await rm(destination, { force: true });
};

parseEngineFileName = (options: InitOptions) => {
Expand Down Expand Up @@ -228,5 +230,6 @@ export class InitCliUsecases {
console.log(e);
exit(1);
}
await rm(destination, { force: true });
};
}
18 changes: 0 additions & 18 deletions cortex-js/src/infrastructure/controllers/cortex.controller.spec.ts

This file was deleted.

45 changes: 0 additions & 45 deletions cortex-js/src/infrastructure/controllers/cortex.controller.ts

This file was deleted.

10 changes: 8 additions & 2 deletions cortex-js/src/infrastructure/controllers/models.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import { ApiOperation, ApiParam, ApiTags, ApiResponse } from '@nestjs/swagger';
import { StartModelSuccessDto } from '@/infrastructure/dtos/models/start-model-success.dto';
import { ModelSettingParamsDto } from '../dtos/models/model-setting-params.dto';
import { TransformInterceptor } from '../interceptors/transform.interceptor';
import { CortexUsecases } from '@/usecases/cortex/cortex.usecases';

@ApiTags('Models')
@Controller('models')
@UseInterceptors(TransformInterceptor)
export class ModelsController {
constructor(private readonly modelsUsecases: ModelsUsecases) {}
constructor(
private readonly modelsUsecases: ModelsUsecases,
private readonly cortexUsecases: CortexUsecases,
) {}

@HttpCode(201)
@ApiResponse({
Expand Down Expand Up @@ -62,7 +66,9 @@ export class ModelsController {
@Param('modelId') modelId: string,
@Body() settings: ModelSettingParamsDto,
) {
return this.modelsUsecases.startModel(modelId, settings);
return this.cortexUsecases
.startCortex()
.then(() => this.modelsUsecases.startModel(modelId, settings));
}

@HttpCode(200)
Expand Down
2 changes: 0 additions & 2 deletions cortex-js/src/usecases/cortex/cortex.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Module } from '@nestjs/common';
import { CortexUsecases } from './cortex.usecases';
import { CortexController } from '@/infrastructure/controllers/cortex.controller';
import { HttpModule } from '@nestjs/axios';
import { FileManagerModule } from '@/file-manager/file-manager.module';

@Module({
imports: [HttpModule, FileManagerModule],
providers: [CortexUsecases],
controllers: [CortexController],
exports: [CortexUsecases],
})
export class CortexModule {}

0 comments on commit 862ccba

Please sign in to comment.