fix: 이미지 태그 EASONING_EFFORT = "low" 지정
This commit is contained in:
parent
ac7e4bde9f
commit
9aa4e0a343
@ -6,6 +6,10 @@ from app.utils.prompts.schemas import SpaceType, Subject, Camera, MotionRecommen
|
||||
|
||||
import asyncio
|
||||
|
||||
# medium 추론은 출력 비용의 80%를 차지하고, minimal은 A/B 비교(4회)에서 narrative 점수가
|
||||
# welcome 단계로 편향되고 태그를 과다 선택하는 패턴이 반복돼 low로 고정한다.
|
||||
IMAGE_TAG_REASONING_EFFORT = "low"
|
||||
|
||||
async def autotag_image(image_url : str, industry: str = "") -> list[str]: #tag_list
|
||||
chatgpt = ChatgptService(model_type="gpt")
|
||||
image_input_data = {
|
||||
@ -17,7 +21,7 @@ async def autotag_image(image_url : str, industry: str = "") -> list[str]: #tag_
|
||||
"motion_recommended" : list(MotionRecommended)
|
||||
}
|
||||
|
||||
image_result = await chatgpt.generate_structured_output(image_autotag_prompt, image_input_data, image_url, False)
|
||||
image_result = await chatgpt.generate_structured_output(image_autotag_prompt, image_input_data, image_url, True, reasoning_effort=IMAGE_TAG_REASONING_EFFORT)
|
||||
return image_result
|
||||
|
||||
async def autotag_images(image_url_list : list[str], industry: str = "") -> list[dict]: #tag_list
|
||||
@ -31,7 +35,7 @@ async def autotag_images(image_url_list : list[str], industry: str = "") -> list
|
||||
"motion_recommended" : list(MotionRecommended)
|
||||
}for image_url in image_url_list]
|
||||
|
||||
image_result_tasks = [chatgpt.generate_structured_output(image_autotag_prompt, image_input_data, image_input_data['img_url'], False, silent = True) for image_input_data in image_input_data_list]
|
||||
image_result_tasks = [chatgpt.generate_structured_output(image_autotag_prompt, image_input_data, image_input_data['img_url'], True, silent = True, reasoning_effort=IMAGE_TAG_REASONING_EFFORT) for image_input_data in image_input_data_list]
|
||||
image_result_list: list[BaseModel | BaseException] = await asyncio.gather(*image_result_tasks, return_exceptions=True)
|
||||
MAX_RETRY = 2
|
||||
for _ in range(MAX_RETRY):
|
||||
@ -40,7 +44,7 @@ async def autotag_images(image_url_list : list[str], industry: str = "") -> list
|
||||
if not failed_idx:
|
||||
break
|
||||
retried = await asyncio.gather(
|
||||
*[chatgpt.generate_structured_output(image_autotag_prompt, image_input_data_list[i], image_input_data_list[i]['img_url'], False, silent=True) for i in failed_idx],
|
||||
*[chatgpt.generate_structured_output(image_autotag_prompt, image_input_data_list[i], image_input_data_list[i]['img_url'], True, silent=True, reasoning_effort=IMAGE_TAG_REASONING_EFFORT) for i in failed_idx],
|
||||
return_exceptions=True
|
||||
)
|
||||
for i, result in zip(failed_idx, retried):
|
||||
|
||||
@ -46,7 +46,20 @@ class ChatgptService:
|
||||
)
|
||||
case _:
|
||||
raise NotImplementedError(f"Unknown Provider : {model_type}")
|
||||
|
||||
|
||||
def _log_usage(self, response, model: str, output_format: type[BaseModel]) -> None:
|
||||
usage = getattr(response, "usage", None)
|
||||
if usage is None:
|
||||
return
|
||||
# 토큰 소모량 로깅 (필요 시 주석 해제)
|
||||
# cached = getattr(getattr(usage, "prompt_tokens_details", None), "cached_tokens", None) or 0
|
||||
# reasoning = getattr(getattr(usage, "completion_tokens_details", None), "reasoning_tokens", None) or 0
|
||||
# logger.info(
|
||||
# f"[ChatgptService({self.model_type})] usage model={model} output={output_format.__name__} "
|
||||
# f"prompt={usage.prompt_tokens} cached={cached} "
|
||||
# f"completion={usage.completion_tokens} reasoning={reasoning} total={usage.total_tokens}"
|
||||
# )
|
||||
|
||||
async def _call_pydantic_output(
|
||||
self,
|
||||
prompt : str,
|
||||
@ -113,9 +126,10 @@ class ChatgptService:
|
||||
self,
|
||||
prompt : str,
|
||||
output_format : BaseModel, #입력 output_format의 경우 Pydantic BaseModel Class를 상속한 Class 자체임에 유의할 것
|
||||
model : str,
|
||||
model : str,
|
||||
img_url : str,
|
||||
image_detail_high : bool) -> BaseModel:
|
||||
image_detail_high : bool,
|
||||
reasoning_effort : Optional[str] = None) -> BaseModel:
|
||||
content = []
|
||||
if img_url:
|
||||
content.append({
|
||||
@ -129,13 +143,16 @@ class ChatgptService:
|
||||
"type": "text",
|
||||
"text": prompt
|
||||
})
|
||||
# gpt-5.4 계열/Gemini 호환 엔드포인트는 허용 값이 다르거나 파라미터를 거부하므로 지정된 경우에만 전달
|
||||
extra_kwargs = {"reasoning_effort": reasoning_effort} if reasoning_effort else {}
|
||||
last_error = None
|
||||
for attempt in range(self.max_retries + 1):
|
||||
try:
|
||||
response = await self.client.beta.chat.completions.parse(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": content}],
|
||||
response_format=output_format
|
||||
response_format=output_format,
|
||||
**extra_kwargs,
|
||||
)
|
||||
except (ValidationError, json.JSONDecodeError) as e:
|
||||
# 모델이 스키마에 맞지 않는 JSON을 반환한 경우 (예: trailing characters).
|
||||
@ -148,6 +165,7 @@ class ChatgptService:
|
||||
if attempt < self.max_retries:
|
||||
logger.info(f"[ChatgptService({self.model_type})] Retrying request...")
|
||||
continue
|
||||
self._log_usage(response, model, output_format)
|
||||
# Response 디버그 로깅
|
||||
# logger.debug(f"[ChatgptService({self.model_type})] attempt: {attempt}")
|
||||
# logger.debug(f"[ChatgptService({self.model_type})] Response ID: {response.id}")
|
||||
@ -225,6 +243,7 @@ class ChatgptService:
|
||||
continue
|
||||
raise last_error
|
||||
|
||||
self._log_usage(response, model, output_format)
|
||||
choice = response.choices[0]
|
||||
if choice.finish_reason == "stop":
|
||||
return choice.message.parsed
|
||||
@ -242,7 +261,8 @@ class ChatgptService:
|
||||
input_data : dict,
|
||||
img_url : Optional[str] = None,
|
||||
img_detail_high : bool = False,
|
||||
silent : bool = True
|
||||
silent : bool = True,
|
||||
reasoning_effort : Optional[str] = None,
|
||||
) -> BaseModel:
|
||||
prompt_text = prompt.build_prompt(input_data, silent)
|
||||
|
||||
@ -253,5 +273,5 @@ class ChatgptService:
|
||||
# GPT API 호출
|
||||
#parsed = await self._call_structured_output_with_response_gpt_api(prompt_text, prompt.prompt_output, prompt.prompt_model)
|
||||
# parsed = await self._call_pydantic_output(prompt_text, prompt.prompt_output_class, prompt.prompt_model, img_url, img_detail_high)
|
||||
parsed = await self._call_pydantic_output_chat_completion(prompt_text, prompt.prompt_output_class, prompt.prompt_model, img_url, img_detail_high)
|
||||
parsed = await self._call_pydantic_output_chat_completion(prompt_text, prompt.prompt_output_class, prompt.prompt_model, img_url, img_detail_high, reasoning_effort)
|
||||
return parsed
|
||||
Loading…
Reference in New Issue
Block a user