Phase X'-6 추가: 본문 표 요약 프로세스 (미완성)
- pipeline.py: normalized.tables에서 본문 표 감지 → Kei 요약 요청 - assemble_stage2: _assemble_type_b 하단 우측에 table_summaries 표출 - 검증: 4열x3행 표 생성 확인 미해결: - 들여쓰기 계층이 PNG와 다름 (대제목→소제목→본문 indent) - 상단 컨테이너 내용 잘림 - 하단 우측: 표를 불릿으로 풀지 말고 팝업 링크 + 요약 표로 - [DX 시행 주체별 기대효과 바로가기 →] 팝업 처리 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -877,11 +877,50 @@ def _assemble_type_b(run: Path, ctx: dict):
|
|||||||
clean = bold(clean, rn)
|
clean = bold(clean, rn)
|
||||||
bullets += f'<div class="bl" style="font-size:{font_size}px;"><span class="bl-m">•</span><span class="bl-t">{clean}</span></div>\n'
|
bullets += f'<div class="bl" style="font-size:{font_size}px;"><span class="bl-m">•</span><span class="bl-t">{clean}</span></div>\n'
|
||||||
|
|
||||||
|
# X'-6: 본문 표 요약이 있으면 하단 우측에 추가
|
||||||
|
table_summaries = enh.get("table_summaries", {})
|
||||||
|
table_html_br = ""
|
||||||
|
for ts_key, ts_data in table_summaries.items():
|
||||||
|
fmt = ts_data.get("format", "text")
|
||||||
|
if fmt == "table":
|
||||||
|
cols = ts_data.get("columns", [])
|
||||||
|
data = ts_data.get("data", [])
|
||||||
|
col_count = len(cols)
|
||||||
|
if col_count > 0 and data:
|
||||||
|
header_cells = "".join(
|
||||||
|
f'<div style="padding:{int(font_size*0.3)}px {int(font_size*0.5)}px;font-size:{font_size-2}px;font-weight:700;color:#fff;text-align:center;">{c}</div>'
|
||||||
|
for c in cols
|
||||||
|
)
|
||||||
|
rows_html = ""
|
||||||
|
for ri, row in enumerate(data):
|
||||||
|
bg = "#f8fafc" if ri % 2 == 0 else "#fff"
|
||||||
|
cells = ""
|
||||||
|
for ci, cell in enumerate(row):
|
||||||
|
c_color = "#1e40af" if ci == 0 else "#475569"
|
||||||
|
c_weight = "600" if ci == 0 else "400"
|
||||||
|
cells += f'<div style="padding:{int(font_size*0.2)}px {int(font_size*0.4)}px;font-size:{font_size-2}px;color:{c_color};font-weight:{c_weight};">{bold(str(cell), rn)}</div>'
|
||||||
|
rows_html += f'<div style="display:grid;grid-template-columns:repeat({col_count},1fr);border-top:1px solid #e2e8f0;background:{bg};">{cells}</div>\n'
|
||||||
|
table_html_br = (
|
||||||
|
f'<div style="margin-top:{int(font_size*0.5)}px;border:1px solid #e2e8f0;border-radius:{int(font_size*0.4)}px;overflow:hidden;">'
|
||||||
|
f'<div style="display:grid;grid-template-columns:repeat({col_count},1fr);background:linear-gradient(135deg,#0d47a1,#1565c0);">{header_cells}</div>'
|
||||||
|
f'{rows_html}</div>'
|
||||||
|
)
|
||||||
|
elif fmt == "bullets":
|
||||||
|
items = ts_data.get("items", [])
|
||||||
|
table_html_br = "".join(
|
||||||
|
f'<div style="padding-left:{int(font_size*1.2)}px;font-size:{font_size-1}px;margin-bottom:1px;">• {bold(str(item), rn)}</div>'
|
||||||
|
for item in items
|
||||||
|
)
|
||||||
|
elif fmt == "text":
|
||||||
|
table_html_br = f'<div style="font-size:{font_size-1}px;color:#475569;margin-top:{int(font_size*0.5)}px;">{bold(str(ts_data.get("summary", "")), rn)}</div>'
|
||||||
|
|
||||||
br_html = (
|
br_html = (
|
||||||
f'<div style="position:relative;height:100%;padding:{gap_small}px;box-sizing:border-box;">'
|
f'<div style="position:relative;height:100%;padding:{gap_small}px;box-sizing:border-box;'
|
||||||
|
f'display:flex;flex-direction:column;">'
|
||||||
f'{popup_html_br}'
|
f'{popup_html_br}'
|
||||||
f'<div style="font-weight:700;font-size:{font_size+1}px;color:#1a365d;margin-bottom:4px;">{topic_title}</div>'
|
f'<div style="font-weight:700;font-size:{font_size+1}px;color:#1a365d;margin-bottom:4px;">{topic_title}</div>'
|
||||||
f'<div style="font-size:{font_size}px;line-height:1.55;color:#333;">{bullets}</div></div>'
|
f'<div style="font-size:{font_size}px;line-height:1.55;color:#333;flex:1;">{bullets}</div>'
|
||||||
|
f'{table_html_br}</div>'
|
||||||
)
|
)
|
||||||
|
|
||||||
# 결론
|
# 결론
|
||||||
|
|||||||
@@ -780,6 +780,41 @@ async def generate_slide(
|
|||||||
popup_summaries[pr] = summary
|
popup_summaries[pr] = summary
|
||||||
logger.info(f"[V'-2] {pr}: format={summary.get('format')}")
|
logger.info(f"[V'-2] {pr}: format={summary.get('format')}")
|
||||||
|
|
||||||
|
# X'-6: 본문 표 요약 (유형 B — normalized.tables가 있으면)
|
||||||
|
table_summaries = {}
|
||||||
|
norm_tables = context.normalized.tables or []
|
||||||
|
if norm_tables and context.analysis.layout_template == "B":
|
||||||
|
from src.kei_client import call_kei_summarize_popup
|
||||||
|
for ti, table_data in enumerate(norm_tables):
|
||||||
|
headers = table_data.get("headers", [])
|
||||||
|
rows = table_data.get("rows", [])
|
||||||
|
if not headers or not rows:
|
||||||
|
continue
|
||||||
|
# 표를 마크다운 형태로 변환하여 Kei에게 전달
|
||||||
|
md_table = "| " + " | ".join(headers) + " |\n"
|
||||||
|
md_table += "| " + " | ".join(["---"] * len(headers)) + " |\n"
|
||||||
|
for row in rows:
|
||||||
|
md_table += "| " + " | ".join(str(c) for c in row) + " |\n"
|
||||||
|
|
||||||
|
# 하단 우측 공간 계산
|
||||||
|
bottom_roles = [r for r, ci in updated_containers.items() if ci.zone in ("bottom_left", "bottom_right")]
|
||||||
|
if bottom_roles:
|
||||||
|
br_ci = next((ci for r, ci in updated_containers.items() if ci.zone == "bottom_right"), None)
|
||||||
|
if br_ci:
|
||||||
|
available_h = br_ci.height_px - 30 # 제목 + padding
|
||||||
|
available_w = br_ci.width_px
|
||||||
|
fs = font_h.get("core", 12)
|
||||||
|
summary = await call_kei_summarize_popup(
|
||||||
|
popup_title=f"본문표{ti+1}",
|
||||||
|
popup_content=md_table,
|
||||||
|
available_width_px=available_w,
|
||||||
|
available_height_px=available_h,
|
||||||
|
font_size=fs,
|
||||||
|
)
|
||||||
|
if summary:
|
||||||
|
table_summaries[f"table_{ti}"] = summary
|
||||||
|
logger.info(f"[X'-6] 본문표{ti+1}: format={summary.get('format')}")
|
||||||
|
|
||||||
# 결과를 context에 저장 (Stage 2에서 사용)
|
# 결과를 context에 저장 (Stage 2에서 사용)
|
||||||
return {
|
return {
|
||||||
"containers": updated_containers,
|
"containers": updated_containers,
|
||||||
@@ -811,6 +846,7 @@ async def generate_slide(
|
|||||||
"emphasis_blocks": enhancements.emphasis_blocks,
|
"emphasis_blocks": enhancements.emphasis_blocks,
|
||||||
"bold_keywords": enhancements.bold_keywords,
|
"bold_keywords": enhancements.bold_keywords,
|
||||||
"popup_summaries": popup_summaries,
|
"popup_summaries": popup_summaries,
|
||||||
|
"table_summaries": table_summaries,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user