<p align="center">
  <img src="https://evren.ssyz.org.tr/logo.svg" alt="EVREN" width="180" />
</p>

<h1 align="center">evren-sdk</h1>

<p align="center">
  <strong>EVREN MLOps Platform — Official Python SDK</strong>
</p>

<p align="center">
  <a href="https://pypi.org/project/evren-sdk/"><img src="https://img.shields.io/pypi/v/evren-sdk?style=flat-square&color=10b981&label=pypi" alt="PyPI" /></a>
  <a href="https://pypi.org/project/evren-sdk/"><img src="https://img.shields.io/pypi/pyversions/evren-sdk?style=flat-square&color=3b82f6" alt="Python" /></a>
  <a href="https://github.com/speker/evren-sdk/blob/main/LICENSE"><img src="https://img.shields.io/github/license/speker/evren-sdk?style=flat-square&color=6366f1" alt="License" /></a>
  <a href="https://github.com/speker/evren-sdk/actions"><img src="https://img.shields.io/github/actions/workflow/status/speker/evren-sdk/publish.yml?style=flat-square&label=CI" alt="CI" /></a>
  <img src="https://img.shields.io/badge/GPU-H200_×_48-f59e0b?style=flat-square" alt="GPU" />
</p>

<p align="center">
  <a href="#-türkçe">Türkçe</a> · <a href="#-english">English</a> · <a href="examples/">Examples</a> · <a href="CHANGELOG.md">Changelog</a>
</p>

---

<br/>

## 🇹🇷 Türkçe

EVREN platformu üzerinde eğitilmiş bilgisayarlı görü modellerine Python'dan çıkarım yapmanızı sağlayan resmi SDK.

**Nesne tespiti** · **Sınıflandırma** · **Segmentasyon** · **OBB** · **Keypoint** · **Edge Inference**

<br/>

### Mimari

```
                           ┌──────────────────────────────┐
                           │      EVREN Cloud (HPC)       │
                           │                              │
 ┌──────────┐   HTTPS/TLS │  ┌────────┐   ┌───────────┐  │
 │  Python  │─────────────▶│  │FastAPI │──▶│  Triton   │  │
 │   SDK    │◀─────────────│  │  GW    │◀──│  Server   │  │
 └──────────┘    JSON      │  └────────┘   └─────┬─────┘  │
       │                   │                     │        │
       │                   │              ┌──────┴──────┐ │
       │                   │              │ 48× H200 GPU│ │
       │                   │              │ InfiniBand  │ │
       │                   │              │ 400 Gbps    │ │
       │                   │              └─────────────┘ │
       │                   └──────────────────────────────┘
       │
       ▼
 ┌───────────┐
 │  Lokal    │  Edge mode: GPU gerektirmez
 │  Cihaz    │  Webcam / RTSP / Video / Klasör
 └───────────┘
```

**SDK → API Gateway → GPU Cluster** — tek bir `predict()` çağrısı altında
48× NVIDIA H200 GPU, InfiniBand NDR 400G ağ altyapısı çalışır.
Kullanıcı altyapı yönetmez, sadece `pip install` ve 3 satır kod yeter.

<br/>

### Kurulum

```bash
pip install evren-sdk            # temel SDK
pip install evren-sdk[edge]      # + OpenCV (kamera/video desteği)
```

<br/>

### Hızlı Başlangıç

```python
from evren_sdk import EvrenClient

client = EvrenClient(api_key="evren_xxxxx")
result = client.predict("kullanici/model-adi", "foto.jpg", confidence=0.3)

for det in result.predictions:
    print(f"{det.class_name}: {det.confidence:.0%}  bbox={det.bbox}")
```

> 📖 **Daha fazla örnek:** [`examples/`](examples/) dizininde 7 çalıştırılabilir script bulunur.

<br/>

### Kimlik Doğrulama

Platformda **Ayarlar → API Anahtarları** sayfasından anahtar oluşturun.
Anahtar `evren_` ön eki ile başlar.

