수집한 객실·이용 정보가 발행 화면에 연결되지 않던 경로를 보완하고, 숙소 소개와 지역 맛집 표시를 개선한다. - NOL 브라우저 수집 어댑터와 수집·반영 스크립트 추가 - 크롤링 fact 즉시 노출 및 직접 입력·정정값 보호 - 이용안내 항목별 구조화와 기존 표 연결, 원문 UI 비표시 - 군산 한일옥 고정 등록과 지역 맛집 탐색·보강 경로 추가 - 숙소 소개 요약, 히어로 문구, 지역 콘텐츠·목업 표시 개선 검증: 작업 트리 기준 site 타입·린트·빌드 및 안내 렌더링 테스트 통과, PC·모바일 화면 확인. 스테이징 diff 공백 검사 통과. 사용자 요청에 따라 현재 스테이징된 55개 파일만 포함하며 미스테이징 문서·테스트 등은 제외.
58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
"""지역명으로 맛집 후보 이름을 찾는다.
|
|
|
|
★ services/external/perplexity.py(채널 발견: 단일 업소 → URL)와는 다른 용도다 —
|
|
여기는 "이 지역에 뭐가 있나"를 묻는 지역 목록 검색이다. 원칙은 같다:
|
|
Perplexity 응답을 사실로 쓰지 않는다. 이름만 후보로 받고, 실제 값은 이후
|
|
네이버 크롤링(NaverPlaceAdapter)이 확정한다.
|
|
"""
|
|
import json
|
|
|
|
from common.logger import LOG
|
|
from services.llm.perplexity import DEFAULT_MAX_TOKENS, DEFAULT_MODEL, PerplexityError, call
|
|
from services.prompts.restaurant_search import RESPONSE_SCHEMA, SYSTEM_PROMPT, build_prompt
|
|
|
|
MAX_RESULTS = 10
|
|
|
|
|
|
def _parse_names(payload: dict) -> list[str]:
|
|
choices = payload.get("choices") or []
|
|
if not choices or not isinstance(choices[0], dict):
|
|
return []
|
|
content = ((choices[0].get("message") or {}).get("content")) or ""
|
|
try:
|
|
doc = json.loads(content)
|
|
except (json.JSONDecodeError, TypeError):
|
|
LOG.w("[restaurant_discovery] 구조화 출력 파싱 실패")
|
|
return []
|
|
names = doc.get("restaurants")
|
|
if not isinstance(names, list):
|
|
return []
|
|
return [str(n).strip() for n in names if str(n or "").strip()][:MAX_RESULTS]
|
|
|
|
|
|
async def search_region_restaurants(
|
|
region_label: str, *, model: str = DEFAULT_MODEL, client=None,
|
|
) -> list[str]:
|
|
"""지역명으로 맛집 상위 10곳의 이름만 받는다.
|
|
|
|
실패(미설정·타임아웃·5xx)하면 빈 목록 — 호출측이 TourAPI 결과만으로 계속 진행한다.
|
|
"""
|
|
if not (region_label or "").strip():
|
|
return []
|
|
body = {
|
|
"model": model,
|
|
"messages": [
|
|
{"role": "system", "content": SYSTEM_PROMPT},
|
|
{"role": "user", "content": build_prompt(region_label)},
|
|
],
|
|
"max_tokens": DEFAULT_MAX_TOKENS,
|
|
"temperature": 0,
|
|
"response_format": RESPONSE_SCHEMA,
|
|
}
|
|
try:
|
|
payload = await call(body, client=client)
|
|
except PerplexityError as ex:
|
|
LOG.w(f"[restaurant_discovery] '{region_label}' 검색 실패: {ex}")
|
|
return []
|
|
return _parse_names(payload)
|