From d8db7ed0f4d4016f200ba50f5e58f93c28c4fb88 Mon Sep 17 00:00:00 2001 From: hbyang Date: Thu, 11 Jun 2026 16:17:12 +0900 Subject: [PATCH] =?UTF-8?q?perf(ai):=20=EC=9E=90=EB=8F=99=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9D=80=20=EB=B9=84=EC=96=B4=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EC=98=88=EC=B8=A1=EB=A7=8C=20=EC=B1=84=EC=9A=B0=EB=8F=84?= =?UTF-8?q?=EB=A1=9D(=EA=B8=B0=EC=A1=B4=20=EB=B3=B4=EC=A1=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate_ai_predictions(only_missing=True 기본): 이미 있는 (경기×모델) 예측은 보존하고 누락분만 생성 — 매일/기동/새 경기 시 기존 데이터 불변, API 비용↓, 실패했던 모델만 자동 보충. 수동 재생성 스크립트는 강제 전체(only_missing=False). Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/app/regenerate_ai.py | 3 ++- backend/app/worker.py | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/backend/app/regenerate_ai.py b/backend/app/regenerate_ai.py index 7f71cfc..0f887cd 100644 --- a/backend/app/regenerate_ai.py +++ b/backend/app/regenerate_ai.py @@ -40,7 +40,8 @@ async def main() -> None: ).scalar_one() log.info("재생성 대상(미종료) 경기: %d", targets) - await generate_ai_predictions() # GPT/Claude/Gemini 실 API 호출 → 덮어쓰기 + # 수동 트리거 = 전부 강제 재생성(덮어쓰기). 프롬프트 수정 후 갱신 등에 사용. + await generate_ai_predictions(only_missing=False) async with SessionLocal() as db: rows = ( diff --git a/backend/app/worker.py b/backend/app/worker.py index b44ac47..e3823f2 100644 --- a/backend/app/worker.py +++ b/backend/app/worker.py @@ -75,7 +75,13 @@ async def tick_status() -> None: # ── 2) AI 예측 생성 (실연동) ──────────────────────────────── -async def generate_ai_predictions() -> None: +async def generate_ai_predictions(only_missing: bool = True) -> None: + """미종료 경기의 AI 예측 생성. + + only_missing=True(기본): 이미 있는 (경기×모델) 예측은 보존하고 **비어 있는 것만** + 생성한다(직전에 실패/누락된 모델만 채워짐 — API 비용↓, 예측 안정). + only_missing=False: 전부 재생성(덮어쓰기) — 수동 재생성 스크립트용. + """ async with SessionLocal() as db: matches = ( await db.execute( @@ -93,6 +99,9 @@ async def generate_ai_predictions() -> None: kickoff=m.kickoff_at.isoformat(), ) for model, fn in PROVIDERS.items(): + pred = next((p for p in m.predictions if p.model == model), None) + if only_missing and pred is not None: + continue # 이미 작성됨 — 보존, API 호출 안 함 try: data = await fn(ctx) except ProviderUnavailable as e: @@ -102,8 +111,7 @@ async def generate_ai_predictions() -> None: log.error("AI %s failed for %s: %s", model, m.match_id, e) continue - pred = next((p for p in m.predictions if p.model == model), None) - if pred is None: + if pred is None: # 신규 — 위에서 못 찾았으면 생성 pred = AIPrediction(match_id=m.match_id, model=model) db.add(pred) m.predictions.append(pred)