```python
client = EvrenClient(api_key="evren_xxxxx")    # API anahtarı (önerilen)
client = EvrenClient(api_key="eyJhbGci...")    # JWT token
```

<br/>

### Çıkarım Akışı

```
                  ┌─────────┐
                  │  Görsel  │  dosya yolu / Path / bytes
                  └────┬────┘
                       │
                  ┌────▼────┐
                  │ predict │  confidence, iou, image_size, classes
                  └────┬────┘
                       │
               ┌───────▼────────┐
               │ PredictResult  │
               │                │
               │  .count        │
               │  .inference_ms │
               │  .predictions[]│
               └───────┬────────┘
                       │
          ┌────────────┼────────────┐
          │            │            │
     ┌────▼───┐  ┌─────▼────┐  ┌───▼────┐
     │ filter │  │ to_yolo  │  │  save  │
     │ ()     │  │ to_coco  │  │ .json  │
     │        │  │ to_csv   │  │ .csv   │
     └────────┘  └──────────┘  │ .txt   │
                               └────────┘
```

<br/>

### Tekil Çıkarım

```python
result = client.predict(
    model="kullanici/model-adi",        # slug, slug:tag veya UUID
    image="resim.jpg",                  # dosya yolu, Path veya bytes
    confidence=0.25,
    iou=0.45,
    image_size=640,
    classes=["araba", "insan"],         # isteğe bağlı
)
```

| `model` Formatı | Açıklama |
|---|---|
| `"owner/slug"` | Son versiyonu otomatik çözer |
| `"owner/slug:v2.0"` | Belirli versiyon etiketi |
| `"019cec..."` (UUID) | Doğrudan versiyon ID |

<br/>

### Toplu Çıkarım (Batch)

```python
batch = client.predict_batch(
    model="kullanici/model-adi",
    images=["img1.jpg", "img2.jpg", "img3.jpg"],
    confidence=0.3,
)

for r in batch:
    print(f"{r.count} tespit, {r.inference_ms:.0f} ms")
```

> 📖 **Örnek:** [`examples/02_batch_inference.py`](examples/02_batch_inference.py)

<br/>

### Sonuç İşleme & Export

```python
result = client.predict("kullanici/model", "sahne.jpg")

# filtrele
filtre = result.filter(min_confidence=0.5, classes=["araba"])

# export
result.to_yolo()          # YOLO txt format
result.to_coco()          # COCO dict list
result.to_csv()           # CSV string

# dosyaya kaydet (format uzantıdan anlaşılır)
result.save("sonuc.json")
result.save("sonuc.csv")
result.save("labels.txt")
```

> 📖 **Örnek:** [`examples/03_result_export.py`](examples/03_result_export.py)

<br/>

### Model Bilgileri & Warmup

```python
# sınıfları listele
info = client.model_classes("kullanici/model-adi")
for cls in info.classes:
    print(f"  {cls.name}: {cls.color}")

# mevcut modelleri listele
for m in client.list_models():
    print(f"{m.full_slug} — {m.architecture}")

# GPU'ya ön-yükleme (cold-start elimine)
client.warmup(["kullanici/model-adi"])
```

<br/>

### Performans Testi

```python
bench = client.benchmark("kullanici/model", "test.jpg", rounds=20)

print(f"Avg: {bench.avg_ms:.1f}ms  |  p95: {bench.p95_ms:.1f}ms")
print(f"Min: {bench.min_ms:.1f}ms  |  Max: {bench.max_ms:.1f}ms")
print(f"Throughput: {bench.throughput_fps:.1f} FPS")
```

> 📖 **Örnek:** [`examples/04_benchmark.py`](examples/04_benchmark.py)

<br/>

### Model İndirme

```python
path = client.download_model("kullanici/model", output="weights/", fmt="onnx")
print(f"Kaydedildi: {path}")   # weights/best.onnx
```

<br/>

### Active Learning

