(prompt_dict)
| 63 | per_motion_metrics = [] |
| 64 | |
| 65 | def evaluate_entry(prompt_dict): |
| 66 | video_label = prompt_dict.get('prompt', 'unknown') |
| 67 | auxiliary_info = prompt_dict.get('auxiliary_info', []) |
| 68 | video_path = prompt_dict.get('evaluation_file', '') |
| 69 | motion_id = prompt_dict.get('id') |
| 70 | |
| 71 | if not os.path.exists(video_path): |
| 72 | return {"skip": True, "id": motion_id, "error": f"Missing video {video_path}"} |
| 73 | |
| 74 | try: |
| 75 | # Read video bytes directly - fps is now handled by Gemini API |
| 76 | with open(video_path, 'rb') as f: |
| 77 | video_bytes = f.read() |
| 78 | except Exception as exc: |
| 79 | return {"skip": True, "id": motion_id, "error": f"Video read error: {exc}"} |
| 80 | |
| 81 | |
| 82 | motion_list = auxiliary_info.copy() |
| 83 | if video_label not in motion_list: |
| 84 | motion_list.append(video_label) |
| 85 | random.shuffle(motion_list) |
| 86 | result_string = ", ".join(motion_list) |
| 87 | |
| 88 | try: |
| 89 | response = call_gemini_api(video_bytes, prompt + f'"{result_string}"', api_key, fps=vlm_fps) |
| 90 | |
| 91 | except Exception as exc: |
| 92 | return {"skip": True, "id": motion_id, "error": f"Gemini error: {exc}"} |
| 93 | |
| 94 | response = response.encode('utf-8').decode('utf-8').strip() |
| 95 | response_clean = response.split("\n\n", 1)[-1] |
| 96 | response_clean = response_clean.split(":", 1)[-1].strip() |
| 97 | # Remove trailing punctuation (., ", ', etc.) that may cause false negatives |
| 98 | response_clean = response_clean.rstrip('.,;:!?\'"') |
| 99 | |
| 100 | is_correct = response_clean.lower() == video_label.lower() |
| 101 | return { |
| 102 | "skip": False, |
| 103 | "id": motion_id, |
| 104 | "is_correct": is_correct, |
| 105 | "video_label": video_label, |
| 106 | "video_path": video_path, |
| 107 | "motion_list": motion_list, |
| 108 | "response_clean": response_clean, |
| 109 | "raw_response": response, |
| 110 | } |
| 111 | |
| 112 | with ThreadPoolExecutor(max_workers=gemini_workers) as executor: |
| 113 | futures = {executor.submit(evaluate_entry, prompt_dict): prompt_dict for prompt_dict in prompt_dict_ls} |
nothing calls this directly
no test coverage detected