본문 바로가기
C.W.K.
Stream
Lesson 01 of 06 · published

MLX 모델 형식 — safetensors, 설정, 토크나이저

~12 min · model-format, safetensors, config

Level 0호기심
0 XP0/51 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

MLX 모델 폴더 안에는 무엇이 있나

Hugging Face의 MLX 형식 모델과 mlx_lm.convert로 만든 모델은 작은 표준 파일들을 한 폴더에 둬. 정체를 알 수 없는 덩어리도, 독점 컨테이너도 없어. 흔한 도구로 모두 살펴볼 수 있어.

  • model.safetensors — 가중치를 담아. 큰 모델은 model-00001-of-00003.safetensors 같은 조각으로 나뉘어. mmap할 수 있고 텐서 이름으로 중복을 줄여 빠르게 불러와.
  • model.safetensors.index.json — 조각난 모델에만 있어. 각 텐서 이름이 어느 파일에 있는지 이어줘.
  • config.json — 모델 구조 설명서야. model_type, 은닉 크기, 층 수, 어텐션 헤드 수, 어휘 크기, 양자화 설정을 담아. mlx-lm은 이 파일을 읽고 알맞은 모델 클래스를 골라.
  • tokenizer.jsontokenizer_config.json — 토크나이저, 특수 토큰, Jinja 문자열인 chat_template를 담아. 언어 모델 트랙 레슨 5가 여기에 기대.
  • 선택 파일 — 기본 샘플링 값을 담은 generation_config.json, special_tokens_map.json, added_tokens.json 등이 있어. mlx-lm은 필요한 것만 읽고 나머지는 무시해.

열어볼 수 있다는 게 왜 중요한가

첫째, 실제 내용을 검증할 수 있어. cat config.json 한 번이면 구조와 양자화를 보니 모델 카드만 믿고 추측할 필요가 없어. 둘째, 부품을 재사용할 수 있어. 같은 계열의 변형 모델은 토크나이저 파일을 공유하고 가중치만 바꿀 수 있어. 셋째, 불러오기 실패를 추적할 수 있어. "가중치 키를 찾지 못했다"는 오류는 대개 safetensors와 설정이 서로 맞지 않는다는 뜻이니 둘 다 열어봐.

파일 하나와 여러 조각

디스크에서 약 5 GB보다 작은 모델은 보통 model.safetensors 하나로 나와. 큰 모델은 여러 조각으로 나누고 model.safetensors.index.json이 길잡이를 맡아. mlx-lm이 알아서 고르므로 직접 조각을 지정할 필요는 없어. 조각 크기 한도는 변환할 때 정하며 보통 한 조각에 5 GB야.

30초 검사 습관을 들여

이제 모델 폴더를 보면 먼저 ls하고 config.json을 열어봐. 30초 안에 구조, 자료형, 양자화, 문맥 길이를 답할 수 있어야 해. 뒤 레슨은 이 습관이 있다고 보고 진행해.

Code

캐시된 MLX 모델 폴더 살펴보기·bash
# Find the cached model
SNAP=~/.cache/huggingface/hub/models--mlx-community--Llama-3.2-1B-Instruct-4bit/snapshots/
ls $SNAP*/

# Sample listing (verified 2026-05-03):
#   config.json
#   model.safetensors
#   model.safetensors.index.json   (only if sharded; 1B Q4 fits in single file)
#   special_tokens_map.json
#   tokenizer.json
#   tokenizer_config.json
config.json 읽기 — 구조와 양자화를 한눈에·python
import json, os, glob

snap = glob.glob(os.path.expanduser(
    "~/.cache/huggingface/hub/models--mlx-community--Llama-3.2-1B-Instruct-4bit/snapshots/*/"
))[0]

with open(os.path.join(snap, "config.json")) as f:
    cfg = json.load(f)

print("model_type      :", cfg.get("model_type"))
print("hidden_size     :", cfg.get("hidden_size"))
print("num_hidden_layers:", cfg.get("num_hidden_layers"))
print("num_attention_heads:", cfg.get("num_attention_heads"))
print("vocab_size      :", cfg.get("vocab_size"))
print("max_position_embeddings:", cfg.get("max_position_embeddings"))
print("quantization    :", cfg.get("quantization"))   # group_size, bits, mode
가중치를 불러오지 않고 safetensors 정보 살펴보기·python
import os, glob
from safetensors import safe_open

snap = glob.glob(os.path.expanduser(
    "~/.cache/huggingface/hub/models--mlx-community--Llama-3.2-1B-Instruct-4bit/snapshots/*/"
))[0]
shard = os.path.join(snap, "model.safetensors")

with safe_open(shard, framework="numpy") as f:
    keys = list(f.keys())
    print(f"Total tensors: {len(keys)}")
    print("First 8 tensor names:")
    for k in keys[:8]:
        print(f"  {k:60} dtype={f.get_slice(k).get_dtype()} shape={f.get_slice(k).get_shape()}")

External links

Exercise

현재 Mac에 캐시된 MLX 모델을 살펴봐. config.json을 읽고 (1) 구조 이름, (2) group_size·bits·mode를 포함한 양자화 설정, (3) 최대 문맥 길이를 적어. 이어서 tokenizer_config.jsonchat_template를 찾아 첫 200자를 복사해. 모델 안에 무엇이 있는지 막연히 불안해하지 말고 30초 검사로 답하는 습관을 만드는 연습이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.