Unstructured

Unstructured (Unstructured)

PDF나 워드 문서처럼 정형화되어 있지 않은 텍스트 문서는 그대로 두면 머신러닝 작업에 쓰기 어려워요. Unstructured는 그런 비정형 문서를 사전 처리하고 구조화해 주는 라이브러리인데, 이 파이프라인의 목적지(ingestion destination)로 Qdrant를 사용할 수 있어요. 문서를 정제하고 청크로 자른 뒤, 벡터로 임베딩해서 바로 Qdrant에 쌓는 흐름을 만들 수 있죠.

출처: Qdrant 공식 문서 — unstructured

설정 (Setup)

qdrant extra를 포함해서 Unstructured를 설치해요.

pip install "unstructured-ingest[qdrant]"

사용법 (Usage)

사용 목적에 따라 명령줄(CLI)로 쓸 수도 있고, 애플리케이션 코드 안에서 직접 호출할 수도 있어요.

CLI

unstructured-ingest \
  local \
  --input-path $LOCAL_FILE_INPUT_DIR \
  --chunking-strategy by_title \
  --embedding-provider huggingface \
  --partition-by-api \
  --api-key $UNSTRUCTURED_API_KEY \
  --partition-endpoint $UNSTRUCTURED_API_URL \
  --additional-partition-args="{\"split_pdf_page\":\"true\", \"split_pdf_allow_failed\":\"true\", \"split_pdf_concurrency_level\": 15}" \
  qdrant-cloud \
  --url $QDRANT_URL \
  --api-key $QDRANT_API_KEY \
  --collection-name $QDRANT_COLLECTION \
  --batch-size 50 \
  --num-processes 1

CLI가 받을 수 있는 전체 옵션 목록은 unstructured-ingest <upstream connector> qdrant --help로 확인할 수 있어요. 여기서는 로컬 파일을 입력으로 받아 by_title 전략으로 청크를 나누고, huggingface 임베딩으로 변환한 뒤 qdrant-cloud 커넥터로 Qdrant 클라우드에 저장하는 구성이에요.

프로그래매틱 사용 (Programmatic usage)

파이썬 코드에서는 Pipeline을 구성해서 같은 작업을 수행할 수 있어요. 각 단계의 설정 객체를 from_configs에 넘기는 방식이에요.

import os
from unstructured_ingest.pipeline.pipeline import Pipeline
from unstructured_ingest.interfaces import ProcessorConfig
from unstructured_ingest.processes.connectors.local import (
    LocalIndexerConfig, LocalDownloaderConfig, LocalConnectionConfig
)
from unstructured_ingest.processes.partitioner import PartitionerConfig
from unstructured_ingest.processes.chunker import ChunkerConfig
from unstructured_ingest.processes.embedder import EmbedderConfig
from unstructured_ingest.processes.connectors.qdrant.cloud import (
    CloudQdrantConnectionConfig, CloudQdrantAccessConfig,
    CloudQdrantUploadStagerConfig, CloudQdrantUploaderConfig
)

if __name__ == "__main__":
    Pipeline.from_configs(
        context=ProcessorConfig(),
        indexer_config=LocalIndexerConfig(input_path=os.getenv("LOCAL_FILE_INPUT_DIR")),
        downloader_config=LocalDownloaderConfig(),
        source_connection_config=LocalConnectionConfig(),
        partitioner_config=PartitionerConfig(
            partition_by_api=True,
            api_key=os.getenv("UNSTRUCTURED_API_KEY"),
            partition_endpoint=os.getenv("UNSTRUCTURED_API_URL"),
            additional_partition_args={
                "split_pdf_page": True,
                "split_pdf_allow_failed": True,
                "split_pdf_concurrency_level": 15
            }
        ),
        chunker_config=ChunkerConfig(chunking_strategy="by_title"),
        embedder_config=EmbedderConfig(embedding_provider="huggingface"),
        destination_connection_config=CloudQdrantConnectionConfig(
            access_config=CloudQdrantAccessConfig(api_key=os.getenv("QDRANT_API_KEY")),
            url=os.getenv("QDRANT_URL")
        ),
        stager_config=CloudQdrantUploadStagerConfig(),
        uploader_config=CloudQdrantUploaderConfig(
            collection_name=os.getenv("QDRANT_COLLECTION"),
            batch_size=50,
            num_processes=1
        )
    ).run()

흐름을 간단히 정리하면 이래요. partitioner가 문서를 분할(partitioning)하고, chunkerby_title 전략으로 청크를 만들고, embedder가 huggingface 모델로 임베딩한 뒤, 마지막에 CloudQdrantUploaderConfig가 배치 단위로 Qdrant 클라우드에 업로드해요. API 키 같은 민감한 값은 코드에 하드코딩하지 말고 환경 변수로 주입하는 게 좋아요.

더 알아보기 (Learn more)