Skip to main content

엔터프라이즈 RAG를 위한 범용 문서 전처리 파이프라인 (HWP/PDF/docx/xlsx 지원)

Project description

Ragkit_v1.0 (RAG Toolkit) - RAG 전처리 파이프라인

Python ONNX Runtime NumPy PaddleOCR Transformers License

Ragkit은 멀티포맷(HWP, PDF, DOCX, XLSX, 이미지 등)의 기업 문서를 RAG(Retrieval-Augmented Generation) 시스템 환경에 맞게 변환하는 범용 전처리 파이프라인 모노레포입니다.

💡 프로젝트 탄생 배경

RAG 시스템을 구축할 때 문서를 분류하고, 파싱 및 청킹(Chunking) 규칙을 설계하는 과정은 상당한 리소스를 요구합니다. Ragkit은 이 과정을 자동화하기 위해 설계되었습니다. 대량의 문서를 입력하면 다음 3단계 파이프라인을 거칩니다:

  1. 부서/보안등급별 분류
  2. 표(Table) 셀 병합 구조 분석을 포함한 파싱/청킹
  3. 임베딩 및 8-bit 스칼라 양자화

최종 산출물은 어떤 Vector DB(Milvus, ElasticSearch, Qdrant 등)에든 적재할 수 있도록 DB 비종속적(DB-Agnostic)인 형태(*.parquet)로 출력됩니다.


🛠️ 기술 스택

Ragkit은 무거운 딥러닝 프레임워크(PyTorch 등) 의존도를 낮추고, 하드웨어 자동 감지(GPU/CPU) 및 병렬 처리에 초점을 두었습니다.

  • 언어: Python 3.11
  • 코어 병렬 처리: concurrent.futures.ProcessPoolExecutor
  • 임베딩 추론: onnxruntime (하드웨어 자동 감지: GPU/CPU 가속 지원)
  • 문서 파싱: pdfplumber, python-docx, openpyxl, olefile (HWP 분석)
  • OCR (광학 문자 인식): paddleocr
  • 양자화 및 연산: numpy

💻 모듈 활용 및 고도화 가이드 (Usage & Extension)

본 모듈의 효율을 높이고 RAG 답변 퀄리티를 향상시키기 위한 가이드입니다.

1. 가장 효율적인 사용법 (실행 환경 최적화)

  • CPU 코어 최적화: 본 파이프라인은 ProcessPoolExecutor를 활용해 문서를 병렬 처리합니다. pipeline_config.iniMax_Workers 값을 사용 중인 PC의 실제 CPU 코어 수 - 1 로 설정할 때 빠르고 안정적으로 동작합니다.
  • 메모리 절약 원리: 출력된 벡터는 ScalarQuantizer를 통해 Float32 배열에서 8-bit(uint8) 정수로 양자화됩니다. 이를 통해 Vector DB 로드 시 메모리 사용량을 원본 대비 1/4(25%) 수준으로 관리할 수 있습니다.

2. 답변 퀄리티를 극대화하기 위한 확장 방식 (Extensibility)

  • 복잡한 표(Table) 처리: 본 모듈은 표의 병합 셀(Row/Col span) 구조를 파악해 마크다운(Markdown) 격자 형태로 추출합니다. 이 마크다운 구조를 온전히 이해하고 사칙연산을 수행할 수 있도록 추론 능력이 높은 최신 LLM(예: GPT-4o, Claude 3.5 Sonnet)과 결합할 때 표 데이터 검색 및 집계 능력이 향상됩니다.
  • 하이브리드 검색 (Hybrid Search) 권장: 현재 BAAI/bge-m3 모델 기반의 밀집 벡터(Dense Vector) 검색 방식을 취하고 있습니다. 하지만 특정 제품 코드, 사번, 고유명사를 100% 일치시켜 검색해야 할 경우 Dense 벡터만으로는 한계가 있습니다. Vector DB에 데이터를 적재할 때 BM25 등 희소 벡터(Sparse Vector) 기반의 키워드 매칭 검색을 추가로 연동(Hybrid Search)하는 것을 권장합니다.
  • 시각 정보(차트/그래프) 처리 고도화: 모듈은 PDF 내 차트나 그래프 영역을 감지하고 내부에 적힌 텍스트를 OCR로 추출하지만, 선의 추이나 막대의 높낮이 같은 시각적 형태 정보는 보존되지 않습니다. 필요에 따라 추출된 이미지 영역 좌표(bbox)를 활용해 VLM(Vision-Language Model) API에 전달, 이미지 전체를 서술형 텍스트로 요약하는 파이프라인을 별도로 덧붙이면 품질을 더욱 끌어올릴 수 있습니다.

