Apple Core AI 공개, 애플 실리콘용 온디바이스 AI 추론 스택과 PyTorch 변환 도구 coreai-torch

Apple Core AI 소개

AppleCore AI라는 새로운 온디바이스 추론 프레임워크를 공개했습니다. Core AI는 앱 안에서 AI 모델을 빌드하고, 실행하고, 배포하기 위한 스택으로, 처음부터 Apple silicon을 염두에 두고 설계되었습니다. 모델 추론을 CPU, GPU, 그리고 Neural Engine에 걸쳐 분산해 실행하며, 최신 모델 아키텍처와 추론 기법을 앱에서 곧바로 활용할 수 있게 해줍니다. Swift API는 흔한 작업을 간단하게 만들면서도, 필요할 때는 모델 특화(specialization), 캐싱, 추론 성능에 대한 세밀한 제어를 제공합니다.

여기서 핵심 단어는 온디바이스(on-device) 입니다. 추론이 사용자의 기기에서 직접 일어나기 때문에 데이터가 기기 밖으로 나가지 않아 프라이버시가 보장되고, 네트워크가 없어도 AI 기능이 동작하며, 추론 한 번마다 발생하는 서버 비용도 없습니다. 최근 몇 년간 온디바이스 LLM과 확산 모델(diffusion model)에 대한 관심이 폭발적으로 커졌지만, 트랜스포머(Transformer) 계열의 무거운 모델을 모바일이나 노트북에서 효율적으로 돌리는 일은 여전히 까다롭습니다. Core AI는 바로 이 지점을 겨냥해, 모델 준비부터 변환, 압축, 실행, 디버깅까지 이어지는 일관된 도구 체인을 제공합니다.

PyTorchKR 커뮤니티 입장에서 특히 주목할 부분은, 이 스택이 PyTorch를 1급 시민(first-class citizen)으로 취급한다는 점입니다. Apple은 Core AI 프레임워크와 함께 PyTorch 모델을 Core AI로 가져오는 coreai-torch, 배포를 위한 모델 압축 라이브러리 coreai-optimization, 그리고 바로 쓸 수 있는 모델 갤러리 coreai-models를 함께 오픈소스로 공개했습니다. 즉, torch.export로 내보낸 그래프에서 시작해 Apple 하드웨어에서 도는 .aimodel까지, 익숙한 PyTorch 워크플로우를 그대로 이어갈 수 있습니다.

이 글에서는 Core AI 스택을 구성하는 네 가지 축을 차례로 살펴봅니다. PyTorch와 가장 밀접한 coreai-torch에 가장 많은 분량을 할애하되, 모델 압축을 담당하는 coreai-optimization, Swift로 실제 추론을 수행하는 Core AI 프레임워크, 그리고 모델 레시피와 에이전트 스킬을 모아둔 coreai-models까지 종합적으로 다룹니다.

Core AI 스택을 이루는 네 개의 기둥

Core AI는 단일 라이브러리가 아니라, 모델의 생애주기(lifecycle)를 따라 배치된 여러 도구의 묶음입니다. PyTorch로 학습한 모델이 Apple 기기에서 실행되기까지의 흐름은 대략 다음과 같습니다. 먼저 PyTorch 모델을 준비(압축)하고, 이를 Core AI 중간 표현(IR)으로 변환한 뒤, .aimodel 형식으로 만들어 앱에 넣고, Core AI 런타임이 이를 기기에 맞게 특화해 실행합니다. 각 단계를 담당하는 구성 요소를 정리하면 다음과 같습니다.

구성 요소 역할 형태
Core AI 프레임워크 기기에서 모델을 적재 및 실행하는 런타임과 Swift API Apple OS 내장 프레임워크
coreai-torch PyTorch 모델을 Core AI IR로 변환하거나, PyTorch로 Core AI 모델을 직접 저작 Python 패키지 (pip install coreai-torch)
coreai-optimization 배포를 위한 양자화, 팔레타이제이션, 가지치기 등 모델 압축 Python 패키지 (pip install coreai-opt)
coreai-models 바로 쓰는 모델 갤러리, 내보내기 레시피, Swift 런타임 유틸리티 GitHub 저장소

