2025년 9월 30일 화요일

유전자 단백질 분석을 위한 알파폴드 모델과 GNN 관계, 그리고 동작 메커니즘

이 글은 구글 딥마인드(DeepMind)가 개발하여 생명과학계에 혁신을 가져온 단백질 3차원 구조 예측 모델, 알파폴드2(AlphaFold2)의 핵심 딥러닝 아키텍처를 정리한다. 

알파폴드2의 성공은 트랜스포머(Transformer)의 어텐션 메커니즘을 그래프 신경망(GNN)의 관계형 추론 프레임워크에 통합하고, 3차원 공간적 제약을 직접 모델링한 결과물이다. 이 글은 알파폴드2의 주요 구성요소인 다중 서열 정렬(MSA), 이보포머(Evoformer), 구조 모듈(Structure Module)의 역할을 기술하고, 이러한 구조가 GNN 및 트랜스포머의 원리와 어떻게 결합되는지 심도 있게 고찰하고자 한다.

머리말
단백질의 기능은 고유한 3차원 입체 구조에 의해 결정되므로, 아미노산 서열로부터 3차원 구조를 예측하는 '단백질 접힘 문제'는 지난 50년간 생명과학 분야의 핵심적인 난제였다. 기존의 실험적 방법들은 막대한 시간과 비용이 소요되어 단백질 연구의 큰 장벽으로 작용해왔다.

이러한 상황에서 2020년 구글 딥마인드가 발표한 알파폴드2는 딥러닝을 통해 이 문제를 전례 없는 정확도로 해결하며 해당 분야의 패러다임을 전환시켰다. 본 보고서는 알파폴드2의 기술적 근간을 이루는 딥러닝 아키텍처를 세부적으로 분석하여, 그 성공 요인을 규명하는 데 중점을 둔다.

알파폴드2 아키텍처의 핵심 구성요소
알파폴드2의 시스템은 입력된 아미노산 서열로부터 3차원 구조를 예측하기까지, 여러 독창적인 모듈이 유기적으로 연동되는 파이프라인으로 구성된다.

다중 서열 정렬 (Multiple Sequence Alignment, MSA)
알파폴드2는 단일 아미노산 서열이 아닌, 방대한 유전체 데이터베이스 검색을 통해 확보한 수천 개의 유사 서열 묶음, 즉 MSA를 주된 입력으로 활용한다. 이는 진화 과정에서 특정 위치의 아미노산이 변이될 때, 다른 위치의 아미노산도 함께 변이되는 '공진화(Co-evolution)' 정보를 포착하기 위함이다. 공진화 관계에 있는 아미노산 쌍은 3차원 구조상에서 물리적으로 근접할 확률이 높기 때문에, 이는 구조 예측의 결정적인 단서로 작용한다.

이보포머 (Evoformer): 그래프 기반 추론 엔진
이보포머는 MSA 정보로부터 구조적 단서를 추론하는 알파폴드2의 핵심 엔진이다. 이 모듈은 두 종류의 정보를 병렬적으로 처리하고 상호작용시키며 반복적으로 정교화한다.

MSA 표현 (1D 정보): MSA 내 아미노산 서열 간의 관계를 나타낸다.
쌍 표현 (Pair Representation, 2D 정보): 아미노산 쌍(i, j) 사이의 거리 및 방향과 같은 기하학적 관계를 행렬 형태로 나타낸다. 이는 사실상 그래프의 인접 행렬과 유사한 역할을 수행한다.

이보포머 내부에서는 트랜스포머의 어텐션(Attention) 메커니즘이 MSA와 쌍 표현 사이의 정보 교환을 촉진한다. 즉, 서열의 공진화 정보가 두 아미노산이 가까울 것이라는 구조 정보를 강화하고, 역으로 특정 아미노산 쌍이 가깝다는 정보가 MSA 내의 관계를 재해석하는 데 도움을 준다. 이 과정이 수십 개의 이보포머 블록을 거치며 반복되어, 구조에 대한 예측은 점차 명확해진다.

