"""MDX 01~03에서 17개 단위를 각각 추출.
중목차는 '제목만'이 아니라 소목차/블릿 내용까지 포함한 의미 단위로 처리."""
import re
from pathlib import Path
MDX_DIR = Path(r"d:\ad-hoc\kei\design_agent\samples\mdx_batch")
def read_mdx(fname):
with open(MDX_DIR / fname, encoding="utf-8") as f:
content = f.read()
# frontmatter 제거
content = re.sub(r"^---.*?---", "", content, flags=re.DOTALL).strip()
# import 문 제거
content = re.sub(r"^import .*$", "", content, flags=re.MULTILINE)
return content
def extract_details_blocks(text):
"""... 블록들 반환. [(full_match, inner_text), ...]"""
pattern = re.compile(r".*? ", re.DOTALL)
return pattern.findall(text)
def remove_details(text):
"""... 블록 제거"""
return re.sub(r".*? ", "", text, flags=re.DOTALL)
def extract_markdown_tables(text):
"""| ... | ... | 형식 표 블록들 반환."""
lines = text.split("\n")
tables = []
current = []
in_table = False
for ln in lines:
stripped = ln.strip()
if re.match(r"^\|.*\|", stripped):
current.append(ln)
in_table = True
elif in_table:
# 표 끝
if current:
tables.append("\n".join(current))
current = []
in_table = False
if current:
tables.append("\n".join(current))
return tables
def extract_images(text):
""" 이미지. [(alt, src), ...]"""
pattern = re.compile(r"!\[([^\]]*)\]\(([^)]+)\)")
return pattern.findall(text)
def get_section(text, level, title_pattern, title_weight=3):
"""특정 레벨의 섹션 제목 + 본문 추출.
title_weight: 제목을 본문 맨 앞에 N번 반복해서 가중치 부여 (BM25/TF-IDF에서 자동으로 높은 점수).
0으로 주면 제목 제외 (구버전 동작)."""
prefix = "#" * level
lines = text.split("\n")
start = None
title_text = ""
for i, ln in enumerate(lines):
m = re.match(rf"^{prefix}\s+{title_pattern}", ln)
if m:
start = i
title_text = ln[level:].strip()
break
if start is None:
return ""
end = len(lines)
for i in range(start + 1, len(lines)):
ln = lines[i]
m = re.match(r"^(#+)\s", ln)
if m and len(m.group(1)) <= level:
end = i
break
body = "\n".join(lines[start + 1:end]).strip()
if title_weight > 0 and title_text:
title_block = "\n".join([title_text] * title_weight)
return (title_block + "\n\n" + body).strip()
return body
def extract_units():
"""17개 단위를 추출해서 {unit_id: text} dict 반환"""
mdx01 = read_mdx("01.mdx")
mdx02 = read_mdx("02.mdx")
mdx03 = read_mdx("03.mdx")
units = {}
# ═══════ MDX01 ═══════
# intro: 첫 ## 이전 텍스트, 는 제외
intro_block = mdx01.split("\n## ")[0]
# intro의
details01 = extract_details_blocks(intro_block)
# intro 본문 (details 제외)
units["MDX01-intro"] = remove_details(intro_block).strip()
units["MDX01-intro-details"] = details01[0] if details01 else ""
# ## 1. 용어 정의
sec01_1 = get_section(mdx01, 2, "1\\. 용어 정의")
units["MDX01-1"] = sec01_1
# ## 2. 용어간 상호관계 — 본문은 details 제외, 이미지 제외
sec01_2 = get_section(mdx01, 2, "2\\. 용어간 상호관계")
sec01_2_main = remove_details(sec01_2)
# 이미지 제거
sec01_2_main = re.sub(r"!\[[^\]]*\]\([^)]+\)", "", sec01_2_main).strip()
units["MDX01-2"] = sec01_2_main
# 이미지 단위
imgs01_2 = extract_images(sec01_2)
if imgs01_2:
alt, src = imgs01_2[0]
units["MDX01-2-image"] = f"{alt} {src}"
else:
units["MDX01-2-image"] = ""
# (비교표)
details01_2 = extract_details_blocks(sec01_2)
units["MDX01-2-details"] = details01_2[0] if details01_2 else ""
# ═══════ MDX02 ═══════
# ## 1. DX의 궁극적 목표 — 이미지 제외
sec02_1 = get_section(mdx02, 2, "1\\. DX의 궁극적 목표")
sec02_1_main = re.sub(r"!\[[^\]]*\]\([^)]+\)", "", sec02_1).strip()
units["MDX02-1"] = sec02_1_main
imgs02_1 = extract_images(sec02_1)
units["MDX02-1-image"] = f"{imgs02_1[0][0]} {imgs02_1[0][1]}" if imgs02_1 else ""
# ## 2. 주체별 기대효과 (컨테이너 — 소목차+블릿 전체 포함)
sec02_2 = get_section(mdx02, 2, "2\\. DX 기반 Process 혁신")
units["MDX02-2"] = sec02_2 # 소목차까지 다 포함
# ### 2.1 업무 수행 과정의 변화
sec02_2_1 = get_section(mdx02, 3, "2\\.1 업무 수행 과정")
units["MDX02-2.1"] = sec02_2_1
# ### 2.2 DX 시행 주체별 기대효과
sec02_2_2 = get_section(mdx02, 3, "2\\.2 DX 시행 주체별")
units["MDX02-2.2"] = sec02_2_2
# 2.2 안의 표만
tables02_2_2 = extract_markdown_tables(sec02_2_2)
units["MDX02-2.2-table"] = tables02_2_2[0] if tables02_2_2 else ""
# ═══════ MDX03 ═══════
# ## 1. 필수 요건
sec03_1 = get_section(mdx03, 2, "1\\. DX 시행을 위한 필수 요건")
units["MDX03-1"] = sec03_1
# ## 2. Process/Product 혁신 (컨테이너)
sec03_2 = get_section(mdx03, 2, "2\\. Process의 혁신과 Product")
units["MDX03-2"] = sec03_2
# ### 2.1 과정(Process)의 혁신
sec03_2_1 = get_section(mdx03, 3, "2\\.1 과정\\(Process\\)의 혁신")
units["MDX03-2.1"] = sec03_2_1
# 2.1 안의 표만
tables03_2_1 = extract_markdown_tables(sec03_2_1)
units["MDX03-2.1-table"] = tables03_2_1[0] if tables03_2_1 else ""
# ### 2.2 결과(Product)의 변화
sec03_2_2 = get_section(mdx03, 3, "2\\.2 결과\\(Product\\)의 변화")
units["MDX03-2.2"] = sec03_2_2
return units
if __name__ == "__main__":
units = extract_units()
print(f"총 {len(units)}개 단위 추출\n")
for uid, text in units.items():
preview = text[:80].replace("\n", " ").strip()
print(f" {uid:25s} [{len(text):4d}자] {preview}...")