여기에 더해, 모델을 시각적 및 수치적으로 분석할 수 있는 Core AI Debugger 앱과, 빌드 시점에 모델을 미리 컴파일하는 coreai-build 커맨드라인 도구, 그리고 Xcode에 통합된 Core AI 디버그 게이지(debug gauge)와 인스트루먼트(instrument)가 함께 제공됩니다. 이러한 도구들은 추론 성능을 모니터링 및 프로파일링하고, 텐서 값을 Python 소스 코드까지 거슬러 추적할 수 있게 해줍니다.

한 가지 짚어둘 점은, Core AI가 Core ML을 대체하는 것이 아니라는 사실입니다. Apple은 Core AI를 신경망(neural network) 추론에 특화된 새로운 스택으로 자리매김하고, 의사결정 트리(decision tree)나 표 형식(tabular) 특징 공학처럼 신경망이 아닌 모델 유형은 여전히 Core ML이 담당하도록 역할을 나누었습니다. 다시 말해 Core AI는 현대적인 LLM, 확산 모델, 비전 트랜스포머처럼 무겁고 동적인 신경망을 Apple silicon에서 효율적으로 돌리기 위한 차세대 경로라고 이해하면 됩니다.

coreai-torch, PyTorch 모델을 Core AI로 가져오는 다리

coreai-torch는 PyTorch와 Core AI를 잇는 Python 패키지입니다. 크게 두 가지 용도가 있습니다. 하나는 기존 PyTorch 모델을 가져오는(bring-up) 것이고, 다른 하나는 PyTorch로 Core AI 모델을 직접 저작하는 것입니다.

가져오기의 동작 원리는 명확합니다. coreai-torchtorch.export.export로 내보낸 ExportedProgram의 FX 그래프를 노드 단위로 순회하면서, 각 ATen 연산자를 그에 대응하는 Core AI 연산으로 매핑(lowering)합니다. 그 결과물은 Core AI 컴파일러와 런타임이 그대로 소비하는 IR이며, 변환 과정에서 위치(location) 정보와 모듈 스택(module-stack) 정보를 보존하기 때문에 나중에 디버깅할 때 텐서 값을 원래 Python 코드까지 추적할 수 있습니다. 공개 진입점(entry point)은 TorchConverter 클래스 하나입니다.

세 단계로 끝나는 모델 가져오기

가장 기본적인 가져오기 파이프라인은 세 단계로 이루어집니다. 첫째, torch.export.export로 모델의 계산 그래프를 포착합니다. 둘째, get_decomp_table()이 돌려주는 분해 테이블로 run_decompositions()를 호출해, 복합 ATen 연산을 TorchConverter가 매핑할 수 있는 기본 연산 집합으로 낮춥니다. 셋째, TorchConverter().add_exported_program(ep).to_coreai()를 호출해 AIProgram을 얻습니다.

import torch
from coreai_torch import TorchConverter, get_decomp_table

model = MyModel().eval()
ep = torch.export.export(model, args=(torch.randn(1, 10),))
ep = ep.run_decompositions(get_decomp_table())
coreai_program = TorchConverter().add_exported_program(ep).to_coreai()
coreai_program.optimize()

여기서 get_decomp_table()을 반드시 사용해야 하는 이유가 있습니다. 이 분해 테이블은 instance_norm, pixel_shuffle, scaled_dot_product_attention처럼 TorchConverter복합 연산(composite op) 으로 낮추는 연산들을 보존합니다. 즉, 단순히 모든 것을 잘게 쪼개는 것이 아니라, 런타임 성능에 중요한 연산은 하나의 인식 가능한 단위로 남겨두어 컴파일러가 최적화된 구현을 적용할 수 있게 합니다. 그래서 문서에서는 "run_decompositions()를 먼저 호출해야 하며, 반드시 get_decomp_table()을 사용하라" 고 경고합니다.

