LLM 엔지니어링6장 · RAG 의 원리와 로컬 모델로 옮기기3 / 23← 이전목차다음 →MetaContents

6장. RAG 의 원리와 로컬 모델로 옮기기

LLM 이 모르는 것

새로 온 아르바이트생을 떠올려 봅시다. 똑똑하고 말도 잘하지만, 우리 가게의 환불 규정이나 쿠폰 규칙은 모릅니다. 손님이 물으면 "보통은 이렇습니다" 하고 그럴듯하게 답해 버리기도 합니다. LLM 도 같습니다.

학습 뒤에 생긴 일, 우리만 아는 문서, 자주 바뀌는 숫자의 세 가지를 카드로 놓은 그림

세 카드가 LLM 이 모르는 세 가지입니다. 학습이 끝난 뒤에 생긴 일, 인터넷에 없는 우리만의 문서, 자주 바뀌는 가격과 기한입니다. 여기서 아르바이트생이 LLM, 가게 규정집이 우리 문서입니다. 비유와 다른 점은, 아르바이트생은 "잘 모르겠어요"라고 말할 줄 알지만 작은 LLM 은 그 말을 잘 하지 못한다는 것입니다.

모르는 것의 종류

모르는 것예모델을 다시 학습하면?
지식 마감 뒤의 일이번 달에 바뀐 정책, 새 상품바뀔 때마다 다시 학습해야 한다
우리만 아는 문서사내 규정, 상품 설명서, 관리규약학습할 수는 있지만 문서가 바뀌면 또 학습한다
자주 바뀌는 숫자가격, 재고, 마감 시각학습보다 그때그때 찾아보는 편이 맞다

맞혔는지 세는 법

이 장의 실습은 질문마다 "정답 열쇠"를 두고, 답에 그 낱말이 들어 있으면 맞힌 것으로 셉니다. 정답 열쇠가 없는 질문(문서에 없는 질문)은 "찾지 못했습니다"처럼 모른다고 답해야 맞습니다.

Python
# 모른다고 답했는지 볼 때 찾는 말들
REFUSE = ["찾지 못", "찾을 수 없", "나와 있지 않", "제공되지 않"]

def grade(key, answer):
    """key 는 '|' 로 나눈 정답 열쇠. 빈 글자면 문서에 없는 질문이다."""
    refused = any(w in answer for w in REFUSE)
    if key == "":
        return "모름 맞음" if refused else "지어냄"
    if any(k in answer for k in key.split("|")):
        return "정답"
    return "거절" if refused else "오답"

print(grade("50만원", "휴대폰 결제는 한 달에 50만원까지입니다."))
print(grade("50만원", "휴대폰 결제는 한도가 없습니다."))
print(grade("", "새벽 배송은 오전 7시 전에 도착합니다."))
print(grade("", "문서에서 찾지 못했습니다."))

차례로 "정답", "오답", "지어냄", "모름 맞음"이 나옵니다. 문서에 없는 질문에 그럴듯하게 답한 것이 "지어냄", 곧 환각입니다.

코드에 나오는 함수

코드쉬운 뜻
REFUSE = [...]"모른다"는 뜻으로 쓰이는 말의 앞부분을 모아 둔 목록이다. "찾지 못했습니다", "찾지 못합니다"를 모두 잡으려고 끝을 잘라 두었다
w in answer글자 w 가 답 안에 들어 있는지 True, False 로 알려 준다
any(...)여러 개 가운데 하나라도 True 면 True 다. "모른다는 말이 하나라도 들어 있나"를 묻는다
key.split(...)정답 열쇠를 세로 막대 기호에서 잘라 목록으로 만든다. "50만원" 하나뿐이면 목록에 하나만 들어간다
key == ""정답 열쇠가 비어 있는지 본다. 비어 있으면 문서에 답이 없는 질문이다

이 코드가 뜻하는 것

선생님이 시험지를 채점하는 모습에 빗대 봅시다. 답안에 정답 낱말이 있으면 동그라미를 칩니다. 답이 없는 함정 문제에 "모르겠습니다"라고 쓰면 그것도 맞힌 것으로 칩니다. 함정 문제에 아무 답이나 지어 쓰면 따로 표시해 둡니다.

줄하는 일쉽게 말하면
refused = any(w in answer for w in REFUSE)답에 "찾지 못" 같은 말이 있는지 본다학생이 "모르겠다"고 썼나
if key == "":문서에 답이 없는 질문인지 본다함정 문제인가
return "모름 맞음" if refused else "지어냄"함정 문제에서 모른다고 했으면 맞음, 아니면 지어냄이다함정에 안 걸렸나, 걸렸나
if any(k in answer for k in key.split(...))정답 낱말 가운데 하나라도 답에 있는지 본다동그라미를 칠 낱말이 있나
return "거절" if refused else "오답"답이 있는 질문인데 정답 낱말이 없을 때, 모른다고 했으면 거절, 다른 말을 했으면 오답이다아는 문제를 비웠나, 틀리게 썼나

결과는 네 가지 이름표 가운데 하나입니다. "정답"과 "모름 맞음"은 바른 행동이고, "지어냄"은 환각, "거절"은 답이 있는데도 피한 것, "오답"은 틀린 숫자를 말한 것입니다.

주의할 점

  • 낱말이 들어 있는지로 세는 채점은 빠르지만 거칩니다. "6시"가 열쇠인데 "오후 6시부터는 안 됩니다"처럼 뜻이 반대여도 맞힌 것으로 셉니다. 숫자가 맞았는지만 보는 어림이라 생각하고, 답을 직접 읽어 확인합니다.
  • 큰 모델일수록 환각이 줄지만 없어지지는 않습니다. 모델이 알 수 없는 것은 모델 밖에서 넣어 줘야 합니다.
← 이전 절6장 · 용어 짚고 가기다음 절 →6장 · RAG 의 세 단계