구조 모듈 (Structure Module): 3차원 좌표 생성
이보포머를 통해 최종적으로 정제된 쌍 표현 행렬은 각 아미노산 쌍의 기하학적 관계에 대한 신뢰도 높은 지도로 볼 수 있다. 구조 모듈은 이 지도를 바탕으로 각 아미노산을 하나의 강체(rigid body)로 간주하고, 이들의 3차원 공간상 위치(회전 및 변환)를 직접적으로 예측한다. 이 과정에서는 '불변점 어텐션(IPA)'이라는 특수 메커니즘을 사용하여, 예측된 단백질 전체가 회전하거나 이동하더라도 내부의 상대적인 구조는 변하지 않는 물리적 일관성을 보장한다.

GNN과 트랜스포머 관점에서의 아키텍처 융합
알파폴드의 핵심적인 혁신은 GNN의 관계형 추론 프레임워크와 트랜스포머의 강력한 정보 교환 방식을 3차원 공간 문제에 맞게 융합한 데 있다.

GNN 프레임워크: 알파폴드는 단백질을 아미노산(노드)과 이들 간의 상호작용(엣지)으로 구성된 완전 연결 그래프(Fully Connected Graph)로 간주한다. 쌍 표현(Pair Representation)은 이 그래프의 엣지 가중치를 동적으로 학습하는 역할을 수행한다.

트랜스포머의 어텐션 메커니즘: 알파폴드는 GNN의 메시지 전달 과정을 트랜스포머의 어텐션으로 구현한다. 일반적인 GNN이 1홉(hop) 이웃의 정보만 취합하는 것과 달리, 어텐션은 모든 노드가 다른 모든 노드와 직접적으로 정보를 교환하도록 한다. 이를 통해 모델은 어떤 노드의 정보를 더 중요하게 참고할지(Attention Score)를 학습하여 전역적인 문맥을 효과적으로 파악한다. 이보포머 블록을 반복하는 것은 GNN 레이어를 여러 겹 쌓는 것과 동일한 효과를 낸다.

3차원 공간 정보의 직접적 활용: 전통적인 GNN이 추상적인 연결성을 다루는 반면, 알파폴드의 구조 모듈은 3차원 공간에서의 회전과 변환이라는 기하학적 특징을 직접적으로 다룬다. '불변점 어텐션(IPA)'은 이러한 3차원 변환에도 예측의 일관성을 유지하게 하는 핵심 장치로, 이는 GNN이 실제 물리 공간의 제약을 학습하도록 진화한 형태로 볼 수 있다.

구조(Structure)와 기능(Function)의 차이
알파폴드의 역할을 정확히 이해하기 위해서는 예측 목표가 단백질의 '기능'이 아닌 '구조'라는 점을 명확히 해야 한다.

알파폴드는 특정 단백질이 어떤 역할을 수행하는지(예: '신호 전달')를 직접 분류하는 기능 예측 모델이 아니다. 대신, 해당 단백질을 구성하는 모든 원자의 3차원 공간 좌표(x, y, z)를 예측하여 물리적인 형태(Shape)를 알아내는 구조 예측 모델이다.

구조 예측이 생명과학에서 결정적으로 중요한 이유는 "구조가 기능을 결정한다(Structure Dictates Function)"는 근본 원리 때문이다. 특정 효소 단백질이 화학 반응을 촉진하는 기능은, 그 표면에 특정 분자만 결합할 수 있는 고유한 3차원 홈(활성 부위)이라는 구조를 가지고 있기 때문에 가능하다. 따라서 정확한 3차원 구조 정보는 단백질의 기능을 이해하고 제어하기 위한 가장 필수적인 전제 조건이다.

결론적으로, 알파폴드는 기능이라는 최종 목적지를 향한 여정에서 가장 어렵고 중요한 첫 관문인 '3차원 구조 설계도'를 제공하는 역할을 수행한다.

알파폴드의 3차원 공간 좌표 표현 및 정규화 방식

이 장은 딥마인드(DeepMind)의 단백질 구조 예측 모델 알파폴드(AlphaFold)가 3차원 공간 좌표를 어떻게 표현하고 예측하는지에 대한 기술적 원리를 분석하는 것을 목적으로 한다. 단백질의 3차원 구조는 전체적인 회전(Rotation) 및 이동(Translation) 변환에 대해 불변(Invariant)하는 특성을 가지므로, 절대적인 전역 좌표(Global Coordinates)를 직접 예측하는 방식은 학습에 본질적인 한계를 가진다. 본 보고서는 알파폴드가 이 문제를 해결하기 위해 도입한 지역 좌표계(Local Frame)와 상대적 변환(Relative Transformation) 기반의 독창적인 접근법을 상세히 기술한다.

