5장. LoRA 파인튜닝과 DPO 정렬
정렬의 위험과 평가
아이에게 "어른에게는 존댓말을 써라"만 반복해 가르치면, 존댓말은 잘 쓰게 되지만 내용이 맞는지는 따로 가르쳐야 합니다. 너무 엄하게 가르치면 아예 말을 안 하려 들기도 합니다. 정렬도 바뀐 뒤를 여러 방향에서 다시 재야 합니다.
왼쪽 지나친 회피는 무엇이든 "답할 수 없습니다"로 피하는 것, 가운데 말투만 배우기는 형식은 바뀌었는데 사실은 여전히 틀리는 것, 오른쪽 잊어버리기는 원래 잘하던 일을 못하게 되는 것(파국적 망각)입니다. 실습 6에서 가운데 위험을 실제로 봅니다. 여기서 존댓말이 정렬로 바뀐 말투, 내용이 사실입니다.
정렬 뒤에 잴 것
| 잴 것 | 재는 법 | 이 장에서 |
|---|---|---|
| 바라던 성향 | 표시 낱말 세기(예: "고객님"), 사람의 평가 | 실습 6, 프로젝트 |
| 사실의 정확성 | 정답 열쇠가 들어 있나 | 실습 3, 6, 프로젝트 |
| 피하는 답 | "답할 수 없습니다", "인공지능으로서" 세기 | 실습 6 |
| 원래 능력 | 정렬과 상관없는 질문(일반 상식, 다른 언어)에 답해 보기 | 프로젝트 5단계 |
| 답의 길이 | 글자 수 평균 | 실습 6 |
answers = ["안녕하세요, 고객님. 결제 후 1~3일 안에 도착합니다. 감사합니다.",
"죄송합니다, 저는 인공지능으로서 그 정보를 알지 못합니다."]
keys = ["1~3일", "1~3일"]
for a, k in zip(answers, keys):
print({"정답": k in a, "고객님": "고객님" in a, "회피": "인공지능" in a, "길이": len(a)})첫 답은 정답과 "고객님"이 들어 있고 피하지 않았으며, 둘째 답은 그 반대입니다. 이런 간단한 표시로 수십 개의 답을 빠르게 훑고, 마지막에는 사람이 답을 직접 읽습니다.
코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
zip(answers, keys) | 두 목록에서 같은 자리의 값을 하나씩 짝지어 꺼낸다. 답 하나와 그 답의 정답 열쇠가 짝이 된다 |
k in a | 글 a 안에 글자 묶음 k 가 들어 있으면 True 다. 정답 열쇠가 답에 들어 있는지 본다 |
"고객님" in a, "인공지능" in a | 바라던 말투의 표시 낱말과 피하는 답의 표시 낱말이 들어 있는지 본다 |
len(a) | 답의 글자 수를 센다. 띄어쓰기와 문장 부호도 한 글자로 센다 |
이 코드가 뜻하는 것
시험지를 채점할 때 답안마다 "정답 낱말이 있나, 존댓말을 썼나, 백지로 냈나, 얼마나 길게 썼나"를 체크 칸에 표시하는 일과 같습니다. 여기서 체크 칸 하나가 정렬 뒤에 잴 것 하나입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
answers = [...] | 친절하고 맞는 답 하나, 피하는 답 하나를 적는다 | 채점할 답안 두 장 |
keys = [...] | 답마다 들어 있어야 할 정답 열쇠다 | 채점 기준표의 정답 |
for a, k in zip(...) | 답과 열쇠를 짝지어 하나씩 본다 | 답안을 한 장씩 넘긴다 |
print({...}) | 네 가지 표시를 사전으로 찍는다 | 체크 칸 네 개에 표시한다 |
첫 답은 {'정답': True, '고객님': True, '회피': False, '길이': 38}, 둘째 답은 정답·고객님이 False, 회피가 True, 길이 32 입니다. 이 표시를 수십 개의 답에 대해 세면 "정답 비율", "회피 비율" 같은 숫자가 되고, 실습 6에서 DPO 전후를 이 숫자로 견줍니다.
주의할 점
- 표시 낱말 세기는 거친 채점입니다. "고객님"이 들어 있어도 무례한 답일 수 있으니, 숫자와 함께 답을 몇 개는 꼭 읽습니다.
- 정렬은 "어떻게 말할지"를 바꾸는 데 강하고 "무엇이 사실인지"를 가르치는 데는 약합니다. 사실은 SFT(실습 3)나 검색(6장 RAG)으로 넣습니다.