Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve configuration experience #22

Merged
merged 13 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
env:
DOCKER_BUILDKIT: 1
AWS_REGION: eu-west-1
UV_SYSTEM_PYTHON: 1
jobs:
Run-test:
runs-on: ubuntu-22.04
Expand All @@ -13,6 +13,9 @@ jobs:
contents: read
issues: write
pull-requests: write
strategy:
matrix:
python-version: ["3.10", "3.11","3.12"]
steps:
- name: Checkout Repository
uses: actions/checkout@v4
Expand All @@ -21,10 +24,13 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.12"
cache: "pip"
python-version: ${{ matrix.python-version }}
- name: Install the latest version of uv and set the python version to 3.12
uses: astral-sh/setup-uv@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: pip install .[cpu,dev]
run: uv pip install .[cpu,dev]
- name: Run test
run: make test
- name: Pytest coverage comment
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ profile_default/
ipython_config.py

.env
.envrc
.focoos
.data
notebooks/.data
Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
| focoos_isaid_nano | Semantic Segmentation | - | Satellite Imagery, 15 classes |
| focoos_isaid_medium | Semantic Segmentation | - | Satellite Imagery, 15 classes |


# Focoos SDK


## Requirements

For **local inference**, ensure that you have CUDA 12 and cuDNN 9 installed, as they are required for onnxruntime version 1.20.1.

To install cuDNN 9:

```bash
apt-get -y install cudnn9-cuda-12
```
Expand All @@ -31,22 +31,23 @@ To perform inference using TensorRT, ensure you have TensorRT version 10.5 insta
# Install

Nvidia GPU:

```bash
pip install .[gpu]
pip install '.[gpu]'
```

Nvidia GPU,TensorRT:

```bash
pip install .[gpu,tensorrt]
pip install '.[gpu,tensorrt]'
```

CPU,COREML:

```bash
pip install .[cpu]
pip install '.[cpu]'
```



## 🤖 Cloud Inference

```python
Expand All @@ -58,19 +59,21 @@ model = focoos.get_remote_model("focoos_object365")
model.deploy()
detections = model.infer("./image.jpg", threshold=0.4)
```

## 🤖 Cloud Inference with Gradio

setup FOCOOS_API_KEY_GRADIO environment variable with your Focoos API key

```bash
pip install .[gradio]
pip install '.[gradio]'
```

```bash
python gradio/app.py
```

## Local Inference

