Skip to content

Commit

Permalink
[Feat] NeuralNetworks
Browse files Browse the repository at this point in the history
Created endpoints for viewing NNs and getting them and their metadata.
Resolves #23.
  • Loading branch information
angel-penchev committed Oct 28, 2021
1 parent a38e232 commit 5d02e04
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 6 deletions.
1 change: 1 addition & 0 deletions server/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_CODE_SNIPPETS_S3_BUCKET=
AWS_RECORDINGS_S3_BUCKET=
AWS_NEURAL_NETWORKS_S3_BUCKET=
6 changes: 6 additions & 0 deletions server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { User } from './users/entities/user.entity';
import { UsersController } from './users/controllers/users.controller';
import { UsersModule } from './users/users.module';
import { UsersService } from './users/services/users.service';
import { NeuralNetworksModule } from './neural-networks/neural-networks.module';
import { NeuralNetworksController } from './neural-networks/controllers/neural-networks.controller';
import { NeuralNetworksService } from './neural-networks/service/neural-networks.service';
import { configuration } from './configuration';

@Module({
Expand All @@ -26,6 +29,7 @@ import { configuration } from './configuration';
AuthModule,
CodeSnippetsModule,
RecordingsModule,
NeuralNetworksModule,
ConfigModule.forRoot({
load: [configuration],
}),
Expand All @@ -51,12 +55,14 @@ import { configuration } from './configuration';
AuthController,
CodeSnippetsController,
RecordingsController,
NeuralNetworksController,
],
providers: [
UsersService,
AuthService,
CodeSnippetsService,
RecordingsService,
NeuralNetworksService,
],
})
export class AppModule {}
1 change: 1 addition & 0 deletions server/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const configuration = () => ({
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
codeSnippetsS3Bucket: process.env.AWS_CODE_SNIPPETS_S3_BUCKET,
recordingsS3Bucket: process.env.AWS_RECORDINGS_S3_BUCKET,
neuralNetworksS3Bucket: process.env.AWS_NEURAL_NETWORKS_S3_BUCKET,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { NeuralNetworksController } from './neural-networks.controller';

describe('NeuralNetworksController', () => {
let controller: NeuralNetworksController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [NeuralNetworksController],
}).compile();

controller = module.get<NeuralNetworksController>(NeuralNetworksController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
Controller,
Get,
HttpCode,
HttpStatus,
Param,
ParseBoolPipe,
Query,
} from '@nestjs/common';
import { ApiNotFoundResponse, ApiOkResponse } from '@nestjs/swagger';
import { NeuralNetworksService } from '../service/neural-networks.service';

@Controller('/neural-networks')
export class NeuralNetworksController {
constructor(private readonly neuralNetworksService: NeuralNetworksService) {}

@Get('/')
@HttpCode(HttpStatus.OK)
@ApiOkResponse({
description: 'List of neural network models on the server.',
})
@ApiNotFoundResponse({ description: 'No such file or directory.' })
async listNetworks() {
return await this.neuralNetworksService.listModels();
}

@Get(':path(*)')
@HttpCode(HttpStatus.OK)
@ApiOkResponse({
description: 'Neural network model or its metadata in JSON.',
})
@ApiNotFoundResponse({ description: 'No such file or directory.' })
async getNetwork(
@Param('path') path: string,
@Query('metadata', new ParseBoolPipe()) metadata: boolean,
) {
return metadata
? await this.neuralNetworksService.getModelMetadata(path)
: await this.neuralNetworksService.getModel(path);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum NeuralNetworksErrorCode {
INVALID_FILE_PATH = 'Invalid file path.',
}
6 changes: 6 additions & 0 deletions server/src/neural-networks/errors/neural-networks.error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default class NeuralNetworksError extends Error {
constructor(message: string) {
super(message);
this.name = 'NeuralNetworksError';
}
}
12 changes: 12 additions & 0 deletions server/src/neural-networks/neural-networks.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { NeuralNetworksService } from './service/neural-networks.service';
import { NeuralNetworksController } from './controllers/neural-networks.controller';
import { AwsSdkModule } from 'nest-aws-sdk';
import { S3 } from 'aws-sdk';

@Module({
imports: [AwsSdkModule.forFeatures([S3])],
providers: [NeuralNetworksService],
controllers: [NeuralNetworksController],
})
export class NeuralNetworksModule {}
18 changes: 18 additions & 0 deletions server/src/neural-networks/service/neural-networks.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { NeuralNetworksService } from './neural-networks.service';

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

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [NeuralNetworksService],
}).compile();

service = module.get<NeuralNetworksService>(NeuralNetworksService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
60 changes: 60 additions & 0 deletions server/src/neural-networks/service/neural-networks.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Injectable } from '@nestjs/common';
import { S3 } from 'aws-sdk';
import { InjectAwsService } from 'nest-aws-sdk';
import { configObject } from 'src/configuration';
import NeuralNetworksError from '../errors/neural-networks.error';
import { NeuralNetworksErrorCode } from '../errors/neural-networks.error.codes';

@Injectable()
export class NeuralNetworksService {
constructor(@InjectAwsService(S3) private readonly s3: S3) {}

async listModels() {
const queryResponse = await this.s3
.listObjectsV2({
Bucket: configObject.aws.neuralNetworksS3Bucket,
Prefix: `models/`,
})
.promise();

const result = queryResponse.Contents.filter(
(item) => !item.Key.endsWith('/'),
).map((item) => item.Key.replace('models/', ''));

return result;
}

async getModel(filepath: string) {
const completeFilepath = `models/${filepath}`;

if (completeFilepath.endsWith('/')) {
throw new NeuralNetworksError(NeuralNetworksErrorCode.INVALID_FILE_PATH);
}

const queryResponse = await this.s3
.getObject({
Bucket: configObject.aws.neuralNetworksS3Bucket,
Key: completeFilepath,
})
.promise();

return JSON.parse(queryResponse.Body.toString());
}

async getModelMetadata(filepath: string) {
const completeFilepath = `metadata/${filepath}`;

if (completeFilepath.endsWith('/')) {
throw new NeuralNetworksError(NeuralNetworksErrorCode.INVALID_FILE_PATH);
}

const queryResponse = await this.s3
.getObject({
Bucket: configObject.aws.neuralNetworksS3Bucket,
Key: completeFilepath,
})
.promise();

return JSON.parse(queryResponse.Body.toString());
}
}
6 changes: 0 additions & 6 deletions server/src/users/entities/user.entity.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import {
IsEmail,
IsNotEmpty,
IsOptional,
IsPhoneNumber,
} from 'class-validator';

@Entity({ name: 'users' })
export class User implements IUser {
Expand Down
1 change: 1 addition & 0 deletions server/types/enviourment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ declare namespace NodeJS {
AWS_SECRET_ACCESS_KEY?: string;
AWS_CODE_SNIPPETS_S3_BUCKET?: string;
AWS_RECORDINGS_S3_BUCKET?: string;
AWS_NEURAL_NETWORKS_S3_BUCKET?: string;
}
}

0 comments on commit 5d02e04

Please sign in to comment.