Skip to content

Commit 26bdba5

Browse files
committed
perf: optimal option when gemma4 model is used
1 parent 86d3c53 commit 26bdba5

3 files changed

Lines changed: 102 additions & 1 deletion

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,6 @@ serve: ## Web UI: make serve [OUTPUT_DIR=...] [HOST=...] [PORT=...] [ARGS="--ope
8686

8787
run: ## Full pipeline: make run [SOURCE=...] [OUTPUT_DIR=...] [MODEL=...] [ARGS="..."]
8888
$(ARGUS) run $(SOURCE) --output-dir $(OUTPUT_DIR) $(arg_model) $(arg_ollama_host) $(ARGS)
89+
90+
test: ## Run tests: make test
91+
PYTHONPATH=src python3 -m unittest tests.test_scanner -v

src/argus/captioner.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,19 @@ def caption_frame(image_path: Path, *, model: str, ollama_host: str) -> dict:
234234
"messages": [
235235
{
236236
"role": "user",
237-
"content": FRAME_CAPTION_PROMPT,
238237
"images": [encoded],
238+
"content": FRAME_CAPTION_PROMPT,
239239
}
240240
],
241241
"format": "json",
242242
"stream": False,
243243
}
244+
if base_model_name(model) == "gemma4":
245+
payload["options"] = {
246+
"temperature": 1.0,
247+
"top_p": 0.95,
248+
"top_k": 64,
249+
}
244250

245251
try:
246252
response = ollama_chat(payload, ollama_host=ollama_host)
@@ -303,6 +309,12 @@ def summarize_captions(
303309
"format": "json",
304310
"stream": False,
305311
}
312+
if base_model_name(model) == "gemma4":
313+
payload["options"] = {
314+
"temperature": 1.0,
315+
"top_p": 0.95,
316+
"top_k": 64,
317+
}
306318

307319
try:
308320
response = ollama_chat(payload, ollama_host=ollama_host)

tests/test_scanner.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from unittest.mock import MagicMock, patch
99

1010
from argus.captioner import (
11+
caption_frame,
1112
caption_output_items,
1213
match_ollama_model,
1314
normalize_clip_title,
@@ -141,6 +142,32 @@ def test_summarize_captions_parses_json_response(self, ollama_chat_mock) -> None
141142
self.assertLessEqual(len(result["title"]), 100)
142143
self.assertEqual(result["summary"], "Wide exterior drone footage.")
143144
self.assertEqual(result["suggested_tags"], ["drone", "aerial"])
145+
payload = ollama_chat_mock.call_args[0][0]
146+
self.assertNotIn("options", payload)
147+
148+
@patch("argus.captioner.ollama_chat")
149+
def test_summarize_captions_includes_options_for_gemma4(self, ollama_chat_mock) -> None:
150+
ollama_chat_mock.return_value = {
151+
"message": {
152+
"content": (
153+
'{"title":"Short title","summary":"Wide exterior drone footage here.",'
154+
'"suggested_tags":["a","b","c"]}'
155+
)
156+
}
157+
}
158+
159+
result = summarize_captions(
160+
[{"timestamp_seconds": 1.0, "caption": "Drone shot over a road."}],
161+
model="gemma4",
162+
ollama_host="http://localhost:11434",
163+
)
164+
165+
self.assertEqual(result["status"], "ok")
166+
payload = ollama_chat_mock.call_args[0][0]
167+
self.assertIn("options", payload)
168+
self.assertEqual(payload["options"]["temperature"], 1.0)
169+
self.assertEqual(payload["options"]["top_p"], 0.95)
170+
self.assertEqual(payload["options"]["top_k"], 64)
144171

145172
@patch("argus.captioner.ollama_chat")
146173
def test_summarize_captions_rejects_missing_title(self, ollama_chat_mock) -> None:
@@ -158,6 +185,65 @@ def test_summarize_captions_rejects_missing_title(self, ollama_chat_mock) -> Non
158185

159186
self.assertEqual(result["status"], "error")
160187
self.assertIn("required fields", result["reason"])
188+
payload = ollama_chat_mock.call_args[0][0]
189+
self.assertNotIn("options", payload)
190+
191+
@patch("argus.captioner.ollama_chat")
192+
def test_caption_frame_includes_options_for_gemma4(self, ollama_chat_mock) -> None:
193+
ollama_chat_mock.return_value = {
194+
"message": {
195+
"content": json.dumps(
196+
{
197+
"short_caption": "A test frame.",
198+
"tags": ["tag"] * 40,
199+
"visible_text": [],
200+
}
201+
)
202+
}
203+
}
204+
205+
with tempfile.TemporaryDirectory() as temp_dir:
206+
image_path = Path(temp_dir) / "frame.jpg"
207+
image_path.write_bytes(b"\xff\xd8\xff")
208+
result = caption_frame(
209+
image_path,
210+
model="gemma4:latest",
211+
ollama_host="http://localhost:11434",
212+
)
213+
214+
self.assertEqual(result["status"], "ok")
215+
payload = ollama_chat_mock.call_args[0][0]
216+
self.assertIn("options", payload)
217+
self.assertEqual(payload["options"]["temperature"], 1.0)
218+
self.assertEqual(payload["options"]["top_p"], 0.95)
219+
self.assertEqual(payload["options"]["top_k"], 64)
220+
221+
@patch("argus.captioner.ollama_chat")
222+
def test_caption_frame_omits_options_for_non_gemma4(self, ollama_chat_mock) -> None:
223+
ollama_chat_mock.return_value = {
224+
"message": {
225+
"content": json.dumps(
226+
{
227+
"short_caption": "A test frame.",
228+
"tags": ["tag"] * 40,
229+
"visible_text": [],
230+
}
231+
)
232+
}
233+
}
234+
235+
with tempfile.TemporaryDirectory() as temp_dir:
236+
image_path = Path(temp_dir) / "frame.jpg"
237+
image_path.write_bytes(b"\xff\xd8\xff")
238+
result = caption_frame(
239+
image_path,
240+
model="gemma3",
241+
ollama_host="http://localhost:11434",
242+
)
243+
244+
self.assertEqual(result["status"], "ok")
245+
payload = ollama_chat_mock.call_args[0][0]
246+
self.assertNotIn("options", payload)
161247

162248
def test_normalize_clip_title_truncates_to_max_length(self) -> None:
163249
long_title = "word " * 40

0 commit comments

Comments
 (0)