16장. vLLM 서빙 벤치마킹과 RAG 최적화
컨텍스트와 답 길이 줄이기
여행 짐을 쌀 때 혹시 몰라 다 넣으면 가방이 무거워지고 찾기도 어렵습니다. 꼭 필요한 것만 넣으면 가볍고 빠릅니다. RAG 프롬프트도 조각을 많이 붙일수록 프리필이 길어지고, 답을 길게 쓰게 하면 디코드가 길어집니다.
왼쪽 조각 수(k)와 가운데 조각 길이는 입력 토큰을 정하고, 오른쪽 답 길이는 출력 토큰을 정합니다. 줄일수록 빨라지지만, 정답이 든 조각까지 빼면 틀리기 시작합니다. 가방에 넣는 짐이 조각, 짐의 무게가 토큰 수입니다.
줄이는 곳과 잃는 것
| 줄이는 곳 | 빨라지는 단계 | 잃을 수 있는 것 |
|---|---|---|
| 조각 수(k) | 프리필 | 정답 조각이 빠진다(검색 순위가 낮을 때) |
| 조각 길이 | 프리필 | 조항의 뒷부분 조건이 잘린다 |
답 길이(지시와 num_predict) | 디코드 | 설명이 짧아진다, 너무 짧으면 말이 끊긴다 |
| 재정렬 후보 수 | 재정렬 | 정답 조각이 후보에 들지 못한다 |
조각 수에 따른 길이
import re
from pathlib import Path
# 7차시의 가상 회사 규정집에서 조항 줄만 모은다
articles = [l for l in Path("company_rules.txt").read_text(encoding="utf-8").splitlines() if re.match(r"^제\d+조\(", l)]
for k in [1, 3, 5, 8]:
context = "\n".join(articles[:k])
print(f"조각 {k}개 → 글자 {len(context):4d}자")코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
Path("company_rules.txt") | 파일 경로를 다루는 pathlib 의 Path(경로) 객체를 만든다 |
.read_text(encoding="utf-8") | 파일 전체를 글자로 읽는다. encoding(부호화) 은 글자를 저장한 방식이고, UTF-8 은 Unicode Transformation Format 8-bit 의 줄임말이다 |
.splitlines() | 글을 줄마다 나눠 목록으로 만든다 |
re.match(r"^제\d+조\(", l) | 줄의 맨 앞(^)이 "제 + 숫자 하나 이상(\d+) + 조(" 꼴인지 본다. 조항이 시작하는 줄만 고른다 |
"\n".join(articles[:k]) | 앞의 k 개 조항을 줄바꿈으로 이어 붙인다. 프롬프트에 붙일 컨텍스트다 |
len(context) | 컨텍스트의 글자 수다. 길수록 입력 토큰이 많아 프리필이 길어진다 |
이 코드가 뜻하는 것
여행 가방에 짐을 하나, 셋, 다섯, 여덟 개 넣어 보며 무게를 다는 일입니다. 여기서 짐 하나가 조항 하나, 가방의 무게가 컨텍스트의 글자 수입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
articles = [...] | 7장 가상 규정집에서 조항 줄만 모은다 | 넣을 수 있는 짐을 늘어놓는다 |
for k in [1, 3, 5, 8]: | 조항 수를 바꿔 가며 잰다 | 짐을 몇 개 넣을지 바꿔 본다 |
context = ... | 앞의 k 개 조항을 붙인다 | 가방에 짐을 넣는다 |
print(...) | 62, 231, 389, 606자 | 가방의 무게를 단다 |
조각을 1개에서 8개로 늘리면 글자 수가 62자에서 606자로 열 배 가까이 늡니다. 조각 수에 거의 비례해 입력이 길어지므로, 정답이 든 조각만 남길수록 프리필이 짧아집니다.
작게 줄여서 눈으로 보기
re.match 가 어떤 줄을 조항으로 고르는지 지어낸 줄 넷으로 봅니다.
import re
lines = ["제1조(목적) 이 규정은 ...", " 보충 설명 줄", "제12조(연차) 연차는 ...", "부칙"] # 지어낸 줄
for l in lines:
print(f"{l!r:28s} → {bool(re.match(r'^제\d+조\(', l))}")'제1조(목적) 이 규정은 ...' → True
' 보충 설명 줄' → False
'제12조(연차) 연차는 ...' → True
'부칙' → False| 결과 | 읽는 법 |
|---|---|
'제1조(목적) ...' → True | 맨 앞이 "제1조(" 꼴이라 고른다 |
' 보충 설명 줄' → False | 맨 앞이 빈칸이라 고르지 않는다. re.match 는 줄의 처음부터만 맞춰 본다 |
'제12조(연차) ...' → True | \d+ 는 숫자가 여러 자리여도 맞는다 |
'부칙' → False | "제 + 숫자 + 조(" 꼴이 아니다 |
주의할 점
- 조각을 줄이기 전에 재정렬로 정답 조각을 위로 올려 두면, 적은 조각으로도 정답이 들어갑니다.
- 답 길이를
num_predict로만 자르면 문장이 중간에 끊깁니다. 프롬프트에서 "한 문장으로"처럼 길이를 지시하고,num_predict는 안전장치로 둡니다.