feat(jamie-journal): implement LinkRecommender (procedure cross-linking suggestions)

This commit is contained in:
2026-03-29 07:29:11 +09:00
parent 311adaf06c
commit ccdd2c44ef

View File

@@ -388,8 +388,58 @@ class SpellingChecker:
class LinkRecommender: class LinkRecommender:
"""Recommends internal/external links and detects broken or missing ones.""" """Recommends internal/external links and detects broken or missing ones."""
PROCEDURE_MAP: Dict[str, Tuple[str, List[str]]] = {
'double_eyelid': ('쌍꺼풀 수술', ['쌍꺼풀', '매몰법', '절개법', '퀵매몰']),
'ptosis': ('안검하수 눈매교정', ['안검하수', '눈매교정', '졸린 눈', '눈매 교정']),
'under_eye_fat': ('눈밑 지방 재배치', ['눈밑 지방', '다크서클', '눈밑지방', '지방 재배치']),
'dual_epicanthoplasty': ('듀얼 트임', ['듀얼 트임', '앞트임', '뒤트임', '눈꼬리']),
'forehead_lift': ('내시경 이마거상술', ['이마거상', '이마리프팅', '이마 거상', '이마 리프팅']),
'brow_lift': ('내시경 눈썹거상술', ['눈썹거상', '눈썹리프팅', '눈썹 거상', '눈썹 리프팅']),
'sub_brow': ('눈썹밑 피부절개술', ['눈썹밑', '상안검', '눈꺼풀 처짐']),
'smas_lifting': ('스마스 리프팅', ['스마스', 'SMAS', '안면거상', '페이스리프트']),
'fat_graft': ('자가지방 이식', ['자가지방', '지방이식', '지방 이식', '지방 생착']),
'hifu': ('하이푸 리프팅', ['하이푸', 'HIFU', '초음파 리프팅']),
'cheek_lift': ('앞광대 리프팅', ['앞광대', '팔자 주름', '팔자주름', '광대 리프팅']),
'endotine': ('엔도타인 고정', ['엔도타인', 'endotine', '3점 고정']),
}
def _detect_main_topic(self, lines: List[str]) -> Optional[str]:
"""Scan first 10 lines to find the main procedure topic."""
opening_text = '\n'.join(lines[:10])
for topic_key, (display_name, keywords) in self.PROCEDURE_MAP.items():
for kw in keywords:
if kw in opening_text:
return topic_key
return None
def check(self, content: str) -> List[ValidationIssue]: def check(self, content: str) -> List[ValidationIssue]:
return [] issues: List[ValidationIssue] = []
lines = content.split('\n')
main_topic = self._detect_main_topic(lines)
for topic_key, (display_name, keywords) in self.PROCEDURE_MAP.items():
if topic_key == main_topic:
continue
for line_idx, line in enumerate(lines, start=1):
matched_kw = None
for kw in keywords:
if kw in line:
matched_kw = kw
break
if matched_kw:
issues.append(ValidationIssue(
checker='LinkRecommender',
issue_type='internal_link_opportunity',
severity='info',
line_number=line_idx,
matched_text=matched_kw,
message=f'"{matched_kw}" 언급 발견 — "{display_name}" 글로의 내부 링크를 고려하세요.',
suggestion=f'"{display_name}" 시술 페이지로 연결되는 앵커 텍스트 링크를 추가하세요.',
))
break # one recommendation per topic
return issues
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------