Diversify AI predictions via per-model analyst personas

GPT (data-driven), Claude (tactical/upset-aware), Gemini (attacking-minded)
each get a distinct perspective so the 3 picks genuinely diverge instead of
producing identical scorelines. Honest: still each model's own judgment.
Finished matches are untouched (generation filters result_outcome IS NULL).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
develop
hbyang 2026-06-12 17:33:59 +09:00
parent 0f055dace1
commit 1d406f6a4e
1 changed files with 29 additions and 6 deletions

View File

@ -32,10 +32,33 @@ class MatchContext:
kickoff: str # ISO
def _prompt(ctx: MatchContext) -> str:
# 모델별 분석 관점(페르소나) — 동일 경기라도 서로 다른 시각으로 보게 해
# 예측이 자연스럽게 갈리도록 한다(강제 분산이 아니라 진짜 판단의 다양화).
PERSONA = {
"GPT": (
"You are a DATA-DRIVEN analyst. Base your call on recent form, head-to-head, "
"FIFA ranking gaps and goals-scored/conceded trends. Be objective and "
"evidence-led; pick the scoreline the numbers most support."
),
"Claude": (
"You are a TACTICAL analyst. Focus on matchups, defensive organization, "
"midfield control and game-state. Take low-scoring games, tight margins and "
"genuine upset potential seriously — do not just rubber-stamp the favorite."
),
"Gemini": (
"You are an ATTACKING-MINDED analyst. Weigh momentum, attacking quality, "
"star players and scoring potential. Lean toward open, higher-scoring "
"scenarios when the talent and tempo justify it."
),
}
def _prompt(ctx: MatchContext, persona: str) -> str:
return (
f"You are a football match analyst. Predict the result of this "
f"2026 FIFA World Cup match.\n"
f"{persona}\n"
f"Predict the result of this 2026 FIFA World Cup match using YOUR perspective "
f"above. Judge independently — it is fine to differ from the obvious consensus "
f"pick when your perspective warrants it.\n"
f"Team A: {ctx.team_a}\nTeam B: {ctx.team_b}\n"
f"Venue: {ctx.venue}\nKickoff: {ctx.kickoff}\n"
f"Important: World Cup group-stage matches are played at NEUTRAL venues. "
@ -96,7 +119,7 @@ async def predict_gpt(ctx: MatchContext) -> dict:
model=settings.openai_model,
messages=[
{"role": "system", "content": "You output only valid JSON."},
{"role": "user", "content": _prompt(ctx)},
{"role": "user", "content": _prompt(ctx, PERSONA["GPT"])},
],
response_format={"type": "json_object"},
)
@ -116,7 +139,7 @@ async def predict_claude(ctx: MatchContext) -> dict:
return await client.messages.create(
model=settings.anthropic_model,
max_tokens=1024,
messages=[{"role": "user", "content": _prompt(ctx)}],
messages=[{"role": "user", "content": _prompt(ctx, PERSONA["Claude"])}],
**extra,
)
@ -143,7 +166,7 @@ async def predict_gemini(ctx: MatchContext) -> dict:
client = genai.Client(api_key=settings.google_api_key)
resp = await client.aio.models.generate_content(
model=settings.google_model,
contents=_prompt(ctx),
contents=_prompt(ctx, PERSONA["Gemini"]),
config=types.GenerateContentConfig(response_mime_type="application/json"),
)
return _normalize(json.loads(resp.text or "{}"))