# Named-Entity Recognition (NER)

## Overview

**Named Entity Recognition (NER)** is a text-processing method that reads unstructured text and **identifies specific entities** within it.

While Regular Expressions (Regex) are excellent for detecting patterns like IDs or Phone Numbers, they often fail at detecting unstructured entities. NER fills this gap.

**Key capabilities:**

* **Unstructured Detection:** Accurately detects **People (PERSON)**, **Organizations (ORGANIZATION)**, and **Locations (LOCATION)**.
* **Context Aware:** Distinguishes between "Apple" the fruit and "Apple" the company based on sentence context.

***

### API Categories

The GDP Labs NER service exposes **two categories of APIs**:

**1. `/analyze` — Detect Entities**

Extracts entities with their type, confidence score, and character offsets.

* **Use case:** You want to know *what* is in the text to tag it, filter it, or inspect it.

**2. `/anonymize` — Mask Entities**

Returns the text with PII already masked/replaced.

* **Use case:** You want a clean string immediately for storage or LLM consumption without custom logic.

***

## 1. Base URL & Authentication

**Staging Base URL** `https://stag-api-gdplabs-ner-api.obrol.id`

**Required Headers**

* `x-api-key: <YOUR_API_KEY>`
* `Content-Type: application/json`

{% hint style="info" %}
Contact your manager or the infrastructure team to obtain a valid API Key.
{% endhint %}

***

## 2. Option A – Direct HTTP API

Use this option if you are working in a non-Python environment (Node.js, Go, etc.) or want direct control.

**2.1 `POST /analyze` — Detect Entities**

**Endpoint:** `POST /analyze`

**Request:**

```json
{
  "text": "Nama saya John, alamat saya di Jalan Melati No. 21, dan saya bekerja di Acme Corp."
}
```

**Response:**

```json
{
  "entities": [
    {
      "entity_type": "PERSON",
      "start": 10,
      "end": 14,
      "score": 0.98
    },
    {
      "entity_type": "LOCATION",
      "start": 31,
      "end": 53,
      "score": 0.94
    },
    {
      "entity_type": "ORGANIZATION",
      "start": 77,
      "end": 86,
      "score": 0.92
    }
  ]
}
```

**cURL Example:**

```bash
curl -X POST 'https://stag-api-gdplabs-ner-api.obrol.id/analyze' \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: <YOUR_API_KEY>' \
  -d '{"text": "Nama saya John, alamat saya di Jalan Melati No. 21."}'
```

**2.2 `POST /anonymize` — Mask PII**

**Endpoint:** `POST /anonymize`

**Request:**

```json
{
  "text": "Nama saya Sarah, email saya sarah@example.com."
}
```

**Response:**

```json
{
  "text": "Nama saya Sa***h, email saya sa*************om."
}
```

**cURL Example:**

```bash
curl -X POST 'https://stag-api-gdplabs-ner-api.obrol.id/anonymize' \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: <YOUR_API_KEY>' \
  -d '{"text": "Nama saya Sarah, email saya sarah@example.com."}'
```

***

## 3. Option B – Using `gllm-privacy` SDK

If you are using Python, the `gllm-privacy` library provides a seamless wrapper around the NER service.

{% hint style="info" %}
**Note:** The SDK uses the `/analyze` endpoint under the hood to detect entities, but performs the actual **Anonymization** locally using its own `TextAnonymizer`. This gives you more control over the masking strategy (e.g., placeholders vs fake data).
{% endhint %}

### **3.1 Installation**

```bash
pip install keyring keyrings.gl-artifactregistry-auth
pip install gllm-privacy-binary --index-url https://glsdk.gdplabs.id/gen-ai/simple
```

### **3.2 Configuration & Initialization**

To use the remote service, you must configure the `GDPLabsNerApiRemoteRecognizer`.

```python
import os
from gllm_privacy.pii_detector import TextAnalyzer, TextAnonymizer
from gllm_privacy.pii_detector.constants import Entities
from gllm_privacy.pii_detector.recognizer.gdplabs_ner_api_remote_recognizer import GDPLabsNerApiRemoteRecognizer

# 1. Configure Credentials
NER_API_URL = "https://stag-api-gdplabs-ner-api.obrol.id/analyze"
NER_API_KEY = os.getenv("NER_API_KEY", "<YOUR_API_KEY>")

headers = {
    "x-api-key": NER_API_KEY
}

# 2. Initialize the Remote Recognizer
# You can create specific instances for different languages if needed (id/en)
remote_recognizer = GDPLabsNerApiRemoteRecognizer(
    api_url=NER_API_URL,
    api_headers=headers,
    supported_entities=[Entities.PERSON, Entities.ORGANIZATION_NAME, Entities.LOCATION]
)

# 3. Inject into Analyzer
text_analyzer = TextAnalyzer(additional_recognizers=[remote_recognizer])
```

### **3.3 Run Analysis (Detection)**

Use this step to inspect what the NER model detects before taking action.

```python
text = "Budi Santoso adalah Lead Engineer di PT Samudra Raya."

# Run Analysis
results = text_analyzer.analyze(
    text=text,
    entities=[Entities.PERSON, Entities.ORGANIZATION_NAME]
)

print("--- Detected Entities ---")
for res in results:
    detected_word = text[res.start:res.end]
    print(f"[{res.entity_type}] {detected_word} (Score: {res.score})")

# Output:
# [PERSON] Budi Santoso (Score: 0.99)
# [ORGANIZATION] PT Samudra Raya (Score: 0.98)
```

### **3.4 Run Anonymization**

Use the `TextAnonymizer` to mask the entities detected by the remote service.

```python
# Initialize Anonymizer
text_anonymizer = TextAnonymizer(text_analyzer)

# Execute Anonymization
anonymized_text = text_anonymizer.anonymize(
    text=text,
    entities=[Entities.PERSON, Entities.ORGANIZATION_NAME]
)

print(anonymized_text)

# Output:
# <PERSON_1> adalah Lead Engineer di <ORGANIZATION_1>.
```

***

## 4. When to Use What?

| Feature           | **HTTP API**                  | **SDK (`gllm-privacy`)**                            |
| ----------------- | ----------------------------- | --------------------------------------------------- |
| **Environment**   | Non-Python (Node, Go, etc.)   | Python Applications                                 |
| **Detection**     | Returns raw JSON of entities. | Returns `RecognizerResult` objects.                 |
| **Anonymization** | Server-side masking (\*\*\*). | Client-side masking (Placeholders or Fake Data).    |
| **Flexibility**   | Fixed output format.          | Highly customizable (add Regex, custom logic, etc). |
