Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: failed tests #702

Merged
merged 3 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cortex-js/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"name": "@janhq/cortex",
"version": "0.0.1",
"description": "",
"author": "",
"description": "Cortex is an openAI-compatible local AI server that developers can use to build LLM apps. It is packaged with a Docker-inspired command-line interface and a Typescript client library. It can be used as a standalone server, or imported as a library.",
"author": "Jan <[email protected]>",
"license": "AGPL-3.0",
"homepage": "https://github.com/janhq/cortex",
"bin": {
"cortex": "./dist/src/command.js"
},
Expand Down Expand Up @@ -114,7 +115,8 @@
"coverageDirectory": "../coverage",
"testEnvironment": "node",
"moduleNameMapper": {
"@/(.*)$": "<rootDir>/$1"
"@/(.*)$": "<rootDir>/$1",
"@commanders/(.*)$": "<rootDir>/../src/infrastructure/commanders/$1"
}
}
}
2 changes: 0 additions & 2 deletions cortex-js/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { AppLoggerMiddleware } from './infrastructure/middlewares/app.logger.mid
import { EventEmitterModule } from '@nestjs/event-emitter';
import { DownloadManagerModule } from './download-manager/download-manager.module';
import { EventsController } from './infrastructure/controllers/events.controller';
import { AppController } from './infrastructure/controllers/app.controller';
import { AssistantsController } from './infrastructure/controllers/assistants.controller';
import { ChatController } from './infrastructure/controllers/chat.controller';
import { EmbeddingsController } from './infrastructure/controllers/embeddings.controller';
Expand Down Expand Up @@ -49,7 +48,6 @@ import { ProcessController } from './infrastructure/controllers/process.controll
DownloadManagerModule,
],
controllers: [
AppController,
AssistantsController,
ChatController,
EmbeddingsController,
Expand Down
4 changes: 4 additions & 0 deletions cortex-js/src/command.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { EmbeddingCommand } from './infrastructure/commanders/embeddings.command
import { BenchmarkCommand } from './infrastructure/commanders/benchmark.command';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { DownloadManagerModule } from './download-manager/download-manager.module';
import { ServeStopCommand } from './infrastructure/commanders/sub-commands/serve-stop.command';

@Module({
imports: [
Expand Down Expand Up @@ -78,6 +79,9 @@ import { DownloadManagerModule } from './download-manager/download-manager.modul

// Shortcuts
RunCommand,

// Serve
ServeStopCommand,
],
})
export class CommandModule {}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DownloadManagerService } from './download-manager.service';
import { HttpModule } from '@nestjs/axios';
import { EventEmitterModule } from '@nestjs/event-emitter';

describe('DownloadManagerService', () => {
let service: DownloadManagerService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [HttpModule, EventEmitterModule.forRoot()],
providers: [DownloadManagerService],
}).compile();

Expand Down
12 changes: 9 additions & 3 deletions cortex-js/src/infrastructure/commanders/benchmark.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { BenchmarkConfig } from './types/benchmark-config.interface';

@SubCommand({
name: 'benchmark',
subCommands: [],
arguments: '[model_id]',
argsDescription: {
model_id: 'Model to benchmark with',
},
description:
'Benchmark and analyze the performance of a specific AI model using a variety of system resources',
})
Expand All @@ -14,10 +17,13 @@ export class BenchmarkCommand extends CommandRunner {
}

async run(
_input: string[],
passedParams: string[],
options?: Partial<BenchmarkConfig>,
): Promise<void> {
return this.benchmarkUsecases.benchmark(options ?? {});
return this.benchmarkUsecases.benchmark({
...options,
...(passedParams[0] ? { modelId: passedParams[0] } : {}),
});
}

