Fixing timeouts in label detection, maybe.
This commit is contained in:
1 parent
9925362352
commit
c58bbc3672
2 files changed
+34
-5
No files matched your search
@@ -31,6 +31,7 @@ from copienator.utils import natural_key, read_all_labels
|
|||||||
|
|
||||||
MODEL_ID = config.MODEL_FOR_LABEL_ID
|
MODEL_ID = config.MODEL_FOR_LABEL_ID
|
||||||
api_key = config.API_KEY
|
api_key = config.API_KEY
|
||||||
|
REQUEST_TIMEOUT_SECONDS = 80
|
||||||
|
|
||||||
my_prompt = """I'm giving you an image of the left columns of a written exam.
|
my_prompt = """I'm giving you an image of the left columns of a written exam.
|
||||||
Students answer several exercises, which can have several questions.
|
Students answer several exercises, which can have several questions.
|
||||||
@@ -213,6 +214,8 @@ def generate_request(
|
|||||||
wrong_label_text_context="",
|
wrong_label_text_context="",
|
||||||
wrong_label_text_file: Path | None = None,
|
wrong_label_text_file: Path | None = None,
|
||||||
seed: int = 0,
|
seed: int = 0,
|
||||||
|
*,
|
||||||
|
retry: bool = False,
|
||||||
):
|
):
|
||||||
"""Generates request for Gemini with context."""
|
"""Generates request for Gemini with context."""
|
||||||
|
|
||||||
@@ -275,11 +278,11 @@ def generate_request(
|
|||||||
|
|
||||||
generate_content_config = types.GenerateContentConfig(
|
generate_content_config = types.GenerateContentConfig(
|
||||||
http_options=types.HttpOptions(
|
http_options=types.HttpOptions(
|
||||||
timeout=120_000,
|
timeout=REQUEST_TIMEOUT_SECONDS * 1000,
|
||||||
retry_options=types.HttpRetryOptions(attempts=1),
|
retry_options=types.HttpRetryOptions(attempts=1),
|
||||||
),
|
),
|
||||||
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
|
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
|
||||||
thinking_config=thinking_config(config.THINKING_LEVEL_FOR_LABEL),
|
thinking_config=thinking_config("low" if retry else config.THINKING_LEVEL_FOR_LABEL),
|
||||||
seed=seed,
|
seed=seed,
|
||||||
max_output_tokens=65535,
|
max_output_tokens=65535,
|
||||||
response_mime_type= "application/json",
|
response_mime_type= "application/json",
|
||||||
@@ -435,7 +438,11 @@ def process_copy_group(
|
|||||||
if attempt > 0:
|
if attempt > 0:
|
||||||
print(f"[{group_key}] Retrying {image_file.name} in {10 * attempt}s...")
|
print(f"[{group_key}] Retrying {image_file.name} in {10 * attempt}s...")
|
||||||
sleep(10 * attempt)
|
sleep(10 * attempt)
|
||||||
print(f"[{group_key}] {image_file.name}: attempt {attempt + 1}/{MAX_ATTEMPTS} (120s timeout).")
|
level = "low" if attempt > 0 else config.THINKING_LEVEL_FOR_LABEL
|
||||||
|
print(
|
||||||
|
f"[{group_key}] {image_file.name}: attempt {attempt + 1}/{MAX_ATTEMPTS} "
|
||||||
|
f"({REQUEST_TIMEOUT_SECONDS}s timeout, thinking={level or 'default'})."
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
text_context_file, text_context = closest_text_context(
|
text_context_file, text_context = closest_text_context(
|
||||||
workspace, wrong_labels
|
workspace, wrong_labels
|
||||||
@@ -455,6 +462,7 @@ def process_copy_group(
|
|||||||
text_context,
|
text_context,
|
||||||
text_context_file,
|
text_context_file,
|
||||||
seed=request_seed,
|
seed=request_seed,
|
||||||
|
retry=attempt > 0,
|
||||||
)
|
)
|
||||||
response = client.models.generate_content(
|
response = client.models.generate_content(
|
||||||
model=MODEL_ID,
|
model=MODEL_ID,
|
||||||
|
|||||||
@@ -69,10 +69,25 @@ class LabelTimeoutTests(unittest.TestCase):
|
|||||||
self.assertEqual(self.client.models.generate_content.call_count, 2)
|
self.assertEqual(self.client.models.generate_content.call_count, 2)
|
||||||
for call in self.client.models.generate_content.call_args_list:
|
for call in self.client.models.generate_content.call_args_list:
|
||||||
options = call.kwargs["config"].http_options
|
options = call.kwargs["config"].http_options
|
||||||
self.assertEqual(options.timeout, 120_000)
|
self.assertEqual(options.timeout, 80_000)
|
||||||
self.assertEqual(options.retry_options.attempts, 1)
|
self.assertEqual(options.retry_options.attempts, 1)
|
||||||
self.assertTrue((self.workspace.copies_dir / "Copie01_01.json").exists())
|
self.assertTrue((self.workspace.copies_dir / "Copie01_01.json").exists())
|
||||||
|
|
||||||
|
def test_retries_use_low_thinking_and_next_image_restores_configured_level(self):
|
||||||
|
self.client.models.generate_content.side_effect = [
|
||||||
|
TimeoutError(), TimeoutError(), self.response, self.response,
|
||||||
|
]
|
||||||
|
with patch.object(labels.config, "THINKING_LEVEL_FOR_LABEL", "medium"):
|
||||||
|
self.assertEqual(self.group(self.images[:2]), 2)
|
||||||
|
self.assertEqual(labels.config.THINKING_LEVEL_FOR_LABEL, "medium")
|
||||||
|
configs = [call.kwargs["config"]
|
||||||
|
for call in self.client.models.generate_content.call_args_list]
|
||||||
|
self.assertEqual(
|
||||||
|
[cfg.thinking_config.thinking_level.value for cfg in configs],
|
||||||
|
["MEDIUM", "LOW", "LOW", "MEDIUM"],
|
||||||
|
)
|
||||||
|
self.assertTrue(all(cfg.http_options.timeout == 80_000 for cfg in configs))
|
||||||
|
|
||||||
def test_exhaustion_defers_dependent_pages_but_other_copies_finish_and_resume(self):
|
def test_exhaustion_defers_dependent_pages_but_other_copies_finish_and_resume(self):
|
||||||
self.client.models.generate_content.side_effect = [
|
self.client.models.generate_content.side_effect = [
|
||||||
TimeoutError(), TimeoutError(), TimeoutError(), self.response,
|
TimeoutError(), TimeoutError(), TimeoutError(), self.response,
|
||||||
@@ -99,9 +114,15 @@ class LabelTimeoutTests(unittest.TestCase):
|
|||||||
self.client.models.generate_content.side_effect = [Mock(text=(
|
self.client.models.generate_content.side_effect = [Mock(text=(
|
||||||
'{"name":"Student","list":[{"box_2d":[1,2,3,4],"label":"bad%d"}]}' % index
|
'{"name":"Student","list":[{"box_2d":[1,2,3,4],"label":"bad%d"}]}' % index
|
||||||
)) for index in range(3)]
|
)) for index in range(3)]
|
||||||
with self.assertRaises(labels.IncompleteCopyError):
|
with patch.object(labels.config, "THINKING_LEVEL_FOR_LABEL", "medium"), \
|
||||||
|
self.assertRaises(labels.IncompleteCopyError):
|
||||||
self.group(self.images[:1])
|
self.group(self.images[:1])
|
||||||
self.assertEqual(self.client.models.generate_content.call_count, 3)
|
self.assertEqual(self.client.models.generate_content.call_count, 3)
|
||||||
|
self.assertEqual(
|
||||||
|
[call.kwargs["config"].thinking_config.thinking_level.value
|
||||||
|
for call in self.client.models.generate_content.call_args_list],
|
||||||
|
["MEDIUM", "LOW", "LOW"],
|
||||||
|
)
|
||||||
|
|
||||||
def test_progress_reports_waiting_image_and_elapsed_time(self):
|
def test_progress_reports_waiting_image_and_elapsed_time(self):
|
||||||
entered, release = Event(), Event()
|
entered, release = Event(), Event()
|
||||||
|
|||||||
Reference in new issue
Block a user