aiverify-moonshot 0.4.1__py3-none-any.whl → 0.4.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/METADATA +2 -2
  2. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/RECORD +70 -56
  3. moonshot/__main__.py +77 -35
  4. moonshot/api.py +16 -0
  5. moonshot/integrations/cli/benchmark/benchmark.py +29 -13
  6. moonshot/integrations/cli/benchmark/cookbook.py +62 -24
  7. moonshot/integrations/cli/benchmark/datasets.py +79 -40
  8. moonshot/integrations/cli/benchmark/metrics.py +62 -23
  9. moonshot/integrations/cli/benchmark/recipe.py +89 -69
  10. moonshot/integrations/cli/benchmark/result.py +85 -47
  11. moonshot/integrations/cli/benchmark/run.py +99 -59
  12. moonshot/integrations/cli/common/common.py +20 -6
  13. moonshot/integrations/cli/common/connectors.py +154 -74
  14. moonshot/integrations/cli/common/dataset.py +66 -0
  15. moonshot/integrations/cli/common/prompt_template.py +57 -19
  16. moonshot/integrations/cli/redteam/attack_module.py +90 -24
  17. moonshot/integrations/cli/redteam/context_strategy.py +83 -23
  18. moonshot/integrations/cli/redteam/prompt_template.py +1 -1
  19. moonshot/integrations/cli/redteam/redteam.py +52 -6
  20. moonshot/integrations/cli/redteam/session.py +565 -44
  21. moonshot/integrations/cli/utils/process_data.py +52 -0
  22. moonshot/integrations/web_api/__main__.py +2 -0
  23. moonshot/integrations/web_api/app.py +6 -6
  24. moonshot/integrations/web_api/container.py +12 -2
  25. moonshot/integrations/web_api/routes/bookmark.py +173 -0
  26. moonshot/integrations/web_api/routes/dataset.py +46 -1
  27. moonshot/integrations/web_api/schemas/bookmark_create_dto.py +13 -0
  28. moonshot/integrations/web_api/schemas/dataset_create_dto.py +18 -0
  29. moonshot/integrations/web_api/schemas/recipe_create_dto.py +0 -2
  30. moonshot/integrations/web_api/services/bookmark_service.py +94 -0
  31. moonshot/integrations/web_api/services/dataset_service.py +25 -0
  32. moonshot/integrations/web_api/services/recipe_service.py +0 -1
  33. moonshot/integrations/web_api/services/utils/file_manager.py +52 -0
  34. moonshot/integrations/web_api/status_updater/moonshot_ui_webhook.py +0 -1
  35. moonshot/integrations/web_api/temp/.gitkeep +0 -0
  36. moonshot/src/api/api_bookmark.py +95 -0
  37. moonshot/src/api/api_connector_endpoint.py +1 -1
  38. moonshot/src/api/api_context_strategy.py +2 -2
  39. moonshot/src/api/api_dataset.py +35 -0
  40. moonshot/src/api/api_recipe.py +0 -3
  41. moonshot/src/api/api_session.py +1 -1
  42. moonshot/src/bookmark/bookmark.py +257 -0
  43. moonshot/src/bookmark/bookmark_arguments.py +38 -0
  44. moonshot/src/configs/env_variables.py +12 -2
  45. moonshot/src/connectors/connector.py +15 -7
  46. moonshot/src/connectors_endpoints/connector_endpoint.py +65 -49
  47. moonshot/src/cookbooks/cookbook.py +57 -37
  48. moonshot/src/datasets/dataset.py +125 -5
  49. moonshot/src/metrics/metric.py +8 -4
  50. moonshot/src/metrics/metric_interface.py +8 -2
  51. moonshot/src/prompt_templates/prompt_template.py +5 -1
  52. moonshot/src/recipes/recipe.py +38 -40
  53. moonshot/src/recipes/recipe_arguments.py +0 -4
  54. moonshot/src/redteaming/attack/attack_module.py +18 -8
  55. moonshot/src/redteaming/attack/context_strategy.py +6 -2
  56. moonshot/src/redteaming/session/session.py +15 -11
  57. moonshot/src/results/result.py +7 -3
  58. moonshot/src/runners/runner.py +65 -42
  59. moonshot/src/runs/run.py +15 -11
  60. moonshot/src/runs/run_progress.py +7 -3
  61. moonshot/src/storage/db_interface.py +14 -0
  62. moonshot/src/storage/storage.py +33 -2
  63. moonshot/src/utils/find_feature.py +45 -0
  64. moonshot/src/utils/log.py +72 -0
  65. moonshot/src/utils/pagination.py +25 -0
  66. moonshot/src/utils/timeit.py +8 -1
  67. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/WHEEL +0 -0
  68. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/licenses/AUTHORS.md +0 -0
  69. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/licenses/LICENSE.md +0 -0
  70. {aiverify_moonshot-0.4.1.dist-info → aiverify_moonshot-0.4.3.dist-info}/licenses/NOTICES.md +0 -0
