Skip to content

Commit a1f470e

Browse files
committed
Initial commit: GRPO algorithm implementation
1 parent 4b39c9c commit a1f470e

File tree

10 files changed

+551
-4
lines changed

10 files changed

+551
-4
lines changed

.github/workflows/publish.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Publish Python distribution to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
jobs:
9+
build:
10+
name: Build distribution 📦
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- name: Set up Python
15+
uses: actions/setup-python@v5
16+
with:
17+
python-version: "3.x"
18+
- name: Install build tools
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install build
22+
- name: Build package
23+
run: python -m build
24+
- name: Store distribution packages
25+
uses: actions/upload-artifact@v4
26+
with:
27+
name: python-package-distributions
28+
path: dist/
29+
30+
publish-to-pypi:
31+
name: Publish to PyPI
32+
needs:
33+
- build
34+
runs-on: ubuntu-latest
35+
environment:
36+
name: pypi
37+
url: https://pypi.org/p/optimrl
38+
permissions:
39+
id-token: write
40+
41+
steps:
42+
- name: Download built packages
43+
uses: actions/download-artifact@v4
44+
with:
45+
name: python-package-distributions
46+
path: dist/
47+
- name: Publish to PyPI
48+
uses: pypa/gh-action-pypi-publish@release/v1
49+
50+
github-release:
51+
name: Create GitHub Release
52+
needs:
53+
- publish-to-pypi
54+
runs-on: ubuntu-latest
55+
permissions:
56+
contents: write
57+
id-token: write
58+
59+
steps:
60+
- name: Download packages
61+
uses: actions/download-artifact@v4
62+
with:
63+
name: python-package-distributions
64+
path: dist/
65+
- name: Sign with Sigstore
66+
uses: sigstore/[email protected]
67+
with:
68+
inputs: >-
69+
./dist/*.tar.gz
70+
./dist/*.whl
71+
- name: Create Release
72+
env:
73+
GITHUB_TOKEN: ${{ github.token }}
74+
run: >-
75+
gh release create
76+
"$GITHUB_REF_NAME"
77+
--repo "$GITHUB_REPOSITORY"
78+
--notes ""
79+
- name: Upload assets
80+
env:
81+
GITHUB_TOKEN: ${{ github.token }}
82+
run: >-
83+
gh release upload
84+
"$GITHUB_REF_NAME" dist/**
85+
--repo "$GITHUB_REPOSITORY"

.github/workflows/tests.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
matrix:
14+
os: [ubuntu-latest, macos-latest, windows-latest]
15+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Python ${{ matrix.python-version }}
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
25+
- name: Install dependencies
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install -e '.[test]'
29+
30+
- name: Run tests
31+
run: |
32+
pytest tests/ -v
33+
34+
lint:
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
39+
- name: Set up Python
40+
uses: actions/setup-python@v5
41+
with:
42+
python-version: '3.12'
43+
44+
- name: Install dependencies
45+
run: |
46+
python -m pip install --upgrade pip
47+
pip install black isort flake8
48+
49+
- name: Check code formatting
50+
run: |
51+
black --check optimrl tests
52+
isort --check-only optimrl tests
53+
flake8 optimrl tests

.gitignore

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ env/
44
.env/
55
.venv/
66
ENV/
7+
optimrl/
8+
**/lib/
9+
**/bin/
10+
**/include/
11+
**/share/
12+
pyvenv.cfg
713

814
# PyTorch model files
915
*.pt
1016
*.pth
1117
*.ckpt
1218

13-
# Python cache
19+
# Python cache
1420
__pycache__/
1521
*.py[cod]
1622
*$py.class
@@ -19,16 +25,16 @@ __pycache__/
1925
dist/
2026
build/
2127
*.egg-info/
28+
*.pyc
29+
*.pyo
30+
*.so
2231

2332
# IDE settings
2433
.vscode/
2534
.idea/
2635
*.swp
2736
*.swo
2837

29-
# Jupyter Notebook
30-
.ipynb_checkpoints
31-
3238
# Local development settings
3339
.env
3440
.env.local

OptimRL.code-workspace

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"folders": [
3+
{
4+
"path": "."
5+
}
6+
],
7+
"settings": {}
8+
}

pyproject.toml

Whitespace-only changes.