문제 정의: 전역 좌표계 방식의 한계
기존의 딥러닝 모델이 3차원 객체의 구조를 예측할 때, 각 구성 요소의 절대적인 (x, y, z) 좌표를 직접 출력하도록 설계하는 것은 일반적이다. 그러나 이 방식은 단백질 구조 예측에 다음과 같은 심각한 문제를 야기한다. 

  • SE(3) 등변성(Equivariance) 위배: 단백질의 기능과 구조적 본질은 분자 전체가 3차원 공간상에서 회전하거나 이동해도 변하지 않는다. 하지만 절대 좌표 값은 이러한 변환에 따라 완전히 달라진다.
  • 학습의 비효율성: 모델은 동일한 구조에 대해서도 무한히 많은 정답(좌표 값)을 학습해야 하므로, 데이터의 복잡성이 기하급수적으로 증가하여 안정적인 학습이 거의 불가능하다.

결론적으로, 전역 좌표계는 단백질 구조의 내재적 특성을 표현하기에 부적합하며, 이를 직접 예측하는 것은 비효율적이고 불안정한 접근법이다.

알파폴드의 해결책: 지역 좌표계와 상대적 변환 예측
알파폴드는 전역 좌표 문제를 해결하기 위해, 예측 대상을 '절대 위치'에서 '상대적 관계'로 변환하였다. 이 접근법은 다음 세 단계로 구성된다.

1단계: 각 아미노산 잔기에 지역 좌표계(Local Frame) 설정

