Skip to content

feat: Add DGX Spark cluster support, TP awareness, use-case/availability filters, and live benchmarking#181

Closed
michaeljabbour wants to merge 325 commits into
AlexsJones:mainfrom
michaeljabbour:feature/all-spark-features
Closed

feat: Add DGX Spark cluster support, TP awareness, use-case/availability filters, and live benchmarking#181
michaeljabbour wants to merge 325 commits into
AlexsJones:mainfrom
michaeljabbour:feature/all-spark-features

Conversation

@michaeljabbour

Copy link
Copy Markdown
Contributor

Summary

This PR adds several features to llmfit from the llmfit-spark fork, all applied additively on top of current upstream/main. The diff is +2,408 / -75 across 14 files — purely additive.


Features

1. DGX Spark Cluster Support (llmfit cluster)

  • New cluster subcommand with init, status, remove actions
  • New llmfit-core/src/cluster.rs (542 lines): ClusterSpecs struct, Ray API discovery, TOML config persistence
  • --cluster / --no-cluster global flags to override hardware detection with cluster resources
  • Cluster mode replaces local GPU detection with aggregated multi-node VRAM for fit analysis
  • TUI system bar shows cluster info when cluster mode is active
  • vLLM selected as inference runtime in cluster mode; tensor-parallel notes added to fit output

2. Tensor Parallelism Awareness

  • New supports_tp(tp_size) and valid_tp_sizes() methods on LlmModel
  • num_attention_heads / num_key_value_heads fields added to LlmModel (optional, heuristic inference fallback)
  • TP filter in TUI: cycle All → TP=2 → TP=3 → TP=4 with x key
  • TP column in TUI table showing max valid TP degree
  • TP compatibility line in detail view (green when cluster TP matches, yellow otherwise)
  • TP penalty (0.9×) added to speed estimation formula

3. Use-Case Filter + Availability Filter

  • Cycling use-case filter (u key): All → General → Coding → Reasoning → Chat → Multi → Embed
  • Availability filter (a key): All → GGUF Avail → Installed (checks llmfit-core GGUF source metadata)
  • Both filters compose with existing provider/fit/capability filters in apply_filters()

4. Year Sort Column

  • SortColumn::ReleaseYear — sort by release year (newest first), secondary sort by score
  • Year column in TUI table
  • s key cycles now includes Year in the rotation

5. Live Inference Benchmarking (llmfit bench)

  • New llmfit-core/src/bench.rs (610 lines): BenchTarget enum, BenchResult, provider-specific benchmark functions
  • Supports Ollama, vLLM (OpenAI-compat), and MLX endpoints
  • Auto-detection of running providers (--provider auto)
  • --all flag benchmarks every discovered model across all running providers
  • --url flag overrides the provider endpoint
  • JSON output (--json) for tool/agent integration
  • discover_all_targets() queries running Ollama/vLLM/MLX instances

Files Changed

File Change
llmfit-core/src/cluster.rs New — cluster management (542 lines)
llmfit-core/src/bench.rs New — live benchmarking (610 lines)
llmfit-core/src/models.rs TP head counts, supports_tp(), valid_tp_sizes()
llmfit-core/src/fit.rs Cluster/TP run mode, vLLM runtime, TP speed penalty
llmfit-core/src/hardware.rs cluster_mode, cluster_node_count, total_gpu_vram_gb on SystemSpecs
llmfit-core/src/lib.rs Module exports for cluster and bench
llmfit-core/Cargo.toml toml dependency for cluster config persistence
llmfit-tui/src/main.rs cluster, bench subcommands; --cluster/--no-cluster flags
llmfit-tui/src/tui_app.rs TP/use-case/availability filters, tp_filter field
llmfit-tui/src/tui_ui.rs TP column, Year column, filter widgets, cluster system bar
llmfit-tui/src/tui_events.rs x key (TP filter), a key (availability filter)
llmfit-tui/src/display.rs Minor display updates
README.md Documentation for all new features
Cargo.lock Lock file update

