LLM 엔지니어링20장 · LLM 평가와 모니터링6 / 22← 이전목차다음 →MetaContents

20장. LLM 평가와 모니터링

뜻으로 채점하기

받아쓰기는 글자가 같아야 맞지만, 들은 이야기를 요약하는 숙제는 뜻이 같으면 맞습니다. 의미 유사도는 두 문장을 임베딩으로 바꿔 뜻이 얼마나 가까운지 숫자로 잽니다.

참조 답과 챗봇의 답을 임베딩하고, 코사인 유사도를 재고, 문턱과 견주는 세 단계 흐름도

1번에서 참조 답과 챗봇의 답을 같은 임베딩 모델로 벡터로 바꿉니다(7장). 2번에서 두 벡터의 코사인 유사도를 잽니다. 3번에서 정해 둔 문턱보다 높으면 맞음으로 봅니다. 요약 숙제의 "뜻이 같다"가 높은 유사도입니다. 비유가 맞지 않는 곳도 있습니다. 임베딩은 숫자 하나가 다른 두 문장도 아주 가깝다고 봅니다.

세 채점 방법 견주기

규칙의미 유사도LLM 채점자
빠르기가장 빠르다빠르다느리다(답마다 LLM 호출)
같은 뜻 다른 표현놓친다잡는다잡는다
숫자 하나 틀림열쇠가 숫자면 잡는다잘 놓친다기준표에 따라 잡는다
다시 채점하면같다같다조금 달라질 수 있다

숫자 하나가 다른 두 문장

아래는 글자 조각(TF-IDF)으로 잰 유사도입니다. 실습 2에서는 e5 임베딩으로 같은 일을 잽니다.

Python
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

ref = "한 사람이 7권까지 빌릴 수 있습니다."
cands = ["한 사람이 5권까지 빌릴 수 있습니다.", "책은 일곱 권까지 대출됩니다.", "주차는 30분까지 무료입니다."]
vec = TfidfVectorizer(analyzer="char_wb", ngram_range=(2, 3)).fit([ref] + cands)
sims = cosine_similarity(vec.transform([ref]), vec.transform(cands))[0]
# 결과: 숫자만 틀린 문장이 뜻이 같은 문장보다 더 가깝게 나온다
for c, s in zip(cands, sims):
    print(f"{s:.3f}  {c}")

코드에 나오는 함수

코드쉬운 뜻
TfidfVectorizer글을 TF-IDF 숫자 벡터로 바꾸는 도구다. TF-IDF 는 Term Frequency–Inverse Document Frequency(낱말 빈도–역문서 빈도)의 머리글자로, 한 글에 자주 나오고 다른 글에는 드문 조각에 큰 무게를 준다
analyzer="char_wb"character word boundary(낱말 경계 안의 글자)의 줄임말이다. 낱말 단위가 아니라 낱말 안의 글자 조각으로 자른다
ngram_range=(2, 3)n-gram(n 개짜리 조각)의 길이 범위다. 2글자 조각과 3글자 조각을 쓴다
.fit([ref] + cands)네 문장을 보고 어떤 조각이 있는지와 조각마다의 무게를 배운다
vec.transform([...])배운 조각표로 문장을 벡터로 바꾼다
cosine_similarity(A, B)두 벡터 묶음의 코사인 유사도 표를 만든다. 1에 가까울수록 닮았다
[0]표의 첫 줄, 곧 참조 답과 세 후보의 유사도 셋을 꺼낸다

이 코드가 뜻하는 것

두 사람의 마트 영수증을 나란히 놓고 같은 물건이 얼마나 겹치는지 보는 일과 같습니다. 겹치는 물건이 많을수록 두 장바구니가 닮았다고 봅니다. 여기서 영수증이 문장, 물건 하나하나가 글자 조각입니다. TF-IDF 는 누구나 사는 흔한 물건에는 무게를 낮게 줍니다. 비유와 다른 점도 있습니다. 사람은 "일곱"과 "7"이 같은 뜻인 줄 알지만, 이 방법은 뜻을 모르고 글자 조각만 견줍니다.

줄하는 일쉽게 말하면
vec = TfidfVectorizer(...).fit(...)네 문장의 글자 조각표를 만든다물건 목록 만들기
vec.transform([ref]), vec.transform(cands)문장마다 조각의 무게를 벡터로 만든다영수증마다 물건 체크
cosine_similarity(...)[0]참조 답과 후보 셋의 닮은 정도를 잰다영수증 겹침 정도

결과에서 숫자만 틀린 "5권" 문장이 0.817 로 가장 가깝고, 뜻이 같은 "일곱 권" 문장은 0.133 입니다. 겹치는 글자 조각이 많을수록 높게 나오기 때문입니다. 유사도가 높다고 사실이 맞다는 뜻은 아닙니다.

작게 줄여서 눈으로 보기

char_wb 가 글을 어떤 조각으로 자르는지 직접 봅니다.

Python
from sklearn.feature_extraction.text import TfidfVectorizer

vec = TfidfVectorizer(analyzer="char_wb", ngram_range=(2, 3))
analyze = vec.build_analyzer()          # 글을 조각으로 자르는 함수만 꺼낸다
print(analyze("7권까지"))
print(analyze("5권까지"))
출력
[' 7', '7권', '권까', '까지', '지 ', ' 7권', '7권까', '권까지', '까지 ']
[' 5', '5권', '권까', '까지', '지 ', ' 5권', '5권까', '권까지', '까지 ']
결과읽는 법
' 7', '7권', '권까', '까지', '지 '2글자 조각이다. 낱말 앞뒤에 빈칸을 붙여 자르므로 ' 7' 처럼 빈칸이 든 조각이 생긴다
' 7권', '7권까', '권까지', '까지 '3글자 조각이다
두 줄 견주기9조각 가운데 숫자가 든 넷(' 7', '7권', ' 7권', '7권까')만 다르고 다섯은 같다

build_analyzer() 는 벡터라이저가 글을 자를 때 쓰는 함수를 꺼내 줍니다. "7권까지" 와 "5권까지" 는 조각 다섯을 나눠 가집니다. 숫자 하나가 틀려도 유사도가 높게 나오는 까닭이 여기 있습니다.

주의할 점

  • 유사도의 문턱은 모델마다 다릅니다. 사람이 판정한 몇십 개로 문턱을 정합니다.
  • 숫자와 날짜가 핵심인 서비스는 유사도만 믿지 않습니다. 열쇠 규칙이나 LLM 채점자와 함께 씁니다.
← 이전 절20장 · 규칙으로 채점하기다음 절 →20장 · LLM 을 채점자로