현재 모두의 연구소에서 진행하고 있는 스터디로 제가 퍼실리로 활동을 하고 있습니다. 이 글을 쓰게 된 이유는 주간 공부한 것을 정리하고 스터디에서 나온 insight를 정리할 겸 글을 정리해보려고 합니다. 저희 스터디 같은 경우는 하브루타 방식의 스터디로 와서 공부하는 방식입니다. 1~3주 차까지는 domain 선정 후 기능 아키텍처 정의를 하고 RFP처럼 문서를 작성하고 PT 발표를 3주 차에 진행하고 4주 차부터는 구현을 10주 차까지 하고 개발 테스트 검증 하나의 프로젝트처럼 해볼 예정입니다. 그 과정에 있어서 매주 한분씩 'RAG' 관련 PT 발표를 진행 예정이고, '이상윤'님 께서 금주 에는 파일처리에 관련하여 정리해서 PT 발표해 주셨습니다.
처음에 상윤 님이 문서파일 관련 아이디어를 톡을 주셨을 때 pdf 관련 이슈가 많다 보니 정리해서 주시나 보다 생각했는데, 너무너무! 놀랍게 많은 내용과 범용적인 문서단위에서 어떻게 로드하고, 청크 하고 방법론에 대해 자세히 설명을 해주셨습니다. 이를 한번 정리해 보겠습니다. 우선 제 블로그나 이전 글에서 RAG 관련설명이나, 간단한 이론은 스킵하겠습니다.
문서처리의 중요성
RAG는 데이터 품질이 중요하고, 문서파일로드는 매우 많고 다양한 형태로 많은 개발 r&d가 이루어지고 있다. 현재 우리는 불러온 문서에 대해 어떤 식으로 단락을 나눌지 중요하다 볼 수 있다.
LangChain에서 현재 호환하고 있는 Text Splitters이다.
이름분할 | 기준 | 메타데이터 | 추가설명 |
Recursive | 사용자 정의 문자 목록 | 텍스트를 재귀적으로 분할합니다. 재귀적으로 텍스트를 분할하는 것은 관련된 텍스트 조각들을 서로 가깝게 유지하는 목적을 가집니다. 텍스트 분할을 시작할 때 권장되는 방법입니다. | |
HTML | HTML 특정 문자 | HTML 특정 문자를 기준으로 텍스트를 분할합니다. | |
Markdown | 마크다운 특정 문자 | 마크다운 특정 문자를 기준으로 텍스트를 분할합니다. | |
Code | 코드 (Python, JS) 특정 문자 | 코딩 언어에 특정한 문자를 기준으로 텍스트를 분할합니다. 15개의 다른 언어를 선택할 수 있습니다. | |
Token | 토큰 | 토큰을 기준으로 텍스트를 분할합니다. 토큰을 측정하는 몇 가지 방법이 있습니다. | |
Character | 사용자 정의 문자 | 사용자 정의 문자를 기준으로 텍스트를 분할합니다. 비교적 간단한 방법 중 하나입니다. |
발표에서는 5개의 예제를 다뤄주셨는데, 제일 많이 쓰고 있는 Chunk 방법들이다.
• CharacterTextSplitter
• RecursiveCharacterTextSplitter
• TokenTextSplitter
• HuggingFace
• SemanticChunker(experimental)
청크방법에 따라 나뉘는 기준이 달라질 수 있다. 여기에 RAG에서 중요한 임베딩을 하기 때문에 Chunk 단위에서 뭔가 원활하게 분리를 하지 않았더라면 임베딩을 했을 때 과연 벡터기반의 Space에서 유연하게 표현되기가 힘들 것이다.
위 예제처럼, lexical search 기반으로 Retrieval을 해오게 되면 단어 수 기반으로 검색엔진에서 가져오는 영향이 있어서 Sementic Search를 같이 섞어서 사용하기도 하는 것이고, 예로 들어 Chunk 개수가 1개만 레트리버가 된다면 Answer 처럼 절대 답변을 할 수 없거나 핧루시네이션을 만들어 낼것이다. 여기서도 리트리버 개수를 몇 개를 주냐도 RAG 테크닉이 될 수 있을 것 같다. 이 예시를 예로 chunk를 오버랩해서 사용하는 경우가 일반적이다. 청킹 오버를 주면, 문맥을 일정하게 잘랐을떄 앞 앞에 내용이 일부 같이 있기 때문에 문맥적으로 이해를 할 수 있기 때문이다. 그러나 때때론 오버랩 때문에 오히려 Chunking 이 이상하게 되거나 낭비가 되거나 노이즈가 발생하기도 하는 문제가 있긴 하다. 이래서 RAG가 어렵다.
정말 다양한 청킹방법이 존재한다. 일반적으로 그냥 자르는 방법도 있고, 자르고 그 Chunk를 LLM을 통해서 해결하기 위해 Summarization을 해서 쓰는 경우도 있다. Langchain의 예로 QA Retrieval에서 Chain_type 파라미터를 본 적 있을 것이다. Stuff, map_reduce를 선택해서 쓰는데 Stuff는 청크 된 내용을 전부, map_reduce는 요약한 후 진행하는 경우인데 각 장단점이 있을 것 같다. 근데 일반적으로는 Stuff 원본내용을 살려서 레트리버를 하려고 한다.
결국 문서 하나 로드하고, 청크 하는데 뭐가 이리 많아 할 수 있지만, 나는 이 과정이 뒤에 단계보다 중요하다고 생각한다. garbage in garbage out 인 것처럼 말이다. 링크드인 정보의 바다 덕분에 Google Vertax AI에서도 Chunk 관련 OCR과 함께 지원해 주는 docs를 발견했다. 코드도 본 것 같은데 잠결에서 봐서 그런지 퍼오기를 안 했다🥲 시간 날 때 쭉 둘러봐야겠다.
현업 사례 - 삼성 SDS
사내의 수천 개의 데이터를 RAG 해봤는데 왜 결과가 안 좋나 분석을 해보고 추적을 해보니 Document 로더 및 청크에서부터 문제가 있었고 이문제를 해결하기 위해 인력자체가 RAG를 잘하고, 문단에 최적화되게끔 수작업으로 하니 잘 찾더라 관련된 내용이었다. 결국 이걸 딥러닝을 활용해 해결할 수 없을까가 뜨거운 감자가 될 것 같다.
데이터 & 문서의 유형 (PDF)
Native PDF - 글씨, 이미지가 객체로 인식이 되어서 스크롤이 되는 형태
Image PDF - 글씨 이미지가 하나의 이미의 형태
두 가지의 형태로 있었다는 사실을 처음 알았다 Arvix 논문을 항상 볼 때 네이티브였던 것 같은데 되게 신기했다. image PDF는 어쩔 수 없이 OCR을 활용해야 하는 부분이 있을 듯하다.
바이너리 vs XML
바이너리 파일 같은 경우 왼쪽처럼 많이 깨지는 모습을 볼 수 있는데 특정 Viewer와 같은 파일로 볼 수 있다. xml 같은 경우는 글자마다의 요소, 위치, 폰트, 색깔등 다양한 메타데이터가 있다. 아무래도 컴퓨터 언어 친화적이게 xml 이 조금 더언어모델에는 유리하지 않을까 생각이 들었고 metadata처럼 다양한 힌트들이 있어서, 레트리버를 한다면 좋지 않을까 생각이 들지만, 아마 Tag 분리와 다양한 전처리를 고려도 해야 할 것이고, 토큰이 조금 더 소모되지 않을까 생각된다.
상윤 님이 너무 정리를 잘해주셔서 이해하기가 쉬웠다.. 👍
문서 분석 방법
1. 기계식 추론(heuristic)
- 설명
- 무한대에 가까운 경우의 수를 계산하는 방식
- 시간이 오래 들릴수록 품질이 좋음
- SolidDocument가 접근하는 방식 (대략 20년 개발 기간 보유)
- 품질 수준이 높을수록 개발 공수가 크게 늘어남
- 새로운 요구사항에 대응하기 어려움
- 개발 항목
- PDF에서 RAW 데이터(글자, 이미지) 읽기 : PDF 담당자
- 개발 필요 항목 (오픈소스 활용 가능 - 품질 낮음)
- PDF 파일 내 텍스트 추출 및 추출
- PDF 파일 내 테이블 추출 및 추출
- PDF 파일 내 워터마크/헤더/푸터 추출 및 추출
- 유의 사항
- 단기간 내 고품질 데이터 추출은 어려움
- 많은 인력을 투입하여 알고리즘 개발 및 수정해야 하는 경우가 발생
- 현재 한계의 보유 기술은 없음
-> 규칙과 패턴에 의한 하드코딩..
2. 인공지능 추론
- 설명
- 인공지능으로 문서의 구조를 추론하는 방식
- AWS, Microsoft, Google, Adobe 등 빅테크 기업들이 접근하는 방식
- 짧은 시간 내 기계식 추론의 기술력을 따라잡을 수 있음
- 현재 기준으로 빠른 시간 안에 적은 개발 공수로 개발 가능
- 기계식 추론보다 유연하게 새로운 요구에 대응 가능
- 다양한 입력뿐만 아니라, 새로운 형태의 데이터 추론도 확장 가능
- LLM 용량이 크고, 속도가 느리다는 단점
- AI 분야가 빠르게 발전하고 있어 조만간 해결 가능할 것으로 예측
- 개발 항목
- PDF에서 RAW 데이터(글자, 이미지) 읽기 : PDF 담당자
- PDF 파일 내 텍스트 추출 및 추출 : AI 기술 필요 (예: LayoutLM)
- PDF 파일 내 테이블 추출 및 추출 : AI 기술 필요 (예: table-transformer)
- PDF 파일 내 워터마크/헤더/푸터 추출 및 추출 : AI 기술 필요 (예: LayoutLM)
- 다국어 OCR : OCR 기술 필요 (tesseract, DocTr)
- 언어 판단 AI : OCR 기술 필요 (fastText)
- 문서 내 정보 추출 속도 개선 : AI를 위한 고성능 그래픽카드 필요
- 순서 인지 및 정보 추출 가능하도록 개선 : AI 기술 필요 (AI 리서치 필요)
- 외곽 테두리가 있는 테이블의 경우 Detect를 못하는 경우가 있음 : AI 기술 필요 (예: table-transformer)
- 유의 사항
- 단기간 내 오픈된 모델을 활용하여 구축 가능
- 다만, 오픈된 모델은 빅테크 상용화 모델에 비해 품질이 떨어짐
내가 했던 방법도 어떻게 보면 인공지능 추론이라 할 수 있지만, 코드 단에 라이브러리 형태로 배포되려는 노력들이 많이 보인다. pymupdf와 같은 기업들 그리고 위에서 Google Vertax와 같이 다양하게 LLM , OCR 다양한 기술을 활용해서 더 효과적인 로더를 해서 추론하는 것이다. 근데 아직은 시기상조 같기도... 좋은 모델이 나오면 쓰자.. 괜히 대용량 처리하다가 오히려 더 안 좋은 노이즈가 들어갈 것 같다.
국내 기업 로민에서 위와 같은 설루션을 판매하고 있다. html 형태로 파싱을 다해주는 듯하다. 되게 이번 스터디를 하고 나서 Document 단에서 많은 노력과 돈들이 쓰이고 있다는 걸 알게 되었던 것 같다. 특히 우리나라 같은 경우 병원, 공기업 관련해서 문서들이 표도 문제고 이미지도 문제고 고질적인 문제점들이 많다. 이걸 해결하기 위해 많은 기업들이 노력을 하고 있다.
객체 탐지
이미지처럼 문서의 헤더, 본문, 테이블, 이미지 등을 Detection 해서 html 형태로 표현하는 것
출처 - 업스테이지(https://www.content.upstage.ai/blog/business/introducing-layout-analysis)
순서(문맥) 탐지
먼저 객체 탐지 후 탐지한 객체의 순서를 판단하는 기술이다.
(예를 들어 다단의 경우, 순서 탐지를 하지 못할 경우, Contents의 순서 엉망이 됨)
출처 - 업스테이지(https://www.content.upstage.ai/blog/business/introducing-layout-analysis)
계층(Level) 탐지
특정 객체가 다른 객체의 하위 객체인지 관계를 판단하는 기술이다. 대문단 2에 들어가는 하위의 문단의 내용들이 맞는지 판단하는 기술이라 할 수 있다.
표 탐지
표를 인식하고,, 병합 등 복잡한 구성을 판단하는 기술이다. 표 안의 경계가 없거나, 한 칸으로 구성이 되어있는데 텍스트는 나누어져 있다던지, 다양하게 처리해야 할 부분이 많다.
이 외에도 다양한 방법들이 있을 텐데 문서 로드하는 라이브러리를 만든다고 가정하면 이 모든 걸 종합 고려해봐야 할 것이다. 실제로 Upstage에서 출시된 Layout Analyzer이다. 사용은 안 해봤지만. 엄청난 노력이 들어간 결과물 아닐까 생각한다.
PDF 문서 로더 설루션 소개
- Aspose
PDF to Markdown
- Tabula
지원출력 형식 : CSV, TSV, JSON
https://tabula.technology/
- Apryse
지원 출력 형식 : MS Word, SVG, HTML
- AWS Textract (text + extract)
- Adobe PDF Extract API
나만 몰랐다.. 글로벌기업 문서 특화기업에서도 다 있다는 것을..(?) 무조건 LangChain 호환이 되는 것만 봤던 게 문제 아니었나 싶다.
json 형태로 뽑아서 문서를 이쁘게 적재하는 코드를 짜야겠지만 데이터자체가 정돈이 잘 된 모습이라 할 수 있을 것 같다.
- LLamaParse
LlamaParse는 LlamaIndex가 LlamaIndex 프레임워크를 사용하여 효율적인 검색과 콘텍스트 증강을 위해 파일을 효율적으로 구문 분석하고 표현하기 위해 만든 API이다.
LlamaParse는 LlamaIndex와 직접 통합됩니다.
무료 플랜은 하루 최대 1000페이지입니다. 유료 플랜은 주당 7,000페이지 무료 + 추가 페이지당 0.3c입니다.
요즘 제일 많이 examples 나 recipes에 많이 보이는 코드인 llamaparse이다. 성능이 생각보다 괜찮다고 한다.
- PDF4 LLM
LangChain, llamaindex, 특히 OpenAI 가 이걸 활용해서 데이터를 전처리한 걸로 알려져 있다. 나도 실제로 이번에 대회하면서 markdown을 변형 형태를 PDF4 LLM을 통해 표 추출을 하였다.
활용 사례
Parent Document Retriever
일반적인 RAG에서는 이것만 잘 써도 RAG가 어느 정도 많이 해결되지 않을까 생각이 든다. 부모 - 자식 단위로 구분을 하고 벡터스토어에는 부모인 Document를 큰 단위로 쪼개서 넣어놓고, 크 Document 를 이제 청크 해서 벡터스토어에 저장을 한다. 그럼 일반적으로 유사도 검색을 하였을 때는, 자식청크기준으로 리턴을 할 수 있지만,get_relevant_documents()와 같은 함수로 같은 쿼리를 넣게 되면 자식 청크가 참조한 큰 덩어리의 Document를 가지고 오게 된다. 그럼 이걸로 Retrieval을 해도 되는 것이다.
'Study notes' 카테고리의 다른 글
실전 RAG로 역량강화하기 - 멀티모달 프로토타입 (0) | 2024.09.05 |
---|---|
Docker Container 이해하기 - Dockerfile (0) | 2024.07.12 |
Docker Container 이해하기 - (4) image 명령어, 도커파일 (0) | 2024.07.12 |
Docker Container 이해하기 - (3) (0) | 2024.07.12 |
Docker Container 이해하기 - (2) (0) | 2024.07.11 |