RAG & LANCHAIN (3)- Langchain 개념 & 문법 정리 ch.07 텍스트 분할(Text Splitter)

이영락·2024년 8월 29일
0

인공지능 공부

목록 보기
13/33

🏖️ CH07 텍스트 분할(Text Splitter)

텍스트 분할의 개요

  • 문서 분할Retrieval-Augmented Generation (RAG) 시스템의 두 번째 단계로서, 로드된 문서들을 효율적으로 처리하고, 시스템이 정보를 보다 잘 활용할 수 있도록 준비하는 중요한 과정이다.

    • 이 단계의 목적은 크고 복잡한 문서를 LLM이 받아들일 수 있는 효율적인 작은 규모의 조각으로 나누는 작업이다.

    • 나중에 사용자가 입력한 질문에 대하여 보다 효율적인 정보만 압축/선별하여 가져오기 위함이다.

(예시) 구글이 앤스로픽에 투자한 금액은 얼마야?

분할의 필요성

  • 핀포인트 정보 검색(정확성): 문서를 세분화함으로써 질문(Query)에 연관성이 있는 정보만 가져오는데 도움이 된다. 각각의 단위는 특정 주제나 내용에 초점을 맞추므로, 관련성이 높은 정보를 제공한다.

  • 리소스 최적화(효율성): 전체 문서를 LLM으로 입력하게 되면 비용이 많이 발생할 뿐더러, 효율적인 답변을 많은 정보 속에 발췌하여 답변하지 못하게 된다. 때로는 이러한 문제가 할루시네이션으로 이어지게 된다. 따라서, 답변에 필요한 정보만 발췌하기 위한 목적도 있다.

문서 분할 과정

  1. 문서 구조 파악: PDF 파일, 웹 페이지, 전자 책 등 다양한 형식의 문서에서 구조를 파악한다. 이는 문서의 헤더, 푸터, 페이지 번호, 섹션 제목 등을 식별하는 과정을 포함할 수 있다.

  2. 단위 선정: 문서를 어떤 단위로 나눌지 결정한다. 이는 페이지별, 섹션별, 또는 문단별일 수 있으며, 문서의 내용과 목적에 따라 다르다.

  3. 단위 크기 선정(chunk size): 문서를 몇 개의 토큰 단위로 나눌 것인지를 정한다.

  4. 청크 오버랩(chunk overlap): 분할된 끝 부분에서 맥락이 이어질 수 있도록 일부를 겹쳐서(overlap) 분할하는 것이 일반적이다.

청크 크기 & 청크 오버랩

  • 청크 크기청크 오버랩은 문서 분할에서 중요한 요소이다. 청크 크기는 문서를 몇 개의 토큰으로 나눌지 결정하는 것이며, 청크 오버랩은 문서의 끝 부분에서 맥락을 유지하기 위해 일부를 겹쳐서 분할하는 방법이다.

코드 예시

from langchain_text_splitters import RecursiveCharacterTextSplitter

# 단계 2: 문서 분할(Split Documents)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)
splits = text_splitter.split_documents(docs)

Chunk 분할 시각화

  • Greg Kamradt가 만든 Chunk Visualization 사이트를 활용하여 분할 과정을 시각적으로 확인할 수 있다.

Chunk Visualization 사이트


🏖️ 01. 문자 텍스트 분할(CharacterTextSplitter)

CharacterTextSplitter

  • CharacterTextSplitter는 텍스트를 가장 간단한 방식으로 분할하는 방법이다. 기본적으로 \n\n을 기준으로 문자 단위로 텍스트를 분할하고, 청크의 크기를 문자 수로 측정한다.

특징

  • 텍스트 분할 방식: 단일 문자 기준
  • 청크 크기 측정 방식: 문자 수 기준
%pip install -qU langchain-text-splitters

텍스트 파일 읽기

  • ./data/appendix-keywords.txt 파일을 열어 내용을 읽어들인다.
  • 읽어들인 내용을 file 변수에 저장한다.
# data/appendix-keywords.txt 파일을 열어서 f라는 파일 객체를 생성합니다.
with open("./data/appendix-keywords.txt") as f:
    file = f.read()  # 파일의 내용을 읽어서 file 변수에 저장합니다.
  • 파일로부터 읽은 파일의 일부 내용을 출력한다.
# 파일으로부터 읽은 내용을 일부 출력합니다.
print(file[:500])

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.
연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Embedding

정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.
예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다.
연관키워드: 자연어 처리, 벡터화, 딥러닝

CharacterTextSplitter를 사용하여 텍스트 분할

  • CharacterTextSplitter를 사용하여 텍스트를 청크(chunk)로 분할하는 코드.
from langchain_text_splitters import CharacterTextSplitter

text_splitter = CharacterTextSplitter(
    # 텍스트를 분할할 때 사용할 구분자를 지정합니다. 기본값은 "\n\n"입니다.
    # separator=" ",
    # 분할된 텍스트 청크의 최대 크기를 지정합니다.
    chunk_size=250,
    # 분할된 텍스트 청크 간의 중복되는 문자 수를 지정합니다.
    chunk_overlap=50,
    # 텍스트의 길이를 계산하는 함수를 지정합니다.
    length_function=len,
    # 구분자가 정규식인지 여부를 지정합니다.
    is_separator_regex=False,
)
  • text_splitter를 사용하여 file 텍스트를 문서 단위로 분할하고, 분할된 문서 리스트 중 첫 번째 문서를 출력한다.
