"""② split 부속 — cast 태그 섹션에서 배우 이름을 읽는다. NOL meta에는 출연진 필드가 아예 없어 상세페이지 이미지에서 읽는 수밖에 없다. 캐스트는 영상의 필수 재료가 아니므로 실패해도 멈추지 않고 source로 남긴다. """ from collections.abc import Sequence from answers.cast_answer import CastAnswer from models.cast import CastExtraction from models.detail_section import DetailSection from settings import settings from utils.common_llm import StructuredLLM from utils.image import to_data_uri from utils.prompt import load_prompt CAST_TAG = "cast" CAST_IMAGE_MAX_SIZE = (640, 2000) # 세로 4천px짜리가 온다 MAX_NAMES = 12 EXTRACT_CAST_PROMPT = load_prompt("extract_cast") cast_llm = StructuredLLM("gpt-4o", settings.chatgpt_api_key) async def extract_cast(sections: Sequence[DetailSection]) -> CastExtraction: section = next((item for item in sections if item.tag == CAST_TAG), None) if section is None: return CastExtraction() try: answer = await cast_llm.ask_with_images( CastAnswer, EXTRACT_CAST_PROMPT, [("출연진 구간:", to_data_uri(section.image, CAST_IMAGE_MAX_SIZE))]) except Exception: return CastExtraction(source="failed") names = [name.strip() for name in answer.cast if name.strip()][:MAX_NAMES] return CastExtraction(names=names, source="vlm")