Spaces:
Runtime error
Runtime error
soutrik commited on
Commit ·
035df3d
1
Parent(s): a31745a
check and confirm docker compose on gpu
Browse files- Dockerfile +29 -13
- docker-compose.yaml +29 -0
- ec2_runner_setup.md +20 -1
- main.py +4 -2
- poetry.lock +125 -80
- pyproject.toml +1 -1
- src/litserve_benchmark.py +32 -37
Dockerfile
CHANGED
|
@@ -1,16 +1,31 @@
|
|
| 1 |
-
# Stage 1: Base image with
|
| 2 |
-
FROM
|
| 3 |
|
| 4 |
LABEL maintainer="Soutrik [email protected]" \
|
| 5 |
description="Base Docker image for running a Python app with Poetry and GPU support."
|
| 6 |
|
| 7 |
-
# Install
|
| 8 |
-
RUN apt-get update && apt-get install -y --no-install-recommends
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 11 |
|
| 12 |
-
#
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
# Configure Poetry environment
|
| 16 |
ENV POETRY_NO_INTERACTION=1 \
|
|
@@ -23,7 +38,7 @@ WORKDIR /app
|
|
| 23 |
# Copy pyproject.toml and poetry.lock to install dependencies
|
| 24 |
COPY pyproject.toml poetry.lock /app/
|
| 25 |
|
| 26 |
-
# Install dependencies without
|
| 27 |
RUN --mount=type=cache,target=/tmp/poetry_cache poetry install --only main --no-root
|
| 28 |
|
| 29 |
# Stage 2: Build stage for the application
|
|
@@ -38,13 +53,11 @@ COPY main.py /app/main.py
|
|
| 38 |
# Stage 3: Final runtime stage
|
| 39 |
FROM base as runner
|
| 40 |
|
| 41 |
-
# Copy application source code and
|
| 42 |
COPY --from=builder /app/src /app/src
|
| 43 |
COPY --from=builder /app/configs /app/configs
|
| 44 |
COPY --from=builder /app/.project-root /app/.project-root
|
| 45 |
COPY --from=builder /app/main.py /app/main.py
|
| 46 |
-
|
| 47 |
-
# Copy virtual environment from the builder stage
|
| 48 |
COPY --from=builder /app/.venv /app/.venv
|
| 49 |
|
| 50 |
# Copy client files
|
|
@@ -53,8 +66,11 @@ COPY run_client.sh /app/run_client.sh
|
|
| 53 |
# Set the working directory to /app
|
| 54 |
WORKDIR /app
|
| 55 |
|
| 56 |
-
#
|
| 57 |
ENV PATH="/app/.venv/bin:$PATH"
|
| 58 |
|
| 59 |
-
#
|
|
|
|
|
|
|
|
|
|
| 60 |
CMD ["python", "-m", "main"]
|
|
|
|
| 1 |
+
# Stage 1: Base image with CUDA 12.2, cuDNN 9, and minimal runtime for PyTorch
|
| 2 |
+
FROM nvidia/cuda:12.2.0-runtime-ubuntu20.04 as base
|
| 3 |
|
| 4 |
LABEL maintainer="Soutrik [email protected]" \
|
| 5 |
description="Base Docker image for running a Python app with Poetry and GPU support."
|
| 6 |
|
| 7 |
+
# Install necessary system dependencies, including Python 3.10
|
| 8 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 9 |
+
software-properties-common && \
|
| 10 |
+
add-apt-repository ppa:deadsnakes/ppa && \
|
| 11 |
+
apt-get update && apt-get install -y --no-install-recommends \
|
| 12 |
+
python3.10 \
|
| 13 |
+
python3.10-venv \
|
| 14 |
+
python3.10-dev \
|
| 15 |
+
python3-pip \
|
| 16 |
+
curl \
|
| 17 |
+
git \
|
| 18 |
+
build-essential && \
|
| 19 |
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 20 |
|
| 21 |
+
# Set Python 3.10 as the default
|
| 22 |
+
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1 && \
|
| 23 |
+
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 && \
|
| 24 |
+
python --version
|
| 25 |
+
|
| 26 |
+
# Install Poetry
|
| 27 |
+
RUN curl -sSL https://install.python-poetry.org | python3 - && \
|
| 28 |
+
ln -s /root/.local/bin/poetry /usr/local/bin/poetry
|
| 29 |
|
| 30 |
# Configure Poetry environment
|
| 31 |
ENV POETRY_NO_INTERACTION=1 \
|
|
|
|
| 38 |
# Copy pyproject.toml and poetry.lock to install dependencies
|
| 39 |
COPY pyproject.toml poetry.lock /app/
|
| 40 |
|
| 41 |
+
# Install Python dependencies without building the app itself
|
| 42 |
RUN --mount=type=cache,target=/tmp/poetry_cache poetry install --only main --no-root
|
| 43 |
|
| 44 |
# Stage 2: Build stage for the application
|
|
|
|
| 53 |
# Stage 3: Final runtime stage
|
| 54 |
FROM base as runner
|
| 55 |
|
| 56 |
+
# Copy application source code and dependencies from the builder stage
|
| 57 |
COPY --from=builder /app/src /app/src
|
| 58 |
COPY --from=builder /app/configs /app/configs
|
| 59 |
COPY --from=builder /app/.project-root /app/.project-root
|
| 60 |
COPY --from=builder /app/main.py /app/main.py
|
|
|
|
|
|
|
| 61 |
COPY --from=builder /app/.venv /app/.venv
|
| 62 |
|
| 63 |
# Copy client files
|
|
|
|
| 66 |
# Set the working directory to /app
|
| 67 |
WORKDIR /app
|
| 68 |
|
| 69 |
+
# Add virtual environment to PATH
|
| 70 |
ENV PATH="/app/.venv/bin:$PATH"
|
| 71 |
|
| 72 |
+
# Install PyTorch with CUDA 12.2 support (adjusted for compatibility)
|
| 73 |
+
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu122
|
| 74 |
+
|
| 75 |
+
# Default command to run the application
|
| 76 |
CMD ["python", "-m", "main"]
|
docker-compose.yaml
CHANGED
|
@@ -19,6 +19,13 @@ services:
|
|
| 19 |
- default
|
| 20 |
env_file:
|
| 21 |
- .env
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
eval:
|
| 24 |
build:
|
|
@@ -38,6 +45,13 @@ services:
|
|
| 38 |
- default
|
| 39 |
env_file:
|
| 40 |
- .env
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
|
| 43 |
server:
|
|
@@ -61,6 +75,13 @@ services:
|
|
| 61 |
- .env
|
| 62 |
ports:
|
| 63 |
- "8080:8080"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
client:
|
| 66 |
build:
|
|
@@ -82,6 +103,14 @@ services:
|
|
| 82 |
env_file:
|
| 83 |
- .env
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
volumes:
|
| 87 |
data:
|
|
|
|
| 19 |
- default
|
| 20 |
env_file:
|
| 21 |
- .env
|
| 22 |
+
deploy:
|
| 23 |
+
resources:
|
| 24 |
+
reservations:
|
| 25 |
+
devices:
|
| 26 |
+
- driver: nvidia
|
| 27 |
+
count: 1
|
| 28 |
+
capabilities: [gpu]
|
| 29 |
|
| 30 |
eval:
|
| 31 |
build:
|
|
|
|
| 45 |
- default
|
| 46 |
env_file:
|
| 47 |
- .env
|
| 48 |
+
deploy:
|
| 49 |
+
resources:
|
| 50 |
+
reservations:
|
| 51 |
+
devices:
|
| 52 |
+
- driver: nvidia
|
| 53 |
+
count: 1
|
| 54 |
+
capabilities: [gpu]
|
| 55 |
|
| 56 |
|
| 57 |
server:
|
|
|
|
| 75 |
- .env
|
| 76 |
ports:
|
| 77 |
- "8080:8080"
|
| 78 |
+
deploy:
|
| 79 |
+
resources:
|
| 80 |
+
reservations:
|
| 81 |
+
devices:
|
| 82 |
+
- driver: nvidia
|
| 83 |
+
count: 1
|
| 84 |
+
capabilities: [gpu]
|
| 85 |
|
| 86 |
client:
|
| 87 |
build:
|
|
|
|
| 103 |
env_file:
|
| 104 |
- .env
|
| 105 |
|
| 106 |
+
deploy:
|
| 107 |
+
resources:
|
| 108 |
+
reservations:
|
| 109 |
+
devices:
|
| 110 |
+
- driver: nvidia
|
| 111 |
+
count: 1
|
| 112 |
+
capabilities: [gpu]
|
| 113 |
+
|
| 114 |
|
| 115 |
volumes:
|
| 116 |
data:
|
ec2_runner_setup.md
CHANGED
|
@@ -335,4 +335,23 @@ If successful, it should show details of the T4 GPU.
|
|
| 335 |
- **PyTorch**: Installed with CUDA 12.2 support
|
| 336 |
|
| 337 |
This setup ensures your system is ready for deep learning workloads with the T4 GPU.
|
| 338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
- **PyTorch**: Installed with CUDA 12.2 support
|
| 336 |
|
| 337 |
This setup ensures your system is ready for deep learning workloads with the T4 GPU.
|
| 338 |
+
|
| 339 |
+
Install conda and create a new environment for the project
|
| 340 |
+
Install pytorch and torchvision in the new environment
|
| 341 |
+
Install other dependencies like numpy, pandas, matplotlib, etc.
|
| 342 |
+
Run the project code in the new environment
|
| 343 |
+
>>> import torch
|
| 344 |
+
>>> print(torch.cuda.is_available())
|
| 345 |
+
>>> print(torch.cuda.get_device_name(0))
|
| 346 |
+
>>> print(torch.version.cuda)
|
| 347 |
+
```
|
| 348 |
+
__CUDA Docker Setup__:
|
| 349 |
+
```bash
|
| 350 |
+
# If you are using docker and want to run a container with CUDA support
|
| 351 |
+
sudo apt install -y nvidia-container-toolkit
|
| 352 |
+
nvidia-ctk --version
|
| 353 |
+
sudo systemctl restart docker
|
| 354 |
+
sudo systemctl status docker
|
| 355 |
+
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu20.04 nvidia-smi
|
| 356 |
+
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu20.04 nvcc --version
|
| 357 |
+
```
|
main.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
| 1 |
-
|
| 2 |
|
| 3 |
-
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
|
| 3 |
+
print(torch.cuda.is_available()) # Should return True if our GPU is enabled
|
| 4 |
+
print(torch.cuda.get_device_name(0)) # Should return "Tesla T4" if our GPU is enabled
|
| 5 |
+
print(torch.version.cuda) # Should return "12.4" if our GPU is enabled
|
poetry.lock
CHANGED
|
@@ -246,92 +246,93 @@ files = [
|
|
| 246 |
|
| 247 |
[[package]]
|
| 248 |
name = "aiohttp"
|
| 249 |
-
version = "3.11.
|
| 250 |
description = "Async http client/server framework (asyncio)"
|
| 251 |
optional = false
|
| 252 |
python-versions = ">=3.9"
|
| 253 |
files = [
|
| 254 |
-
{file = "aiohttp-3.11.
|
| 255 |
-
{file = "aiohttp-3.11.
|
| 256 |
-
{file = "aiohttp-3.11.
|
| 257 |
-
{file = "aiohttp-3.11.
|
| 258 |
-
{file = "aiohttp-3.11.
|
| 259 |
-
{file = "aiohttp-3.11.
|
| 260 |
-
{file = "aiohttp-3.11.
|
| 261 |
-
{file = "aiohttp-3.11.
|
| 262 |
-
{file = "aiohttp-3.11.
|
| 263 |
-
{file = "aiohttp-3.11.
|
| 264 |
-
{file = "aiohttp-3.11.
|
| 265 |
-
{file = "aiohttp-3.11.
|
| 266 |
-
{file = "aiohttp-3.11.
|
| 267 |
-
{file = "aiohttp-3.11.
|
| 268 |
-
{file = "aiohttp-3.11.
|
| 269 |
-
{file = "aiohttp-3.11.
|
| 270 |
-
{file = "aiohttp-3.11.
|
| 271 |
-
{file = "aiohttp-3.11.
|
| 272 |
-
{file = "aiohttp-3.11.
|
| 273 |
-
{file = "aiohttp-3.11.
|
| 274 |
-
{file = "aiohttp-3.11.
|
| 275 |
-
{file = "aiohttp-3.11.
|
| 276 |
-
{file = "aiohttp-3.11.
|
| 277 |
-
{file = "aiohttp-3.11.
|
| 278 |
-
{file = "aiohttp-3.11.
|
| 279 |
-
{file = "aiohttp-3.11.
|
| 280 |
-
{file = "aiohttp-3.11.
|
| 281 |
-
{file = "aiohttp-3.11.
|
| 282 |
-
{file = "aiohttp-3.11.
|
| 283 |
-
{file = "aiohttp-3.11.
|
| 284 |
-
{file = "aiohttp-3.11.
|
| 285 |
-
{file = "aiohttp-3.11.
|
| 286 |
-
{file = "aiohttp-3.11.
|
| 287 |
-
{file = "aiohttp-3.11.
|
| 288 |
-
{file = "aiohttp-3.11.
|
| 289 |
-
{file = "aiohttp-3.11.
|
| 290 |
-
{file = "aiohttp-3.11.
|
| 291 |
-
{file = "aiohttp-3.11.
|
| 292 |
-
{file = "aiohttp-3.11.
|
| 293 |
-
{file = "aiohttp-3.11.
|
| 294 |
-
{file = "aiohttp-3.11.
|
| 295 |
-
{file = "aiohttp-3.11.
|
| 296 |
-
{file = "aiohttp-3.11.
|
| 297 |
-
{file = "aiohttp-3.11.
|
| 298 |
-
{file = "aiohttp-3.11.
|
| 299 |
-
{file = "aiohttp-3.11.
|
| 300 |
-
{file = "aiohttp-3.11.
|
| 301 |
-
{file = "aiohttp-3.11.
|
| 302 |
-
{file = "aiohttp-3.11.
|
| 303 |
-
{file = "aiohttp-3.11.
|
| 304 |
-
{file = "aiohttp-3.11.
|
| 305 |
-
{file = "aiohttp-3.11.
|
| 306 |
-
{file = "aiohttp-3.11.
|
| 307 |
-
{file = "aiohttp-3.11.
|
| 308 |
-
{file = "aiohttp-3.11.
|
| 309 |
-
{file = "aiohttp-3.11.
|
| 310 |
-
{file = "aiohttp-3.11.
|
| 311 |
-
{file = "aiohttp-3.11.
|
| 312 |
-
{file = "aiohttp-3.11.
|
| 313 |
-
{file = "aiohttp-3.11.
|
| 314 |
-
{file = "aiohttp-3.11.
|
| 315 |
-
{file = "aiohttp-3.11.
|
| 316 |
-
{file = "aiohttp-3.11.
|
| 317 |
-
{file = "aiohttp-3.11.
|
| 318 |
-
{file = "aiohttp-3.11.
|
| 319 |
-
{file = "aiohttp-3.11.
|
| 320 |
-
{file = "aiohttp-3.11.
|
| 321 |
-
{file = "aiohttp-3.11.
|
| 322 |
-
{file = "aiohttp-3.11.
|
| 323 |
-
{file = "aiohttp-3.11.
|
| 324 |
-
{file = "aiohttp-3.11.
|
| 325 |
-
{file = "aiohttp-3.11.
|
| 326 |
-
{file = "aiohttp-3.11.
|
| 327 |
-
{file = "aiohttp-3.11.
|
| 328 |
-
{file = "aiohttp-3.11.
|
| 329 |
-
{file = "aiohttp-3.11.
|
| 330 |
]
|
| 331 |
|
| 332 |
[package.dependencies]
|
| 333 |
aiohappyeyeballs = ">=2.3.0"
|
| 334 |
aiosignal = ">=1.1.2"
|
|
|
|
| 335 |
attrs = ">=17.3.0"
|
| 336 |
frozenlist = ">=1.1.1"
|
| 337 |
multidict = ">=4.5,<7.0"
|
|
@@ -544,8 +545,10 @@ files = [
|
|
| 544 |
]
|
| 545 |
|
| 546 |
[package.dependencies]
|
|
|
|
| 547 |
idna = ">=2.8"
|
| 548 |
sniffio = ">=1.1"
|
|
|
|
| 549 |
|
| 550 |
[package.extras]
|
| 551 |
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
|
@@ -646,6 +649,9 @@ files = [
|
|
| 646 |
{file = "asyncpg-0.30.0.tar.gz", hash = "sha256:c551e9928ab6707602f44811817f82ba3c446e018bfe1d3abecc8ba5f3eac851"},
|
| 647 |
]
|
| 648 |
|
|
|
|
|
|
|
|
|
|
| 649 |
[package.extras]
|
| 650 |
docs = ["Sphinx (>=8.1.3,<8.2.0)", "sphinx-rtd-theme (>=1.2.2)"]
|
| 651 |
gssauth = ["gssapi", "sspilib"]
|
|
@@ -883,6 +889,8 @@ mypy-extensions = ">=0.4.3"
|
|
| 883 |
packaging = ">=22.0"
|
| 884 |
pathspec = ">=0.9.0"
|
| 885 |
platformdirs = ">=2"
|
|
|
|
|
|
|
| 886 |
|
| 887 |
[package.extras]
|
| 888 |
colorama = ["colorama (>=0.4.3)"]
|
|
@@ -1614,6 +1622,9 @@ files = [
|
|
| 1614 |
{file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"},
|
| 1615 |
]
|
| 1616 |
|
|
|
|
|
|
|
|
|
|
| 1617 |
[package.extras]
|
| 1618 |
toml = ["tomli"]
|
| 1619 |
|
|
@@ -2133,6 +2144,20 @@ files = [
|
|
| 2133 |
{file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"},
|
| 2134 |
]
|
| 2135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2136 |
[[package]]
|
| 2137 |
name = "fastapi"
|
| 2138 |
version = "0.115.5"
|
|
@@ -4248,6 +4273,9 @@ files = [
|
|
| 4248 |
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
|
| 4249 |
]
|
| 4250 |
|
|
|
|
|
|
|
|
|
|
| 4251 |
[[package]]
|
| 4252 |
name = "mypy-extensions"
|
| 4253 |
version = "1.0.0"
|
|
@@ -4768,7 +4796,7 @@ files = [
|
|
| 4768 |
]
|
| 4769 |
|
| 4770 |
[package.dependencies]
|
| 4771 |
-
numpy = {version = ">=1.
|
| 4772 |
python-dateutil = ">=2.8.2"
|
| 4773 |
pytz = ">=2020.1"
|
| 4774 |
tzdata = ">=2022.7"
|
|
@@ -5791,9 +5819,11 @@ files = [
|
|
| 5791 |
|
| 5792 |
[package.dependencies]
|
| 5793 |
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|
|
|
| 5794 |
iniconfig = "*"
|
| 5795 |
packaging = "*"
|
| 5796 |
pluggy = ">=1.5,<2"
|
|
|
|
| 5797 |
|
| 5798 |
[package.extras]
|
| 5799 |
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
|
@@ -6048,6 +6078,9 @@ files = [
|
|
| 6048 |
{file = "redis-5.0.8.tar.gz", hash = "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870"},
|
| 6049 |
]
|
| 6050 |
|
|
|
|
|
|
|
|
|
|
| 6051 |
[package.extras]
|
| 6052 |
hiredis = ["hiredis (>1.0.0)"]
|
| 6053 |
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
|
@@ -7245,6 +7278,17 @@ dev = ["tokenizers[testing]"]
|
|
| 7245 |
docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"]
|
| 7246 |
testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"]
|
| 7247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7248 |
[[package]]
|
| 7249 |
name = "tomlkit"
|
| 7250 |
version = "0.13.2"
|
|
@@ -7620,6 +7664,7 @@ h11 = ">=0.8"
|
|
| 7620 |
httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
|
| 7621 |
python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
| 7622 |
pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
|
|
|
|
| 7623 |
uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
|
| 7624 |
watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
| 7625 |
websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
|
|
@@ -8177,5 +8222,5 @@ type = ["pytest-mypy"]
|
|
| 8177 |
|
| 8178 |
[metadata]
|
| 8179 |
lock-version = "2.0"
|
| 8180 |
-
python-versions = "3.
|
| 8181 |
-
content-hash = "
|
|
|
|
| 246 |
|
| 247 |
[[package]]
|
| 248 |
name = "aiohttp"
|
| 249 |
+
version = "3.11.6"
|
| 250 |
description = "Async http client/server framework (asyncio)"
|
| 251 |
optional = false
|
| 252 |
python-versions = ">=3.9"
|
| 253 |
files = [
|
| 254 |
+
{file = "aiohttp-3.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7510b3ca2275691875ddf072a5b6cd129278d11fe09301add7d292fc8d3432de"},
|
| 255 |
+
{file = "aiohttp-3.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfab0d2c3380c588fc925168533edb21d3448ad76c3eadc360ff963019161724"},
|
| 256 |
+
{file = "aiohttp-3.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf02dba0f342f3a8228f43fae256aafc21c4bc85bffcf537ce4582e2b1565188"},
|
| 257 |
+
{file = "aiohttp-3.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92daedf7221392e7a7984915ca1b0481a94c71457c2f82548414a41d65555e70"},
|
| 258 |
+
{file = "aiohttp-3.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2274a7876e03429e3218589a6d3611a194bdce08c3f1e19962e23370b47c0313"},
|
| 259 |
+
{file = "aiohttp-3.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a2e1eae2d2f62f3660a1591e16e543b2498358593a73b193006fb89ee37abc6"},
|
| 260 |
+
{file = "aiohttp-3.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:978ec3fb0a42efcd98aae608f58c6cfcececaf0a50b4e86ee3ea0d0a574ab73b"},
|
| 261 |
+
{file = "aiohttp-3.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51f87b27d9219ed4e202ed8d6f1bb96f829e5eeff18db0d52f592af6de6bdbf"},
|
| 262 |
+
{file = "aiohttp-3.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:04d1a02a669d26e833c8099992c17f557e3b2fdb7960a0c455d7b1cbcb05121d"},
|
| 263 |
+
{file = "aiohttp-3.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3679d5fcbc7f1ab518ab4993f12f80afb63933f6afb21b9b272793d398303b98"},
|
| 264 |
+
{file = "aiohttp-3.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a4b24e03d04893b5c8ec9cd5f2f11dc9c8695c4e2416d2ac2ce6c782e4e5ffa5"},
|
| 265 |
+
{file = "aiohttp-3.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d9abdfd35ecff1c95f270b7606819a0e2de9e06fa86b15d9080de26594cf4c23"},
|
| 266 |
+
{file = "aiohttp-3.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b5c3e7928a0ad80887a5eba1c1da1830512ddfe7394d805badda45c03db3109"},
|
| 267 |
+
{file = "aiohttp-3.11.6-cp310-cp310-win32.whl", hash = "sha256:913dd9e9378f3c38aeb5c4fb2b8383d6490bc43f3b427ae79f2870651ae08f22"},
|
| 268 |
+
{file = "aiohttp-3.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:4ac26d482c2000c3a59bf757a77adc972828c9d4177b4bd432a46ba682ca7271"},
|
| 269 |
+
{file = "aiohttp-3.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26ac4c960ea8debf557357a172b3ef201f2236a462aefa1bc17683a75483e518"},
|
| 270 |
+
{file = "aiohttp-3.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8b1f13ebc99fb98c7c13057b748f05224ccc36d17dee18136c695ef23faaf4ff"},
|
| 271 |
+
{file = "aiohttp-3.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4679f1a47516189fab1774f7e45a6c7cac916224c91f5f94676f18d0b64ab134"},
|
| 272 |
+
{file = "aiohttp-3.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74491fdb3d140ff561ea2128cb7af9ba0a360067ee91074af899c9614f88a18f"},
|
| 273 |
+
{file = "aiohttp-3.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f51e1a90412d387e62aa2d243998c5eddb71373b199d811e6ed862a9f34f9758"},
|
| 274 |
+
{file = "aiohttp-3.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72ab89510511c3bb703d0bb5504787b11e0ed8be928ed2a7cf1cda9280628430"},
|
| 275 |
+
{file = "aiohttp-3.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6681c9e046d99646e8059266688374a063da85b2e4c0ebfa078cda414905d080"},
|
| 276 |
+
{file = "aiohttp-3.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a17f8a6d3ab72cbbd137e494d1a23fbd3ea973db39587941f32901bb3c5c350"},
|
| 277 |
+
{file = "aiohttp-3.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:867affc7612a314b95f74d93aac550ce0909bc6f0b6c658cc856890f4d326542"},
|
| 278 |
+
{file = "aiohttp-3.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:00d894ebd609d5a423acef885bd61e7f6a972153f99c5b3ea45fc01fe909196c"},
|
| 279 |
+
{file = "aiohttp-3.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:614c87be9d0d64477d1e4b663bdc5d1534fc0a7ebd23fb08347ab9fd5fe20fd7"},
|
| 280 |
+
{file = "aiohttp-3.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:533ed46cf772f28f3bffae81c0573d916a64dee590b5dfaa3f3d11491da05b95"},
|
| 281 |
+
{file = "aiohttp-3.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589884cfbc09813afb1454816b45677e983442e146183143f988f7f5a040791a"},
|
| 282 |
+
{file = "aiohttp-3.11.6-cp311-cp311-win32.whl", hash = "sha256:1da63633ba921669eec3d7e080459d4ceb663752b3dafb2f31f18edd248d2170"},
|
| 283 |
+
{file = "aiohttp-3.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:d778ddda09622e7d83095cc8051698a0084c155a1474bfee9bac27d8613dbc31"},
|
| 284 |
+
{file = "aiohttp-3.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:943a952df105a5305257984e7a1f5c2d0fd8564ff33647693c4d07eb2315446d"},
|
| 285 |
+
{file = "aiohttp-3.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d24ec28b7658970a1f1d98608d67f88376c7e503d9d45ff2ba1949c09f2b358c"},
|
| 286 |
+
{file = "aiohttp-3.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6720e809a660fdb9bec7c168c582e11cfedce339af0a5ca847a5d5b588dce826"},
|
| 287 |
+
{file = "aiohttp-3.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4252d30da0ada6e6841b325869c7ef5104b488e8dd57ec439892abbb8d7b3615"},
|
| 288 |
+
{file = "aiohttp-3.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f65f43ff01b238aa0b5c47962c83830a49577efe31bd37c1400c3d11d8a32835"},
|
| 289 |
+
{file = "aiohttp-3.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc5933f6c9b26404444d36babb650664f984b8e5fa0694540e7b7315d11a4ff"},
|
| 290 |
+
{file = "aiohttp-3.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5bf546ba0c029dfffc718c4b67748687fd4f341b07b7c8f1719d6a3a46164798"},
|
| 291 |
+
{file = "aiohttp-3.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c351d05bbeae30c088009c0bb3b17dda04fd854f91cc6196c448349cc98f71c3"},
|
| 292 |
+
{file = "aiohttp-3.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:10499079b063576fad1597898de3f9c0a2ce617c19cc7cd6b62fdcff6b408bf7"},
|
| 293 |
+
{file = "aiohttp-3.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:442ee82eda47dd59798d6866ce020fb8d02ea31ac9ac82b3d719ed349e6a9d52"},
|
| 294 |
+
{file = "aiohttp-3.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:86fce9127bc317119b34786d9e9ae8af4508a103158828a535f56d201da6ab19"},
|
| 295 |
+
{file = "aiohttp-3.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:973d26a5537ce5d050302eb3cd876457451745b1da0624cbb483217970e12567"},
|
| 296 |
+
{file = "aiohttp-3.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532b8f038a4e001137d3600cea5d3439d1881df41bdf44d0f9651264d562fdf0"},
|
| 297 |
+
{file = "aiohttp-3.11.6-cp312-cp312-win32.whl", hash = "sha256:4863c59f748dbe147da82b389931f2a676aebc9d3419813ed5ca32d057c9cb32"},
|
| 298 |
+
{file = "aiohttp-3.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:5d7f481f82c18ac1f7986e31ba6eea9be8b2e2c86f1ef035b6866179b6c5dd68"},
|
| 299 |
+
{file = "aiohttp-3.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:40f502350496ba4c6820816d3164f8a0297b9aa4e95d910da31beb189866a9df"},
|
| 300 |
+
{file = "aiohttp-3.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9072669b0bffb40f1f6977d0b5e8a296edc964f9cefca3a18e68649c214d0ce3"},
|
| 301 |
+
{file = "aiohttp-3.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:518160ecf4e6ffd61715bc9173da0925fcce44ae6c7ca3d3f098fe42585370fb"},
|
| 302 |
+
{file = "aiohttp-3.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f69cc1b45115ac44795b63529aa5caa9674be057f11271f65474127b24fc1ce6"},
|
| 303 |
+
{file = "aiohttp-3.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6be90a6beced41653bda34afc891617c6d9e8276eef9c183f029f851f0a3c3d"},
|
| 304 |
+
{file = "aiohttp-3.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:00c22fe2486308770d22ef86242101d7b0f1e1093ce178f2358f860e5149a551"},
|
| 305 |
+
{file = "aiohttp-3.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2607ebb783e3aeefa017ec8f34b506a727e6b6ab2c4b037d65f0bc7151f4430a"},
|
| 306 |
+
{file = "aiohttp-3.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f761d6819870c2a8537f75f3e2fc610b163150cefa01f9f623945840f601b2c"},
|
| 307 |
+
{file = "aiohttp-3.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e44d1bc6c88f5234115011842219ba27698a5f2deee245c963b180080572aaa2"},
|
| 308 |
+
{file = "aiohttp-3.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7e0cb6a1b1f499cb2aa0bab1c9f2169ad6913c735b7447e058e0c29c9e51c0b5"},
|
| 309 |
+
{file = "aiohttp-3.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a76b4d4ca34254dca066acff2120811e2a8183997c135fcafa558280f2cc53f3"},
|
| 310 |
+
{file = "aiohttp-3.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:69051c1e45fb18c0ae4d39a075532ff0b015982e7997f19eb5932eb4a3e05c17"},
|
| 311 |
+
{file = "aiohttp-3.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:aff2ed18274c0bfe0c1d772781c87d5ca97ae50f439729007cec9644ee9b15fe"},
|
| 312 |
+
{file = "aiohttp-3.11.6-cp313-cp313-win32.whl", hash = "sha256:2fbea25f2d44df809a46414a8baafa5f179d9dda7e60717f07bded56300589b3"},
|
| 313 |
+
{file = "aiohttp-3.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:f77bc29a465c0f9f6573d1abe656d385fa673e34efe615bd4acc50899280ee47"},
|
| 314 |
+
{file = "aiohttp-3.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:de6123b298d17bca9e53581f50a275b36e10d98e8137eb743ce69ee766dbdfe9"},
|
| 315 |
+
{file = "aiohttp-3.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a10200f705f4fff00e148b7f41e5d1d929c7cd4ac523c659171a0ea8284cd6fb"},
|
| 316 |
+
{file = "aiohttp-3.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7776ef6901b54dd557128d96c71e412eec0c39ebc07567e405ac98737995aad"},
|
| 317 |
+
{file = "aiohttp-3.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e5c2a55583cd91936baf73d223807bb93ace6eb1fe54424782690f2707162ab"},
|
| 318 |
+
{file = "aiohttp-3.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b032bd6cf7422583bf44f233f4a1489fee53c6d35920123a208adc54e2aba41e"},
|
| 319 |
+
{file = "aiohttp-3.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fe2d99acbc5cf606f75d7347bf3a027c24c27bc052d470fb156f4cfcea5739"},
|
| 320 |
+
{file = "aiohttp-3.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84a79c366375c2250934d1238abe5d5ea7754c823a1c7df0c52bf0a2bfded6a9"},
|
| 321 |
+
{file = "aiohttp-3.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33cbbe97dc94a34d1295a7bb68f82727bcbff2b284f73ae7e58ecc05903da97"},
|
| 322 |
+
{file = "aiohttp-3.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:19e4fb9ac727834b003338dcdd27dcfe0de4fb44082b01b34ed0ab67c3469fc9"},
|
| 323 |
+
{file = "aiohttp-3.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a97f6b2afbe1d27220c0c14ea978e09fb4868f462ef3d56d810d206bd2e057a2"},
|
| 324 |
+
{file = "aiohttp-3.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c3f7afeea03a9bc49be6053dfd30809cd442cc12627d6ca08babd1c1f9e04ccf"},
|
| 325 |
+
{file = "aiohttp-3.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0d10967600ce5bb69ddcb3e18d84b278efb5199d8b24c3c71a4959c2f08acfd0"},
|
| 326 |
+
{file = "aiohttp-3.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:60f2f631b9fe7aa321fa0f0ff3f5d8b9f7f9b72afd4eecef61c33cf1cfea5d58"},
|
| 327 |
+
{file = "aiohttp-3.11.6-cp39-cp39-win32.whl", hash = "sha256:4d2b75333deb5c5f61bac5a48bba3dbc142eebbd3947d98788b6ef9cc48628ae"},
|
| 328 |
+
{file = "aiohttp-3.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:8908c235421972a2e02abcef87d16084aabfe825d14cc9a1debd609b3cfffbea"},
|
| 329 |
+
{file = "aiohttp-3.11.6.tar.gz", hash = "sha256:fd9f55c1b51ae1c20a1afe7216a64a88d38afee063baa23c7fce03757023c999"},
|
| 330 |
]
|
| 331 |
|
| 332 |
[package.dependencies]
|
| 333 |
aiohappyeyeballs = ">=2.3.0"
|
| 334 |
aiosignal = ">=1.1.2"
|
| 335 |
+
async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""}
|
| 336 |
attrs = ">=17.3.0"
|
| 337 |
frozenlist = ">=1.1.1"
|
| 338 |
multidict = ">=4.5,<7.0"
|
|
|
|
| 545 |
]
|
| 546 |
|
| 547 |
[package.dependencies]
|
| 548 |
+
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
|
| 549 |
idna = ">=2.8"
|
| 550 |
sniffio = ">=1.1"
|
| 551 |
+
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""}
|
| 552 |
|
| 553 |
[package.extras]
|
| 554 |
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
|
|
|
|
| 649 |
{file = "asyncpg-0.30.0.tar.gz", hash = "sha256:c551e9928ab6707602f44811817f82ba3c446e018bfe1d3abecc8ba5f3eac851"},
|
| 650 |
]
|
| 651 |
|
| 652 |
+
[package.dependencies]
|
| 653 |
+
async-timeout = {version = ">=4.0.3", markers = "python_version < \"3.11.0\""}
|
| 654 |
+
|
| 655 |
[package.extras]
|
| 656 |
docs = ["Sphinx (>=8.1.3,<8.2.0)", "sphinx-rtd-theme (>=1.2.2)"]
|
| 657 |
gssauth = ["gssapi", "sspilib"]
|
|
|
|
| 889 |
packaging = ">=22.0"
|
| 890 |
pathspec = ">=0.9.0"
|
| 891 |
platformdirs = ">=2"
|
| 892 |
+
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
| 893 |
+
typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
|
| 894 |
|
| 895 |
[package.extras]
|
| 896 |
colorama = ["colorama (>=0.4.3)"]
|
|
|
|
| 1622 |
{file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"},
|
| 1623 |
]
|
| 1624 |
|
| 1625 |
+
[package.dependencies]
|
| 1626 |
+
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
| 1627 |
+
|
| 1628 |
[package.extras]
|
| 1629 |
toml = ["tomli"]
|
| 1630 |
|
|
|
|
| 2144 |
{file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"},
|
| 2145 |
]
|
| 2146 |
|
| 2147 |
+
[[package]]
|
| 2148 |
+
name = "exceptiongroup"
|
| 2149 |
+
version = "1.2.2"
|
| 2150 |
+
description = "Backport of PEP 654 (exception groups)"
|
| 2151 |
+
optional = false
|
| 2152 |
+
python-versions = ">=3.7"
|
| 2153 |
+
files = [
|
| 2154 |
+
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
| 2155 |
+
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
| 2156 |
+
]
|
| 2157 |
+
|
| 2158 |
+
[package.extras]
|
| 2159 |
+
test = ["pytest (>=6)"]
|
| 2160 |
+
|
| 2161 |
[[package]]
|
| 2162 |
name = "fastapi"
|
| 2163 |
version = "0.115.5"
|
|
|
|
| 4273 |
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
|
| 4274 |
]
|
| 4275 |
|
| 4276 |
+
[package.dependencies]
|
| 4277 |
+
typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""}
|
| 4278 |
+
|
| 4279 |
[[package]]
|
| 4280 |
name = "mypy-extensions"
|
| 4281 |
version = "1.0.0"
|
|
|
|
| 4796 |
]
|
| 4797 |
|
| 4798 |
[package.dependencies]
|
| 4799 |
+
numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""}
|
| 4800 |
python-dateutil = ">=2.8.2"
|
| 4801 |
pytz = ">=2020.1"
|
| 4802 |
tzdata = ">=2022.7"
|
|
|
|
| 5819 |
|
| 5820 |
[package.dependencies]
|
| 5821 |
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
| 5822 |
+
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
| 5823 |
iniconfig = "*"
|
| 5824 |
packaging = "*"
|
| 5825 |
pluggy = ">=1.5,<2"
|
| 5826 |
+
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
| 5827 |
|
| 5828 |
[package.extras]
|
| 5829 |
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
|
|
|
| 6078 |
{file = "redis-5.0.8.tar.gz", hash = "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870"},
|
| 6079 |
]
|
| 6080 |
|
| 6081 |
+
[package.dependencies]
|
| 6082 |
+
async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""}
|
| 6083 |
+
|
| 6084 |
[package.extras]
|
| 6085 |
hiredis = ["hiredis (>1.0.0)"]
|
| 6086 |
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
|
|
|
| 7278 |
docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"]
|
| 7279 |
testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"]
|
| 7280 |
|
| 7281 |
+
[[package]]
|
| 7282 |
+
name = "tomli"
|
| 7283 |
+
version = "2.1.0"
|
| 7284 |
+
description = "A lil' TOML parser"
|
| 7285 |
+
optional = false
|
| 7286 |
+
python-versions = ">=3.8"
|
| 7287 |
+
files = [
|
| 7288 |
+
{file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
|
| 7289 |
+
{file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
|
| 7290 |
+
]
|
| 7291 |
+
|
| 7292 |
[[package]]
|
| 7293 |
name = "tomlkit"
|
| 7294 |
version = "0.13.2"
|
|
|
|
| 7664 |
httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
|
| 7665 |
python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
| 7666 |
pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
|
| 7667 |
+
typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
|
| 7668 |
uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
|
| 7669 |
watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
|
| 7670 |
websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
|
|
|
|
| 8222 |
|
| 8223 |
[metadata]
|
| 8224 |
lock-version = "2.0"
|
| 8225 |
+
python-versions = "3.10.15"
|
| 8226 |
+
content-hash = "f716178afcbcd2f78554e71f39d279ce266c633a668a8246716f601c76801647"
|
pyproject.toml
CHANGED
|
@@ -7,7 +7,7 @@ license = "Apache-2.0"
|
|
| 7 |
readme = "README.md"
|
| 8 |
|
| 9 |
[tool.poetry.dependencies]
|
| 10 |
-
python = "3.
|
| 11 |
black = "24.8.0"
|
| 12 |
coverage = ">=7.6.1"
|
| 13 |
hydra-colorlog = "1.2.0"
|
|
|
|
| 7 |
readme = "README.md"
|
| 8 |
|
| 9 |
[tool.poetry.dependencies]
|
| 10 |
+
python = "3.10.15"
|
| 11 |
black = "24.8.0"
|
| 12 |
coverage = ">=7.6.1"
|
| 13 |
hydra-colorlog = "1.2.0"
|
src/litserve_benchmark.py
CHANGED
|
@@ -6,6 +6,11 @@ import requests
|
|
| 6 |
import psutil
|
| 7 |
from urllib.request import urlopen
|
| 8 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# Try importing `gpustat` for GPU monitoring
|
| 11 |
try:
|
|
@@ -16,7 +21,7 @@ except ImportError:
|
|
| 16 |
GPU_AVAILABLE = False
|
| 17 |
|
| 18 |
# Constants
|
| 19 |
-
SERVER_URL = "http://localhost:8080"
|
| 20 |
TEST_IMAGE_URL = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/beignets-task-guide.png"
|
| 21 |
|
| 22 |
|
|
@@ -28,7 +33,7 @@ def fetch_and_prepare_payload():
|
|
| 28 |
img_data = urlopen(TEST_IMAGE_URL).read()
|
| 29 |
return base64.b64encode(img_data).decode("utf-8")
|
| 30 |
except Exception as e:
|
| 31 |
-
|
| 32 |
return None
|
| 33 |
|
| 34 |
|
|
@@ -47,7 +52,7 @@ def send_request(payload, batch=False):
|
|
| 47 |
predictions = response.json() if response.status_code == 200 else None
|
| 48 |
return response_time, response.status_code, predictions
|
| 49 |
except Exception as e:
|
| 50 |
-
|
| 51 |
return None, None, None
|
| 52 |
|
| 53 |
|
|
@@ -73,7 +78,7 @@ def benchmark_api(num_requests=100, concurrency_level=10, batch=False):
|
|
| 73 |
"""
|
| 74 |
payload = fetch_and_prepare_payload()
|
| 75 |
if not payload:
|
| 76 |
-
|
| 77 |
return
|
| 78 |
|
| 79 |
payloads = [payload] * num_requests if batch else [payload]
|
|
@@ -114,11 +119,11 @@ def benchmark_api(num_requests=100, concurrency_level=10, batch=False):
|
|
| 114 |
avg_response_time = np.mean(response_times) * 1000 if response_times else 0 # ms
|
| 115 |
requests_per_second = num_requests / total_benchmark_time
|
| 116 |
|
| 117 |
-
|
| 118 |
for i, prediction in enumerate(
|
| 119 |
predictions[:5]
|
| 120 |
): # Show predictions for the first 5 requests
|
| 121 |
-
|
| 122 |
|
| 123 |
return {
|
| 124 |
"total_requests": num_requests,
|
|
@@ -134,66 +139,56 @@ def benchmark_api(num_requests=100, concurrency_level=10, batch=False):
|
|
| 134 |
|
| 135 |
def run_benchmarks():
|
| 136 |
"""
|
| 137 |
-
Run comprehensive benchmarks and create plots.
|
| 138 |
"""
|
| 139 |
concurrency_levels = [1, 8, 16, 32]
|
| 140 |
metrics = []
|
| 141 |
|
| 142 |
-
|
| 143 |
for concurrency in concurrency_levels:
|
| 144 |
-
|
| 145 |
result = benchmark_api(
|
| 146 |
num_requests=50, concurrency_level=concurrency, batch=False
|
| 147 |
)
|
| 148 |
if result:
|
| 149 |
metrics.append(result)
|
| 150 |
-
|
| 151 |
f"Concurrency {concurrency}: "
|
| 152 |
f"{result['requests_per_second']:.2f} reqs/sec, "
|
| 153 |
f"CPU: {result['avg_cpu_usage']:.1f}%, "
|
| 154 |
f"GPU: {result['avg_gpu_usage']:.1f}%"
|
| 155 |
)
|
| 156 |
|
| 157 |
-
# Generate
|
| 158 |
-
plt.figure(figsize=(
|
| 159 |
-
|
| 160 |
-
# Throughput
|
| 161 |
-
plt.subplot(1, 2, 1)
|
| 162 |
-
plt.plot(
|
| 163 |
-
concurrency_levels,
|
| 164 |
-
[m["requests_per_second"] for m in metrics],
|
| 165 |
-
"r-o",
|
| 166 |
-
label="Throughput",
|
| 167 |
-
)
|
| 168 |
-
plt.xlabel("Concurrency Level")
|
| 169 |
-
plt.ylabel("Requests per Second")
|
| 170 |
-
plt.title("API Throughput")
|
| 171 |
-
plt.grid(True)
|
| 172 |
-
|
| 173 |
-
# Resource Usage
|
| 174 |
-
plt.subplot(1, 2, 2)
|
| 175 |
plt.plot(
|
| 176 |
concurrency_levels,
|
| 177 |
[m["avg_cpu_usage"] for m in metrics],
|
| 178 |
"b-o",
|
| 179 |
label="CPU Usage",
|
| 180 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
if GPU_AVAILABLE:
|
|
|
|
| 182 |
plt.plot(
|
| 183 |
concurrency_levels,
|
| 184 |
[m["avg_gpu_usage"] for m in metrics],
|
| 185 |
"g-o",
|
| 186 |
label="GPU Usage",
|
| 187 |
)
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
plt.tight_layout()
|
| 195 |
-
plt.savefig("benchmark_results.png")
|
| 196 |
-
print("Benchmark results saved as 'benchmark_results.png'.")
|
| 197 |
|
| 198 |
|
| 199 |
if __name__ == "__main__":
|
|
|
|
| 6 |
import psutil
|
| 7 |
from urllib.request import urlopen
|
| 8 |
import matplotlib.pyplot as plt
|
| 9 |
+
from loguru import logger
|
| 10 |
+
import os
|
| 11 |
+
from dotenv import load_dotenv, find_dotenv
|
| 12 |
+
|
| 13 |
+
load_dotenv(find_dotenv())
|
| 14 |
|
| 15 |
# Try importing `gpustat` for GPU monitoring
|
| 16 |
try:
|
|
|
|
| 21 |
GPU_AVAILABLE = False
|
| 22 |
|
| 23 |
# Constants
|
| 24 |
+
SERVER_URL = os.getenv("SERVER_URL", "http://localhost:8080")
|
| 25 |
TEST_IMAGE_URL = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/beignets-task-guide.png"
|
| 26 |
|
| 27 |
|
|
|
|
| 33 |
img_data = urlopen(TEST_IMAGE_URL).read()
|
| 34 |
return base64.b64encode(img_data).decode("utf-8")
|
| 35 |
except Exception as e:
|
| 36 |
+
logger.info(f"Error fetching the image: {e}")
|
| 37 |
return None
|
| 38 |
|
| 39 |
|
|
|
|
| 52 |
predictions = response.json() if response.status_code == 200 else None
|
| 53 |
return response_time, response.status_code, predictions
|
| 54 |
except Exception as e:
|
| 55 |
+
logger.info(f"Error sending request: {e}")
|
| 56 |
return None, None, None
|
| 57 |
|
| 58 |
|
|
|
|
| 78 |
"""
|
| 79 |
payload = fetch_and_prepare_payload()
|
| 80 |
if not payload:
|
| 81 |
+
logger.info("Error preparing payload. Benchmark aborted.")
|
| 82 |
return
|
| 83 |
|
| 84 |
payloads = [payload] * num_requests if batch else [payload]
|
|
|
|
| 119 |
avg_response_time = np.mean(response_times) * 1000 if response_times else 0 # ms
|
| 120 |
requests_per_second = num_requests / total_benchmark_time
|
| 121 |
|
| 122 |
+
logger.info("\n--- Sample Predictions ---")
|
| 123 |
for i, prediction in enumerate(
|
| 124 |
predictions[:5]
|
| 125 |
): # Show predictions for the first 5 requests
|
| 126 |
+
logger.info(f"Request {i + 1}: {prediction}")
|
| 127 |
|
| 128 |
return {
|
| 129 |
"total_requests": num_requests,
|
|
|
|
| 139 |
|
| 140 |
def run_benchmarks():
|
| 141 |
"""
|
| 142 |
+
Run comprehensive benchmarks and create separate plots for CPU and GPU usage.
|
| 143 |
"""
|
| 144 |
concurrency_levels = [1, 8, 16, 32]
|
| 145 |
metrics = []
|
| 146 |
|
| 147 |
+
logger.info("Running API benchmarks...")
|
| 148 |
for concurrency in concurrency_levels:
|
| 149 |
+
logger.info(f"\nTesting concurrency level: {concurrency}")
|
| 150 |
result = benchmark_api(
|
| 151 |
num_requests=50, concurrency_level=concurrency, batch=False
|
| 152 |
)
|
| 153 |
if result:
|
| 154 |
metrics.append(result)
|
| 155 |
+
logger.info(
|
| 156 |
f"Concurrency {concurrency}: "
|
| 157 |
f"{result['requests_per_second']:.2f} reqs/sec, "
|
| 158 |
f"CPU: {result['avg_cpu_usage']:.1f}%, "
|
| 159 |
f"GPU: {result['avg_gpu_usage']:.1f}%"
|
| 160 |
)
|
| 161 |
|
| 162 |
+
# Generate CPU Usage Plot
|
| 163 |
+
plt.figure(figsize=(10, 5))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
plt.plot(
|
| 165 |
concurrency_levels,
|
| 166 |
[m["avg_cpu_usage"] for m in metrics],
|
| 167 |
"b-o",
|
| 168 |
label="CPU Usage",
|
| 169 |
)
|
| 170 |
+
plt.xlabel("Concurrency Level")
|
| 171 |
+
plt.ylabel("CPU Usage (%)")
|
| 172 |
+
plt.title("CPU Usage vs. Concurrency Level")
|
| 173 |
+
plt.grid(True)
|
| 174 |
+
plt.savefig("artifacts/cpu_usage.png")
|
| 175 |
+
logger.info("CPU usage plot saved as 'cpu_usage.png'.")
|
| 176 |
+
|
| 177 |
+
# Generate GPU Usage Plot
|
| 178 |
if GPU_AVAILABLE:
|
| 179 |
+
plt.figure(figsize=(10, 5))
|
| 180 |
plt.plot(
|
| 181 |
concurrency_levels,
|
| 182 |
[m["avg_gpu_usage"] for m in metrics],
|
| 183 |
"g-o",
|
| 184 |
label="GPU Usage",
|
| 185 |
)
|
| 186 |
+
plt.xlabel("Concurrency Level")
|
| 187 |
+
plt.ylabel("GPU Usage (%)")
|
| 188 |
+
plt.title("GPU Usage vs. Concurrency Level")
|
| 189 |
+
plt.grid(True)
|
| 190 |
+
plt.savefig("artifacts/gpu_usage.png")
|
| 191 |
+
logger.info("GPU usage plot saved as 'gpu_usage.png'.")
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
|
| 194 |
if __name__ == "__main__":
|