Notes

  • All changes are additive — no existing functionality was removed or broken
  • The ClusterSpecs config is stored at ~/.config/llmfit/cluster.toml
  • Benchmarking requires a running provider (Ollama/vLLM/MLX); llmfit bench exits cleanly if none found
  • TP head count heuristics cover Qwen, Llama, DeepSeek, Mistral, Gemma, Phi families; unknown models use param-count defaults

counterposition and others added 30 commits February 20, 2026 11:52
Add MlxProvider implementing ModelProvider for Apple MLX framework.
Detects MLX availability via server probe and mlx_lm Python package
check. Scans ~/.cache/huggingface/hub/ for installed mlx-community
models. Supports pulling via huggingface-cli with Python fallback.

Wire into TUI for multi-provider installed-model detection: models
show as installed if found in either Ollama or MLX. Provider-aware
download selects MLX for MLX-runtime models, Ollama otherwise.

- Add MlxProvider with is_available(), installed_models(), start_pull()
- Add hf_name_to_mlx_candidates() with ~27 model mappings + heuristic
- Add is_model_installed_mlx() and mlx_pull_tag() helpers
- Add mlx_available, mlx_installed, mlx fields to App
- Update start_download() to choose provider based on ModelFit::runtime
- Update refresh_installed() to query both providers
- Add 3 new tests for MLX name matching and cache detection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trying a Python fallback when huggingface-cli fails, we now
provide actionable feedback telling users to install huggingface-cli using
uv tool install 'huggingface_hub[cli']'. This avoids issues with global
Python package installation being a logistical minefield.
Display MLX vs llama.cpp runtime distinction across all output modes
so users can see and act on the inference runtime selection.

TUI changes:
- Add MLX status in system bar alongside Ollama
- Add Runtime line in detail view with estimated tok/s
- Show per-provider installed status (✓ Ollama  ✓ MLX)
- Enable d/i/r keybindings when any provider is available

CLI changes:
- Add Runtime column to CLI table output
- Add runtime info to display_model_detail()
- Add "runtime" and "runtime_label" fields to JSON output
- Add --runtime filter to recommend subcommand (mlx, llamacpp, any)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
APU integrated GPUs like 'AMD Radeon(TM) Graphics' were matching the
generic 'radeon' fallback and getting 8 GB estimated VRAM, when they
typically have only 0.5 GB dedicated VRAM. This caused the iGPU to be
ranked above discrete GPUs, affecting model recommendations.

Now detect APU iGPUs by checking for 'radeon/amd' + 'graphics/igpu'
without a discrete model number (RX/HD/R5/R7/R9) and return 0.5 GB.

Fixes AlexsJones#25
…m-estimation

fix: correctly estimate VRAM for APU integrated GPUs
Signed-off-by: Alex <alexsimonjones@gmail.com>
Signed-off-by: Alex <alexsimonjones@gmail.com>
…ches--main--components--llmfit

chore(main): release llmfit 0.3.5
Signed-off-by: Alex <alexsimonjones@gmail.com>
…ches--main--components--llmfit

chore(main): release llmfit 0.3.6
Signed-off-by: Alex <alexsimonjones@gmail.com>
…ches--main--components--llmfit

chore(main): release 0.3.7
Signed-off-by: Alex <alexsimonjones@gmail.com>
Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxes53235@gmail.com>
Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxesyes3inatrenchcoat@gmail.com>
feat: MLX-native inference support for Apple Silicon
The name 'huggingface-cli' is deprecated.
Their CLI is now called 'hf': https://huggingface.co/docs/huggingface_hub/en/guides/cli
fix: invoke hf instead of huggingface-cli
Restructure single-crate project into Cargo workspace:
- llmfit-core: core library (hardware detection, model fitting, providers)
- llmfit-tui: CLI/TUI binary (unchanged user experience)
- llmfit-desktop: macOS desktop app via Tauri 2

The workspace split enables the desktop app to reuse core logic
while keeping the CLI/TUI as the default build target.

Moved SortColumn to core crate for shared use across frontends.