🧩 3-Phase 파이프라인 데이터 흐름 및 출력 구조

사용자가 Ragkit에 대량의 문서를 입력하면, 파일들은 다음의 3단계를 거치며 LLM이 인식하기 적합한 형태로 가공됩니다.

[Phase 1] 파일 분류 모듈 (ragkit.classify)

  • 작동 원리: 원본 파일의 경로, 이름, 확장자 등을 분석하여 지정된 Taxonomy(보안등급, 부서, 지식유형 등)에 맞춰 분류합니다.
  • 초고속 델타 동기화 (Delta Sync):
    • 수백만 개의 문서를 매번 전체 스캔하지 않습니다. 최종 산출물인 .parquet 파일의 시스템 헤더(Schema Metadata)에 숨겨진 이전 작업의 글로벌 인덱스를 복원하여, 원본 폴더와 **0.1초 만에 3-Way Check (신규, 수정, 삭제, 유지)**를 수행합니다. 변경이 없는 파일은 완벽하게 스킵하여 파이프라인 구동 비용을 획기적으로 낮춥니다.
  • 가상 폴더 트리 구조 예시:
    data/virtual_index/
    ├── HR_Department/
    │   ├── Security_Level_S/
    │   │   ├── Structural_Data/
    │   │   │   └── index.json (원본 파일 경로 및 심볼릭 링크 정보 매핑)
    ├── Engineering/
    │   ├── Security_Level_A/
    │   │   ├── Unstructured_Data/
    │   │   │   └── index.json
    ...
    
  • 왜 이 방식을 택했는가?: 수백만 개의 거대한 원본 문서를 폴더별로 실제로 복사/이동시키면 심각한 I/O 병목과 디스크 용량 낭비가 발생합니다. 따라서 물리적 파일 이동 없이 가상의 디렉토리 트리와 심볼릭 링크(index.json) 만 생성하는 방식을 최선으로 채택했습니다.
  • 활용 가치: RAG 검색 시 "엔지니어링 부서의 A등급 보안 문서 안에서만 찾아줘"와 같이 카테고리 제한(Metadata Filtering)을 즉시 걸 수 있어 검색 속도와 보안성이 대폭 향상됩니다.