setup.cfg

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[versioneer]
2+
VCS = git
3+
style = pep440
4+
versionfile_source = optimrl/_version.py
5+
versionfile_build = optimrl/_version.py
6+
tag_prefix = v
7+
parentdir_prefix = optimrl-

setup.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from setuptools import setup, find_packages, Extension
2+
from setuptools.command.build_ext import build_ext
3+
import os
4+
import platform
5+
import shutil
6+
import versioneer
7+
8+
class CustomBuildExt(build_ext):
9+
"""Custom build command to handle library file copying and platform-specific compilation."""
10+
11+
def build_extensions(self):
12+
# Set platform-specific compiler flags
13+
compiler_type = self.compiler.compiler_type
14+
15+
for ext in self.extensions:
16+
if compiler_type == 'unix':
17+
# macOS and Linux specific flags
18+
if platform.system() == 'Darwin':
19+
# macOS specific flags
20+
ext.extra_compile_args += ['-O3', '-fPIC']
21+
# Support both Intel and Apple Silicon
22+
ext.extra_compile_args += ['-arch', 'x86_64', '-arch', 'arm64']
23+
ext.extra_link_args += ['-arch', 'x86_64', '-arch', 'arm64']
24+
else:
25+
# Linux specific flags
26+
ext.extra_compile_args += ['-O3', '-fPIC']
27+
elif compiler_type == 'msvc':
28+
# Windows specific flags
29+
ext.extra_compile_args += ['/O2']
30+
31+
# Build the extensions
32+
super().build_extensions()
33+
34+
# After building, copy the library to the package directory
35+
self.copy_extensions_to_package()
36+
37+
def copy_extensions_to_package(self):
38+
"""Copy the built extension to the package directory."""
39+
for ext in self.extensions:
40+
# Get the full path of the built library
41+
built_lib = self.get_ext_fullpath(ext.name)
42+
43+
# Determine the destination directory within the package
44+
dest_dir = os.path.join('optimrl', 'c_src')
45+
os.makedirs(dest_dir, exist_ok=True)
46+
47+
# Get the filename only
48+
filename = os.path.basename(built_lib)
49+
50+
# Create platform-specific library name
51+
if platform.system() == 'Darwin':
52+
lib_name = 'libgrpo.dylib'
53+
elif platform.system() == 'Linux':
54+
lib_name = 'libgrpo.so'
55+
else:
56+
lib_name = 'libgrpo.dll'
57+
58+
# Copy the file to the package directory with the correct name
59+
dest_path = os.path.join(dest_dir, lib_name)
60+
shutil.copy2(built_lib, dest_path)
61+
print(f"Copied {built_lib} to {dest_path}")
62+
63+
# Define the extension module
64+
grpo_module = Extension(
65+
'optimrl.c_src.libgrpo',
66+
sources=['optimrl/c_src/grpo.c'],
67+
include_dirs=['optimrl/c_src'],
68+
libraries=['m'] if platform.system() != 'Windows' else [],
69+
extra_compile_args=['-O3', '-fPIC'] if platform.system() != 'Windows' else ['/O2']
70+
)
71+
72+
# Read the README file
73+
with open('README.md', 'r', encoding='utf-8') as f:
74+
long_description = f.read()
75+
76+
setup(
77+
name="optimrl",
78+
version=versioneer.get_version(),
79+
cmdclass=versioneer.get_cmdclass(),
80+
author="Subashanan Nair",
81+
author_email="[email protected]",
82+
description="Group Relative Policy Optimization for Efficient RL Training",
83+
long_description=long_description,
84+
long_description_content_type="text/markdown",
85+
url="https://github.com/SubaashNair/OptimRL",
86+
packages=find_packages(),
87+
ext_modules=[grpo_module],
88+
install_requires=[
89+
"numpy>=1.20.0",
90+
"torch>=1.8.0"
91+
],
92+
extras_require={
93+
'test': ['pytest>=6.0'],
94+
'dev': ['pytest>=6.0', 'black', 'isort', 'flake8']
95+
},
96+
python_requires=">=3.8",
97+
cmdclass={'build_ext': CustomBuildExt},
98+
include_package_data=True,
99+
package_data={
100+
'optimrl': ['c_src/*.dylib', 'c_src/*.so', 'c_src/*.dll']
101+
},
102+
)

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)