opencode-skills-antigravity 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +10 -1
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.csv +34 -0
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.md +2 -0
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/sources/sources.md +2 -2
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/hugging-face-cli/SKILL.md +192 -195
- package/bundled-skills/hugging-face-community-evals/SKILL.md +213 -0
- package/bundled-skills/hugging-face-community-evals/examples/.env.example +3 -0
- package/bundled-skills/hugging-face-community-evals/examples/USAGE_EXAMPLES.md +101 -0
- package/bundled-skills/hugging-face-community-evals/scripts/inspect_eval_uv.py +104 -0
- package/bundled-skills/hugging-face-community-evals/scripts/inspect_vllm_uv.py +306 -0
- package/bundled-skills/hugging-face-community-evals/scripts/lighteval_vllm_uv.py +297 -0
- package/bundled-skills/hugging-face-dataset-viewer/SKILL.md +120 -120
- package/bundled-skills/hugging-face-gradio/SKILL.md +304 -0
- package/bundled-skills/hugging-face-gradio/examples.md +613 -0
- package/bundled-skills/hugging-face-jobs/SKILL.md +25 -18
- package/bundled-skills/hugging-face-jobs/index.html +216 -0
- package/bundled-skills/hugging-face-jobs/references/hardware_guide.md +336 -0
- package/bundled-skills/hugging-face-jobs/references/hub_saving.md +352 -0
- package/bundled-skills/hugging-face-jobs/references/token_usage.md +570 -0
- package/bundled-skills/hugging-face-jobs/references/troubleshooting.md +475 -0
- package/bundled-skills/hugging-face-jobs/scripts/cot-self-instruct.py +718 -0
- package/bundled-skills/hugging-face-jobs/scripts/finepdfs-stats.py +546 -0
- package/bundled-skills/hugging-face-jobs/scripts/generate-responses.py +587 -0
- package/bundled-skills/hugging-face-model-trainer/SKILL.md +11 -12
- package/bundled-skills/hugging-face-model-trainer/references/gguf_conversion.md +296 -0
- package/bundled-skills/hugging-face-model-trainer/references/hardware_guide.md +283 -0
- package/bundled-skills/hugging-face-model-trainer/references/hub_saving.md +364 -0
- package/bundled-skills/hugging-face-model-trainer/references/local_training_macos.md +231 -0
- package/bundled-skills/hugging-face-model-trainer/references/reliability_principles.md +371 -0
- package/bundled-skills/hugging-face-model-trainer/references/trackio_guide.md +189 -0
- package/bundled-skills/hugging-face-model-trainer/references/training_methods.md +150 -0
- package/bundled-skills/hugging-face-model-trainer/references/training_patterns.md +203 -0
- package/bundled-skills/hugging-face-model-trainer/references/troubleshooting.md +282 -0
- package/bundled-skills/hugging-face-model-trainer/references/unsloth.md +313 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/convert_to_gguf.py +424 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/dataset_inspector.py +417 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/estimate_cost.py +150 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_dpo_example.py +106 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_grpo_example.py +89 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_sft_example.py +122 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/unsloth_sft_example.py +512 -0
- package/bundled-skills/hugging-face-paper-publisher/SKILL.md +11 -4
- package/bundled-skills/hugging-face-paper-publisher/examples/example_usage.md +326 -0
- package/bundled-skills/hugging-face-paper-publisher/references/quick_reference.md +216 -0
- package/bundled-skills/hugging-face-paper-publisher/scripts/paper_manager.py +606 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/arxiv.md +299 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/ml-report.md +358 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/modern.md +319 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/standard.md +201 -0
- package/bundled-skills/hugging-face-papers/SKILL.md +241 -0
- package/bundled-skills/hugging-face-trackio/.claude-plugin/plugin.json +19 -0
- package/bundled-skills/hugging-face-trackio/SKILL.md +117 -0
- package/bundled-skills/hugging-face-trackio/references/alerts.md +196 -0
- package/bundled-skills/hugging-face-trackio/references/logging_metrics.md +206 -0
- package/bundled-skills/hugging-face-trackio/references/retrieving_metrics.md +251 -0
- package/bundled-skills/hugging-face-vision-trainer/SKILL.md +595 -0
- package/bundled-skills/hugging-face-vision-trainer/references/finetune_sam2_trainer.md +254 -0
- package/bundled-skills/hugging-face-vision-trainer/references/hub_saving.md +618 -0
- package/bundled-skills/hugging-face-vision-trainer/references/image_classification_training_notebook.md +279 -0
- package/bundled-skills/hugging-face-vision-trainer/references/object_detection_training_notebook.md +700 -0
- package/bundled-skills/hugging-face-vision-trainer/references/reliability_principles.md +310 -0
- package/bundled-skills/hugging-face-vision-trainer/references/timm_trainer.md +91 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/dataset_inspector.py +814 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/estimate_cost.py +217 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/image_classification_training.py +383 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/object_detection_training.py +710 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/sam_segmentation_training.py +382 -0
- package/bundled-skills/jq/SKILL.md +273 -0
- package/bundled-skills/odoo-edi-connector/SKILL.md +32 -10
- package/bundled-skills/odoo-woocommerce-bridge/SKILL.md +9 -5
- package/bundled-skills/tmux/SKILL.md +370 -0
- package/bundled-skills/transformers-js/SKILL.md +639 -0
- package/bundled-skills/transformers-js/references/CACHE.md +339 -0
- package/bundled-skills/transformers-js/references/CONFIGURATION.md +390 -0
- package/bundled-skills/transformers-js/references/EXAMPLES.md +605 -0
- package/bundled-skills/transformers-js/references/MODEL_ARCHITECTURES.md +167 -0
- package/bundled-skills/transformers-js/references/PIPELINE_OPTIONS.md +545 -0
- package/bundled-skills/transformers-js/references/TEXT_GENERATION.md +315 -0
- package/bundled-skills/viboscope/SKILL.md +64 -0
- package/package.json +1 -1
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.12"
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "polars>=1.31.0",
|
|
5
|
+
# "huggingface-hub",
|
|
6
|
+
# "datasets",
|
|
7
|
+
# "ascii-graph",
|
|
8
|
+
# ]
|
|
9
|
+
# ///
|
|
10
|
+
"""
|
|
11
|
+
Analyze educational quality trends across CommonCrawl dumps using Polars streaming.
|
|
12
|
+
|
|
13
|
+
Answers: "Is the web getting more educational over time?"
|
|
14
|
+
|
|
15
|
+
Demonstrates Polars HF Hub integration - process 50M+ docs without downloading 300GB+.
|
|
16
|
+
|
|
17
|
+
Example usage:
|
|
18
|
+
# Analyze English PDFs (default)
|
|
19
|
+
uv run finepdfs-stats.py
|
|
20
|
+
|
|
21
|
+
# Analyze all 70+ languages
|
|
22
|
+
uv run finepdfs-stats.py --all-languages
|
|
23
|
+
|
|
24
|
+
# Quick test
|
|
25
|
+
uv run finepdfs-stats.py --limit 10000 --show-plan
|
|
26
|
+
|
|
27
|
+
# Save results to HF Hub
|
|
28
|
+
uv run finepdfs-stats.py --output-repo username/finepdfs-temporal-stats
|
|
29
|
+
|
|
30
|
+
# Run on HF Jobs
|
|
31
|
+
hf jobs uv run \\
|
|
32
|
+
-s HF_TOKEN \\
|
|
33
|
+
-e HF_XET_HIGH_PERFORMANCE=1 \\
|
|
34
|
+
https://huggingface.co/datasets/uv-scripts/dataset-stats/raw/main/finepdfs-stats.py \\
|
|
35
|
+
-- --output-repo username/stats
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
import argparse
|
|
39
|
+
import logging
|
|
40
|
+
import os
|
|
41
|
+
import sys
|
|
42
|
+
import time
|
|
43
|
+
from pathlib import Path
|
|
44
|
+
|
|
45
|
+
import polars as pl
|
|
46
|
+
from ascii_graph import Pyasciigraph
|
|
47
|
+
from datasets import Dataset
|
|
48
|
+
from huggingface_hub import HfApi, create_repo, list_repo_tree, login
|
|
49
|
+
|
|
50
|
+
logging.basicConfig(
|
|
51
|
+
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
|
52
|
+
)
|
|
53
|
+
logger = logging.getLogger(__name__)
|
|
54
|
+
|
|
55
|
+
# Common language+script codes for finepdfs-edu
|
|
56
|
+
COMMON_LANGUAGES = {
|
|
57
|
+
"eng_Latn": "English (Latin script)",
|
|
58
|
+
"fra_Latn": "French (Latin script)",
|
|
59
|
+
"deu_Latn": "German (Latin script)",
|
|
60
|
+
"spa_Latn": "Spanish (Latin script)",
|
|
61
|
+
"por_Latn": "Portuguese (Latin script)",
|
|
62
|
+
"ita_Latn": "Italian (Latin script)",
|
|
63
|
+
"nld_Latn": "Dutch (Latin script)",
|
|
64
|
+
"pol_Latn": "Polish (Latin script)",
|
|
65
|
+
"rus_Cyrl": "Russian (Cyrillic script)",
|
|
66
|
+
"zho_Hans": "Chinese (Simplified)",
|
|
67
|
+
"zho_Hant": "Chinese (Traditional)",
|
|
68
|
+
"jpn_Jpan": "Japanese",
|
|
69
|
+
"kor_Hang": "Korean",
|
|
70
|
+
"ara_Arab": "Arabic",
|
|
71
|
+
"hin_Deva": "Hindi (Devanagari)",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def list_available_languages(dataset_id: str) -> list[str]:
|
|
76
|
+
"""List available language subsets in the dataset."""
|
|
77
|
+
try:
|
|
78
|
+
tree = list_repo_tree(dataset_id, path_in_repo="data", repo_type="dataset")
|
|
79
|
+
languages = [
|
|
80
|
+
item.path.replace("data/", "")
|
|
81
|
+
for item in tree
|
|
82
|
+
if item.path.startswith("data/")
|
|
83
|
+
and "/" not in item.path.replace("data/", "")
|
|
84
|
+
]
|
|
85
|
+
return sorted(languages)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
logger.warning(f"Could not list languages: {e}")
|
|
88
|
+
return list(COMMON_LANGUAGES.keys())
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def compute_temporal_stats(df: pl.LazyFrame, output_path: Path) -> pl.DataFrame:
|
|
92
|
+
"""Single scan: compute stats grouped by dump for temporal analysis."""
|
|
93
|
+
query = df.group_by("dump").agg(
|
|
94
|
+
pl.len().alias("doc_count"),
|
|
95
|
+
pl.col("token_count").sum().alias("total_tokens"),
|
|
96
|
+
pl.col("fw_edu_scores").list.mean().mean().alias("avg_edu_score"),
|
|
97
|
+
(pl.col("fw_edu_scores").list.mean() >= 3).sum().alias("high_edu_count"),
|
|
98
|
+
)
|
|
99
|
+
query.sink_parquet(output_path, engine="streaming")
|
|
100
|
+
return pl.read_parquet(output_path)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def compute_global_stats(temporal: pl.DataFrame) -> pl.DataFrame:
|
|
104
|
+
"""Compute global stats from temporal breakdown."""
|
|
105
|
+
total = temporal["doc_count"].sum()
|
|
106
|
+
return pl.DataFrame(
|
|
107
|
+
{
|
|
108
|
+
"total_docs": [total],
|
|
109
|
+
"total_tokens": [temporal["total_tokens"].sum()],
|
|
110
|
+
"avg_edu_score": [
|
|
111
|
+
(temporal["avg_edu_score"] * temporal["doc_count"]).sum() / total
|
|
112
|
+
],
|
|
113
|
+
"high_edu_rate": [temporal["high_edu_count"].sum() / total],
|
|
114
|
+
"num_dumps": [len(temporal)],
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def format_temporal_stats(temporal: pl.DataFrame) -> pl.DataFrame:
|
|
120
|
+
"""Format temporal stats with high_edu_rate, sorted chronologically."""
|
|
121
|
+
return (
|
|
122
|
+
temporal.with_columns(
|
|
123
|
+
(pl.col("high_edu_count") / pl.col("doc_count")).alias("high_edu_rate")
|
|
124
|
+
)
|
|
125
|
+
.select(["dump", "doc_count", "avg_edu_score", "high_edu_rate"])
|
|
126
|
+
.sort(
|
|
127
|
+
"dump"
|
|
128
|
+
) # Chronological order (CC-MAIN-2017-xx comes before CC-MAIN-2024-xx)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def create_ascii_charts(temporal_stats: pl.DataFrame) -> str:
|
|
133
|
+
"""Create ASCII bar charts showing temporal trends."""
|
|
134
|
+
# Extract year from dump name (CC-MAIN-2024-42 -> 2024)
|
|
135
|
+
# Group by year and average the values for cleaner display
|
|
136
|
+
yearly = (
|
|
137
|
+
temporal_stats.with_columns(
|
|
138
|
+
pl.col("dump").str.extract(r"CC-MAIN-(\d{4})", 1).alias("year")
|
|
139
|
+
)
|
|
140
|
+
.group_by("year")
|
|
141
|
+
.agg(
|
|
142
|
+
pl.col("doc_count").sum(),
|
|
143
|
+
pl.col("avg_edu_score").mean(),
|
|
144
|
+
pl.col("high_edu_rate").mean(),
|
|
145
|
+
)
|
|
146
|
+
.sort("year")
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
lines = []
|
|
150
|
+
|
|
151
|
+
# High edu rate chart (more dramatic differences)
|
|
152
|
+
data_rate = [
|
|
153
|
+
(row["year"], row["high_edu_rate"] * 100)
|
|
154
|
+
for row in yearly.iter_rows(named=True)
|
|
155
|
+
]
|
|
156
|
+
graph = Pyasciigraph(line_length=60, float_format="{0:.1f}%")
|
|
157
|
+
lines.extend(graph.graph("High Educational Content (edu >= 3)", data_rate))
|
|
158
|
+
|
|
159
|
+
lines.append("")
|
|
160
|
+
|
|
161
|
+
# Avg edu score chart
|
|
162
|
+
data_score = [
|
|
163
|
+
(row["year"], row["avg_edu_score"]) for row in yearly.iter_rows(named=True)
|
|
164
|
+
]
|
|
165
|
+
graph2 = Pyasciigraph(line_length=60, float_format="{0:.2f}")
|
|
166
|
+
lines.extend(graph2.graph("Average Educational Score", data_score))
|
|
167
|
+
|
|
168
|
+
return "\n".join(lines)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def create_readme(
|
|
172
|
+
args,
|
|
173
|
+
global_stats: pl.DataFrame,
|
|
174
|
+
temporal_stats: pl.DataFrame,
|
|
175
|
+
scan_time: float,
|
|
176
|
+
ascii_charts: str,
|
|
177
|
+
) -> str:
|
|
178
|
+
"""Create README content for the stats dataset."""
|
|
179
|
+
stats = global_stats.to_dicts()[0]
|
|
180
|
+
total_docs = stats.get("total_docs", 0)
|
|
181
|
+
docs_per_sec = total_docs / scan_time if scan_time > 0 else 0
|
|
182
|
+
|
|
183
|
+
# Get first and last year averages for trend (more representative than single dumps)
|
|
184
|
+
yearly = (
|
|
185
|
+
temporal_stats.with_columns(
|
|
186
|
+
pl.col("dump").str.extract(r"CC-MAIN-(\d{4})", 1).alias("year")
|
|
187
|
+
)
|
|
188
|
+
.group_by("year")
|
|
189
|
+
.agg(
|
|
190
|
+
pl.col("doc_count").sum(),
|
|
191
|
+
pl.col("avg_edu_score").mean(),
|
|
192
|
+
pl.col("high_edu_rate").mean(),
|
|
193
|
+
)
|
|
194
|
+
.sort("year")
|
|
195
|
+
)
|
|
196
|
+
first_year = yearly.head(1).to_dicts()[0]
|
|
197
|
+
last_year = yearly.tail(1).to_dicts()[0]
|
|
198
|
+
|
|
199
|
+
scope = (
|
|
200
|
+
"all languages"
|
|
201
|
+
if args.all_languages
|
|
202
|
+
else COMMON_LANGUAGES.get(args.lang, args.lang)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return f"""---
|
|
206
|
+
tags:
|
|
207
|
+
- uv-script
|
|
208
|
+
- statistics
|
|
209
|
+
- polars
|
|
210
|
+
- finepdfs-edu
|
|
211
|
+
- temporal-analysis
|
|
212
|
+
license: odc-by
|
|
213
|
+
configs:
|
|
214
|
+
- config_name: global_stats
|
|
215
|
+
data_files: global_stats/train-*.parquet
|
|
216
|
+
- config_name: temporal_stats
|
|
217
|
+
data_files: temporal_stats/train-*.parquet
|
|
218
|
+
default_viewer_config: temporal_stats
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
# Is the Web Getting More Educational?
|
|
222
|
+
|
|
223
|
+
Temporal analysis of educational quality in **{scope}** across {stats.get("num_dumps", 0)} CommonCrawl dumps.
|
|
224
|
+
|
|
225
|
+
## Trend
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
{ascii_charts}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Key Finding
|
|
232
|
+
|
|
233
|
+
| Year | Avg Edu Score | High Edu Rate |
|
|
234
|
+
|------|---------------|---------------|
|
|
235
|
+
| {first_year["year"]} | {first_year["avg_edu_score"]:.2f} | {first_year["high_edu_rate"] * 100:.1f}% |
|
|
236
|
+
| {last_year["year"]} | {last_year["avg_edu_score"]:.2f} | {last_year["high_edu_rate"] * 100:.1f}% |
|
|
237
|
+
|
|
238
|
+
## Performance
|
|
239
|
+
|
|
240
|
+
- **{total_docs:,} documents** processed in **{scan_time:.0f} seconds**
|
|
241
|
+
- **{docs_per_sec:,.0f} docs/sec** using Polars streaming
|
|
242
|
+
- Single scan, no full dataset download required
|
|
243
|
+
|
|
244
|
+
## Summary
|
|
245
|
+
|
|
246
|
+
| Metric | Value |
|
|
247
|
+
|--------|-------|
|
|
248
|
+
| Scope | {scope} |
|
|
249
|
+
| Total Documents | {total_docs:,} |
|
|
250
|
+
| Total Tokens | {stats.get("total_tokens", 0):,} |
|
|
251
|
+
| Avg Edu Score | {stats.get("avg_edu_score", 0):.3f} |
|
|
252
|
+
| High Edu Rate | {stats.get("high_edu_rate", 0) * 100:.1f}% |
|
|
253
|
+
| CommonCrawl Dumps | {stats.get("num_dumps", 0)} |
|
|
254
|
+
|
|
255
|
+
## Files
|
|
256
|
+
|
|
257
|
+
- `global_stats` - Overall summary
|
|
258
|
+
- `temporal_stats` - Per-dump breakdown (sorted chronologically)
|
|
259
|
+
|
|
260
|
+
## Reproduce
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
uv run https://huggingface.co/datasets/uv-scripts/dataset-stats/raw/main/finepdfs-stats.py \\
|
|
264
|
+
{"--all-languages" if args.all_languages else f"--lang {args.lang}"} --output-repo your-username/stats
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Source
|
|
268
|
+
|
|
269
|
+
- **Dataset**: [{args.source_dataset}](https://huggingface.co/datasets/{args.source_dataset})
|
|
270
|
+
- **Script**: [uv-scripts/dataset-stats](https://huggingface.co/datasets/uv-scripts/dataset-stats)
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def main():
|
|
275
|
+
parser = argparse.ArgumentParser(
|
|
276
|
+
description="Analyze educational quality trends across CommonCrawl dumps",
|
|
277
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
278
|
+
epilog=__doc__,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
parser.add_argument(
|
|
282
|
+
"--source-dataset",
|
|
283
|
+
type=str,
|
|
284
|
+
default="HuggingFaceFW/finepdfs-edu",
|
|
285
|
+
help="Source dataset (default: HuggingFaceFW/finepdfs-edu)",
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
parser.add_argument(
|
|
289
|
+
"--lang",
|
|
290
|
+
type=str,
|
|
291
|
+
default="eng_Latn",
|
|
292
|
+
help="Language+script code (default: eng_Latn)",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
parser.add_argument(
|
|
296
|
+
"--all-languages",
|
|
297
|
+
action="store_true",
|
|
298
|
+
help="Analyze all languages (70+) instead of single language",
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
parser.add_argument(
|
|
302
|
+
"--show-plan",
|
|
303
|
+
action="store_true",
|
|
304
|
+
help="Show Polars query plan (demonstrates optimization)",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
parser.add_argument(
|
|
308
|
+
"--list-languages",
|
|
309
|
+
action="store_true",
|
|
310
|
+
help="List available languages and exit",
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
parser.add_argument(
|
|
314
|
+
"--limit",
|
|
315
|
+
type=int,
|
|
316
|
+
help="Limit to first N rows (for testing)",
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
parser.add_argument(
|
|
320
|
+
"--output-repo",
|
|
321
|
+
type=str,
|
|
322
|
+
help="HuggingFace dataset repository to upload results",
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
parser.add_argument(
|
|
326
|
+
"--output-dir",
|
|
327
|
+
type=str,
|
|
328
|
+
default="./stats_output",
|
|
329
|
+
help="Local directory for output files",
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
parser.add_argument(
|
|
333
|
+
"--hf-token",
|
|
334
|
+
type=str,
|
|
335
|
+
help="HuggingFace API token (or set HF_TOKEN env var)",
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
parser.add_argument(
|
|
339
|
+
"--private",
|
|
340
|
+
action="store_true",
|
|
341
|
+
help="Make the output dataset private",
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
args = parser.parse_args()
|
|
345
|
+
|
|
346
|
+
# Check for high-performance mode
|
|
347
|
+
if os.environ.get("HF_XET_HIGH_PERFORMANCE"):
|
|
348
|
+
logger.info("High-performance mode enabled (HF_XET_HIGH_PERFORMANCE=1)")
|
|
349
|
+
|
|
350
|
+
# List languages mode
|
|
351
|
+
if args.list_languages:
|
|
352
|
+
print(f"Available language+script codes for {args.source_dataset}:\n")
|
|
353
|
+
print("Common languages:")
|
|
354
|
+
for code, name in COMMON_LANGUAGES.items():
|
|
355
|
+
print(f" {code:12} - {name}")
|
|
356
|
+
print("\nFetching full list from HF Hub...")
|
|
357
|
+
all_langs = list_available_languages(args.source_dataset)
|
|
358
|
+
print(f"\nAll available ({len(all_langs)} total):")
|
|
359
|
+
for lang in all_langs[:30]: # Show first 30
|
|
360
|
+
name = COMMON_LANGUAGES.get(lang, "")
|
|
361
|
+
print(f" {lang:12} {name}")
|
|
362
|
+
if len(all_langs) > 30:
|
|
363
|
+
print(f" ... and {len(all_langs) - 30} more")
|
|
364
|
+
sys.exit(0)
|
|
365
|
+
|
|
366
|
+
# Build the parquet path
|
|
367
|
+
if args.all_languages:
|
|
368
|
+
source_path = f"hf://datasets/{args.source_dataset}/data/*/train/*.parquet"
|
|
369
|
+
scope_desc = "all languages"
|
|
370
|
+
else:
|
|
371
|
+
source_path = (
|
|
372
|
+
f"hf://datasets/{args.source_dataset}/data/{args.lang}/train/*.parquet"
|
|
373
|
+
)
|
|
374
|
+
scope_desc = f"{args.lang} ({COMMON_LANGUAGES.get(args.lang, 'unknown')})"
|
|
375
|
+
|
|
376
|
+
logger.info(f"Scanning: {source_path}")
|
|
377
|
+
logger.info(f"Scope: {scope_desc}")
|
|
378
|
+
|
|
379
|
+
# Create lazy frame - this doesn't load any data yet!
|
|
380
|
+
logger.info("Creating lazy query plan...")
|
|
381
|
+
df = pl.scan_parquet(source_path)
|
|
382
|
+
|
|
383
|
+
# Apply limit if specified
|
|
384
|
+
if args.limit:
|
|
385
|
+
logger.info(f"Limiting to first {args.limit:,} rows")
|
|
386
|
+
df = df.head(args.limit)
|
|
387
|
+
|
|
388
|
+
# Show query plan if requested
|
|
389
|
+
if args.show_plan:
|
|
390
|
+
# Build a sample query to show the plan
|
|
391
|
+
sample_query = df.select(
|
|
392
|
+
pl.len(),
|
|
393
|
+
pl.col("token_count").sum(),
|
|
394
|
+
pl.col("language").n_unique(),
|
|
395
|
+
)
|
|
396
|
+
print("\nQuery Plan (showing Polars optimization):")
|
|
397
|
+
print("=" * 60)
|
|
398
|
+
print(sample_query.explain())
|
|
399
|
+
print("=" * 60)
|
|
400
|
+
print("\nNote: Polars uses projection pushdown - only reads columns needed!")
|
|
401
|
+
print("The 'text' column is never loaded, making this very fast.\n")
|
|
402
|
+
|
|
403
|
+
# Create output directory
|
|
404
|
+
output_dir = Path(args.output_dir)
|
|
405
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
406
|
+
|
|
407
|
+
# Single scan: compute temporal stats
|
|
408
|
+
logger.info("Computing temporal stats (single scan)...")
|
|
409
|
+
start = time.perf_counter()
|
|
410
|
+
temporal_path = output_dir / "temporal_stats.parquet"
|
|
411
|
+
temporal_raw = compute_temporal_stats(df, temporal_path)
|
|
412
|
+
scan_time = time.perf_counter() - start
|
|
413
|
+
logger.info(f"Scan complete in {scan_time:.2f}s - {len(temporal_raw)} dumps")
|
|
414
|
+
|
|
415
|
+
# Compute stats
|
|
416
|
+
global_stats = compute_global_stats(temporal_raw)
|
|
417
|
+
temporal_stats = format_temporal_stats(temporal_raw)
|
|
418
|
+
|
|
419
|
+
# Save
|
|
420
|
+
global_stats.write_parquet(output_dir / "global_stats.parquet")
|
|
421
|
+
temporal_stats.write_parquet(output_dir / "temporal_stats.parquet")
|
|
422
|
+
|
|
423
|
+
# Print results
|
|
424
|
+
total_docs = global_stats["total_docs"][0]
|
|
425
|
+
docs_per_sec = total_docs / scan_time if scan_time > 0 else 0
|
|
426
|
+
|
|
427
|
+
print("\n" + "=" * 70)
|
|
428
|
+
print("IS THE WEB GETTING MORE EDUCATIONAL?")
|
|
429
|
+
print("=" * 70)
|
|
430
|
+
|
|
431
|
+
print(f"\nScope: {scope_desc}")
|
|
432
|
+
print(f"Dataset: {args.source_dataset}")
|
|
433
|
+
|
|
434
|
+
print("\n" + "-" * 70)
|
|
435
|
+
print("GLOBAL STATS")
|
|
436
|
+
print("-" * 70)
|
|
437
|
+
print(global_stats)
|
|
438
|
+
|
|
439
|
+
print("\n" + "-" * 70)
|
|
440
|
+
print(f"TEMPORAL TREND ({len(temporal_stats)} CommonCrawl dumps)")
|
|
441
|
+
print("-" * 70)
|
|
442
|
+
# Show first 5 and last 5
|
|
443
|
+
if len(temporal_stats) > 10:
|
|
444
|
+
print("Earliest dumps:")
|
|
445
|
+
print(temporal_stats.head(5))
|
|
446
|
+
print("\n...")
|
|
447
|
+
print("\nLatest dumps:")
|
|
448
|
+
print(temporal_stats.tail(5))
|
|
449
|
+
else:
|
|
450
|
+
print(temporal_stats)
|
|
451
|
+
|
|
452
|
+
# Create ASCII charts
|
|
453
|
+
ascii_charts = create_ascii_charts(temporal_stats)
|
|
454
|
+
print("\n" + "-" * 70)
|
|
455
|
+
print("TREND VISUALIZATION")
|
|
456
|
+
print("-" * 70)
|
|
457
|
+
print(ascii_charts)
|
|
458
|
+
|
|
459
|
+
print("\n" + "-" * 70)
|
|
460
|
+
print("PERFORMANCE")
|
|
461
|
+
print("-" * 70)
|
|
462
|
+
print(f"Scan time: {scan_time:.2f}s")
|
|
463
|
+
print(f"Documents: {total_docs:,}")
|
|
464
|
+
print(f"Throughput: {docs_per_sec:,.0f} docs/sec")
|
|
465
|
+
|
|
466
|
+
logger.info(f"Results saved to: {output_dir}")
|
|
467
|
+
|
|
468
|
+
# Upload to HF Hub if requested
|
|
469
|
+
if args.output_repo:
|
|
470
|
+
hf_token = args.hf_token or os.environ.get("HF_TOKEN")
|
|
471
|
+
if hf_token:
|
|
472
|
+
login(token=hf_token)
|
|
473
|
+
|
|
474
|
+
api = HfApi(token=hf_token)
|
|
475
|
+
|
|
476
|
+
logger.info(f"Creating/updating dataset repository: {args.output_repo}")
|
|
477
|
+
create_repo(
|
|
478
|
+
args.output_repo,
|
|
479
|
+
repo_type="dataset",
|
|
480
|
+
private=args.private,
|
|
481
|
+
token=hf_token,
|
|
482
|
+
exist_ok=True,
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Upload each as a dataset config
|
|
486
|
+
configs = [
|
|
487
|
+
("global_stats", global_stats),
|
|
488
|
+
("temporal_stats", temporal_stats),
|
|
489
|
+
]
|
|
490
|
+
|
|
491
|
+
for config_name, stats_df in configs:
|
|
492
|
+
logger.info(f"Uploading {config_name}...")
|
|
493
|
+
ds = Dataset.from_polars(stats_df)
|
|
494
|
+
ds.push_to_hub(
|
|
495
|
+
args.output_repo,
|
|
496
|
+
config_name=config_name,
|
|
497
|
+
token=hf_token,
|
|
498
|
+
private=args.private,
|
|
499
|
+
)
|
|
500
|
+
time.sleep(1) # Avoid 409 conflicts
|
|
501
|
+
|
|
502
|
+
# Upload README
|
|
503
|
+
readme_content = create_readme(
|
|
504
|
+
args, global_stats, temporal_stats, scan_time, ascii_charts
|
|
505
|
+
)
|
|
506
|
+
api.upload_file(
|
|
507
|
+
path_or_fileobj=readme_content.encode(),
|
|
508
|
+
path_in_repo="README.md",
|
|
509
|
+
repo_id=args.output_repo,
|
|
510
|
+
repo_type="dataset",
|
|
511
|
+
token=hf_token,
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
dataset_url = f"https://huggingface.co/datasets/{args.output_repo}"
|
|
515
|
+
logger.info(f"Dataset uploaded: {dataset_url}")
|
|
516
|
+
print(f"\nResults uploaded to: {dataset_url}")
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
if __name__ == "__main__":
|
|
520
|
+
if len(sys.argv) == 1:
|
|
521
|
+
print("Is the Web Getting More Educational?")
|
|
522
|
+
print("=" * 40)
|
|
523
|
+
print("\nAnalyze educational quality trends across CommonCrawl dumps")
|
|
524
|
+
print("using Polars streaming - no download needed!\n")
|
|
525
|
+
print("Example commands:\n")
|
|
526
|
+
print("# Quick test:")
|
|
527
|
+
print("uv run finepdfs-stats.py --limit 10000\n")
|
|
528
|
+
print("# Analyze English PDFs:")
|
|
529
|
+
print("uv run finepdfs-stats.py\n")
|
|
530
|
+
print("# Analyze ALL 70+ languages:")
|
|
531
|
+
print("uv run finepdfs-stats.py --all-languages\n")
|
|
532
|
+
print("# Show query plan (see Polars optimization):")
|
|
533
|
+
print("uv run finepdfs-stats.py --show-plan --limit 1000\n")
|
|
534
|
+
print("# Save results to HF Hub:")
|
|
535
|
+
print("uv run finepdfs-stats.py --output-repo username/temporal-stats\n")
|
|
536
|
+
print("# Run on HF Jobs:")
|
|
537
|
+
print("hf jobs uv run \\")
|
|
538
|
+
print(" -s HF_TOKEN \\")
|
|
539
|
+
print(" -e HF_XET_HIGH_PERFORMANCE=1 \\")
|
|
540
|
+
print(
|
|
541
|
+
" https://huggingface.co/datasets/uv-scripts/dataset-stats/raw/main/finepdfs-stats.py \\"
|
|
542
|
+
)
|
|
543
|
+
print(" -- --output-repo username/stats")
|
|
544
|
+
sys.exit(0)
|
|
545
|
+
|
|
546
|
+
main()
|