Merge pull request #64 from mjun0812/feat/download-graph

feat: Add graph of download history
This commit is contained in:
Junya Morioka
2025-12-04 23:11:49 +09:00
committed by GitHub
5 changed files with 290 additions and 0 deletions
@@ -0,0 +1,39 @@
name: Update Download Statistics
on:
schedule:
# Run daily at 00:00 UTC
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
update-stats:
name: Update download statistics and graph
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Install dependencies
run: |
pip install requests matplotlib
- name: Update download statistics
run: |
python update_download_stats.py
- name: Commit and push changes
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add docs/data/download_history.json docs/data/download_graph.png
git diff --staged --quiet || git commit -m "chore: update download statistics
Update download statistics and graph for $(date -u +%Y-%m-%d)"
git push
+28
View File
@@ -136,6 +136,34 @@ If you use this repository in your research and find it helpful, please cite the
}
```
## Star History and Download Statistics
<div style="display: flex; flex-direction: row; gap: 24px; width: 100%;">
<a href="https://www.star-history.com/#mjun0812/flash-attention-prebuild-wheels&type=date&legend=top-left" style="display: inline-block;">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=mjun0812/flash-attention-prebuild-wheels&type=date&theme=dark&legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=mjun0812/flash-attention-prebuild-wheels&type=date&legend=top-left" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=mjun0812/flash-attention-prebuild-wheels&type=date&legend=top-left" height="300"/>
</picture>
</a>
<img alt="Download Statistics" src="./docs/data/download_graph.png" height="300" style="display: inline-block;"/>
</div>
## Original Repository
[repo](https://github.com/Dao-AILab/flash-attention)
```bibtex
@inproceedings{dao2022flashattention,
title={Flash{A}ttention: Fast and Memory-Efficient Exact Attention with {IO}-Awareness},
author={Dao, Tri and Fu, Daniel Y. and Ermon, Stefano and Rudra, Atri and R{\'e}, Christopher},
booktitle={Advances in Neural Information Processing Systems (NeurIPS)},
year={2022}
}
@inproceedings{dao2023flashattention2,
title={Flash{A}ttention-2: Faster Attention with Better Parallelism and Work Partitioning},
author={Dao, Tri},
booktitle={International Conference on Learning Representations (ICLR)},
year={2024}
}
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

+30
View File
@@ -0,0 +1,30 @@
[
{
"timestamp": "2024-10-27T00:00:00+00:00",
"total_downloads": 0
},
{
"timestamp": "2025-12-04T13:25:33.785415+00:00",
"total_downloads": 906514
},
{
"timestamp": "2025-12-04T13:26:09.117076+00:00",
"total_downloads": 906524
},
{
"timestamp": "2025-12-04T13:46:48.639327+00:00",
"total_downloads": 906741
},
{
"timestamp": "2025-12-04T13:53:02.674280+00:00",
"total_downloads": 906828
},
{
"timestamp": "2025-12-04T13:53:35.050423+00:00",
"total_downloads": 906834
},
{
"timestamp": "2025-12-04T13:56:13.655744+00:00",
"total_downloads": 906837
}
]
+193
View File
@@ -0,0 +1,193 @@
#!/usr/bin/env python3
"""
Fetch GitHub release download statistics and generate a graph.
This script fetches download counts from GitHub API, stores historical data,
and generates a graph showing download trends over time.
"""
import json
from datetime import datetime, timezone
from pathlib import Path
import matplotlib.pyplot as plt
import requests
def fetch_download_stats(owner: str, repo: str) -> dict:
"""
Fetch download statistics from GitHub API.
Args:
owner: Repository owner
repo: Repository name
Returns:
dict: Dictionary containing total downloads and timestamp
"""
url = f"https://api.github.com/repos/{owner}/{repo}/releases"
headers = {}
# Fetch all releases with pagination
all_releases = []
page = 1
per_page = 100 # Maximum per page allowed by GitHub API
while True:
params = {"page": page, "per_page": per_page}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
releases = response.json()
if not releases:
break
all_releases.extend(releases)
page += 1
# Check if there are more pages
if len(releases) < per_page:
break
print(f"Fetched {len(all_releases)} releases")
total_downloads = 0
release_data = []
for release in all_releases:
release_downloads = 0
for asset in release.get("assets", []):
release_downloads += asset.get("download_count", 0)
total_downloads += release_downloads
release_data.append(
{
"tag": release["tag_name"],
"name": release["name"],
"downloads": release_downloads,
"created_at": release["created_at"],
}
)
return {
"total_downloads": total_downloads,
"releases": release_data,
}
def load_history(filepath: Path) -> list:
"""
Load historical download statistics from JSON file.
Args:
filepath: Path to the history JSON file
Returns:
list: List of historical data points
"""
if not filepath.exists():
return []
with open(filepath, "r") as f:
return json.load(f)
def save_history(filepath: Path, history: list) -> None:
"""
Save historical download statistics to JSON file.
Args:
filepath: Path to the history JSON file
history: List of historical data points
"""
filepath.parent.mkdir(parents=True, exist_ok=True)
with open(filepath, "w") as f:
json.dump(history, f, indent=2)
def generate_graph(history: list, output_path: Path, label: str = "") -> None:
"""
Generate a download statistics graph in Star History (XKCD) style.
"""
if len(history) < 2:
print("Not enough data to generate a graph (need at least 2 data points)")
return
dates = [datetime.fromisoformat(entry["timestamp"]) for entry in history]
downloads = [entry["total_downloads"] for entry in history]
# --- XKCD Style Context ---
# これにより手書き風のエフェクト(歪んだ線、手書きフォント)が適用されます
with plt.xkcd():
fig, ax = plt.subplots(figsize=(8, 6))
# Star History風の色(オレンジ/赤系)
line_color = "#f05133"
# プロット
ax.plot(
dates,
downloads,
color=line_color,
linewidth=3,
label=label if label else "Downloads",
)
if label:
legend = ax.legend(loc="upper left", frameon=True, fontsize=10)
legend.get_frame().set_edgecolor("black")
legend.get_frame().set_linewidth(1.5)
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
ax.spines["bottom"].set_linewidth(1.5)
ax.spines["left"].set_linewidth(1.5)
plt.title("Download History", fontsize=16, y=1.05)
plt.xlabel("Date", fontsize=12)
plt.ylabel("Total Downloads", fontsize=12)
ax.set_ylim(bottom=0)
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{int(x):,}"))
fig.autofmt_xdate(rotation=0, ha="center")
plt.tight_layout()
output_path.parent.mkdir(parents=True, exist_ok=True)
plt.savefig(output_path, dpi=150, bbox_inches="tight", facecolor="white")
print(f"Graph saved to {output_path}")
def main():
"""Main function to update download statistics and generate graph."""
owner = "mjun0812"
repo = "flash-attention-prebuild-wheels"
history_file = Path("docs/data/download_history.json")
graph_output = Path("docs/data/download_graph.png")
# Fetch current stats
print("Fetching download statistics from GitHub API...")
current_stats = fetch_download_stats(owner, repo)
print(f"Total downloads: {current_stats['total_downloads']}")
# Load and update history
history = load_history(history_file)
history.append(
{
"timestamp": datetime.now(timezone.utc).isoformat(),
"total_downloads": current_stats["total_downloads"],
}
)
# Save updated history
save_history(history_file, history)
print(f"History saved to {history_file}")
generate_graph(history, graph_output, f"{owner}/{repo}")
if __name__ == "__main__":
main()