# IVT AI Plugin

## 1. Project Overview

The **IVT AI Plugin** is a lightweight real-time Invalid Traffic (IVT) validation and risk-scoring system for ad traffic requests.

It validates incoming OpenRTB requests using rule-based checks, Redis-based real-time state tracking, and an IsolationForest machine learning model.

The system produces:

* Rule-based risk score
* ML anomaly risk score
* Final combined risk score
* IVT verdict
* Contributing IVT features
* AI-generated explanation

---

## 2. Objective

The objective is to identify potentially invalid or suspicious ad traffic in real time by analyzing multiple signals:

* IP blocklist
* User-Agent
* Geo mismatch
* Request velocity
* Duplicate requests
* ML-based anomaly detection

The plugin also uses **Google Gemini** to explain the validation result in simple, human-readable language.

> **Important:** Gemini is used only for explanation. It does not calculate the risk score or determine the IVT verdict.

---

## 3. Architecture / Flow

```text
Client / SSP / Postman
       |
       v
OpenRTB Request
       |
       v
FastAPI /validate
       |
       v
RTB Request Adapter
       |
       v
Pydantic Request Validation
       |
       v
Feature Extraction
       |
       +----------------------+
       |                      |
       v                      v
IP Blocklist            User-Agent Check
       |                      |
       +----------+-----------+
                  |
                  v
           Geo Mismatch Check
                  |
                  v
               Redis
           +------+------+
           |             |
           v             v
       Velocity       Duplicate
           |             |
           +------+------+
                  |
                  v
          Rule-Based Scoring
                  |
                  v
           IsolationForest
                  |
                  v
          ML Risk Score 0-100
                  |
                  v
       Rule Score + ML Score
             70% + 30%
                  |
                  v
          Final Risk Score
                  |
                  v
          Verdict Generation
                  |
                  v
       Clean / Suspicious / Blocked
                  |
                  v
            Gemini AI
                  |
                  v
        AI Explanation
                  |
                  v
          JSON Response
```

### Key Design Principle

```text
Rules + ML
    ↓
Risk Score + Verdict
    ↓
Gemini AI
    ↓
Explanation
```

Gemini must never directly decide whether traffic is **Clean, Suspicious, or Blocked**.

---

## 4. Project Structure

```text
ivt_ai_plugin/
│
├── main.py
│
├── validation/
│   ├── __init__.py
│   └── request_validator.py
│
├── features/
│   ├── __init__.py
│   ├── feature_extractor.py
│   └── rtb_adapter.py
│
├── scoring/
│   ├── __init__.py
│   ├── weighted_scorer.py
│   ├── redis_state.py
│   ├── anomaly_model.py
│   └── blender.py
│
├── explain/
│   ├── __init__.py
│   └── ai_explainer.py
│
├── data/
│   ├── blocklist_ips.csv
│   ├── blocklist_user_agents.csv
│   ├── traffic_events.csv
│   ├── ml_features.csv
│   └── prepare_ml_data.py
│
├── test_validation.py
├── test_blocklist.py
├── test_user_agent.py
├── test_features.py
├── test_redis.py
├── test_duplicate.py
├── test_anomaly.py
└── test_blender.py
```

---

## 5. Libraries Used

| Library | Purpose |
|---|---|
| **FastAPI** | REST API for IVT validation |
| **Pydantic** | Request validation and data modeling |
| **Pandas** | Data processing and ML feature preparation |
| **Scikit-learn** | IsolationForest anomaly detection |
| **Redis** | Real-time velocity and duplicate tracking |
| **Google GenAI SDK** | Gemini AI-based explanations |
| **Pytest** | Unit and integration testing |

---

## 6. OpenRTB Request Mapping

The plugin accepts an **OpenRTB request** through the FastAPI `/validate` endpoint.

The RTB adapter converts the OpenRTB request into the internal `IVTRequest` format.

Example mapping:

```text
OpenRTB Request
      ↓
RTB Adapter
      ↓
Internal IVTRequest
      ↓
Feature Extraction
```

The following information is extracted from the OpenRTB request:

```text
Request ID       → event_id
device.ip        → ip
device.ua        → user_agent
device.geo       → geo_declared
timestamp        → timestamp
```

The current implementation treats the request as an impression event when processing the sample RTB request.

> `imp.id` is an **Impression ID**, not a Creative ID. Therefore, `creative_id` is not used in the current validator design.

---

## 7. Request Validation

Incoming requests are validated using **Pydantic**.

The internal request schema contains:

```text
event_id
timestamp
ip
user_agent
geo_declared
geo_ip
event_type
```

The `event_type` accepts:

```text
impression
click
```

The IP address is validated using Pydantic's `IPvAnyAddress`.

---

