이번에는 저번 Prompt Engineering에 이어서 Chunking에 대해서 알아보겠다.
청킹은 자연어를 특정 크기로 나누는 것을 의미한다. 각 나누어진 단위를 청크(chunk)라고 하며, 이러한 기법을 적용하는 도구를 텍스트 분할기(Text splitters)라고 한다. 따라서 텍스트 분할을 어떻게 하느냐에 따라서 청킹이 구성되는 방식이 달라진다. 중요한 점은 이러한 텍스트 분할은 분할을 적용하려는 자연어의 종류에 따라 나뉜다는 것이다.
텍스트 분할은 RAG(Retrieval-Augmented Generation, 검색 증강 생성)에서 사용되는 핵심 기법이다. 긴 문서를 모델이 처리하기 쉬운 작은 단위인 청크로 나누어, 효율적인 검색과 정확한 답변 생성을 가능하게 한다.
문서를 나누는 구체적인 이유는 다음과 같다.
텍스트 분할을 구현하는 방법은 여러 가지가 있다.
가장 직관적인 방법으로, 정해진 길이(문자 또는 토큰 수)를 기준으로 문서를 나눈다.
문단, 문장, 단어 등 텍스트의 계층적 구조를 활용하여 자연스러운 언어 흐름을 유지하며 분할한다.
HTML, Markdown, JSON 등 문서 자체의 내재된 구조를 활용하여 분할한다.
#, ##), HTML의 태그, JSON의 객체나 배열 등을 기준으로 분할한다.텍스트의 내용적 의미를 직접 분석하여 분할한다.
참고로, 슬라이딩 윈도우는 특정 데이터를 어떠한 단위(윈도우)로 나누고, 그 데이터 단위들을 순회(슬라이딩)하며 작업을 진행하는 기법이다. 의미적 유사도 기반 분할의 경우, 특정 단위의 문장(윈도우)의 의미를 분석하여 임베딩을 하고, 다음 문장으로 넘어간 뒤(슬라이딩), 다시 해당 문장을 임베딩하여 임베딩된 문장 사이의 차이점을 알아내 분할 지점을 찾는 방식이다.
텍스트 분할을 진행할 때 고려해야 하는 점은 자연어를 청크로 나누는 단위인 청크 크기(Chunk Size)와, 나누어진 청크 사이의 관계인 청크 중첩(Chunk Overlap)을 유지하는 것이다. 인접한 청크 사이에 청크 중첩을 적용하여 문맥적 연속성을 유지시켜주는 작업을 진행한다.
청크 크기와 청크 중첩, 이 두 변수를 적용하여 텍스트 분할을 진행하게 되는데, 해당 변수의 크기에 따라 자연어를 분석하는 정도가 달라진다. 중요한 점은, 해당 자연어가 어떠한 종류의 자연어인지가 중요한데, 각 종류에 따라 문장의 복잡도와 구조가 다르기 때문이다.
청크 크기에 따라 좋은 성능을 보이는 문서들을 표로 정리하면 다음과 같다. 이는 문서의 구조와 내용적 특성을 기반으로 한다.
| 특징 | 작은 청크 크기(Small Chunk Size) | 큰 청크 크기(Large Chunk Size) |
|---|---|---|
| 적합한 문서 종류 | 질문-답변(FAQ) 문서, 기술 문서의 API 설명, 법률 조항, 단순 사실 목록 | 학술 논문, 연구 보고서, 소설, 에세이, 복잡한 기술 매뉴얼, 심층 뉴스 기사 |
| 효율성 근거 | 정확한 검색, 노이즈 감소, 컨텍스트 창 효율 | 문맥 보존, 관계 추론 용이, 종합적 답변 가능 |
청크 크기를 결정할 때는 문서의 내용이 얼마나 독립적인지와 문맥이 얼마나 중요한지를 기준으로 판단하는 것이 중요하다. 정형화되고 독립적인 내용이 많은 문서는 작은 청크가, 문맥적 흐름과 논리적 관계가 중요한 문서는 큰 청크가 더 효율적이다.
또한, 청크 오버랩은 보통 청크 크기의 10~20% 를 사용한다. 문서 구조와 내용에 따라 적절한 청크 크기를 찾아내고 10~20% 비율 안에서 최적의 오버랩 비율을 찾아내는 것이 좋은 텍스트 분할기를 만드는 방법이라 볼 수 있겠다.
다음 시간에는 LangChain 환경에서 간단한 청킹 실습을 진행해 보겠다.