File size: 7,806 Bytes
e9f0d54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
### **FastAPI AI**

This FastAPI app loads a GPT-2 model, tokenizes input text, classifies it, and returns whether the text is AI-generated or human-written.

### **install Dependencies**

```bash
pip install -r requirements.txt

```

This command installs all the dependencies listed in the `requirements.txt` file. It ensures that your environment has the required packages to run the project smoothly.

**NOTE: IF YOU HAVE DONE ANY CHANGES DON'NT FORGOT TO PUT IT IN THE REQUIREMENTS.TXT USING `bash pip freeze > requirements.txt `**

---

### **Functions**

1. **`load_model()`**  
   Loads the GPT-2 model and tokenizer from specified paths.

2. **`lifespan()`**  
   Manages the app's lifecycle: loads the model at startup and handles cleanup on shutdown.

3. **`classify_text_sync()`**  
   Synchronously tokenizes input text and classifies it using the GPT-2 model. Returns the classification and perplexity.

4. **`classify_text()`**  
   Asynchronously executes `classify_text_sync()` in a thread pool to ensure non-blocking processing.

5. **`analyze_text()`**  
   **POST** endpoint: accepts text input, classifies it using `classify_text()`, and returns the result with perplexity.

6. **`health_check()`**  
   **GET** endpoint: simple health check to confirm the API is running.

---

### **Code Overview**

```python
executor = ThreadPoolExecutor(max_workers=2)
```

- **`ThreadPoolExecutor(max_workers=2)`** limits the number of concurrent threads (tasks) per worker process to 2 for text classification. This helps control resource usage and prevent overloading the server.

---

### **Running and Load Balancing:**

To run the app in production with load balancing:

```bash
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
```

This command launches the FastAPI app with **4 worker processes**, allowing it to handle multiple requests concurrently.

### **Concurrency Explained:**

1. **`ThreadPoolExecutor(max_workers=20)`**

   - Controls the **number of threads** within a **single worker** process.
   - Allows up to 20 tasks (text classification requests) to be handled simultaneously per worker, improving responsiveness for I/O-bound tasks.

2. **`--workers 4` in Uvicorn**
   - Spawns **4 independent worker processes** to handle incoming HTTP requests.
   - Each worker can independently handle multiple tasks, increasing the app's ability to process concurrent requests in parallel.

### **How They Relate:**

- **Uvicorn’s `--workers`** defines how many worker processes the server will run.
- **`ThreadPoolExecutor`** limits how many tasks (threads) each worker can process concurrently.

For example, with **4 workers** and **20 threads per worker**, the server can handle **80 tasks concurrently**. This provides scalable and efficient processing, balancing the load across multiple workers and threads.

### **Endpoints**

#### 1. **`/analyze`**

- **Method:** `POST`
- **Description:** Classifies whether the text is AI-generated or human-written.
- **Request:**
  ```json
  { "text": "sample text" }
  ```
- **Response:**
  ```json
  { "result": "AI-generated", "perplexity": 55.67 }
  ```

#### 2. **`/health`**

- **Method:** `GET`
- **Description:** Returns the status of the API.
- **Response:**
  ```json
  { "status": "ok" }
  ```

---

### **Running the API**

Start the server with:

```bash
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
```

---

### **πŸ§ͺ Testing the API**

You can test the FastAPI endpoint using `curl` like this:

```bash
curl -X POST http://127.0.0.1:8000/analyze \
  -H "Authorization: Bearer HelloThere" \
  -H "Content-Type: application/json" \
  -d '{"text": "This is a sample sentence for analysis."}'
```

- The `-H "Authorization: Bearer HelloThere"` part is used to simulate the **handshake**.
- FastAPI checks this token against the one loaded from the `.env` file.
- If the token matches, the request is accepted and processed.
- Otherwise, it responds with a `403 Unauthorized` error.

---

### **API Documentation**

- **Swagger UI:** `http://127.0.0.1:8000/docs` -> `/docs`
- **ReDoc:** `http://127.0.0.1:8000/redoc` -> `/redoc`

### **πŸ” Handshake Mechanism**

In this part, we're implementing a simple handshake to verify that the request is coming from a trusted source (e.g., our NestJS server). Here's how it works:

- We load a secret token from the `.env` file.
- When a request is made to the FastAPI server, we extract the `Authorization` header and compare it with our expected secret token.
- If the token does **not** match, we immediately return a **403 Forbidden** response with the message `"Unauthorized"`.
- If the token **does** match, we allow the request to proceed to the next step.

The verification function looks like this:

```python
def verify_token(auth: str):
    if auth != f"Bearer {EXPECTED_TOKEN}":
        raise HTTPException(status_code=403, detail="Unauthorized")
```

This provides a basic but effective layer of security to prevent unauthorized access to the API.

### **Implement it with NEST.js**

NOTE: Make an micro service in NEST.JS and implement it there and call it from app.controller.ts

in fastapi.service.ts file what we have done is

### Project Structure

```files
nestjs-fastapi-bridge/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app.controller.ts
β”‚   β”œβ”€β”€ app.module.ts
β”‚   └── fastapi.service.ts
β”œβ”€β”€ .env

```

---

### Step-by-Step Setup

#### 1. `.env`

Create a `.env` file at the root with the following:

```environment
  FASTAPI_BASE_URL=http://localhost:8000
  SECRET_TOKEN="HelloThere"
```

#### 2. `fastapi.service.ts`

```javascript
  // src/fastapi.service.ts
  import { Injectable } from "@nestjs/common";
  import { HttpService } from "@nestjs/axios";
  import { ConfigService } from "@nestjs/config";
  import { firstValueFrom } from "rxjs";

  @Injectable()
  export class FastAPIService {
    constructor(
      private http: HttpService,
      private config: ConfigService,
    ) {}

    async analyzeText(text: string) {
      const url = `${this.config.get("FASTAPI_BASE_URL")}/analyze`;
      const token = this.config.get("SECRET_TOKEN");

      const response = await firstValueFrom(
        this.http.post(
          url,
          { text },
          {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          },
        ),
      );

      return response.data;
    }
  }
```

#### 3. `app.module.ts`

```javascript
// src/app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { HttpModule } from "@nestjs/axios";
import { AppController } from "./app.controller";
import { FastAPIService } from "./fastapi.service";

@Module({
  imports: [ConfigModule.forRoot(), HttpModule],
  controllers: [AppController],
  providers: [FastAPIService],
})
export class AppModule {}
```

---

#### 4. `app.controller.ts`

```javascript
  // src/app.controller.ts
  import { Body, Controller, Post, Get, Query } from '@nestjs/common';
  import { FastAPIService } from './fastapi.service';

  @Controller()
  export class AppController {
    constructor(private readonly fastapiService: FastAPIService) {}

    @Post('analyze-text')
    async callFastAPI(@Body('text') text: string) {
      return this.fastapiService.analyzeText(text);
    }

    @Get()
    getHello(): string {
      return 'NestJS is connected to FastAPI ';
    }
  }
```

### πŸš€ How to Run

Run the server of flask and nest.js:

- for nest.js
  ```bash
  npm run start
  ```
- for Fastapi

  ```bash
  uvicorn app:app --reload
  ```

Make sure your FastAPI service is running at `http://localhost:8000`.

### Test with CURL

```bash
curl -X POST http://localhost:3000/analyze-text \
  -H 'Content-Type: application/json' \
  -d '{"text": "This is a test input"}'
```