Phase W + V' 완료: before→filled→after 파이프라인 + 조립 로직 수정
Phase W: - weight 비율 초기 배정 (space_allocator header 높이 반영) - block_assembler 공통 조립 함수 (filled/assembled 통합) - filled → Selenium 측정 → context 저장 - sidebar overflow 확장 + body 재배분 - sub_layouts 사전 계산 (이미지 누락 해결) Phase V': - 팝업 링크 우측상단 배치 (인라인 → position:absolute) - 표 내용 Kei 판단 (공란 크기 계산 → 행/열 산출 → Kei 요약) - 출처 라벨 삭제 + 이미지 아래 캡션 배치 - after 공란 제거 (결론 바로 위까지 body/sidebar 채움) 추가: - V-10 bold 키워드: 기계적 추출 → Kei 문맥 판단 - ** 마크다운 → <strong> 변환 - [이미지:] 마커 제거 (bold 변환 전 처리) - grid-template-rows AFTER 크기 반영 (Sonnet final) - assemble_stage2 CSS font-size override, white-space fix - 하드코딩 전수 검토 완료 - 본심 여러 topic 텍스트 합침 Phase X 계획 문서 작성 (동적 역할 구조) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -376,14 +376,15 @@ def verify_no_forbidden_content(
|
||||
# Layer 3: 구조 검증
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
|
||||
# Phase T: overflow:hidden 필수 요구 제거.
|
||||
# Phase T 프롬프트가 "overflow:hidden 금지"를 지시하므로 L3에서 요구하면 모순.
|
||||
# 텍스트 잘림은 L4(Selenium 실측)에서 감지.
|
||||
REQUIRED_PATTERNS: dict[str, list[str]] = {
|
||||
"body_bg": ["overflow:hidden|overflow: hidden"],
|
||||
"body_bg": [],
|
||||
"body_core": [
|
||||
"overflow:hidden|overflow: hidden",
|
||||
"key-msg",
|
||||
],
|
||||
"sidebar": [
|
||||
"overflow:hidden|overflow: hidden",
|
||||
"padding-left",
|
||||
"text-indent",
|
||||
],
|
||||
@@ -395,8 +396,12 @@ def verify_structure(
|
||||
generated_html: str,
|
||||
area_name: str,
|
||||
has_image: bool = False,
|
||||
font_hierarchy: dict | None = None,
|
||||
) -> VerificationResult:
|
||||
"""필수 CSS/HTML 패턴이 존재하는지 검증."""
|
||||
"""필수 CSS/HTML 패턴이 존재하는지 검증.
|
||||
|
||||
Phase T-8: font_hierarchy가 제공되면 폰트 위계 위반도 검사.
|
||||
"""
|
||||
patterns = REQUIRED_PATTERNS.get(area_name, [])
|
||||
missing = []
|
||||
|
||||
@@ -410,13 +415,36 @@ def verify_structure(
|
||||
if "slide-img-" not in generated_html:
|
||||
missing.append("slide-img-* (이미지 태그)")
|
||||
|
||||
# Phase T-8: 폰트 위계 검사
|
||||
font_warnings = []
|
||||
if font_hierarchy:
|
||||
role_font_map = {
|
||||
"body_bg": font_hierarchy.get("bg", 11),
|
||||
"body_core": font_hierarchy.get("core", 12),
|
||||
"sidebar": font_hierarchy.get("sidebar", 10),
|
||||
"footer": font_hierarchy.get("core", 12),
|
||||
}
|
||||
max_font = role_font_map.get(area_name)
|
||||
if max_font:
|
||||
# HTML에서 font-size 값 추출
|
||||
font_sizes = re.findall(r"font-size:\s*(\d+(?:\.\d+)?)\s*px", generated_html)
|
||||
for fs_str in font_sizes:
|
||||
fs = float(fs_str)
|
||||
if fs > max_font + 1: # 1px 허용 오차
|
||||
font_warnings.append(
|
||||
f"폰트 위계 위반: {area_name}에서 {fs}px 사용 (최대 {max_font}px)"
|
||||
)
|
||||
|
||||
passed = len(missing) == 0
|
||||
all_errors = [f"필수 패턴 누락: {p}" for p in missing]
|
||||
|
||||
return VerificationResult(
|
||||
passed=passed,
|
||||
area_name=area_name,
|
||||
checks={"structure": passed},
|
||||
score=1.0 if passed else (1.0 - len(missing) / max(1, len(patterns))),
|
||||
errors=[f"필수 패턴 누락: {p}" for p in missing],
|
||||
errors=all_errors,
|
||||
warnings=font_warnings,
|
||||
)
|
||||
|
||||
|
||||
@@ -551,18 +579,35 @@ async def generate_with_retry(
|
||||
return [topic_map[tid] for tid in info.get("topic_ids", []) if tid in topic_map]
|
||||
|
||||
area_texts = {}
|
||||
|
||||
def _get_role_text(role_topics):
|
||||
"""structured_text 우선, 없으면 source_hint 키워드로 sections 매칭."""
|
||||
texts = []
|
||||
for t in role_topics:
|
||||
st = t.get("structured_text", "")
|
||||
if st:
|
||||
texts.append(st)
|
||||
else:
|
||||
# fallback: source_hint에서 키워드 추출하여 매칭
|
||||
hint = t.get("source_hint", "")
|
||||
keywords = [w for w in hint.split() if len(w) >= 2][:3]
|
||||
matched = _map_sections_for_role(sections, [t], keywords) if keywords else ""
|
||||
if matched:
|
||||
texts.append(matched)
|
||||
return "\n\n".join(texts) if texts else ""
|
||||
|
||||
bg_topics = get_topics_for_role("배경")
|
||||
if bg_topics:
|
||||
area_texts["body_bg"] = _map_sections_for_role(sections, bg_topics, ["혼용", "사례"])
|
||||
area_texts["body_bg"] = _get_role_text(bg_topics)
|
||||
core_topics = get_topics_for_role("본심")
|
||||
if core_topics:
|
||||
area_texts["body_core"] = _map_sections_for_role(sections, core_topics, ["관계", "핵심기술", "DX"])
|
||||
area_texts["body_core"] = _get_role_text(core_topics)
|
||||
ref_topics = get_topics_for_role("첨부")
|
||||
if ref_topics:
|
||||
area_texts["sidebar"] = _get_definitions(content)
|
||||
area_texts["sidebar"] = _get_role_text(ref_topics)
|
||||
conclusion_topics = get_topics_for_role("결론")
|
||||
if conclusion_topics:
|
||||
area_texts["footer"] = _get_conclusion(content)
|
||||
area_texts["footer"] = _get_role_text(conclusion_topics)
|
||||
|
||||
has_image_areas = set()
|
||||
if images:
|
||||
|
||||
Reference in New Issue
Block a user