알파폴드는 단백질을 구성하는 모든 아미노산 잔기(residue)마다 고유한 지역 좌표계를 설정한다. 이 좌표계는 각 잔기의 뼈대(backbone)를 구성하는 3개의 원자(N, Cα, C')를 기준으로 정의된다.

  • 원점 (Origin): 알파탄소(Cα)
  • 축 (Axes): Cα, N, C' 원자들의 상대적 위치 벡터를 기반으로 직교 좌표계(x, y, z축)를 생성한다.

이 방식을 통해 단백질 전체의 위치와 상관없이, 각 아미노산은 자신만의 독립적인 기준 좌표계를 갖게 된다.

2단계: 좌표계 간의 상대적 변환(Transformation) 예측

알파폴드 모델의 최종 단계인 '구조 모듈(Structure Module)'은 절대 좌표를 직접 예측하지 않는다. 대신, i번째 아미노산의 지역 좌표계에서 i+1번째 아미노산의 지역 좌표계로 변환하기 위해 필요한 회전(Rotation)과 이동(Translation) 값을 예측한다.
  • 회전: 3x3 회전 행렬 (Rotation Matrix)
  • 이동: 3차원 이동 벡터 (Translation Vector)

이 상대적 변환 값은 단백질 전체의 위치나 방향과 무관하게 항상 일정하므로, 모델은 구조의 본질적인 기하학적 관계만을 학습하게 된다.

3단계: 예측된 변환을 통한 전체 구조 조립
모든 잔기 쌍에 대한 상대적 변환 값이 예측되면, 이를 순차적으로 적용하여 전체 3차원 구조를 조립한다.

첫 번째 아미노산의 지역 좌표계를 공간의 원점에 배치한다.
예측된 첫 번째 변환(회전/이동)을 적용하여 두 번째 아미노산의 위치와 방향을 계산한다.

이 과정을 단백질 서열의 마지막 잔기까지 반복하여 모든 뼈대 원자의 3차원 좌표를 최종적으로 결정한다. 

알파폴드의 접근 방식은 다음과 같은 핵심적인 장점을 가진다.

구분

전역 좌표 예측 방식

알파폴드의 지역 좌표계 방식

예측 대상

각 원자의 최종 (x, y, z) 절대 좌표

아미노산 잔기 간의 상대적 회전/이동

특징

SE(3) 등변성을 위배하여 학습이 불안정하다.

SE(3) 등변성(Equivariance)을 자연스럽게 만족하여 안정적이고 효율적인 학습이 가능하다.

비유

건물의 모든 벽돌의 GPS 좌표를 학습하는 것

한 벽돌에서 다음 벽돌까지의 방향과 거리를 학습하는 것


결론적으로, 알파폴드의 혁신은 3차원 공간 좌표라는 결과물을 직접 예측하는 대신, 문제를 지역 좌표계 간의 기하학적 관계로 재정의한 데에 있다. 이는 3D 구조 예측 문제에서 딥러닝 모델이 가져야 할 회전/이동 불변성(등변성)을 확보하는 표준적인 해법을 제시했으며, 알파폴드가 전례 없는 정확도를 달성할 수 있었던 가장 핵심적인 기술적 토대이다.

마무리
알파폴드2의 성공은 단일한 혁신이 아닌 여러 핵심 기술의 유기적인 결합에 기인한다. 그 핵심은 (1) 진화적 정보(MSA)를 초기 단서로 활용하고, (2) GNN의 프레임워크 위에서 트랜스포머의 어텐션 메커니즘을 통해 관계를 추론하며, (3) 최종적으로 3차원 공간의 물리적 제약을 만족하는 구조를 생성하는 정교한 파이프라인을 구축한 데 있다.

특히, 아미노산을 노드로, 상호작용을 엣지로 간주하는 그래프적 접근 방식은 단백질 접힘 문제를 관계형 추론 문제로 재정의하였으며, 이는 GNN과 트랜스포머 모델이 융합될 때 복잡한 과학적 시스템을 얼마나 효과적으로 모델링할 수 있는지를 입증하는 대표적인 사례이다. 알파폴드2의 등장은 단백질 구조 생물학 연구를 가속화했을 뿐만 아니라, 향후 신약 개발 및 질병 연구에 있어 AI 기반의 과학적 발견이 핵심적인 역할을 수행할 것임을 시사한다.

레퍼런스

2025년 9월 26일 금요일

고속 LLM 실행을 지원하는 vLLM 동작 원리 분석, 설치 및 사용법

이 글은 고속 LLM 실행을 지원하는 vLLM 동작 원리를 분석하고, 사용 방법을 간략히 정리한 것이다. vLLM은 대규모 언어 모델(LLM)의 추론 및 서빙을 위한 고성능 라이브러리이다.
vLLM 메모리 사용 효율성


대규모 언어 모델을 서비스로 제공할 때 가장 큰 병목 현상은 메모리에서 발생한다. 특히 트랜스포머 아키텍처의 핵심인 어텐션 메커니즘은 이전 토큰들의 키(Key)와 값(Value)을 KV 캐시라는 메모리 공간에 저장하는데, 이 공간의 비효율적인 관리가 추론 속도를 저하시키는 주된 원인이다. 기존 방식에서는 모든 요청에 대해 최대 길이를 가정하고 메모리를 미리 할당하여 심각한 낭비를 초래했다.

vLLM은 이러한 문제를 해결하기 위해 PagedAttention이라는 알고리즘을 도입한 것이다. 이는 운영체제의 가상 메모리와 페이징 기법에서 영감을 얻은 기술이다. KV 캐시를 연속된 메모리 공간에 할당하는 대신, 페이지처럼 작은 블록 단위로 분할하여 관리한다. 이로써 메모리 단편화를 거의 없애고, 실제 필요한 만큼만 동적으로 메모리를 할당하여 낭비를 최대 90% 이상 줄일 수 있다. 결과적으로 동일한 하드웨어에서 훨씬 더 많은 요청을 동시에 처리하는 높은 처리량(Throughput)을 달성하게 된 것이다.

이 기술은 미국 UC 버클리 대학의 Sky Computing Lab 소속 연구원들이 개발했으며, 논문 발표와 함께 오픈소스로 공개되어 LLM 서빙 분야의 핵심 기술로 빠르게 자리 잡았다.


vLLM 동작 메커니즘

vLLM의 혁신은 단순히 빠른 코드를 작성한 것이 아니라, 대규모 언어 모델(LLM) 서빙의 근본적인 병목 지점인 메모리 관리 방식을 새롭게 설계한 것에서 출발한다.

1. 문제 정의: 비효율적인 KV 캐시 메모리

기존 시스템은 모든 요청에 대해 최대 출력 길이를 가정하고 거대한 메모리 공간을 미리 할당했다. 이는 아래 그림과 같이 심각한 메모리 낭비를 초래했다.


  • 내부 단편화 (Internal Fragmentation): 그림에서 'Request A'는 최대 2048개의 토큰을 생성할 수 있도록 메모리 공간을 미리 할당받았지만, 실제로는 1개의 토큰만 생성했다. 그 결과, 사용되지 않는 2038개의 슬롯이 낭비되고 있다. 'Request B' 역시 507개의 슬롯이 같은 이유로 낭비되고 있다. 이것이 바로 내부 단편화이다. vLLM은 운영체제의 '페이징(Paging)' 기법처럼 KV 캐시를 '블록(Block)'이라는 작은 단위로 나눈다. 처음부터 최대 길이에 맞춰 거대한 메모리 덩어리를 할당하는 대신, 토큰이 생성될 때마다 필요한 만큼 블록을 하나씩 동적으로 할당해 준다. 이는 C의 malloc 이 링크드 리스트 방식으로 메모리 효율적 관리하는 기법과 거의 유사하다.

  • 외부 단편화 (External Fragmentation): 'Request A'와 'Request B' 사이에는 사용되지 않는 빈 메모리 공간(회색 칸)이 존재한다. 하지만 이 공간이 새로운 요청을 처리하기에 너무 작거나 조각나 있다면, 전체적으로는 메모리가 충분해도 새로운 요청을 배치하지 못하는 외부 단편화가 발생한다. vLLM은 블록 단위로 메모리를 관리하기 때문에, 이 블록들이 물리적으로 연속될 필요가 없다. 

2. 핵심 아이디어: PagedAttention과 '메모리 링크드 리스트'

vLLM은 이 문제를 해결하기 위해 운영체제의 가상 메모리(Virtual Memory)와 페이징(Paging) 기법에서 영감을 얻은 PagedAttention 알고리즘을 도입했다. 

  • 기존 방식 (연속 할당): 한 권의 두꺼운 책처럼, 모든 페이지(토큰)가 순서대로 붙어있는 거대한 메모리 덩어리를 할당하는 것이다. 

  • vLLM 방식 (불연속 할당): 낱장의 종이(블록)에 내용을 적고, 어떤 종이가 다음 내용인지를 알려주는 별도의 '목차(Block Table)'를 관리하는 것과 같다. 이 종이들은 메모리 여기저기에 흩어져 있어도 목차만 따라가면 전체 내용을 순서대로 읽을 수 있다. 

이 '목차'가 바로 링크드 리스트의 '링크(포인터)'와 같은 역할을 하며, 메모리를 작은 블록 단위로 잘게 나누어 필요할 때마다 동적으로 할당해주기 때문에 내부 및 외부 단편화가 거의 발생하지 않는다.

3. 구현: 맞춤형 순전파(Forward) 및 역전파(Backward) 커널

PagedAttention이라는 새로운 메모리 구조를 만들었기 때문에, 이 구조를 이해하고 계산할 수 있는 새로운 연산 엔진이 필요해졌다. PyTorch의 기본 Attention 함수는 흩어져 있는 메모리 블록을 읽을 수 없기 때문이다.

이를 위해 vLLM은 순전파(Forward)와 역전파(Backward) 연산을 위한 CUDA 커널을 직접 개발하여 PyTorch 시스템에 이식했다.

1) 순전파(Forward) CUDA 커널