## 8. IVT Feature Detection

### IP Blocklist

The incoming IP is checked against:

```text
data/blocklist_ips.csv
```

Example:

```text
ip,reason
192.0.2.55,datacenter_ip
10.10.10.10,known_bot
203.0.113.25,suspicious_source
```

If the IP is found:

```text
blocklist_hit = true
```

---

### User-Agent Check

The User-Agent is checked against:

```text
data/blocklist_user_agents.csv
```

Example patterns:

```text
bot
crawler
python-requests
curl
```

If a matching pattern is found:

```text
bad_ua = true
```

---

### Geo Mismatch

The declared geography is compared with the IP-derived geography.

Example:

```text
geo_declared = US
geo_ip       = SG
```

Result:

```text
geo_mismatch = true
```

> The current sample RTB adapter uses the declared geo as a temporary `geo_ip` value for testing. A real IP geolocation service/database is not currently integrated.

---

## 9. Redis Implementation

Redis is used for **real-time state tracking**.

Redis is responsible for:

1. Request velocity detection
2. Duplicate request detection

### Velocity Detection

Requests are tracked by IP using a Redis sorted set.

Current configuration:

```text
Window: 60 seconds
Threshold: 3 requests
```

Example:

```text
Request 1 → count = 1
Request 2 → count = 2
Request 3 → count = 3
                 ↓
          high_velocity = true
```

### Duplicate Detection

Duplicate requests are detected using:

```text
IP + User-Agent
```

within the configured time window.

Example:

```text
Same IP
+
Same User-Agent
        ↓
duplicate = true
```

The current duplicate detection window is:

```text
60 seconds
```

Redis is not currently used for IP blocklist or User-Agent validation. Those checks use local CSV files.

---

## 10. Rule-Based Scoring

The rule-based scorer uses weighted IVT signals.

Current weights:

| Feature | Weight |
|---|---:|
| Blocklist IP | 40 |
| Bad User-Agent | 20 |
| High Velocity | 15 |
| Duplicate | 15 |
| Geo Mismatch | 10 |

Maximum rule score:

```text
100
```

Example:

```text
Blocklist IP     = 40
Bad User-Agent   = 20
Geo mismatch     = 10
--------------------
Rule Score       = 70
```

The score is capped at 100.

---

## 11. IsolationForest Anomaly Detection

The ML layer uses **IsolationForest** from Scikit-learn.

The model uses these features:

```text
request_count
high_velocity
duplicate
geo_mismatch
bad_ua
```

The model is trained using:

```text
data/ml_features.csv
```

The model is trained once when the FastAPI application starts.

It then generates an anomaly score for each incoming request.

### Anomaly Score

IsolationForest produces a decision score where:

```text
Higher score → more normal
Lower score  → more anomalous
```

The score is normalized to a:

```text
0–100 ML risk score
```

where a higher value represents higher risk.

---

## 12. Rule + ML Score Blending

The final risk score combines both scoring layers.

Current weights:

```text
Rule Score = 70%
ML Score   = 30%
```

Formula:

```text
Final Risk Score =
    (Rule Score × 0.70)
    +
    (ML Risk Score × 0.30)
```

Example:

```text
Rule Score = 70
ML Score   = 48.55

Final Risk Score =
(70 × 0.70) + (48.55 × 0.30)

= 49 + 14.565

= 63.56
```

---

## 13. Verdict Thresholds

The final risk score determines the verdict.

```text
0 – 29     → Clean
30 – 70    → Suspicious
71 – 100   → Blocked
```

Examples:

```text
13.53 → Clean
63.56 → Suspicious
86.74 → Blocked
```

---

## 14. Gemini AI Integration

The plugin uses **Google Gemini** to generate a short explanation for the final IVT validation result.

### Purpose

Gemini provides a human-readable explanation based on:

```text
Risk Score
Verdict
Contributing Features
```

Example:

```text
Risk Score: 80.19
Verdict: Blocked
Contributing Features:
blocklist_hit, bad_ua, high_velocity, duplicate
```

Gemini then generates a short explanation such as:

```text
The traffic was blocked because the IP was found in the
blocklist and the request showed an automated User-Agent,
high request velocity, and duplicate behavior.
```

### AI Responsibility

Gemini:

* Explains the result
* Uses the existing risk score
* Uses the existing verdict
* Describes the contributing features

Gemini does **not**:

* Calculate the risk score
* Change the risk score
* Determine the verdict
* Override the rule-based or ML decision

### Configuration

Set the Gemini API key as an environment variable:

```bash
export GEMINI_API_KEY="your_api_key"
```

The application reads the key using:

```python
os.getenv("GEMINI_API_KEY")
```

### Gemini Model

The current implementation uses:

```text
gemini-2.5-flash
```

