Confluence 문서 내 표(Table), 그림(PNG/JPG), 구성도(Draw.io)는 LLM의 RAG 시각과 텍스트 시각 모두에서 매우 중요한 맥락(Context)을 가지고 있습니다. Air-Gapped 환경에서 이를 손실 없이 Markdown화하고 인덱싱하는 구체적인 처리 전략과 구현 방법입니다.
| 요소 | Markdown 변환 방식 | Git 저장 방식 | RAG / Hybrid Search 처리 방식 |
|---|---|---|---|
| 표 (Table) | Clean Markdown Table (` | --- | --- |
| 이미지 (PNG/JPG) | Relative Image Tag () | Git 저장소 내 assets/ 폴더에 바이너리 다운로드 | Local Vision LLM (VLM)을 이용해 Image Captioning(설명 텍스트) 생성 후 MD에 포함 |
| 구성도 (Draw.io) | SVG/PNG 변환 + Mermaid.js (텍스트 코드) | Git 저장소 내 이미지 및 .drawio 원본 파일 | Mermaid 코드로 변환 시 아키텍처 구조 자체가 텍스트화되어 완벽한 RAG 검색 가능 |
html2text 기본 설정으로 변환하면 복잡한 표가 깨지는 경우가 많습니다. BeautifulSoup으로 표 내부의 병합된 셀(colspan, rowspan)이나 깨진 태그를 정제한 후 표준 Markdown 표 형식으로 변환합니다.
import html2text
h2t = html2text.HTML2Text()
h2t.ignore_tables = False # 표를 Markdown 표로 변환 활성화
h2t.body_width = 0 # 표 내부 강제 줄바꿈 방지
Air-Gapped 환경이므로 이미지 URL을 외부로 연결할 수 없습니다. 따라서 Confluence Attachment API를 통해 이미지를 로컬 다운로드하여 Git 저장소에 넣고, Local Vision LLM을 이용해 텍스트 설명(Caption)을 추출하여 메타데이터로 함께 저장합니다.
ops-knowledge/
└── OPS/
├── CONF-10429_Cilium_BGP.md
└── assets/
├── CONF-10429_fig1.png
└── CONF-10429_fig2.png
import os
import requests
# 망분리 내 배포된 Local Vision LLM (e.g., Qwen2-VL, Llama-3.2-Vision)
LOCAL_VLM_URL = "http://vllm-vision.internal:8000/v1/chat/completions"
def process_confluence_images(page_id: str, soup: BeautifulSoup, space: str) -> BeautifulSoup:
assets_dir = f"/workspace/ops-knowledge-repo/ops-knowledge/{space}/assets"
os.makedirs(assets_dir, exist_ok=True)
for img_tag in soup.find_all('img'):
src = img_tag.get('src', '')
# Confluence 첨부파일 이미지인 경우
if 'download/attachments' in src or 'attachments' in src:
img_url = f"http://confluence.internal{src}"
img_name = f"{page_id}_{os.path.basename(src.split('?')[0])}"
local_img_path = os.path.join(assets_dir, img_name)
# 1. 이미지 바이너리 다운로드
res = requests.get(img_url, headers={"Authorization": "Bearer TOKEN"})
if res.status_code == 200:
with open(local_img_path, 'wb') as f:
f.write(res.content)
# 2. Local VLM을 이용해 이미지 요약/설명 텍스트 생성 (선택 사항)
img_caption = generate_image_caption(local_img_path)
# 3. HTML 태그를 상대 경로 Markdown 이미지 태그 + Caption으로 대체
markdown_img_str = f"\n\n*그림 설명: {img_caption}*\n"
img_tag.replace_with(markdown_img_str)
return soup
구성도 디아그램은 AIOps 시스템에서 노드 간 연결 관계, 네트워크 경로, 서비스 의존성을 파악하는 핵심 자산입니다. 단순 이미지로만 변환하면 LLM이 구조를 파악하기 어렵습니다.
.drawio (또는 .xml) 파일과 렌더링된 .png를 동시에 저장합니다. 이를 Git assets/ 폴더에 함께 보관합니다.### 아키텍처 구성도
```mermaid
graph TD
A[Client Ingress] --> B[Cilium eBPF Router]
B --> C[MinIO AIStor Storage Pool]
B --> D[Vault Secret Engine]
원본 파일: [CONF-10429_arch.drawio](https://www.google.com/search?q=./assets/CONF-10429_arch.drawio)
converter.py) 통합 적용 방식기존 converter.py 흐름에 위에서 구현한 [표 정제 이미지 다운로드 및 VLM Captioning Draw.io / Mermaid 변환]을 추가한 통합 프로세스 순서입니다.
def convert_confluence_html_to_md(page_data: dict, raw_html: str) -> str:
soup = BeautifulSoup(raw_html, 'html.parser')
# 1. 문서 속성 표(Page Properties) 파싱 및 제거
human_meta = extract_human_metadata_from_table(soup)
# 2. Draw.io / 다이어그램 매크로 정제 및 Mermaid/텍스트 추출
soup = process_drawio_diagrams(soup, page_data["id"], page_data["space"]["key"])
# 3. 일반 이미지 다운로드 & Local VLM 설명 추출 & 상대 경로 교체
soup = process_confluence_images(page_data["id"], soup, page_data["space"]["key"])
# 4. Clean Markdown 변환 (표 변환 옵션 포함)
h2t = html2text.HTML2Text()
h2t.ignore_tables = False
h2t.body_width = 0
clean_md_body = h2t.handle(str(soup))
# 5. 메타데이터 최종 합성 (YAML Front-Matter)
# ... (기존 동일)
return yaml_frontmatter + clean_md_body
html2text.ignore_tables = False 설정으로 텍스트 표로 100% 보존합니다.assets/ 디렉토리에 다운로드 후 상대 경로로 링크하며, Local VLM을 통해 1~2줄 텍스트 캡션을 생성해 추가하면 검색 정밀도가 올라갑니다..drawio 파일 보관과 함께, 노드 간 연결 관계를 Mermaid.js 코드 블록으로 변환하여 Markdown에 넣으면 LLM이 아키텍처 관계를 완전하게 추론할 수 있게 됩니다.