[fix] solution/backend: 히어로 아래 한 줄이 소개문 세 문장을 이고 있었다

`narrative.summary` 는 계약이 "요약 **한 문장**"이라 적어 둔 자리인데(shared/site-payload.ts)
첫 **문단**을 통째로 넣고 있었다. 그 값은 두 곳으로 나간다 — 히어로 아래 한 줄과
meta description. 그래서 히어로가 세 문장을 이고 서고(실측 2026-09-10), 검색 결과에서는
설명이 중간에 잘렸다.

- site_payload._first_sentence: 첫 문장만 뗀다. **문장을 새로 생성하지 않는다** —
  있는 글에서 자를 뿐이다(요약을 또 생성하면 근거 검사를 한 번 더 통과해야 한다).
  숫자 사이의 점은 자르지 않는다(1.5km) — 뒤가 숫자면 문장 끝이 아니다.

★ 곁에서 확인한 것 — 생성기가 만든 meta_description 이 **버려지고 있다.**
  copy_service 는 소개문과 함께 50~120자짜리 메타 요약을 만들지만, 업종 스키마에
  `meta_description` 필드가 없어서 "allow_llm 이 아닌 필드" 로 조용히 건너뛴다
  (lodging.json 의 allow_llm 은 intro·room_intro 둘뿐). 지금은 첫 문장으로 대신하지만,
  스키마에 자리를 만들면 생성기가 쓴 요약이 그대로 meta description 이 된다 — 별건이다.

검증: 재발행 후 히어로 한 문장 · meta description 동일. test_snapshot 통과
(site_theme 의 섹션표 parity 4건 실패는 이 변경 전 기준선과 같다).
This commit is contained in:
hbyang 2026-09-10 15:29:42 +09:00
parent 868127a69a
commit c8cf704217

View File

@ -163,6 +163,21 @@ _DEFAULT_THEME = {
# ── 값 변환 헬퍼 ──────────────────────────────────────────────────────────
def _first_sentence(text: str) -> str:
"""첫 문장. 마침표가 없으면 통째로 돌려준다.
★ 왜 필요한가: 히어로 아래 한 줄과 meta description 이 같은 값을 쓴다. 둘 다 **한 문장**
자리라, 문단이 들어가면 히어로는 세 줄로 부풀고 검색 결과에서는 뒤가 잘린다.
★ 마침표 뒤에 공백이 없어도 자른다("…입니다.일본식" 같은 생성물이 실제로 온다).
다만 숫자 사이의 점(1.5km)은 자르지 않는다 — 뒤가 숫자면 문장 끝이 아니다.
"""
import re as _re
match = _re.search(r"[.!?](?![0-9])", text or "")
return text[: match.end()].strip() if match else (text or "").strip()
def _get(row, key, default=None):
"""ORM 행이든 dict 든 같은 방식으로 읽는다(테스트가 가짜 행을 넣기 쉬우라고)."""
if isinstance(row, dict):
@ -805,8 +820,12 @@ def to_site_payload(place, snapshot: dict, site, version, links) -> dict:
paragraphs = [p.strip() for p in intro.split("\n") if p.strip()] if intro else []
narrative = {
"about": paragraphs,
# 요약은 첫 문단을 그대로 쓴다(요약문을 새로 생성하지 않는다).
"summary": paragraphs[0] if paragraphs else None,
# ★ 요약은 **첫 문장**이다. 문단이 아니다.
# 계약이 "요약 한 문장"이라 적어 뒀는데(shared/site-payload.ts) 첫 문단을 통째로
# 넣고 있었다. 그 값은 두 곳으로 나간다 — 히어로 아래 한 줄과 meta description.
# 문단이 들어가면 히어로가 세 문장을 이고 서고(실측 2026-09-10), meta description 은
# 검색 결과에서 잘린다. 문장을 새로 생성하지는 않는다 — 있는 글의 첫 문장을 뗄 뿐이다.
"summary": _first_sentence(paragraphs[0]) if paragraphs else None,
}
theme_spec = _DEFAULT_THEME.get(category) or _DEFAULT_THEME[PlaceCategory.LODGING.value]