kimodo.cpp 소개
텍스트로 3D 사람 모션을 만들어 내는 모델을 로컬에서 써 보려고 하면, 모델 자체보다 주변 환경이 먼저 문제가 됩니다. 파이썬과 PyTorch, CUDA 버전이 맞아야 하고, 텍스트를 벡터로 바꾸는 인코더와 모션을 만들어 내는 확산 모델이 동시에 GPU 메모리에 올라가며, 그 둘이 각각 다른 의존성 트리를 끌고 옵니다. 결과물을 게임 엔진이나 그래픽 도구에 넣으려면 다시 파이썬 밖으로 데이터를 꺼내야 합니다. 모델을 애플리케이션에 붙이려는 사람에게는 추론(Inference) 자체보다 이 연결 작업이 더 오래 걸립니다.
이번에 소개할 kimodo.cpp는 NVIDIA가 공개한 텍스트 기반 모션 생성 모델 Kimodo (
Kimodo: NVIDIA가 공개한, 텍스트를 기반으로 한 인간 및 로봇의 고품질 3D 모션 생성 모델)를 ggml과 C++만으로 다시 구현한 프로젝트입니다. 파이썬 런타임(Runtime)도 PyTorch도 없이 실행 파일 하나가 UTF-8 프롬프트를 받아 SMPL-X22 골격의 관절 회전값과 루트 이동값을 만들어 냅니다. 연산은 CPU에서도 Vulkan GPU에서도 돌아가고, 두 경로가 같은 결과를 내는지 확인하는 대조 테스트가 저장소에 함께 들어 있습니다. 같은 계열의 시도로는 커뮤니티에 소개된 SAM3DBody-cpp가 있는데, 그쪽이 영상에서 몸을 복원하는 방향이라면 이쪽은 문장에서 움직임을 만들어 내는 방향입니다.
프로젝트는 ggml과 gguf에만 직접 연결하고 llama.cpp 전체를 가져오거나 링크하지 않습니다. 텍스트 인코더로 쓰이는 LLM2Vec이 일반 Llama 어텐션을 양방향으로 바꾸고 MNTP 계열 어댑터를 적용한 뒤 평균 풀링(Mean Pooling)을 하기 때문에, 인과적(Causal) 방식으로 동작하는 기성 런타임을 감싸서는 결과가 정확히 맞지 않는다는 것이 그 이유입니다. 그래서 Llama-3 바이트 단위 BPE 토크나이저와 LLM2Vec이 실제로 쓰는 Llama 구성 요소만 골라 GGML 연산으로 직접 작성했습니다. 임베딩과 RMSNorm, 회전 위치 인코딩, Q/K/V/O 투영, 게이트 MLP, 잔차 스택, 비인과 어텐션 마스크, 평균 풀링까지가 그 목록이고, 생성이나 KV 캐시, 샘플링, 서버, 멀티모달 같은 llama.cpp의 나머지 기능은 들어 있지 않습니다.
kimodo.cpp가 구현한 범위와 아직 아닌 것
지금 동작하는 체크포인트는 Kimodo-SMPLX-RP-v1 하나입니다. 프롬프트 하나에 샘플 하나, 제약 조건 없는 모션, 후처리 없음이 첫 배포 범위이고, 결과는 초당 30프레임짜리 SMPL-X22 관절 회전 시퀀스와 루트 이동값으로 나옵니다. 프로젝트가 완료로 표시한 항목은 검사를 거치는 GGUF 로딩, safetensors 변환, DDIM(Denoising Diffusion Implicit Models) 샘플링, C와 C++ API, CPU와 Vulkan 대조 테스트, 그리고 로컬 텍스트 투 모션 데모입니다.
아직 들어 있지 않은 것도 프로젝트가 같은 자리에 적어 두었습니다. 제약 조건(Constraints), SOMA 체크포인트, G1 골격 변형, GLB 내보내기, 양자화(Quantization)된 모델이 미구현 목록입니다. 특히 뒤의 두 가지가 실무에서 미치는 영향이 큽니다. GLB 내보내기가 없으면 결과를 그래픽 도구에 바로 넣을 수 없어 첫 CLI 출력인 NPZ와 JSON 메타데이터를 직접 변환해야 하고, 양자화 모델이 없으면 F32 가중치를 그대로 올려야 하므로 메모리 여유가 필요합니다. SOMA는 커뮤니티에도 별도로 소개된 인체 표현 레이어인데, 프로젝트는 첫 배포 범위가 통과한 뒤 SOMA 체크포인트를 주요 품질 기준으로 올릴 예정이라고 밝히고 있습니다.
kimodo.cpp가 텍스트 인코더와 디노이저를 분리한 이유
kimodo.cpp의 모델 핸들은 모션 GGUF와 텍스트 GGUF 두 개를 메모리 맵으로 들고 있지만, 둘을 동시에 백엔드에 올려 두지는 않습니다. 프롬프트가 들어오면 먼저 텍스트 세션을 만들어 토큰화하고 양방향 Llama 추론을 수행한 뒤 평균 풀링으로 4096개의 실수값을 얻고, 그 임베딩을 호스트 캐시로 복사한 다음 텍스트 세션과 그 백엔드 버퍼를 파괴합니다. 그러고 나서야 모션 세션을 만들어 임베딩을 올리고 DDIM 100회 반복으로 이뤄진 두 단계 디노이저를 끝까지 실행합니다.
프로젝트는 이 방식이 상위 파이썬 구현보다 의도적으로 더 보수적이라고 설명합니다. 원본은 텍스트 인코더와 디노이저 객체를 모두 살려 두는데, 텍스트 인코더가 80억 파라미터 규모의 Llama 3 기반이라 둘을 함께 올리면 최대 GPU 메모리 사용량이 그만큼 커집니다. kimodo.cpp는 지연 시간을 조금 내주고 메모리 최대치를 낮추는 쪽을 택했고, 나중에 --keep-text-loaded 같은 선택지로 반대 교환을 열어 둘 수 있다고 적어 두었습니다. 텍스트 인코더 쪽 VRAM은 별도로도 조절할 수 있는데, 기본값은 여덟 계층씩 묶어 처리하는 것이고 KIMODO_TEXT_LAYER_CHUNK 환경 변수로 1에서 32까지 바꿀 수 있습니다.
또한 같은 프롬프트를 반복해서 쓰는 경우를 위해 임베딩 캐시도 있습니다. 캐시 키는 텍스트 모델 식별자와 어댑터 식별자, 토크나이저 식별자, 그리고 UTF-8 프롬프트 원문을 합친 값의 SHA-256이라, 넷 중 하나라도 달라지면 캐시가 재사용되지 않습니다. 미리 계산해 둔 4096차원 임베딩을 직접 넣는 경로도 열려 있어서, 텍스트 인코더를 아예 건너뛰고 디노이저만 검증하거나 여러 프롬프트를 일괄 생성할 때 쓸 수 있습니다.
kimodo.cpp가 원본과의 일치를 확인하는 방법
이식 프로젝트에서 가장 어려운 부분은 동작시키는 것이 아니라 원본과 같은 값이 나오는지 확인하는 것입니다. kimodo.cpp는 파이썬 원본과 소스 파일을 한 줄도 공유하지 않고, 둘을 잇는 유일한 접점을 버전이 붙은 검사 대상 테스트 데이터로 두었습니다. 상위 구현에서 단계별 중간값을 추출해 고정 데이터로 저장한 뒤, C++ 구현이 그 값을 재현하는지 경계마다 대조하는 방식입니다:
| 고정 데이터 | 대응하는 C++ 테스트 |
|---|---|
| Llama 토큰 ID, 마스크, 최종 상태, 풀링된 임베딩 | 토크나이저와 텍스트 인코더 일치 |
| 루트 모델 입출력 | 루트 트랜스포머 일치 |
| 전역 루트에서 지역 루트로의 변환 결과 | 모션 표현 변환 일치 |
| 바디 모델 입출력 | 바디 트랜스포머 일치 |
| CFG(Classifier-Free Guidance)로 합성한 예측값 | CFG 일치 |
DDIM x(t-1) |
샘플러 일치 |
| 전체 확산 상태와 복원된 모션 | 전체 파이프라인 일치 |
| 후처리된 모션 | C++ 보정 코드 일치 |
고정 데이터에는 상위 저장소의 Git 커밋과 체크포인트 텐서 해시, 모델 설정, 장치, PyTorch와 CUDA 버전, 프롬프트, CFG 설정, 프레임 수, 초기 노이즈가 함께 기록됩니다. 테스트는 배열을 비교하기 전에 이 메타데이터부터 확인하고 어긋나면 거부하므로, 다른 조건에서 뜬 값과 우연히 맞춰 보는 사고가 나지 않습니다. 초기 노이즈를 저장해 두고 참조 테스트가 그것을 읽어 쓰는 것도 같은 이유입니다. 난수 시드가 두 구현에서 같은 값을 만들어 준다고 가정하지 않습니다.
변환 경로에도 안전장치가 있습니다. 체크포인트는 격리된 파이썬 컨테이너에서만 다루고, 일반 변환기는 safetensors만 읽습니다. 상위 모델이 예전 방식의 PyTorch pickle 체크포인트를 쓰는 경우에는 참조 컨테이너가 그것을 한 번만 읽어 해시로 검사한 safetensors 중간 파일로 바꾸고, C++ 쪽과 일반 변환 경로는 pickle을 절대 역직렬화하지 않습니다. 신뢰할 수 없는 입력으로 다뤄야 하는 지점을 명확히 나눠 둔 구성입니다.
kimodo.cpp 빌드와 실행
리눅스 기준 준비물은 C++23 컴파일러, CMake 3.25 이상, Ninja, Hugging Face CLI가 설치된 Python 3이며, Vulkan을 쓰려면 로더와 헤더가 추가로 필요합니다. GGML은 고정된 Git 서브모듈로 들어 있습니다:
git submodule update --init --recursive
scripts/download_gguf_weights.sh --output "$PWD"
cmake --preset debug
cmake --build --preset debug
ctest --preset debug
다만 표준 테스트 스위트는 로컬 모션 GGUF와 텍스트 번들, 고정 데이터를 요구하며 스스로 가중치를 내려받지 않습니다. release, asan-ubsan, fuzz 프리셋도 함께 제공됩니다. 의존성을 재현 가능하게 갖추고 싶으면 Nix 플레이크를 쓸 수 있고, 소독기(Sanitizer) 작업에서 누수 검출이 꺼져 있는 것은 Vulkan 로더와 드라이버의 할당이 프로세스 전역이기 때문입니다. GGUF 파서 퍼저는 Clang이 필요합니다.
공개 API는 include/kimodo/kimodo_capi.h의 평탄한 C 인터페이스입니다. 모델을 올릴 때 모션 GGUF와 텍스트 번들을 먼저 검사하고, 미리 계산한 임베딩을 넣을 때는 kimodo_generate_embedding으로 4096개의 F32 값을 주며, 문장에서 시작할 때는 kimodo_generate를 씁니다. 두 함수 모두 SMPL-X22의 루트 이동값과 지역 XYZW 회전값을 돌려줍니다.
결과를 눈으로 보려면 저장소에 포함된 로컬 데모를 실행하면 됩니다. 디버그 프리셋을 빌드하고 네이티브 GGUF 번들을 내려받은 뒤 다음을 실행하고 http://localhost:8094를 열면 됩니다:
go run ./demo -addr 0.0.0.0:8094
왼쪽 사이드바에 프롬프트 입력창과 기록이 남아 있어서, 이전에 만든 애니메이션을 고르면 그 프롬프트가 복원되어 새로 생성할 수 있습니다.
kimodo.cpp의 가중치와 사용 조건
바로 쓸 수 있는 네이티브 GGML 가중치는 Hugging Face의 LocalAI-io 조직에 올라와 있습니다. GitHub 조직명 localai-org와 이름이 달라 혼동하기 쉬운 부분입니다. 재사용 가능한 텍스트 인코더 Llama-3-Kimodo-GGML과 상위 저장소에 연결된 확산 모델 Kimodo-SMPLX-RP-v1-GGML이 따로 배포되어 있어서 사용자가 직접 변환할 필요가 없고, 설치 스크립트가 공개된 매니페스트와 SHA-256 해시를 검증합니다. 이미 4096차원 임베딩을 가지고 있다면 --motion-only로 모션 모델만 받을 수 있습니다.
이용 조건은 이 프로젝트를 검토할 때 가장 먼저 확인해야 하는 항목입니다. 저장소에는 LICENSE 파일이 없고 NOTICE 파일만 있으며, 그 내용은 ggml 저작권 표시와 데모가 LocalAI 로고를 쓴다는 고지뿐입니다. 코드 자체를 어떤 조건으로 쓸 수 있는지는 저장소만 보고는 확인되지 않습니다. 가중치 쪽 조건은 프로젝트가 직접 밝혀 두었는데, GGUF 번들에 변환된 Meta Llama 3 자산이 포함되어 있고 Kimodo는 비상업 연구 전용이므로 내려받거나 재배포하기 전에 공개된 모델 카드와 상위 라이선스를 확인하라고 안내하고 있습니다. 번들을 직접 다시 만드는 경우에는 SMPL-X 체크포인트와 Llama 기반 모델이 모두 접근 승인이 필요한 자산이라 Hugging Face 인증을 거쳐야 합니다.
kimodo.cpp는 누구에게 맞는가
모션 생성 모델을 파이썬 밖의 애플리케이션에 넣으려는 개발자에게 kimodo.cpp가 실질적인 값어치가 있습니다. 평탄한 C ABI와 단일 실행 파일 구조라 게임 엔진이나 도구 체인에 붙이기 쉽고, 텍스트 인코더를 분리해 두어서 임베딩을 미리 만들어 두면 실행 시점에 80억 파라미터 모델을 올리지 않아도 됩니다. 원본과의 일치를 단계마다 고정 데이터로 확인하는 구조라 이식 구현을 직접 만들어 보려는 사람에게도 참고할 만한 설계 문서가 함께 있습니다.
반대로 지금 바로 완성된 3D 애셋을 만들어 내야 하는 팀에게는 kimodo.cpp가 아직 이른 선택입니다. GLB 내보내기가 미구현이라 NPZ와 JSON을 직접 변환해야 하고, 양자화 모델이 없어 F32 가중치를 그대로 올려야 하며, 제약 조건과 SOMA, G1 변형도 아직 들어오지 않았습니다. 무엇보다 코드의 이용 조건이 저장소에서 확인되지 않고 가중치는 비상업 연구 전용이므로, 상업적 사용을 전제로 한 프로젝트라면 상위 라이선스부터 확인한 뒤에 검토해야 합니다.
kimodo.cpp 프로젝트 GitHub 저장소
kimodo.cpp 구현 설계 문서
kimodo.cpp용 GGML 변환 가중치 (LocalAI-io)
NVIDIA Kimodo 프로젝트 페이지 (이식 대상 원본 모델)
더 읽어보기
이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. ![]()
이 도구를 직접 설치해 사용해보셨다면, 파이토치 한국 사용자 모임
회원들을 위해 경험이나 팁을 댓글로 남겨주세요! ![]()