```python
from focoos import Focoos

Expand Down
7 changes: 7 additions & 0 deletions focoos/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import typing
from typing import Optional

from pydantic_settings import BaseSettings

from focoos.ports import PROD_API_URL, RuntimeTypes

LogLevel = typing.Literal["DEBUG", "INFO", "WARNING", "ERROR", "FATAL", "CRITICAL"]


class FocoosConfig(BaseSettings):
focoos_api_key: Optional[str] = None
focoos_log_level: LogLevel = "DEBUG"
default_host_url: str = PROD_API_URL
runtime_type: RuntimeTypes = RuntimeTypes.ONNX_CUDA32
warmup_iter: int = 2


FOCOOS_CONFIG = FocoosConfig()
16 changes: 7 additions & 9 deletions focoos/focoos.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@

from tqdm import tqdm

from focoos.config import FocoosConfig
from focoos.config import FOCOOS_CONFIG
from focoos.local_model import LocalModel
from focoos.ports import DatasetMetadata, ModelMetadata, ModelPreview, ModelStatus
from focoos.ports import DatasetMetadata, ModelMetadata, ModelPreview, RuntimeTypes
from focoos.remote_model import RemoteModel
from focoos.utils.logger import setup_logging
from focoos.utils.system import HttpClient

logger = setup_logging()
config = FocoosConfig()


class Focoos:
def __init__(
self,
api_key: str = config.focoos_api_key, # type: ignore
host_url: str = config.default_host_url,
api_key: str = FOCOOS_CONFIG.focoos_api_key, # type: ignore
host_url: str = FOCOOS_CONFIG.default_host_url,
):
self.api_key = api_key
if not self.api_key:
Expand Down Expand Up @@ -69,13 +68,12 @@ def list_focoos_models(self) -> list[ModelPreview]:
def get_local_model(
self,
model_ref: str,
runtime_type: RuntimeTypes = FOCOOS_CONFIG.runtime_type,
) -> LocalModel:
model_dir = os.path.join(self.cache_dir, model_ref)
if os.path.exists(os.path.join(model_dir, "model.onnx")):
return LocalModel(model_dir)
else:
if not os.path.exists(os.path.join(model_dir, "model.onnx")):
self._download_model(model_ref)
return LocalModel(model_dir)
return LocalModel(model_dir, runtime_type)

def get_remote_model(self, model_ref: str) -> RemoteModel:
return RemoteModel(model_ref, self.http_client)
Expand Down
7 changes: 3 additions & 4 deletions focoos/local_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from PIL import Image
from supervision import BoxAnnotator, Detections, LabelAnnotator, MaskAnnotator

from focoos.config import FocoosConfig
from focoos.config import FOCOOS_CONFIG
from focoos.ports import (
FocoosDetections,
FocoosTask,
Expand All @@ -24,14 +24,13 @@
)

logger = get_logger(__name__)
config = FocoosConfig()


class LocalModel:
def __init__(
self,
model_dir: Union[str, Path],
runtime_type: RuntimeTypes = config.runtime_type,
runtime_type: RuntimeTypes = FOCOOS_CONFIG.runtime_type,
):
logger.debug(f"Runtime type: {runtime_type}, Loading model from {model_dir},")
if not os.path.exists(model_dir):
Expand All @@ -46,7 +45,7 @@ def __init__(
runtime_type,
str(os.path.join(model_dir, "model.onnx")),
self.metadata,
config.warmup_iter,
FOCOOS_CONFIG.warmup_iter,
)

def _read_metadata(self) -> ModelMetadata:
Expand Down
2 changes: 1 addition & 1 deletion focoos/ports.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,4 @@ class RuntimeTypes(str, Enum):
ONNX_TRT32 = "onnx_trt32"
ONNX_TRT16 = "onnx_trt16"
ONNX_CPU = "onnx_cpu"
COREML = "coreml"
ONNX_COREML = "onnx_coreml"
17 changes: 1 addition & 16 deletions focoos/remote_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,20 @@
from typing import Optional, Tuple, Union

import numpy as np
from PIL import Image
from supervision import BoxAnnotator, Detections, LabelAnnotator, MaskAnnotator
from tqdm import tqdm

from focoos.config import FocoosConfig
from focoos.ports import (
DeploymentMode,
FocoosDet,
FocoosDetections,
FocoosTask,
Hyperparameters,
LatencyMetrics,
ModelMetadata,
ModelStatus,
OnnxEngineOpts,
TrainInstance,
)
from focoos.runtime import ONNXRuntime
from focoos.utils.logger import get_logger
from focoos.utils.system import HttpClient
from focoos.utils.vision import (
focoos_detections_to_supervision,
image_loader,
image_preprocess,
scale_detections,
sv_to_focoos_detections,
)

config = FocoosConfig()
from focoos.utils.vision import focoos_detections_to_supervision, image_loader

logger = get_logger()

Expand Down
14 changes: 12 additions & 2 deletions focoos/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ def __init__(
options.enable_profiling = opts.verbose
# options.intra_op_num_threads = 1
available_providers = ort.get_available_providers()
if opts.cuda and "CUDAExecutionProvider" not in available_providers:
self.logger.warning("CUDA ExecutionProvider not found.")
if opts.trt and "TensorrtExecutionProvider" not in available_providers:
self.logger.warning("Tensorrt ExecutionProvider not found.")
if opts.vino and "OpenVINOExecutionProvider" not in available_providers:
self.logger.warning("OpenVINO ExecutionProvider not found.")
if opts.coreml and "CoreMLExecutionProvider" not in available_providers:
self.logger.warning("CoreML ExecutionProvider not found.")
# Set providers
providers = []
dtype = np.float32
Expand Down Expand Up @@ -160,7 +168,9 @@ def __init__(
self.dtype = dtype
self.binding = binding
self.ort_sess = ort.InferenceSession(model_path, options, providers=providers)
self.logger.info(f"[onnxruntime] Providers:{self.ort_sess.get_providers()}")
self.logger.info(
f"[onnxruntime] Active providers:{self.ort_sess.get_providers()}"
)
if self.ort_sess.get_inputs()[0].type == "tensor(uint8)":
self.dtype = np.uint8
else:
Expand Down Expand Up @@ -297,7 +307,7 @@ def get_runtime(
)
elif runtime_type == RuntimeTypes.ONNX_CPU:
opts = OnnxEngineOpts(cuda=False, verbose=False, warmup_iter=warmup_iter)
elif runtime_type == RuntimeTypes.COREML:
elif runtime_type == RuntimeTypes.ONNX_COREML:
opts = OnnxEngineOpts(
cuda=False, verbose=False, coreml=True, warmup_iter=warmup_iter
)
Expand Down
10 changes: 6 additions & 4 deletions focoos/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import logging.config
from functools import cache

from focoos.config import FOCOOS_CONFIG, LogLevel


class ColoredFormatter(logging.Formatter):
log_format = "[%(asctime)s][%(levelname)s][%(name)s]: %(message)s"
Expand Down Expand Up @@ -43,7 +45,7 @@ def format(self, record):
"default": {
"class": "logging.StreamHandler",
"formatter": "color",
"level": "DEBUG",
"level": FOCOOS_CONFIG.focoos_log_level,
},
},
"root": { # Configura il logger di default (root)
Expand All @@ -53,7 +55,7 @@ def format(self, record):
"loggers": {
"focoos": {
"handlers": ["default"],
"level": "DEBUG",
"level": FOCOOS_CONFIG.focoos_log_level,
"propagate": False,
},
"matplotlib": {"level": "WARNING"},
Expand All @@ -63,10 +65,10 @@ def format(self, record):


@cache
def get_logger(name="focoos", level=logging.DEBUG):
def get_logger(name="focoos", level: LogLevel = FOCOOS_CONFIG.focoos_log_level):
logger = logging.getLogger(name)
logger.setLevel(level)
return logging.getLogger(name)
return logger


def setup_logging():
Expand Down
12 changes: 5 additions & 7 deletions focoos/utils/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@

import requests

from focoos.config import FocoosConfig

config = FocoosConfig()
from focoos.config import FOCOOS_CONFIG


class HttpClient:
def __init__(
self, api_key: Optional[str] = None, host_url: str = config.default_host_url
self,
api_key: str,
host_url: str,
):
if not api_key and not config.focoos_api_key:
raise ValueError("API key is required")
self.api_key = api_key or config.focoos_api_key
self.api_key = api_key
self.host_url = host_url

self.default_headers = {
Expand Down
8 changes: 3 additions & 5 deletions notebooks/playground.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,12 @@
"\n",
"# os.environ[\"RUNTIME_TYPE\"] = \"onnx_trt16\"\n",
"from focoos import Focoos, DEV_API_URL\n",
"from focoos.config import FocoosConfig\n",
"from focoos.config import FOCOOS_CONFIG\n",
"import os\n",
"from pprint import pprint\n",
"from supervision import plot_image\n",
"\n",
"\n",
"config = FocoosConfig()\n",
"print(config)\n",
"print(FOCOOS_CONFIG)\n",
"focoos = Focoos(\n",
" api_key=os.getenv(\"FOCOOS_API_KEY\"),\n",
" host_url=DEV_API_URL,\n",
Expand Down Expand Up @@ -271,7 +269,7 @@
"metadata": {},
"outputs": [],
"source": [
"from focoos import Focoos, DEV_API_URL, DeploymentMode\n",
"from focoos import Focoos, DEV_API_URL\n",
"import os\n",
"from pprint import pprint\n",
"from supervision import plot_image\n",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ include = ["focoos**"]

[project]
name = "focoos"
version = "0.1.3"
version = "0.2.0"
description = "Focoos SDK"
readme = "README.md"
requires-python = ">=3.10"
Expand Down