Düşük güvenli tespitleri otomatik olarak veri setine gönderip insan doğrulaması ile model döngüsünü iyileştirin.

```
  ┌──────────┐     ┌───────────┐     ┌──────────┐     ┌───────────┐
  │ Çıkarım  │────▶│  Filtrele │────▶│  Upload  │────▶│  İnsan    │
  │ predict()│     │ conf<0.5  │     │ submit() │     │ Doğrulama │
  └──────────┘     └───────────┘     └──────────┘     └─────┬─────┘
                                                            │
       ┌────────────────────────────────────────────────────┘
       │
  ┌────▼─────┐
  │  Yeniden │
  │  Eğitim  │
  └──────────┘
```

```python
result = client.predict("kullanici/model", "belirsiz.jpg", confidence=0.1)
belirsiz = result.filter(max_confidence=0.5)

client.submit_for_review(dataset_id="<UUID>", image="belirsiz.jpg")
```

> 📖 **Örnek:** [`examples/06_active_learning.py`](examples/06_active_learning.py)

<br/>

### Asenkron Kullanım

```python
import asyncio
from evren_sdk import AsyncEvrenClient

async def main():
    async with AsyncEvrenClient(api_key="evren_xxxxx") as client:
        result = await client.predict("kullanici/model", "foto.jpg")
        batch  = await client.predict_batch("kullanici/model", ["a.jpg", "b.jpg"])

asyncio.run(main())
```

> 📖 **Örnek:** [`examples/07_async_pipeline.py`](examples/07_async_pipeline.py) — paralel çıkarım

<br/>

### Edge Modu (GPU'suz Cihazlar)

GPU olmayan cihazlarda (Raspberry Pi, laptop, endüstriyel PC) gerçek zamanlı
çıkarım. Çıkarım EVREN GPU'larında çalışır — lokal deneyim hissi verir.

```
  ┌────────────┐         ┌──────────────────┐         ┌────────────┐
  │   Kamera   │  frame  │   EvrenCamera    │  HTTPS  │ EVREN GPU  │
  │  Webcam /  │────────▶│                  │────────▶│  Cluster   │
  │  RTSP /    │         │  compress + send │         │            │
  │  Video     │◀────────│  draw results    │◀────────│  predict   │
  └────────────┘  render └──────────────────┘  JSON   └────────────┘
```

```bash
pip install evren-sdk[edge]
```

```python
from evren_sdk import EvrenCamera

cam = EvrenCamera("evren_...", "kullanici/model", confidence=0.3)

cam.run(0)                                      # webcam, ESC ile kapat
cam.record("input.mp4", "output.mp4")           # video isle + kaydet

for frame, result in cam.stream(0):             # kendi loop'unuz
    print(f"{result.count} tespit")

for path, result in cam.scan("images/"):        # klasör tarama
    print(f"{path.name}: {result.count} nesne")
```

| Parametre | Varsayılan | Açıklama |
|---|---|---|
| `max_fps` | `15.0` | Bant genişliği koruma limiti |
| `jpeg_quality` | `70` | Sıkıştırma kalitesi (20-95) |
| `draw` | `True` | Tahminleri frame üzerine çiz |
| `confidence` | `0.25` | Minimum güven eşiği |

> 📖 **Örnek:** [`examples/05_edge_camera.py`](examples/05_edge_camera.py)

<br/>

### Hata Yönetimi

```python
from evren_sdk import (
    EvrenClient, InsufficientCreditsError,
    NotFoundError, RateLimitError, InferenceError,
)

client = EvrenClient(api_key="evren_xxxxx")

try:
    result = client.predict("kullanici/model", "test.jpg")
except InsufficientCreditsError as e:
    print(f"Kredi yetersiz — gerekli: {e.required}, bakiye: {e.available}")
except NotFoundError:
    print("Model bulunamadı")
except RateLimitError as e:
    time.sleep(e.retry_after)
except InferenceError:
    print("GPU sunucusu geçici olarak kullanılamıyor")
```

