LLM은 왜 최신 사내 문서를 답하지 못하는가
LLM의 답이 틀리는 이유는 크게 세 가지다. 학습 시점, 데이터 접근 범위, 생성 방식에서 한계가 생긴다.
LLM은 정해진 시점까지의 데이터로 학습한다. 그 뒤에 바뀐 내용은 알지 못한다. 이를 Knowledge Cutoff라고 한다.
사내 규정이나 학교 학칙처럼 공개되지 않은 문서도 학습 데이터에 없다. 또 LLM은 사실이 아닌 내용도 그럴듯하게 만들어낸다. 이것이 Hallucination이다.
- Knowledge Cutoff
- 모델 학습 시점 이후의 최신 데이터를 알지 못하는 한계다. 오늘 바뀐 정책을 물으면 답할 수 없다.
- Private Data 부재
- 공개되지 않은 사내 문서나 학칙은 학습 데이터에 없어 알 수 없다. 따로 넣어주지 않으면 답이 나오지 않는다.
- Hallucination(환각)
- 없는 사실을 사실인 것처럼 확률적으로 생성하는 현상이다. 문장이 그럴듯해도 근거가 없을 수 있다.
문서를 모델에 넣는 방법은 세 가지다
Prompting, Fine-tuning, RAG는 모두 LLM에 지식을 더하려는 시도다. 비용과 정확도에서 갈린다.
Prompting은 매 질문마다 문서를 프롬프트에 넣는 방식이다. 구현은 쉽지만 문서가 길면 Context Window를 넘는다. 토큰 비용도 늘고, 중간 정보를 놓치는 Lost in the Middle 문제가 생긴다.
Fine-tuning은 모델 자체를 재학습시킨다. 비용과 시간이 많이 든다. RAG는 질문과 관련된 부분만 검색해 넣어 정확도와 신뢰도를 높인다.
- Prompting
- 문서를 프롬프트에 직접 붙이는 방식이다. 컨텍스트 윈도우 제한, 토큰 비용, 정보 유실이 단점이다.
- Fine-tuning
- 모델을 다시 학습시켜 지식을 반영하는 방식이다. 비용과 시간이 많이 소요된다.
- RAG
- 질문과 관련된 부분만 검색해 컨텍스트로 주입한다. 정확도와 신뢰도를 높이는 방식이다.
Prompting
- 매 질문마다 문서를 통째로 넣는다
- Context Window 한계에 부딪힌다
- 토큰 비용이 커지고 정보가 묻힌다
RAG
- 질문과 관련된 청크만 검색한다
- 필요한 부분만 컨텍스트에 담는다
- 근거를 함께 넣어 신뢰도를 높인다
같은 문서를 쓰더라도 넣는 범위가 다르다.
인덱싱 파이프라인: 저장할 준비를 하는 네 단계
인덱싱은 문서를 검색 가능한 형태로 바꿔 저장하는 과정이다. Document → Chunking → Embedding → Vector DB 순서다.
먼저 원본 문서를 읽어 들인다. 다음으로 검색하기 좋은 크기로 자른다. 자른 조각을 벡터로 바꾸고, pgvector 같은 벡터 DB에 저장한다.
이렇게 저장해 두어야 질문이 들어왔을 때 비슷한 조각을 바로 찾을 수 있다.
5주차의 네 단계는 개념 설명이다. 6주차에서는 업로드·바이트 추출·텍스트 정제를 앞에 붙여 여섯 단계로 구현한다. 같은 파이프라인을 더 잘게 센 것이다.
- Document
- 원본 문서를 로드하는 단계다. 이후 모든 처리는 이 원본에서 시작한다.
- Chunking
- 문서를 검색 가능한 작은 단위로 나눈다. 임베딩 모델의 입력 제한을 지키기 위해서다.
- Embedding
- 청크 텍스트를 벡터 값으로 변환한다. 의미가 비슷한 텍스트는 가까운 벡터가 된다.
- Vector DB 저장
- 벡터를 pgvector 같은 벡터 데이터베이스에 저장한다. 유사도 검색의 대상이 된다.
저장이 끝나야 검색할 수 있다.
쿼리 파이프라인: 질문이 답이 되는 네 단계
쿼리는 질문을 벡터로 바꿔 비슷한 청크를 찾고, 그것을 프롬프트에 붙여 답을 만든다.
사용자 질문은 인덱싱 때와 같은 임베딩 모델로 벡터화한다. 그래야 같은 기준으로 비교할 수 있다. 벡터 DB에서 유사도가 높은 청크를 찾는다.
찾은 청크, 시스템 프롬프트, 사용자 질문을 하나로 합쳐 LLM에 넘긴다. LLM은 이 근거를 바탕으로 답변을 생성한다.
- User Query Embedding
- 사용자 질문을 벡터로 바꾼다. 인덱싱과 동일한 임베딩 모델을 써야 한다.
- Similarity Search
- 벡터 DB에서 유사도가 높은 청크를 검색한다. 코사인 유사도 같은 척도를 쓴다.
- Prompt Assembly
- 시스템 프롬프트, 검색된 컨텍스트, 사용자 질문을 결합한다.
- LLM Generation
- LLM이 근거에 기반한 최종 답변을 생성한다.
청킹: 왜 자르고, 어떻게 자르는가
청킹은 문서를 검색 단위로 나누는 일이다. 목적은 세 가지이고, 방법도 세 가지로 나뉜다.
임베딩 모델은 한 번에 넣을 수 있는 토큰 수가 정해져 있다. 문서가 길면 그대로 넣을 수 없다. 또 한 덩어리가 너무 길면 여러 주제가 섞여 벡터의 의미가 흐려진다.
잘게 나눌수록 검색은 정밀해지지만 문맥이 끊길 수 있다. 그래서 자르는 기준을 고르는 일이 중요하다.
- 입력 토큰 제한 준수
- 임베딩 모델이 받을 수 있는 입력 토큰 수를 넘지 않게 한다.
- 의미 희석 방지
- 한 청크에 여러 주제가 섞이면 벡터의 의미가 흐려진다. 이를 막는다.
- 검색 정밀도 향상
- 질문에 맞는 조각을 찾을 확률을 높인다.
| 방식 | 나누는 기준 | 특징 |
|---|---|---|
| 고정 크기 (Fixed-size) | 일정 글자 수 | 가장 간단하지만 문맥이 중간에 끊길 위험이 있다 |
| 구조 기반 (Structure-based) | 마크다운·HTML의 헤더 등 문서 구조 | 논리적 단위로 나눠 문맥을 유지한다 |
| 의미 기반 (Semantic) | 문장 간 임베딩 유사도 | 품질은 높지만 비용이 많이 든다 |
검색한 근거를 답변으로 바꾸는 시스템 프롬프트
프롬프트에는 세 가지 규칙을 넣는다. 근거 안에서만 답하고, 없으면 모른다고 하고, 출처를 밝힌다.
검색된 컨텍스트를 넣어도 LLM이 지어낼 수 있다. 시스템 프롬프트로 답변의 범위를 묶어야 한다.
출처 표기는 답변의 신뢰도를 높이고, 나중에 원문을 확인할 수 있게 한다.
- 컨텍스트 근거 원칙
- 제공된 컨텍스트 안의 정보만 근거로 답하라고 지시한다. 환각을 줄이는 첫 번째 장치다.
- 모른다 원칙
- 컨텍스트에 내용이 없으면 찾을 수 없다고 답하게 한다. 추측으로 채우지 못하게 막는다.
- 출처 표기 원칙
- 답변에 [1] 같은 출처를 반드시 표기하게 한다. 신뢰도와 추적 가능성을 확보한다.
시험 직전 체크
EXAM POINTS- LLM의 세 한계(Knowledge Cutoff, Private Data, Hallucination)를 구분한다.
- Prompting·Fine-tuning·RAG의 차이와 Prompting의 단점을 설명한다.
- 개념 인덱싱 4단계와 쿼리 4단계를 순서대로 쓴다. 6주차의 구현 6단계와 구분한다.
- 청킹의 목적 3가지와 세 전략의 기준을 비교한다.
- 시스템 프롬프트 3원칙과 각 원칙이 막는 문제를 연결한다.
헷갈리는 것만
COMMON TRAPS아니다. Fine-tuning만 모델을 재학습시킨다. RAG는 검색한 근거를 프롬프트에 넣는다.
아니다. 잘게 나누면 문맥이 끊긴다. 검색 정밀도와 문맥 유지 사이에서 고른다.
아니다. 근거를 무시하거나 왜곡할 수 있어 시스템 프롬프트로 범위를 묶어야 한다.
안 된다. 인덱싱과 같은 임베딩 모델을 써야 같은 기준으로 벡터를 비교할 수 있다.
KEYWORDS
- RAG
- Knowledge Cutoff
- Hallucination
- Embedding
- Chunking
- Vector DB
- pgvector
- Similarity Search
- Context Window
- Prompt Injection
연결해서 기억하기
- 6주차에서는 이 인덱싱 파이프라인을 실제 파일 업로드와 저장소 설계로 구현한다.
- 여기서 고른 청킹 전략이 6주차의 재귀적 분할로 구체화된다.