Mac·iPhone 앱에 로컬 AI 넣기: uzu의 속도 비교를 읽는 법
앱에 넣는 로컬 추론 엔진 uzu를 소개하고, 4배라는 속도 차이가 디코딩 방식과 기기에 따라 달라짐을 짚었습니다.
쉽게 말하면비유하자면 매번 본사에 전화해 묻는 대신 매장 안에 작은 상담원을 앉혀 두는 도구다. 다만 광고 속 4배 안팎의 속도는 한 글자씩 쓰는 방식과, 작은 모델이 미리 낸 여러 글자를 큰 모델이 한꺼번에 확인하는 방식을 견준 값이라 같은 방식끼리 다시 견줘 봐야 한다.
- 왜 봐야 하나
- 앱에 로컬 AI를 넣으려는 사람은 광고 배율을 그대로 적용하면 안 된다. 같은 생성 방식끼리 MLX와 견준 218쌍에서 속도 비율의 중앙값은 약 1.08배였다. 자기 기기와 자기 프롬프트로 속도와 품질을 따로 재 볼 만하다.
uzu는 Mac·iPhone 앱 안에서 언어 모델을 실행하도록 만든 Rust 기반 추론 엔진이다. Swift·Python·TypeScript·Rust 인터페이스와 전용 모델 변환 도구를 제공한다. 이번 자료는 기존 프로젝트를 소개한 11월 1일의 새 커뮤니티 해설이며, 제품의 첫 출시나 새 논문 발표가 아니다. 핵심은 속도 비교를 읽는 방법이다. 공개 데이터에서 같은 자기회귀 방식의 uzu/MLX 출력 속도 비율은 중앙값 약 1.08배다. 광고의 4배 안팎 차이는 일부 M5 이후 칩에서 추측 디코딩을 사용한 값과 기본 생성값을 비교한 것이다. 측정 주체는 개발사 Mirai이며 체크포인트와 측정 조건도 함께 봐야 한다.
알아낸 것
- 공식 공개 데이터의 기기·체크포인트 218쌍을 재계산하면, 같은 자기회귀 출력에서 uzu/MLX 속도 비율의 중앙값은 약 1.08배이며 15쌍에서는 MLX가 더 빨랐습니다.
- M5 Max 128GB의 Qwen3.6 27B에서 uzu는 자기회귀 35.6, 추측 디코딩 142.3 tok/s이고 MLX 자기회귀는 33.1 tok/s였습니다. 약 4.3배는 서로 다른 디코딩 방식의 비교입니다.
- Rust 엔진을 Swift·Python·TypeScript 등에서 쓸 수 있지만 전용 모델 변환이 필요하고, Swift 패키지는 iOS·macOS·Mac Catalyst 26.4 이상을 요구합니다.
한계와 주의할 점
- 이번에 새로 게시된 것은 11월 1일의 커뮤니티 해설입니다. 기존 프로젝트의 최초 출시나 기반 논문의 신규 발표가 아닙니다.
- 성능은 Mirai 자체 측정이며 엔진별 양자화 체크포인트·측정 분모가 다릅니다. 모든 기기·한국어 작업에서 같은 속도와 품질을 보장하지 않습니다.
- 고수준 API 일부가 재작성 대상으로 표시되어 있고, 소스의 WebGPU 코드만으로 범용 OS 배포가 완성됐다고 볼 수 없습니다.
용어 풀이
- 추측 디코딩
- 작은 초안 모델이 다음 토큰들을 미리 제안하고 큰 모델이 검증하는 생성 방식. 후보 수와 채택률, 기기와 작업에 따라 속도 이득이 달라진다.
- 양자화
- 모델 가중치를 낮은 비트 수로 표현해 메모리 사용과 연산량을 줄이는 기법. uzu는 4비트 비대칭(Mirai-M)과 8비트 대칭(Mirai-L) 형식을 쓰며, 랜덤 하다마드 변환으로 이상치를 줄인다.
- 자기회귀
- 앞서 생성한 토큰을 보고 다음 토큰을 하나씩 만드는 기본 방식. 추측 디코딩 사용 여부를 같게 비교하면 속도 차이를 더 정확히 해석할 수 있지만, 체크포인트와 다른 조건도 확인해야 한다.
- lalamo
- Mirai의 모델 변환 도구. 원본 체크포인트를 uzu가 읽는 전용 형식으로 바꾼다. 새로운 레이어에는 변환 처리와 실행 커널이 추가로 필요할 수 있다.
더 깊이 읽기 읽는 데 약 7분
배경과 문제
로컬 AI를 개발자 컴퓨터에서 시험하는 것과 실제 앱에 넣어 배포하는 것은 다른 일이다. 앱에서는 모델을 내려받고 메모리를 관리하며 답변을 조금씩 표시하는 연결 작업도 필요하다. uzu는 Rust 코어를 여러 언어로 감싸 이런 앱 통합을 돕는다. 다만 llama.cpp나 MLX에도 바인딩과 앱 통합 방법이 있으므로, uzu만 앱에 넣을 수 있다는 뜻은 아니다.
Mirai는 변환 도구 lalamo, 모델 양자화 형식, 실행 커널을 함께 설계했다. 앱은 지원 모델의 식별자를 통해 다운로드와 추론을 요청할 수 있다. 이 통합 방식은 편리함을 지향하지만, 범용 모델 파일을 그대로 사용하는 유연성과는 교환관계가 있다. 자체 제품 페이지의 빠르다는 주장을 어떤 조건에서 측정했는지 따져보는 것이 이 해설의 주된 가치다.
기존 도구와의 차이
llama.cpp의 GGUF나 MLX 형식을 그대로 쓰는 대신, uzu는 lalamo로 바꾼 전용 형식을 읽는다. 이미 지원하는 블록으로 구성된 모델은 변환할 수 있지만 새로운 레이어에는 변환 처리와 실행 커널이 추가돼야 한다. 다운로드 가능한 체크포인트가 있다고 해서 다른 모델도 모두 즉시 실행되는 것은 아니다.
배포 범위도 확인해야 한다. 조사 시점의 Swift 패키지는 iOS·macOS·Mac Catalyst 26.4 이상을, Python 0.6.15 휠은 Python 3.12 이상과 macOS 26 이상을 요구한다. README가 지원 백엔드로 밝힌 것은 Metal과 CPU다. 소스에 WebGPU 코드가 있다는 사실만으로 Linux·Windows용 배포가 완성됐다고 볼 수 없다.
작동 방식을 단계별로
먼저 lalamo가 원본 모델을 통일된 블록의 중간 표현으로 변환한다. 엔진은 각 블록을 해당 기기의 커널로 실행한다. 작은 모델을 골라 실제 기기의 메모리에 올릴 수 있는지 확인하는 과정도 필요하다. 모델 크기와 사용 가능한 메모리가 다르므로 Mac에서 돌아가는 구성을 iPhone에 그대로 옮길 수는 없다.
다음으로 양자화가 메모리와 계산의 부담을 줄인다. Mirai-M은 4비트 비대칭 정수 형식이고 Mirai-L은 8비트 대칭 형식이다. Qwen3.6 27B 모델 카드의 M 형식은 그룹 크기 64, 4비트 영점과 bf16 스케일을 쓴다. 블록 크기 32의 랜덤 하다마드 변환은 값이 유난히 큰 성분의 영향을 줄이도록 적용한다.
학습 후 양자화에는 YAQA를 JAX로 구현한 방식을 사용한다. 이후 원본 모델의 응답을 이용한 짧은 증류로 품질을 회복한다. 공식 글은 양자화 가중치도 Muon으로 조정하고 그룹 스케일과 영점은 AdamW로 조정한다고 설명한다. 스케일만 다시 맞추는 과정은 아니다. 보정 자료는 공식 글에서 내부 데이터셋이라고 명시하므로 특정 공개 데이터셋으로 고정해 설명할 근거는 없다.
결과와 숫자의 의미
2026년 10월 20일 공개 측정은 13개 기기와 24개 체크포인트를 포함한다. 방법 절에는 약 1,357 입력 토큰, 최대 4,096 출력 토큰, 구성별 3회 실행과 매회 CPU·GPU 온도 60°C 미만 대기가 적혀 있다. 출력 패널은 공개 평가의 실행 기록을 섞은 자체 자료도 설명한다. 따라서 모든 결과를 동일한 짧은 프롬프트 하나로 얻었다고 해석해서는 안 된다.
M5 Max 128GB에서 Qwen3.6 27B의 출력은 uzu 0.6.9의 자기회귀 35.6 tok/s, 추측 디코딩 142.3 tok/s였다. MLX 0.32.4의 자기회귀는 33.1 tok/s다. 같은 자기회귀끼리는 약 8% 차이지만 142.3과 33.1을 나누면 약 4.3배가 된다. 추측 디코딩끼리 비교한 oMLX 64.0, llama.cpp 48.1 tok/s와도 구분해야 한다. 각 엔진의 4비트 체크포인트가 달라 엔진 코드 하나만 바꾼 실험은 아니다.
MLX와 비교 가능한 기기·체크포인트 218쌍을 보면 자기회귀 속도 비율의 중앙값은 1.08배, 범위는 0.94~1.64배이며 15쌍에서는 MLX가 더 빨랐다. 이 집계는 공개 원시 값으로 재계산해 확인했다. 218은 사용자 수나 반복 실험 수가 아니며, 모든 기기에서 8% 빨라졌다는 뜻도 아니다. 추측 디코딩이 보고된 범위는 네 모델의 M/L 체크포인트와 M5·M6 계열 기기다.
구체적인 예시
이해를 위한 가상 예로, 네트워크 없이 메모를 정리하는 iPhone 앱을 생각할 수 있다. 개발자는 지원되는 소형 모델을 내려받고 세션에 메모를 넣어 스트리밍 답변을 받는다. JSON 스키마로 제목과 할 일 목록의 형식을 제한하거나 앱의 함수를 도구로 연결할 수도 있다. 이것은 활용 원리를 설명한 예이며, 논문이 그 앱의 한국어 정확도나 배터리 절감을 실증한 결과가 아니다.
추측 디코딩은 작은 초안 모델이 여러 다음 토큰을 제안하고 큰 모델이 한 번에 검증하는 방식이다. 후보를 얼마나 받아들이는지에 따라 속도가 달라지므로, 짧은 답변이나 문체가 다른 작업에서 같은 배율을 기대할 수 없다. 이 기법을 쓰더라도 실제 앱에서는 출력 속도뿐 아니라 첫 답변까지의 시간, 모델 다운로드, 메모리 부담을 함께 측정해야 한다.
한계와 오해하기 쉬운 점
속도 표는 Mirai 자체 측정이며 독립적인 재현 실험은 아니다. 메모리도 uzu의 세션 피크, MLX의 네이티브 피크, llama.cpp의 프로세스 상주 메모리로 정의가 다르다. 입력 속도에서 MLX는 첫 토큰까지의 벽시계 시간을 분모로 쓰는 반면 uzu는 자체 prefill 지표를 쓴다. 비슷한 이름의 지표라도 계산 기준이 동일하다고 가정하면 안 된다.
양자화 품질은 특정 모델과 평가 범위의 결과다. Qwen3.5 0.8B·2B의 M 형식은 Q4_K_M과 비슷한 품질에서 약 20% 작았지만, 4B는 Q3_K_M과 Q4_0 사이였다. 8비트 품질을 구분하기 어렵다는 설명도 MMLU-Pro와 KL 평가의 잡음 수준에 관한 것으로 모든 출력이 같다는 뜻은 아니다. KL은 Lmsys-Chat-1M 질문 100개의 원본 모델 응답에서 평가했으며, 한국어 서비스 품질을 별도로 보장하지 않는다.
포럼의 추측 디코딩 구조 설명에는 기존 Trees from Marginals 논문이 인용돼 있다. 이를 이번에 나온 새 논문으로 취급하지 않았다. 공개 표에서 일부 기기에 결과가 없다는 사실 역시 기법이 그 기기에서 원리상 불가능하다는 증거는 아니다. 이번 비교에서 확인된 범위와 아직 시험하지 않은 환경을 나눠 읽어야 한다.
실제로 활용하려면
먼저 앱의 최소 운영체제, 모델 형식, 메모리 예산을 확인하고 작은 지원 모델로 통합을 시험하는 것이 한 방법이다. 자신이 사용할 같은 프롬프트에서 원본 모델과 양자화 모델의 품질을 비교하고, 자기회귀와 추측 디코딩의 속도를 따로 기록하면 광고 배율을 그대로 적용하는 실수를 줄일 수 있다. 이는 공개 설계를 바탕으로 한 적용 제안이다.
버전과 라이선스도 분리해서 확인해야 한다. Cargo.toml은 바인딩·CLI·고수준 uzu 코드를 legacy 아래 재작성 대상으로 표시하므로 API가 계속 같을 것이라고 가정하기 어렵다. 엔진은 MIT 라이선스지만 변환한 모델은 원본 모델의 라이선스를 따른다. 앱에 넣기 전에 사용할 모델 카드와 고정한 패키지 버전을 확인해야 한다.
원문에서 확인한 근거 5곳
- uzu는 Rust로 작성한 코어를 Swift, Python, TypeScript 바인딩으로 감싸 앱에 바로 넣을 수 있게 했다.uzu 소개
- Mirai-M은 4비트 영점과 bf16 스케일을 쓰는 4비트 비대칭 정수 양자화이고, Mirai-L은 8비트 대칭 양자화다.format
- M5 Max 128GB에서 Qwen3.6 27B의 uzu 자기회귀 출력은35.6 tok/s,추측 디코딩은142.3 tok/s이며 MLX 자기회귀는33.1 tok/s다.uzu 벤치마크
- MLX 결과가 함께 있는 218개 기기와 모델 쌍에서 uzu와 MLX의 자기회귀 출력 속도 비율은 중앙값 1.08배(최소 0.94배, 최대 1.64배)이고, 15개 쌍에서는 MLX가 더 빠르다.uzu 벤치마크
- Qwen3.5 0.8B와 2B의 Mirai-M은 llama.cpp의 Q4_K_M과 품질이 비슷하면서 크기가 약 20% 작고, 4B는 Q3_K_M과 Q4_0 사이에 놓인다.Evaluation
11월 2일(월) 정리 · AI가 쓰고 원문과 대조
AI 목록