If the API key is unavailable or the Gemini request fails, the validator continues to work and returns:

```text
AI explanation unavailable.
```

---

## 15. API Endpoint

### POST `/validate`

The FastAPI endpoint accepts an OpenRTB request and returns the calculated risk score, verdict, and AI explanation.

Start the server:

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

API:

```text
POST /validate
```

Swagger UI:

```text
http://127.0.0.1:8000/docs
```

---

## 16. Sample OpenRTB Request

```json
{
    "id": "b35bacd195733f5f27c8268c29b74fe8yt",
    "device": {
        "ip": "192.0.2.55",
        "ua": "python-requests/2.31.0",
        "geo": {
            "country": "US"
        }
    },
    "imp": [
        {
            "id": "1"
        }
    ]
}
```

The request is mapped through the RTB adapter before IVT validation.

---

## 17. Sample Response

```json
{
    "event_id": "b35bacd195733f5f27c8268c29b74fe8yt",
    "rule_score": 90,
    "ml_score": 57.3,
    "risk_score": 80.19,
    "verdict": "Blocked",
    "contributing_features": [
        "blocklist_hit",
        "bad_ua",
        "high_velocity",
        "duplicate"
    ],
    "explanation": "The traffic was classified as blocked due to multiple high-risk IVT signals."
}
```

---

## 18. Installation & Setup

Create a Python virtual environment:

```bash
python3 -m venv venv
```

Activate it:

```bash
source venv/bin/activate
```

Install required packages:

```bash
pip install fastapi uvicorn pydantic redis pandas scikit-learn google-genai
```

Make sure Redis is running:

```bash
redis-cli ping
```

Expected:

```text
PONG
```

Configure the Gemini API key:

```bash
export GEMINI_API_KEY="your_api_key"
```

Verify that the environment variable is configured:

```bash
python -c "import os; print('API key set' if os.getenv('GEMINI_API_KEY') else 'API key NOT set')"
```

---

## 19. Running the Application

Start FastAPI:

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

The API can then be tested using:

```text
Swagger UI
Postman
```

Swagger:

```text
http://127.0.0.1:8000/docs
```

---

## 20. Testing

Individual components were tested separately:

```bash
python3 test_validation.py
python3 test_blocklist.py
python3 test_user_agent.py
python3 test_features.py
python3 test_redis.py
python3 test_duplicate.py
python3 test_anomaly.py
python3 test_blender.py
```

End-to-end testing was performed through the FastAPI `/validate` endpoint using sample OpenRTB requests.

Tested scenarios include:

```text
Clean traffic
Duplicate requests
High-velocity traffic
Blocklisted IP
Bad User-Agent
Geo mismatch
Suspicious traffic
Blocked traffic
ML anomaly detection
Rule + ML score blending
Gemini AI explanation
```

---

## 21. Current Implementation Status

```text
Pydantic Request Validation        Completed
OpenRTB Request Mapping            Completed
IP Blocklist Validation            Completed
User-Agent Validation              Completed
Geo Mismatch Detection             Completed
Redis Velocity Detection           Completed
Redis Duplicate Detection          Completed
Rule-Based Risk Scoring            Completed
IsolationForest Anomaly Detection  Completed
ML Score Normalization             Completed
Rule + ML Score Blending           Completed
Verdict Generation                 Completed
FastAPI Integration                Completed
Gemini AI Integration              Completed
AI Explanation                     Completed
Postman End-to-End Testing         Completed
```

---

## 22. Future Improvements

Potential future enhancements include:

* Use a larger historical traffic dataset for ML training.
* Improve ML score calibration using real labeled traffic.
* Tune rule weights and verdict thresholds using validation data.
* Add persistent Redis-based blocked IP storage and fast lookup.
* Add better logging and monitoring.
* Add automated unit and integration tests.
* Add additional IVT signals.
* Integrate the plugin with the production ad-serving pipeline.
* Add real IP geolocation for accurate geo mismatch detection.
* Evaluate additional ML models if required.

---

## 23. Summary

The IVT AI Plugin provides a lightweight real-time validation and scoring pipeline that combines:

```text
OpenRTB Request
       ↓
Request Validation
       ↓
Feature Detection
       ↓
Rule-Based Detection
       +
Redis Real-Time State
       +
IsolationForest Anomaly Detection
       ↓
Combined Risk Score
       ↓
Clean / Suspicious / Blocked
       ↓
Gemini AI
       ↓
Human-readable Explanation
```

The plugin has been tested using FastAPI/Postman with multiple IVT scenarios, including Clean, Suspicious, and Blocked traffic.

The AI layer is intentionally separated from the decision-making layer so that **rules and ML determine the IVT risk and verdict, while Gemini only explains the result**.