@@ -9,6 +9,10 @@ from moonshot.src.configs.env_variables import EnvVariables
9
9
  from moonshot.src.datasets.dataset import Dataset
10
10
  from moonshot.src.recipes.recipe_arguments import RecipeArguments
11
11
  from moonshot.src.storage.storage import Storage
12
+ from moonshot.src.utils.log import configure_logger
13
+
14
+ # Create a logger for this module
15
+ logger = configure_logger(__name__)
12
16
 
13
17
 
14
18
  class Recipe:
@@ -21,7 +25,6 @@ class Recipe:
21
25
  self.datasets = rec_args.datasets
22
26
  self.prompt_templates = rec_args.prompt_templates
23
27
  self.metrics = rec_args.metrics
24
- self.attack_modules = rec_args.attack_modules
25
28
  self.grading_scale = rec_args.grading_scale
26
29
  self.stats = rec_args.stats
27
30
 
@@ -64,12 +67,7 @@ class Recipe:
64
67
  """
65
68
  try:
66
69
  rec_id = slugify(rec_args.name, lowercase=True)
67
- # check if the recipe exists
68
- if Storage.is_object_exists(EnvVariables.RECIPES.name, rec_id, "json"):
69
- raise RuntimeError(f"Recipe with ID '{rec_id}' already exists.")
70
-
71
70
  rec_info = {
72
- "id": rec_id,
73
71
  "name": rec_args.name,
74
72
  "description": rec_args.description,
75
73
  "tags": rec_args.tags,
@@ -77,10 +75,13 @@ class Recipe:
77
75
  "datasets": rec_args.datasets,
78
76
  "prompt_templates": rec_args.prompt_templates,
79
77
  "metrics": rec_args.metrics,
80
- "attack_modules": rec_args.attack_modules,
81
78
  "grading_scale": rec_args.grading_scale,
82
79
  }
83
80
 
81
+ # check if the recipe exists
82
+ if Storage.is_object_exists(EnvVariables.RECIPES.name, rec_id, "json"):
83
+ raise RuntimeError(f"Recipe with ID '{rec_id}' already exists.")
84
+
84
85
  Recipe.check_file_exists(
85
86
  EnvVariables.PROMPT_TEMPLATES.name,
86
87
  rec_args.prompt_templates,
@@ -93,19 +94,13 @@ class Recipe:
93
94
  Recipe.check_file_exists(
94
95
  EnvVariables.METRICS.name, rec_args.metrics, "Metric", "py"
95
96
  )
96
- Recipe.check_file_exists(
97
- EnvVariables.ATTACK_MODULES.name,
98
- rec_args.attack_modules,
99
- "Attack Module",
100
- "py",
101
- )
102
97
 
103
98
  # Write as json output
104
99
  Storage.create_object(EnvVariables.RECIPES.name, rec_id, rec_info, "json")
105
100
  return rec_id
106
101
 
107
102
  except Exception as e:
108
- print(f"Failed to create recipe: {str(e)}")
103
+ logger.error(f"Failed to create recipe: {str(e)}")
109
104
  raise e
110
105
 
111
106
  @staticmethod
@@ -128,13 +123,17 @@ class Recipe:
128
123
  Exception: If there is an issue reading the file or during any other part of the process.
129
124
  """
130
125
  try:
131
- if rec_id:
132
- return RecipeArguments(**Recipe._read_recipe(rec_id, {}))
133
- else:
134
- raise RuntimeError("Recipe ID is empty")
126
+ if not rec_id:
127
+ raise RuntimeError("Recipe ID is empty.")
128
+
129
+ recipe_details = Recipe._read_recipe(rec_id, {})
130
+ if not recipe_details:
131
+ raise RuntimeError(f"Recipe with ID '{rec_id}' does not exist.")
132
+
133
+ return RecipeArguments(**recipe_details)
135
134
 
136
135
  except Exception as e:
137
- print(f"Failed to read recipe: {str(e)}")
136
+ logger.error(f"Failed to read recipe: {str(e)}")
138
137
  raise e
139
138
 
140
139
  @staticmethod
@@ -171,9 +170,12 @@ class Recipe:
171
170
  Raises:
172
171
  RuntimeError: If the recipe file cannot be read or does not exist.
173
172
  """
174
- obj_results = Storage.read_object(EnvVariables.RECIPES.name, rec_id, "json")
175
- if not obj_results:
173
+ obj_results = {"id": rec_id}
174
+ recipe_info = Storage.read_object(EnvVariables.RECIPES.name, rec_id, "json")
175
+ if not recipe_info:
176
176
  raise RuntimeError(f"Unable to get results for {rec_id}.")
177
+ else:
178
+ obj_results.update(recipe_info)
177
179
 
178
180
  # Calculate statistics for the recipe and update the results dictionary with them
179
181
  stats = {
@@ -181,7 +183,6 @@ class Recipe:
181
183
  "num_of_datasets": len(obj_results["datasets"]),
182
184
  "num_of_prompt_templates": len(obj_results["prompt_templates"]),
183
185
  "num_of_metrics": len(obj_results["metrics"]),
184
- "num_of_attack_modules": len(obj_results["attack_modules"]),
185
186
  "num_of_datasets_prompts": {},
186
187
  }
187
188
 
@@ -203,25 +204,28 @@ class Recipe:
203
204
  @staticmethod
204
205
  def update(rec_args: RecipeArguments) -> bool:
205
206
  """
206
- Updates the recipe information based on the provided RecipeArguments.
207
+ Updates the recipe information in the storage based on the provided RecipeArguments object.
207
208
 
208
- This method takes RecipeArguments, converts it to a dictionary, and writes the updated
209
- recipe information to the storage. If the operation is successful, it returns True.
210
- If an exception occurs, it prints an error message and re-raises the exception.
209
+ This method processes an instance of RecipeArguments, transforming it into a dictionary format. It ensures
210
+ that certain required files exist before proceeding to update the recipe information in the storage system.
211
+ Upon successful update, it returns True. If any error is encountered during the process, the error message is
212
+ logged, and the exception is propagated upwards.
211
213
 
212
214
  Args:
213
- rec_args (RecipeArguments): The recipe arguments containing updated values.
215
+ rec_args (RecipeArguments): An object containing the updated recipe information.
214
216
 
215
217
  Returns:
216
- bool: True if the recipe was successfully updated.
218
+ bool: Indicates whether the recipe update was successful (True) or not (False).
217
219
 
218
220
  Raises:
219
- Exception: If an error occurs during the update process.
221
+ Exception: Propagates any exceptions that occur during the update process.
220
222
  """
221
223
  try:
222
- # Convert the recipe arguments to a dictionary
224
+ # Transform RecipeArguments into a dictionary, excluding the 'id' field
223
225
  rec_info = rec_args.to_dict()
226
+ rec_info.pop("id", None) # The 'id' is derived and should not be written
224
227
 
228
+ # Verify existence of related files in storage
225
229
  Recipe.check_file_exists(
226
230
  EnvVariables.PROMPT_TEMPLATES.name,
227
231
  rec_args.prompt_templates,
@@ -234,21 +238,15 @@ class Recipe:
234
238
  Recipe.check_file_exists(
235
239
  EnvVariables.METRICS.name, rec_args.metrics, "Metric", "py"
236
240
  )
237
- Recipe.check_file_exists(
238
- EnvVariables.ATTACK_MODULES.name,
239
- rec_args.attack_modules,
240
- "Attack Module",
241
- "py",
242
- )
243
241
 
244
- # Write the updated recipe information to the file
242
+ # Persist the updated recipe information to storage
245
243
  Storage.create_object(
246
244
  EnvVariables.RECIPES.name, rec_args.id, rec_info, "json"
247
245
  )
248
246
  return True
249
247
 
250
248
  except Exception as e:
251
- print(f"Failed to update recipe: {str(e)}")
249
+ logger.error(f"Failed to update recipe: {str(e)}")
252
250
  raise e
253
251
 
254
252
  @staticmethod
@@ -275,7 +273,7 @@ class Recipe:
275
273
  return True
276
274
 
277
275
  except Exception as e:
278
- print(f"Failed to delete recipe: {str(e)}")
276
+ logger.error(f"Failed to delete recipe: {str(e)}")
279
277
  raise e
280
278
 
281
279
  @staticmethod
@@ -314,7 +312,7 @@ class Recipe:
314
312
  return retn_recs_ids, retn_recs
315
313
 
316
314
  except Exception as e:
317
- print(f"Failed to get available recipes: {str(e)}")
315
+ logger.error(f"Failed to get available recipes: {str(e)}")
318
316
  raise e
319
317
 
320
318
  @staticmethod
@@ -27,9 +27,6 @@ class RecipeArguments(BaseModel):
27
27
  # metrics (list): The list of metrics in the recipe.
28
28
  metrics: list[str] = Field(min_length=1)
29
29
 
30
- # attack_modules (list): The list of attack modules in the recipe.
31
- attack_modules: list[str]
32
-
33
30
  # grading_scale (dict): A dictionary where keys are grading categories and values are lists of grading scale.
34
31
  grading_scale: dict[str, list[int]]
35
32
 
@@ -105,7 +102,6 @@ class RecipeArguments(BaseModel):
105
102
  "datasets": self.datasets,
106
103
  "prompt_templates": self.prompt_templates,
107
104
  "metrics": self.metrics,
108
- "attack_modules": self.attack_modules,
109
105
  "grading_scale": self.grading_scale,
110
106
  "stats": self.stats,
111
107
  }
@@ -18,6 +18,10 @@ from moonshot.src.redteaming.attack.context_strategy import ContextStrategy
18
18
  from moonshot.src.runs.run_status import RunStatus
19
19
  from moonshot.src.storage.storage import Storage
20
20
  from moonshot.src.utils.import_modules import get_instance
21
+ from moonshot.src.utils.log import configure_logger
22
+
23
+ # Create a logger for this module
24
+ logger = configure_logger(__name__)
21
25
 
22
26
 
23
27
  class AttackModule:
@@ -173,7 +177,7 @@ class AttackModule:
173
177
  for generator in generator_list:
174
178
  async for result in generator:
175
179
  if self.cancel_event.is_set():
176
- print(
180
+ logger.warning(
177
181
  "[Red Teaming] Cancellation flag is set. Cancelling task..."
178
182
  )
179
183
  break
@@ -197,7 +201,9 @@ class AttackModule:
197
201
  for prepared_prompt in list_of_prompts:
198
202
  for target_llm_connector in self.connector_instances:
199
203
  if self.cancel_event.is_set():
200
- print("[Red Teaming] Cancellation flag is set. Cancelling task...")
204
+ logger.warning(
205
+ "[Red Teaming] Cancellation flag is set. Cancelling task..."
206
+ )
201
207
  break
202
208
 
203
209
  if self.red_teaming_progress:
@@ -256,7 +262,9 @@ class AttackModule:
256
262
  consolidated_responses = []
257
263
  for prepared_prompt in list_of_prompts:
258
264
  if self.cancel_event.is_set():
259
- print("[Red Teaming] Cancellation flag is set. Cancelling task...")
265
+ logger.warning(
266
+ "[Red Teaming] Cancellation flag is set. Cancelling task..."
267
+ )
260
268
  break
261
269
 
262
270
  if self.red_teaming_progress:
@@ -344,7 +352,9 @@ class AttackModule:
344
352
  """
345
353
  async for prompt_info in gen_prompts_generator:
346
354
  if self.cancel_event.is_set():
347
- print("[Red Teaming] Cancellation flag is set. Cancelling task...")
355
+ logger.warning(
356
+ "[Red Teaming] Cancellation flag is set. Cancelling task..."
357
+ )
348
358
  break