[Phase 2] 전처리 및 파싱/청킹 모듈 (ragkit.ingest)

  • 작동 원리: 가상 인덱스에 매핑된 문서(HWP, PDF, DOCX 등)를 열어 텍스트와 표(Table)를 추출합니다. 개인정보는 마스킹 처리되며 데이터가 의미 단위로 분할됩니다.

  • 동적 1차 페이지 보안 격상 (Security Override):

    • 일반 부서 폴더에 저장된 문서라도, 문서를 파싱하는 순간 **첫 페이지(또는 최상단 블록)의 내용(OCR/텍스트)**을 실시간으로 스캔합니다. 만약 "대외비", "보안", "confidential", "secret" 등의 텍스트가 도장이나 본문에 발견되면, 즉시 해당 문서의 메타데이터를 S(최고보안) 등급으로 강제 격상하여 보안 유출을 원천 차단합니다.
  • 텍스트 추출 및 청킹 방식:

    • 기존의 '글자 수 기반 분할(예: 1000자씩 자르기)' 대신 "의미론적 문단(Semantic Paragraph)" 단위로 데이터를 나눕니다.
      • 판단 기준 (속도 저하 없는 Rule-Based 기본 가동): 모든 문서를 임베딩 모델에 태우면 심각한 속도 저하가 발생합니다. 따라서 Ragkit은 기본적으로 임베딩 모델을 사용하지 않습니다. 대신, 문서의 구조적 특징(예: '제N조', '제N항' 등의 법률/규정 조항 패턴이나 마침표, 줄바꿈 등 문장 경계)을 정규식으로 감지하여 1차 분할합니다.
      • 옵션 기능 (임베딩 기반 코사인 유사도 분할): 만약 사용자가 처리 속도보다 '극한의 문맥 절단 방지'를 원할 경우, 파이프라인에 임베딩 모델을 주입(Opt-in)할 수 있습니다. 이 기능을 켜면 문장 간의 코사인 유사도(Cosine Similarity)를 계산하여 주제가 급변하는 구간에서만 청크를 자르게 됩니다.
    • 추출된 텍스트에는 원본의 페이지 번호(혹은 구역 정보)가 메타데이터에 기록되며, TF-IDF 기반의 고유 키워드(anchor_tags)가 자동 부여되어 검색 정확도를 높입니다.
  • 출력 결과 (JSON 추출 예시):

    [예시 1] 일반 텍스트 문단 추출

    [
      {
        "chunk_id": "doc_001_chunk_4",
        "text": "전자사업부의 2024년 핵심 목표는 AI 기반 신제품 라인업 확장을 통한 매출 200억 달성입니다. 이를 위해 상반기 내 R&D 인력을 30% 확충할 계획입니다.",
        "metadata": {
          "source": "2024년_사업계획서.hwp",
          "page": "Section 2",
          "department": "Engineering",
          "anchor_tags": ["전자사업부", "매출", "목표", "R&D"]
        }
      }
    ]
    
  • 표(Table) 추출 방식:

    • 표는 임의로 나누지 않고 표 전체를 하나의 독립된 마크다운 청크로 보존합니다.
    • 병합된 셀(Merged Cells) 처리 시, 값을 무작정 여러 칸에 복사해 넣으면 LLM이 중복 합산 오류(환각)를 일으킬 수 있습니다. 이를 방지하기 위해 덮어씌워진 칸은 비워두고 원본 데이터를 가리키는 앵커(Anchor) 기반 마크다운 인코딩 기법을 적용하여 표의 구조를 사실 기반으로 유지합니다.
  • 출력 결과 (JSON 추출 예시):

    [예시 2] 표(Table) 추출 (마크다운 격자 보존)

    [
      {
        "chunk_id": "doc_001_chunk_5",
        "text": "| 구분 | 2023년 매출 | 2024년 목표 |\n|:---|:---|:---|\n| 전자사업부 | 150억 | 200억 |",
        "metadata": {
          "source": "2024년_사업계획서.hwp",
          "page": "Section 2",
          "department": "Engineering",
          "anchor_tags": ["매출", "전자사업부", "목표"]
        }
      }
    ]
    
  • 잘못된 청킹 방법 및 주의사항:

    • 엑셀이나 복잡한 표를 단순히 쉼표(CSV)나 평문 텍스트로 나열하면 좌표(행/열) 정보가 사라져 LLM이 문맥을 추론하기 어려워집니다.
    • 표가 너무 커서 불가피하게 청킹해야 할 때는, 상단의 '헤더(Header)'를 매 청크마다 강제 주입(Context Injection)해야 구조적 손실을 막을 수 있습니다.
  • Ragkit 모듈의 사용 방식 (LLM 연동): 추출된 JSON의 text 필드는 구조화된 마크다운 형태입니다. 이 텍스트를 그대로 LLM(GPT-4o, Claude 등)의 프롬프트에 제공하고 데이터 분석을 요청하면 됩니다.

  • 향후 고도화 방안: 추출된 차트 이미지나 수식의 영역 좌표를 활용해 시각 모델(Vision-Language Model) API로 내용을 분석하고, 서술형 텍스트로 보강하는 파이프라인을 추가할 수 있습니다.