texts = text_splitter.create_documents([file])
print(texts[0])  # 분할된 문서 중 첫 번째 문서를 출력합니다.

출력 예시:

page_content='Semantic Search\n\n정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.\n예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.\n연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝\n\nEmbedding'

메타데이터와 함께 문서 분할

  • 다음은 문서와 함께 메타데이터를 전달하는 예시다. 메타데이터가 문서와 함께 분할되는 점에 주목해야 한다.
metadatas = [
    {"document": 1},
    {"document": 2},
]  # 문서에 대한 메타데이터 리스트를 정의합니다.

documents = text_splitter.create_documents(
    [file, file],  # 분할할 텍스트 데이터를 리스트로 전달합니다.
    metadatas=metadatas,  # 각 문서에 해당하는 메타데이터를 전달합니다.
)
print(documents[0])  # 분할된 문서 중 첫 번째 문서를 출력합니다.

출력 예시:

page_content='Semantic Search\n\n정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.\n예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.\n연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝\n\nEmbedding' metadata={'document': 1}

텍스트 분할 예시

  • split_text() 메서드를 사용하여 텍스트를 분할한다.
text_splitter.split_text(file)[0]

출력 예시:

'Semantic Search\n\n정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.\n예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.\n연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝\n\nEmbedding'

🏖️ 02. 재귀적 문자 텍스트 분할(RecursiveCharacterTextSplitter)

RecursiveCharacterTextSplitter

  • RecursiveCharacterTextSplitter는 일반적인 텍스트를 분할하는 데 권장되는 방식이다. 이 방식은 텍스트를 단락, 문장, 단어 등 의미적으로 연관된 단위로 분할하여 문서의 의미를 최대한 유지하면서 작은 청크로 나누도록 설계되었다.

특징

  • 텍스트가 분할되는 방식: 문자 목록 ["\n\n", "\n", " ", ""]에 의해 분할된다.
  • 청크 크기가 측정되는 방식: 문자 수에 의해 측정된다.
  • 재귀적 분할: 단락 → 문장 → 단어 순서로 재귀적으로 분할한다.
%pip install -qU langchain-text-splitters

텍스트 파일 읽기

  • appendix-keywords.txt 파일을 열어 내용을 읽어들인다.
  • 읽어들인 내용을 file 변수에 저장한다.
# appendix-keywords.txt 파일을 열어서 f라는 파일 객체를 생성합니다.
with open("./data/appendix-keywords.txt") as f:
    file = f.read()  # 파일의 내용을 읽어서 file 변수에 저장합니다.
  • 파일로부터 읽은 파일의 일부 내용을 출력한다.
# 파일으로부터 읽은 내용을 일부 출력합니다.
print(file[:500])

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.
연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Embedding

정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.
예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다.
연관키워드: 자연어 처리, 벡터화, 딥러닝

Token

정의: 토큰은 텍스트를 더 작은 단위로 분할하는 것을 의미합니다. 이는 일반적으로 단어, 문장, 또는 구절일 수 있습니다.
예시: 문장 "나는 학교에 간다"를 "나는", "학교에", "간다"로 분할합니다.
연관키워드: 토큰화, 자연어

RecursiveCharacterTextSplitter를 사용하여 텍스트 분할

  • RecursiveCharacterTextSplitter를 사용하여 텍스트를 작은 청크로 분할하는 예제다.
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=250,  # 청크 크기를 매우 작게 설정합니다. 예시를 위한 설정입니다.
    chunk_overlap=50,  # 청크 간의 중복되는 문자 수를 설정합니다.
    length_function=len,  # 문자열 길이를 계산하는 함수를 지정합니다.
    is_separator_regex=False,  # 구분자로 정규식을 사용할지 여부를 설정합니다.
)
  • text_splitter를 사용하여 file 텍스트를 문서 단위로 분할하고, 분할된 문서의 첫 번째와 두 번째 문서를 출력한다.
texts = text_splitter.create_documents([file])
print(texts[0])  # 분할된 문서의 첫 번째 문서를 출력합니다.
print("===" * 20)
print(texts[1])  # 분할된 문서의 두 번째 문서를 출력합니다.

출력 예시:

page_content='Semantic Search\n\n정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.\n예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.\n연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝\n\nEmbedding'
============================================================
page_content='Embedding\n\n정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.\n예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다.\n연관키워드: 자연어 처리, 벡터화, 딥러닝\n\nToken'

텍스트 분할 예시

  • split_text() 함수를 사용하여 텍스트를 분할하고, 분할된 텍스트의 처음 2개 요소를 반환한다.
text_splitter.split_text(file)[:2]

출력 예시:

['Semantic Search\n\n정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.\n예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.\n연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝\n\nEmbedding', 'Embedding\n\n정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.\n예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다.\n연관키워드: 자연어 처리, 벡터화, 딥러닝\n\nToken']

🏖️ 03. 토큰 텍스트 분할(TokenTextSplitter)

TokenTextSplitter

  • TokenTextSplitter는 언어 모델의 토큰 제한을 고려하여 텍스트를 토큰 단위로 분할하는 데 사용되는 유용한 방법입니다. 이 분할기는 텍스트를 적절한 토큰 수로 청크(chunk)로 나누어 처리 성능을 최적화합니다.