| Exception | HTTP | Açıklama |
|---|---|---|
| `AuthenticationError` | 401, 403 | Geçersiz veya süresi dolmuş anahtar |
| `InsufficientCreditsError` | 402 | Kredi bakiyesi yetersiz |
| `NotFoundError` | 404 | Model veya versiyon bulunamadı |
| `ValidationError` | 422 | Hatalı parametre |
| `RateLimitError` | 429 | İstek limiti aşıldı |
| `InferenceError` | 502, 503 | GPU sunucusu hatası |

> Her çıkarım kredi tüketir. Bakiye yetersizse SDK `InsufficientCreditsError` fırlatır —
> `e.required` ve `e.available` alanları bakiye bilgisini taşır.

<br/>

### API Referansı

<details>
<summary><strong>Veri Modelleri</strong></summary>

| Sınıf | Alanlar / Metotlar |
|---|---|
| `PredictResult` | `predictions`, `inference_ms`, `count`, `image_width`, `image_height` |
| ↳ metotlar | `filter()`, `to_yolo()`, `to_coco()`, `to_csv()`, `save()` |
| `Prediction` | `class_name`, `confidence`, `bbox`, `color`, `mask`, `keypoints`, `obb` |
| ↳ metotlar | `to_dict()` |
| `BatchResult` | `results`, `total_ms`, `count` — iterable, `len()` destekler |
| `BenchmarkResult` | `model`, `rounds`, `avg_ms`, `min_ms`, `max_ms`, `p95_ms`, `throughput_fps` |
| `ModelClasses` | `classes`, `architecture`, `model_name`, `total`, `imgsz` — `in` operatörü |
| ↳ metotlar | `names()` |
| `ModelInfo` | `id`, `name`, `slug`, `architecture`, `owner_username`, `full_slug` |
| `ModelVersion` | `id`, `version_tag`, `framework`, `metrics`, `weights_url` |
| `ClassInfo` | `name`, `color` |
| `EvrenCamera` | `stream()`, `run()`, `scan()`, `record()`, `stats` |

</details>

<details>
<summary><strong>Client Metotları</strong></summary>

| Metot | Açıklama |
|---|---|
| `predict(model, image, **kw)` | Tekil çıkarım |
| `predict_batch(model, images, **kw)` | GPU batch çıkarım |
| `model_classes(model)` | Model sınıfları, mimari, imgsz |
| `warmup(models)` | GPU ön-yükleme |
| `list_models(limit)` | Mevcut modelleri listele |
| `list_versions(model_id)` | Model versiyonlarını listele |
| `resolve(slug)` | Slug → version UUID çözümle |
| `benchmark(model, image, **kw)` | Performans testi |
| `download_model(model, output, fmt)` | Ağırlık dosyası indir |
| `submit_for_review(dataset_id, image)` | Active Learning yükle |

`AsyncEvrenClient` aynı API'yi `async/await` ile sunar.

</details>

<br/>

---

<br/>

## 🇬🇧 English

Official Python SDK for running inference on computer vision models trained on
the EVREN platform.

**Object Detection** · **Classification** · **Segmentation** · **OBB** · **Keypoint** · **Edge Inference**

<br/>

### Architecture

```
                           ┌──────────────────────────────┐
                           │      EVREN Cloud (HPC)       │
                           │                              │
 ┌──────────┐   HTTPS/TLS │  ┌────────┐   ┌───────────┐  │
 │  Python  │─────────────▶│  │FastAPI │──▶│  Triton   │  │
 │   SDK    │◀─────────────│  │  GW    │◀──│  Server   │  │
 └──────────┘    JSON      │  └────────┘   └─────┬─────┘  │
       │                   │                     │        │
       │                   │              ┌──────┴──────┐ │
       │                   │              │ 48× H200 GPU│ │
       │                   │              │ InfiniBand  │ │
       │                   │              │ 400 Gbps    │ │
       │                   │              └─────────────┘ │
       │                   └──────────────────────────────┘
       │
       ▼
 ┌───────────┐
 │  Local    │  Edge mode: no GPU required
 │  Device   │  Webcam / RTSP / Video / Folder
 └───────────┘
```

