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

Commit 88c7421

Browse files
authored
Merge pull request #557 from janhq/chore/clean-up-fetch
chore: clean up node-fetch
2 parents 62f8ddb + 7adc199 commit 88c7421

File tree

8 files changed

+73
-71
lines changed

8 files changed

+73
-71
lines changed

cortex-js/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
"class-validator": "^0.14.1",
3939
"cli-progress": "^3.12.0",
4040
"nest-commander": "^3.13.0",
41-
"node-fetch": "2",
4241
"readline": "^1.3.0",
4342
"reflect-metadata": "^0.2.0",
4443
"rxjs": "^7.8.1",
Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,52 @@
11
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
import { HttpService } from '@nestjs/axios';
23
import { EngineExtension } from './engine.abstract';
34

45
export abstract class OAIEngineExtension extends EngineExtension {
56
abstract apiUrl: string;
67

8+
constructor(protected readonly httpService: HttpService) {
9+
super();
10+
}
11+
712
async inference(
813
createChatDto: any,
914
headers: Record<string, string>,
1015
res: any,
1116
) {
12-
// eslint-disable-next-line @typescript-eslint/no-var-requires
13-
const fetch = require('node-fetch');
14-
const response = await fetch(this.apiUrl, {
15-
method: 'POST',
16-
headers: {
17-
'Content-Type': headers['content-type'] ?? 'application/json',
18-
Authorization: headers['authorization'],
19-
},
20-
body: JSON.stringify(createChatDto),
21-
});
17+
if (createChatDto.stream === true) {
18+
const response = await this.httpService
19+
.post(this.apiUrl, createChatDto, {
20+
headers: {
21+
'Content-Type': headers['content-type'] ?? 'application/json',
22+
Authorization: headers['authorization'],
23+
},
24+
responseType: 'stream',
25+
})
26+
.toPromise();
27+
28+
res.writeHead(200, {
29+
'Content-Type': 'text/event-stream',
30+
'Cache-Control': 'no-cache',
31+
Connection: 'keep-alive',
32+
'Access-Control-Allow-Origin': '*',
33+
});
2234

23-
res.writeHead(200, {
24-
'Content-Type':
25-
createChatDto.stream === true
26-
? 'text/event-stream'
27-
: 'application/json',
28-
'Cache-Control': 'no-cache',
29-
Connection: 'keep-alive',
30-
'Access-Control-Allow-Origin': '*',
31-
});
35+
response?.data.pipe(res);
36+
} else {
37+
const response = await this.httpService
38+
.post(this.apiUrl, createChatDto, {
39+
headers: {
40+
'Content-Type': headers['content-type'] ?? 'application/json',
41+
Authorization: headers['authorization'],
42+
},
43+
})
44+
.toPromise();
3245

33-
response.body.pipe(res);
46+
res.json(response?.data);
47+
}
3448
}
3549

36-
async loadModel(loadModel: any): Promise<void> {}
37-
async unloadModel(modelId: string): Promise<void> {}
50+
async loadModel(_loadModel: any): Promise<void> {}
51+
async unloadModel(_modelId: string): Promise<void> {}
3852
}

cortex-js/src/infrastructure/providers/cortex/cortex.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { Module } from '@nestjs/common';
22
import CortexProvider from './cortex.provider';
3+
import { HttpModule } from '@nestjs/axios';
34

