재귀 문자 텍스트 분할
재귀 문자 텍스트 분할 (RecursiveCharacterTextSplitter)
텍스트를 청크로 쪼갤 때 가장 많이 쓰이는 분할기가 바로 재귀 문자 텍스트 분할기예요. 이름에서 느껴지듯 구분자 목록을 순서대로 시도하면서 청크가 충분히 작아질 때까지 재귀적으로 나누는 방식이에요. 일반 텍스트에는 이 분할기가 공식 권장 사항이라서, 어떤 분할기를 쓸지 고민될 때는 일단 이걸 선택하면 돼요.
출처: 공식문서
분할 방식
이 분할기의 동작은 두 가지로 요약할 수 있어요.
- 텍스트를 어떻게 나누나: 문자 구분자 목록에 따라요.
- 청크 크기를 어떻게 재나: 문자 수로 측정해요.
구분자 목록은 문자 배열로 설정하며, 기본값은 ["\n\n", "\n", " ", ""]예요. 이 순서 덕분에 가능한 한 문단(그리고 문장, 단어)을 한 덩어리로 유지하려고 해요. 문단 경계가 없으면 문장으로, 문장도 없으면 단어로 내려가면서 나누기 때문에, 의미적으로 가장 강하게 연결된 텍스트 조각끼리 뭉치게 되는 거죠.
설치
Python
pip install -qU langchain-text-splitters
JavaScript
npm install @langchain/textsplitters
pnpm install @langchain/textsplitters
yarn add @langchain/textsplitters
bun add @langchain/textsplitters
사용 방법
문자열 그대로의 결과가 필요하면 .split_text를, 이후 작업에 쓸 Document 객체가 필요하면 .create_documents를 사용해요.
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Load example document
with open("state_of_the_union.txt") as f:
state_of_the_union = f.read()
text_splitter = RecursiveCharacterTextSplitter(
# Set a really small chunk size, just to show.
chunk_size=100,
chunk_overlap=20,
length_function=len,
is_separator_regex=False,
)
texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
print(texts[1])
page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and'
page_content='of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.'
print(text_splitter.split_text(state_of_the_union)[:2])
['Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and',
'of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.']
JavaScript 예시
문자열을 직접 얻으려면 .splitText, Document 객체가 필요하면 .createDocuments를 쓰면 돼요.
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 100, chunkOverlap: 0 })
const texts = splitter.createDocuments([{ pageContent: "..." }])
[
{ pageContent: "...", metadata: {} },
]
주요 매개변수
RecursiveCharacterTextSplitter에서 위 예시에 쓴 매개변수들을 차례로 살펴볼게요.
chunk_size: 청크 하나의 최대 크기예요. 실제 크기는length_function이 결정해요.chunk_overlap: 청크 사이의 목표 중첩량이에요. 문맥이 두 청크로 나뉘어 정보가 유실되는 걸 완화해 줘요.length_function: 청크 크기를 결정하는 함수예요.is_separator_regex: 구분자 목록(기본값["\n\n", "\n", " ", ""])을 정규식으로 해석할지 여부예요.
단어 경계가 없는 언어의 텍스트 분할
중국어, 일본어, 태국어처럼 단어 경계가 없는 문자 체계도 있어요. 기본 구분자 목록인 ["\n\n", "\n", " ", ""]으로 이 텍스트를 나누면 단어가 청크 사이에서 잘릴 수 있죠. 단어를 온전히 유지하려면 구분자 목록에 추가 구두점을 넣어 재정의하면 돼요.
- ASCII 마침표
".", 전각 마침표"."(중국어 텍스트에 사용), 한자권 마침표"。"(일본어·중국어에 사용) 추가 - 태국어·미얀마어·크메르어·일본어에서 쓰이는 제로 폭 공백(Zero-width space) 추가
- ASCII 쉼표
",", 전각 쉼표",", 한자권 쉼표"、"추가
text_splitter = RecursiveCharacterTextSplitter(
separators=[
"\n\n",
"\n",
" ",
".",
",",
"\u200b", # Zero-width space
"\uff0c", # Fullwidth comma
"\u3001", # Ideographic comma
"\uff0e", # Fullwidth full stop
"\u3002", # Ideographic full stop
"",
],
# Existing args
)
const splitter = new RecursiveCharacterTextSplitter({
separators: [
"\n\n",
"\n",
" ",
".",
",",
"\u200b", // Zero-width space
"\uff0c", // Fullwidth comma
"\u3001", // Ideographic comma
"\uff0e", // Fullwidth full stop
"\u3002", // Ideographic stop
"",
],
});
더 알아보기 (Learn more)
- Text splitters 개요 — 분할기의 종류와 선택 기준
- 문자 단위 텍스트 분할 — 가장 단순한 분할 방식
- 토큰 단위 텍스트 분할 — 언어 모델 토큰 제한에 맞춘 분할
- 코드 텍스트 분할 — 프로그래밍 언어별 분할