**SDK → API Gateway → GPU Cluster** — a single `predict()` call leverages
48× NVIDIA H200 GPUs with InfiniBand NDR 400G interconnect.
No infrastructure management — just `pip install` and 3 lines of code.

<br/>

### Installation

```bash
pip install evren-sdk            # core SDK
pip install evren-sdk[edge]      # + OpenCV (camera/video support)
```

<br/>

### Quick Start

```python
from evren_sdk import EvrenClient

client = EvrenClient(api_key="evren_xxxxx")
result = client.predict("owner/model-name", "photo.jpg", confidence=0.3)

for det in result.predictions:
    print(f"{det.class_name}: {det.confidence:.0%}  bbox={det.bbox}")
```

> 📖 **More examples:** see the [`examples/`](examples/) directory for 7 runnable scripts.

<br/>

### Authentication

Create an API key from **Settings → API Keys** on the platform.
Keys start with the `evren_` prefix.

```python
client = EvrenClient(api_key="evren_xxxxx")    # API key (recommended)
client = EvrenClient(api_key="eyJhbGci...")    # JWT token
```

<br/>

### Inference Pipeline

```
                  ┌─────────┐
                  │  Image  │  file path / Path / bytes
                  └────┬────┘
                       │
                  ┌────▼────┐
                  │ predict │  confidence, iou, image_size, classes
                  └────┬────┘
                       │
               ┌───────▼────────┐
               │ PredictResult  │
               │                │
               │  .count        │
               │  .inference_ms │
               │  .predictions[]│
               └───────┬────────┘
                       │
          ┌────────────┼────────────┐
          │            │            │
     ┌────▼───┐  ┌─────▼────┐  ┌───▼────┐
     │ filter │  │ to_yolo  │  │  save  │
     │ ()     │  │ to_coco  │  │ .json  │
     │        │  │ to_csv   │  │ .csv   │
     └────────┘  └──────────┘  │ .txt   │
                               └────────┘
```

<br/>

### Single Prediction

```python
result = client.predict(
    model="owner/model-name",           # slug, slug:tag, or UUID
    image="image.jpg",                  # file path, Path, or bytes
    confidence=0.25,
    iou=0.45,
    image_size=640,
    classes=["car", "person"],          # optional
)
```

| `model` Format | Description |
|---|---|
| `"owner/slug"` | Resolves to latest version |
| `"owner/slug:v2.0"` | Specific version tag |
| `"019cec..."` (UUID) | Direct version ID |

<br/>

### Batch Prediction

```python
batch = client.predict_batch(
    model="owner/model-name",
    images=["img1.jpg", "img2.jpg", "img3.jpg"],
    confidence=0.3,
)

for r in batch:
    print(f"{r.count} detections, {r.inference_ms:.0f} ms")
```

> 📖 **Example:** [`examples/02_batch_inference.py`](examples/02_batch_inference.py)

<br/>

### Result Processing & Export

```python
result = client.predict("owner/model", "scene.jpg")

filtered = result.filter(min_confidence=0.5, classes=["car"])

result.to_yolo()          # YOLO txt
result.to_coco()          # COCO dict list
result.to_csv()           # CSV string

result.save("result.json")
result.save("result.csv")
result.save("labels.txt")
```

> 📖 **Example:** [`examples/03_result_export.py`](examples/03_result_export.py)

<br/>

### Model Info & Warmup

```python
info = client.model_classes("owner/model-name")
for cls in info.classes:
    print(f"  {cls.name}: {cls.color}")

for m in client.list_models():
    print(f"{m.full_slug} — {m.architecture}")

client.warmup(["owner/model-name"])   # eliminate cold-start
```

<br/>

### Benchmarking