두 가지 입력 방식: ExportedProgram과 nn.Module

TorchConverter는 모델을 두 가지 형태로 받습니다. 가지고 있는 것이 무엇인지, 그리고 외부화(externalization)가 필요한지에 따라 선택하면 됩니다.

가진 것 사용 메서드
분해된 ExportedProgram add_exported_program()
nn.Module + 외부화 필요 externalize_modules와 함께 add_pytorch_module()
nn.Module, 외부화 불필요 둘 다 가능 (add_exported_program()이 더 직접적)

nn.Module을 직접 넘기는 경우에는 분해된 ExportedProgram을 돌려주는 export_fn을 함께 전달합니다. 이는 export_fn의 결과를 add_exported_program()에 넘기는 것과 동일합니다.

import coreai_torch
from coreai_torch import TorchConverter

model = MyModel().eval()
sample = (torch.randn(1, 3, 224, 224),)

converter = TorchConverter().add_pytorch_module(
    model,
    export_fn=lambda m: torch.export.export(m, args=sample).run_decompositions(
        coreai_torch.get_decomp_table()
    ),
)
coreai_program = converter.to_coreai()
coreai_program.optimize()

복합 연산과 외부화로 성능 끌어올리기

coreai-torch가 단순 변환기에 머무르지 않는 핵심 이유가 바로 외부화(externalization) 입니다. 어텐션(attention), RoPE 임베딩, RMSNorm, 그리고 MoE의 핵심 연산인 gather-matmul처럼 잘 알려진 빌딩 블록을 복합 연산 으로 표시해 두면, 컴파일러가 그 연산을 인식하고 해당 연산에 맞춰 튜닝된 최적화 구현을 적용해 더 빠른 모델을 만들어냅니다.

이를 위해 coreai_torch.composite_ops는 이러한 빌딩 블록들을 PyTorch 모듈로 제공합니다. 외부화는 add_pytorch_moduleexternalize_modules 인자를 통해 이루어지며, 각 서브모듈에 ExternalizeSpec을 붙여 복합 연산 이름과 동작을 정의하는 속성을 지정합니다.

import torch
import torch.nn as nn
import coreai_torch
from coreai_torch import ExternalizeSpec, TorchConverter
from coreai_torch.composite_ops import RMSNormImpl

class RMSNorm(nn.Module):
    """Convenience wrapper that owns the learnable scale parameter."""
    def __init__(self, dim: int, eps: float = 1e-5):
        super().__init__()
        self.weight = nn.Parameter(torch.ones(dim))
        self.norm = RMSNormImpl(eps=eps)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.norm(x, self.weight)

converter = TorchConverter().add_pytorch_module(
    model,
    export_fn=lambda m: torch.export.export(m, args=sample).run_decompositions(
        coreai_torch.get_decomp_table()
    ),
    externalize_modules=[
        ExternalizeSpec(
            target_class=RMSNormImpl,
            composite_op_name="rms_norm",
            composite_attrs=["axes", "eps"],
        )
    ],
)
coreai_program = converter.to_coreai()
coreai_program.optimize()

여기서 composite_ops가 제공하는 RMSNorm 같은 편의 래퍼(wrapper)는 학습 가능한 스케일 파라미터를 대신 소유해 주지만, ExternalizeSpectarget_class는 여전히 변환기가 rms_norm 복합 연산으로 인식하는 내부 모듈인 RMSNormImpl이어야 합니다. 참고로 ExternalizeSpec 없이 모듈 클래스만 넘기는 단순 외부화(simple externalization) 도 있는데, 이 경우 서브모듈이 독립 그래프로 추출될 뿐 복합 연산 메타데이터나 최적화 이점은 없으며 현재 실험적(experimental) 기능으로 분류되어 있습니다.

새로운 연산과 Metal 커널 직접 저작하기

