feat(curator): pipeline 4계층 직렬화 + retrospective 컨텍스트 + N=30

This commit is contained in:
2026-05-11 08:51:07 +09:00
parent ff3134b838
commit e14278ec69

View File

@@ -9,6 +9,7 @@ from ..config import ANTHROPIC_API_KEY, LOTTO_CURATOR_MODEL
from .. import service_proxy from .. import service_proxy
from .prompt import SYSTEM_PROMPT, build_user_message from .prompt import SYSTEM_PROMPT, build_user_message
from .schema import validate_response from .schema import validate_response
from .retrospective import build_retrospective
API_URL = "https://api.anthropic.com/v1/messages" API_URL = "https://api.anthropic.com/v1/messages"
@@ -36,12 +37,12 @@ async def _call_claude(user_text: str, feedback: str = "") -> tuple[dict, dict]:
user_text = f"이전 응답이 다음 이유로 거절됨: {feedback}\n올바른 스키마로 다시 응답.\n\n{user_text}" user_text = f"이전 응답이 다음 이유로 거절됨: {feedback}\n올바른 스키마로 다시 응답.\n\n{user_text}"
payload = { payload = {
"model": LOTTO_CURATOR_MODEL, "model": LOTTO_CURATOR_MODEL,
"max_tokens": 4096, "max_tokens": 8192, # 4계층 20세트 + narrative + retrospective 수용
"system": system_blocks, "system": system_blocks,
"messages": [{"role": "user", "content": [{"type": "text", "text": user_text}]}], "messages": [{"role": "user", "content": [{"type": "text", "text": user_text}]}],
} }
started = time.monotonic() started = time.monotonic()
async with httpx.AsyncClient(timeout=120) as client: async with httpx.AsyncClient(timeout=180) as client: # 큰 응답 → 시간 여유
r = await client.post(API_URL, headers=headers, json=payload) r = await client.post(API_URL, headers=headers, json=payload)
r.raise_for_status() r.raise_for_status()
resp = r.json() resp = r.json()
@@ -68,16 +69,19 @@ async def _call_claude(user_text: str, feedback: str = "") -> tuple[dict, dict]:
async def curate_weekly(source: str = "auto") -> Dict[str, Any]: async def curate_weekly(source: str = "auto") -> Dict[str, Any]:
cand_resp = await service_proxy.lotto_candidates(n=20) cand_resp = await service_proxy.lotto_candidates(n=30) # ← 30 으로 확장
draw_no = cand_resp["draw_no"] draw_no = cand_resp["draw_no"]
candidates = cand_resp["candidates"] candidates = cand_resp["candidates"]
context = await service_proxy.lotto_context() context = await service_proxy.lotto_context()
retrospective = await build_retrospective(draw_no)
user_text = build_user_message(draw_no, candidates, { user_text = build_user_message(draw_no, candidates, {
"hot_numbers": context.get("hot_numbers", []), "hot_numbers": context.get("hot_numbers", []),
"cold_numbers": context.get("cold_numbers", []), "cold_numbers": context.get("cold_numbers", []),
"last_draw_summary": context.get("last_draw_summary", ""), "last_draw_summary": context.get("last_draw_summary", ""),
"my_recent_performance": context.get("my_recent_performance", []), "my_recent_performance": context.get("my_recent_performance", []),
"retrospective": retrospective,
}) })
candidate_numbers = [c["numbers"] for c in candidates] candidate_numbers = [c["numbers"] for c in candidates]
@@ -101,8 +105,14 @@ async def curate_weekly(source: str = "auto") -> Dict[str, Any]:
payload = { payload = {
"draw_no": draw_no, "draw_no": draw_no,
"picks": [p.model_dump() for p in validated.picks], "picks": {
"core": [p.model_dump() for p in validated.core_picks],
"bonus": [p.model_dump() for p in validated.bonus_picks],
"extended": [p.model_dump() for p in validated.extended_picks],
"pool": [p.model_dump() for p in validated.pool_picks],
},
"narrative": validated.narrative.model_dump(), "narrative": validated.narrative.model_dump(),
"tier_rationale": validated.tier_rationale.model_dump(),
"confidence": validated.confidence, "confidence": validated.confidence,
"model": LOTTO_CURATOR_MODEL, "model": LOTTO_CURATOR_MODEL,
"tokens_input": usage_total["input"], "tokens_input": usage_total["input"],
@@ -118,4 +128,5 @@ async def curate_weekly(source: str = "auto") -> Dict[str, Any]:
"draw_no": draw_no, "draw_no": draw_no,
"confidence": validated.confidence, "confidence": validated.confidence,
"tokens": {"input": usage_total["input"], "output": usage_total["output"]}, "tokens": {"input": usage_total["input"], "output": usage_total["output"]},
"payload": payload, # 텔레그램 알림용
} }