45
@Module({
6+
imports: [HttpModule],
57
providers: [
68
{
79
provide: 'CORTEX_PROVIDER',

cortex-js/src/infrastructure/providers/cortex/cortex.provider.ts

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { PromptTemplate } from '@/domain/models/prompt-template.interface';
44
import { basename, join, resolve } from 'path';
55
import { Model } from '@/domain/models/model.interface';
66
import { ConfigService } from '@nestjs/config';
7+
import { HttpService } from '@nestjs/axios';
8+
79
/**
810
* A class that implements the InferenceExtension interface from the @janhq/core package.
911
* The class provides methods for initializing and stopping a model, and for making inference requests.
@@ -14,13 +16,17 @@ const NITRO_DEFAULT_PORT = 3928;
1416
const NITRO_HTTP_SERVER_URL = `http://${LOCAL_HOST}:${NITRO_DEFAULT_PORT}`;
1517
const LOAD_MODEL_URL = `${NITRO_HTTP_SERVER_URL}/inferences/server/loadmodel`;
1618
const UNLOAD_MODEL_URL = `${NITRO_HTTP_SERVER_URL}/inferences/server/unloadmodel`;
19+
1720
@Injectable()
1821
export default class CortexProvider extends OAIEngineExtension {
1922
provider: string = 'cortex';
2023
apiUrl = 'http://127.0.0.1:3928/inferences/server/chat_completion';
2124

22-
constructor(private readonly configService: ConfigService) {
23-
super();
25+
constructor(
26+
private readonly configService: ConfigService,
27+
protected readonly httpService: HttpService,
28+
) {
29+
super(httpService);
2430
}
2531

2632
override async loadModel(model: Model): Promise<void> {
@@ -38,7 +44,7 @@ export default class CortexProvider extends OAIEngineExtension {
3844
// TODO: NamH check if the binary is there
3945

4046
const cpuThreadCount = 1; // TODO: NamH Math.max(1, nitroResourceProbe.numCpuPhysicalCore);
41-
const nitroModelSettings = {
47+
const modelSettings = {
4248
// This is critical and requires real CPU physical core count (or performance core)
4349
cpu_threads: cpuThreadCount,
4450
...model.settings,
@@ -55,38 +61,18 @@ export default class CortexProvider extends OAIEngineExtension {
5561
if (prompt?.error) {
5662
throw new Error(prompt.error);
5763
}
58-
nitroModelSettings.system_prompt = prompt.system_prompt;
59-
nitroModelSettings.user_prompt = prompt.user_prompt;
60-
nitroModelSettings.ai_prompt = prompt.ai_prompt;
64+
modelSettings.system_prompt = prompt.system_prompt;
65+
modelSettings.user_prompt = prompt.user_prompt;
66+
modelSettings.ai_prompt = prompt.ai_prompt;
6167
}
6268

63-
return fetch(LOAD_MODEL_URL, {
64-
method: 'POST',
65-
headers: {
66-
'Content-Type': 'application/json',
67-
},
68-
body: JSON.stringify(nitroModelSettings),
69-
})
70-
.then((res) => {
71-
if (!res.ok) {
72-
throw new Error('Failed to load model');
73-
}
74-
})
75-
.catch((e) => {
76-
throw e;
77-
});
69+
await this.httpService.post(LOAD_MODEL_URL, modelSettings).toPromise();
7870
}
7971

8072
override async unloadModel(modelId: string): Promise<void> {
81-
return fetch(UNLOAD_MODEL_URL, {
82-
method: 'POST',
83-
headers: {
84-
'Content-Type': 'application/json',
85-
},
86-
body: JSON.stringify({
87-
model: modelId,
88-
}),
89-
}).then();
73+
await this.httpService
74+
.post(UNLOAD_MODEL_URL, { model: modelId })
75+
.toPromise();
9076
}
9177

9278
private readonly promptTemplateConverter = (

cortex-js/src/infrastructure/repositories/extensions/extension.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
22
import { ExtensionRepositoryImpl } from './extension.repository';
33
import { ExtensionRepository } from '@/domain/repositories/extension.interface';
44
import { CortexProviderModule } from '@/infrastructure/providers/cortex/cortex.module';
5+
import { HttpModule } from '@nestjs/axios';
56

67
@Module({
7-
imports: [CortexProviderModule],
8+
imports: [CortexProviderModule, HttpModule],
89
providers: [
910
{
1011
provide: ExtensionRepository,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Module } from '@nestjs/common';
22
import { CortexUsecases } from './cortex.usecases';
33
import { CortexController } from '@/infrastructure/controllers/cortex.controller';
4+
import { HttpModule } from '@nestjs/axios';
45

56
@Module({
7+
imports: [HttpModule],
68
providers: [CortexUsecases],
79
controllers: [CortexController],
810
exports: [CortexUsecases],

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

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import { ChildProcess, spawn } from 'child_process';
44
import { join } from 'path';
55
import { existsSync } from 'fs';
66
import { CortexOperationSuccessfullyDto } from '@/infrastructure/dtos/cortex/cortex-operation-successfully.dto';
7+
import { HttpService } from '@nestjs/axios';
78

89
@Injectable()
910
export class CortexUsecases {
1011
private cortexProcess: ChildProcess | undefined;
1112

12-
constructor(private readonly configService: ConfigService) {}
13+
constructor(
14+
private readonly configService: ConfigService,
15+
private readonly httpService: HttpService,
16+
) {}
1317

1418
async startCortex(
1519
host: string,
@@ -70,25 +74,18 @@ export class CortexUsecases {
7074
host?: string,
7175
port?: number,
7276
): Promise<CortexOperationSuccessfullyDto> {
73-
if (this.cortexProcess) {
74-
this.cortexProcess.kill();
77+
try {
78+
await this.httpService
79+
.delete(`http://${host}:${port}/processmanager/destroy`)
80+
.toPromise();
81+
} catch (err) {
82+
console.error(err);
83+
} finally {
84+
this.cortexProcess?.kill();
7585
return {
7686
message: 'Cortex stopped successfully',
7787
status: 'success',
7888
};
79-
} else {
80-
return new Promise((resolve) => {
81-
return fetch(`http://${host}:${port}/processmanager/destroy`, {
82-
method: 'DELETE',
83-
})
84-
.catch(() => {})
85-
.finally(() => {
86-
resolve({
87-
message: 'Cortex stopped successfully',
88-
status: 'success',
89-
});
90-
});
91-
});
9289
}
9390
}
9491

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ export class ModelsUsecases {
108108
modelId: loadModelDto.modelId,
109109
};
110110
})
111-
.catch(() => {
111+
.catch((err) => {
112+
console.error(err);
112113
return {
113114
message: 'Model failed to load',
114115
modelId: loadModelDto.modelId,

0 commit comments

Comments
 (0)