37 lines
1.4 KiB
Python
37 lines
1.4 KiB
Python
"""② 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")
|