[Phase 3] 임베딩 & 양자화 모듈 (ragkit.search)

  • 작동 원리: Phase 2의 JSON 청크를 ONNX 추론 엔진(BAAI/bge-m3 등)으로 고차원 실수 벡터(Float32)로 임베딩한 후, 이를 (X - min) * scale 공식을 통해 8-bit 스칼라 정수(uint8, 0~255) 로 압축(양자화)합니다. PC 환경에 따라 GPU(CUDA 등)를 자동 감지하여 가속합니다.
  • 데이터 보존 여부 (삭제되는 부분이 있는가?):
    • 결론부터 말씀드리면, 앞서 추출된 텍스트와 표, 메타데이터는 단 1글자의 삭제나 변형 없이 100% 원본 그대로 보존됩니다.
    • 양자화(압축)는 오직 기계가 읽는 '벡터 숫자 배열' 부분에만 적용되며, 사람이 읽고 LLM이 읽어야 할 text와 JSON 정보는 그대로 유지되어 최종 파일에 담깁니다.
  • 왜 이 양자화 방식을 택했는가?:
    • 수천만 건의 문서 벡터를 32비트 실수형 그대로 Vector DB에 올리면 수백 GB의 막대한 RAM이 필요하여 서버 유지비가 폭증합니다.
    • 8-bit 스칼라 양자화는 Binarization(1-bit)이나 PQ 방식보다 훨씬 속도가 빠르면서도 검색 정확도(Recall) 손실률이 1~2% 내외로 극히 적어 가장 실무적이고 가성비 높은 최선의 방식입니다.
  • 잘못된 양자화 방법 및 주의사항:
    • 용량을 더 줄이겠다고 1-bit나 4-bit 등 극단적인 양자화를 수행하면, 세밀한 도메인 전문 용어들 간의 벡터 거리(유사도) 분별력이 완전히 상실되어 엉뚱한 문서를 검색해 오는 치명적인 오류가 발생합니다.
    • 최종 산출물을 Vector DB에 넣을 때, 해당 DB(예: Milvus)가 uint8 형태의 거리 계산을 네이티브로 지원하는지 반드시 확인하고 Collection을 생성해야 합니다.
  • 최종 산출물 활용 및 물리적 격리 (Segregation):
    • Phase 1에서 감지된 삭제/수정 파일의 과거 청크 데이터는 자동 가비지 컬렉션(GC) 되어 깔끔히 제거됩니다.
    • 보안 강화를 위해 전체 데이터는 하나의 파일이 아니라, ragkit_{부서명}_{보안등급}.parquet 형태로 물리적으로 분할되어 저장됩니다. (예: ragkit_인사본부_S.parquet)
    • Python(pandas)으로 읽어서 Vector DB에 로드할 때 Collection을 분리하기 쉬워져, RAG 시스템의 권한 제어 체계를 극도로 단순화할 수 있습니다.
    • 고도화: 검색 품질을 높이려면, 1차 검색은 양자화된 벡터 DB에서 빠르게 100개를 뽑아오고(Top 100), 2차로 메모리에 보관된 Float32 벡터를 이용해 Cross-Encoder로 Re-ranking(재정렬)하는 '2-Stage 아키텍처'를 적용해 볼 수 있습니다.

🏃 시작하기 (CLI 기반 실행)

이제 Ragkit은 패키지 형태로 배포되므로, 어느 디렉토리에서든 ragkit 명령어를 사용하여 손쉽게 파이프라인을 구축할 수 있습니다.

1. 패키지 설치

pip install ragkit
# 필요 모듈에 따라 pip install "ragkit[all]" 등으로 설치 가능

2. 프로젝트 초기화 (초기 설정 파일 생성)

작업을 진행할 빈 폴더를 만들고, 해당 폴더에서 아래 명령어를 실행하여 기본 설정 파일 템플릿(pipeline_config.ini, security_rules.yml)을 생성합니다.

ragkit init

3. pipeline_config.ini 설정하기

현재 폴더에 생성된 설정 파일을 열어 환경에 맞게 수정합니다.

[PipelineMode]
Full_Auto = True

[Modules]
Run_Classify = True
Run_Ingest = True
Run_Embed = True

[Directories]
# 원본 문서가 위치한 폴더 (여러 네트워크 드라이브 등 다중 경로 지원, 쉼표로 구분)
# 예: Raw_Data_Dir = data/raw_docs, Z:/HR_Docs, X:/Eng_Docs
Raw_Data_Dir = data/raw_docs