Desktop app features:
- System specs display (RAM, CPU, GPU)
- Model compatibility table with fit scoring
- Dark theme UI using project icon from assets/icon.svg
- Tauri 2 with minimal permissions

No changes to data files — moved as-is via git mv.

Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxes53235@gmail.com>
Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxesyes3inatrenchcoat@gmail.com>
- Remove llama title/subtitle header from desktop app
- Show total + available RAM separately
- Render all detected GPUs with VRAM, backend, and count
- Show unified memory indicator for Apple Silicon
- Responsive grid layout for system spec cards

Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxesyes3inatrenchcoat@gmail.com>
…t/workspace-and-desktop-v2

feat: workspace restructure + Tauri desktop app
Adds build-desktop job that builds Tauri desktop app for both
aarch64-apple-darwin and x86_64-apple-darwin targets.
DMGs are uploaded alongside CLI tarballs in GitHub Releases.

Signed-off-by: Three Foxes (in a Trenchcoat) <threefoxesyes3inatrenchcoat@gmail.com>
…t/workspace-and-desktop-v2

ci: build macOS desktop app (.dmg) in release workflow
AlexsJones and others added 3 commits March 10, 2026 17:19
Document Docker usage in README.md
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
AlexsJones and others added 12 commits March 11, 2026 01:43
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…port

feat: add AWQ/GPTQ support with vLLM inference runtime
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Add cluster-aware hardware detection and model scoring for DGX Spark
clusters (2-3+ nodes with GB10 Blackwell GPUs connected via QSFP).

New features:
- `llmfit cluster init` — interactive setup with Ray API auto-discovery
- `llmfit cluster status` — show cluster config and Ray connectivity
- `llmfit cluster remove` — remove saved cluster configuration
- `--cluster` / `--no-cluster` flags to control cluster mode
- Auto-loads saved config from ~/.config/llmfit/cluster.toml
- New VLlm inference runtime and TensorParallel run mode
- Cluster-aware TUI system bar showing aggregated resources
- JSON output includes cluster metadata

Cluster specs per DGX Spark node:
- NVIDIA GB10 Grace Blackwell (1 PFLOP FP4 with sparsity)
- 128 GB LPDDR5x unified memory (~85 GB usable for models)
- 20-core ARM CPU (10× X925 + 10× A725)
- QSFP 200 Gb/s interconnect for NCCL tensor parallelism

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three changes in this commit:

1. Remove PII: Changed default head node IP from user's actual network
   address to generic 10.0.0.1 placeholder.

2. Use case filter: Added cycle filter [u] in TUI filter bar for
   General/Coding/Reasoning/Chat/Multimodal/Embedding. Shortened
   search bar to accommodate.

3. TP compatibility: Models now report valid tensor parallelism sizes
   based on attention head counts. In cluster mode, llmfit automatically
   selects the best TP degree that the model supports (e.g., TP=2 for
   most models with 64 heads on a 3-node cluster, since 64 is not
   divisible by 3). Notes explain free GPUs and suggest PP fallback.
   Includes head count inference for Qwen, Llama, DeepSeek, Mistral,
   Gemma, Phi, and MiniMax families.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sort by year: new "Year" sort option (press [s] to cycle) groups
  models by release year, newest first. Date column now shows year
  instead of YYYY-MM to save space.

- TP column: new "TP" column in the table shows valid tensor
  parallelism sizes for each model (e.g., "2,4,8"). In cluster mode,
  green = supports full cluster TP, yellow = supports TP=2 only.

- TP filter: press [x] to cycle through All → TP=2 → TP=3 → TP=4.
  Filters to only show models compatible with that TP degree. Useful
  for finding which models can actually use all your cluster GPUs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `bench` subcommand measures actual inference performance against
live providers:

  llmfit bench                        # auto-detect provider and model
  llmfit bench --model qwen3-32b      # specific model
  llmfit bench --provider vllm        # target vLLM cluster
  llmfit bench --runs 5 --json        # multiple runs, JSON output