```python
bench = client.benchmark("owner/model", "test.jpg", rounds=20)

print(f"Avg: {bench.avg_ms:.1f}ms  |  p95: {bench.p95_ms:.1f}ms")
print(f"Throughput: {bench.throughput_fps:.1f} FPS")
```

> 📖 **Example:** [`examples/04_benchmark.py`](examples/04_benchmark.py)

<br/>

### Model Download

```python
path = client.download_model("owner/model", output="weights/", fmt="onnx")
print(f"Saved to: {path}")   # weights/best.onnx
```

<br/>

### Active Learning

Automatically send uncertain predictions to a dataset for human review.

```
  ┌──────────┐     ┌───────────┐     ┌──────────┐     ┌───────────┐
  │ Predict  │────▶│  Filter   │────▶│  Upload  │────▶│  Human    │
  │          │     │ conf<0.5  │     │ submit() │     │  Review   │
  └──────────┘     └───────────┘     └──────────┘     └─────┬─────┘
                                                            │
       ┌────────────────────────────────────────────────────┘
       │
  ┌────▼──────┐
  │  Retrain  │
  └───────────┘
```

```python
result = client.predict("owner/model", "uncertain.jpg", confidence=0.1)
uncertain = result.filter(max_confidence=0.5)

client.submit_for_review(dataset_id="<UUID>", image="uncertain.jpg")
```

> 📖 **Example:** [`examples/06_active_learning.py`](examples/06_active_learning.py)

<br/>

### Async Usage

```python
import asyncio
from evren_sdk import AsyncEvrenClient

async def main():
    async with AsyncEvrenClient(api_key="evren_xxxxx") as client:
        result = await client.predict("owner/model", "photo.jpg")
        batch  = await client.predict_batch("owner/model", ["a.jpg", "b.jpg"])

asyncio.run(main())
```

> 📖 **Example:** [`examples/07_async_pipeline.py`](examples/07_async_pipeline.py)

<br/>

### Edge Mode (GPU-free Devices)

Real-time inference on devices without a GPU (Raspberry Pi, laptops,
industrial PCs). Inference runs on EVREN cloud GPUs — the UX feels local.

```
  ┌────────────┐         ┌──────────────────┐         ┌────────────┐
  │   Camera   │  frame  │   EvrenCamera    │  HTTPS  │ EVREN GPU  │
  │  Webcam /  │────────▶│                  │────────▶│  Cluster   │
  │  RTSP /    │         │  compress + send │         │            │
  │  Video     │◀────────│  draw results    │◀────────│  predict   │
  └────────────┘  render └──────────────────┘  JSON   └────────────┘
```

```bash
pip install evren-sdk[edge]
```

```python
from evren_sdk import EvrenCamera

cam = EvrenCamera("evren_...", "owner/model", confidence=0.3)

cam.run(0)                                      # webcam, ESC to quit
cam.record("input.mp4", "output.mp4")           # process + save
for frame, result in cam.stream(0):             # custom loop
    print(f"{result.count} detections")
for path, result in cam.scan("images/"):        # folder scan
    print(f"{path.name}: {result.count} objects")
```

| Parameter | Default | Description |
|---|---|---|
| `max_fps` | `15.0` | FPS cap to conserve bandwidth |
| `jpeg_quality` | `70` | JPEG compression quality (20-95) |
| `draw` | `True` | Render predictions on frame |
| `confidence` | `0.25` | Minimum confidence threshold |

> 📖 **Example:** [`examples/05_edge_camera.py`](examples/05_edge_camera.py)

<br/>

### Error Handling

```python
from evren_sdk import (
    EvrenClient, InsufficientCreditsError,
    NotFoundError, RateLimitError, InferenceError,
)

try:
    result = client.predict("owner/model", "test.jpg")
except InsufficientCreditsError as e:
    print(f"Not enough credits — need: {e.required}, have: {e.available}")
except NotFoundError:
    print("Model not found")
except RateLimitError as e:
    time.sleep(e.retry_after)
except InferenceError:
    print("GPU server temporarily unavailable")
```

