라이선스 미확인 OSS는 기사화할 수 없었지만, GPU 측의 '작동 불가' 문제는 sglang 패치로 극복
요약
본 글은 TokenRouter의 검증 과정에서 발생한 기술적 난관을 다룹니다. 라이선스 문제로 인해 도구 자체를 주요 소재로 삼지는 못했지만, 최신 GPU(Blackwell) 환경에서 sglang이 작동하지 않는 문제를 직접 패치하여 해결하는 과정을 상세히 설명합니다.
핵심 포인트
- TokenRouter는 여러 LLM을 토큰 단위로 분배해 비용을 낮추는 라우팅 방식입니다.
- 최신 GPU 세대(Blackwell, sm_120)에서 sglang이 작동하지 않는 문제는 라이브러리 빌드 문제였습니다.
- sgl-kernel의 최신 버전과 torch와의 ABI 호환성을 확인하며 문제를 해결했습니다.
- 궁극적으로는 sglang 서버 자체에 패치를 적용하여 GPU 세대 의존성 문제를 극복했습니다.
필자는 해외 AI 관련 뉴스를 매일 1건씩 검증하여 발신하는 챌린지의 14일차로서, Hugging Face Daily Papers에 게재된 TokenRouter(thu-nics)를 검증해 보려고 했다. 이 기술은 여러 LLM을 토큰 단위로 동적으로 분배하고, 큰 모델과 작은 모델을 조합하여 추론 비용을 낮추는 라우팅 방식의 구현이다.
결론부터 말하자면, TokenRouter 자체의 라이선스가 미확정이었기 때문에, 이 도구의 코드나 검증 결과를 기사의 주요 소재로 삼을 수는 없었다. 한편, 검증 과정에서 부딪혔던 '최신 세대 GPU에서는 작동하지 않는다'는 또 다른 장벽은, 최종적으로 본인이 직접 sglang(TokenRouter가 의존하는 추론 서버)의 소스에 패치를 적용함으로써 실제로 극복할 수 있었다. 이번 글에서는 그 과정을 다루고자 한다.
첫 번째 벽: 라이선스가 미확정
검증을 시작하기 전에, CLAUDE.md의 '라이선스를 확인하는' 규칙에 따라 리포지토리를 확인했다.
$ find /tmp/tokenrouter-license-check -iname "*licen*" -o -iname "*copying*" -o -iname "*notice*"
(해당 파일 없음)
리포지토리 루트에 LICENSE, COPYING, NOTICE 중 어느 것도 존재하지 않았다. pyproject.toml의 classifiers에 `
(sglang이 사용하는 CUDA 커널 구현 패키지(당시 버전은 0.3.8)가 포함하는 사전 컴파일된 바이너리에, RTX 50 시리즈(Blackwell, sm_120)용 커널 이미지가 포함되어 있지 않았다. torch 자체는 cu128 빌드로 Blackwell에 대응하고 있었지만, sgl-kernel의 바이너리 배포가 그 속도를 따라가지 못하고 있었다. 이는 'GPU 유무'의 문제가 아니라 'GPU 세대에 대해 의존 라이브러리의 빌드가 적절히 따라오고 있는지 여부'라는 또 다른 종류의 장벽이었다.
회피책 1: sgl-kernel을 새 버전으로 교체하기
sgl-kernel의 새로운 버전이라면 Blackwell에 대응하고 있지 않을까 하는 가설을 실제로 시도했다. torch==2.8.0은 변경하지 않은 채, sgl-kernel만 단계적으로 최신 버전으로 교체하며 import가 가능한지(torch와의 C++ ABI 호환성이 있는지)를 이분 탐색했다.
| sgl-kernel 버전 | torch==2.8.0과의 import |
|---|---|
| 0.3.8 (원래 지정) | OK (단, RMSNorm에서 sm_120 미지원 오류) |
| ... | |
| 최신 버전인 0.3.21은 이쪽의 torch보다 더 새로운 버전을 대상으로 빌드된 듯하여, C++ 심볼 불일치로 인해 import조차 실패했다. 0.3.9부터 0.3.18까지는 import 자체에는 문제가 없었다. |
import가 가능했던 최신 버전인 0.3.18에서 문제의 RMSNorm 커널만 직접 호출하여 확인한 결과, 실제로 Blackwell 위에서 정상적으로 동작했다.
from sgl_kernel import rmsnorm
out = rmsnorm(x, w, 1e-6) # RTX 5060 Ti에서 정상 종료
sgl_kernel 패키지 안에 아키텍처별 바이너리(sm90, sm100)의 디렉터리가 새로 생겨나 있었고, sm_120 GPU에는 sm100용 바이너리가 사용되도록 하는 구조가 되어 있었다. 0.3.8 시점에서는 이러한 분할 자체가 없었으며, Blackwell 커널 이미지가 빠져있었던 것이었다.
회피책 1의 장벽: sglang 본체가 새로운 API를 따라가지 못함
여기서 만족하지 않고, sgl-kernel==0.3.18로 교체한 상태에서 sglang==0.5.1(TokenRouter 지정 버전) 서버를 실제로 구동해 보았다. 그러자 RMSNorm과는 다른 지점에서 멈췄다.
ImportError: cannot import name 'fused_marlin_moe' from 'sgl_kernel'
sgl-kernel 측에서 MoE/Marlin 양자화 관련 함수군이 재구성되면서, fused_marlin_moe라는 이름의 함수가 사라졌다(moe_wna16_marlin_gemm 등으로 대체되었다). sglang==0.5.1은 이 함수를 양자화를 사용하든 안 하든 구동 시점에 무조건 import하기 때문에, 서버 자체가 구동되지 못했다.
회피책 2: 사용되지 않는 기능의 import만 지연시키기
여기서 소스 코드를 들여다보았다. fused_marlin_moe가 실제로 호출되는 곳은, sglang의 전체 소스에서 단 2군데(awq.py와 gptq.py, 각각 AWQ/GPTQ 버전 MoE 양자화 메서드 내부)뿐이었다. 내가 로컬에서 구동하는 Qwen3-0.6B는 bf16(양자화 없음)이므로, 둘 다 실행 시점에는 한 번도 호출되지 않았다. 문제는 'import되었는지 여부'이지, '호출되는지 여부'가 아니었다.
로컬의 .venv에 설치된 sglang 패키지의 이 두 파일에만, import를 try/except로 감싸는 최소한의 패치를 적용했다(TokenRouter 리포지토리나 sgl-kernel 본체에는 변경을 가하지 않았다).
if _is_cuda:
from sgl_kernel import awq_dequantize, awq_marlin_moe_repack, awq_marlin_repack
try:
...
이 상태로 서버를 재구동하자, 이전에 충돌했던 첫 번째 추론 요청을 정상적으로 통과했다.
curl http://127.0.0.1:30003/generate -d '{"text": "The capital of France is", "sampling_params": {"max_new_tokens": 16, "temperature": 0}}'
{"text":" Paris. The capital of France is also the capital of the Republic of France.", ...}
에러 없이 끝까지 생성이 완료되었다. 0.6B 모델의 greedy decoding으로 인해 문장 자체는 다소 반복적이지만, Blackwell 위에서 TokenRouter가 의존하는 추론 스택이 끝까지 작동했다는 사실 자체가 중요했다.
요약
이번에는 TokenRouter 자체의 라이선스가 미확정이었기 때문에 그 검증 결과를 기사의 주인공으로 삼을 수는 없었다. 하지만 검증 과정에서 마주친 '최신 세대 GPU에서는 의존 라이브러리가 따라가지 못하고 있다'는 벽은, (1) 의존 패키지를 새로운 버전으로 교체하고, (2) 그럼에도 남아있는 작은 API의 불일치를 소스를 읽어 패치하는, 이 두 단계의 작업을 통해 실제로 극복할 수 있음을 확인했다.
에러 메시지만 보고 '작동하지 않는다'고 끝내지 않고, 의존 관계 속에서 어느 버전의 어떤 함수가 문제인지 실제로 분리해 나가다 보면, 의외로 작은 변경만으로 해결되는 경우가 있다. 막 출시된 GPU 세대를 사용하고 있다면, 앞으로도 이런 '라이브러리 빌드가 아직 따라가지 못하고 있다'는 벽에 몇 번이나 부딪힐 것 같지만, 이번처럼 절차를 분해하여 확인해 나간다면 극복할 수 있는 경우도 있다는 것을 알게 된 것은 좋은 수확이었다.
- 출처(라이선스 미확정으로 전재하지 않음): https://github.com/thu-nics/TokenRouter
- 패치 대상:
sglang==0.5.1
(Apache-2.0, https://github.com/sgl-project/sglang ) - 검증 환경: NVIDIA GeForce RTX 5060 Ti(16GB, Blackwell/sm_120),
torch==2.8.0+cu128
논의

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기