Skip to content

Commit 5746931

Browse files
committed
feat: initial implementation 🚀
1 parent 012d4b6 commit 5746931

20 files changed

+1288
-835
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ lerna-debug.log*
3232
!.vscode/settings.json
3333
!.vscode/tasks.json
3434
!.vscode/launch.json
35-
!.vscode/extensions.json
35+
!.vscode/extensions.json
36+
37+
.env

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"typescript.tsdk": "node_modules/typescript/lib"
3+
}

Dockerfile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#
2+
# Base image
3+
#
4+
5+
FROM mcr.microsoft.com/playwright:v1.32.0-jammy as base
6+
7+
RUN apt update -y && apt upgrade -y && \
8+
apt install -y bash && \
9+
mkdir /opt/app
10+
11+
WORKDIR /opt/app
12+
13+
#
14+
# Build image
15+
#
16+
17+
FROM base as build
18+
19+
RUN apt update -y && apt upgrade -y && \
20+
apt install -y make gcc g++
21+
22+
COPY package.json yarn.lock ./
23+
24+
RUN yarn
25+
26+
COPY . .
27+
28+
RUN yarn build
29+
30+
#
31+
# Runtime image
32+
#
33+
34+
FROM base
35+
36+
ENV NODE_ENV production
37+
38+
COPY --from=build /opt/app .
39+
40+
CMD bash -c 'node dist/main'

README.md

Lines changed: 2 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,3 @@
1-
<p align="center">
2-
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
3-
</p>
1+
# ChatGPT Browser API Proxy
42

