PDF 문서에서 지식을 추출하고 대규모 언어 모델(LLM)을 효율적으로 파인튜닝하는 Azure-first 멀티클라우드 엔드투엔드 파이프라인입니다. 경량 CPU 컨테이너의 PDF 파싱과 최적화된 LLM 파인튜닝을 결합하여 문서 기반 질의응답 시스템을 구축합니다.
기본 백엔드는 Azure AI Foundry(Azure OpenAI / Foundry Agent Service)와 Azure Machine Learning이며, AWS Bedrock + SageMaker 경로도 그대로 지원합니다. 하나의 공개 컨테이너 이미지(GHCR)를 두 클라우드가 함께 사용합니다.
- 금융보안원 AI 개발 강의, 2025
- 경량 PDF 추출: Unstructured 라이브러리로 텍스트/표/이미지 추출 (CPU 슬림 이미지
:latest~2GB, 레이아웃+표를 GPU로 가속하는:latest-gpu~8GB는 선택) - Q&A 자동 생성 (멀티 공급자): Azure AI Foundry(Azure OpenAI · Foundry Agent), OpenAI, Amazon Bedrock Claude, 로컬 Ollama(자격 증명 불필요) 중 환경 변수 하나로 전환. Azure는 Entra ID 키리스 인증으로 한 번에 기동(키 없이
DefaultAzureCredential). Ollama는 텍스트·비전 모델을 분리 지정(OLLAMA_VISION_MODEL로qwen2.5vl·minicpm-v·llama3.2-vision등 멀티모달 태그) - 출력 언어 고정(드리프트 방지):
OUTPUT_LANGUAGE로 생성 Q&A 언어를 고정 — 기본auto(원문 언어 자동 감지)로 영문 PDF→한국어 답변 같은 드리프트를 차단하고,korean/english/japanese등으로 강제도 가능. 프롬프트에 언어 락 지시가 주입됨 - 데이터 품질 관리(검증·중복 제거): 데이터셋 저장 직전 빈 항목·너무 짧은 응답·질문=답변·모델 거부("제공된 정보로는 알 수 없…")를 제거하고, 정규화 기반 정확/유사 중복 질문을 제거.
VALIDATE_QA·DEDUP_QA·DEDUP_SIMILARITY등으로 조절하며 제거 사유 통계를 리포트(웹앱·manifest에 노출) - 다중 페르소나:
PERSONA로 교수·소크라테스식 튜터·실무 컨설턴트·기술 면접관·리서치 분석가·파인만(쉬운 설명)·자서전 저자(1인칭·문체 보존) 등 서로 다른 방식을 전환해 하나의 PDF로 여러 파인튜닝 데이터셋 생성. 페르소나는pdf_qa/personas.yaml원장에서 관리하며PERSONA_FILE로 외부 파일 지정 가능 - GPU 자동 가속(디바이스 인지): 실행 시 GPU를 점검해 감지되면
hi_res레이아웃(onnxruntime-gpu)+표 구조(CUDA torch)를 자동으로 GPU에 태우고, CPU에서는 경량 경로 유지 - 클라우드 무관 코어 패키지:
pdf_qa패키지 + 공급자 플러그인 구조로 코드 중복 제거, 런타임별 얇은 진입점 - 단일 공개 이미지:
ghcr.io/hyeonsangjeon/pdf2llm-tuning-studio/pdf-qa-extractor하나로 로컬·Azure ML·SageMaker 실행 - 로컬 데모 웹앱(싱글 노드): 같은 이미지에서
python run_webapp.py→ 브라우저에서 문서 업로드·페르소나 선택. 파이프라인을 같은 프로세스에서 직접 호출(in-process) 해 GPU 유무를 자동 감지하며, 미리보기 모드는 클라우드 자격 증명 없이 오프라인으로 동작(병렬 팬아웃은 advanced) - 아주 쉬운 사용: 한 줄 함수 API
extract_qa("report.pdf", out="qa.jsonl", provider="ollama")+ 모든 환경변수를 문서화한 원장pdf_qa/settings.yaml(→.env.example생성/검증:python -m pdf_qa.settings --check) - 차트-문맥 추출 파이프라인: 차트/도표 PNG를 단독으로 넘기지 않고 읽기 순서·좌표·이미지 경로로 각 도표를 주변 절·문단·캡션과 연결해 비전 프롬프트에 문맥을 주입(숫자·라벨은 이미지에서만). 각 이미지 Q&A에
page·section·figure_index·context_used출처 기록 - 폴더 일괄 처리 & Compose: 레포 루트
docker-compose.yml로 웹앱/배치를 CPU·GPU 한 번에 구동,run_auto.py가INPUT_DIR→OUTPUT_DIR로 파일별 JSONL +all.qa.jsonl+manifest.json(차트 연결 포함) 생성. 웹앱은<문서>.qa.jsonl·manifest.json서버 다운로드 제공 - 메모리 효율적 파인튜닝: Unsloth 최적화와 LoRA 어댑터로 제한된 GPU 환경에서도 대형 모델 학습
PDF 문서
│
┌─────────────▼──────────────┐
│ pdf_qa 코어 패키지 (파싱·프롬프트·파이프라인) │
│ providers: azure · openai · bedrock · ollama │
└─────────────┬──────────────┘
│ 빌드/배포
ghcr.io/.../pdf-qa-extractor (공개 경량 컨테이너 이미지 1개)
│ pull │ pull
┌────────▼──── Azure (기본) ──┐ ┌────────▼──── AWS (also) ──┐
│ Azure ML Command Job │ │ SageMaker Processing Job │
│ └▶ Azure AI Foundry │ │ └▶ Bedrock Claude │
│ Blob · Key Vault · Entra ID │ │ S3 · SSM · IAM │
└──────────────┬──────────────┘ └─────────────┬─────────────┘
└──────────────┬───────────────────┘
▼
qa_pairs.jsonl (Q&A 데이터셋)
▼
fine_tuning/ (Unsloth + LoRA 파인튜닝)
동일한 코드·이미지에서 LLM_PROVIDER 환경 변수만 바꾸면 백엔드가 교체됩니다.
PDF2LLM-Tuning-Studio/
├── .github/workflows/
│ └── build-and-push.yml # GHCR 컨테이너 자동 빌드/푸시 (공개 이미지)
│
├── azure/ # ☁️ Azure ML + AI Foundry 자산 (Azure-first)
│ ├── azureml_job.yml # Azure ML Command Job 스펙
│ ├── azureml_pdf_qa_extraction.ipynb # Azure ML 배치 잡 제출 데모
│ ├── foundry_agent_quickstart.ipynb # Foundry Agent Service 데모
│ └── README.md # Azure 설정/실행 가이드
│
├── assets/ # 공통 리소스
│ ├── images/ # 다이어그램 및 이미지
│ └── utils/ # iam.py(AWS) · ssm.py(AWS) · keyvault.py(Azure)
│
├── pdf_qa_extraction/ # PDF 처리 및 Q&A 추출 모듈
│ ├── pdf_qa/ # ⭐ 클라우드 무관 코어 패키지
│ │ ├── config.py · parsing.py · prompts.py · extract.py · pipeline.py · device.py
│ │ ├── api.py # 🟢 한 줄 함수 API (extract_qa)
│ │ ├── layout.py # 📊 정렬된 레이아웃 + 차트↔문맥 연결
│ │ ├── manifest.py # 실행 매니페스트 + 도표 연결 요약
│ │ ├── settings.py · settings.yaml # 🗒️ 환경변수 원장 (.env 생성/검증)
│ │ ├── personas.yaml # 🎭 페르소나 원장 (YAML, PERSONA_FILE로 외부 지정 가능)
│ │ └── providers/ # azure_foundry · openai · bedrock · ollama (+ base 팩토리)
│ ├── webapp/ # 🖥️ 로컬 데모 웹앱 (FastAPI, in-process 파이프라인)
│ │ ├── app.py # /api/{personas,device,providers,settings,extract,download}
│ │ └── static/index.html # 싱글 페이지 UI (GPU/CPU 배지, 페르소나, 차트 연결·다운로드)
│ ├── run_local.py # 로컬/컨테이너 통합 진입점 (LLM_PROVIDER로 전환)
│ ├── run_auto.py # 📁 폴더 일괄 처리 (INPUT_DIR→OUTPUT_DIR, JSONL+manifest)
│ ├── run_webapp.py # 로컬 데모 웹앱 진입점 (uvicorn, 기본 :8000)
│ ├── azureml_job.py # Azure ML 잡 진입점
│ ├── processing.py # SageMaker Processing Job 진입점
│ ├── processing_local*.py # (하위호환) Bedrock/OpenAI 로컬 실행 shim
│ ├── pyproject.toml · requirements.txt
│ ├── Dockerfile · Dockerfile_event_eng
│ └── README.md · README_en.md
│
├── docker-compose.yml # 🐳 웹앱/배치 원커맨드 구동 (CPU·GPU 프로필)
├── .env.example # 🗒️ settings.yaml 원장에서 생성된 환경변수 예시
│
└── fine_tuning/ # LLM 파인튜닝 모듈
├── 01_setup_environment.ipynb
├── 02_data_preprocessing_and_analysis.ipynb # Blob/S3/로컬 데이터 로딩
├── 03_train_unsloth_model.ipynb
└── README.md
# 파이썬 한 줄: PDF → Q&A JSONL (GPU/CPU·페르소나·차트 문맥 자동)
from pdf_qa import extract_qa
extract_qa("report.pdf", out="qa_pairs.jsonl", provider="ollama", persona="feynman")# 또는 Docker Compose 원커맨드 (레포 루트)
cp .env.example .env # 공급자 자격 증명 입력 (Ollama는 불필요)
docker compose up webapp # 데모 웹앱 → http://localhost:8000
mkdir -p data/input && cp *.pdf data/input/
docker compose run --rm batch # 폴더 일괄 처리 → data/output/*.qa.jsonl + manifest.json
# GPU: docker compose --profile gpu up webapp-gpu / --profile gpu run --rm batch-gpu환경변수는
pdf_qa/settings.yaml원장에서 관리합니다 —python -m pdf_qa.settings --check azure로 검증,--write-env로.env.example재생성.
공개 GHCR 이미지를 그대로 받거나 직접 빌드합니다.
# 공개 이미지 pull (권장)
docker pull ghcr.io/hyeonsangjeon/pdf2llm-tuning-studio/pdf-qa-extractor:latest
# 또는 직접 빌드
cd pdf_qa_extraction
docker build -t pdf-qa-extractor -f Dockerfile .경량 컨테이너에서 PDF의 텍스트/표/이미지를 추출하고 고품질 Q&A 쌍을 생성합니다. 공급자는 LLM_PROVIDER로 선택합니다(기본 azure).
# Azure OpenAI (Foundry 모델 배포) 사용
docker run --rm -v $(pwd):/app -w /app --env-file .env \
ghcr.io/hyeonsangjeon/pdf2llm-tuning-studio/pdf-qa-extractor:latest \
python run_local.py.env 예시(Azure OpenAI):
LLM_PROVIDER=azure
AZURE_MODE=openai
AZURE_OPENAI_ENDPOINT=https://<res>.openai.azure.com/
AZURE_OPENAI_DEPLOYMENT=gpt-4o
AZURE_OPENAI_API_VERSION=2024-10-21
# 키 대신 Managed Identity/az login 사용 시 API_KEY 생략 → Entra ID로 한 번에 기동
PDF_PATH=data/fsi_data.pdf
DOMAIN=International Finance
NUM_QUESTIONS=5
NUM_IMG_QUESTIONS=1
# hi_res 레이아웃 모델 선택(=unstructured의 hi_res_model_name): yolox(기본)·detectron2_onnx 등
TABLE_MODEL=yolox- Azure ML 배치 잡으로 실행:
azure/README.md,azure/azureml_job.yml,azure/azureml_pdf_qa_extraction.ipynb - Foundry Agent Service(교수 페르소나 에이전트)로 생성:
azure/foundry_agent_quickstart.ipynb(AZURE_MODE=agent)
# 로컬에서 Ollama 서버를 띄우고 모델을 받은 뒤(예: ollama pull llama3.1)
LLM_PROVIDER=ollama OLLAMA_MODEL=llama3.1 \
OLLAMA_BASE_URL=http://localhost:11434 python run_local.py
# 차트/도표를 읽으려면 멀티모달 태그를 따로 지정 (텍스트=llama3.1, 비전=qwen2.5vl)
LLM_PROVIDER=ollama OLLAMA_MODEL=llama3.1 \
OLLAMA_VISION_MODEL=qwen2.5vl python run_local.py # 대안: minicpm-v, llama3.2-vision, llava비전 태그 선택: 한국어·차트·표 OCR에는
qwen2.5vl·minicpm-v가 강하고,llama3.2-vision·llava도 지원됩니다.OLLAMA_VISION_MODEL을 비우면OLLAMA_MODEL을 그대로 재사용합니다. 참고:MAI(MAI-DS-R1)는 텍스트 전용이며 Ollama 라이브러리에 없습니다(멀티모달 아님) — 텍스트 추론은 Azure Foundry로 사용하세요.
# AWS Bedrock 사용
LLM_PROVIDER=bedrock docker run --rm -v $(pwd):/app -w /app --env-file .env \
ghcr.io/hyeonsangjeon/pdf2llm-tuning-studio/pdf-qa-extractor:latest \
python run_local.pySageMaker Processing 배치 잡 실행은 PDF Q&A 추출 가이드와 sagemaker_processingjob_pdf_qa_extraction.ipynb를 참조하세요.
CLI 대신 브라우저로 체험하려면 같은 이미지에서 웹앱을 띄웁니다. 문서를 올리고 페르소나를 고른 뒤 실행하면 호스트 GPU 유무를 자동 감지합니다. 미리보기 모드는 자격 증명 없이 오프라인으로 추출·페르소나 프롬프트를 보여주고, 전체 모드는 선택한 공급자로 Q&A까지 생성합니다(자세한 내용은 PDF Q&A 추출 가이드의 "로컬 데모 웹앱" 절 참조).
# http://localhost:8000 접속 (GPU 호스트는 --gpus all 추가)
docker run --rm -p 8000:8000 --env-file .env \
ghcr.io/hyeonsangjeon/pdf2llm-tuning-studio/pdf-qa-extractor:latest \
python run_webapp.py처리 방식은 두 가지 중 선택합니다 — 단일 노드·인프로세스(기본
WORKERS=1, GPU 데모 권장)와 멀티 프로세스(WORKERS=N, CPU 동시성↑). 파일 없이도 UI의 📄 샘플 문서로 시도로 번들 PDF를 바로 미리볼 수 있습니다.
생성된 Q&A 데이터를 파인튜닝에 적합한 형식으로 변환합니다. fine_tuning/02_data_preprocessing_and_analysis.ipynb에서 진행하며, 입력 데이터는 Azure Blob / AWS S3 / 로컬에서 로드할 수 있습니다(DATA_SOURCE 환경 변수).
- 데이터 품질 검증(중복/짧은 응답 제거), 통계 분석/시각화, 학습·검증 분할, 학습 포맷 변환
Unsloth와 LoRA 어댑터로 메모리 효율적 파인튜닝을 수행합니다. fine_tuning/03_train_unsloth_model.ipynb에서 진행하며, Azure ML Compute 또는 AWS/온프레미스 GPU 어디서든 동작합니다. 자세한 내용은 LLM 파인튜닝 가이드를 참조하세요.
| 목표 | LLM_PROVIDER |
추가 설정 |
|---|---|---|
| Azure OpenAI (기본) | azure |
AZURE_MODE=openai, AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_DEPLOYMENT |
| Azure AI Foundry Agent | azure |
AZURE_MODE=agent, AZURE_AI_PROJECT_ENDPOINT, AZURE_AI_AGENT_MODEL |
| OpenAI 직접 | openai |
OPENAI_API_KEY |
| AWS Bedrock | bedrock |
AWS 자격증명 / SageMaker 실행 역할, MODEL_ID |
- Q&A 생성 (기본): Azure AI Foundry — Azure OpenAI · Foundry Agent Service
- 오케스트레이션 (기본): Azure Machine Learning (Command Job)
- Q&A 생성 (also): Amazon Bedrock Claude, OpenAI(GPT-4o 등)
- 오케스트레이션 (also): Amazon SageMaker Processing
- 컨테이너/레지스트리: Docker, GitHub Container Registry(GHCR, 공개)
- PDF 추출: Unstructured, CUDA
- 모델 파인튜닝: Unsloth, PyTorch, LoRA
- 지원 모델: Llama, Mistral, Gemma, Qwen 등 오픈소스 LLM
- PDF 추출: CPU (경량 슬림 이미지, 스캔 문서 레이아웃/OCR 가속용 GPU는 선택)
- 파인튜닝: 최소 8GB VRAM (16GB+ 권장)
- PDF 처리: 대용량 PDF(100MB+)는 분할 처리,
batch_size로 메모리 조절 - 모델 파인튜닝: 4비트 양자화로 메모리 75% 감소,
gradient_checkpointing="unsloth"로 추가 30% VRAM 절약
- 추가 모델 지원: 새로운 오픈소스 LLM 적용
- 다국어 지원: 다양한 언어 문서 처리
- Azure ML / SageMaker 통합: 대규모 병렬 파인튜닝·추론
- RAG 시스템 구축: 문서 임베딩으로 검색 증강 생성
각 모듈에 대한 자세한 정보는 해당 디렉토리의 README를 참조하세요:
- Azure AI Foundry Documentation
- Azure AI Foundry Agent Service
- Azure Machine Learning Documentation
- Unsloth: Accelerating LLM Fine-tuning
- Unstructured: Open-source PDF extraction
- Amazon Bedrock Documentation
- OpenAI Platform Documentation
- LoRA: Low-Rank Adaptation of Large Language Models
- Llama 3: Open Foundation and Fine-Tuned Chat Models
- teddylee777: LangChain 한국어 튜토리얼
