RAG 파이프라인과 평가
목표
문서를 청크로 나눠 색인하고, 질의로 검색하고, 검색 품질을 지표로 측정하고, 근거 없는 답변과 답할 수 없는 질문을 걸러 내는 RAG 파이프라인 한 벌을 만듭니다.
왜 중요한가
RAG 에서 가장 흔한 실수는 검색 실패와 생성 실패를 구분하지 않는 것입니다. 답변이 이상할 때 프롬프트부터 고치는데, 정답 문서가 애초에 검색되지 않았다면 프롬프트를 아무리 다듬어도 소용이 없습니다.
그래서 이 실습은 검색 지표를 먼저 계산합니다. Recall@3 은 정답 문서가 상위 3개 안에 들어왔는지를, MRR 은 몇 위에 나왔는지를 봅니다. 이 숫자가 낮으면 손볼 곳은 검색기이지 생성기가 아닙니다.
다음으로 근거 판정과 거절 규칙을 만듭니다. 검색 점수가 낮을 때 답하지 않는 것은 기능 부족이 아니라 안전장치입니다. 관련 없는 문서를 근거로 그럴듯한 답을 지어내는 것보다 모른다고 말하는 편이 훨씬 낫습니다.
모델은 쓰지 않습니다. 검색과 평가는 전부 numpy 로 계산할 수 있고, 그 부분이 RAG 품질의 대부분을 결정하기 때문입니다.
단계
작업 디렉터리는 /root/llm 이고, 토큰화 규칙은 앞 실습과 같습니다(소문자로 바꾼 뒤 [가-힣a-z0-9]+).
docs의 각body를 마침표(.)로 나눠 앞뒤 공백을 지우고 빈 조각을 버린 청크를/root/llm/chunks.tsv에 저장합니다. 형식은docs.id<탭>청크번호<탭>본문이고 청크번호는 문서마다 0부터 시작합니다. 문서 순서대로 씁니다.- 청크 단위 TF-IDF 행렬을
/root/llm/chunk_tfidf.npy로 저장합니다. 모양은 (청크 수, 항 수)이고 항은 청크 전체에서 모은 어휘를 오름차순 정렬한 것입니다. idf 의 N 은 청크 수이며 공식과 정규화는 앞 실습과 같습니다. - 아래 질의 8개에 대해 상위 3개 청크를
/root/llm/retrieved.tsv에질의번호<탭>순위<탭>docs.id<탭>청크번호<탭>점수로 저장합니다. 총 24줄이고 점수는 소수점 여섯 자리, 동점이면 문서 id 가 작은 쪽, 그다음 청크 번호가 작은 쪽이 앞섭니다.인덱스를 만들었는데 왜 순차 스캔인가복합 인덱스는 컬럼 순서를 어떻게 정하나격리 수준을 올려도 안 잡히는 이상 현상은 무엇인가페이지 폴트가 잦으면 왜 느려지나가상 주소를 물리 주소로 어떻게 바꾸나연결 거부와 타임아웃은 무엇이 다른가큰 요청만 멈추는 이유는 무엇인가GPU 에서 워프란 무엇인가
- 위 질의의 정답 문서는 순서대로
24, 25, 27, 12, 11, 19, 17, 6입니다. Recall@3 과 MRR 을 계산해/root/llm/metrics.tsv에 두 줄로 저장합니다. 첫 칸은recall_at_3과mrr, 둘째 칸은 소수점 세 자리 값입니다. Recall@3 은 정답 문서가 상위 3개 안에 있으면 1로 세어 질의 수로 나눈 값이고, MRR 은 정답이 처음 나온 순위의 역수를 평균한 값(없으면 0)입니다. - 1번 질의의 상위 3개 청크 본문을 순위 순서대로 한 줄씩
/root/llm/context.txt에 저장합니다. - 아래 답변 후보 3개가 5번 컨텍스트에 근거하는지 판정해
/root/llm/grounded.tsv에번호<탭>겹침비율<탭>판정으로 저장합니다. 겹침 비율은 답변 토큰을 중복 없이 모아 그중 컨텍스트 토큰 집합에 들어 있는 비율이고 소수점 세 자리입니다. 0.6 이상이면grounded, 아니면hallucinated입니다.인덱스는 값으로 정렬된 구조라 컬럼에 함수를 씌우면 그 정렬이 쓸모없어진다옵티마이저가 인덱스를 쓰지 않는 것은 대개 옳은 판단이다인덱스를 만들면 어떤 쿼리든 언제나 세 배 빨라진다
- 코퍼스에 없는 질의 3개에 대해 최고 점수와 판정을
/root/llm/refusal.tsv에번호<탭>최고점수<탭>판정으로 저장합니다. 점수는 소수점 여섯 자리이고, 0.15 미만이면refuse, 아니면answer입니다.김치찌개 맛있게 끓이는 법프리미어리그 이번 주 경기 일정제주도 항공권 최저가 예약
/root/llm/rag_report.tsv에 세 줄로 요약을 남깁니다.chunks<탭>청크수,queries<탭>질의수,recall_at_3<탭>값형식입니다.
참고
- 청크 색인은 문서 색인보다 항 수가 비슷해도 행 수가 훨씬 많아집니다. 모양을 먼저 확인하세요.
- 점수는 정규화된 벡터의 내적, 즉 코사인 유사도입니다.
- 흔한 실수 1: idf 를 문서 수 기준으로 계산하면 값이 전부 어긋납니다. 청크 수를 쓰세요.
- 흔한 실수 2: 겹침 비율의 분모는 답변 토큰의 중복 없는 개수입니다.
문서를 문장 단위 청크로 나누기
마침표로 나눈 뒤 앞뒤 공백을 지우고 빈 조각은 버립니다. 청크 번호는 문서마다 0부터 다시 시작합니다.
청크 단위로 색인 만들기
idf 를 계산할 때 N 이 문서 수가 아니라 청크 수라는 점에 주의하세요.
질의 8개로 상위 3개 청크 검색하기
질의도 같은 방식으로 벡터를 만듭니다. 동점 처리 규칙을 지키세요.
Recall@3 과 MRR 계산하기
정답 문서가 상위 3개 안에 있으면 1, 없으면 0 입니다. MRR 은 정답이 나온 순위의 역수를 평균합니다.
컨텍스트 조립하기
1번 질의의 검색 결과를 순위 순서대로 한 줄씩 이어 붙입니다.
답변이 컨텍스트에 근거하는지 판정하기
답변 토큰을 중복 없이 모아 컨텍스트에 있는 비율을 셉니다. 기준값을 넘는지로 판정합니다.
코퍼스 밖 질문 거절하기
최고 점수가 임계값 미만이면 답하지 않는다고 표시합니다. 점수 자체도 기록해야 합니다.
요약 보고서 만들기
청크 수, 질의 수, Recall@3 세 가지를 이름과 값의 쌍으로 남깁니다.