ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LlamaIndex] Loading Data
    카테고리 없음 2024. 1. 16. 16:03

    LLM을 설정한 이후, 데이터와 관련된 작업을 시키기 위해서는 먼저 데이터를 로드 하고 처리해야 합니다. 로드 & 처리된 데이터는 색인화 및 저장 단계를 거쳐 활용할 수 있습니다. Loading Data 단계에서는 Loaders와 Transformaions으로 데이터를 어떻게 불러들이고 처리하는지 살펴보겠습니다.

     

    ○ Loaders

    LlamaIndex에서는 Data Connector를 통해 데이터를 Load 합니다. Data Connector는 다양한 데이터 원본에서 데이터를 수집한 것을 'Document'라는 개체로 저장합니다. 'Document'는 텍스트, 이미지 등의 데이터를 의미하는것 뿐만 아니라 관련된 메타데이터도 포함하여 의미합니다.

     

    # 기본 Data Connector 사용

    LlamaIndex에서는 SympleDirectoryReader를 사용하여 Markdown, PDF, Word, PPT, 이미지, 오디오 등의 다양한 형식의 데이터를 편리하게 읽을 수 있습니다.

    from llama_index import SimpleDirectoryReader
    
    documents = SimpleDirectoryReader("./data").load_data()

     

    # 다양한 Data Connector 사용

    LlamaIndex에서는 다양한 포맷의 데이터를 Load하는 Data Connector 들을 LlamaHub(https://llamahub.ai)에서 제공하고 있으며, 수백개의 Data Connector를 제공하고 있습니다. 아래의 예시는 SQL 데이터베이스를 읽고 쿼리를 실행합니다. 

    from llama_index import download_loader
    
    DatabaseReader = download_loader("DatabaseReader")
    
    reader = DatabaseReader(
        scheme=os.getenv("DB_SCHEME"),
        host=os.getenv("DB_HOST"),
        port=os.getenv("DB_PORT"),
        user=os.getenv("DB_USER"),
        password=os.getenv("DB_PASS"),
        dbname=os.getenv("DB_NAME"),
    )
    
    query = "SELECT * FROM users"
    documents = reader.load_data(query=query)

     

     

    ○ Transformations

    데이터가 로드된 후 데이터를 저장하기 전에 처리하고 변환(Transformation)해야 합니다. 이러한 변환에는 Chunk 분할, 메타데이터 추출 등이 포함됩니다. 이는 LLM에서 데이터를 검색하고 최적으로 사용할 수 있는지 확인하는 데 필요합니다. LlamaIndex에서는 분할된 Document인 Chunk를 'Node'라고 표현합니다. 

     

    # Transformations 사용

    LlamaIndex에서는 '.from_documents' 메서드를 통해 기본적인 Chunking 기능을 제공하고 있습니다.

    from llama_index import VectorStoreIndex
    
    vector_index = VectorStoreIndex.from_documents(documents)
    vector_index.as_query_engine()

     

    Chuk size, overlap 등의 설정이 필요한 경우, 아래 예시와 같이 설정 할 수 있습니다.

    text_splitter = SentenceSplitter(chunk_size=512, chunk_overlap=10)
    service_context = ServiceContext.from_defaults(text_splitter=text_splitter)
    
    index = VectorStoreIndex.from_documents(
        documents, service_context=service_context
    )

     

    # 사용자 정의 Transformations 사용

    'ServiceContext'와 결합하여 Transformation에 대해 더 구체적으로 설정할 수 있습니다.

    from llama_index import ServiceContext, VectorStoreIndex
    from llama_index.extractors import (
        TitleExtractor,
        QuestionsAnsweredExtractor,
    )
    from llama_index.ingestion import IngestionPipeline
    from llama_index.text_splitter import TokenTextSplitter
    
    transformations = [
        TokenTextSplitter(chunk_size=512, chunk_overlap=128),
        TitleExtractor(nodes=5),
        QuestionsAnsweredExtractor(questions=3),
    ]
    
    service_context = ServiceContext.from_defaults(
        transformations=[text_splitter, title_extractor, qa_extractor]
    )
    
    index = VectorStoreIndex.from_documents(
        documents, service_context=service_context
    )

     

     

    ○ Transformations - 텍스트 분할기

    LlamaIndex에서는 좋은 품질의 Node 생성을 위해 다양한 텍스트 분할기를 제공합니다.

     

    # LanchainNodeParser

    랭체인에서 제공하는 텍스트 분할기를 래핑하여 사용 할 수 있습니다. 

    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from llama_index.node_parser import LangchainNodeParser
    
    parser = LangchainNodeParser(RecursiveCharacterTextSplitter())
    nodes = parser.get_nodes_from_documents(documents)

     

     

    # SentenceSplitter

    문장의 경계를 보존하며 텍스트를 분할합니다.

    from llama_index.text_splitter import SentenceSplitter
    
    splitter = SentenceSplitter(
        chunk_size=1024,
        chunk_overlap=20,
    )
    nodes = splitter.get_nodes_from_documents(documents)

     

     

    # SentenceWindowNodeParser

    문장 단의로 텍스트를 분할하지만, 실제 LLM에 input되는 Node는 해당 문장 주변의 문장이 추가됩니다. window size에 따라 주변 문장의 수를 정할 수 있습니다.

    import nltk
    from llama_index.node_parser import SentenceWindowNodeParser
    
    node_parser = SentenceWindowNodeParser.from_defaults(
        # how many sentences on either side to capture
        window_size=3,
        # the metadata key that holds the window of surrounding sentences
        window_metadata_key="window",
        # the metadata key that holds the original sentence
        original_text_metadata_key="original_sentence",
    )

     

     

    # SemanticSplitterNodeParser

    의미론적 Chunking은 고정된 Chuk size를 적용하는 대신 의미론적 유사성을 고려하여 문장 사이의 중단점을 선택하여 분할 합니다. 

    from llama_index.node_parser import SemanticSplitterNodeParser
    from llama_index.embeddings import OpenAIEmbedding
    
    embed_model = OpenAIEmbedding()
    splitter = SemanticSplitterNodeParser(
        buffer_size=1, breakpoint_percentile_threshold=95, embed_model=embed_model
    )

     

     

     

    # Source 출처

    https://docs.llamaindex.ai/en/stable/index.html

Designed by Tistory.