Supports three backends:
- Ollama: uses /api/generate with native timing (eval_duration,
  prompt_eval_duration) for precise TPS and TTFT
- vLLM: uses /v1/chat/completions (OpenAI-compatible) with
  wall-clock timing and usage token counts
- MLX: same OpenAI-compatible protocol

Auto-detection priority: cluster config (vLLM) → Ollama → MLX.
Includes warmup run, configurable number of benchmark runs, and
statistical summary (avg/min/max TPS, avg TTFT, avg latency).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- `llmfit bench --all` discovers and benchmarks every model across
  all reachable providers (Ollama, vLLM, MLX). Shows per-model results
  plus a comparison table at the end.

- `llmfit bench --url http://host:port` overrides the provider URL,
  useful when cluster config IP doesn't match or for ad-hoc testing.

- Auto-detects models from vLLM /v1/models endpoint when --url is
  provided, no need to also specify --model.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comprehensive README update covering all llmfit-spark features:

- Renamed project header to llmfit-spark with upstream attribution
- DGX Spark cluster support: init, status, remove, config format
- Tensor parallelism compatibility: TP column, filter, head count math
- Benchmarking: bench command, --all, --url, metrics explanation
- Updated keybindings table with u (use case), x (TP filter)
- Updated project structure to reflect workspace layout
- Added vLLM and TensorParallel to run modes and speed constants
- Updated dependencies table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix non-exhaustive RunMode::TensorParallel match (fit.rs, serve_api.rs, desktop)
- Fix keybinding collision: clear_compare_mark moved to 'X'
- Eliminate double ClusterSpecs::load() in detect_specs
- Replace wrapping_add with checked_add in increment_ip
- Add warmup error handling, IP validation, node count feedback
- Make vLLM port configurable via VLLM_PORT env var
- Document DGX Spark constants and TTFT estimation
- Add 38 unit tests (models TP, cluster, bench)
- Rebase README: remove fork branding, preserve sympozium link
- Fix contradictory streaming comment in bench.rs
@michaeljabbour

Copy link
Copy Markdown
Contributor Author

Closing this PR — split into 3 focused PRs

Thanks for the thorough review @AlexsJones! We noticed several of our original features have been independently implemented in main since this PR was opened:

Thank you for integrating these — the implementations look great.

We've rebased the remaining unique features onto current main (v0.8.2) and split them into 3 smaller, focused PRs that address all your original review feedback:

  1. feat: add tensor parallelism awareness for multi-GPU model fitting #277 — Tensor Parallelism Awarenesssupports_tp(), valid_tp_sizes(), TP filter in TUI, RunMode::TensorParallel with 0.9× speed penalty
  2. feat: add llmfit bench for live inference benchmarking #278 — Inference Benchmarking (llmfit bench) — Live TPS/TTFT/latency benchmarking against Ollama, vLLM, and MLX. TTFT is now Option<f64> (None for non-streaming providers). Warmup errors properly reported.
  3. feat: add remote GPU cluster support for multi-node model fitting #279 — Remote GPU Cluster Support — Reworked to be hardware-agnostic (not DGX Spark-specific). Users specify node IPs + VRAM/RAM/cores for any GPU hardware. Ray auto-discovery optional. IP validation, proper error messages.

All original review items addressed across the 3 PRs:

Review item Fix
Non-exhaustive match on RunMode TensorParallel added to all matches
Keybinding collision (x key) TP filter uses Shift-T
Double ClusterSpecs::load() Single load in detect_specs
increment_ip overflow checked_add with error return
Stale streaming comment Removed; TTFT is None for non-streaming
TTFT presented as fact Changed to Option<f64>
Warmup errors silently discarded Returns Err with message
No IP validation Proper IPv4 octet + hostname validation
Node count silent default Returns error on invalid input
Missing tests Added for TP, cluster, IP validation, bench summary
Hardcoded vLLM port Reads VLLM_PORT env var
README rebranding Not included
DGX Spark hardcoded constants Removed — fully user-configurable

Closing this PR in favor of the focused ones above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.