@Option({
Expand Down
21 changes: 16 additions & 5 deletions cortex-js/src/infrastructure/commanders/chat.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ type ChatOptions = {
attach: boolean;
};

@SubCommand({ name: 'chat', description: 'Send a chat request to a model' })
@SubCommand({
name: 'chat',
description: 'Send a chat request to a model',
arguments: '[model_id] [message]',
argsDescription: {
model_id:
'Model ID to chat with. If there is no model_id provided, it will prompt to select from running models.',
message: 'Message to send to the model',
},
})
export class ChatCommand extends CommandRunner {
constructor(
private readonly inquirerService: InquirerService,
Expand All @@ -27,17 +36,19 @@ export class ChatCommand extends CommandRunner {
super();
}

async run(_input: string[], options: ChatOptions): Promise<void> {
let modelId = _input[0];
async run(passedParams: string[], options: ChatOptions): Promise<void> {
let modelId = passedParams[0];
// First attempt to get message from input or options
// Extract input from 1 to end of array
let message = options.message ?? _input.slice(1).join(' ');
let message = options.message ?? passedParams.slice(1).join(' ');

// Check for model existing
if (!modelId || !(await this.modelsUsecases.findOne(modelId))) {
// Model ID is not provided
// first input might be message input
message = _input.length ? _input.join(' ') : options.message ?? '';
message = passedParams.length
? passedParams.join(' ')
: 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) {
Expand Down
26 changes: 10 additions & 16 deletions cortex-js/src/infrastructure/commanders/cortex-command.commander.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RootCommand, CommandRunner, Option } from 'nest-commander';
import { RootCommand, CommandRunner } from 'nest-commander';
import { ServeCommand } from './serve.command';
import { ChatCommand } from './chat.command';
import { ModelsCommand } from './models.command';
Expand All @@ -11,10 +11,9 @@ import pkg from '@/../package.json';
import { PresetCommand } from './presets.command';
import { EmbeddingCommand } from './embeddings.command';
import { BenchmarkCommand } from './benchmark.command';
import chalk from 'chalk';
import { printSlogan } from '@/utils/logo';

interface CortexCommandOptions {
version: boolean;
}
@RootCommand({
subCommands: [
ModelsCommand,
Expand All @@ -32,17 +31,12 @@ interface CortexCommandOptions {
description: 'Cortex CLI',
})
export class CortexCommand extends CommandRunner {
async run(input: string[], option: CortexCommandOptions): Promise<void> {
if (option.version) console.log(pkg.version);
}

@Option({
flags: '-v, --version',
description: 'Cortex version',
defaultValue: false,
name: 'version',
})
parseVersion() {
return true;
async run(): Promise<void> {
printSlogan();
console.log('\n');
console.log(`Cortex CLI - v${pkg.version}`);
console.log(chalk.blue(`Github: ${pkg.homepage}`));
console.log('\n');
this.command?.help();
}
}
16 changes: 12 additions & 4 deletions cortex-js/src/infrastructure/commanders/embeddings.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ interface EmbeddingCommandOptions {

@SubCommand({
name: 'embeddings',
arguments: '[model_id]',
description: 'Creates an embedding vector representing the input text.',
argsDescription: {
model_id:
'Model to use for embedding. If not provided, it will prompt to select from running models.',
},
})
export class EmbeddingCommand extends CommandRunner {
constructor(
Expand All @@ -29,16 +34,19 @@ export class EmbeddingCommand extends CommandRunner {
) {
super();
}
async run(_input: string[], options: EmbeddingCommandOptions): Promise<void> {
let modelId = _input[0];
async run(
passedParams: string[],
options: EmbeddingCommandOptions,
): Promise<void> {
let modelId = passedParams[0];
// First attempt to get message from input or options
let input: string | string[] = options.input ?? _input.splice(1);
let input: string | string[] = options.input ?? passedParams.splice(1);

// Check for model existing
if (!modelId || !(await this.modelsUsecases.findOne(modelId))) {
// Model ID is not provided
// first input might be message input
input = _input ?? options.input;
input = passedParams ?? options.input;
// If model ID is not provided, prompt user to select from running models
const models = await this.psCliUsecases.getModels();
if (models.length === 1) {
Expand Down
17 changes: 12 additions & 5 deletions cortex-js/src/infrastructure/commanders/init.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { InitOptions } from './types/init-options.interface';
@SubCommand({
name: 'init',
aliases: ['setup'],
arguments: '[version]',
description: "Init settings and download cortex's dependencies",
argsDescription: {
version: 'Version of cortex engine',
},
})
export class InitCommand extends CommandRunner {
constructor(
Expand All @@ -20,16 +24,19 @@ export class InitCommand extends CommandRunner {
super();
}

async run(input: string[], options?: InitOptions): Promise<void> {
async run(passedParams: string[], options?: InitOptions): Promise<void> {
if (options?.silent) {
return this.initSilently(input);
return this.initSilently(passedParams);
} else {
return this.initPrompts(input, options);
return this.initPrompts(passedParams, options);
}
}

private initSilently = async (input: string[], options: InitOptions = {}) => {
const version = input[0] ?? 'latest';
private initSilently = async (
passedParams: string[],
options: InitOptions = {},
) => {
const version = passedParams[0] ?? 'latest';
if (process.platform === 'darwin') {
const engineFileName = this.initUsecases.parseEngineFileName(options);
return this.initUsecases.installEngine(engineFileName, version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@ import { CommandRunner, SubCommand } from 'nest-commander';
import { ModelsCliUsecases } from '@commanders/usecases/models.cli.usecases';
import { exit } from 'node:process';

@SubCommand({ name: 'get', description: 'Get a model by ID.' })
@SubCommand({
name: 'get',
description: 'Get a model by ID.',
arguments: '<model_id>',
argsDescription: {
model_id: 'Model ID to get information about.',
},
})
export class ModelGetCommand extends CommandRunner {
constructor(private readonly modelsCliUsecases: ModelsCliUsecases) {
super();
}

async run(input: string[]): Promise<void> {
if (input.length === 0) {
async run(passedParams: string[]): Promise<void> {
if (passedParams.length === 0) {
console.error('Model ID is required');
exit(1);
}

const model = await this.modelsCliUsecases.getModel(input[0]);
const model = await this.modelsCliUsecases.getModel(passedParams[0]);
if (!model) console.error('Model not found');
else console.log(model);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class ModelListCommand extends CommandRunner {
super();
}

async run(_input: string[], option: ModelListOptions): Promise<void> {
async run(passedParams: string[], option: ModelListOptions): Promise<void> {
const models = await this.modelsCliUsecases.listAllModels();
option.format === 'table'
? console.table(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,29 @@ import { ModelNotFoundException } from '@/infrastructure/exception/model-not-fou
@SubCommand({
name: 'pull',
aliases: ['download'],
arguments: '<model_id>',
argsDescription: { model_id: 'Model repo to pull' },
description: 'Download a model. Working with HuggingFace model id.',
})
export class ModelPullCommand extends CommandRunner {
constructor(private readonly modelsCliUsecases: ModelsCliUsecases) {
super();
}

async run(input: string[]) {
if (input.length < 1) {
async run(passedParams: string[]) {
if (passedParams.length < 1) {
console.error('Model Id is required');
exit(1);
}

await this.modelsCliUsecases.pullModel(input[0]).catch((e: Error) => {
if (e instanceof ModelNotFoundException)
console.error('Model does not exist.');
else console.error(e);
exit(1);
});
await this.modelsCliUsecases
.pullModel(passedParams[0])
.catch((e: Error) => {
if (e instanceof ModelNotFoundException)
console.error('Model does not exist.');
else console.error(e);
exit(1);
});

console.log('\nDownload complete!');
exit(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ import { CommandRunner, SubCommand } from 'nest-commander';
import { ModelsCliUsecases } from '@commanders/usecases/models.cli.usecases';
import { exit } from 'node:process';

@SubCommand({ name: 'remove', description: 'Remove a model by ID locally.' })
@SubCommand({
name: 'remove',
description: 'Remove a model by ID locally.',
arguments: '<model_id>',
argsDescription: {
model_id: 'Model to remove',
},
})
export class ModelRemoveCommand extends CommandRunner {
constructor(private readonly modelsCliUsecases: ModelsCliUsecases) {
super();
}

async run(input: string[]): Promise<void> {
if (input.length === 0) {
async run(passedParams: string[]): Promise<void> {
if (passedParams.length === 0) {
console.error('Model ID is required');
exit(1);
}

await this.modelsCliUsecases.removeModel(input[0]).then(console.log);
await this.modelsCliUsecases.removeModel(passedParams[0]).then(console.log);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ type ModelStartOptions = {
attach: boolean;
preset?: string;
};
@SubCommand({ name: 'start', description: 'Start a model by ID.' })
@SubCommand({
name: 'start',
description: 'Start a model by ID.',
arguments: '[model_id]',
argsDescription: {
model_id:
'Model ID to start. If there is no model ID, it will prompt you to select from the available models.',
},
})
export class ModelStartCommand extends CommandRunner {
constructor(
private readonly inquirerService: InquirerService,
Expand All @@ -22,8 +30,8 @@ export class ModelStartCommand extends CommandRunner {
super();
}

async run(input: string[], options: ModelStartOptions): Promise<void> {
let modelId = input[0];
async run(passedParams: string[], options: ModelStartOptions): Promise<void> {
let modelId = passedParams[0];
if (!modelId) {
try {
modelId = await this.modelInquiry();
Expand Down
Loading