Home > EulerWeave > Tutorials > 튜토리얼 5: 추출기 플러그인 개발

튜토리얼 5: 추출기 플러그인 개발

eulerweave는 Python entry points 기반의 플러그인 시스템을 사용합니다. 이 튜토리얼에서는 내장 추출기의 구조를 이해하고, 직접 추출기 플러그인을 만드는 방법을 설명합니다.

사전 요구 사항: 튜토리얼 1: 빠른 시작의 기본 워크플로에 익숙해야 합니다.


내장 추출기 현황

eulerweave v0.1에는 6개의 내장 추출기가 포함되어 있습니다:

eulerweave plugins list
Extractors:
  txt      eulerweave.core.io.local_files:TxtExtractor          [.txt]
  jsonl    eulerweave.core.io.jsonl:JsonlExtractor               [.jsonl]
  csv      eulerweave.core.io.csv_extractor:CsvExtractor         [.csv]
  parquet  eulerweave.core.io.parquet_extractor:ParquetExtractor [.parquet]
  html     eulerweave.core.io.html_extractor:HtmlExtractor       [.html]
  pdf      eulerweave.core.io.pdf_extractor:PdfExtractor         [.pdf]

각 추출기는 pyproject.tomleulerweave.extractors entry point에 등록됩니다:

[project.entry-points."eulerweave.extractors"]
txt = "eulerweave.core.io.local_files:TxtExtractor"
jsonl = "eulerweave.core.io.jsonl:JsonlExtractor"
csv = "eulerweave.core.io.csv_extractor:CsvExtractor"
parquet = "eulerweave.core.io.parquet_extractor:ParquetExtractor"
html = "eulerweave.core.io.html_extractor:HtmlExtractor"
pdf = "eulerweave.core.io.pdf_extractor:PdfExtractor"

내장 추출기 옵션 (options_schema)

일부 추출기는 options 필드를 통해 세부 설정을 받습니다. 컴파일러는 각 추출기의 options_schema()를 호출하여 옵션을 검증합니다.

CSV 추출기 옵션

inputs:
  - type: csv
    uri: data/train.csv
    options:
      text_column: content       # 텍스트로 사용할 컬럼
      delimiter: "\t"            # 구분자 (기본: ",")

Parquet 추출기 옵션

inputs:
  - type: parquet
    uri: data/train.parquet
    options:
      text_column: text

PDF 추출기 옵션

inputs:
  - type: pdf
    uri: data/paper.pdf
    options:
      strategy: auto             # auto, text, ocr
      page_range: "1-10"         # 페이지 범위

잘못된 옵션 예시

# 에러: additionalProperties 위반
inputs:
  - type: pdf
    uri: data/paper.pdf
    options:
      bad_key: true              # ← 허용되지 않는 키
Compilation error: Input option validation failed for 'pdf'
  Additional properties not allowed: 'bad_key'
# 에러: strategy 열거형 위반
inputs:
  - type: pdf
    uri: data/paper.pdf
    options:
      strategy: magic            # ← auto, text, ocr 중 하나여야 함
Compilation error: Input option validation failed for 'pdf'
  'magic' is not one of ['auto', 'text', 'ocr']

ExtractorInterface 이해하기

모든 추출기 플러그인은 ExtractorInterface를 구현해야 합니다:

from eulerweave.registry.loader import ExtractorInterface
from eulerweave.core.record import CanonicalRecord


class ExtractorInterface:
    """모든 추출기가 구현해야 하는 프로토콜."""

    def extract(self, uri: str, options: dict | None = None) -> Iterator[CanonicalRecord]:
        """URI에서 데이터를 읽어 CanonicalRecord를 yield."""
        ...

    def options_schema(self) -> dict | None:
        """JSON Schema dict를 반환. 옵션이 없으면 None."""
        return None

    def supported_schemes(self) -> list[str]:
        """지원하는 URI 스킴 목록. 기본: ["file"]."""
        return ["file"]

    def probe(self, uri: str) -> bool:
        """URI를 처리할 수 있는지 빠르게 확인. 기본: True."""
        return True

핵심 포인트:


커스텀 추출기 만들기: 예제

패키지 구조

eulerweave-xlsx-extractor/
  pyproject.toml
  eulerweave_xlsx_extractor/
    __init__.py
    extractor.py
  tests/
    test_extractor.py