349
359
  new_prompt_info = RedTeamingPromptArguments(
350
360
  conn_id=prompt_info.conn_id,
@@ -415,7 +425,7 @@ class AttackModule:
415
425
  )
416
426
  return cache_info if cache_info else {}
417
427
  except Exception as e:
418
- print(f"No previous cache information: {str(e)}")
428
+ logger.error(f"No previous cache information: {str(e)}")
419
429
  return {}
420
430
 
421
431
  @staticmethod
@@ -434,7 +444,7 @@ class AttackModule:
434
444
  obj_extension=AttackModule.cache_extension,
435
445
  )
436
446
  except Exception as e:
437
- print(f"Failed to write cache information: {str(e)}")
447
+ logger.error(f"Failed to write cache information: {str(e)}")
438
448
  raise e
439
449
 
440
450
  @staticmethod
@@ -479,7 +489,7 @@ class AttackModule:
479
489
  return retn_am_ids, retn_ams
480
490
 
481
491
  except Exception as e:
482
- print(f"Failed to get available attack modules: {str(e)}")
492
+ logger.error(f"Failed to get available attack modules: {str(e)}")
483
493
  raise e
484
494
 
485
495
  @staticmethod
@@ -542,7 +552,7 @@ class AttackModule:
542
552
  return True
543
553
 
544
554
  except Exception as e:
545
- print(f"Failed to delete attack module: {str(e)}")
555
+ logger.error(f"Failed to delete attack module: {str(e)}")
546
556
  raise e
547
557
 
548
558
 
@@ -6,6 +6,10 @@ from moonshot.src.configs.env_variables import EnvVariables
6
6
  from moonshot.src.storage.db_interface import DBInterface
7
7
  from moonshot.src.storage.storage import Storage
8
8
  from moonshot.src.utils.import_modules import get_instance
9
+ from moonshot.src.utils.log import configure_logger
10
+
11
+ # Create a logger for this module
12
+ logger = configure_logger(__name__)
9
13
 
10
14
 
11
15
  class ContextStrategy:
@@ -84,7 +88,7 @@ class ContextStrategy:
84
88
  return True
85
89
 
86
90
  except Exception as e:
87
- print(f"Failed to delete context strategy: {str(e)}")
91
+ logger.error(f"Failed to delete context strategy: {str(e)}")
88
92
  raise e
89
93
 
90
94
  @staticmethod
@@ -125,7 +129,7 @@ class ContextStrategy:
125
129
  context_strategy_instance = context_strategy_instance(context_strategy_name)
126
130
  return context_strategy_instance.add_in_context(user_prompt, list_of_chats)
127
131
  else:
128
- print(
132
+ logger.error(
129
133
  "Cannot load context strategy. Make sure the name of the context strategy is correct."
130
134
  )
131
135
  return ""
@@ -17,6 +17,10 @@ from moonshot.src.runs.run_status import RunStatus
17
17
  from moonshot.src.storage.db_interface import DBInterface
18
18
  from moonshot.src.storage.storage import Storage
19
19
  from moonshot.src.utils.import_modules import get_instance
20
+ from moonshot.src.utils.log import configure_logger
21
+
22
+ # Create a logger for this module
23
+ logger = configure_logger(__name__)
20
24
 
21
25
 
22
26
  class SessionMetadata:
@@ -283,13 +287,13 @@ class Session:
283
287
 
284
288
  # check if the session metadata record already exists
285
289
  if session_metadata_records:
286
- print("[Session] Session already exists.")
290
+ logger.info("[Session] Session already exists.")
287
291
  self.session_metadata = SessionMetadata.from_tuple(
288
292
  session_metadata_records[0]
289
293
  )
290
294
  # create a new record if session metadata does not exist
291
295
  else:
292
- print("[Session] Creating new session.")
296
+ logger.info("[Session] Creating new session.")
293
297
 
294
298
  # create chat history table for each endpoint
295
299
 
@@ -379,13 +383,13 @@ class Session:
379
383
  # ------------------------------------------------------------------------------
380
384
  # Part 1: Get asyncio running loop
381
385
  # ------------------------------------------------------------------------------
382
- print("[Session] Part 1: Loading asyncio running loop...")
386
+ logger.debug("[Session] Part 1: Loading asyncio running loop...")
383
387
  loop = asyncio.get_running_loop()
384
388
 
385
389
  # ------------------------------------------------------------------------------
386
390
  # Part 2: Load runner processing module
387
391
  # ------------------------------------------------------------------------------
388
- print("[Session] Part 2: Loading runner processing module...")
392
+ logger.debug("[Session] Part 2: Loading runner processing module...")
389
393
  start_time = time.perf_counter()
390
394
  runner_module_instance = None
391
395
  try:
@@ -414,20 +418,20 @@ class Session:
414
418
  )
