무료 로컬 RAG로 내 문서에 질문 228번 — 조각을 6개로 늘리자 정답이 줄었습니다
시정명령이 몇 건인지 물었습니다.
법 위반 행위에 부과된 시정명령은 몇 건인가요?
검색기는 정답 문장이 든 조각을 1순위로 가져왔습니다. 그 조각 안에는 이 줄이 있습니다.
▸법 위반 행위(537개 기관)에 대해 과징금·과태료 1,997억원, 시정명령 259건 부과
모델의 답은 이랬습니다.
537건
기관 수에 「건」을 붙인 답입니다. 정답 259건은 같은 문장 안에 있었죠. 조각 3개를 넘기는 조건에서 세 번 물었고, 세 번 다 537건이었습니다. 조각을 6개로 늘리자 세 번 다 259건으로 바뀌었습니다.
그럼 조각을 늘리면 될까요. 반대 방향도 나왔습니다. 표본 설계 표에서 허용오차 1.0에 대응하는 표본 크기를 물은 질문입니다. 조각 3개일 때는 세 번 모두 정답인 6,436을 답했습니다. 6개일 때는 세 번 모두 6,500이었습니다. 두 조건 모두 같은 조각이 1순위였고, 그 조각에는 표의 6,436과 바로 뒤 「최종 표본의 크기는 허용오차가 1.0% 내외가 되도록 6,500개로 결정함」이 나란히 있습니다.
내 PC에서 무료로 문서 질의응답을 꾸리려 한다면, 몇 조각을 넘길지와 어떤 답을 그대로 믿을지부터 정해야 합니다. 이번 228회에서 조각 3개 조건은 답이 있는 질문 96회 중 81회를 맞혔습니다. 6개로 늘린 조건은 74회였습니다. 조각 수를 바꾸면 고쳐지는 답과 틀어지는 답이 함께 나왔고, 검색이 정답 문장을 못 가져온 질문은 조각을 늘려도 그대로 남았습니다.
스캔 PDF는 점수에 잡히지도 않았습니다
넣은 문서는 넷입니다. 개인정보보호위원회 2025년 업무계획 PDF, 2024 정보보호 실태조사 보고서 PDF, 1996년 관보를 스캔한 PDF, 개인정보위 보도자료 HWPX 파일. 모두 공공기관이 공개한 자료입니다.
첫 단계인 텍스트 추출에서 관보가 사라졌습니다. 21,510KB짜리 스캔 PDF에서 pdftotext가 꺼낸 글자는 0자였습니다.
이 실패는 아래 어느 점수에도 나타나지 않습니다. 관보에서 답을 찾는 질문을 이번 38문항에 넣지 않았기 때문입니다. 경고창도 없었습니다. 파이프라인은 끝까지 돌았고, 관보만 검색 대상에서 조용히 빠졌습니다. 스캔본을 내 문서 폴더에 넣어 두고 「이 자료도 검색되겠지」 하고 넘기면, 그 자료에 관한 질문은 처음부터 답할 재료가 없습니다.
HWPX 보도자료도 한 번에 되지는 않았습니다. libreoffice 변환이 실패해서, 파일을 압축 해제한 뒤 본문 XML의 글자만 모으는 방식으로 우회했고 4,858자를 얻었습니다.
남은 세 문서를 700자씩 잘랐더니 청크 247개가 나왔습니다. 그중 223개가 실태조사 보고서 한 권에서 나왔습니다. 검색 대상의 90%가 표가 많은 보고서 한 권입니다.
이렇게 물었습니다
이번 테스트는 2026년 9월, 로컬 Ollama 0.32.1에서 돌렸습니다. 임베딩은 bge-m3, 답변은 gemma3:4b(Q4_K_M)가 맡았습니다.
- 청크는 700자, 앞 청크와 150자씩 겹치게 잘랐습니다.
- 질문과 청크의 코사인 유사도로 상위 3개 또는 6개를 골라 프롬프트에 넣었습니다.
- 프롬프트는 「아래 [문서]만 근거로 답하고, 없으면 "문서에 없음"이라고만 답하라」입니다.
- 질문은 38개입니다. 문서에 답이 있는 32개와, 문서에 답이 없는 함정 6개입니다.
- 답이 있는 질문에는 PDF 배치 때문에 숫자가 이름표에서 떨어져 추출되는 3개, 기업 부문과 개인 부문처럼 비슷한 통계가 두 벌 있는 4개, 표의 행·열을 읽어야 하는 1개를 섞었습니다.
- 조각 3개와 6개, 두 조건을 각각 세 번씩 돌렸습니다. 파일럿 20회로 진행 판정을 받은 뒤 나머지 208회를 이어서 실행했습니다.
온도와 seed는 요청에 넣지 않았습니다. 모델에 저장된 기본 설정을 그대로 썼고, 그 설정의 temperature는 1입니다. 컨텍스트는 8,192 토큰으로 고정했습니다. 가장 긴 프롬프트가 4,002 토큰이라 입력이 잘린 회차는 없습니다. 답 하나를 받는 데 걸린 시간은 중앙값 0.85초였고, 모델을 처음 올린 첫 요청만 13.9초가 걸렸습니다.
채점은 rag_score.py가 합니다. 질문마다 정답 표기를 미리 정해 두고, 답에 정답이 있으면 정답, 「문서에 없음」만 있으면 물러선 답, 둘 다 없으면 오답으로 셉니다. 검색된 조각 안에 정답 문장이 들어 있었는지도 따로 셉니다.
채점기는 두 번 고쳤습니다. 파일럿에서 단위 없이 「7」이라고만 적은 정답을 오답으로 셌습니다. 본측정 뒤 228개 답을 하나씩 대조하다가, 반대로 「1. 1. 1명」처럼 깨진 답 두 개를 정답으로 센 것을 찾았습니다. 둘 다 고친 채점기로 전체를 다시 채점했습니다.
| 조각 3개 vs 6개 | 조각 3개 | 조각 6개 |
|---|---|---|
| 정답 (답이 있는 질문 96회) | 81 | 74 |
| 오답 | 6 | 8 |
| 답이 있는데 「문서에 없음」 | 9 | 14 |
| 정답 문장이 든 조각이 검색됨 | 84 | 84 |
| 함정 질문에 「문서에 없음」 | 18/18 | 18/18 |
이 화면은 실행이 끝난 순간의 채점값입니다. 조각 6개 쪽 76은 깨진 답 두 개를 정답으로 센 숫자이고, 바로잡은 뒤의 기록은 위 표의 74입니다. 실행 기록상 인프라 오류는 0건이었습니다.
「문서에 없음」이 문서에 없다는 뜻은 아니었습니다
함정 질문 여섯 개는 두 조건 모두 모든 회차에서 「문서에 없음」이라고 답했습니다. 챗GPT 요금이나 2026년 총회 개최지처럼 문서에 없는 것을 물었을 때, 숫자를 지어 붙인 답은 이번 기록에 없었습니다.
문제는 반대쪽입니다. 조각 3개 조건에서 나온 「문서에 없음」 27번 가운데 세 번에 한 번은 문서에 답이 있는 질문이었습니다. 조각 6개 조건에서는 32번 가운데 절반에 조금 못 미쳤습니다.
개인 부문 조사의 유효 응답자 수를 물은 질문이 그런 경우입니다. 보고서에는 「유효 응답자 수 : 4,000명」이 적혀 있습니다. 검색기는 이 문장이 든 조각을 3개 안에도, 6개 안에도 넣지 못했고, 모델은 여섯 번 모두 「문서에 없음」이라고 답했습니다. 2024년에 개발을 마친 기술 수처럼 배치 때문에 숫자가 떨어져 나간 질문 하나와, 처리방침 컨설팅 규모를 물은 질문도 같은 길을 걸었습니다.
정답 문장 조각을 못 받은 회차에서 모델은 대부분 물러섰습니다. 틀린 숫자를 낸 쪽은 기업 부문 유효 응답 업체 수를 물은 질문 하나였습니다.
1순위로 들어온 조각은 업종·규모별 모집단과 표본 수를 나눈 표였습니다. 1,322는 그 표의 한 칸입니다. 조각을 6개로 늘리자 표본 설계 부분의 「6,500개로 결정함」 문장이 들어왔고, 답은 6,500으로 바뀌었습니다. 숫자는 맞았지만 채점기가 정답 근거로 정해 둔 「유효 응답 업체 수」 문장은 여전히 조각 밖이었습니다.
읽는 쪽에서 챙길 것은 하나입니다. 로컬 RAG의 「문서에 없음」은 검색이 못 찾았다는 뜻일 수 있습니다.
조각을 늘리면 고쳐지는 답과 틀어지는 답이 같이 나왔습니다
조각 6개는 조각 3개를 그대로 포함합니다. 그래서 정답 문장 조각이 검색된 회차 수는 두 조건이 같고, 차이는 모두 모델이 같은 재료를 받고 다르게 답한 데서 나왔습니다. 정답 문장이 든 조각을 받은 회차만 놓고 보면, 조각 3개 조건은 세 번 놓쳤고 조각 6개 조건은 열세 번 놓쳤습니다.
답이 달라진 질문을 모으면 이렇습니다.
| 질문 | 조각 3개 · 3회 | 조각 6개 · 3회 |
|---|---|---|
| 시정명령 건수 | 537건 · 오답 3 | 259건 · 정답 3 |
| 기업 부문 유효 응답 업체 수 | 1,322 · 오답 3 | 6,500 · 정답 3 |
| 허용오차 1.0 표본 크기 | 6,436 · 정답 3 | 6,500 · 오답 3 |
| 3대 전략 아래 핵심 과제 수 | 6개 · 정답 3 | 3개 · 오답 3 |
| 기업체당 정보보호 담당 인력 | 1.1명 · 정답 3 | 정답 1 · 「1. 1. 1명」 2 |
| CISO 임명률 · 데이터 부족 비율 · 지원센터 수 | 정답 9 | 정답 4 · 「문서에 없음」 5 |
위 네 줄은 세 번 모두 같은 답이 나왔습니다. 조각 수를 바꾸면 결과가 한쪽으로 확실하게 넘어간 셈이라, 우연한 흔들림으로 보기 어렵습니다. 핵심 과제 질문의 조각에는 「3대 전략 하에 6대 핵심 과제를 추진한다」가 들어 있었고, 6개 조건에서는 앞쪽 숫자가 답이 됐습니다.
아래 두 줄은 흔들림입니다. 조각 3개 조건은 38문항 모두 세 번 같은 판정이 나왔습니다. 조각 6개 조건에서는 4문항이 회차마다 달랐습니다. 정답 문장이 조각 안에 있는데도 한두 번씩 「문서에 없음」이라고 답한 질문이 셋입니다.
같은 정답 조각을 받고도 옆 조각이 늘면 답이 바뀌었고, 바뀐 방향은 질문마다 달랐습니다.
조각 수보다 먼저 확인할 곳
이 구성이라면 저는 조각 3개에서 시작하겠습니다. 이번 기록에서 조각 6개는 정답 문장 조각을 한 번도 새로 가져오지 못했고, 흔들리는 답과 틀어지는 답을 더했습니다. 못 찾는 질문을 조각 수로 풀려고 하지 않겠습니다.
그 대신 확인할 곳은 이렇습니다.
- 추출된 글자 수를 먼저 봅니다. 문서마다 몇 자가 나왔는지 표로 뽑아 두면 0자짜리 스캔본이 바로 보입니다. 그런 파일은 글자를 읽어 내는 OCR 단계를 거쳐야 검색 대상에 들어갈 수 있습니다.
- 「문서에 없음」 답에는 검색된 조각을 함께 띄웁니다. 이번 기록처럼 문서에 있는 답을 못 찾은 경우를 사람이 바로 가려낼 수 있습니다.
- 숫자 답은 원문 문장과 대조합니다. 537건처럼 같은 문장 안의 다른 숫자를 가져온 오답은 원문을 옆에 두면 금방 보입니다.
- 정답을 아는 질문 몇십 개로 먼저 돌려 봅니다. 내 문서에서 답이 확실한 질문과 답이 없는 질문을 섞어 두고, 조각 수를 바꿔 가며 결과를 비교하면 이번 같은 뒤집힘이 내 문서에서도 생기는지 확인할 수 있습니다.
문서를 통째로 넣는 쪽이 궁금하다면 긴 문서를 넣으면 AI가 중간을 놓치는지 잰 기록이 이어서 볼 만합니다. 답변 자체를 검수하는 방법은 AI 답변의 환각을 거르는 방법에 정리돼 있습니다.
처음의 537건으로 돌아가면, 그 오답은 정답이 든 문장이 모델 앞에 놓인 상태에서 나왔습니다. 로컬 RAG를 쓸 때 오늘 챙길 것은 조각 수를 몇으로 둘지보다, 답 옆에 그 답이 나온 문장을 같이 보여 주는 화면입니다.
재현과 원자료
실행 파일은 run_rag_bench.py입니다. 질문과 정답 표기는 rag_bench_cases.json, 채점기는 rag_score.py에 있습니다. --mode pilot으로 파일럿을 돌리고, 같은 실행 폴더에서 --mode full로 이어갑니다. 채점기를 고친 뒤에는 --rescore로 원출력을 그대로 둔 채 다시 채점했습니다.
이번 기록의 기준 파일은 test_runs/local-rag-20260923/run.yaml입니다. 조건별 집계는 같은 폴더의 aggregate.json, 회차별 판정은 results.csv, 질문별 프롬프트·검색 조각·응답은 raw/에 있습니다. 문서별 추출 결과는 corpus_report.json입니다. 이 경로들은 비공개 작업 폴더라 외부에서 열 수 없습니다. 본문에는 이번 실행 중에 찍힌 터미널 화면 캡처 세 장을 실었습니다.
재현: cinevyze-bench의 run_rag_bench.py·rag_score.py·rag_bench_cases.json. 검색 대상 문서 네 개와 위 test_runs/… 실행 기록은 공개하지 않습니다.
이번 결과는 gemma3:4b Q4_K_M, bge-m3 임베딩, 700자 청크, 공공문서 네 개와 질문 38개를 놓고 얻었습니다. 다른 임베딩 모델, 청크 크기, 재정렬 단계를 넣은 구성에서는 다시 재야 합니다.
질문 38개 228회는 로컬 Ollama에서 bge-m3와 gemma3:4b로 실행한 결과입니다. 측정 코드와 원고 작성에 AI 도구를 썼고, 조건 승인과 발행 전 검수는 제 몫입니다.
시네 · cinevyze 운영자 — AI 도구의 응답을 원출력과 검사 기준으로 대조합니다. 이번 측정은 RTX 4070 Ti SUPER가 있는 Linux 환경에서 Ollama 0.32.1, gemma3:4b Q4_K_M, bge-m3로 진행했습니다. 측정 시점은 2026년 9월입니다. 운영자 소개
댓글
댓글 쓰기