PyTorch 연산에 내장 매핑 규칙이 없을 때는 register_torch_lowering으로 커스텀 낮춤(lowering) 함수를 등록할 수 있습니다. 또한 계산 집약적인 커스텀 연산을 위해서는 register_custom_kernelsTorchMetalKernel을 사용해 인라인 Metal GPU 커널 소스를 직접 작성하고 변환 파이프라인에 연결할 수 있습니다. 이 모든 것이 PyTorch nn.Module로 표현되고, 컴파일러가 네이티브로 인식하고 최적화하는 Core AI IR로 낮춰진다는 점이 coreai-torch의 설계 철학을 잘 보여줍니다. 단순히 "변환만" 하는 것이 아니라, PyTorch를 Core AI 모델을 저작하는 프런트엔드 로도 쓸 수 있게 한 것입니다.

coreai-torch 더 알아보기

Core AI PyTorch Extensions 공식 문서 - 가져오기 워크플로우, 복합 연산, 커스텀 Metal 커널 가이드

coreai-torch GitHub 저장소 - 소스 코드와 연산자 커버리지 노트북

coreai-optimization, 배포를 위한 모델 압축

온디바이스 배포에서 모델 크기와 메모리는 곧 사용자 경험입니다. coreai-optimization(패키지명 coreai-opt)은 PyTorch 모델을 Apple silicon에 배포하기 위해 맞춤화된 압축 기법들을 제공합니다. 대표적으로 양자화(quantization), 팔레타이제이션(palettization, 코드북 기반 압축), 그리고 가지치기(pruning) 가 포함됩니다.

흐름상 coreai-optcoreai-torch로 변환하기 직전 단계, 즉 모델을 더 작고 빠르게 만드는 준비 과정에 해당합니다. API는 PyTorch 사용자에게 익숙한 prepare 및 finalize 패턴을 따릅니다. 아래는 내장 프리셋(preset)을 사용해 INT8 가중치 전용(weight-only) 양자화를 적용하는 예시입니다.

import torch
from coreai_opt.quantization import Quantizer, QuantizerConfig
from torch import nn

# A simple model and example input.
model = nn.Sequential(nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 10)).eval()
example_inputs = (torch.randn(1, 128),)

# Apply INT8 weight-only quantization using a built-in preset.
config = QuantizerConfig.presets.w8()
quantizer = Quantizer(model, config)
prepared_model = quantizer.prepare(example_inputs)

# Finalize for Core AI export.
finalized_model = quantizer.finalize()

QuantizerConfig.presets.w8() 같은 프리셋으로 흔한 설정을 빠르게 적용하고, prepare()로 모델을 준비한 뒤 finalize()로 Core AI 내보내기에 적합한 형태로 마무리하는 구조입니다. 더 세밀한 옵션과 워크플로우는 호스팅된 coreai-optimization 공식 문서에서 확인할 수 있습니다.

coreai-optimization 더 알아보기

Core AI Optimization 공식 문서 - 양자화, 팔레타이제이션, 가지치기 API와 상세 워크플로우

coreai-optimization GitHub 저장소

Core AI 프레임워크, Swift로 모델을 실행하기

변환과 압축을 거쳐 .aimodel 파일이 만들어지면, 이제 Apple 기기 위에서 실제로 추론을 수행할 차례입니다. 이 역할을 맡는 것이 Core AI 프레임워크의 Swift API입니다. .aimodel 파일은 앱의 지능형 기능을 구동하는 하나 이상의 추론 함수(inference function) 를 담고 있으며, Xcode 프로젝트나 Swift 패키지에 직접 번들로 넣거나 네트워크로 내려받을 수 있습니다.

핵심 흐름은 모델을 적재(load)하고, 함수를 불러오고, 입력 텐서를 만들어 실행한 뒤, 출력을 읽는 것입니다. 모델 적재는 .aimodel 파일로부터 AIModel을 생성하는 것으로 시작합니다.

import CoreAI

// Specialize the model for this device and load it.
let model = try await AIModel(contentsOf: urlOfModel)

// Load a function from the model.
guard let function = try model.loadFunction(named: "main") else {
    // Handle case where expected function is not found.
}

