안녕하세요. 이번에는 LangChain을 활용해서 문서를 분할 할 수 있는 여러가지 TextSplitter에 대해 살펴보겠습니다. 현 포스팅 이후에 업데이트되어 새로 추가되는 내용들은 댓글에 남겨주시면 감사하겠습니다 :)
텍스트 분할기는 종종 문장에 해당하는 의미론적 의미를 지닌 작은 조각으로 텍스트를 나누는 도구입니다. 이 텍스트 분할기가 중요한 이유는 LLM모델마다 max token의 수가 다르기 때문입니다. 그래서 텍스트 분할기를 통해 모델에 들어가는 토큰수를 제한해주어야하는데 이때 TextSplitter가 중요한 역할을 합니다. chatGPT 3.5 API의 최대 토큰수는 4096이기 때문에 chunk 크기를 4000으로 잘라줘도 되지만, 그렇게되면 효율적이지 못하기 때문에 2000정도로 잘라주게 되면 2000/2096으로 잘라지게되어 더 효율적으로 문서를 찾을 수 있습니다. 최대 토큰수가 8000이라면 그거에 맞게 최적의 수로 잘라주시면 됩니다. 동작방법은 다음과 같습니다.
1. 텍스트를 문장과 같은 의미론적 의미를 지닌 작은 조각으로 나눕니다.
2. 일반적으로 일부 기능으로 측정되는 특정 크기에 도달할 때까지 이러한 작은 조각을 더 큰 조각으로 결합합니다.
3. 해당 크기에 도달하면 해당 조각은 자체 텍스트단위가 됩니다. 그런 다음 조각 간의 컨텍스트를 유지하기 위해 일부 겹치는 새로운 텍스트 조각 생성이 시작됩니다.
텍스트 분할기는 2가지 기본 측면에서 사용자정의가 가능합니다.
1. 텍스트를 어떻게 나눌 수 있는가? characters, word 혹은 tokens
2. 조각(fragment)의 크기를 측정하는 방법 : 특정 요구 사항에 따라 조각의 크기를 조정할 수 있습니다.
# LangChain의 TextSplitter 유형
- RecursiveCharacterTextSplitter : 문자를 기준으로 텍스트를 조각 내어 첫 번째 문자부터 시작합니다. 조각이 너무 크게 나오면, 다음 문자로 이동합니다. 분할 문자와 조각 크기를 정의 할 수 있어 유연성을 제공합니다. 토큰 수가 아닌 문자 수로 분할됩니다. separators는 인자를 넘기지 않으면 None값을 전달하고 separator로써 \n\n만 사용가능합니다!
from langchain.text_splitter import RecursiveCharacterTextSplitter
CHUNK_SIZE_WORDS = 1500
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=CHUNK_SIZE_WORDS,
chunk_overlap=0,
separators = ['\n'] # optional, Use only "\n\n" as the separator
)
- 만약에 문자수가 아닌 토큰수로 분할하고자 한다면 ?! from_tiktoken_encoder를 사용하면됩니다
from langchain.text_splitter import RecursiveCharacterTextSplitter
CHUNK_SIZE_TOKENS = 1_500
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=CHUNK_SIZE_TOKENS,
chunk_overlap=0,
)
- CharacterTextSplitter : RecursiveCharacterTextSplitter와 유사하지만 보다 구체적인 구분을 위해 사용자 정의 구분 기호를 정의할 수 있는 기능이 있습니다. 기본적으로 "\n\n", "\n", " " 및 ""와 같은 문자로 분할을 시도합니다.
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
separator = "\n\n",
chunk_size = 1000,
chunk_overlap = 200,
)
- RecursiveTextSplitter : 이전 버전과 달리 RecursiveTextSplitter는 문자 대신 단어나 토큰을 기반으로 텍스트를 조각으로 나눕니다. 이는 보다 의미론적인 보기를 제공하며 구조보다는 콘텐츠 분석에 이상적입니다.
- TokenTextSplitter : OpenAI언어 모델을 사용하여 토큰을 기반으로 텍스트를 조각으로 분할하여 정확하고 상황에 맞는 분할이 가능하며 고급 자연어 처리 애플리케이션에 이상적입니다.
# TextSplitter 후 text출력
TextSplitter로 분할한 후에는 create_document혹은 split_text로 전달하게 되는데 결과의 차이를 보여드리겠습니다.
# 문서를 읽어드립니다.
with open('../../../rimiyeyo_txt.txt') as f:
rimiyeyo_txt = f.read()
create_doucumets로 했을 때의 결과입니다. page_content키와 metadata키가 같이 출력됩니다.
texts = text_splitter.create_documents([rimiyeyo_text])
print(texts[0])
page_content='Madam Speaker, Madam Vice President, \n\nLast year COVID-19 kept us apart., ' lookup_str='' metadata={} lookup_index=0
split_text로 했을 때의 결과입니다. text만 출력됩니다.
texts = text_splitter.split_text([rimiyeyo_text])
print(texts[0])
'Madam Speaker, Madam Vice President, \n\nLast year COVID-19 kept us apart.'
여기까지 LangChain에서 제공하는 여러가지 TextSplitter과 TextSplitter사용방법에 대해 살펴보았습니다~ 각 TextSplitter를 통해서 비교실험해보는 것도 굉장히 재미있을 것 같습니다.
'LLM > LangChain' 카테고리의 다른 글
RAG를 수행하기 위한 LangChain의 RetrievalQA 구조와 구현방법 (2) | 2023.11.19 |
---|