From 6b17f448eb469db00ace5a381eb643102d007a01 Mon Sep 17 00:00:00 2001 From: kyeongmin Date: Mon, 6 Apr 2026 11:57:46 +0900 Subject: [PATCH] =?UTF-8?q?Phase=20X'-6=20=EC=B6=94=EA=B0=80:=20=EB=B3=B8?= =?UTF-8?q?=EB=AC=B8=20=ED=91=9C=20=EC=9A=94=EC=95=BD=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=84=B8=EC=8A=A4=20(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- scripts/assemble_stage2.py | 43 ++++++++++++++++++++++++++++++++++++-- src/pipeline.py | 36 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/scripts/assemble_stage2.py b/scripts/assemble_stage2.py index e4c501c..2658e25 100644 --- a/scripts/assemble_stage2.py +++ b/scripts/assemble_stage2.py @@ -877,11 +877,50 @@ def _assemble_type_b(run: Path, ctx: dict): clean = bold(clean, rn) bullets += f'
{clean}
\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'
{c}
' + 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'
{bold(str(cell), rn)}
' + rows_html += f'
{cells}
\n' + table_html_br = ( + f'
' + f'
{header_cells}
' + f'{rows_html}
' + ) + elif fmt == "bullets": + items = ts_data.get("items", []) + table_html_br = "".join( + f'
• {bold(str(item), rn)}
' + for item in items + ) + elif fmt == "text": + table_html_br = f'
{bold(str(ts_data.get("summary", "")), rn)}
' + br_html = ( - f'
' + f'
' f'{popup_html_br}' f'
{topic_title}
' - f'
{bullets}
' + f'
{bullets}
' + f'{table_html_br}
' ) # 결론 diff --git a/src/pipeline.py b/src/pipeline.py index 8480c35..7ce8674 100644 --- a/src/pipeline.py +++ b/src/pipeline.py @@ -780,6 +780,41 @@ async def generate_slide( popup_summaries[pr] = summary 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에서 사용) return { "containers": updated_containers, @@ -811,6 +846,7 @@ async def generate_slide( "emphasis_blocks": enhancements.emphasis_blocks, "bold_keywords": enhancements.bold_keywords, "popup_summaries": popup_summaries, + "table_summaries": table_summaries, }, }