AIModel 생성이 비동기(async)인 이유는 특화(specialization) 때문입니다. Core AI는 현재 기기에서 사용 가능한 모든 컴퓨트 유닛(CPU, GPU, Neural Engine)을 고려해 최고의 성능을 내는 조합을 선택하는데, 이 특화 과정이 끝나야 유효한 AIModel이 반환됩니다. 모델 크기에 따라 특화에는 상당한 시간이 걸릴 수 있으므로, Core AI는 특화 결과를 캐시(AIModelCache)에 저장하고, 빌드 시점에 미리 컴파일하는 coreai-build 도구로 기기에서의 특화 시간을 줄이는 길도 함께 제공합니다.

실제 추론에서는 입력과 출력 텐서를 NDArray라는 다차원 배열 타입으로 다룹니다. NDArray는 기본적으로 읽기 전용이며, 데이터를 쓰려면 mutableView로 가변 뷰(mutable view)를, 읽으려면 view로 읽기 뷰를 얻습니다. Swift가 이를 컴파일 타임에 강제하므로 데이터 접근 방식이 항상 명확합니다.

// Create an `NDArray` that matches the expected type and shape.
var input = NDArray(shape: [3, 4], scalarType: .float32)

// Access a mutable view to write data into the array.
var mutableView = input.mutableView(as: Float.self)
guard let elements = mutableView.contiguousElements else {
    // Handle non-contiguous memory layout.
}
writeInputData(into: elements)

// Run the function with the `NDArray` input.
var outputs = try await function.run(inputs: ["input": input])

추론 결과는 InferenceValue 타입으로 반환되며, .ndArray 또는 이미지인 경우 .pixelBuffer로 접근합니다. 각 추론 함수는 입력과 출력의 이름, 타입, 형태를 기술하는 InferenceFunctionDescriptor를 노출하므로, 앱이 제공하는 입력이 함수가 기대하는 형태 및 타입과 맞는지 런타임에 검증하거나, 배포마다 달라지는 입출력에 코드 변경 없이 동적으로 적응할 수도 있습니다. 또한 Xcode의 모델 뷰어에서는 .aimodel을 선택해 파라미터 수, 저장 크기, 수치 정밀도(연산 정밀도와 저장 정밀도), 함수 시그니처 등을 시각적으로 점검할 수 있습니다.

coreai-models, 바로 쓰는 모델 갤러리와 에이전트 스킬

마지막 기둥인 coreai-models는 직접 모델을 변환하기 전에 둘러보기 좋은 출발점입니다. 이 저장소는 모델 내보내기 레시피, PyTorch로 커스텀 Core AI 모델을 저작하기 위한 재사용 가능한 Python 프리미티브, 그리고 모델을 앱에 통합하는 Swift 런타임 유틸리티를 한데 모았습니다. 주요 디렉토리는 모델 카탈로그(models/), Python 프리미티브와 내보내기 유틸리티(python/), Swift 패키지(swift/), 그리고 코딩 에이전트용 스킬(skills/)로 나뉩니다.

내보내기 레시피는 Hugging Face를 비롯한 여러 소스의 인기 오픈소스 모델을 Core AI 형식으로 변환하는 방법을 담고 있습니다. 언어 모델은 토크나이저가, 확산 모델은 여러 모델을 순차로 실행하는 파이프라인이 필요한데, 이런 경우 레시피는 하나 이상의 .aimodel 파일과 함께 필요한 리소스를 담은 폴더를 만들어 줍니다. 지원 모델 목록은 저장소를 클론한 뒤 uv run coreai.model.registry --list-models 명령으로 확인할 수 있습니다(환경 관리에는 uv를 사용합니다).