| Exception | HTTP | Description |
|---|---|---|
| `AuthenticationError` | 401, 403 | Invalid or expired key |
| `InsufficientCreditsError` | 402 | Insufficient credits |
| `NotFoundError` | 404 | Model or version not found |
| `ValidationError` | 422 | Invalid parameter |
| `RateLimitError` | 429 | Rate limit exceeded |
| `InferenceError` | 502, 503 | GPU server error |

> Every inference call consumes credits. When balance is too low, the SDK raises
> `InsufficientCreditsError` with `e.required` and `e.available` fields.

<br/>

### API Reference

<details>
<summary><strong>Data Models</strong></summary>

| Class | Fields / Methods |
|---|---|
| `PredictResult` | `predictions`, `inference_ms`, `count`, `image_width`, `image_height` |
| ↳ methods | `filter()`, `to_yolo()`, `to_coco()`, `to_csv()`, `save()` |
| `Prediction` | `class_name`, `confidence`, `bbox`, `color`, `mask`, `keypoints`, `obb` |
| ↳ methods | `to_dict()` |
| `BatchResult` | `results`, `total_ms`, `count` — iterable, supports `len()` |
| `BenchmarkResult` | `model`, `rounds`, `avg_ms`, `min_ms`, `max_ms`, `p95_ms`, `throughput_fps` |
| `ModelClasses` | `classes`, `architecture`, `model_name`, `total`, `imgsz` — supports `in` |
| ↳ methods | `names()` |
| `ModelInfo` | `id`, `name`, `slug`, `architecture`, `owner_username`, `full_slug` |
| `ModelVersion` | `id`, `version_tag`, `framework`, `metrics`, `weights_url` |
| `ClassInfo` | `name`, `color` |
| `EvrenCamera` | `stream()`, `run()`, `scan()`, `record()`, `stats` |

</details>

<details>
<summary><strong>Client Methods</strong></summary>

| Method | Description |
|---|---|
| `predict(model, image, **kw)` | Single inference |
| `predict_batch(model, images, **kw)` | GPU batch inference |
| `model_classes(model)` | Model classes, architecture, imgsz |
| `warmup(models)` | GPU pre-load |
| `list_models(limit)` | List available models |
| `list_versions(model_id)` | List model versions |
| `resolve(slug)` | Slug → version UUID |
| `benchmark(model, image, **kw)` | Performance test |
| `download_model(model, output, fmt)` | Download weights |
| `submit_for_review(dataset_id, image)` | Active Learning upload |

`AsyncEvrenClient` provides the same API with `async/await`.

</details>

<br/>

---

## Examples

| # | File | Description |
|---|---|---|
| 1 | [`01_quickstart.py`](examples/01_quickstart.py) | Temel tekil çıkarım / Basic single prediction |
| 2 | [`02_batch_inference.py`](examples/02_batch_inference.py) | Toplu GPU çıkarım / Batch GPU inference |
| 3 | [`03_result_export.py`](examples/03_result_export.py) | Filtreleme & export (YOLO, COCO, CSV, JSON) |
| 4 | [`04_benchmark.py`](examples/04_benchmark.py) | Performans testi / Latency & throughput |
| 5 | [`05_edge_camera.py`](examples/05_edge_camera.py) | Edge cihaz kamera / GPU-free real-time |
| 6 | [`06_active_learning.py`](examples/06_active_learning.py) | Aktif öğrenme döngüsü / Active learning loop |
| 7 | [`07_async_pipeline.py`](examples/07_async_pipeline.py) | Asenkron paralel çıkarım / Async pipeline |

---

## Requirements

- Python >= 3.10
- [httpx](https://www.python-httpx.org/) >= 0.27
- [opencv-python](https://pypi.org/project/opencv-python/) >= 4.8 *(only for `evren-sdk[edge]`)*

## License

[Apache License 2.0](LICENSE)
