diff --git a/src/api/static/index.html b/src/api/static/index.html index 143a49f..93f617c 100644 --- a/src/api/static/index.html +++ b/src/api/static/index.html @@ -3249,7 +3249,7 @@

데이터 라이선스

}, 60); if(d.scores) requestAnimationFrame(function(){drawRadar(d.scores);}); var mapPoisFinal = (d.poi_info||[]).filter(function(p){return p.lat&&p.lng&&p.lat!==37.5665;}); - if (mapPoisFinal.length) requestAnimationFrame(function(){initMap(mapPoisFinal, d.optimal_route, d.congestion_warnings);}); + if (mapPoisFinal.length) initMap(mapPoisFinal, d.optimal_route, d.congestion_warnings); } function animateScore(target) { diff --git a/src/data/models.py b/src/data/models.py index e6814fe..c272868 100644 --- a/src/data/models.py +++ b/src/data/models.py @@ -253,7 +253,7 @@ def hard_fail_score_cap(self) -> "ValidationResult": class Settings(BaseSettings): anthropic_api_key: str = "" - claude_model: str = "claude-sonnet-4-6" + claude_model: str = "claude-haiku-4-5" tour_api_key: str = "" kakao_rest_api_key: str = "" kakao_mobility_key: str = "" diff --git a/src/explain/explain_engine.py b/src/explain/explain_engine.py index 3a1439c..8fe248e 100644 --- a/src/explain/explain_engine.py +++ b/src/explain/explain_engine.py @@ -35,7 +35,7 @@ _ANTHROPIC_AVAILABLE = False # ── LLM 설정 ────────────────────────────────────────────────────────────── -DEFAULT_MODEL: str = "claude-sonnet-4-6" +DEFAULT_MODEL: str = "claude-haiku-4-5" DEFAULT_TIMEOUT_SEC: float = 20.0 DEFAULT_MAX_TOKENS: int = 2500 diff --git a/src/explain/plan_extractor.py b/src/explain/plan_extractor.py index c22976c..2b67265 100644 --- a/src/explain/plan_extractor.py +++ b/src/explain/plan_extractor.py @@ -24,7 +24,7 @@ except ImportError: _ANTHROPIC_AVAILABLE = False -DEFAULT_MODEL: str = "claude-sonnet-4-6" +DEFAULT_MODEL: str = "claude-haiku-4-5" DEFAULT_TIMEOUT_SEC: float = 45.0 DEFAULT_MAX_TOKENS: int = 4000 @@ -148,7 +148,11 @@ def extract_from_document(self, data: bytes, media_type: str) -> ParsedPlanRespo "type": block_type, "source": {"type": "base64", "media_type": media_type, "data": b64}, }, - {"type": "text", "text": _USER_PREFIX_DOC}, + { + "type": "text", + "text": _USER_PREFIX_DOC, + "cache_control": {"type": "ephemeral"}, + }, ] return self._call(content) diff --git a/src/scoring/theme_alignment.py b/src/scoring/theme_alignment.py index 45284cb..ecb0b31 100644 --- a/src/scoring/theme_alignment.py +++ b/src/scoring/theme_alignment.py @@ -39,7 +39,7 @@ PENALTY_CRIT: int = 20 # ── LLM 설정 ───────────────────────────────────────────────────────── -DEFAULT_MODEL: str = "claude-sonnet-4-6" +DEFAULT_MODEL: str = "claude-haiku-4-5" DEFAULT_TIMEOUT_SEC: float = 10.0 DEFAULT_MAX_TOKENS: int = 500 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..66a87a9 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,12 @@ +"""테스트 전역 fixture. + +src.api.main은 import 시점에 .env를 읽어 os.environ에 ANTHROPIC_API_KEY를 주입한다. +그 모듈을 import하는 테스트가 먼저 수집되면 이후 테스트의 "키 없음" 케이스가 +실행 순서에 따라 랜덤하게 깨진다 — 매 테스트마다 강제로 지워 격리한다. +""" +import pytest + + +@pytest.fixture(autouse=True) +def _clean_anthropic_api_key(monkeypatch): + monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)