415
419
 
416
420
  except Exception as e:
417
- print(
421
+ logger.error(
418
422
  f"[Session] Failed to load runner processing module in Part 2 due to error: {str(e)}"
419
423
  )
420
424
  raise e
421
425
 
422
426
  finally:
423
- print(
427
+ logger.debug(
424
428
  f"[Session] Loading runner processing module took {(time.perf_counter() - start_time):.4f}s"
425
429
  )
426
430
 
427
431
  # ------------------------------------------------------------------------------
428
432
  # Part 3: Run runner processing module
429
433
  # ------------------------------------------------------------------------------
430
- print("[Session] Part 3: Running runner processing module...")
434
+ logger.debug("[Session] Part 3: Running runner processing module...")
431
435
  start_time = time.perf_counter()
432
436
  runner_results = {}
433
437
 
@@ -446,7 +450,7 @@ class Session:
446
450
  raise RuntimeError("Failed to initialise runner module instance.")
447
451
 
448
452
  except Exception as e:
449
- print(
453
+ logger.error(
450
454
  f"[Session] Failed to run runner processing module in Part 3 due to error: {str(e)}"
451
455
  )
452
456
  raise e
@@ -455,14 +459,14 @@ class Session:
455
459
  self.red_teaming_progress.status = RunStatus.COMPLETED
456
460
  if self.check_redteaming_type() == RedTeamingType.AUTOMATED:
457
461
  self.red_teaming_progress.notify_progress()
458
- print(
462
+ logger.debug(
459
463
  f"[Session] Running runner processing module took {(time.perf_counter() - start_time):.4f}s"
460
464
  )
461
465
 
462
466
  # ------------------------------------------------------------------------------
463
467
  # Part 4: Wrap up run
464
468
  # ------------------------------------------------------------------------------
465
- print("[Session] Part 4: Wrap up run...")
469
+ logger.debug("[Session] Part 4: Wrap up run...")
466
470
  return runner_results
467
471
 
468
472
  def cancel(self) -> None:
@@ -476,7 +480,7 @@ class Session:
476
480
  Returns:
477
481
  None
478
482
  """
479
- print("[Session] Cancelling automated red teaming...")
483
+ logger.warning("[Session] Cancelling automated red teaming...")
480
484
  self.cancel_event.set()
481
485
 
482
486
  def check_redteaming_type(self) -> RedTeamingType:
@@ -6,6 +6,10 @@ from pydantic import validate_call
6
6
 
7
7
  from moonshot.src.configs.env_variables import EnvVariables
8
8
  from moonshot.src.storage.storage import Storage
9
+ from moonshot.src.utils.log import configure_logger
10
+
11
+ # Create a logger for this module
12
+ logger = configure_logger(__name__)
9
13
 
10
14
 
11
15
  class Result:
@@ -35,7 +39,7 @@ class Result:
35
39
  raise RuntimeError("Result ID is empty")
36
40
 
37
41
  except Exception as e:
38
- print(f"Failed to read result: {str(e)}")
42
+ logger.error(f"Failed to read result: {str(e)}")
39
43
  raise e
40
44
 
41
45
  @staticmethod
@@ -85,7 +89,7 @@ class Result:
85
89
  return True
86
90
 
87
91
  except Exception as e:
88
- print(f"Failed to delete result: {str(e)}")
92
+ logger.error(f"Failed to delete result: {str(e)}")
89
93
  raise e
90
94
 
91
95
  @staticmethod
@@ -115,5 +119,5 @@ class Result:
115
119
  return retn_results_ids, retn_results
116
120
 
117
121
  except Exception as e:
118
- print(f"Failed to get available results: {str(e)}")
122
+ logger.error(f"Failed to get available results: {str(e)}")
119
123
  raise e