|
8 | 8 | from unittest.mock import MagicMock, patch |
9 | 9 |
|
10 | 10 | from argus.captioner import ( |
| 11 | + caption_frame, |
11 | 12 | caption_output_items, |
12 | 13 | match_ollama_model, |
13 | 14 | normalize_clip_title, |
@@ -159,6 +160,63 @@ def test_summarize_captions_rejects_missing_title(self, ollama_chat_mock) -> Non |
159 | 160 | self.assertEqual(result["status"], "error") |
160 | 161 | self.assertIn("required fields", result["reason"]) |
161 | 162 |
|
| 163 | + @patch("argus.captioner.ollama_chat") |
| 164 | + def test_caption_frame_includes_options_for_gemma4(self, ollama_chat_mock) -> None: |
| 165 | + ollama_chat_mock.return_value = { |
| 166 | + "message": { |
| 167 | + "content": json.dumps( |
| 168 | + { |
| 169 | + "short_caption": "A test frame.", |
| 170 | + "tags": ["tag"] * 40, |
| 171 | + "visible_text": [], |
| 172 | + } |
| 173 | + ) |
| 174 | + } |
| 175 | + } |
| 176 | + |
| 177 | + with tempfile.TemporaryDirectory() as temp_dir: |
| 178 | + image_path = Path(temp_dir) / "frame.jpg" |
| 179 | + image_path.write_bytes(b"\xff\xd8\xff") |
| 180 | + result = caption_frame( |
| 181 | + image_path, |
| 182 | + model="gemma4:latest", |
| 183 | + ollama_host="http://localhost:11434", |
| 184 | + ) |
| 185 | + |
| 186 | + self.assertEqual(result["status"], "ok") |
| 187 | + payload = ollama_chat_mock.call_args[0][0] |
| 188 | + self.assertIn("options", payload) |
| 189 | + self.assertEqual(payload["options"]["temperature"], 1.0) |
| 190 | + self.assertEqual(payload["options"]["top_p"], 0.95) |
| 191 | + self.assertEqual(payload["options"]["top_k"], 64) |
| 192 | + |
| 193 | + @patch("argus.captioner.ollama_chat") |
| 194 | + def test_caption_frame_omits_options_for_non_gemma4(self, ollama_chat_mock) -> None: |
| 195 | + ollama_chat_mock.return_value = { |
| 196 | + "message": { |
| 197 | + "content": json.dumps( |
| 198 | + { |
| 199 | + "short_caption": "A test frame.", |
| 200 | + "tags": ["tag"] * 40, |
| 201 | + "visible_text": [], |
| 202 | + } |
| 203 | + ) |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + with tempfile.TemporaryDirectory() as temp_dir: |
| 208 | + image_path = Path(temp_dir) / "frame.jpg" |
| 209 | + image_path.write_bytes(b"\xff\xd8\xff") |
| 210 | + result = caption_frame( |
| 211 | + image_path, |
| 212 | + model="gemma3", |
| 213 | + ollama_host="http://localhost:11434", |
| 214 | + ) |
| 215 | + |
| 216 | + self.assertEqual(result["status"], "ok") |
| 217 | + payload = ollama_chat_mock.call_args[0][0] |
| 218 | + self.assertNotIn("options", payload) |
| 219 | + |
162 | 220 | def test_normalize_clip_title_truncates_to_max_length(self) -> None: |
163 | 221 | long_title = "word " * 40 |
164 | 222 | out = normalize_clip_title(long_title, max_len=100) |
|
0 commit comments