tiktoken

  • tiktoken은 OpenAI에서 만든 빠른 BPE Tokenizer로, 토큰화를 빠르게 수행할 수 있습니다. 이를 사용하여 텍스트를 효율적으로 분할할 수 있습니다.
%pip install --upgrade --quiet langchain-text-splitters tiktoken

텍스트 파일 읽기

  • appendix-keywords.txt 파일을 열어 내용을 읽어들입니다.
  • 읽어들인 내용을 file 변수에 저장합니다.
# data/appendix-keywords.txt 파일을 열어서 f라는 파일 객체를 생성합니다.
with open("./data/appendix-keywords.txt") as f:
    file = f.read()  # 파일의 내용을 읽어서 file 변수에 저장합니다.
  • 파일로부터 읽은 파일의 일부 내용을 출력합니다.
# 파일으로부터 읽은 내용을 일부 출력합니다.
print(file[:500])

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.
연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Embedding

정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.
예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다.
연관키워드: 자연어 처리, 벡터화, 딥러닝

Token

정의: 토큰은 텍스트를 더 작은 단위로 분할하는 것을 의미합니다. 이는 일반적으로 단어, 문장, 또는 구절일 수 있습니다.
예시: 문장 "나는 학교에 간다"를 "나는", "학교에", "간다"로 분할합니다.
연관키워드: 토큰화, 자연어

tiktoken 인코더 기반 텍스트 분할

  • CharacterTextSplitterfrom_tiktoken_encoder 메서드를 사용하여 Tiktoken 인코더 기반의 텍스트 분할기를 초기화합니다.
from langchain_text_splitters import CharacterTextSplitter

text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=300,  # 청크 크기를 300으로 설정합니다.
    chunk_overlap=0,  # 청크 간 중복되는 부분이 없도록 설정합니다.
)
  • file 텍스트를 청크 단위로 분할하고, 분할된 청크의 개수를 출력합니다.
texts = text_splitter.split_text(file)
print(len(texts))  # 분할된 청크의 개수를 출력합니다.

출력 예시:

51
  • texts 리스트의 첫 번째 요소를 출력합니다.
# texts 리스트의 첫 번째 요소를 출력합니다.
print(texts[0])

출력 예시:

Semantic Search

TokenTextSplitter 사용 예시

  • TokenTextSplitter 클래스를 사용하여 텍스트를 토큰 단위로 분할합니다.
from langchain_text_splitters import TokenTextSplitter

text_splitter = TokenTextSplitter(
    chunk_size=200,  # 청크 크기를 200으로 설정합니다.
    chunk_overlap=0,  # 청크 간 중복을 0으로 설정합니다.
)
  • file 텍스트를 청크 단위로 분할하고, 분할된 텍스트의 첫 번째 청크를 출력합니다.
texts = text_splitter.split_text(file)
print(texts[0])  # 분할된 텍스트의 첫 번째 청크를 출력합니다.

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"�

Hugging Face tokenizer 사용 예시

  • Hugging Face에서 제공하는 GPT2TokenizerFast를 사용하여 텍스트의 토큰 길이를 계산하고, 텍스트를 분할합니다.
from transformers import GPT2TokenizerFast

# GPT-2 모델의 토크나이저를 불러옵니다.
hf_tokenizer = GPT2TokenizerFast.from_pretrained("gpt2")
  • CharacterTextSplitterfrom_huggingface_tokenizer 메서드를 통해 허깅페이스 토크나이저를 사용하여 텍스트 분할기를 초기화합니다.
text_splitter = CharacterTextSplitter.from_huggingface_tokenizer(
    hf_tokenizer,
    chunk_size=300,
    chunk_overlap=50,
)
texts = text_splitter.split_text(file)
  • texts 리스트의 1번째 요소를 출력합니다.
print(texts[1])

출력 예시:

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.
연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

🏖️ 04. 시멘틱 청커(SemanticChunker)

SemanticChunker는 텍스트를 의미론적 유사성에 기반하여 분할하는 도구입니다. 이 도구는 텍스트를 문장 단위로 분할한 후, 유사한 의미를 가진 문장들을 그룹화하여 청크(chunk)로 나눕니다. 이를 통해 유사한 내용을 가진 문장들이 함께 처리되며, 효율적인 텍스트 분석과 정보 검색이 가능합니다.

의존성 패키지 설치

%pip install -qU langchain_experimental langchain_openai

샘플 텍스트 로드

  • appendix-keywords.txt 파일을 열어 내용을 읽어들입니다.
# data/appendix-keywords.txt 파일을 열어서 f라는 파일 객체를 생성합니다.
with open("./data/appendix-keywords.txt") as f:
    file = f.read()  # 파일의 내용을 읽어서 file 변수에 저장합니다.

# 파일로부터 읽은 내용을 일부 출력합니다.
print(file[:350])

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다.
예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다.
연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Embedding

정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다.

SemanticChunker 생성

  • SemanticChunker를 사용하여 텍스트를 의미론적으로 관련된 청크로 분할합니다.
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings

# OpenAI 임베딩을 사용하여 의미론적 청크 분할기를 초기화합니다.
text_splitter = SemanticChunker(OpenAIEmbeddings())

텍스트 분할

  • text_splitter를 사용하여 file 텍스트를 분할합니다.
chunks = text_splitter.split_text(file)
  • 분할된 청크를 확인합니다.
# 분할된 청크 중 첫 번째 청크를 출력합니다.
print(chunks[0])

