feat(ai): 전체 AI 예측 재생성 스크립트 추가

워커의 generate_ai_predictions() 를 즉시 1회 실행하는 수동 트리거.
미종료 경기 전부에 대해 GPT/Claude/Gemini 재생성(덮어쓰기).
실행: docker compose run --rm worker python -m app.regenerate_ai

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
develop
hbyang 2026-06-11 11:55:50 +09:00
parent 5f8858c978
commit 464145a234
1 changed files with 57 additions and 0 deletions

View File

@ -0,0 +1,57 @@
"""전체 AI 예측 재생성 — 수동 트리거.
워커의 generate_ai_predictions() 즉시 1 실행한다(매일 00:05 자동 생성과 동일 로직).
미종료(결과 미입력) 경기 전부에 대해 GPT/Claude/Gemini API 호출하여
ai_predictions 덮어쓴다(source='llm'). 없는/실패한 모델은 건너뛴다.
DB 접속은 backend/.env(DB_* 또는 DATABASE_URL) 따른다.
실행:
# Docker (운영 DB로 1회 실행)
docker compose run --rm worker python -m app.regenerate_ai
# 로컬
cd backend && python -m app.regenerate_ai
"""
from __future__ import annotations
import asyncio
import logging
from sqlalchemy import func, select
from .database import SessionLocal, init_db
from .models import AIPrediction, Match
from .worker import generate_ai_predictions
logging.basicConfig(level=logging.INFO)
log = logging.getLogger("triplepick.regen")
async def main() -> None:
await init_db() # 테이블 보장(idempotent)
async with SessionLocal() as db:
targets = (
await db.execute(
select(func.count())
.select_from(Match)
.where(Match.result_outcome.is_(None))
)
).scalar_one()
log.info("재생성 대상(미종료) 경기: %d", targets)
await generate_ai_predictions() # GPT/Claude/Gemini 실 API 호출 → 덮어쓰기
async with SessionLocal() as db:
rows = (
await db.execute(
select(AIPrediction.model, func.count())
.where(AIPrediction.source == "llm")
.group_by(AIPrediction.model)
)
).all()
log.info("재생성 완료. 모델별 LLM 예측 수: %s", {m: c for m, c in rows})
if __name__ == "__main__":
asyncio.run(main())