Skip to content

Commit

Permalink
Code Quality (#10)
Browse files Browse the repository at this point in the history
* `setup.py` is replaced with the `pyproject.toml`. More here: https://peps.python.org/pep-0621/
    * Code Quality tool configurations are improved
    * Dependencies are grouped to be reused by other tools
* All issues are resolved according to code quality requirements
* The `tox` tool is added to the dependencies list to automate the code quality-checking process
    * Python versions that are tested: 3.8, 3.9, 3.10, 3.11, 3.12
    * The `tox.ini` configuration file is created
* Github Actions CI workflow is added
    * Integration tests are not added to the automation process. sLLM service in GithubActions TBD...
* `flake8` linter is removed since the `ruff` is used
* `README.md` now includes the *Code Quality* section with all the instructions and examples

---------

Co-authored-by: Dmytro Parfeniuk <[email protected]>
Co-authored-by: dalthecow <[email protected]>
  • Loading branch information
3 people authored Jul 15, 2024
1 parent ae61346 commit f905346
Show file tree
Hide file tree
Showing 20 changed files with 329 additions and 137 deletions.
24 changes: 23 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
TODO
name: Code Quality Check

on:
pull_request:
branches:
- main

jobs:
code_quality:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Run tox
run: tox

1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
TODO
30 changes: 21 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,48 +1,59 @@
.PHONY: install
install:
python -m pip install -r requirements.txt
python -m pip install .


.PHONY: install.dev
install.dev:
python -m pip install -e .[dev]


.PHONY: build
build:
python setup.py sdist bdist_wheel

.PHONY: style
style:
python -m ruff format src tests
python -m isort src tests
python -m flake8 src tests --max-line-length 88


.PHONY: types
types:
python -m mypy --check-untyped-defs


.PHONY: quality
quality:
python -m ruff check src tests
python -m black --check src tests
python -m isort --check src tests
python -m flake8 src tests --max-line-length 88
python -m mypy src
python -m mypy --check-untyped-defs


.PHONY: style
style:
python -m ruff format src tests
python -m isort src tests
python -m flake8 src tests --max-line-length 88


.PHONY: test
test:
python -m pytest -s -vvv --cache-clear tests


.PHONY: test.unit
test.unit:
python -m pytest tests/unit


.PHONY: test.integration
test.integration:
python -m pytest tests/integration


.PHONY: test.e2e
test.e2e:
python -m pytest tests/e2e



.PHONY: clean
clean:
rm -rf build
Expand All @@ -52,3 +63,4 @@ clean:
find . -type d -name "__pycache__" -exec rm -r {} +
rm -rf .mypy_cache
rm -rf .pytest_cache
rm -rf .tox
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,53 @@ set -o allexport; source .env; set +o allexport
| --------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OPENAI_BASE_URL | http://127.0.0.1:8080 | The host where the `openai` library will make requests to. For running integration tests it is required to have the external OpenAI compatible server running. |
| OPENAI_API_KEY | invalid | [OpenAI Platform](https://platform.openai.com/api-keys) to create a new API key. This value is not used for tests. |

</br>

# Code Quality

The variety of tools are available for checking the code quality.

All the code quality tools configuration is placed into next files: `pyproject.toml`, `Makefile`, `tox.ini`

**To provide the code quality next tools are used:**

- `pytest` as a testing framework
- `ruff` as a linter
- `black` & `isort` as formatters
- `mypy` as a static type checker
- `tox` as a automation tool
- `make` as a automation tool (works only on Unix by default)

**Checking code quality using CLI**

All the tools could be run right from the CLI.

Recommended command template: `python -m pytest test.integration`


**Checking code quality using Makefile**

Using `Makefile` you can run almost all common scripts to check the code quality, install dependencies, and to provide auto fixes. All the commands from the `Makefile` are valid to be used in the CLI.

Here are some commands

```sh
# install dev dependencies
make install.dev

# run unit tests
make test.unit

# run quality checkers
make quality

# run autofixes
make style
```

**Checking code quality using tox**

The `tox` is an automation tool for running code quality checkers for selected Python versions. The configuration is placed in the `tox.ini`.

To run the automation just run: `python -m tox`
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
TODO
TODO
79 changes: 76 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,96 @@
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"


[tool.setuptools.packages.find]
where = ["src"]
include = ["*"]

[tool.setuptools.package-data]
guidellm = ["*"]


# ************************************************
# ********** Project Metadata **********
# ************************************************

[project]
name = "guidellm"
version = "0.1.0"
description = "Guidance platform for deploying and managing large language models."
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.8.0,<4.0"
license = { file = "LICENSE" }
authors = [ { name = "Neuralmagic, Inc." } ]
urls = { homepage = "https://github.com/neuralmagic/guidellm" }
dependencies = [
"click",
"datasets",
"loguru",
"numpy",
"openai",
"requests",
"transformers",
]

[project.optional-dependencies]
dev = [
"guidellm[code_quality]",
"pre-commit",
"sphinx",
]
code_quality = [
"black",
"isort",
"mypy",
"pytest",
"pytest-mock",
"ruff",
"tox",
"types-requests"
]


[project.entry-points.console_scripts]
guidellm = "guidellm.main:main"


# ************************************************
# ********** Code Quality Tools **********
# ************************************************

[tool.black]
line-length = 88
target-version = ['py38']


[tool.isort]
profile = "black"


[tool.mypy]
files = "src/guidellm"
python_version = '3.8'
warn_redundant_casts = true
warn_unused_ignores = true
show_error_codes = true
namespace_packages = true
exclude = ["venv", ".tox"]

# Silint "type import errors" as our 3rd-party libs does not have types
# Check: https://mypy.readthedocs.io/en/latest/config_file.html#import-discovery
follow_imports = 'silent'

[[tool.mypy.overrides]]
module = ["transformers.*", "datasets.*"]
ignore_missing_imports=true


[tool.ruff]
line-length = 88
exclude = ["build", "dist", "env", ".venv"]
lint.select = ["E", "F", "W"]

[tool.flake8]
max-line-length = 88

[tool.pytest.ini_options]
addopts = '-s -vvv --cache-clear'
Expand All @@ -27,4 +101,3 @@ markers = [
"sanity: detailed tests to ensure major functions work correctly",
"regression: tests to ensure that new changes do not break existing functionality"
]

64 changes: 0 additions & 64 deletions setup.py

This file was deleted.

10 changes: 5 additions & 5 deletions src/guidellm/backend/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum
from typing import Iterator, List, Optional, Type, Union
from typing import Dict, Iterator, List, Optional, Type

from loguru import logger

Expand Down Expand Up @@ -41,7 +41,7 @@ class Backend(ABC):
An abstract base class with template methods for generative AI backends.
"""

_registry = {}
_registry: Dict[BackendEngine, "Type[Backend]"] = {}

@classmethod
def register(cls, backend_type: BackendEngine):
Expand All @@ -59,7 +59,7 @@ def inner_wrapper(wrapped_class: Type["Backend"]):
return inner_wrapper

@classmethod
def create(cls, backend_type: Union[str, BackendEngine], **kwargs) -> "Backend":
def create(cls, backend_type: BackendEngine, **kwargs) -> "Backend":
"""
Factory method to create a backend based on the backend type.
Expand All @@ -77,7 +77,7 @@ def create(cls, backend_type: Union[str, BackendEngine], **kwargs) -> "Backend":
logger.error(f"Unsupported backend type: {backend_type}")
raise ValueError(f"Unsupported backend type: {backend_type}")

return cls._registry[backend_type](**kwargs)
return Backend._registry[backend_type](**kwargs)

def submit(self, request: TextGenerationRequest) -> TextGenerationResult:
"""
Expand All @@ -91,7 +91,7 @@ def submit(self, request: TextGenerationRequest) -> TextGenerationResult:

logger.info(f"Submitting request with prompt: {request.prompt}")

result = TextGenerationResult(request=request)
result = TextGenerationResult(TextGenerationRequest(prompt=request.prompt))
result.start(request.prompt)

for response in self.make_request(request): # GenerativeResponse
Expand Down
2 changes: 1 addition & 1 deletion src/guidellm/backend/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def available_models(self) -> List[str]:
:rtype: List[str]
"""

models: list[str] = [
models: List[str] = [
model.id for model in self.openai_client.models.list().data
]
logger.info(f"Available models: {models}")
Expand Down
Loading

0 comments on commit f905346

Please sign in to comment.