출력 예시:

Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다. 예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다. 연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Embedding

정의: 임베딩은 단어나 문장 같은 텍스트 데이터를 저차원의 연속적인 벡터로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트를 이해하고 처리할 수 있게 합니다. 예시: "사과"라는 단어를 [0.65, -0.23, 0.17]과 같은 벡터로 표현합니다. 연관키워드: 자연어 처리, 벡터화, 딥러닝

Breakpoints 방법

  • Breakpoints 방식은 문장을 분리할 시점을 결정하여 작동합니다. 임베딩 차이가 특정 임계값을 넘으면 문장이 분리됩니다.

Percentile 기준

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="percentile",
    breakpoint_threshold_amount=70,
)
  • 분할된 결과를 확인합니다.
docs = text_splitter.create_documents([file])
for i, doc in enumerate(docs[:5]):
    print(f"[Chunk {i}]", end="\n\n")
    print(doc.page_content)
    print("===" * 20)

출력 예시:

[Chunk 0]
Semantic Search

정의: 의미론적 검색은 사용자의 질의를 단순한 키워드 매칭을 넘어서 그 의미를 파악하여 관련된 결과를 반환하는 검색 방식입니다. 예시: 사용자가 "태양계 행성"이라고 검색하면, "목성", "화성" 등과 같이 관련된 행성에 대한 정보를 반환합니다. 연관키워드: 자연어 처리, 검색 알고리즘, 데이터 마이닝

Standard Deviation 기준

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="standard_deviation",
    breakpoint_threshold_amount=1.25,
)
  • 분할된 결과를 확인합니다.
docs = text_splitter.create_documents([file])
for i, doc in enumerate(docs[:5]):
    print(f"[Chunk {i}]", end="\n\n")
    print(doc.page_content)
    print("===" * 20)

Interquartile 기준

text_splitter = SemanticChunker(
    OpenAIEmbeddings(),
    breakpoint_threshold_type="interquartile",
    breakpoint_threshold_amount=0.5,
)
  • 분할된 결과를 확인합니다.
docs = text_splitter.create_documents([file])
for i, doc in enumerate(docs[:5]):
    print(f"[Chunk {i}]", end="\n\n")
    print(doc.page_content)
    print("===" * 20)

청크 분할 기준의 선택

SemanticChunker는 다양한 기준(Percentile, Standard Deviation, Interquartile)을 사용하여 텍스트를 의미론적으로 관련된 청크로 나누어 줍니다. 이는 LLM(대규모 언어 모델) 기반 응용 프로그램에서 효율적으로 텍스트를 처리하고, 정확한 정보를 제공하는 데 매우 유용합니다.


🏖️ 05. 코드 분할 (Python, Markdown, JAVA, C++, C#, GO, JS, Latex 등)

코드 분할은 다양한 프로그래밍 언어로 작성된 코드를 청크 단위로 분할하여 처리하는 과정입니다. 이를 통해 코드 내 특정 기능이나 문법을 쉽게 분석하거나 검색할 수 있습니다. 여기서는 RecursiveCharacterTextSplitterLanguage 클래스를 사용하여 Python, JavaScript, Markdown, LaTeX 등의 코드를 분할하는 방법을 설명합니다.

의존성 패키지 설치

%pip install -qU langchain-text-splitters

Python 코드 분할

from langchain_text_splitters import Language, RecursiveCharacterTextSplitter

PYTHON_CODE = """
def hello_world():
    print("Hello, World!")

hello_world()
"""

python_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.PYTHON, chunk_size=50, chunk_overlap=0
)

python_docs = python_splitter.create_documents([PYTHON_CODE])

for doc in python_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

def hello_world():
    print("Hello, World!")
==================
hello_world()
==================

JavaScript(JS) 코드 분할

JS_CODE = """
function helloWorld() {
  console.log("Hello, World!");
}

helloWorld();
"""

js_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.JS, chunk_size=60, chunk_overlap=0
)

js_docs = js_splitter.create_documents([JS_CODE])

for doc in js_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

function helloWorld() {
  console.log("Hello, World!");
}
==================
helloWorld();
==================

Markdown 텍스트 분할

markdown_text = """
# 🦜️🔗 LangChain

⚡ LLM을 활용한 초스피드 애플리케이션 구축 ⚡

## 빠른 설치

```bash
pip install langchain
빠르게 발전하는 분야의 오픈 소스 프로젝트 입니다. 많관부 🙏
"""

md_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.MARKDOWN,
    chunk_size=60,
    chunk_overlap=0,
)

md_docs = md_splitter.create_documents([markdown_text])

for doc in md_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

# 🦜️🔗 LangChain

⚡ LLM을 활용한 초스피드 애플리케이션 구축 ⚡
==================
## 빠른 설치

