fetch_models.py - HuggingFace Model Categorizer
fetch_models.py
Comprehensive GGUF Model Fetcher and Categorizer
Fetches GGUF models from all major quantization uploaders on HuggingFace. Filters by param count (0.1B-14B). Categorizes by keyword rules. Anything not matched goes into Auto/
via a second-pass clusterer.
Overview
fetch_models.py is a production-grade tool that solves a critical problem: How do you make sense of thousands of LLM models on HuggingFace?
It fetches models from all major GGUF quantization uploaders, intelligently categorizes them, and produces a clean, structured output that can be used to power model selection interfaces, analysis tools, or any application that needs to work with the LLM ecosystem at scale.
Problem Statement
As of mid-2026, there are:
- 20+ major GGUF quantization uploaders on HuggingFace
- 500+ models per uploader
- 10,000+ total GGUF models
- No standard categorization scheme
- Constantly changing model landscape
Manual categorization is:
- ❌ Time-consuming
- ❌ Error-prone
- ❌ Always out of date
- ❌ Doesn’t scale
fetch_models.py automates this entirely.
Features
1. Comprehensive Coverage
Fetches from 23 major uploaders:
UPLOADERS = [
"Lewdiculous", "QuantFactory", "brittlewis12", "RichardErkhov",
"second-state", "mradermacher", "lmstudio-community", "MaziyarPanahi",
"bartowski", "TheBloke", "unsloth", "mmnga", "SanctumAI",
"OuteAI", "crusoeai", "NousResearch", "instructlab",
"tiiuae", "stabilityai", "xtuner", "mlabonne",
"adrienbrault", "tensorblock", "ChaoticNeutrals",
]
2. Intelligent Categorization
Two-stage categorization system:
Stage 1: Primary Categories (15 categories, first match wins)
| Category | Matching Patterns | Examples |
|---|---|---|
| Audio | tts, speech, voice, whisper, bark, oute, text-to-speech | Whisper, Bark, Outé |
| Vision | vl, vision, llava, moondream, minicpm, bakllava, visual, idefics, paligemma, internvl, pixmo, image-text, multimodal, qvq | LLaVA, MiniCPM-V |
| Coding | coder, starcoder, codellama, codegemma, deepseek-coder, octocoder, codestral, santacoder, wizardcoder, phind, codegeex, openhands, deepseek-v2, deepseek-v3 | StarCoder2, DeepSeek-Coder |
| Reasoning | -r1, deepseek-r, qwq, reasoning, math, skywork, -o1, longwriter, thinking, cot, science, deepscaler, reflection, sky-t1, prm, orm, verif | DeepSeek-R1, QWQ, Skywork |
| Medical | medical, clinical, health, nurse, doctor, medllama, biomed, pubmed, med-, meditron, medialpaca | MedLlama, Meditron |
| Legal | legal, law, lawyer, juris, contracts, court, attorney | LawLlama, JurisAI |
| Finance | finance, financial, trading, econom, bloomberg, stock | FinLlama, BloombergGPT |
| Roleplay | roleplay, rpg, persona, narrative, fiction, novel, dungeon, tavern, simulator | TavernAI |
| Uncensored | uncensored, unfiltered, unrestricted, adult, nsfw, lewdplay, gemmasutra, eris, stheno, spicy, erotic, unchained, abliterat, venice | UncensoredLlama |
| Creative | dolphin, hermes, openchat, zephyr, capybara, wizard, neural, samantha, mytho, airoboros, manticore, orca, platypus, starling, neuralhermes, beluga, chimera | Dolphin, Hermes, Zephyr |
| Long Context | long, context, 128k, 256k, extended, infini, yarn, longchat | LongLlama, Infini, Yarn |
| Multilingual | multilingual, bloom, xglm, arabic, japanese, korean, german, french, spanish, hindi, turkish, aya, command-r, c4ai, glm, glm-4 | Bloom, XGLM, GLM-4 |
| Merged | merge, franken, slerp, ties, dare, hybrid, fusion, amalgam, supernova | FrankenLlama, Supernova |
| Tiny | smollm, tinyllama, smol-, 135m, 360m, phi-1, edge, mobile, nano, on-device | TinyLlama, Phi-1, SmolLM |
| Instruct | instruct, chat, assistant, sft, rlhf, dpo, orpo, chatqa, nemotron, orchestrat, phi-4, phi-3, phi-2 | Llama-3-Instruct, Phi-3 |
Stage 2: Auto-Categorization (14 subcategories)
For models that don’t match primary categories:
| Category | Matching Patterns |
|---|---|
| Auto/Gemma | gemma |
| Auto/Llama | llama |
| Auto/Qwen | qwen |
| Auto/Mistral | mistral, mistrale |
| Auto/Phi | phi |
| Auto/Falcon | falcon |
| Auto/DeepSeek | deepseek |
| Auto/GLM | glm |
| Auto/Reka | reka |
| Auto/Nvidia | nvidia, nemotron |
| Auto/SPPO | sppo |
| Auto/Command | command |
| Auto/Yi | yi- |
| Auto/Other | (catch-all) |
3. Smart Parameter Extraction
Handles complex parameter notation:
def extract_params(text):
text = text.replace("_", "-")
# Handle MoE notation like 30B-A3B (active params)
moe = re.search(r'(\d+(?:\.\d+)?)[Bb]-[Aa]\d', text)
if moe:
return float(moe.group(1)) # Use total, not active
# Standard notation: 7B, 13B, 70B
matches = re.findall(r'(\d+(?:\.\d+)?)\s*([BbMm])(?:[^a-zA-Z]|$)', text)
for num, unit in matches:
val = float(num)
if unit.upper() == 'M':
val = val / 1000.0
if val > 200: # Exclude models > 200B
continue
return val
return None
4. Intelligent File Selection
For each model repository with multiple files, picks the best GGUF file:
def pick_sibling(siblings):
# Get GGUF files
names = [s.get("rfilename", "") for s in siblings
if s.get("rfilename", "").endswith(".gguf")]
def bad(n):
# Exclude: 4/4, 4/8, 8/8 quantizations, fp16, f32, bf16, slash-containing
return any(x in n for x in
["_4_4", "_4_8", "_8_8", "-fp16", "f16.", "f32.", "bf16.", "/"])
# Priority order: Q4_K_M > Q4_K_S > Q4_0 > other Q4 > others
for pat in ["Q4_K_M", "Q4_K_S", "Q4_0"]:
for n in names:
if pat in n and not bad(n):
return n
for n in names:
if "Q4" in n and not bad(n):
return n
for n in names:
if not bad(n) and not any(x in n for x in ["f16","f32","bf16","Q8","Q6","Q5"]):
return n
return None
5. Human-Readable Size Estimation
def human_size(filename, params):
if params is None:
return "?"
# Bits per byte for different quantizations
bpb = {"Q2":0.28e9,"Q3":0.38e9,"Q4":0.50e9,
"Q5":0.62e9,"Q6":0.75e9,"Q8":1.00e9}
# Find quantization in filename
quant = next((k for k,v in bpb.items() if k in filename), "Q4")
bytes = params * bpb.get(quant, 0.50e9)
if bytes >= 1e9:
return f"{bytes/1e9:.1f}GB"
else:
return f"{bytes/1e6:.0f}MB"
Usage
Basic Usage
# Fetch all models, cache in ./cache, output to models.txt
python3 fetch_models.py ./cache models.txt
Arguments
| Argument | Description | Required |
|---|---|---|
<cache_dir> | Directory to cache fetched JSON | Yes |
<model_list_out> | Output file path | Yes |
Output Format
Pipe-delimited format for easy parsing:
# llama-menu model list — fetched from HuggingFace
# NAME|CATEGORY|REPO|FILE|SIZE|LIKES|DOWNLOADS|DATE
Llama-3-8B-Instruct|Instruct|meta-llama/Meta-Llama-3-8B-Instruct-GGUF|Q4_K_M.gguf|6.8GB|15000|85000|2026-07-15
Mistral-7B-Instruct|Instruct|TheBloke/Mistral-7B-Instruct-v0.2-GGUF|Q4_K_M.gguf|4.1GB|12000|75000|2026-07-10
Phi-3-mini-4k-instruct|Instruct|mradermacher/Phi-3-mini-4k-instruct-4k-GGUF|Q4_K_M.gguf|2.1GB|8000|45000|2026-07-20
CodeLlama-7B-Instruct|Coding|TheBloke/CodeLlama-7B-Instruct-GGUF|Q4_K_M.gguf|4.2GB|9000|50000|2026-07-05
DeepSeek-R1|Reasoning|TheBloke/DeepSeek-R1-GGUF|Q4_K_M.gguf|6.5GB|2500|12000|2026-07-25
Example: Filter Coding Models
# Get all coding models
grep "|Coding|" models.txt
# Output:
CodeLlama-7B-Instruct|Coding|TheBloke/CodeLlama-7B-Instruct-GGUF|Q4_K_M.gguf|4.2GB|9000|50000|2026-07-05
StarCoder2-7B|Coding|TheBloke/StarCoder2-7B-GGUF|Q4_K_M.gguf|4.8GB|7000|35000|2026-07-18
DeepSeek-Coder-V2|Coding|TheBloke/DeepSeek-Coder-V2-GGUF|Q4_K_M.gguf|6.7GB|5000|20000|2026-07-22
Example: Integration with Shell Scripts
#!/bin/bash
# Parse model list and create a menu
MODEL_FILE="models.txt"
# Skip header lines
tail -n +3 "$MODEL_FILE" | while IFS='|' read -r name category repo file size likes downloads date; do
# Only show Instruct models
if [ "$category" = "Instruct" ]; then
# Format for display
printf "%-30s %10s %s\n" "$name" "$size" "[$category]"
fi
done
Technical Implementation
Fetching Strategy
def fetch_json(url, timeout=20):
try:
req = urllib.request.urlopen(url, timeout=timeout)
return json.loads(req.read().decode())
except Exception as e:
print(f" WARN {url[:60]}: {e}", flush=True)
return None
# Main fetch loop
for uploader in UPLOADERS:
print(f"\nFetching {uploader}...", flush=True)
url = (f"https://huggingface.co/api/models"
f"?author={uploader}&sort=likes&direction=-1&limit=500&full=true")
data = fetch_json(url)
if not data:
continue
# Process models...
Categorization Logic
def categorize(repo, filename):
haystack = (repo + " " + filename).lower()
# Stage 1: Try primary categories (first match wins)
for cat, patterns in PRIMARY_RULES:
for pat in patterns:
if re.search(pat, haystack):
return cat, False # Matched primary, not auto
# Stage 2: Auto-categorize by architecture
for cat, patterns in AUTO_RULES:
for pat in patterns:
if re.search(pat, haystack):
return cat, True # Auto-categorized
return "Auto/Other", True
Name Shortening
def short_name(repo):
n = repo.split("/")[-1] # Get model name from repo
# Remove common suffixes
for s in ["-GGUF", "-gguf", "-Instruct", "-instruct",
"-it", "-IT", "-chat", "-Chat", "-hf", "-HF"]:
n = n.replace(s, "")
return n[:36] # Truncate to 36 chars
Performance
Runtime
- Network bound — Sequential fetching from 20+ uploaders
- Typical runtime: 2-5 minutes (depends on network speed)
- Models processed: 10,000+ per run
- Output size: ~500KB (compressed)
Caching
- Caches fetched JSON in
<cache_dir>/<uploader>.json - Subsequent runs skip already-fetched uploaders
- Cache persists between runs
Memory Usage
- Peak memory: ~100MB (for storing all models in memory)
- Efficient: Uses generators where possible
- Scalable: Can handle 50,000+ models
Limitations & Future Work
Current Limitations
- Sequential fetching — Could be parallelized for speed
- Static uploader list — Could auto-discover new uploaders
- Basic filtering — Could add more sophisticated filters
- No deduplication — Same model from different uploaders appears multiple times
Future Enhancements
- Parallel fetching — Use async requests for faster downloads
- Model deduplication — Identify and merge duplicate models
- Quality scoring — Rank models by quality metrics
- Compatibility checking — Verify GGUF format compatibility
- Download verification — Check file hashes and integrity
- Incremental updates — Only fetch new/updated models
Source Code
Complete source available:
Or copy directly:
cp /opt/aurora/work/fetch_models.py ./fetch_models.py
chmod +x ./fetch_models.py
License
This tool is provided as-is for educational and production use. No warranty is provided. Use at your own risk.
Related
- LLM Infrastructure Overview — Other LLM tools
- friend.zip - Mobile LLM Project — On-device LLM implementation
- Aurora Tools — How these tools are used
- fetch_context_memory.py — Related memory tool
In a world of model chaos, good categorization is the first step toward understanding.