Attention Score를 계산하는 핵심 함수이다. block_tables라는 '목차'를 받아 흩어져 있는 Key, Value 블록의 물리적 주소를 찾아내어 Attention 연산을 수행한다.


  • 파일 위치: vllm/csrc/attention/attention_kernels.cu

C++
// 순전파(Forward Pass)를 위한 PagedAttention CUDA 커널
__global__ void paged_attention_v1_kernel(
  torch::Tensor out,              // 결과 텐서
  torch::Tensor query,            // Query 텐서
  torch::Tensor key_cache,        // Key 블록들이 저장된 전체 KV 캐시
  torch::Tensor value_cache,      // Value 블록들이 저장된 전체 KV 캐시
  torch::Tensor block_tables,     // ★★★ 흩어진 블록의 주소록 (메모리 링크드 리스트의 '링크')
  torch::Tensor context_lens,     // 각 시퀀스의 길이
  ...
) {
  // ... GPU 스레드 ID 계산 ...

  // ★★★ 블록 테이블에서 현재 시퀀스에 해당하는 블록 주소 목록을 가져온다
  const int64_t* block_table = block_tables[prompt_idx].data_ptr<int64_t>();

  // 루프를 돌며 block_table을 참조해 물리적 블록 주소를 계산하고
  // 해당 주소에서 Key, Value를 로드하여 Attention 연산을 수행한다.
  // ...
}