```bash
pip install langchain
==================
# 빠르게 발전하는 분야의 오픈 소스 프로젝트 입니다. 많관부 🙏
==================

LaTeX 코드 분할

latex_text = """
\documentclass{article}

\begin{document}

\maketitle

\section{Introduction}
LLM은 방대한 양의 텍스트 데이터로 학습하여 사람과 유사한 언어를 생성할 수 있는 기계 학습 모델의 한 유형입니다.

\subsection{History of LLMs}
초기 LLM은 1980년대와 1990년대에 개발되었지만, 처리할 수 있는 데이터 양과 당시 사용 가능한 컴퓨팅 능력으로 인해 제한되었습니다.

\subsection{Applications of LLMs}
LLM은 챗봇, 콘텐츠 생성, 가상 어시스턴트 등 산업 분야에서 많은 응용 분야를 가지고 있습니다.

\end{document}
"""

latex_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.LATEX, chunk_size=60, chunk_overlap=0
)

latex_docs = latex_splitter.create_documents([latex_text])

for doc in latex_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

\documentclass{article}

\begin{document}

\maketitle
==================
\section{Introduction}
LLM은 방대한 양의 텍스트 데이터로 학습하여 사람과 유사한
==================
언어를 생성할 수 있는 기계 학습 모델의 한 유형입니다.
==================
\subsection{History of LLMs}
초기 LLM은 1980년대와 1990년대에 개발되었지만, 처리할 수 있는 데이터 양과 당시 사용 가능한 컴퓨팅 능력으로 인해 제한되었습니다.
==================
\subsection{Applications of LLMs}
LLM은 챗봇, 콘텐츠 생성, 가상 어시스턴트 등 산업 분야에서 많은 응용 분야를 가지고 있습니다.
==================

Solidity 코드 분할

SOL_CODE = """
pragma solidity ^0.8.20; 
contract HelloWorld {  
   function add(uint a, uint b) pure public returns(uint) {
       return a + b;
   }
}
"""

sol_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.SOL, chunk_size=128, chunk_overlap=0
)

sol_docs = sol_splitter.create_documents([SOL_CODE])

for doc in sol_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

pragma solidity ^0.8.20;
==================
contract HelloWorld {  
   function add(uint a, uint b) pure public returns(uint) {
       return a + b;
   }
}
==================

C# 코드 분할

C_CODE = """
using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Enter a number (1-5):");
        int input = Convert.ToInt32(Console.ReadLine());
        for (int i = 1; i <= input; i++)
        {
            if (i % 2 == 0)
            {
                Console.WriteLine($"{i} is even.");
            }
            else
            {
                Console.WriteLine($"{i} is odd.");
            }
        }
        Console.WriteLine("Goodbye!");
    }
}
"""

c_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.CSHARP, chunk_size=128, chunk_overlap=0
)

c_docs = c_splitter.create_documents([C_CODE])

for doc in c_docs:
    print(doc.page_content, end="\n==================\n")

출력 예시:

using System;
==================
class Program
{
    static void Main()
    {
        Console.WriteLine("Enter a number (1-5):");
==================
int input = Convert.ToInt32(Console.ReadLine());
        for (int i = 1; i <= input; i++)
        {
==================
if (i % 2 == 0)
            {
                Console.WriteLine($"{i} is even.");
            }
            else
==================
{
                Console.WriteLine($"{i} is odd.");
            }
        }
        Console.WriteLine("Goodbye!");
    }
}
==================

결론

RecursiveCharacterTextSplitter를 사용하면 다양한 프로그래밍 언어로 작성된 코드를 손쉽게 청크 단위로 분할할 수 있습니다. 이 과정은 코드 분석, 검색, 이해에 유용하며, 코드의 구조를 잘 유지하면서 필요한 정보만을 효과적으로 추출할 수 있게 합니다.


🏖️ 06. 마크다운 헤더 텍스트 분할(MarkdownHeaderTextSplitter)

MarkdownHeaderTextSplitter는 마크다운 파일의 구조를 이해하고 효율적으로 다루는 데 유용한 도구입니다. 문서의 전체적인 맥락과 구조를 고려하여 텍스트를 의미 있는 방식으로 분할할 수 있습니다. 특히, 마크다운 파일의 헤더별로 내용을 나눠서 각 헤더 아래의 내용을 별도의 청크로 관리할 수 있습니다.

의존성 패키지 설치

%pip install -qU langchain-text-splitters

MarkdownHeaderTextSplitter 사용

from langchain_text_splitters import MarkdownHeaderTextSplitter

# 마크다운 형식의 문서를 문자열로 정의합니다.
markdown_document = "# Title\n\n## 1. SubTitle\n\nHi this is Jim\n\nHi this is Joe\n\n### 1-1. Sub-SubTitle \n\nHi this is Lance \n\n## 2. Baz\n\nHi this is Molly"

headers_to_split_on = [  # 문서를 분할할 헤더 레벨과 해당 레벨의 이름을 정의합니다.
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
]

# 마크다운 헤더를 기준으로 텍스트를 분할하는 MarkdownHeaderTextSplitter 객체를 생성합니다.
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# markdown_document를 헤더를 기준으로 분할하여 md_header_splits에 저장합니다.
md_header_splits = markdown_splitter.split_text(markdown_document)

# 분할된 결과를 출력합니다.
for header in md_header_splits:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

출력 예시:

Hi this is Jim  
Hi this is Joe
{'Header 1': 'Title', 'Header 2': '1. SubTitle'}
=====================
Hi this is Lance
{'Header 1': 'Title', 'Header 2': '1. SubTitle', 'Header 3': '1-1. Sub-SubTitle'}
=====================
Hi this is Molly
{'Header 1': 'Title', 'Header 2': '2. Baz'}
=====================

헤더를 제거하지 않고 분할하기

기본적으로 MarkdownHeaderTextSplitter는 청크 내에서 헤더를 제거합니다. 이를 비활성화하여 헤더를 유지하고 싶다면 strip_headers=False로 설정할 수 있습니다.

markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on,
    strip_headers=False,
)
md_header_splits = markdown_splitter.split_text(markdown_document)

# 분할된 결과를 출력합니다.
for header in md_header_splits:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

출력 예시:

# Title  
## 1. SubTitle  
Hi this is Jim  
Hi this is Joe
{'Header 1': 'Title', 'Header 2': '1. SubTitle'}
=====================
### 1-1. Sub-SubTitle  
Hi this is Lance
{'Header 1': 'Title', 'Header 2': '1. SubTitle', 'Header 3': '1-1. Sub-SubTitle'}
=====================
## 2. Baz  
Hi this is Molly
{'Header 1': 'Title', 'Header 2': '2. Baz'}
=====================

MarkdownHeaderTextSplitter와 다른 분할기 연결하기

MarkdownHeaderTextSplitter로 분할된 결과를 다시 RecursiveCharacterTextSplitter와 같은 다른 분할기를 사용하여 더 세부적으로 분할할 수 있습니다.

from langchain_text_splitters import RecursiveCharacterTextSplitter

markdown_document = "# Intro \n\n## History \n\nMarkdown[9] is a lightweight markup language for creating formatted text using a plain-text editor. John Gruber created Markdown in 2004 as a markup language that is appealing to human readers in its source code form.[9] \n\nMarkdown is widely used in blogging, instant messaging, online forums, collaborative software, documentation pages, and readme files. \n\n## Rise and divergence \n\nAs Markdown popularity grew rapidly, many Markdown implementations appeared, driven mostly by the need for \n\nadditional features such as tables, footnotes, definition lists,[note 1] and Markdown inside HTML blocks. \n\n#### Standardization \n\nFrom 2012, a group of people, including Jeff Atwood and John MacFarlane, launched what Atwood characterised as a standardisation effort. \n\n## Implementations \n\nImplementations of Markdown are available for over a dozen programming languages."

headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
]

markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on, strip_headers=False
)
md_header_splits = markdown_splitter.split_text(markdown_document)

chunk_size = 200
chunk_overlap = 20
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=chunk_size, chunk_overlap=chunk_overlap
)

splits = text_splitter.split_documents(md_header_splits)

# 분할된 결과를 출력합니다.
for header in splits:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

출력 예시:

# Intro  
## History
{'Header 1': 'Intro', 'Header 2': 'History'}
=====================
Markdown[9] is a lightweight markup language for creating formatted text using a plain-text editor. John Gruber created Markdown in 2004 as a markup language that is appealing to human readers in its
{'Header 1': 'Intro', 'Header 2': 'History'}
=====================
readers in its source code form.[9]
{'Header 1': 'Intro', 'Header 2': 'History'}
=====================
Markdown is widely used in blogging, instant messaging, online forums, collaborative software, documentation pages, and readme files.
{'Header 1': 'Intro', 'Header 2': 'History'}
=====================
## Rise and divergence  
As Markdown popularity grew rapidly, many Markdown implementations appeared, driven mostly by the need for
{'Header 1': 'Intro', 'Header 2': 'Rise and divergence'}
=====================
additional features such as tables, footnotes, definition lists,[note 1] and Markdown inside HTML blocks.  
#### Standardization
{'Header 1': 'Intro', 'Header 2': 'Rise and divergence'}
=====================
From 2012, a group of people, including Jeff Atwood and John MacFarlane, launched what Atwood characterised as a standardisation effort.
{'Header 1': 'Intro', 'Header 2': 'Rise and divergence'}
=====================
## Implementations  
Implementations of Markdown are available for over a dozen programming languages.
{'Header 1': 'Intro', 'Header 2': 'Implementations'}
=====================

MarkdownHeaderTextSplitter와 같은 도구를 사용하면 문서의 구조를 유지하면서도 각 헤더별로 분할된 텍스트를 관리할 수 있습니다. 이 방법을 통해 텍스트의 공통된 맥락을 유지하면서도 세부적인 청크를 효과적으로 다룰 수 있습니다.


🏖️ 07. HTML 헤더 텍스트 분할(HTMLHeaderTextSplitter)

HTMLHeaderTextSplitter는 HTML 문서의 구조를 이해하고 각 요소를 분할하여 메타데이터를 추가하는 "구조 인식" 청크 생성기입니다. 이는 문서의 구조적 맥락을 보존하면서 관련 텍스트를 그룹화하고, 다양한 텍스트 처리를 용이하게 합니다.

의존성 패키지 설치

%pip install -qU langchain-text-splitters

① HTML 문자열을 사용하는 경우

from langchain_text_splitters import HTMLHeaderTextSplitter

html_string = """
<!DOCTYPE html>
<html>
<body>
    <div>
        <h1>Foo</h1>
        <p>Some intro text about Foo.</p>
        <div>
            <h2>Bar main section</h2>
            <p>Some intro text about Bar.</p>
            <h3>Bar subsection 1</h3>
            <p>Some text about the first subtopic of Bar.</p>
            <h3>Bar subsection 2</h3>
            <p>Some text about the second subtopic of Bar.</p>
        </div>
        <div>
            <h2>Baz</h2>
            <p>Some text about Baz</p>
        </div>
        <br>
        <p>Some concluding text about Foo</p>
    </div>
</body>
</html>
"""

headers_to_split_on = [
    ("h1", "Header 1"),  # 분할할 헤더 태그와 해당 헤더의 이름을 지정합니다.
    ("h2", "Header 2"),
    ("h3", "Header 3"),
]

# 지정된 헤더를 기준으로 HTML 텍스트를 분할하는 HTMLHeaderTextSplitter 객체를 생성합니다.
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# HTML 문자열을 분할하여 결과를 html_header_splits 변수에 저장합니다.
html_header_splits = html_splitter.split_text(html_string)

# 분할된 결과를 출력합니다.
for header in html_header_splits:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

출력 예시:

Foo
{}
=====================
Some intro text about Foo.  
Bar main section Bar subsection 1 Bar subsection 2
{'Header 1': 'Foo'}
=====================
Some intro text about Bar.
{'Header 1': 'Foo', 'Header 2': 'Bar main section'}
=====================
Some text about the first subtopic of Bar.
{'Header 1': 'Foo', 'Header 2': 'Bar main section', 'Header 3': 'Bar subsection 1'}
=====================
Some text about the second subtopic of Bar.
{'Header 1': 'Foo', 'Header 2': 'Bar main section', 'Header 3': 'Bar subsection 2'}
=====================
Baz
{'Header 1': 'Foo'}
=====================
Some text about Baz
{'Header 1': 'Foo', 'Header 2': 'Baz'}
=====================
Some concluding text about Foo
{'Header 1': 'Foo'}
=====================

② 웹 URL에서 HTML을 로드하여 처리하는 경우

이 예시에서는 웹 URL로부터 HTML 콘텐츠를 로드한 후, 이를 HTML 헤더를 기준으로 분할하고, 이후에 다른 분할기를 사용하여 추가로 처리합니다.

from langchain_text_splitters import RecursiveCharacterTextSplitter

url = "https://plato.stanford.edu/entries/goedel/"  # 분할할 텍스트의 URL을 지정합니다.

headers_to_split_on = [  # 분할할 HTML 헤더 태그와 해당 헤더의 이름을 지정합니다.
    ("h1", "Header 1"),
    ("h2", "Header 2"),
    ("h3", "Header 3"),
    ("h4", "Header 4"),
]

# HTML 헤더를 기준으로 텍스트를 분할하는 HTMLHeaderTextSplitter 객체를 생성합니다.
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

# URL에서 텍스트를 가져와 HTML 헤더를 기준으로 분할합니다.
html_header_splits = html_splitter.split_text_from_url(url)

chunk_size = 500  # 텍스트를 분할할 청크의 크기를 지정합니다.
chunk_overlap = 30  # 분할된 청크 간의 중복되는 문자 수를 지정합니다.
text_splitter = RecursiveCharacterTextSplitter(  # 텍스트를 재귀적으로 분할하는 RecursiveCharacterTextSplitter 객체를 생성합니다.
    chunk_size=chunk_size, chunk_overlap=chunk_overlap
)

# HTML 헤더로 분할된 텍스트를 다시 청크 크기에 맞게 분할합니다.
splits = text_splitter.split_documents(html_header_splits)

# 분할된 텍스트 중 80번째부터 85번째까지의 청크를 출력합니다.
for header in splits[80:85]:
    print(f"{header.page_content}")
    print(f"{header.metadata}", end="\n=====================\n")

출력 예시:

We see that Gödel first tried to reduce the consistency problem for analysis to that of arithmetic. This seemed to require a truth definition for arithmetic, which in turn led to paradoxes, such as the Liar paradox (“This sentence is false”) and Berry’s paradox (“The least number not defined by an expression consisting of just fourteen English words”). Gödel then noticed that such paradoxes would not necessarily arise if truth were replaced by provability. But this means that arithmetic truth
{'Header 1': 'Kurt Gödel', 'Header 2': '2. Gödel’s Mathematical Work', 'Header 3': '2.2 The Incompleteness Theorems', 'Header 4': '2.2.1 The First Incompleteness Theorem'}
=====================
means that arithmetic truth and arithmetic provability are not co-extensive — whence the First Incompleteness Theorem.
{'Header 1': 'Kurt Gödel', 'Header 2': '2. Gödel’s Mathematical Work', 'Header 3': '2.2 The Incompleteness Theorems', 'Header 4': '2.2.1 The First Incompleteness Theorem'}
=====================
This account of Gödel’s discovery was told to Hao Wang very much after the fact; but in Gödel’s contemporary correspondence with Bernays and Zermelo, essentially the same description of his path to the theorems is given. (See Gödel 2003a and Gödel 2003b respectively.) From those accounts we see that the undefinability of truth in arithmetic, a result credited to Tarski, was likely obtained in some form by Gödel by 1931. But he neither publicized nor published the result; the biases logicians
{'Header 1': 'Kurt Gödel', 'Header 2': '2. Gödel’s Mathematical Work', 'Header 3': '2.2 The Incompleteness Theorems', 'Header 4': '2.2.1 The First Incompleteness Theorem'}
=====================
result; the biases logicians had expressed at the time concerning the notion of truth, biases which came vehemently to the fore when Tarski announced his results on the undefinability of truth in formal systems 1935, may have served as a deterrent to Gödel’s publication of that theorem.
{'Header 1': 'Kurt Gödel', 'Header 2': '2. Gödel’s Mathematical Work', 'Header 3': '2.2 The Incompleteness Theorems', 'Header 4': '2.2.1 The First Incompleteness Theorem'}
=====================
We now describe the proof of the two theorems, formulating Gödel’s results in Peano arithmetic. Gödel himself used a system related to that defined in Principia Mathematica, but containing Peano arithmetic. In our presentation of the First and Second Incompleteness Theorems we refer to Peano arithmetic as P, following Gödel’s notation.
{'Header 1': 'Kurt Gödel', 'Header 2': '2. Gödel’s Mathematical Work', 'Header 3': '2.2 The Incompleteness Theorems', 'Header 4': '2.2.2 The proof of the First Incompleteness Theorem'}
=====================

한계

HTMLHeaderTextSplitter는 문서 구조의 차이를 처리하려고 시도하지만, 특정 경우에는 헤더를 누락할 수 있습니다. 예를 들어, 헤더가 예상하지 못한 하위 트리에 위치할 경우 관련된 텍스트와 헤더가 메타데이터에 제대로 나타나지 않을 수 있습니다. 이러한 점을 고려하여 HTML 문서의 구조를 분석하고 텍스트를 분할하는 것이 중요합니다.


🏖️ 08. 재귀적 JSON 분할(RecursiveJsonSplitter)

RecursiveJsonSplitter는 JSON 데이터를 깊이 우선 탐색하여 작은 청크로 분할하는 도구입니다. 이 분할기는 중첩된 JSON 구조를 가능한 한 보존하면서, 청크 크기를 설정된 범위 내에 유지하려고 합니다.

분할 기준 및 원리

  • 텍스트 분할 방식: JSON 값 기준으로 분할
  • 청크 크기 측정 방식: 문자 수 기준
  • 중첩된 JSON: 가능하면 유지하나, 크기 조절이 필요할 경우 분할

의존성 패키지 설치

%pip install -qU langchain-text-splitters

JSON 데이터 로드 및 분할 예제

import requests
from langchain_text_splitters import RecursiveJsonSplitter

# JSON 데이터를 로드합니다.
json_data = requests.get("https://api.smith.langchain.com/openapi.json").json()

# JSON 데이터를 최대 300 크기의 청크로 분할하는 RecursiveJsonSplitter 객체를 생성합니다.
splitter = RecursiveJsonSplitter(max_chunk_size=300)

# JSON 데이터를 재귀적으로 분할합니다.
json_chunks = splitter.split_json(json_data=json_data)

# JSON 데이터를 기반으로 문서를 생성합니다.
docs = splitter.create_documents(texts=[json_data])

# JSON 데이터를 기반으로 문자열 청크를 생성합니다.
texts = splitter.split_text(json_data=json_data)

# 첫 번째 문서를 출력합니다.
print(docs[0].page_content)

print("===" * 20)

# 첫 번째 문자열 청크를 출력합니다.
print(texts[0])

출력 예시:

{"openapi": "3.1.0", "info": {"title": "LangSmith", "version": "0.1.0"}, "paths": {"/api/v1/sessions/{session_id}": {"get": {"tags": ["tracer-sessions"], "summary": "Read Tracer Session", "description": "Get a specific session."}}}}
============================================================
{"openapi": "3.1.0", "info": {"title": "LangSmith", "version": "0.1.0"}, "paths": {"/api/v1/sessions/{session_id}": {"get": {"tags": ["tracer-sessions"], "summary": "Read Tracer Session", "description": "Get a specific session."}}}}

JSON 리스트 분할 및 파싱 예제

JSON 데이터에서 큰 리스트 객체가 포함된 경우, RecursiveJsonSplitter는 리스트 객체를 분할하지 않습니다. 리스트를 딕셔너리 형태로 변환하는 방법은 다음과 같습니다.

import json

# 청크의 크기를 확인해 봅시다.
print([len(text) for text in texts][:10])

# 더 큰 청크 중 하나를 검토해 보면 리스트 객체가 있는 것을 볼 수 있습니다.
print(texts[1])

# JSON 모듈을 사용하여 2번 index 청크를 파싱합니다.
json_data = json.loads(texts[2])
print(json_data["paths"])

출력 예시:

[232, 197, 469, 210, 213, 237, 271, 191, 232, 215]
{"paths": {"/api/v1/sessions/{session_id}": {"get": {"operationId": "read_tracer_session_api_v1_sessions__session_id__get", "security": [{"API Key": []}, {"Tenant ID": []}, {"Bearer Auth": []}]}}}}

리스트를 딕셔너리로 변환하는 방법

리스트를 index:item 형태로 변환하여 분할하는 방법입니다.

# JSON을 전처리하고 리스트를 인덱스:항목을 키:값 쌍으로 하는 딕셔너리로 변환합니다.
texts = splitter.split_text(json_data=json_data, convert_lists=True)

# 리스트가 딕셔너리로 변환되었고, 그 결과를 확인합니다.
print(texts[2])

출력 예시:

{"paths": {"/api/v1/sessions/{session_id}": {"get": {"parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Session Id"}}, {"name": "include_stats", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Include Stats"}}, {"name": "accept", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accept"}}]}}}}

결론

RecursiveJsonSplitter를 사용하면 복잡한 JSON 데이터를 구조적으로 이해하고, 이를 적절한 크기의 청크로 분할할 수 있습니다. 이 과정은 JSON 데이터의 분석 및 처리를 용이하게 하며, 청크 크기에 대한 엄격한 제한이 필요한 경우 추가적인 텍스트 분할기를 사용할 수 있습니다.

profile
AI Engineer / 의료인공지능

0개의 댓글

관련 채용 정보