토큰 하나를 만든다는 것: 로컬 LLM 내부에서 실제로 일어나는 계산
LLM은 문장을 한 번에 통째로 쓰지 않는다. 다음에 올 토큰 하나를 예측하고, 그 토큰을 붙인 뒤, 다시 다음 토큰을 예측한다. 우리가 채팅창에서 보는 자연스러운 문장은 이 반복의 결과다. 그래서 A3B처럼 “한 토큰 처리 시 활성 파라미터”라는 표현이 나온다.
여기서 중요한 질문이 생긴다. “액션”이라는 단어를 만들 때 3B 파라미터가 활성화된다는 건, 그 단어가 30억 개 파라미터 안으로 들어간다는 뜻일까? 아니다. 더 정확히는 현재까지의 문맥을 숫자 벡터로 바꾼 뒤, 다음 토큰을 예측하기 위한 forward pass에서 약 30억 개 규모의 가중치가 실제 계산 경로에 참여한다는 뜻이다.
토큰은 단어와 다르다
사람은 문장을 글자나 단어로 본다. 하지만 모델은 tokenizer가 만든 토큰 단위로 본다. 오늘 날씨 어때?라는 문장은 모델에 따라 오늘, 날씨, 어, 때, ?처럼 나뉠 수도 있고, 다른 방식으로 나뉠 수도 있다. 한국어는 영어보다 토큰화가 더 직관적이지 않은 경우가 많다.
액션도 마찬가지다. 어떤 모델에서는 하나의 토큰일 수 있고, 어떤 모델에서는 액, 션처럼 두 토큰일 수 있다. 액션 아이템은 액션, 아이템처럼 나뉠 수도 있다. 따라서 사람이 보는 “한 단어”와 모델이 생성하는 “한 토큰”은 같은 단위가 아니다.
채팅에서는 시스템 프롬프트, 이전 대화, 현재 질문, 첨부 문서, 도구 결과가 모두 입력 토큰이 된다. 모델이 새로 쓰는 답변은 출력 토큰이다. 총 비용과 속도는 입력 토큰을 읽는 비용과 출력 토큰을 생성하는 비용으로 나뉜다.
다음 토큰 확률을 계산한다
사용자가 “회의록에서 해야 할 일을 정리해줘”라고 입력했다고 하자. 모델은 바로 완성된 답변을 쓰는 것이 아니라, 다음에 올 토큰 후보들의 확률을 계산한다. 예를 들면 액션, 다음, 해야, 요약 같은 후보가 있을 수 있다. 샘플링 설정에 따라 그중 하나가 선택된다.
첫 토큰으로 액션이 선택되면, 모델은 이제 “회의록에서 해야 할 일을 정리해줘 + 액션”까지를 문맥으로 보고 다음 토큰을 고른다. 다음 후보는 아이템, 은, :, 목록 같은 것이 될 수 있다. 이렇게 토큰을 하나씩 이어 붙이면서 문장이 만들어진다.
이 순차성이 출력 생성 속도를 제한한다. 입력 토큰을 읽는 prefill 단계는 병렬화가 어느 정도 가능하지만, 출력 토큰은 이전 결과를 알아야 다음을 만들 수 있다. 그래서 사용자가 보는 tokens/sec는 보통 답변 생성 단계의 체감 속도다.
내부 계산은 벡터와 행렬 연산이다
모델 내부에서 텍스트는 숫자로 바뀐다. 토큰은 먼저 token id가 되고, 그 id는 임베딩 벡터로 변환된다. 이 벡터가 여러 Transformer 레이어를 통과한다. 각 레이어에서는 attention과 MLP 또는 FFN 계산이 일어난다.
Attention은 현재 토큰이 이전의 어떤 토큰을 얼마나 봐야 하는지 계산한다. 예를 들어 “그것”이라는 표현이 앞의 어떤 명사를 가리키는지, 회의록 중 어떤 부분이 현재 답변과 관련 있는지 같은 정보를 다룬다. MLP/FFN은 벡터를 변환하면서 모델이 학습한 언어 패턴과 추론 패턴을 적용한다.
MoE 모델에서는 일부 FFN 영역이 여러 expert로 나뉘어 있다. Router가 각 토큰과 문맥에 맞는 expert를 고르고, 선택된 expert의 가중치만 계산에 참여한다. 이 선택된 경로의 총량이 A3B, A4B로 표현된다.
3B 파라미터가 활성화된다는 말의 정확한 의미
35B-A3B 모델에서 “3B 파라미터 활성”은 액션이라는 문자열이 30억 개 숫자 안에 들어간다는 뜻이 아니다. 이미 토큰화와 임베딩을 거친 숫자 벡터가 모델 내부 레이어를 지나가며, 선택된 expert와 공유 레이어의 가중치들과 연산된다는 뜻이다.
좀 더 간단히 쓰면 다음과 같다.
- 현재 대화 문맥이 토큰 id로 바뀐다.
- 토큰 id가 임베딩 벡터가 된다.
- 벡터가 Transformer 레이어들을 통과한다.
- MoE 레이어에서 router가 일부 expert를 선택한다.
- 선택된 expert와 관련 가중치들이 계산에 참여한다.
- 마지막 벡터로 다음 토큰 후보 확률을 만든다.
- 샘플링 결과로
액션같은 토큰이 선택된다.
즉 active parameter는 “이번 토큰 예측에 실제 사용된 모델 내부 숫자들”에 가깝다.
액션이 2토큰이면 계산도 두 번이다
만약 tokenizer가 액션을 두 토큰으로 쪼갠다면, 모델은 첫 토큰을 만들 때 한 번, 두 번째 토큰을 만들 때 또 한 번 계산한다. A3B 모델이라면 개념적으로 A3B 규모의 활성 계산이 두 번 반복된다. 출력 100토큰이면 100번, 출력 1000토큰이면 1000번 반복된다.
이 때문에 긴 답변은 느리고 전력도 더 쓴다. 모델이 “생각을 많이 해서”만 느린 것이 아니라, 물리적으로 더 많은 토큰을 순차 생성하기 때문이다. reasoning 모델이 느린 이유도 내부 사고 토큰이나 긴 중간 생성이 많아지는 것과 관련이 있다.
입력 토큰도 계산을 한다. 긴 회의록 10,000토큰을 넣으면 모델은 먼저 그 입력을 읽고 KV cache를 만든다. 이 단계가 prompt eval 또는 prefill이다. 이후 답변 생성 단계에서는 KV cache를 활용해 다음 토큰을 순차적으로 만든다.
실행 체크리스트
- 토큰은 사람이 보는 단어와 다르며 tokenizer마다 쪼개짐이 달라진다.
- LLM은 답변을 한 번에 쓰지 않고 다음 토큰을 하나씩 예측한다.
A3B 활성은 토큰 문자열이 파라미터 안으로 들어간다는 뜻이 아니라, 다음 토큰 예측 계산에 약 3B 규모의 가중치가 참여한다는 뜻이다.- 출력 토큰이 많을수록 active 계산이 반복되어 시간이 늘어난다.
- 입력 토큰은 prefill 단계에서 처리되고, 출력 토큰은 decode 단계에서 순차 생성된다.
- MoE 모델은 router가 토큰마다 일부 expert를 선택한다.
- tokens/sec는 대체로 출력 토큰 생성 체감 속도를 의미한다.
토큰과 파라미터를 분리해서 이해하면 로컬 LLM의 속도와 비용이 훨씬 명확해진다. 모델이 글을 쓰는 것처럼 보이지만, 실제로는 매 순간 다음 토큰 확률을 계산하고 있다. A3B와 A4B는 바로 그 순간마다 얼마나 큰 계산 경로가 열리는지를 알려주는 숫자다.