isPowerfulBlog
[LangChain] Text Splitter로 긴 문서를 작은 Chunk로 쪼개기 본문
LLM으로 문서 요약이 가능하다.
어떤 모델이냐에 따라서 다르지만, 모든 LLM은 input token 수에 제한이 있다.
그리고 보통 문서는 그 input token 수 제한을 뛰어넘기 마련이다ㅠㅠ...
따라서 LLM을 이용해 문서를 요약하기 위해서는 문서를 작은 chunk 단위로 쪼개는 작업을 먼서 해야한다.
문서를 chunk 단위로 쪼갠다는게 정확하게 뭘까? - Text Split
ㄴ 랭체인 공식 트위터에서 퍼왔다
먼저 Documents란, pdf, text, pptx, html 등 다양한 형태의 문서를 말할 수 있겠지만, text split에서 말하는 Documents는 기본적으로 텍스트로 파싱되어있는 형태의 문서를 가정한다. text여야 text split이 가능하니까..?
\
문서라 함은 정말 단순 텍스트의 나열일 수도 있겠지만, 보통 langchain의 fileloader 모듈을 사용하고, text splitter 모듈을 사용하고자 한다면 Dcoument
객체 형태로 다뤄야할 것이다.
\
Document
객체는 텍스트인 'page_content' 뿐만 아니라 문서에 대한 메타 데이터(page 등)를 포함한다.
보통 pdf 파일을 파싱하면 Document 객체 하나에는 한 페이지에 대한 텍스트와 정보(page 정보 등)이 들어가게 된다.
\
한 페이지의 내용이 너무 길 수도, 너무 짧을 수도 있다. 그래서 모든 Document
객체의 컨텐츠를 싸악 모아서 새로운 기준인 Chunk 단위로 분리하는 것이 Text split이다.
그렇다면 문서는 어떻게 쪼갤 수 있을까?
Langchain이 야무지게 모듈이 다 잘 만들어져있기 때문에...
공식 문서를 먼저 살펴본다.
LangcChain에서는 다음과 같은 타입의 Text Spliiter 모듈을 제공하고 있다.
(내맘대로) 간단한 순서대로 설명하면
- token : 토큰 단위로 쪼개는 방법이다.
- 토큰이란? 의미를 가지는 최소한의 단위
- character : 유저가 정의한 char 개수 기준으로 쪼개는 방법.
- 3이라고 정의해놨으면, 3글자씩 쪼갠다.
- recursive : 재귀적으로 쪼개기를 반복하면서 관련있는 조각을 옆에 두고자 노력하는 방식이다. 무난하게 얘를 많이 쓴다.
- 나머지 생략. sentence, sematic splitter는 나도 써보고 싶은데 뭐 돈이 너무 드는거 아닌가?
어떤 splitter를 쓸까?
- token splitter: 토큰 개수를 파악하기 위해서 쓰자
- recursive character splitter: character splitter보다는 유연하게 다른 splitter보다는 zero 비용으로 문서를 쪼개기 위해서 쓰자
이렇게 두 가지를 쓸 거다!
1. 문서의 양 (토큰 개수) 파악하기 - token splitter
langchain에서는 토큰 기반으로 text split을 할 수 있도록 tiktoken을 이용한 character text splitter를 제공하는데,
tiktoken으로 token재는 거 자체가 간단해서 굳이 랭체인으로 말린 걸 쓸 필욘 없다. 나도 그냥 tiktoken 갖다 씀!
import tiktoken
def num_tokens_from_string(self, documents) -> int:
encoding = tiktoken.get_encoding("cl100k_base")
total_tokens = 0
for document in documents:
num_tokens = len(encoding.encode(document.page_content))
total_tokens += num_tokens
print(f'예상되는 토큰 수: {total_tokens}')
return total_tokens
- "cl100k_base" 이라는 인코딩 모델을 쓴다.
- documents 리스트를 돌면서 document의 page_content를 인코딩씌워주면 토큰이 쫙 나온다. 이 토큰 리스트의 길이를 쟤서 토큰 수를 집계한다.
- 예상되는 토큰 수이고 실제로 gpt에서 어떻게 토크나이징 하는지에 따라서 다소 차이가 있을 수 있다. 참고용!
2. 문서 쪼개기 - recursive character splitter
def split_docs(self, documents):
text_splitter = RecursiveCharacterTextSplitter(chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP, length_function=len)
splitted_docs = text_splitter.split_documents(documents)
return splitted_docs
- chunk size: chunk 하나 사이즈, recursive를 쓰면 무조건 chunk size로 잘리진 않고 엇비슷하게 유연하게 잘라준다.
- chunk overlap: chunk랑 그 다음 chunk를 얼마나 겹치게 할지?, 개인적으로는 적당히 오버랩 줄 때가 더 성능이 괜찮았다.
예시 결과
페이지 수: 12
예상되는 토큰 수: 17146
총 48개의 문서 조각이 준비되었습니다.
- 12 페이지 짜리 pdf를 파싱하고
- tiktoken으로 토큰수를 계산해보며 컨텐츠 양을 측정한다.
- 나는 총 48개의 문서 조각으로 split되었다.
References
https://python.langchain.com/docs/modules/data_connection/document_transformers/
https://twitter.com/LangChainAI/status/1668275755300851715/photo/1
'AI' 카테고리의 다른 글
[NLP] 다양한 문서에서 중요한 키워드 추출하기 (2) | 2024.05.06 |
---|---|
[LangChain] LLM으로 문서 요약하기 (summarization) (0) | 2024.04.23 |
[LLM] LangChain 🦜🔗 (0) | 2023.11.07 |
[프로젝트] Anti-aginGAN for CAT based StyleGAN2 (0) | 2023.02.20 |
[Anaconda] 아나콘다 기본 명령어 (0) | 2023.01.24 |