2) PyTorch 연동 및 역전파(Backward) 커널

이 커스텀 CUDA 커널을 PyTorch의 자동 미분 시스템과 연동시키기 위해 torch.autograd.Function을 상속받아 forward와 backward 메소드를 직접 정의한다. backward 메소드는 편미분을 통한 Gradient 계산을 위해 별도로 제작된 역전파용 CUDA 커널을 호출한다.

  • 파일 위치: vllm/model_executor/layers/attention.py

# PyTorch의 자동 미분 기능에 새로운 함수를 등록하는 부분
class PagedAttention(torch.autograd.Function):

    @staticmethod
    def forward(ctx, ...):
        # 순전파(Forward)용 CUDA 커널 (ops.paged_attention_v1)을 호출한다
        ops.paged_attention_v1(...)
        return output

    @staticmethod
    def backward(ctx, grad_output: torch.Tensor):
        # 역전파(Backward)를 위한 별도의 Gradient 계산용 CUDA 커널을 호출한다
        ops.paged_attention_v2_backward(...)
        return (d_query, d_key, d_value, ...)이

참고로, 파치토치 커널 함수는 다음과 같이 Monkey Patch 기법으로 간단히 커스텀 교체할 수 있다.

import transformers

from transformers.models.llama.modeling_llama import LlamaAttention

original_forward = LlamaAttention.forward

LlamaAttention.forward = custom_paged_attention_forward


단, 이렇게 블럭에 서브 시퀀스를 저장하면, QKV 내적 계산시 토큰의 위치별로 희소행렬 방식으로 계산해야 한다. vLLM은 고정된 블록 크기라는 규칙을 이용해 모든 토큰의 절대 위치를 즉시 계산한다. 특정 토큰의 순서를 고정된 블록 크기로 나누면 그 몫은 해당 토큰이 위치한 논리적 블록의 순서가 되고, 나머지는 그 블록 내에서의 상대적 위치가 된다. 시스템은 이 논리적 블록 순서를 블록 테이블에 대입하여 실제 물리 메모리 주소를 찾는다. 이를 통해 희소행렬처럼 표현된 시퀀스의 토큰들을 서로 계산되어야 할 위치의 토큰 임베딩벡터 끼리 내적계산한다.

vLLM은 1) PagedAttention이라는 효율적인 메모리 관리 기법을 고안하고, 2) 이 기법 위에서 동작하는 순전파 및 역전파 CUDA 커널 세트를 직접 개발하여, 3) 이를 PyTorch 시스템에 완벽하게 통합함으로써 하나의 고성능 추론 시스템을 완성한 것이다.

vLLM 설치

vLLM은 리눅스 환경을 정식으로 지원하며, 파이썬 3.8 이상과 CUDA 11.8 이상을 지원하는 NVIDIA GPU가 필요하다. 윈도우 사용자의 경우 WSL2(Windows Subsystem for Linux 2)를 통해 리눅스 환경을 구축한 후 설치해야 한다.

설치는 파이썬 패키지 관리자인 pip를 통해 간단하게 진행할 수 있다. 가상 환경을 먼저 구성하고 그 내부에 설치하는 것이 권장된다.

  1. 가상 환경 생성 및 활성화

    Bash
    python -m venv vllm-env
    source vllm-env/bin/activate
    
  2. vLLM 설치

    PyTorch가 자동으로 함께 설치되며, 시스템에 맞는 CUDA 버전과 호환되는 버전을 설치하는 것이 중요하다.

    Bash
    pip install vllm 


