""" Stage 3 오케스트레이터 — 캐릭터 반응 + 정원 + 리캡 생성 입력: Stage 2 출력 (Stage2Output) 출력: Stage 3 출력 (Stage3Output) """ from src.common.schemas import Stage2Output, Stage3Output, Segment from src.stage3.character_mapping import map_characters from src.stage3.garden_logic import compute_garden_update from src.stage3.recap_generator import generate_recap_llm, generate_recap_fallback def process( stage2_output: Stage2Output, segments: list[Segment] | None = None, current_garden_level: int = 1, use_llm: bool = True, ) -> Stage3Output: """ Stage 3 메인 진입점. Args: stage2_output: Stage 2의 감정 분석 결과 segments: Stage 1의 발화 세그먼트 (리캡 생성에 사용, 없으면 fallback) current_garden_level: 현재 정원 레벨 (DB에서 가져옴) use_llm: True면 Claude API 리캡, False면 규칙 기반 fallback """ # 1. 캐릭터 반응 매핑 character_reactions = map_characters(stage2_output.speaker_summaries) # 2. 정원 성장 계산 garden_update = compute_garden_update( stage2_output.speaker_summaries, current_level=current_garden_level, ) # 3. 리캡 생성 if use_llm and segments: recap_card = generate_recap_llm(segments, stage2_output.speaker_summaries) else: recap_card = generate_recap_fallback(stage2_output.speaker_summaries) return Stage3Output( call_id=stage2_output.call_id, character_reactions=character_reactions, garden_update=garden_update, recap_card=recap_card, # Surface Stage2 data at top level for frontend convenience emotions=stage2_output.emotions, speaker_summaries=stage2_output.speaker_summaries, )