흥미로운 점은 coreai-models코딩 에이전트를 위한 스킬(skills) 을 플러그인 형태로 제공한다는 것입니다. Claude Code, Codex CLI, Gemini CLI 등에 설치할 수 있는 이 스킬들은, 에이전트가 Core AI를 전문가처럼 다루도록 돕습니다. 제공되는 스킬은 다음과 같습니다.

  • working-with-coreai: coreai-torch로 내보내고 Core AI 런타임으로 실행하는, PyTorch 모델을 Apple silicon에 배포하는 엔드 투 엔드 워크플로우를 다룹니다.

  • model-authoring: BC1S 레이아웃, 연산 호환성, KV 캐시 패턴, 정밀도 규칙, MoE, 흔한 이슈 등 Apple 플랫폼에서의 온디바이스 실행을 위해 PyTorch 모델을 저작하는 경험적 규칙을 담습니다.

  • model-compression-exploration: coreai-opt로 양자화와 팔레타이제이션 등 가중치 압축 설정을 체계적으로 탐색합니다.

다만 coreai-models는 출시 시점 기준으로 코드 기여(pull request)는 받지 않고 있으며, 대신 GitHub 이슈를 통한 버그 신고와 모델 요청은 환영한다고 명시하고 있습니다.

Core ML, ExecuTorch, MLX 사이에서 Core AI의 자리

Core AI를 이해할 때 가장 자연스러운 질문은 "기존의 온디바이스 경로들과 무엇이 다른가"입니다. 먼저 같은 Apple 생태계 안에서 Core ML은 의사결정 트리나 표 형식 데이터처럼 신경망이 아닌 모델 유형을 계속 담당하고, Core AI는 현대적인 신경망 추론을 새롭게 책임지는 식으로 역할이 나뉩니다. 과거 PyTorch에서 Apple 기기로 가는 길이 주로 coremltools를 통한 Core ML 변환이었다면, 이제 LLM과 확산 모델처럼 무겁고 동적인 신경망에 대해서는 coreai-torch.aimodel → Core AI 런타임이라는 새로운 1급 경로가 생긴 셈입니다.

PyTorch 진영의 다른 온디바이스 솔루션과 비교하면 차이가 더 선명해집니다. Meta의 ExecuTorch는 마이크로컨트롤러부터 스마트폰까지 다양한 하드웨어를 백엔드 델리게이트(delegate) 구조로 폭넓게 아우르는 PyTorch 네이티브 엣지 배포 프레임워크입니다. 실제로 ExecuTorch에 MLX 델리게이트를 붙여 Apple Silicon GPU에서 PyTorch 모델을 실행하는 시도도 있었습니다. 반면 Apple의 MLX는 Apple silicon에 네이티브로 설계된 배열 프레임워크로, 통합 메모리(unified memory)를 적극 활용합니다.

이러한 흐름 속에서 Core AI의 차별점은 Apple이 직접, 자사 OS와 칩에 깊이 통합된 형태로 제공하는 수직 통합 스택 이라는 데 있습니다. CPU, GPU, Neural Engine을 모두 고려해 기기별로 모델을 특화하고, Xcode 및 Core AI Debugger와 한 몸으로 묶이며, PyTorch 저작과 변환부터 Swift 실행까지를 공식 도구 체인으로 잇습니다. 어느 한 도구가 다른 도구를 곧바로 대체한다기보다는, 온디바이스 AI를 향한 선택지가 그만큼 두터워졌다고 보는 편이 정확합니다.

가용성과 라이선스

Core AI 프레임워크는 iOS, iPadOS, macOS, tvOS, visionOS, watchOS의 27.0 버전에서 도입되었으며(현재 베타), 모델 통합과 실행에는 macOS 및 iOS 27.0 이상과 Xcode 27.0 이상이 필요합니다. PyTorch 쪽 도구인 coreai-torch, coreai-optimization, coreai-models는 모두 BSD 3-Clause License로 공개되어, 연구 목적은 물론 상업적 용도로도 자유롭게 사용 및 수정이 가능합니다. coreai-torchcoreai-opt는 각각 pip install coreai-torch, pip install coreai-opt로 PyPI에서 바로 설치할 수 있습니다.

:scroll: Apple Core AI 공식 문서

:github: coreai-torch GitHub 저장소

:github: coreai-models GitHub 저장소

더 읽어보기




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다!
텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다. :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck:

1개의 좋아요