vLLM의 사용법은 크게 두 가지로 나뉜다. 첫째는 파이썬 코드 내에서 라이브러리로 직접 사용하는 오프라인 추론 방식이고, 둘째는 모델을 API 서버로 실행해두고 HTTP 요청으로 사용하는 온라인 서빙 방식이다.


파이썬 코드 예시 

다음은 파이썬 스크립트에서 직접 모델을 불러와 텍스트를 생성하는 예시이다. LLM 클래스로 모델을 로드하고 SamplingParams로 온도(temperature), top-p 등 생성 옵션을 조절한다.
Python
from vllm import LLM, SamplingParams

# 허깅페이스에서 모델 이름을 지정하여 LLM 객체 생성
# tensor_parallel_size는 사용할 GPU의 수를 의미한다
llm = LLM(model="meta-llama/Meta-Llama-3-8B-Instruct", tensor_parallel_size=1)

# 생성할 텍스트의 프롬프트 목록
prompts = [
    "대한민국의 수도는 어디인가?",
    "인공지능의 미래에 대해 한 문장으로 요약하면",
]

# 샘플링 파라미터 설정
sampling_params = SamplingParams(temperature=0.7, top_p=0.95, max_tokens=100)

# 텍스트 생성 실행
outputs = llm.generate(prompts, sampling_params)

