perf(ai): 자동 생성은 비어있는 예측만 채우도록(기존 보존)

generate_ai_predictions(only_missing=True 기본): 이미 있는 (경기×모델)
예측은 보존하고 누락분만 생성 — 매일/기동/새 경기 시 기존 데이터 불변,
API 비용↓, 실패했던 모델만 자동 보충. 수동 재생성 스크립트는 강제 전체(only_missing=False).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
develop
hbyang 2026-06-11 16:17:12 +09:00
parent 4244518ffd
commit d8db7ed0f4
2 changed files with 13 additions and 4 deletions

View File

@ -40,7 +40,8 @@ async def main() -> None:
).scalar_one() ).scalar_one()
log.info("재생성 대상(미종료) 경기: %d", targets) log.info("재생성 대상(미종료) 경기: %d", targets)
await generate_ai_predictions() # GPT/Claude/Gemini 실 API 호출 → 덮어쓰기 # 수동 트리거 = 전부 강제 재생성(덮어쓰기). 프롬프트 수정 후 갱신 등에 사용.
await generate_ai_predictions(only_missing=False)
async with SessionLocal() as db: async with SessionLocal() as db:
rows = ( rows = (

View File

@ -75,7 +75,13 @@ async def tick_status() -> None:
# ── 2) AI 예측 생성 (실연동) ──────────────────────────────── # ── 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: async with SessionLocal() as db:
matches = ( matches = (
await db.execute( await db.execute(
@ -93,6 +99,9 @@ async def generate_ai_predictions() -> None:
kickoff=m.kickoff_at.isoformat(), kickoff=m.kickoff_at.isoformat(),
) )
for model, fn in PROVIDERS.items(): 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: try:
data = await fn(ctx) data = await fn(ctx)
except ProviderUnavailable as e: 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) log.error("AI %s failed for %s: %s", model, m.match_id, e)
continue 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) pred = AIPrediction(match_id=m.match_id, model=model)
db.add(pred) db.add(pred)
m.predictions.append(pred) m.predictions.append(pred)