diff --git a/src/BowongModalFunctions/models/web_model.py b/src/BowongModalFunctions/models/web_model.py index 169ee54..66505e4 100644 --- a/src/BowongModalFunctions/models/web_model.py +++ b/src/BowongModalFunctions/models/web_model.py @@ -504,6 +504,7 @@ class GeminiRequest(BaseFFMPEGTaskRequest): end_time: str = Field(default="00:20:00.000", description="结束时间(hls)") options: FFMPEGSliceOptions = Field(default=FFMPEGSliceOptions(), description="输出质量选项") scale: float = Field(default=0.85, description="视频尺寸缩放倍率") + last_product_text:str = Field(default="", description="上一段视频结尾介绍的商品以及标签") @field_validator('media_hls_url', mode='before') @classmethod diff --git a/src/BowongModalFunctions/router/google.py b/src/BowongModalFunctions/router/google.py index 4611d46..62b681c 100644 --- a/src/BowongModalFunctions/router/google.py +++ b/src/BowongModalFunctions/router/google.py @@ -206,7 +206,7 @@ async def inference_gemini( x_baggage=sentry_sdk.get_baggage()) if headers.x_trace_id is None else SentryTransactionInfo(x_trace_id=headers.x_trace_id, x_baggage=headers.x_baggage), - data.webhook, 3, data.scale) + data.webhook, 3, data.scale, data.last_product_text) return ModalTaskResponse(success=True, taskId=fn_call.object_id) diff --git a/src/BowongModalFunctions/utils/TimeUtils.py b/src/BowongModalFunctions/utils/TimeUtils.py index cd114b6..4ed99bb 100644 --- a/src/BowongModalFunctions/utils/TimeUtils.py +++ b/src/BowongModalFunctions/utils/TimeUtils.py @@ -49,8 +49,18 @@ def parse_time(time_str): dt = datetime.strptime(time_str, '%M:%S:%f') # 将小时设为0,只保留分钟和秒 parsed_time = datetime.combine(dt.date(), dt.time().replace(hour=0)) + elif re.match(r"^\d{2}:\d{2}$",time_str): + # 如果失败,尝试 MM:SS:fff 格式 + dt = datetime.strptime(time_str, '%M:%S') + # 将小时设为0,只保留分钟和秒 + parsed_time = datetime.combine(dt.date(), dt.time().replace(hour=0)) + elif re.match(r"^\d{2}\.\d{2}$",time_str): + # 如果失败,尝试 MM:SS:fff 格式 + dt = datetime.strptime(time_str, '%M.%S') + # 将小时设为0,只保留分钟和秒 + parsed_time = datetime.combine(dt.date(), dt.time().replace(hour=0)) else: - logger.error(f"转换时间格式失败 {time_str}") + raise RuntimeError(f"转换时间格式失败 {time_str}") return parsed_time diff --git a/src/cluster/video_apps/hls_slice_inference.py b/src/cluster/video_apps/hls_slice_inference.py index 2a90e04..e6d9959 100644 --- a/src/cluster/video_apps/hls_slice_inference.py +++ b/src/cluster/video_apps/hls_slice_inference.py @@ -48,7 +48,8 @@ with downloader_image.imports(): sentry_trace: SentryTransactionInfo, webhook: WebhookNotify = None, retry_time: int = 3, - scale:float = 0.9 + scale:float = 0.9, + last_product_text="" ): logger.info( f"region {os.environ.get('MODAL_REGION', 'unknown')}, provider {os.environ.get('MODAL_CLOUD_PROVIDER', 'unknown')}") @@ -78,7 +79,8 @@ with downloader_image.imports(): f"\nproduct_grid_list || {json.dumps(product_grid_list, ensure_ascii=False, indent=2)}, " f"\nproduct_list || {json.dumps(product_list, ensure_ascii=False, indent=2)}" f"\noptions || {options.model_dump_json()}, " - f"\nscale || {scale}") + f"\nscale || {scale}" + f"\nlast_product_text || {last_product_text}") client = GoogleAuthUtils.GoogleGenaiClient( cloudflare_project_id="67720b647ff2b55cf37ba3ef9e677083", @@ -388,12 +390,6 @@ with downloader_image.imports(): if len(product_list) == 0: logger.error("商品列表为空, 退出推理") raise Exception("商品列表为空, 退出推理") - product_title_list = [] - if isinstance(product_list[0], dict): - for product in product_list: - product_title_list.append(product["title"]) - else: - product_title_list = product_list # 2、切20分钟的条 logger.info("2、开始截取指定视频") @@ -438,7 +434,7 @@ with downloader_image.imports(): text=Template(IMAGE_PRODUCT_IDENTIFICATION_PROMPT.prompt if isinstance(IMAGE_PRODUCT_IDENTIFICATION_PROMPT, TextPromptClient) else IMAGE_PRODUCT_IDENTIFICATION_PROMPT).render( - PRODUCT_LIST=GeminiFirstStagePromptVariables(product_list=product_title_list).product_list_xml) + PRODUCT_LIST=GeminiFirstStagePromptVariables(product_list=product_list).product_list_xml) ) ) resp, resp_code = client.generate_content(model_id="gemini-2.5-flash", @@ -484,7 +480,8 @@ with downloader_image.imports(): text=Template(VIDEO_TIMELINE_ANALYSIS_PROMPT.prompt if isinstance(VIDEO_TIMELINE_ANALYSIS_PROMPT, TextPromptClient) else VIDEO_TIMELINE_ANALYSIS_PROMPT).render( - IDENTIFIED_PRODUCTS=GeminiSecondStagePromptVariables(product_json_list=identified_products).product_json_list_xml) + IDENTIFIED_PRODUCTS=GeminiSecondStagePromptVariables(product_json_list=identified_products).product_json_list_xml, + LAST_PRODUCT_TEXT=last_product_text) ) ) resp, resp_code = client.generate_content(model_id="gemini-2.5-flash",