# 결과 출력
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"프롬프트: {prompt}")
    print(f"생성된 텍스트: {generated_text}")
    print("---"


Ollama와 연계 (API 서버 활용)

Ollama는 모델을 로컬 환경에서 쉽게 실행하고 관리하게 해주는 도구이다. vLLM과 Ollama는 경쟁 관계이면서 상호 보완적으로 이해할 수 있다. 두 도구 모두 모델을 API 서버로 실행하는 기능을 제공하기 때문이다.

vLLM은 OpenAI의 API와 호환되는 서버를 매우 쉽게 실행할 수 있다. 터미널에서 아래와 같은 명령어를 실행하면 meta-llama/Meta-Llama-3-8B-Instruct 모델이 로드되어 8000번 포트로 API 서비스가 시작된다.

Bash
python -m vllm.entrypoints.openai.api_server \
    --model "meta-llama/Meta-Llama-3-8B-Instruct"
이렇게 실행된 vLLM 서버는 Ollama가 제공하는 API 엔드포인트와 동일한 방식으로 HTTP 요청을 통해 사용할 수 있다. 즉, Ollama를 사용하던 코드에서 API 주소만 vLLM 서버 주소(http://localhost:8000/v1)로 변경하면 vLLM의 높은 처리 성능을 그대로 활용할 수 있게 되는 것이다. 이는 vLLM을 기존 LLM 기반 애플리케이션의 백엔드 추론 엔진으로 손쉽게 교체할 수 있음을 의미한다.


간략한 챗봇 코드 예시

vLLM을 활용하여 터미널에서 간단하게 대화할 수 있는 챗봇 코드는 다음과 같다. 대화 기록을 누적하여 다음 답변 생성에 활용하는 방식이다.

Python
from vllm import LLM, SamplingParams

# 채팅 형식에 최적화된 모델을 선택하는 것이 좋다
llm = LLM(model="meta-llama/Meta-Llama-3-8B-Instruct")
sampling_params = SamplingParams(temperature=0.7, top_p=0.9, max_tokens=1024)

conversation_history = []

print("간단한 챗봇입니다. 대화를 시작하세요. (종료하려면 '종료' 입력)")

while True:
    user_input = input("나: ")
    if user_input == "종료":
        print("챗봇을 종료합니다.")
        break
    
    # 대화 기록에 사용자 입력을 추가한다
    conversation_history.append({"role": "user", "content": user_input})
    
    # 모델에 맞는 채팅 템플릿을 사용하여 프롬프트를 생성한다
    # 허깅페이스의 `apply_chat_template` 기능을 활용할 수 있다
    from transformers import AutoTokenizer
    tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
    
    # 대화 기록을 프롬프트 문자열로 변환한다
    prompt_text = tokenizer.apply_chat_template(
        conversation_history, 
        tokenize=False, 
        add_generation_prompt=True
    )

    # vLLM으로 답변 생성
    outputs = llm.generate([prompt_text], sampling_params)
    
    bot_response = outputs[0].outputs[0].text
    print(f"챗봇: {bot_response}")

    # 대화 기록에 챗봇 답변을 추가한다
    conversation_history.append({"role": "assistant", "content": bot_response})


마무리

vLLM은 PagedAttention 기술을 통해 대규모 언어 모델 서빙의 효율성을 극대화한 핵심적인 도구이다. 메모리 관리의 혁신을 통해 이전에는 불가능했던 수준의 처리량을 달성했으며, 이는 더 많은 사용자가 더 빠르고 저렴하게 LLM 기술을 활용할 수 있는 길을 만들었다. 설치와 사용법 또한 간편하여 개발자들이 자신의 서비스에 강력한 LLM 추론 엔진을 쉽게 통합할 수 있도록 지원한다.

레퍼런스
부록: 다중 LLM 서빙 시 vLLM 사용 사례

AI 에이전트 개발에 사용되는 기술 스택은 회사 데이터를 기반으로 지능적이고 빠르며, 환각 현상이 없는 맞춤형 AI 비서를 만드는 것을 목표로 한다.

첫 번째로 AI 에이전트의 핵심 두뇌는 직접 튜닝한 Private LLM이다. 이는 외부 서비스를 이용하지 않고 회사 내부에 직접 모델을 설치하고 운영하는 방식이어서, 고객 데이터나 회사 기밀 정보의 외부 유출을 방지할 수 있다. 기반이 되는 모델은 Qwen, Llama 3와 같은 고성능 오픈소스 LLM이며, 여기에 파인튜닝 과정을 거친다. 파인튜닝은 범용 지식을 가진 LLM에게 회사의 전문 용어, 업무 방식, 제품 데이터 등을 추가로 학습시켜 회사 전문가로 만드는 과정이다. 모델의 규모는 8B, 32B, 70B 등의 파라미터 수로 표현되는데, 이는 모델의 성능 수준을 나타내는 지표이다.

두 번째로 AI의 지식 창고는 고도화된 RAG 기술이다. RAG는 LLM이 부정확한 정보를 생성하는 환각 현상을 방지하고, 오직 정확한 최신 정보에 기반해 답변하도록 만드는 기술이다. LLM이 기억에만 의존하는 것이 아니라, 질문을 받으면 먼저 사내 데이터베이스에서 정확한 자료를 찾아보고 그 자료를 바탕으로 답변을 생성하는 방식이다. 이 검색 과정의 효율을 높이기 위해 자체 검색기를 구축한다. 자체 검색기는 단순 키워드 검색과 의미 기반의 벡터 검색을 함께 사용한다. 또한, BGE-M3 같은 모델을 회사 데이터에 맞게 직접 파인튜닝하고, 검색된 문서 중 질문과 가장 관련성이 높은 순서로 재정렬하는 리랭커를 사용하여 검색 성능을 극대화한다.

세 번째로 AI의 행동을 총괄하는 것은 LangGraph를 이용한 시나리오 설계이다. 이는 AI가 단순한 질의응답을 넘어 복잡한 작업을 순서에 맞게 처리하도록 제어하는 역할이다. LangChain과 LangGraph는 LLM, RAG, 외부 도구 등을 연결하여 하나의 작업 흐름으로 만드는 도구이다. 특히 LangGraph는 조건에 따른 분기나 반복 등 복잡한 시나리오 구현을 가능하게 한다. 사용자의 복잡한 요청을 받으면 플래너와 MCP가 어떤 도구를 어떤 순서로 사용해야 할지 계획을 수립하고 전체 작업을 지휘하는 것이다.

마지막으로 AI의 빠른 응답 속도를 책임지는 심장은 vLLM 서빙 엔진이다. 직접 튜닝한 거대 모델은 H100, A100과 같은 고사양 GPU를 사용해도 추론 속도가 느린 문제가 발생할 수 있다. vLLM은 GPU 메모리를 매우 효율적으로 관리하는 기술을 통해 기존 방식보다 훨씬 더 많은 요청을 빠르게 처리할 수 있도록 지원하는 라이브러리이다. 결과적으로 사용자의 대기 시간을 줄이고, 한정된 자원으로 더 많은 사용자를 감당할 수 있어 비용 효율성을 높이는 기술이다.