# 새롭게 생성될 최종 결과물(.parquet) 저장 폴더
Final_Out_Dir = data/final_output

# 델타 동기화(Delta Sync)를 위해 과거에 작업했던 파케이(DB) 파일들이 존재하는 폴더 경로
# 최초 실행이거나, 과거 작업물을 무시하고 처음부터 싹 다 다시 밀고 싶다면 False 로 설정합니다.
Previous_DB_Dir = False

[Settings]
Max_Workers = 4

4. 파이프라인 단일 명령어 실행

이제 설정이 완료되었다면 아래 명령어 한 줄로 분류, 전처리, 임베딩/양자화 파이프라인을 구동합니다!

ragkit run

💡 각 모듈별 상세 가이드

  • src/ragkit/classify/README.md
  • src/ragkit/ingest/README.md
  • src/ragkit/search/README.md

⚠️ 한계점 (Limitations)

이 파이프라인은 다양한 환경과 범용적 처리에 초점을 맞추어 개발되었으나, 다음과 같은 기술적 한계점을 가집니다.

  1. 복잡하거나 훼손된 표의 구조 오인식
    • 본 모듈은 TableRecognitionPipelineV2를 통해 표 구조와 병합 셀을 추적하여 복원합니다. 그러나 표의 테두리 선이 아예 없거나, 스캔 상태가 불량한 이미지 PDF의 경우 열(Column)/행(Row) 구조가 정상적으로 인식되지 않아 셀 구조가 뭉개질 수 있습니다.
  2. 차트 및 시각 정보의 유실
    • PDF 내의 그래프, 차트 영역을 감지하고 내부 텍스트(축 이름, 범례 등)를 OCR로 추출하지만, 선 그래프의 추이나 막대의 형태적 비례 같은 '시각적 형태 정보'는 현재의 텍스트 RAG 구조상 온전히 보존되지 않습니다.
  3. 고유명사 및 식별 코드 검색의 약점
    • 구현된 밀집 벡터(Dense Vector) 기반 검색은 텍스트의 '의미적 유사도'를 판단하는 데는 뛰어나지만, 숫자와 영문이 복잡하게 섞인 특정 부품 코드나 생소한 고유 식별자를 단어 그대로(Exact Match) 찾아내는 능력이 부족합니다. 이를 보완하려면 Vector DB 적용 시 키워드 기반 하이브리드 검색을 별도 구성해야 합니다.
  4. 환경 종속성 및 파싱 누락
    • 사내 고유 폰트, 암호화된 파일, 변칙적인 템플릿 구조를 가진 문서는 파싱 과정에서 에러가 발생하거나 특정 텍스트 블록이 누락될 수 있습니다.

이슈 제기 및 버그 리포트 사용 중 발생하는 파싱 오류 및 충돌 내역은 아래 메일로 환경 정보와 로그를 포함해 보내주시기 바랍니다. 📧 Email: support@ragkit-example.com


📜 라이선스 (License)

이 프로젝트는 Apache License 2.0을 따릅니다. 자세한 사항은 LICENSE.md 파일을 참고하세요.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ragkit_core-0.1.0.tar.gz (88.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ragkit_core-0.1.0-py3-none-any.whl (107.5 kB view details)

Uploaded Python 3

File details

Details for the file ragkit_core-0.1.0.tar.gz.

File metadata

  • Download URL: ragkit_core-0.1.0.tar.gz
  • Upload date:
  • Size: 88.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for ragkit_core-0.1.0.tar.gz
Algorithm Hash digest
SHA256 827e79736c16629f3a7b0eb45f338ecfc37e6359343d8a0382264c87f2de4791
MD5 8a67ee213c971c5186084104215652ec
BLAKE2b-256 a226d5ec25e58b1d816d0964b7bc48a44c13713592dc46da76cb1b0416d86d53

See more details on using hashes here.

File details

Details for the file ragkit_core-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ragkit_core-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 107.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for ragkit_core-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a72b2a532b534031d179f2770e3edc213a5e16d344e97763412074db2aa46cd
MD5 1f09dcb77948427b473b70b03b10de24
BLAKE2b-256 944483597032c0dd79acaee5b9830b5846a09acbfe2db43de01ed41620076dda

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page