o2o-triple-pick/backend/app/regenerate_ai.py

59 lines
1.8 KiB
Python

"""전체 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(only_missing=False)
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())