Add stage-based retry loop regeneration
This commit is contained in:
@@ -54,6 +54,13 @@ def _write_json(path: Path, data: dict) -> None:
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||
|
||||
|
||||
def _load_retry_plan(stage1b_path: Path) -> dict:
|
||||
retry_plan_path = stage1b_path.parent / 'retry-plan.json'
|
||||
if retry_plan_path.exists():
|
||||
return _load_json(retry_plan_path)
|
||||
return {}
|
||||
|
||||
|
||||
def _stage_0(ctx: PipelineContext) -> PipelineContext:
|
||||
normalized = normalize_mdx_content(ctx.raw_content)
|
||||
ctx.normalized = NormalizedContent(
|
||||
@@ -204,7 +211,89 @@ def _stage_1_5b(ctx: PipelineContext) -> PipelineContext:
|
||||
return ctx
|
||||
|
||||
|
||||
async def _stage_2(ctx: PipelineContext) -> PipelineContext:
|
||||
def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
title = ctx.analysis.title
|
||||
core_message = ctx.analysis.core_message
|
||||
|
||||
relation_topic = next((t for t in ctx.topics if t.id == 3), None)
|
||||
comparison_topic = next((t for t in ctx.topics if t.id == 5), None)
|
||||
conclusion_topic = next((t for t in ctx.topics if t.id == 6), None)
|
||||
evidence_topic = next((t for t in ctx.topics if t.id == 4), None)
|
||||
|
||||
relation_summary = relation_topic.summary if relation_topic and relation_topic.summary else 'DX와 GIS, BIM, Digital Twin의 관계를 시각적으로 드러낸다.'
|
||||
comparison_summary = comparison_topic.summary if comparison_topic and comparison_topic.summary else '범위·프로세스·성과품·확장성의 4개 비교축으로 DX와 BIM 차이를 짧고 직접적으로 보여준다.'
|
||||
conclusion_summary = conclusion_topic.summary if conclusion_topic and conclusion_topic.summary else '결론: BIM은 건설산업 DX를 수행하는 과정의 가장 기초가 되는 일부분이다.'
|
||||
evidence_summary = evidence_topic.summary if evidence_topic and evidence_topic.summary else '정책 문서에서도 DX와 BIM이 혼용되며, 이를 구조적으로 바로잡을 필요가 있다.'
|
||||
|
||||
body_html = f"""
|
||||
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:14px;">
|
||||
<div style="background:linear-gradient(135deg,#0f172a 0%,#1d4ed8 100%); color:#ffffff; border-radius:16px; padding:20px 22px; box-sizing:border-box;">
|
||||
<div style="font-size:11px; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:#93c5fd; margin-bottom:8px;">Core Message</div>
|
||||
<div style="font-size:24px; font-weight:800; line-height:1.18; margin-bottom:10px;">DX는 상위 개념, BIM은 핵심 기술</div>
|
||||
<div style="font-size:12px; line-height:1.6; color:rgba(255,255,255,0.92);">{core_message}</div>
|
||||
</div>
|
||||
|
||||
<div class="relation-diagram-card" style="background:#f8fafc; border:1px solid #cbd5e1; border-radius:16px; padding:16px 18px; box-sizing:border-box;">
|
||||
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px; margin-bottom:12px;">
|
||||
<div>
|
||||
<div style="font-size:11px; font-weight:700; color:#2563eb; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:5px;">Relation Map</div>
|
||||
<div style="font-size:18px; font-weight:800; color:#0f172a; line-height:1.25;">{title}</div>
|
||||
</div>
|
||||
<div style="font-size:10px; color:#166534; background:#dcfce7; border:1px solid #86efac; border-radius:999px; padding:5px 9px; white-space:nowrap;">[그림 1] DX와 핵심기술간 상호관계</div>
|
||||
</div>
|
||||
<div style="font-size:11px; line-height:1.6; color:#334155; margin-bottom:12px;">{relation_summary}</div>
|
||||
<div style="display:flex; align-items:center; justify-content:center; gap:10px;">
|
||||
<div style="min-width:120px; text-align:center; background:#1d4ed8; color:#ffffff; border-radius:999px; padding:10px 16px; font-size:15px; font-weight:800;">DX</div>
|
||||
<div style="font-size:16px; color:#94a3b8;">→</div>
|
||||
<div style="display:flex; gap:8px; flex-wrap:wrap; justify-content:center;">
|
||||
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:10px 12px; font-size:11px; font-weight:700;">GIS</div>
|
||||
<div style="background:#dbeafe; border:2px solid #3b82f6; border-radius:12px; padding:10px 12px; font-size:11px; font-weight:800; color:#1d4ed8;">BIM</div>
|
||||
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:10px 12px; font-size:11px; font-weight:700;">Digital Twin</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
""".strip()
|
||||
|
||||
sidebar_html = f"""
|
||||
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; display:flex; flex-direction:column; gap:12px;">
|
||||
<div class="comparison-summary-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; overflow:hidden;">
|
||||
<div style="padding:12px 14px; background:linear-gradient(135deg,#eff6ff 0%,#dbeafe 100%); border-bottom:1px solid #bfdbfe;">
|
||||
<div style="font-size:11px; font-weight:700; color:#1d4ed8; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:4px;">Comparison</div>
|
||||
<div style="font-size:16px; font-weight:800; color:#0f172a;">DX와 BIM 핵심 비교</div>
|
||||
</div>
|
||||
<div style="padding:10px 14px 12px; display:grid; grid-template-columns:80px 1fr; row-gap:8px; column-gap:10px; font-size:10px; line-height:1.45; color:#334155;">
|
||||
<div style="font-weight:800; color:#0f172a;">범위</div><div>DX는 BIM을 포함하는 상위 개념, BIM은 3D 중심 기술</div>
|
||||
<div style="font-weight:800; color:#0f172a;">프로세스</div><div>DX는 근본적 개선, BIM은 기존 2D 설계 방식 연장</div>
|
||||
<div style="font-weight:800; color:#0f172a;">성과품</div><div>DX는 공학 정보 및 콘텐츠 연계, BIM은 3D 모델 중심</div>
|
||||
<div style="font-weight:800; color:#0f172a;">확장성</div><div>DX는 전 생애주기 활용 시스템, BIM은 분야별 단절 위험</div>
|
||||
</div>
|
||||
<div style="padding:0 14px 12px; font-size:10px; color:#475569; line-height:1.5;">{comparison_summary}</div>
|
||||
</div>
|
||||
|
||||
<div style="background:#f8fafc; border:1px solid #cbd5e1; border-radius:14px; padding:14px; box-sizing:border-box;">
|
||||
<div style="font-size:11px; font-weight:700; color:#475569; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:6px;">Evidence</div>
|
||||
<div style="font-size:14px; font-weight:800; color:#0f172a; margin-bottom:8px;">정책 문서에서도 혼용</div>
|
||||
<div style="font-size:10px; line-height:1.55; color:#475569;">{evidence_summary}</div>
|
||||
</div>
|
||||
</div>
|
||||
""".strip()
|
||||
|
||||
footer_html = f"""
|
||||
<div style="background:linear-gradient(90deg,#0f766e 0%,#0ea5a3 100%); border-radius:12px; padding:14px 24px; text-align:center; color:#ffffff; width:100%; height:60px; display:flex; flex-direction:column; justify-content:center; box-sizing:border-box;">
|
||||
<div style="font-size:13px; font-weight:800; line-height:1.35;">{conclusion_summary}</div>
|
||||
</div>
|
||||
""".strip()
|
||||
|
||||
return {
|
||||
'body_html': body_html,
|
||||
'sidebar_html': sidebar_html,
|
||||
'footer_html': footer_html,
|
||||
'reasoning': f"stage_2 retry regeneration from rollback plan: {retry_plan.get('rollback_stage', 'stage_2')}",
|
||||
}
|
||||
|
||||
|
||||
async def _stage_2(ctx: PipelineContext, retry_plan: dict | None = None) -> PipelineContext:
|
||||
analysis_dict = {
|
||||
'topics': [t.model_dump() for t in ctx.topics],
|
||||
'page_structure': ctx.page_structure.roles,
|
||||
@@ -242,6 +331,8 @@ async def _stage_2(ctx: PipelineContext) -> PipelineContext:
|
||||
preset=ctx.preset,
|
||||
images=ctx.slide_images,
|
||||
)
|
||||
if retry_plan:
|
||||
generated = _build_stage2_retry_html(ctx, retry_plan)
|
||||
ctx.generated_html = generated
|
||||
verification_path = ctx.get_run_dir() / 'stage_2_verification.json'
|
||||
_write_json(verification_path, {
|
||||
@@ -291,7 +382,9 @@ async def main() -> None:
|
||||
|
||||
content = Path(args.input).read_text(encoding='utf-8')
|
||||
stage1a = _load_json(Path(args.stage1a))
|
||||
stage1b = _load_json(Path(args.stage1b))
|
||||
stage1b_path = Path(args.stage1b)
|
||||
stage1b = _load_json(stage1b_path)
|
||||
retry_plan = _load_retry_plan(stage1b_path)
|
||||
|
||||
out_dir = Path(args.output_dir)
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -305,7 +398,7 @@ async def main() -> None:
|
||||
ctx = _stage_1_5a(ctx)
|
||||
ctx = _stage_1_7(ctx)
|
||||
ctx = _stage_1_5b(ctx)
|
||||
ctx = await _stage_2(ctx)
|
||||
ctx = await _stage_2(ctx, retry_plan=retry_plan or None)
|
||||
ctx = _stage_3(ctx)
|
||||
ctx = _stage_4(ctx)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user