Releases: Changroro/llmux
Release list
v2.8.1 — 안정성·보안 전면 강화
안정성과 보안을 전면 강화했습니다
이번 릴리스는 llmux의 프로필·config 저장부터 컨테이너 실행, 모델 준비,
모니터링까지 전체 흐름을 다시 점검한 안정화 릴리스입니다.
주요 개선
- 프로필·config·runtime 파일을 함께 안전하게 저장해 동시 수정이나 실패 중
일부 파일만 바뀌는 문제를 방지합니다. - vLLM과 llama.cpp, CLI와 TUI가 같은 설정과 오류 의미를 사용합니다.
- Docker·Hugging Face·Git 조회 실패를 빈 결과나 성공으로 표시하지 않습니다.
- GPU·metrics·benchmark에서 실제 0, 데이터 없음, 조회 실패를 구분합니다.
- image reference, Git URL/branch, Hugging Face 경로, YAML 입력 검증과 secret
redaction을 강화했습니다. - 첫 실행, dev image build, prepare, update, clone/rename/delete 흐름의 여러 오류를
수정했습니다.
업그레이드 후 확인
.env.common은 토큰과 로컬 경로를 포함할 수 있으므로 owner-only 권한이어야
합니다. 기존 파일 권한이 넓다면 한 번만 다음을 실행하세요.
chmod 600 .env.common
llmux env-check직접 편집한 profiles.yaml이나 config YAML에 중복 키 또는 잘못된 타입이 있으면
이제 조용히 덮어쓰지 않고 명시적으로 오류를 냅니다. 표시된 항목을 수정한 뒤
다시 실행하면 됩니다.
검증
- Python 3.10·3.13 전체 테스트 각각 818개 통과
- Compose 필수값 검증, CLI/TUI parity, Ruff와 셸 문법 검사 통과
v2.8.0 — GGUF 다운로드 병렬화 + 대역폭 조절
⚡ GGUF 다운로드 병렬화
prepare 의 llama.cpp 경로가 llama-server -hf (단일 커넥션) 대신
huggingface_hub.snapshot_download 로 받는다. 실측 5MB/s → 56MB/s.
- split GGUF 는 프로필에 첫 shard 만 적어도 형제 shard 를 전부 받는다
- 다운로드는
PREPARE_DOWNLOADER_IMAGE컨테이너에서 돈다 (llama.cpp 이미지에는 huggingface_hub 가 없다). 미설정이면 명시적 실패 PREPARE_MAX_WORKERS/prepare --max-workers로 대역폭 조절 — HF 가 연결당 속도를 묶어둬서 워커 수가 곧 대역폭이다 (1연결 5MB/s, 8연결 56MB/s)
🐛 수정
split shard 는 크기가 균등하지 않다 — unsloth 의 첫 조각이 10MB 인데 형제는 50GB 다.
캐시 히트를 프로필에 적힌 파일 하나로만 판정해서, 그 10MB 가 받아지자마자
남은 68GB 를 건너뛰고 "준비 완료" 로 보고하던 문제를 고쳤다.
업그레이드
llmux update.env.common 에 PREPARE_DOWNLOADER_IMAGE 를 추가해야 GGUF 를 받을 수 있다
(.env.common.example 참고).
v2.7.1 — 외부 HTTPS 호출 CA 번들 수정
🐛 고친 것
vLLM recipe fetch 와 llama.cpp GGUF 목록 조회가 일부 환경에서 CERTIFICATE_VERIFY_FAILED 로 죽던 문제.
Could not reach the recipe index: https://raw.githubusercontent.com/...
→ [SSL: CERTIFICATE_VERIFY_FAILED] unable to get local issuer certificate
llmux 는 존재하는 CA 번들을 찾아 붙이는 헬퍼를 갖고 있었지만, 실제로 쓰는 곳은 DockerHub 조회와 버전 체크뿐이었습니다. recipe fetch(raw.githubusercontent.com)와 HF 파일 목록(huggingface.co)은 기본 컨텍스트로 나가서, OpenSSL 기본 경로(/etc/ssl/cert.pem)가 없는 빌드(uv 배포 CPython on RHEL/CentOS 등)에서는 그 두 기능만 실패했습니다.
이제 외부로 나가는 호출은 전부 ssl_ctx.open_url() 한 통로를 지나며, certifi → RHEL → Debian → macOS 순으로 실제 존재하는 번들을 찾아 붙입니다. SSL_CERT_FILE 을 손으로 지정할 필요가 없습니다.
재발 방지로, tui/ 전체를 AST 로 훑어 loopback 이 아닌 대상에 urlopen 을 직접 호출하면 실패하는 테스트를 추가했습니다.
Full changelog: v2.7.0...v2.7.1
v2.7.0 — 매 실행 업데이트 확인 + llmux update
🐛 고친 것
새 릴리스가 나와도 하루 동안 안 보이던 문제. 시작 시 업데이트 확인 결과를 24시간 캐시하고 있어서, 캐시가 찍힌 뒤 나온 릴리스는 다음 날까지 알림이 뜨지 않았습니다. 캐시를 우회할 정식 수단도 없어 .runtime/version-check.json 을 손으로 지워야 했습니다.
이제 인터랙티브 실행마다 확인합니다. 캐시 파일은 조회에 실패했을 때만 쓰이고(15분 백오프), 오프라인 머신이 매번 네트워크 타임아웃을 물지 않게 합니다. 성공하면 즉시 지웁니다.
✨ 새 기능
llmux update
백오프를 무시하고 지금 확인하고, 필요하면 업데이트합니다.
llmux update --check # "llmux is up to date (v2.7.0)."
llmux update --check --json # {"state": "behind", "latest_tag": ..., "local_version": ...}
llmux update -y # git pull + uv tool install, 확인 없이상태를 알 수 없으면(오프라인·rate limit·git 체크아웃 아님·shallow clone) 이유를 말하고 exit 1. 깨끗한 main 이 아니면 이유를 밝히고 자동 업데이트를 거부합니다.
TUI 에서는 대시보드 U 키가 같은 일을 합니다.
🧹 내부
- 릴리스 태그가 체크아웃의
pyproject.toml버전과 같으면 거기서 최신으로 판정 — 평소 API 호출이 2회에서 1회로 줄었습니다. 다를 때만 커밋 ancestry 를 확인합니다(기존 로직 유지). HTTP 타임아웃 4s → 3s. - 판정을
resolve_status()→UpdateStatus(behind/current/unknown)로 분리하고,unknown에 사유를 실었습니다.
Full changelog: v2.6.0...v2.7.0
v2.6.0 — prepare(다운로드만) + 레시피 출처 모델 분리
✨ 새 기능
llmux prepare <profile> — 다운로드·세팅만, 실행은 안 함
up 이 하는 일 중 compose up 직전까지만 수행합니다: 프로필 env(그리고 llama.cpp 의 command override) 렌더 → 이미지 로컬 확보(없으면 pull) → HF 캐시로 가중치 다운로드. 컨테이너를 남기지 않고 GPU 도 건드리지 않습니다 — 나중에 llmux up 이 이미 받아둔 것만 로드하면 됩니다.
llmux prepare qwen3-0-6b
llmux prepare gemma-3-4b --backend llamacpp다운로드는 해당 백엔드 이미지의 일회성 컨테이너 안에서 실행됩니다 — vLLM 은 huggingface_hub.snapshot_download, llama.cpp 는 llama-server 자체 -hf 경로를 태우고 GGUF 가 호스트 캐시에 완성되는 즉시 컨테이너를 중지합니다. 호스트에 hf CLI 를 요구하지 않습니다.
TUI 에서는 중지 상태 프로필의 액션 메뉴 ⬇ Prepare (다운로드만), 또는 대시보드에서 p 키.
레시피 출처 모델 분리
Quick Setup 과 Edit Config 에 Recipe source 입력칸이 생겼습니다. 비워두면 종전대로 위 모델의 레시피를 받고, 채우면 그 모델의 레시피를 가져옵니다. 출처가 다를 때 config 의 model 은 사용자가 입력한 모델을 유지합니다 — 플래그만 차용하고, variant 의 FP8/AWQ 체크포인트 교체도 무시합니다. 레시피가 없는 커뮤니티 양자화 체크포인트에 베이스 모델의 레시피를 입힐 때 쓰세요.
llmux config from-recipe cpatonn/Qwen3-32B-AWQ --recipe-from Qwen/Qwen3-32B --variant awqEdit Config 에서도 레시피 받기
📋 Fetch vLLM recipe 버튼이 Config 편집 폼에도 들어갔습니다. 새로 만들지 않고 열려 있는 폼에 병합합니다 — 같은 키 행은 값이 갱신되고(꺼져 있었으면 다시 켜짐), 없던 키는 행이 추가됩니다. 저장 전이라 확인하고 Save.
llmux config from-recipe Qwen/Qwen3-32B --name my-model --feature reasoning --merge🧹 내부
- llama.cpp 의 config 자동 링크/생성 로직을
up과prepare가 공유하도록 추출(동작 변경 없음). - 문서 갱신: README(en/ko), guide(container-lifecycle · configs · tui), reference(cli).
Full changelog: v2.5.0...v2.6.0
v2.5.0 — btop 스타일 시스템 모니터
실행 중인 모델과 GPU를 한 화면에서 보는 btop 스타일 모니터가 이번 릴리스의 본체입니다. v2.4.1 이후 쌓인 UI 정리와 한국어 README도 함께 나갑니다.
📊 btop 스타일 시스템 모니터 (#75 · #79 · #81)
TUI에서 v, 또는 TUI 없이 llmux top.
GPU는 항상 보입니다. 컨테이너가 하나도 안 떠 있어도 util·VRAM·온도·전력·PCIe rx/tx가 heat bar로 그려집니다. 패널 제목에 카드 이름이 들어가고, GPU가 여러 장이면 전부 나옵니다. 모니터를 여는 이유가 대개 "GPU 지금 어떤가"인데, 이전 버전은 실행 중인 컨테이너가 없으면 아예 열리지도 않았습니다.
실행 중인 모델마다 패널이 붙습니다. 목록을 매 틱 다시 훑기 때문에 다른 터미널에서 띄운 모델도 알아서 나타납니다. 하나면 상세 뷰, 여러 개면 모델별 요약입니다.
상세 뷰에 담기는 것:
- 처리량·KV 캐시 braille 그래프 (현재값과 피크)
- 캐시 적중률 — KV · prefix · external
- 지연 — TTFT·E2E percentile(p50/p95/p99)을 Prometheus 히스토그램 버킷에서 직접 계산. TPOT·queue와 prefill/decode/inference 구간까지
- 요청 — running · waiting · 완료/s · preemption
키: p 일시정지 · r 피크 초기화 · +/- 폴링 주기 · l 언어 · q 종료.
엔진이 안 내주는 지표는 지어내지 않고 —로 둡니다. llama.cpp는 지연 히스토그램과 prefix 캐시를 노출하지 않아 해당 칸이 비고, TPOT만 자체 tok/s 게이지에서 파생합니다.
지표 파싱 수정
vLLM이 릴리스마다 이름을 바꾼 두 지표를 양쪽 다 인식하도록 고쳤습니다.
- KV 사용률 —
kv_cache_usage_perc↔gpu_cache_usage_perc - 토큰당 지연 —
inter_token_latency_seconds↔time_per_output_token_seconds
이전 코드는 옛 이름만 봐서 최신 vLLM에서 KV가 계속 —로 나왔습니다. 두 이름이 동시에 존재해도 먼저 잡힌 것만 합산해 중복 집계를 막습니다.
💄 대시보드 UI 정리 (#76 · #77 · #78)
Status컬럼을 맨 앞으로. 실행 중인지가 가장 먼저 볼 정보인데 뒤에 있었습니다.- vLLM 색을 자홍 → 파랑으로. llama.cpp가 초록이라 자홍이 경고처럼 보였습니다.
- 프로필 이름 변경 경로를 편집 폼으로 일원화 — 별도
R메뉴 제거. - 버전 선택 화면에서 Enter로 바로 시작 — 이전에는 라디오만 선택되고 Start를 또 눌러야 했습니다.
- 모니터 종료 키를
q로 통일 (로그 화면과 동일).
📝 문서 · 데모
- 한국어 README (
README.ko.md) 추가, 언어 전환 링크 연결 (#74) - README 데모 최상단에 모니터 스크린샷 배치, 대시보드 컷은 현재 UI로 재촬영 (#83)
- 재현용 VHS tape 3종 동봉 — 같은 컷을 다시 뽑을 수 있습니다
- Features에 빠져 있던 실기능 보강: 버전 핀·멀티 GPU·LoRA·GGUF 자동 다운로드·플래그 자동완성 (#72 · #73)
- 모니터 관련 "실행 중 전용" 문구를 실제 동작에 맞게 전면 정정 (#82)
업그레이드
cd ~/.llmux && git pull설치되어 있지 않다면:
curl -fsSL https://raw.githubusercontent.com/Bae-ChangHyun/llmux/main/install.sh | shFull Changelog: v2.4.1...v2.5.0
v2.4.1 — 편집 폼에서 이름 변경 + 문서 전면 갱신
v2.4.0의 이름 변경 기능을 실제로 발견 가능하게 만들고, 죽어 있던 문서 링크를 고친 릴리스입니다.
✨ 편집 폼에서도 이름 변경 (#64)
v2.4.0은 이름 변경을 TUI R 키로만 열어두고 편집 폼의 Name 필드는 비활성화로 남겨뒀습니다. 그런데 이름을 바꾸려는 사용자는 당연히 Edit Profile부터 엽니다 — 거기서 Name이 회색이면 기능이 없는 것으로 읽힙니다.
이제 프로필 폼과 config 폼 모두(vLLM · llama.cpp) Name 필드가 열려 있고, 이름을 바꿔 저장하면 rename이 됩니다.
- 실행 중 컨테이너 거부 · 전역 이름 유일성은
R키 경로와 동일한 규칙 - config 이름을 바꾸면 그 config를 참조하던 프로필들이 자동으로 따라옵니다
R키와 액션 메뉴도 그대로 유지 — 목록에서 폼을 열지 않고 바로 바꾸는 경로
📝 문서 전면 갱신 (#63)
README의 문서 링크가 전부 404였습니다. MkDocs 제거 시점에 확장자 없는 URL(/reference/cli/)이 남았는데, 현재 사이트는 손으로 만든 .html이라 GitHub Pages가 리라이트하지 않습니다. 8개 링크 전부 교정했습니다.
문서에 없던 것들도 채웠습니다:
- 프로필·config 이름 변경 — CLI 레퍼런스에만 있고 TUI 가이드·README에 전무했음
VLLM_USE_V2_MODEL_RUNNER— README·docs·.env.common.example어디에도 없었습니다.thinking_token_budget을 쓰려면0이어야 한다는 정보가 사용자에게 도달할 경로가 아예 없었습니다. 흔한 함정(MTP가 켜져 있으면 budget이 조용히 무시됨, top-level로 전달해야 함)까지 문서화LLMUX_LANG— 본문엔 있었으나 환경변수 레퍼런스에서 누락
낡은 서술도 정리했습니다 — 이미 출시된 "Recipe-based config recommender"가 로드맵에 미완료로 남아 있던 것, TUI 가이드의 config 목록 단축키 설명, 한글 도움말에만 "이름변경"이 빠져 있던 i18n 불일치.
✨ llmux --version / -V
버전 문자열을 런타임에서 읽는 곳이 없어 사용자가 자기 버전을 확인할 방법이 없었습니다. 패키지 메타데이터를 읽고, 설치 안 된 소스 체크아웃에서는 pyproject.toml로 폴백합니다.
$ llmux --version
llmux 2.4.1
Full Changelog: v2.4.0...v2.4.1
v2.4.0 — 프로필·config 이름 변경 + UI 언어 전환 + vLLM recipe import
✨ 새 기능
프로필·config 이름 변경 (#62)
최초 커밋 이래 프로필/config 이름은 편집 폼에서 비활성화돼 있었고 CLI에도 rename 경로가 없었습니다. 이름이 profiles.yaml 엔트리 키, 런타임 .env 파일명, 컨테이너 이름, config 파일명의 식별자로 동시에 쓰이기 때문입니다.
컨테이너가 중지된 경우에 한해 이름 변경을 지원합니다.
llmux profile rename qwen3-8b qwen3-8b-fp8
llmux profile clone qwen3-8b qwen3-8b-tuned
llmux config rename qwen3-0-6b qwen3-0-6b-fp8TUI 에서는 대시보드와 config 목록에서 R 키. config 이름을 바꾸면 그 config 를 참조하던 프로필들이 자동으로 따라옵니다.
container_name / config_name 이 설정돼 있지 않으면 프로필 이름으로 fallback 되는데 — 미설정 container_name 은 새 이름을 따라가고, 미설정 config_name 은 옛 이름으로 고정돼 기존 config 파일에 계속 해석됩니다.
UI 언어 전환 (LLMUX_LANG=ko|en)
TUI 전 화면과 footer 가 한국어/영어로 전환됩니다.
vLLM 공식 recipe 기반 config
vllm-project/recipes 의 recipe 를 받아 config 로 만듭니다. GPU 메모리 대비 어떤 variant 가 맞는지 검토 창에서 확인 후 선택합니다.
llmux config from-recipe Qwen/Qwen3-32B --variant fp8config 파라미터 on/off
파라미터를 지우지 않고 비활성화/재활성화합니다 (# llmux:disabled 마커). config 편집 시 손으로 쓴 주석도 보존됩니다.
그 외
- 대시보드 라이브 tok/s 표시, compact 레이아웃
config clone- vLLM
thinking_token_budgetenv
🐛 버그 수정
- 프로필 이름 전역 유일성 등 전수조사 지적 10건
config from-recipe쓰기 경로 크래시 (param_hint누락)- 좁은 터미널 안내 화면이 빈 박스로 뜨던 문제
- 전체 점검에서 확정된 버그 8건 + 후속 하드닝
📝 문서
- README 데모 GIF 재녹화 (단일 복합 워크스루)
- CLI 레퍼런스에
profile rename/profile clone/config rename추가
Full Changelog: v2.3.0...v2.4.0
v2.3.0 — TUI width guard + hf-mem 0.5.5
✨ Features
- TUI width guard. When the terminal narrows below
LlmuxApp.MIN_WIDTH = 80, aTooNarrowScreenoverlay is pushed so modals, forms, and the dashboard no longer clip horizontally. Auto-dismisses the moment the terminal is widened back — nvitop-style behavior. (#55)
⬆️ Dependencies
- hf-mem
0.5.2→0.5.5. Lock-only bump, no call-site changes. Picks up:- KV-cache dtype resolution for
compressed-tensorsmodels that don't declarekv_cache_scheme(e.g. Kimi K2.5) - Sliding-window layer estimation fix → more accurate KV-cache numbers for SWA models
- Missing
dtype/quantization_configparsing fix - New:
modeloptquant_method,F8_E8M0dtype, experimental MoE breakdown for safetensors (relevant foropenai/gpt-oss-120b-class models shown in dashboard) - Upstream: https://github.com/alvarobartt/hf-mem/releases (#55)
- KV-cache dtype resolution for
📝 Docs
- README: dropped the obsolete "Credits" block pointing at the now-superseded
vllm-compose/llamacpp-composerepos.
Changelog
- #55 ✨ feat(tui): width guard against terminals narrower than MIN_WIDTH=80
- #55 ⬆️ chore(deps): bump hf-mem 0.5.2 → 0.5.5
- #56 📝 docs(readme): drop superseded project credits
- #56 🔖 chore: bump version to 2.3.0
Full diff: v2.2.1...v2.3.0
v2.2.1 — installer no longer relocates existing checkouts
🐛 Fixes
- Re-running the curl installer used to silently switch the
llmuxeditable target — e.g. from a dev checkout to~/.llmux, leaving the command pointing at a fresh skeleton without the user's profiles. The installer now detects existing installs viauv-receipt.toml, updates that checkout in place (git pull --ff-only+uv tool install --editable . --forceon the same path), and ignoresLLMUX_DIRonce installed. SetLLMUX_FORCE_RELOCATE=1to override and relocate. (#53)
Changelog
- #53 🐛 fix(installer): update existing checkout in place, never relocate
- #54 🔖 chore: bump version to 2.2.1
Full diff: v2.2.0...v2.2.1