5-
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6-
[circleci-url]: https://circleci.com/gh/nestjs/nest
7-
8-
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9-
<p align="center">
10-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13-
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14-
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
15-
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
16-
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
17-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
18-
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
19-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
20-
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
21-
</p>
22-
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
23-
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
24-
25-
## Description
26-
27-
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28-
29-
## Installation
30-
31-
```bash
32-
$ yarn install
33-
```
34-
35-
## Running the app
36-
37-
```bash
38-
# development
39-
$ yarn run start
40-
41-
# watch mode
42-
$ yarn run start:dev
43-
44-
# production mode
45-
$ yarn run start:prod
46-
```
47-
48-
## Test
49-
50-
```bash
51-
# unit tests
52-
$ yarn run test
53-
54-
# e2e tests
55-
$ yarn run test:e2e
56-
57-
# test coverage
58-
$ yarn run test:cov
59-
```
60-
61-
## Support
62-
63-
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64-
65-
## Stay in touch
66-
67-
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68-
- Website - [https://nestjs.com](https://nestjs.com/)
69-
- Twitter - [@nestframework](https://twitter.com/nestframework)
70-
71-
## License
72-
73-
Nest is [MIT licensed](LICENSE).
3+
Exposes OpenAI APIs using ChatGPT Browser API.

example.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OPENAI_API_TOKEN=<Your OpenAI API Token>

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
},
2323
"dependencies": {
2424
"@nestjs/common": "^9.0.0",
25+
"@nestjs/config": "^2.3.2",
2526
"@nestjs/core": "^9.0.0",
2627
"@nestjs/mapped-types": "*",
2728
"@nestjs/platform-express": "^9.0.0",
29+
"class-transformer": "^0.5.1",
30+
"class-validator": "^0.14.0",
2831
"playwright": "^1.33.0",
2932
"reflect-metadata": "^0.1.13",
3033
"rxjs": "^7.2.0"

src/app.module.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
1-
import { Module } from '@nestjs/common';
1+
import {
2+
Logger,
3+
MiddlewareConsumer,
4+
Module,
5+
RequestMethod,
6+
} from '@nestjs/common';
7+
import { ConfigModule } from '@nestjs/config';
28

39
import { CompletionModule } from './completion/completion.module.js';
10+
import { ChatModule } from './chat/chat.module.js';
411
import { GlobalModule } from './global/global.module.js';
12+
import { RequestLoggerMiddleware } from './global/middlewares/request-logger.js';
513

614
@Module({
7-
imports: [GlobalModule.forRootAsync(), CompletionModule],
15+
imports: [
16+
ConfigModule.forRoot(),
17+
GlobalModule.forRootAsync(),
18+
CompletionModule,
19+
ChatModule,
20+
],
821
controllers: [],
9-
providers: [],
22+
providers: [Logger],
1023
})
11-
export class AppModule {}
24+
export class AppModule {
25+
configure(consumer: MiddlewareConsumer): any {
26+
consumer.apply(RequestLoggerMiddleware).forRoutes({
27+
path: '*',
28+
method: RequestMethod.ALL,
29+
});
30+
}
31+
}

src/chat/chat.controller.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { ChatController } from './chat.controller.js';
3+
import { ChatService } from './chat.service.js';
4+
5+
describe('ChatController', () => {
6+
let controller: ChatController;
7+
8+
beforeEach(async () => {
9+
const module: TestingModule = await Test.createTestingModule({
10+
controllers: [ChatController],
11+
providers: [ChatService],
12+
}).compile();
13+
14+
controller = module.get<ChatController>(ChatController);
15+
});
16+
17+
it('should be defined', () => {
18+
expect(controller).toBeDefined();
19+
});
20+
});

src/chat/chat.controller.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Body, Controller, Post } from '@nestjs/common';
2+
3+
import { ChatService } from './chat.service.js';
4+
import {
5+
ChatCompletionRequestV1DTO,
6+
ChatCompletionResponseV1DTO,
7+
} from './chat.dto.js';
8+
9+
@Controller('v1/chat')
10+
export class ChatController {
11+
constructor(private readonly chatService: ChatService) {}
12+
13+
@Post('completions')
14+
async complete(
15+
@Body() ChatDto: ChatCompletionRequestV1DTO
16+
): Promise<ChatCompletionResponseV1DTO> {
17+
return await this.chatService.complete(ChatDto.messages);
18+
}
19+
}

src/chat/chat.dto.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { Expose } from 'class-transformer';
2+
import {
3+
IsArray,
4+
IsBoolean,
5+
IsNumber,
6+
IsObject,
7+
IsOptional,
8+
IsString,
9+
} from 'class-validator';
10+
11+
@Expose()
12+
export class LogprobsV1DTO {
13+
tokens: string[];
14+
token_logprobs: number[];
15+
top_logprobs: Record<string, number[]>;
16+
text_offset: number[];
17+
text: string;
18+
finish_reason: string;
19+
}
20+
21+
export class UsageV1DTO {
22+
prompt_tokens: number;
23+
completion_tokens: number;
24+
total_tokens: number;
25+
}
26+
27+
export class MessageV1DTO {
28+
role: string;
29+
content: string;
30+
name?: string
31+
}
32+
33+
export class ChatCompletionRequestV1DTO {
34+
@IsString()
35+
model!: string;
36+
37+
@IsArray()
38+
messages!: MessageV1DTO[];
39+
40+
41+
@IsNumber()
42+
@IsOptional()
43+
temperature?: number;
44+
45+
@IsNumber()
46+
@IsOptional()
47+
top_p?: number;
48+
49+
@IsNumber()
50+
@IsOptional()
51+
n?: number;
52+
53+
@IsBoolean()
54+
@IsOptional()
55+
stream?: number;
56+
57+
@IsOptional()
58+
stop?: string | string[];
59+
60+
@IsNumber()
61+
@IsOptional()
62+
max_tokens?: number;
63+
64+
@IsNumber()
65+
@IsOptional()
66+
presence_penalty?: number;
67+
68+
@IsNumber()
69+
@IsOptional()
70+
frequency_penalty?: number;
71+
72+
@IsObject()
73+
@IsOptional()
74+
logit_bias?: Record<string, number>;
75+
76+
@IsString()
77+
@IsOptional()
78+
user?: string;
79+
}
80+
81+
export class ChatCompletionResponseV1DTO {
82+
@Expose()
83+
id: string;
84+
85+
@Expose()
86+
object: string;
87+
88+
@Expose()
89+
created: number;
90+
91+
@Expose()
92+
choices: ChoiceV1DTO[];
93+
94+
@Expose()
95+
usage: UsageV1DTO;
96+
}
97+
98+
@Expose()
99+
export class ChoiceV1DTO {
100+
index: number;
101+
message: MessageV1DTO;
102+
finish_reason: string;
103+
}

src/chat/chat.module.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Module } from '@nestjs/common';
2+
3+
import { ChatController } from './chat.controller.js';
4+
import { ChatService } from './chat.service.js';
5+
6+
@Module({
7+
controllers: [ChatController],
8+
providers: [ChatService],
9+
})
10+
export class ChatModule {}

src/chat/chat.service.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
3+
import { ChatService } from './chat.service.js';
4+
5+
describe('ChatService', () => {
6+
let service: ChatService;
7+
8+
beforeEach(async () => {
9+
const module: TestingModule = await Test.createTestingModule({
10+
providers: [ChatService],
11+
}).compile();
12+
13+
service = module.get<ChatService>(ChatService);
14+
});
15+
16+
it('should be defined', () => {
17+
expect(service).toBeDefined();
18+
});
19+
});

0 commit comments

Comments
 (0)