extractor.py

"""XLSX extractor plugin for eulerweave."""
from __future__ import annotations

import hashlib
from pathlib import Path
from typing import Iterator

from eulerweave.core.record import CanonicalRecord


class XlsxExtractor:
    """Excel 파일에서 텍스트를 추출하는 플러그인."""

    def extract(
        self,
        uri: str,
        options: dict | None = None,
    ) -> Iterator[CanonicalRecord]:
        import openpyxl

        opts = options or {}
        text_column = opts.get("text_column", "A")
        sheet_name = opts.get("sheet_name", None)

        path = Path(uri)
        wb = openpyxl.load_workbook(str(path), read_only=True)
        ws = wb[sheet_name] if sheet_name else wb.active

        for i, row in enumerate(ws.iter_rows(min_row=2, values_only=False)):
            cell_value = str(row[ord(text_column) - ord("A")].value or "")
            if not cell_value.strip():
                continue

            rec_id = hashlib.sha256(
                f"{path.name}:{i}".encode()
            ).hexdigest()[:16]

            yield CanonicalRecord(
                id=rec_id,
                text=cell_value.strip(),
                metadata={"row": i + 2, "sheet": ws.title},
                source_uri=str(path),
                source_type="xlsx",
                extracted_by="XlsxExtractor",
            )

        wb.close()

    def options_schema(self) -> dict:
        return {
            "type": "object",
            "properties": {
                "text_column": {
                    "type": "string",
                    "default": "A",
                    "description": "텍스트가 있는 컬럼 문자 (A, B, C, ...)",
                },
                "sheet_name": {
                    "type": "string",
                    "description": "시트 이름 (기본: 활성 시트)",
                },
            },
            "additionalProperties": False,
        }

pyproject.toml

[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "eulerweave-xlsx-extractor"
version = "0.1.0"
dependencies = ["eulerweave>=0.1.0", "openpyxl>=3.1"]

[project.entry-points."eulerweave.extractors"]
xlsx = "eulerweave_xlsx_extractor.extractor:XlsxExtractor"

설치 및 확인

pip install -e .
eulerweave plugins list     # xlsx가 표시되어야 함
eulerweave plugins doctor   # ✓ xlsx 확인

매니페스트에서 사용

inputs:
  - type: xlsx
    uri: data/training_data.xlsx
    options:
      text_column: B
      sheet_name: Sheet1

플러그인 진단 (plugins doctor)

eulerweave plugins doctor
[eulerweave] Plugin diagnostics

Extractors:
  ✓ txt      — eulerweave.core.io.local_files:TxtExtractor
  ✓ jsonl    — eulerweave.core.io.jsonl:JsonlExtractor
  ✓ csv      — eulerweave.core.io.csv_extractor:CsvExtractor
  ✓ parquet  — eulerweave.core.io.parquet_extractor:ParquetExtractor
  ✓ html     — eulerweave.core.io.html_extractor:HtmlExtractor
  ✓ pdf      — eulerweave.core.io.pdf_extractor:PdfExtractor

No issues found.

로드 실패 시:

  ✗ xlsx — my_package.extractor:XlsxExtractor
    [ImportError: No module named 'openpyxl']

해결: pip install openpyxl


Entry Point 그룹 목록

eulerweave는 4개의 entry point 그룹을 지원합니다:

그룹 용도 예시
eulerweave.extractors 데이터 추출기 txt, jsonl, pdf
eulerweave.blocks 커스텀 파이프라인 블록 외부 전처리 블록
eulerweave.metrics 커스텀 메트릭 블록 도메인 특화 메트릭
eulerweave.providers.llm LLM 프로바이더 커스텀 API 연동

플러그인 체크리스트

  1. extract(self, uri, options=None)Iterator[CanonicalRecord] 구현
  2. options_schema() → JSON Schema dict 반환 (additionalProperties: false 권장)
  3. pyproject.tomleulerweave.extractors entry point에 등록
  4. pip install -e . 실행
  5. eulerweave plugins list로 확인
  6. eulerweave plugins doctor로 진단
  7. 테스트 작성 (기본 추출, 빈 파일, 옵션 검증)

다음 단계

← Prev Back to List Next →