@ericrisco/rsc 0.1.38 → 0.1.40

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.
Files changed (59) hide show
  1. package/README.md +8 -2
  2. package/manifest.json +181 -3
  3. package/package.json +1 -1
  4. package/scripts/lib/domains.js +1 -0
  5. package/scripts/lib/recommend.js +6 -0
  6. package/skills/automation-strategy/SKILL.md +2 -2
  7. package/skills/automation-strategy/references/platform-selection-matrix.md +2 -2
  8. package/skills/deep-learning/SKILL.md +263 -0
  9. package/skills/deep-learning/evals/README.md +11 -0
  10. package/skills/deep-learning/evals/cases.yaml +48 -0
  11. package/skills/deep-learning/references/distributed.md +105 -0
  12. package/skills/deep-learning/references/training-recipes.md +135 -0
  13. package/skills/finetuning/SKILL.md +244 -0
  14. package/skills/finetuning/evals/README.md +13 -0
  15. package/skills/finetuning/evals/cases.yaml +50 -0
  16. package/skills/finetuning/references/hyperparameters-and-eval.md +74 -0
  17. package/skills/finetuning/references/methods.md +189 -0
  18. package/skills/harness/references/providers.yaml +38 -2
  19. package/skills/huggingface/SKILL.md +1 -1
  20. package/skills/machine-learning/SKILL.md +260 -0
  21. package/skills/machine-learning/evals/README.md +15 -0
  22. package/skills/machine-learning/evals/cases.yaml +54 -0
  23. package/skills/machine-learning/references/gbdt-and-tuning.md +83 -0
  24. package/skills/machine-learning/references/metrics-and-imbalance.md +82 -0
  25. package/skills/machine-learning/references/pipelines-and-cv.md +135 -0
  26. package/skills/n8n/SKILL.md +1 -1
  27. package/skills/nlp/SKILL.md +225 -0
  28. package/skills/nlp/evals/README.md +10 -0
  29. package/skills/nlp/evals/cases.yaml +45 -0
  30. package/skills/nlp/references/evaluation.md +107 -0
  31. package/skills/nlp/references/tokenization.md +95 -0
  32. package/skills/open-weights/SKILL.md +239 -0
  33. package/skills/open-weights/evals/README.md +14 -0
  34. package/skills/open-weights/evals/cases.yaml +42 -0
  35. package/skills/open-weights/references/licenses.md +123 -0
  36. package/skills/open-weights/references/model-families.md +83 -0
  37. package/skills/open-weights/references/sizing-and-quant.md +89 -0
  38. package/skills/roast-me/tools/adapters/__pycache__/__init__.cpython-312.pyc +0 -0
  39. package/skills/roast-me/tools/adapters/__pycache__/base.cpython-312.pyc +0 -0
  40. package/skills/roast-me/tools/adapters/__pycache__/claude.cpython-312.pyc +0 -0
  41. package/skills/roast-me/tools/adapters/__pycache__/codex.cpython-312.pyc +0 -0
  42. package/skills/roast-me/tools/adapters/__pycache__/gemini.cpython-312.pyc +0 -0
  43. package/skills/roast-me/tools/adapters/__pycache__/registry.cpython-312.pyc +0 -0
  44. package/skills/training-data/SKILL.md +226 -0
  45. package/skills/training-data/evals/README.md +13 -0
  46. package/skills/training-data/evals/cases.yaml +41 -0
  47. package/skills/training-data/references/formats.md +118 -0
  48. package/skills/training-data/references/synthesis-dedup-quality.md +134 -0
  49. package/skills/unsloth/SKILL.md +254 -0
  50. package/skills/unsloth/evals/README.md +10 -0
  51. package/skills/unsloth/evals/cases.yaml +42 -0
  52. package/skills/unsloth/references/export.md +75 -0
  53. package/skills/unsloth/references/grpo.md +91 -0
  54. package/skills/unsloth/references/masking-and-templates.md +91 -0
  55. package/skills/vllm/SKILL.md +235 -0
  56. package/skills/vllm/evals/README.md +9 -0
  57. package/skills/vllm/evals/cases.yaml +47 -0
  58. package/skills/vllm/references/flags-and-endpoints.md +105 -0
  59. package/skills/vllm/references/memory-and-throughput.md +78 -0
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  ██ ██ ███████ ███████
13
13
  ```
14
14
 
15
- # `rsc` — 248 agent skills, one CLI, zero bloat
15
+ # `rsc` — 256 agent skills, one CLI, zero bloat
16
16
 
17
17
  **A self-recommending skill catalog for 17 coding assistants** — Claude Code,
18
18
  Codex, GitHub Copilot, Cursor, Gemini, Windsurf, Cline, Antigravity, Zed and more.
@@ -243,7 +243,7 @@ just asks in plain language.
243
243
 
244
244
  ## The catalog
245
245
 
246
- 249 skills, grouped by what you're trying to do. Click any skill to read its
246
+ 257 skills, grouped by what you're trying to do. Click any skill to read its
247
247
  `SKILL.md`. It fires on its own when a task matches.
248
248
 
249
249
  ### 🧭 Core & control plane
@@ -324,6 +324,12 @@ Operate the big automation platforms **programmatically or via MCP** — create
324
324
 
325
325
  [replicate](skills/replicate/) · [runpod](skills/runpod/) · [modal](skills/modal/) · [huggingface](skills/huggingface/) · [ollama](skills/ollama/) · [together-fireworks](skills/together-fireworks/) · [fal](skills/fal/)
326
326
 
327
+ ### 🎓 AI — train it
328
+
329
+ Train and adapt open models end to end: classic ML, deep learning, NLP, fine-tuning (with Unsloth), building training datasets, choosing open-weight models by license/size, and serving them at throughput with vLLM. Facts that move monthly (versions, model licenses) are verified at author time and hedged.
330
+
331
+ [machine-learning](skills/machine-learning/) · [deep-learning](skills/deep-learning/) · [nlp](skills/nlp/) · [finetuning](skills/finetuning/) · [training-data](skills/training-data/) · [unsloth](skills/unsloth/) · [open-weights](skills/open-weights/) · [vllm](skills/vllm/)
332
+
327
333
  ### 🗣️ Languages
328
334
 
329
335
  [typescript](skills/typescript/) · [python](skills/python/) · [java](skills/java/) · [csharp-dotnet](skills/csharp-dotnet/) · [php](skills/php/) · [ruby](skills/ruby/) · [cpp](skills/cpp/) · [elixir](skills/elixir/) · [bash-scripting](skills/bash-scripting/) · [sql](skills/sql/) · [go](skills/go/)
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "0.1.38",
2
+ "version": "0.1.40",
3
3
  "counts": {
4
- "skills": 249
4
+ "skills": 257
5
5
  },
6
6
  "skills": [
7
7
  {
@@ -1191,6 +1191,32 @@
1191
1191
  ],
1192
1192
  "profiles": []
1193
1193
  },
1194
+ {
1195
+ "id": "deep-learning",
1196
+ "description": "Use when training or debugging a neural network in PyTorch — writing the training loop, chasing loss that won't drop or goes NaN, adding mixed precision (AMP), scaling across GPUs, or making a run reproducible. Covers tensors/autograd/nn.Module, torch.compile, the forward→loss→backward→step→zero_grad loop and its silent bugs, AdamW + cosine/warmup schedulers, DDP vs FSDP vs DeepSpeed ZeRO, checkpointing and seeds. PyTorch-first (JAX/TF exist). Triggers: 'my training loss isn't decreasing', 'loss becomes NaN after a few steps', 'how do I use torch.autocast and GradScaler', 'train this model across 4 GPUs', 'val accuracy is worse than train and I forgot model.eval()', 'gradients seem to add up across batches', 'build a CNN from scratch and train it', 'entrenar una xarxa neuronal des de zero amb PyTorch'. NOT adapting a pretrained LLM with LoRA/QLoRA (that is finetuning); NOT classic/tabular models like XGBoost or sklearn (that is machine-learning); NOT tokenization or NLP task metrics (that is nlp).",
1197
+ "tags": [
1198
+ "pytorch",
1199
+ "deep-learning",
1200
+ "neural-networks",
1201
+ "training-loop",
1202
+ "autograd",
1203
+ "mixed-precision",
1204
+ "amp",
1205
+ "ddp",
1206
+ "fsdp",
1207
+ "optimizer",
1208
+ "lr-scheduler",
1209
+ "reproducibility",
1210
+ "torch-compile"
1211
+ ],
1212
+ "recommends": [
1213
+ "machine-learning",
1214
+ "finetuning",
1215
+ "nlp",
1216
+ "python"
1217
+ ],
1218
+ "profiles": []
1219
+ },
1194
1220
  {
1195
1221
  "id": "deployment",
1196
1222
  "description": "Use when containerizing an app, writing a Dockerfile, setting up GitHub Actions CI/CD, choosing a deploy target, or deploying to Coolify, Vercel, or a Hetzner VPS — multi-stage builds (FastAPI/uv, Go/distroless, Next.js standalone, Flutter web, Postgres), BuildKit build secrets, image scanning (trivy/hadolint), OIDC to registries (no long-lived secrets), least-privilege GITHUB_TOKEN, zero-downtime/rolling deploys, env/secrets flow GitHub→Coolify, healthchecks, rollback, and a hosting decision matrix (Vercel vs Hetzner+Coolify vs a third option). Trigger phrases: 'dockerize', 'write a Dockerfile', 'CI pipeline', 'GitHub Actions', 'deploy', 'ship it', 'where should I host this', 'Coolify', 'Vercel', 'Hetzner', 'VPS', 'docker-compose for local dev'.",
@@ -1697,6 +1723,30 @@
1697
1723
  ],
1698
1724
  "profiles": []
1699
1725
  },
1726
+ {
1727
+ "id": "finetuning",
1728
+ "description": "Use when adapting an open-weight model to a target FORM or BEHAVIOR — tone, output format, domain style, a reasoning/tool-calling pattern — via LoRA/QLoRA or full fine-tuning with TRL SFTTrainer and then preference optimization (DPO/ORPO/KTO/GRPO); when choosing fine-tune vs prompt vs RAG vs longer context; when setting LoRA r/alpha/target_modules; when eval loss climbs while train loss keeps falling; when the adapter seems to have learned nothing; when inference outputs garbage after a run. Triggers: 'fine-tune Llama/Qwen on our data', 'LoRA vs QLoRA vs full fine-tune', 'SFT then DPO/ORPO/KTO/GRPO', 'set target_modules / rank / alpha', 'my fine-tune overfits', 'the model forgot everything after training', 'write a GRPO reward function', 'ajustar un modelo amb LoRA amb les nostres dades'. NOT adding facts or fresh knowledge to a model (that is rag); NOT the fast single-GPU Unsloth backend or GGUF export (that is unsloth); NOT serving the trained model (that is vllm).",
1729
+ "tags": [
1730
+ "finetuning",
1731
+ "lora",
1732
+ "qlora",
1733
+ "sft",
1734
+ "dpo",
1735
+ "grpo",
1736
+ "peft",
1737
+ "trl",
1738
+ "preference-optimization"
1739
+ ],
1740
+ "recommends": [
1741
+ "training-data",
1742
+ "unsloth",
1743
+ "open-weights",
1744
+ "huggingface",
1745
+ "vllm",
1746
+ "rag"
1747
+ ],
1748
+ "profiles": []
1749
+ },
1700
1750
  {
1701
1751
  "id": "firebase",
1702
1752
  "description": "Use when building on Firebase — modeling Firestore data, writing or auditing Security Rules, wiring Auth, shipping Cloud Functions, storing files in Cloud Storage, or choosing modular Web/Admin SDK imports — and when symptoms appear like 'my database is open to the internet', 'rules reject my query', a counter stuck at 1 write/sec, custom-claim RBAC, or a callable function. Triggers: 'firestore.rules audit', 'denormalize for read paths', 'collection vs subcollection', 'my query works in the emulator but fails in prod with requires-an-index', 'set a custom admin claim', 'regles de seguretat de Firestore', 'mi base de datos está abierta a internet'. NOT managed-Postgres BaaS with SQL and RLS (that is supabase).",
@@ -2203,7 +2253,7 @@
2203
2253
  },
2204
2254
  {
2205
2255
  "id": "huggingface",
2206
- "description": "Use when running open models or working on the Hugging Face platform: calling a model via the Inference Providers router or InferenceClient, downloading/uploading/versioning repos on the Hub with the hf CLI, deploying a dedicated Inference Endpoint with scale-to-zero, hosting a Gradio Space with ZeroGPU, picking an open model by task/license/size, or loading a model locally with transformers. Triggers: 'call an open model through Hugging Face', 'InferenceClient embeddings', 'hf download/upload', 'write a model card', 'router.huggingface.co', 'my hf-inference serverless call 404s on a 70B model', 'scale-to-zero endpoint', 'ZeroGPU Space', 'desplegar un modelo de Hugging Face con escalado a cero', 'necesito controlar el coste de inferencia en HF'. NOT serving a model locally on your own machine (that is ollama), NOT renting and operating your own GPU box (that is runpod), NOT generating creative images via a hosted API (that is replicate-images).",
2256
+ "description": "Use when running open models or working on the Hugging Face platform: calling a model via the Inference Providers router or InferenceClient, downloading/uploading/versioning repos on the Hub with the hf CLI, deploying a dedicated Inference Endpoint with scale-to-zero, hosting a Gradio Space with ZeroGPU, picking an open model by task/license/size, or loading a model locally with transformers. Triggers: 'call an open model through Hugging Face', 'InferenceClient embeddings', 'hf download/upload', 'write a model card', 'router.huggingface.co', 'my hf-inference serverless call 404s on a 70B model', 'scale-to-zero endpoint', 'ZeroGPU Space', 'desplegar un modelo de Hugging Face con escalado a cero'. NOT serving a model locally on your own machine (that is ollama), NOT renting and operating your own GPU box (that is runpod), NOT generating creative images via a hosted API (that is replicate-images), NOT fine-tuning with trl/peft (that is finetuning), NOT building training datasets (that is training-data).",
2207
2257
  "tags": [
2208
2258
  "huggingface",
2209
2259
  "inference-providers",
@@ -2688,6 +2738,31 @@
2688
2738
  ],
2689
2739
  "profiles": []
2690
2740
  },
2741
+ {
2742
+ "id": "machine-learning",
2743
+ "description": "Use when the task is a classic/tabular machine-learning problem — predict a column from rows of features with trees and scikit-learn: fit a RandomForest / XGBoost / LightGBM classifier or regressor, build a leak-proof Pipeline + ColumnTransformer, choose a cross-validation scheme (stratified / k-fold / time-series / grouped), pick the right metric on imbalanced classes (precision/recall/F1/ROC-AUC/PR-AUC, not accuracy), or debug a model that aced CV then collapsed in production. Triggers: 'train a model to predict churn/fraud/price', 'my ROC-AUC is 0.99 — is that leakage', 'which metric for imbalanced classes', 'cross-validation without leaking', 'XGBoost vs LightGBM', 'add a DummyClassifier baseline', 'entrena un modelo de clasificación tabular con scikit-learn'. NOT neural-net / PyTorch training (that is deep-learning), NOT cleaning the raw dirty table first (that is data-cleaning), NOT BI dashboards or forecasting a dated series (that is analytics/forecasting), NOT text/token modeling (that is nlp).",
2744
+ "tags": [
2745
+ "machine-learning",
2746
+ "scikit-learn",
2747
+ "sklearn",
2748
+ "xgboost",
2749
+ "lightgbm",
2750
+ "tabular",
2751
+ "gbdt",
2752
+ "cross-validation",
2753
+ "data-leakage",
2754
+ "classification",
2755
+ "regression",
2756
+ "pipeline"
2757
+ ],
2758
+ "recommends": [
2759
+ "deep-learning",
2760
+ "data-cleaning",
2761
+ "python",
2762
+ "training-data"
2763
+ ],
2764
+ "profiles": []
2765
+ },
2691
2766
  {
2692
2767
  "id": "make",
2693
2768
  "description": "Use when operating Make.com (formerly Integromat) programmatically — driving its REST API v2 or the Make MCP server from code or an agent to create, read, update, activate, run, clone, or delete scenarios, connections, hooks, and data stores. Triggers: 'create a Make scenario via the API', 'export a scenario blueprint, mutate it, and push it back', 'start/stop/run a Make scenario from a script', 'clone this Integromat scenario into another team', 'connect the Make MCP server so an agent runs my scenarios as tools', 'my valid Make API token returns an auth error' (zone trap), 'automatiza escenarios de Make.com desde la API'. NOT designing what the flow should do — trigger, branching, mapping, dedup, error path (automation-flows), NOT choosing Make vs n8n vs Zapier by billing model (automation-strategy), NOT operating n8n / Zapier / Power Automate (their skills), NOT a generic typed REST client with pagination/backoff (api-connector-builder) or an inbound webhook receiver in your own app (webhooks).",
@@ -3035,6 +3110,29 @@
3035
3110
  ],
3036
3111
  "profiles": []
3037
3112
  },
3113
+ {
3114
+ "id": "nlp",
3115
+ "description": "Use when choosing how to tokenize text or which transformer type fits an NLP task, when a tokenizer over-fragments non-English text or inflates token cost, when picking a language metric, or when classification / NER / summarization output looks wrong and you can't tell whether the tokenizer, the architecture, or the metric is at fault. Covers BPE / WordPiece / SentencePiece-Unigram / byte-level BPE, special tokens, encoder (BERT) vs decoder (GPT) vs encoder-decoder (T5) choice, classification, NER, seq2seq, sentence embeddings, and metrics (F1, entity-F1, BLEU / ROUGE / chrF, perplexity, LLM-as-judge). Triggers: 'BPE or WordPiece', 'BERT vs GPT vs T5 for this task', 'tokenizer splits Catalan into too many tokens', 'is BLEU good for summaries', 'entity F1 for NER', 'quin model faig servir per classificar text'. NOT retrieval / vector search (that is embeddings-search), NOT the RAG loop (that is rag), NOT prompt wording (that is prompt-engineering), NOT training the net (that is finetuning / deep-learning).",
3116
+ "tags": [
3117
+ "nlp",
3118
+ "tokenization",
3119
+ "bpe",
3120
+ "wordpiece",
3121
+ "ner",
3122
+ "text-classification",
3123
+ "bleu",
3124
+ "rouge",
3125
+ "perplexity",
3126
+ "transformers"
3127
+ ],
3128
+ "recommends": [
3129
+ "deep-learning",
3130
+ "embeddings-search",
3131
+ "rag",
3132
+ "training-data"
3133
+ ],
3134
+ "profiles": []
3135
+ },
3038
3136
  {
3039
3137
  "id": "no-code-app",
3040
3138
  "description": "Use when building an app on a no-code/low-code platform (Bubble, Softr, Glide, with Airtable/Xano backends) — picking the tool, modeling the data, taming usage/cost metering, or planning the exit before lock-in. Triggers: 'build a CRM without code', 'Bubble or Glide for my MVP', 'monta una app sin codi per reserves', 'my Bubble bill suddenly exploded' (workload-unit metering), 'Glide updates overage', 'how do I avoid getting locked into a no-code tool', 'when should I stop and write real code'. NOT a coded web app (that is nextjs).",
@@ -3134,6 +3232,24 @@
3134
3232
  ],
3135
3233
  "profiles": []
3136
3234
  },
3235
+ {
3236
+ "id": "open-weights",
3237
+ "description": "Use when choosing an open-weight LLM and clearing it for use — which family and size fit a task, hardware and budget, and above all whether the license lets you ship (Llama, Qwen, Mistral/Mixtral, Gemma, DeepSeek, Phi, gpt-oss, and others). Owns the license-CLASS map (OSI-open Apache/MIT vs custom-community like Llama/Gemma vs non-commercial/restricted like the original Codestral) and the always-verify-the-model-card rule, plus size-to-VRAM budgeting and quant formats (GGUF/AWQ/GPTQ, what Q4_K_M means). Triggers: 'which open model should I use', 'can I use Llama/Gemma commercially', 'is Qwen Apache-2.0', 'what open LLM fits a 24GB GPU', 'is this license safe to ship in a product', 'quin model obert puc fer servir legalment'. NOT how to download or host on HF (that is huggingface), NOT running it locally (that is ollama), NOT serving at throughput (that is vllm), NOT fine-tuning it (that is finetuning) — this layer only tells you WHICH model and whether the license permits it, then hands off.",
3238
+ "tags": [
3239
+ "open-weights",
3240
+ "open-source-llm",
3241
+ "model-selection",
3242
+ "model-licenses",
3243
+ "llama-qwen-mistral-gemma"
3244
+ ],
3245
+ "recommends": [
3246
+ "huggingface",
3247
+ "ollama",
3248
+ "finetuning",
3249
+ "vllm"
3250
+ ],
3251
+ "profiles": []
3252
+ },
3137
3253
  {
3138
3254
  "id": "orient",
3139
3255
  "description": "Always-on. The brújula: after every action keep the human oriented — situate them on the project map, say what just happened, teach the why at their level, and propose the next step as a question. NEVER end a turn in seco (dead-end). Reads technical_level + accompaniment_level from 02-DOCS/wiki/harness/user-profile.md and calibrates how much it explains; rewrites the dial when the user asks for more/less ('explícame más', 'explícame menos', 'no me expliques tanto', 'enséñame'). Complements suggest (which installs missing skills) — orient guides the person, not the toolbox. Fires on every turn that finishes an action, reaches a decision fork, or leaves the user unsure what to do next.",
@@ -4731,6 +4847,29 @@
4731
4847
  ],
4732
4848
  "profiles": []
4733
4849
  },
4850
+ {
4851
+ "id": "training-data",
4852
+ "description": "Use when assembling or curating the corpus a fine-tune trains on: turning raw examples into JSONL in the format a trainer expects (Alpaca instruction, conversational messages, DPO preference pairs, KTO binary-label), matching your data to the model's chat template, generating synthetic or distilled examples, deduplicating and decontaminating against eval sets, or quality-filtering. Triggers: 'what format should my fine-tuning dataset be in', 'build a DPO preference dataset', 'convert my Q&A into the messages/chat format', 'my chat template does not match my training data', 'generate synthetic instruction data with distilabel', 'dedup and decontaminate my training set', 'quants exemples necessito i com filtro la qualitat del dataset abans d'entrenar'. NOT cleaning tabular rows/nulls/dtypes (that is data-cleaning), NOT building a retrieval corpus of chunks+embeddings (that is embeddings-search), NOT running the trainer or picking LoRA hyperparameters (that is finetuning/unsloth).",
4853
+ "tags": [
4854
+ "training-data",
4855
+ "fine-tuning-dataset",
4856
+ "jsonl",
4857
+ "chat-template",
4858
+ "preference-data",
4859
+ "dpo",
4860
+ "kto",
4861
+ "synthetic-data",
4862
+ "decontamination",
4863
+ "dataset-curation"
4864
+ ],
4865
+ "recommends": [
4866
+ "finetuning",
4867
+ "unsloth",
4868
+ "huggingface",
4869
+ "data-cleaning"
4870
+ ],
4871
+ "profiles": []
4872
+ },
4734
4873
  {
4735
4874
  "id": "translation-l10n",
4736
4875
  "description": "Use when adding a second or Nth language to a web/app product, wiring i18n plumbing (extract strings, ICU messages, locale routing), fixing broken plurals or dates, or making a UI survive other languages (RTL, text expansion). Triggers: 'ship the app in French and Arabic', 'set up next-intl routing with generateStaticParams', 'our Russian plurals always show the singular', 'German text overflows the buttons', 'dates still show American format for Spanish users', 'the Arabic layout is mirrored wrong', 'traducir la app al árabe y montar el glosario', 'necessito localitzar el producte'. NOT defining the brand's tone in one language (that is brand-voice).",
@@ -4839,6 +4978,26 @@
4839
4978
  "full"
4840
4979
  ]
4841
4980
  },
4981
+ {
4982
+ "id": "unsloth",
4983
+ "description": "Use when fine-tuning an open-weight LLM fast on ONE GPU with low VRAM — Unsloth's FastLanguageModel/FastModel + 4-bit QLoRA + trl SFTTrainer, response-only loss masking via get_chat_template/train_on_responses_only, GRPO reasoning FT, and export to merged-16bit / GGUF / push_to_hub for Ollama or vLLM. Triggers: 'fine-tune Llama/Qwen/Gemma/gpt-oss on a single 16GB/24GB GPU', 'QLoRA OOMs on my GPU, make it fit', 'train ~2x faster with less VRAM', 'why is my loss covering the prompt / how do I mask the user turn', 'save my LoRA as GGUF Q4_K_M for Ollama', 'ajustar un modelo en una sola GPU sense quedar-me sense VRAM'. NOT whether/why/which method to fine-tune or trl/peft theory (that is finetuning), NOT running the exported GGUF locally (that is ollama), NOT serving-engine flags/throughput (that is vllm), NOT building the JSONL dataset (that is training-data).",
4984
+ "tags": [
4985
+ "unsloth",
4986
+ "qlora",
4987
+ "lora",
4988
+ "single-gpu",
4989
+ "gguf",
4990
+ "fine-tuning"
4991
+ ],
4992
+ "recommends": [
4993
+ "finetuning",
4994
+ "training-data",
4995
+ "open-weights",
4996
+ "ollama",
4997
+ "huggingface"
4998
+ ],
4999
+ "profiles": []
5000
+ },
4842
5001
  {
4843
5002
  "id": "vector-db",
4844
5003
  "description": "Use when operating a vector store as a data layer — choosing or migrating between Pinecone, Qdrant, Weaviate, or pgvector; designing a collection/index (distance metric, dimensions, HNSW m/ef_construction, named vectors); filtering on metadata/payload; running hybrid dense+sparse search; or picking quantization to cut RAM and cost. Symptoms: search returns garbage, filters get silently ignored, recall is low, queries are slow, the bill is too high, a filtered query returns fewer than k rows. Triggers: 'set up a vector database', 'my similarity search ignores the metadata filter', 'ef_search vs recall', 'move off Pinecone to pgvector to cut cost', 'hybrid search with RRF', 'why does my filtered query return fewer than k results', 'crear una colección en Qdrant con cuantización binaria', 'la cerca vectorial retorna resultats dolents'. NOT how to produce, chunk, or judge embeddings (that is embeddings-search).",
@@ -4919,6 +5078,25 @@
4919
5078
  ],
4920
5079
  "profiles": []
4921
5080
  },
5081
+ {
5082
+ "id": "vllm",
5083
+ "description": "Use when self-hosting an open-weight LLM for high-throughput, concurrent serving with vLLM — running `vllm serve` as an OpenAI-compatible endpoint, splitting a model across GPUs with tensor/pipeline parallelism, loading AWQ/GPTQ/FP8/compressed-tensors quants, serving one or many LoRA adapters, or debugging KV-cache OOM from --gpu-memory-utilization / --max-model-len. Triggers: 'serve a 70B to many users at once', 'point my OpenAI client at a self-hosted model', 'split a model across 4 GPUs with tensor parallel', 'why does vllm OOM at long context', 'serve my fine-tuned LoRA adapter', 'health check my vllm server', 'servir un modelo abierto con alta concurrencia en mis propias GPUs'. NOT renting/provisioning the GPU box itself (that is runpod / modal), NOT single-user laptop inference (that is ollama), NOT a hosted inference API you do not operate (that is together-fireworks / huggingface).",
5084
+ "tags": [
5085
+ "vllm",
5086
+ "llm-serving",
5087
+ "inference-server",
5088
+ "tensor-parallel",
5089
+ "quantization"
5090
+ ],
5091
+ "recommends": [
5092
+ "open-weights",
5093
+ "finetuning",
5094
+ "runpod",
5095
+ "modal",
5096
+ "ollama"
5097
+ ],
5098
+ "profiles": []
5099
+ },
4922
5100
  {
4923
5101
  "id": "vue-nuxt",
4924
5102
  "description": "Use when building, reviewing, or optimizing a Vue 3 + Nuxt 4 app — Composition API/`<script setup>`, SSR/SSG/hybrid rendering, the `app/`+`server/` structure, SSR-safe data fetching and shared state, Nitro server routes, reactivity/hydration discipline. Triggers: `.vue` SFCs, `useFetch`/`useAsyncData`/`$fetch`, `useState`/Pinia, `defineModel`/`useTemplateRef`, hydration node mismatch, double-fetch on SSR, `server/api` handlers, `routeRules`, Nuxt 3→4 migration, `nuxt.config.ts`, 'app SSR no hidrata', 'per què es fa doble fetch'. NOT React/RSC (that is nextjs), NOT a static multi-framework site (that is astro).",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ericrisco/rsc",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "description": "Eric Risco's agent-skills catalog as a granular, self-recommending CLI installer.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,7 @@ export const DOMAINS = [
16
16
  { title: 'Data & analytics', ids: ['analytics', 'dashboard', 'kpi-framework', 'reporting', 'ab-testing', 'forecasting', 'data-cleaning', 'business-intelligence'] },
17
17
  { title: 'AI — build it in', ids: ['building-agents', 'rag', 'embeddings-search', 'prompt-engineering', 'llm-pipeline', 'agent-eval', 'chatbot', 'ai-media', 'replicate-images', 'structured-extraction', 'agent-safety', 'cost-tracking'] },
18
18
  { title: 'AI — run it on', ids: ['replicate', 'runpod', 'modal', 'huggingface', 'ollama', 'together-fireworks', 'fal'] },
19
+ { title: 'AI — train it', ids: ['machine-learning', 'deep-learning', 'nlp', 'finetuning', 'training-data', 'unsloth', 'open-weights', 'vllm'] },
19
20
  { title: 'Languages', ids: ['typescript', 'python', 'java', 'csharp-dotnet', 'php', 'ruby', 'cpp', 'elixir', 'bash-scripting', 'sql', 'go'] },
20
21
  { title: 'Frameworks & app stacks', ids: ['fastapi', 'nextjs', 'react', 'react-native', 'vue-nuxt', 'angular', 'svelte', 'astro', 'solid-js', 'htmx', 'nodejs', 'nestjs', 'django', 'laravel', 'rails', 'spring-boot', 'phoenix', 'flutter', 'swift-ios', 'kotlin-android', 'compose-multiplatform', 'expo', 'tauri', 'electron', 'rust', 'wordpress', 'shopify', 'no-code-app', 'chrome-extension', 'api-design'] },
21
22
  { title: 'Game development', ids: ['godot', 'unity', 'unreal', 'game-design', 'game-storytelling', 'level-design', 'gamedev-shaders', 'gamedev-multiplayer', 'gamedev-physics', 'gamedev-pathing', 'gamedev-shipping'] },
@@ -21,6 +21,12 @@ const OUTCOMES = {
21
21
  unreal: 'Your game (Unreal)',
22
22
  'game-design': "Design a game that's fun",
23
23
  'fable-operator': 'Reason it through, reliably',
24
+ finetuning: 'Fine-tune an open model',
25
+ 'machine-learning': 'Build a classic ML model',
26
+ 'deep-learning': 'Train a neural network',
27
+ nlp: 'Do NLP the right way',
28
+ 'open-weights': 'Pick an open-weight model',
29
+ vllm: 'Serve open models at scale',
24
30
  'automation-strategy': 'Decide what to automate',
25
31
  n8n: 'Automate with n8n (API/MCP)',
26
32
  make: 'Automate with Make (API/MCP)',
@@ -78,9 +78,9 @@ Pick on **billing unit first** — it's the axis that dictates cost at scale, an
78
78
  | **Billing unit** | per **execution** (whole run = 1, any # of steps); self-host = $0 | per **credit** (each module action = 1; was "operations", renamed 2025-08-27) | per **task** (every action counts) | per **user** or per **flow** (premium); bundled with many M365 plans |
79
79
  | **Best cost shape** | few long/complex flows, high volume | moderate multi-step flows | many short simple flows | teams already paying for M365 |
80
80
  | **Self-host / data residency** | **yes** — your infra, your data | no (EU/US regions only) | no | Microsoft cloud / Dataverse regions |
81
- | **Ecosystem fit** | technical teams, raw HTTP, code nodes | mid-market, deep per-app modules | widest app catalog (~8,000+) | **native to Microsoft 365** — Teams, SharePoint, Outlook, Dataverse |
81
+ | **Ecosystem fit** | technical teams, raw HTTP, code nodes | mid-market, deep per-app modules | widest app catalog (~9,000+) | **native to Microsoft 365** — Teams, SharePoint, Outlook, Dataverse |
82
82
  | **Programmatic + MCP maturity** | public REST API to CRUD workflows; community MCP; strongest for code-driven ops | management API + MCP support maturing | rich API for actions + Zapier MCP to expose actions to agents — **but no public API to create Zaps** | Flow management APIs + solutions/ARM — **but no clean public API to create end-user "My flows"** |
83
- | **Portability** | high — export/import JSON | low — no portable export | low — no portable export | low — tied to MS solutions |
83
+ | **Portability** | high — export/import JSON + self-hostable runtime | medium — blueprint export/import, but runs only on Make | low — no portable export | low — tied to MS solutions |
84
84
 
85
85
  **Routing shortcuts:** already living in Microsoft 365 → **Power Automate** (`../power-automate/SKILL.md`). Data must stay on your own infra, or high volume where execution-billing wins → **n8n** (`../n8n/SKILL.md`). Obscure app, non-technical owner → **Zapier** (`../zapier/SKILL.md`). Deep per-app modules, mid volume → **Make** (`../make/SKILL.md`).
86
86
 
@@ -33,10 +33,10 @@ because it rides existing M365 licenses.
33
33
  | Axis | n8n | Make | Zapier | Power Automate |
34
34
  | --- | --- | --- | --- | --- |
35
35
  | Free / entry | self-host free; cloud Starter ≈ €20/mo | ≈ 1,000 credits free; Core ≈ $9/mo | 100 tasks/mo free; Pro ≈ $19.99/mo | bundled in many M365 plans; premium add-ons |
36
- | App breadth | ~1,000 nodes + generic HTTP + code | ~1,500, often deep per app | ~8,000+ — widest catalog | strong on MS + growing 3rd-party connectors |
36
+ | App breadth | ~1,000 nodes + generic HTTP + code | ~1,500, often deep per app | ~9,000+ apps — widest catalog | strong on MS + growing 3rd-party connectors |
37
37
  | Self-host / data residency | **yes — your infra** | no (EU/US regions) | no | Microsoft cloud / Dataverse regions |
38
38
  | Who runs/maintains it | technical; you run the box | mid; visual but rich | non-technical-friendly | IT/business in a Microsoft shop |
39
- | Portability | high (export/import JSON) | low (no portable export) | low (no portable export) | low (tied to MS solutions) |
39
+ | Portability | high (export/import JSON + self-hostable runtime) | medium (blueprint export/import, runs only on Make) | low (no portable export) | low (tied to MS solutions) |
40
40
  | Complex logic / code | code nodes, sandboxed by default (n8n 2.0) | functions + routers | limited (Code by Zapier) | expressions + Azure Functions escape hatch |
41
41
 
42
42
  ## Programmatic + MCP maturity (honest)
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: deep-learning
3
+ description: "Use when training or debugging a neural network in PyTorch — writing the training loop, chasing loss that won't drop or goes NaN, adding mixed precision (AMP), scaling across GPUs, or making a run reproducible. Covers tensors/autograd/nn.Module, torch.compile, the forward→loss→backward→step→zero_grad loop and its silent bugs, AdamW + cosine/warmup schedulers, DDP vs FSDP vs DeepSpeed ZeRO, checkpointing and seeds. PyTorch-first (JAX/TF exist). Triggers: 'my training loss isn't decreasing', 'loss becomes NaN after a few steps', 'how do I use torch.autocast and GradScaler', 'train this model across 4 GPUs', 'val accuracy is worse than train and I forgot model.eval()', 'gradients seem to add up across batches', 'build a CNN from scratch and train it', 'entrenar una xarxa neuronal des de zero amb PyTorch'. NOT adapting a pretrained LLM with LoRA/QLoRA (that is finetuning); NOT classic/tabular models like XGBoost or sklearn (that is machine-learning); NOT tokenization or NLP task metrics (that is nlp)."
4
+ tags: [pytorch, deep-learning, neural-networks, training-loop, autograd, mixed-precision, amp, ddp, fsdp, optimizer, lr-scheduler, reproducibility, torch-compile]
5
+ recommends: [machine-learning, finetuning, nlp, python]
6
+ origin: risco
7
+ ---
8
+
9
+ # deep-learning — train a neural net in PyTorch without the silent bugs
10
+
11
+ You own **training and understanding neural networks in PyTorch**: the loop, autograd, mixed
12
+ precision, optimizers/schedulers, multi-GPU, and the reproducibility/checkpoint hygiene that
13
+ separates a real result from a lucky one. Nets from scratch, vision, custom architectures — all
14
+ here. This is PyTorch-first by design: JAX and TensorFlow are real and fine, but the patterns,
15
+ APIs, and gotchas below are Torch's.
16
+
17
+ **Version reality (verify at author time).** Current stable is PyTorch **2.x** — ~**2.13** as of
18
+ mid-2026 (`pytorch.org/get-started`, releases move fast; don't hard-pin a minor). Everything below
19
+ is stable 2.x API. The one namespace shift to know: AMP now lives under `torch.amp`
20
+ (`torch.amp.GradScaler("cuda")`), not the old `torch.cuda.amp.*`.
21
+
22
+ ## Am I in the right skill?
23
+
24
+ | You are doing… | Skill |
25
+ |---|---|
26
+ | Training/debugging a net in PyTorch (from scratch, vision, custom loop, AMP, multi-GPU) | **deep-learning (here)** |
27
+ | Adapting a *pretrained LLM* — LoRA/QLoRA, SFT, trl/peft | [`finetuning`](../finetuning/SKILL.md) |
28
+ | Classic/tabular — sklearn, XGBoost/LightGBM, feature engineering | [`machine-learning`](../machine-learning/SKILL.md) |
29
+ | Tokenization, NLP task modeling, task metrics (F1/BLEU/ROUGE) | [`nlp`](../nlp/SKILL.md) |
30
+
31
+ If the model is a from-scratch or vision/custom net and you're writing the loop yourself, stay.
32
+
33
+ ## 1. PyTorch essentials
34
+
35
+ Three objects carry everything.
36
+
37
+ - **Tensor** — an n-d array on a `device` (`cpu`/`cuda`/`mps`) with a `dtype`. `requires_grad=True`
38
+ makes autograd track ops on it. `.to(device)` / `.detach()` / `.item()` are the moves you use
39
+ constantly; `.item()` pulls a Python scalar and **drops the graph** (see the loop bugs below).
40
+ - **autograd** — a tape. Every op on a `requires_grad` tensor records a node; `loss.backward()`
41
+ walks it and *accumulates* into each leaf's `.grad`. "Accumulates" is the word that bites people
42
+ (§2). Wrap read-only regions in `torch.no_grad()` to skip taping.
43
+ - **`nn.Module`** — the model container. `__init__` registers submodules/params; `forward` defines
44
+ compute. `model.parameters()` feeds the optimizer; `model.train()` / `model.eval()` flip
45
+ train-vs-eval behavior for Dropout and BatchNorm.
46
+
47
+ ```python
48
+ import torch, torch.nn as nn
49
+ device = "cuda" if torch.cuda.is_available() else "cpu"
50
+
51
+ class MLP(nn.Module):
52
+ def __init__(self, d_in, d_h, d_out, p=0.1):
53
+ super().__init__()
54
+ self.net = nn.Sequential(nn.Linear(d_in, d_h), nn.ReLU(),
55
+ nn.Dropout(p), nn.Linear(d_h, d_out))
56
+ def forward(self, x):
57
+ return self.net(x)
58
+
59
+ model = MLP(784, 256, 10).to(device)
60
+ ```
61
+
62
+ **`torch.compile`** — wrap the model once and get a JIT-optimized (Dynamo→Inductor) graph, often a
63
+ real speedup with no code change: `model = torch.compile(model)`. Modes: `"default"` (balanced),
64
+ `"reduce-overhead"` (CUDA graphs, best for small batches), `"max-autotune"` (Triton autotuning,
65
+ slowest to warm up). First step(s) are slow — that's compilation, not your model. Keep it *after*
66
+ `.to(device)` and before the loop. (`pytorch.org/docs/stable/generated/torch.compile.html`)
67
+
68
+ ## 2. The training loop — and its classic bugs
69
+
70
+ The whole game is five ordered steps. Get the order or the resets wrong and it fails *silently* —
71
+ no exception, just a model that won't learn.
72
+
73
+ ```python
74
+ model.train() # Dropout/BN in TRAIN mode
75
+ for epoch in range(epochs):
76
+ for x, y in train_loader:
77
+ x, y = x.to(device), y.to(device)
78
+ optimizer.zero_grad(set_to_none=True) # clear LAST step's grads
79
+ out = model(x) # forward
80
+ loss = loss_fn(out, y) # loss (raw logits in, e.g. CrossEntropyLoss)
81
+ loss.backward() # autograd fills .grad (ACCUMULATES)
82
+ optimizer.step() # update weights from .grad
83
+ scheduler.step() # if a per-step scheduler
84
+ ```
85
+
86
+ The load-bearing traps (all in the gotchas table, worth stating once here):
87
+
88
+ - **Missing `optimizer.zero_grad()` → gradients silently add up across batches.** PyTorch
89
+ *accumulates* `.grad` by design (so you can split a batch); if you never zero it, every step
90
+ updates on the sum of all prior batches' grads and training destabilizes. Zero every step.
91
+ (`pytorch.org/tutorials` optimization tutorial; `torch.optim` docs.) `set_to_none=True` is the
92
+ default in modern Torch and is slightly faster.
93
+ - **`CrossEntropyLoss` eats raw logits.** It applies `log_softmax` internally — do **not** put a
94
+ `Softmax`/`Sigmoid` before it or you double-activate and learning stalls. Same for
95
+ `BCEWithLogitsLoss`.
96
+ - **Accumulating `loss` without `.item()` leaks memory.** `total += loss` keeps the whole autograd
97
+ graph alive across the epoch. Use `total += loss.item()` (or `.detach()`).
98
+ - **`backward()` twice on one graph** raises unless you meant it (`retain_graph=True`) — usually a
99
+ sign you forgot to zero or re-ran forward.
100
+
101
+ ## 3. Mixed precision (AMP)
102
+
103
+ Run forward/loss in low precision for speed and memory, keep a master copy for the update. Two
104
+ pieces: `torch.autocast` (picks per-op precision) + `torch.amp.GradScaler` (rescues fp16 gradients
105
+ from underflow). Verified against `pytorch.org/docs/stable/notes/amp_examples.html`.
106
+
107
+ ```python
108
+ scaler = torch.amp.GradScaler("cuda") # current namespace (not torch.cuda.amp)
109
+ for x, y in train_loader:
110
+ x, y = x.to(device), y.to(device)
111
+ optimizer.zero_grad(set_to_none=True)
112
+ with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
113
+ out = model(x) # forward + loss ONLY under autocast
114
+ loss = loss_fn(out, y)
115
+ scaler.scale(loss).backward() # backward OUTSIDE autocast, on scaled loss
116
+ scaler.step(optimizer) # unscales, skips step if inf/NaN grads
117
+ scaler.update() # adjusts the scale for next step
118
+ ```
119
+
120
+ **bf16 vs fp16 — the choice that matters:**
121
+
122
+ | dtype | Exponent range | Needs GradScaler? | Use when |
123
+ |---|---|---|---|
124
+ | **bf16** (`bfloat16`) | same as fp32 | **No** (range can't underflow) | Ampere+ (A100/H100/…) or CPU — **prefer this**, it's the robust default |
125
+ | **fp16** (`float16`) | narrow → underflows | **Yes** — scaler is mandatory | older GPUs without bf16; squeeze extra range with the scaler |
126
+
127
+ - With **bf16 you can skip `GradScaler`** entirely (`GradScaler(enabled=False)` or just don't use
128
+ it) — its whole job is fp16 underflow. With **fp16 the scaler is not optional.**
129
+ - **Gradient clipping under AMP:** `scaler.unscale_(optimizer)` first, *then*
130
+ `torch.nn.utils.clip_grad_norm_(...)`, then `scaler.step`. Clipping scaled grads clips the wrong
131
+ magnitude.
132
+ - Autocast wraps **forward + loss only**. Never wrap `backward()`.
133
+
134
+ ## 4. Optimizers and LR schedules
135
+
136
+ - **`torch.optim.AdamW`** is the default for most modern nets (transformers, and increasingly
137
+ vision): Adam with *decoupled* weight decay (correct L2, unlike plain `Adam(weight_decay=)`).
138
+ **SGD + momentum + Nesterov** still wins on many CNNs and generalizes well — worth trying.
139
+ - **Don't weight-decay everything.** Biases and Norm (LayerNorm/BatchNorm) weights should get
140
+ `weight_decay=0`; use two param groups. Decaying them hurts with no upside.
141
+ - **The LR is the hyperparameter.** Too high → loss NaNs or oscillates; too low → crawls. A warmup
142
+ then cosine decay is the reliable modern recipe.
143
+
144
+ ```python
145
+ opt = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=0.01, betas=(0.9, 0.999))
146
+
147
+ # Warmup (linear ramp) THEN cosine decay, composed with SequentialLR — verified 2.x API.
148
+ from torch.optim.lr_scheduler import LinearLR, CosineAnnealingLR, SequentialLR
149
+ warmup = LinearLR(opt, start_factor=0.1, total_iters=500) # 500 steps ramp-in
150
+ cosine = CosineAnnealingLR(opt, T_max=total_steps - 500, eta_min=3e-5)
151
+ scheduler = SequentialLR(opt, [warmup, cosine], milestones=[500]) # switch at step 500
152
+ # call scheduler.step() every STEP here (T_max/total_iters are in steps).
153
+ ```
154
+
155
+ Alternatively `OneCycleLR(opt, max_lr=..., total_steps=...)` bakes warmup+anneal into one
156
+ scheduler. **Match `step()` cadence to the scheduler's units** — per-step schedulers stepped once
157
+ per epoch (or vice-versa) silently give the wrong curve. (`pytorch.org/docs/stable/optim.html`)
158
+
159
+ ## 5. Distributed training — pick by what doesn't fit
160
+
161
+ One line each on *when*; mechanics and launch commands in `references/distributed.md`.
162
+
163
+ - **DDP** (`torch.nn.parallel.DistributedDataParallel`) — replicate the **whole model** on each GPU,
164
+ all-reduce grads every step. Use when **the model fits on one GPU** and you just want more
165
+ throughput / a larger effective batch. Default choice; one process per GPU via `torchrun`.
166
+ - **FSDP2** (`torch.distributed.fsdp.fully_shard`) — **shard** parameters, gradients, and optimizer
167
+ states across GPUs (gather just-in-time). Use when **the model does NOT fit on one GPU.** FSDP2 is
168
+ the current DTensor-based, per-parameter API; apply it bottom-up (wrap layers, then the root).
169
+ - **DeepSpeed ZeRO** (external Microsoft library, not in core Torch) — config-driven sharding:
170
+ **ZeRO-1** shards optimizer states, **ZeRO-2** adds gradients, **ZeRO-3** adds parameters
171
+ (≈ FSDP), plus CPU/NVMe **offload**. Use when you want offload or config-first scaling, or already
172
+ live in the DeepSpeed/Accelerate ecosystem. Verify the current version — it moves independently.
173
+
174
+ Rule of thumb: fits on one GPU → **DDP**; too big → **FSDP2** (or ZeRO-3); need to offload to
175
+ CPU/NVMe → **ZeRO**.
176
+
177
+ ## 6. Regularization, checkpointing, reproducibility
178
+
179
+ **Regularization** (reach for these when val loss diverges from train — i.e. overfitting):
180
+ weight decay (AdamW), `nn.Dropout`, data augmentation, early stopping on a val metric, label
181
+ smoothing (`CrossEntropyLoss(label_smoothing=0.1)`), and gradient clipping for stability (not
182
+ generalization).
183
+
184
+ **Checkpointing — save `state_dict`s, not the model object.** Pickling the module ties the file to
185
+ your code layout and breaks on refactor.
186
+
187
+ ```python
188
+ torch.save({"epoch": epoch,
189
+ "model": model.state_dict(), # DDP/FSDP: model.module.state_dict(), rank 0 only
190
+ "optimizer": opt.state_dict(),
191
+ "scheduler": scheduler.state_dict(),
192
+ "scaler": scaler.state_dict()}, # AMP scale must survive a resume
193
+ "ckpt.pt")
194
+ # Resume: load model FIRST, then optimizer/scheduler; move optimizer state to device if needed.
195
+ ```
196
+
197
+ Save optimizer + scheduler + scaler too, or a resumed run restarts its LR schedule and loss scale.
198
+
199
+ **Reproducibility — seed everything, and know the ceiling.** From
200
+ `pytorch.org/docs/stable/notes/randomness.html`, quoted: *"Completely reproducible results are not
201
+ guaranteed across PyTorch releases, individual commits, or different platforms. Furthermore,
202
+ results may not be reproducible between CPU and GPU executions, even when using identical seeds."*
203
+ So bit-exact reproducibility is a debugging/regression tool, not a guarantee.
204
+
205
+ ```python
206
+ import random, numpy as np, torch
207
+ seed = 42
208
+ random.seed(seed); np.random.seed(seed); torch.manual_seed(seed) # covers CPU + all CUDA devices
209
+ torch.use_deterministic_algorithms(True) # errors on ops with no deterministic impl
210
+ torch.backends.cudnn.deterministic = True
211
+ torch.backends.cudnn.benchmark = False # benchmark=True picks fastest algo → nondeterministic
212
+ # For CUDA >= 10.2, deterministic matmul also needs, set BEFORE launch:
213
+ # export CUBLAS_WORKSPACE_CONFIG=:4096:8
214
+ ```
215
+
216
+ DataLoader workers need their own seeding (each worker forks its RNG), via `worker_init_fn` +
217
+ a seeded `generator` — full snippet in `references/training-recipes.md`. Determinism costs speed
218
+ (`benchmark=False` disables autotuned convs).
219
+
220
+ ## Guardrails (the silent killers)
221
+
222
+ - **`optimizer.zero_grad()` every step.** Skipping it makes `.grad` accumulate across batches — no
223
+ error, just diverging training. (`torch.optim` / optimization tutorial, pytorch.org)
224
+ - **`model.eval()` + `torch.no_grad()` at inference/validation.** Forgetting `eval()` leaves Dropout
225
+ dropping and BatchNorm using *batch* stats instead of running stats, so val numbers are wrong;
226
+ forgetting `no_grad()` builds the autograd graph and can OOM. Flip back to `model.train()` after.
227
+ (`nn.Module.eval` / autograd docs, pytorch.org)
228
+ - **Determinism is not guaranteed across releases/platforms/CPU-vs-GPU** even with identical seeds —
229
+ seed for debugging, don't promise bit-exactness. (randomness note, pytorch.org)
230
+ - **fp16 without `GradScaler`** underflows to zero grads → no learning. bf16 doesn't need it.
231
+ - **`CrossEntropyLoss`/`BCEWithLogitsLoss` take raw logits** — no Softmax/Sigmoid before them.
232
+ - **Everything on the same device** — a stray CPU tensor in a CUDA graph is a hard error you'll hit
233
+ fast; `.to(device)` inputs, targets, and model.
234
+ - **NaN loss?** LR too high, no AMP scaler on fp16, unclipped exploding grads, or a `log(0)`/`0/0`
235
+ in a custom loss. Bisect: drop LR 10×, clip grads, switch fp16→bf16.
236
+
237
+ ## Related skills
238
+
239
+ - [`finetuning`](../finetuning/SKILL.md) — adapting a **pretrained LLM** (LoRA/QLoRA, SFT via
240
+ trl/peft). If the base is a foundation model you're specializing, that's the skill; this one is
241
+ general/from-scratch net training.
242
+ - [`machine-learning`](../machine-learning/SKILL.md) — classic/**tabular** (sklearn, GBDT). No
243
+ autograd, no GPU loop.
244
+ - [`nlp`](../nlp/SKILL.md) — tokenization, NLP **task** modeling and metrics. Route text task
245
+ specifics there; route the raw training loop back here.
246
+ - [`python`](../python/SKILL.md) — env/packaging, testing, general Python hygiene under the model
247
+ code.
248
+
249
+ ## Checklist
250
+
251
+ - [ ] Right skill: from-scratch/vision/custom net in PyTorch (not finetuning / ML / nlp).
252
+ - [ ] Loop has all five steps in order; `zero_grad(set_to_none=True)` every step.
253
+ - [ ] Loss takes raw logits (no double activation); running loss uses `.item()`.
254
+ - [ ] `model.train()` for training; `model.eval()` **and** `torch.no_grad()` for val/inference.
255
+ - [ ] AMP: `torch.autocast` on forward+loss only; fp16 → `GradScaler`, bf16 → skip it; clip after
256
+ `unscale_`.
257
+ - [ ] AdamW (decoupled decay) with no weight decay on bias/Norm params; LR warmup→cosine, `step()`
258
+ cadence matches scheduler units.
259
+ - [ ] Multi-GPU chosen by fit: DDP (fits) vs FSDP2 (doesn't) vs ZeRO (offload/config).
260
+ - [ ] Checkpoint saves model+optimizer+scheduler+scaler `state_dict`s; resume loads model first.
261
+ - [ ] Seeds set; determinism flags on if needed, with the "not guaranteed across releases/devices"
262
+ caveat acknowledged.
263
+ - [ ] Version claims hedged to "PyTorch 2.x (~2.13, verify)"; no hard minor pin presented as current.
@@ -0,0 +1,11 @@
1
+ # Evals — deep-learning
2
+
3
+ Routing and capability checks for a human or LLM grader, not an automated test suite. To run them:
4
+ read each `should_trigger` prompt and confirm an agent would reach for `deep-learning` (PyTorch
5
+ training/loop/AMP/distributed/reproducibility); read each `should_not_trigger` prompt and confirm it
6
+ routes to the named sibling (`finetuning`, `machine-learning`, `nlp`, `vllm`, `python`) for the
7
+ stated reason. Then grade the `capability` scenario against every `must_include` bullet — the
8
+ correct five-step loop with per-step `zero_grad`, AMP with the bf16/fp16 + scaler rule, `model.eval()`
9
+ + `no_grad()` at validation, AdamW + warmup→cosine, checkpoint hygiene, and the "determinism is not
10
+ guaranteed across releases/platforms/devices" caveat. A pass covers all routing cases plus full
11
+ rubric coverage on the capability scenario.