aiverify-moonshot 0.4.0__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 (163) hide show
  1. aiverify_moonshot-0.4.0.dist-info/METADATA +249 -0
  2. aiverify_moonshot-0.4.0.dist-info/RECORD +163 -0
  3. aiverify_moonshot-0.4.0.dist-info/WHEEL +4 -0
  4. aiverify_moonshot-0.4.0.dist-info/licenses/AUTHORS.md +5 -0
  5. aiverify_moonshot-0.4.0.dist-info/licenses/LICENSE.md +201 -0
  6. aiverify_moonshot-0.4.0.dist-info/licenses/NOTICES.md +3340 -0
  7. moonshot/__init__.py +0 -0
  8. moonshot/__main__.py +198 -0
  9. moonshot/api.py +155 -0
  10. moonshot/integrations/__init__.py +0 -0
  11. moonshot/integrations/cli/__init__.py +0 -0
  12. moonshot/integrations/cli/__main__.py +25 -0
  13. moonshot/integrations/cli/active_session_cfg.py +1 -0
  14. moonshot/integrations/cli/benchmark/__init__.py +0 -0
  15. moonshot/integrations/cli/benchmark/benchmark.py +186 -0
  16. moonshot/integrations/cli/benchmark/cookbook.py +545 -0
  17. moonshot/integrations/cli/benchmark/datasets.py +164 -0
  18. moonshot/integrations/cli/benchmark/metrics.py +141 -0
  19. moonshot/integrations/cli/benchmark/recipe.py +598 -0
  20. moonshot/integrations/cli/benchmark/result.py +216 -0
  21. moonshot/integrations/cli/benchmark/run.py +140 -0
  22. moonshot/integrations/cli/benchmark/runner.py +174 -0
  23. moonshot/integrations/cli/cli.py +64 -0
  24. moonshot/integrations/cli/common/__init__.py +0 -0
  25. moonshot/integrations/cli/common/common.py +72 -0
  26. moonshot/integrations/cli/common/connectors.py +325 -0
  27. moonshot/integrations/cli/common/display_helper.py +42 -0
  28. moonshot/integrations/cli/common/prompt_template.py +94 -0
  29. moonshot/integrations/cli/initialisation/__init__.py +0 -0
  30. moonshot/integrations/cli/initialisation/initialisation.py +14 -0
  31. moonshot/integrations/cli/redteam/__init__.py +0 -0
  32. moonshot/integrations/cli/redteam/attack_module.py +70 -0
  33. moonshot/integrations/cli/redteam/context_strategy.py +147 -0
  34. moonshot/integrations/cli/redteam/prompt_template.py +67 -0
  35. moonshot/integrations/cli/redteam/redteam.py +90 -0
  36. moonshot/integrations/cli/redteam/session.py +467 -0
  37. moonshot/integrations/web_api/.env.dev +7 -0
  38. moonshot/integrations/web_api/__init__.py +0 -0
  39. moonshot/integrations/web_api/__main__.py +56 -0
  40. moonshot/integrations/web_api/app.py +125 -0
  41. moonshot/integrations/web_api/container.py +146 -0
  42. moonshot/integrations/web_api/log/.gitkeep +0 -0
  43. moonshot/integrations/web_api/logging_conf.py +114 -0
  44. moonshot/integrations/web_api/routes/__init__.py +0 -0
  45. moonshot/integrations/web_api/routes/attack_modules.py +66 -0
  46. moonshot/integrations/web_api/routes/benchmark.py +116 -0
  47. moonshot/integrations/web_api/routes/benchmark_result.py +175 -0
  48. moonshot/integrations/web_api/routes/context_strategy.py +129 -0
  49. moonshot/integrations/web_api/routes/cookbook.py +225 -0
  50. moonshot/integrations/web_api/routes/dataset.py +120 -0
  51. moonshot/integrations/web_api/routes/endpoint.py +282 -0
  52. moonshot/integrations/web_api/routes/metric.py +78 -0
  53. moonshot/integrations/web_api/routes/prompt_template.py +128 -0
  54. moonshot/integrations/web_api/routes/recipe.py +219 -0
  55. moonshot/integrations/web_api/routes/redteam.py +609 -0
  56. moonshot/integrations/web_api/routes/runner.py +239 -0
  57. moonshot/integrations/web_api/schemas/__init__.py +0 -0
  58. moonshot/integrations/web_api/schemas/benchmark_runner_dto.py +13 -0
  59. moonshot/integrations/web_api/schemas/cookbook_create_dto.py +19 -0
  60. moonshot/integrations/web_api/schemas/cookbook_response_model.py +9 -0
  61. moonshot/integrations/web_api/schemas/dataset_response_dto.py +9 -0
  62. moonshot/integrations/web_api/schemas/endpoint_create_dto.py +21 -0
  63. moonshot/integrations/web_api/schemas/endpoint_response_model.py +11 -0
  64. moonshot/integrations/web_api/schemas/prompt_response_model.py +14 -0
  65. moonshot/integrations/web_api/schemas/prompt_template_response_model.py +10 -0
  66. moonshot/integrations/web_api/schemas/recipe_create_dto.py +32 -0
  67. moonshot/integrations/web_api/schemas/recipe_response_model.py +7 -0
  68. moonshot/integrations/web_api/schemas/session_create_dto.py +16 -0
  69. moonshot/integrations/web_api/schemas/session_prompt_dto.py +7 -0
  70. moonshot/integrations/web_api/schemas/session_response_model.py +38 -0
  71. moonshot/integrations/web_api/services/__init__.py +0 -0
  72. moonshot/integrations/web_api/services/attack_module_service.py +34 -0
  73. moonshot/integrations/web_api/services/auto_red_team_test_manager.py +86 -0
  74. moonshot/integrations/web_api/services/auto_red_team_test_state.py +57 -0
  75. moonshot/integrations/web_api/services/base_service.py +8 -0
  76. moonshot/integrations/web_api/services/benchmark_result_service.py +25 -0
  77. moonshot/integrations/web_api/services/benchmark_test_manager.py +106 -0
  78. moonshot/integrations/web_api/services/benchmark_test_state.py +56 -0
  79. moonshot/integrations/web_api/services/benchmarking_service.py +31 -0
  80. moonshot/integrations/web_api/services/context_strategy_service.py +22 -0
  81. moonshot/integrations/web_api/services/cookbook_service.py +194 -0
  82. moonshot/integrations/web_api/services/dataset_service.py +20 -0
  83. moonshot/integrations/web_api/services/endpoint_service.py +65 -0
  84. moonshot/integrations/web_api/services/metric_service.py +14 -0
  85. moonshot/integrations/web_api/services/prompt_template_service.py +39 -0
  86. moonshot/integrations/web_api/services/recipe_service.py +155 -0
  87. moonshot/integrations/web_api/services/runner_service.py +147 -0
  88. moonshot/integrations/web_api/services/session_service.py +350 -0
  89. moonshot/integrations/web_api/services/utils/exceptions_handler.py +41 -0
  90. moonshot/integrations/web_api/services/utils/results_formatter.py +47 -0
  91. moonshot/integrations/web_api/status_updater/interface/benchmark_progress_callback.py +14 -0
  92. moonshot/integrations/web_api/status_updater/interface/redteam_progress_callback.py +14 -0
  93. moonshot/integrations/web_api/status_updater/moonshot_ui_webhook.py +72 -0
  94. moonshot/integrations/web_api/types/types.py +99 -0
  95. moonshot/src/__init__.py +0 -0
  96. moonshot/src/api/__init__.py +0 -0
  97. moonshot/src/api/api_connector.py +58 -0
  98. moonshot/src/api/api_connector_endpoint.py +162 -0
  99. moonshot/src/api/api_context_strategy.py +57 -0
  100. moonshot/src/api/api_cookbook.py +160 -0
  101. moonshot/src/api/api_dataset.py +46 -0
  102. moonshot/src/api/api_environment_variables.py +17 -0
  103. moonshot/src/api/api_metrics.py +51 -0
  104. moonshot/src/api/api_prompt_template.py +43 -0
  105. moonshot/src/api/api_recipe.py +182 -0
  106. moonshot/src/api/api_red_teaming.py +59 -0
  107. moonshot/src/api/api_result.py +84 -0
  108. moonshot/src/api/api_run.py +74 -0
  109. moonshot/src/api/api_runner.py +132 -0
  110. moonshot/src/api/api_session.py +290 -0
  111. moonshot/src/configs/__init__.py +0 -0
  112. moonshot/src/configs/env_variables.py +187 -0
  113. moonshot/src/connectors/__init__.py +0 -0
  114. moonshot/src/connectors/connector.py +327 -0
  115. moonshot/src/connectors/connector_prompt_arguments.py +17 -0
  116. moonshot/src/connectors_endpoints/__init__.py +0 -0
  117. moonshot/src/connectors_endpoints/connector_endpoint.py +211 -0
  118. moonshot/src/connectors_endpoints/connector_endpoint_arguments.py +54 -0
  119. moonshot/src/cookbooks/__init__.py +0 -0
  120. moonshot/src/cookbooks/cookbook.py +225 -0
  121. moonshot/src/cookbooks/cookbook_arguments.py +34 -0
  122. moonshot/src/datasets/__init__.py +0 -0
  123. moonshot/src/datasets/dataset.py +255 -0
  124. moonshot/src/datasets/dataset_arguments.py +50 -0
  125. moonshot/src/metrics/__init__.py +0 -0
  126. moonshot/src/metrics/metric.py +192 -0
  127. moonshot/src/metrics/metric_interface.py +95 -0
  128. moonshot/src/prompt_templates/__init__.py +0 -0
  129. moonshot/src/prompt_templates/prompt_template.py +103 -0
  130. moonshot/src/recipes/__init__.py +0 -0
  131. moonshot/src/recipes/recipe.py +340 -0
  132. moonshot/src/recipes/recipe_arguments.py +111 -0
  133. moonshot/src/redteaming/__init__.py +0 -0
  134. moonshot/src/redteaming/attack/__init__.py +0 -0
  135. moonshot/src/redteaming/attack/attack_module.py +618 -0
  136. moonshot/src/redteaming/attack/attack_module_arguments.py +44 -0
  137. moonshot/src/redteaming/attack/context_strategy.py +131 -0
  138. moonshot/src/redteaming/context_strategy/__init__.py +0 -0
  139. moonshot/src/redteaming/context_strategy/context_strategy_interface.py +46 -0
  140. moonshot/src/redteaming/session/__init__.py +0 -0
  141. moonshot/src/redteaming/session/chat.py +209 -0
  142. moonshot/src/redteaming/session/red_teaming_progress.py +128 -0
  143. moonshot/src/redteaming/session/red_teaming_type.py +6 -0
  144. moonshot/src/redteaming/session/session.py +775 -0
  145. moonshot/src/results/__init__.py +0 -0
  146. moonshot/src/results/result.py +119 -0
  147. moonshot/src/results/result_arguments.py +44 -0
  148. moonshot/src/runners/__init__.py +0 -0
  149. moonshot/src/runners/runner.py +476 -0
  150. moonshot/src/runners/runner_arguments.py +46 -0
  151. moonshot/src/runners/runner_type.py +6 -0
  152. moonshot/src/runs/__init__.py +0 -0
  153. moonshot/src/runs/run.py +344 -0
  154. moonshot/src/runs/run_arguments.py +162 -0
  155. moonshot/src/runs/run_progress.py +145 -0
  156. moonshot/src/runs/run_status.py +10 -0
  157. moonshot/src/storage/__init__.py +0 -0
  158. moonshot/src/storage/db_interface.py +128 -0
  159. moonshot/src/storage/io_interface.py +31 -0
  160. moonshot/src/storage/storage.py +525 -0
  161. moonshot/src/utils/__init__.py +0 -0
  162. moonshot/src/utils/import_modules.py +96 -0
  163. moonshot/src/utils/timeit.py +25 -0
@@ -0,0 +1,239 @@
1
+ from dependency_injector.wiring import Provide, inject
2
+ from fastapi import APIRouter, Depends, HTTPException
3
+
4
+ from ..container import Container
5
+ from ..services.runner_service import RunnerService
6
+ from ..services.utils.exceptions_handler import ServiceException
7
+
8
+ router = APIRouter(tags=["Runner"])
9
+
10
+
11
+ @router.get("/api/v1/runners")
12
+ @inject
13
+ def get_all_runners(
14
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
15
+ ) -> list:
16
+ """
17
+ Retrieve all runners from the database.
18
+
19
+ Args:
20
+ runner_service (RunnerService): The service responsible for retrieving runners.
21
+
22
+ Returns:
23
+ list: A list of all runners.
24
+
25
+ Raises:
26
+ HTTPException: An error with status code 404 if no runners are found.
27
+ An error with status code 400 if there is a validation error.
28
+ An error with status code 500 for any other server-side error.
29
+ """
30
+ try:
31
+ return runner_service.get_all_runner()
32
+ except ServiceException as e:
33
+ if e.error_code == "FileNotFound":
34
+ raise HTTPException(
35
+ status_code=404, detail=f"Failed to retrieve runners: {e.msg}"
36
+ )
37
+ elif e.error_code == "ValidationError":
38
+ raise HTTPException(
39
+ status_code=400, detail=f"Failed to retrieve runners: {e.msg}"
40
+ )
41
+ else:
42
+ raise HTTPException(
43
+ status_code=500, detail=f"Failed to retrieve runners: {e.msg}"
44
+ )
45
+
46
+
47
+ @router.get("/api/v1/runners/name")
48
+ @inject
49
+ def get_all_runner_name(
50
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
51
+ ) -> list:
52
+ """
53
+ Retrieve all runner names from the database.
54
+
55
+ Args:
56
+ runner_service (RunnerService): The service responsible for retrieving runner names.
57
+
58
+ Returns:
59
+ list: A list of all runner names.
60
+
61
+ Raises:
62
+ HTTPException: An error with status code 404 if no runner names are found.
63
+ An error with status code 400 if there is a validation error.
64
+ An error with status code 500 for any other server-side error.
65
+ """
66
+ try:
67
+ return runner_service.get_all_runner_name()
68
+ except ServiceException as e:
69
+ if e.error_code == "FileNotFound":
70
+ raise HTTPException(
71
+ status_code=404, detail=f"Failed to retrieve runner names: {e.msg}"
72
+ )
73
+ elif e.error_code == "ValidationError":
74
+ raise HTTPException(
75
+ status_code=400, detail=f"Failed to retrieve runner names: {e.msg}"
76
+ )
77
+ else:
78
+ raise HTTPException(
79
+ status_code=500, detail=f"Failed to retrieve runner names: {e.msg}"
80
+ )
81
+
82
+
83
+ @router.get("/api/v1/runners/{runner_id}")
84
+ @inject
85
+ def get_runner_by_id(
86
+ runner_id: str,
87
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
88
+ ) -> dict:
89
+ """
90
+ Retrieve a specific runner by their ID from the database.
91
+
92
+ Args:
93
+ runner_id (str): The unique identifier of the runner to retrieve.
94
+ runner_service (RunnerService): The service responsible for retrieving the runner.
95
+
96
+ Returns:
97
+ dict: The runner information if found.
98
+
99
+ Raises:
100
+ HTTPException: An error with status code 404 if the runner is not found.
101
+ An error with status code 400 if there is a validation error.
102
+ An error with status code 500 for any other server-side error.
103
+ """
104
+ try:
105
+ run = runner_service.get_runner_by_id(runner_id)
106
+ return run
107
+ except ServiceException as e:
108
+ if e.error_code == "FileNotFound":
109
+ raise HTTPException(
110
+ status_code=404, detail=f"Failed to retrieve runner: {e.msg}"
111
+ )
112
+ elif e.error_code == "ValidationError":
113
+ raise HTTPException(
114
+ status_code=400, detail=f"Failed to retrieve runner: {e.msg}"
115
+ )
116
+ else:
117
+ raise HTTPException(
118
+ status_code=500, detail=f"Failed to retrieve runner: {e.msg}"
119
+ )
120
+
121
+
122
+ @router.delete("/api/v1/runners/{runner_id}")
123
+ @inject
124
+ def delete_runner(
125
+ runner_id: str,
126
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
127
+ ) -> dict:
128
+ """
129
+ Delete a specific runner by their ID from the database.
130
+
131
+ Args:
132
+ runner_id (str): The unique identifier of the runner to delete.
133
+ runner_service (RunnerService): The service responsible for deleting the runner.
134
+
135
+ Returns:
136
+ dict: A message indicating the successful deletion of the runner.
137
+
138
+ Raises:
139
+ HTTPException: An error with status code 404 if the runner is not found.
140
+ An error with status code 400 if there is a validation error.
141
+ An error with status code 500 for any other server-side error.
142
+ """
143
+ try:
144
+ runner_service.delete_run(runner_id)
145
+ return {"message": "Runner deleted successfully"}
146
+ except ServiceException as e:
147
+ if e.error_code == "FileNotFound":
148
+ raise HTTPException(
149
+ status_code=404, detail=f"Failed to delete runner: {e.msg}"
150
+ )
151
+ elif e.error_code == "ValidationError":
152
+ raise HTTPException(
153
+ status_code=400, detail=f"Failed to delete runner: {e.msg}"
154
+ )
155
+ else:
156
+ raise HTTPException(
157
+ status_code=500, detail=f"Failed to delete runner: {e.msg}"
158
+ )
159
+
160
+
161
+ @router.get("/api/v1/runners/{runner_id}/runs/{run_id}")
162
+ @inject
163
+ def get_run_details_by_runner(
164
+ runner_id: str,
165
+ run_id: str,
166
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
167
+ ) -> dict:
168
+ """
169
+ Retrieve the details of a specific run by a runner.
170
+
171
+ Args:
172
+ runner_id (str): The unique identifier of the runner.
173
+ run_id (str): The unique identifier of the run.
174
+ runner_service (RunnerService): The service responsible for retrieving run details.
175
+
176
+ Returns:
177
+ dict: The details of the run.
178
+
179
+ Raises:
180
+ HTTPException: An error with status code 404 if the run details are not found.
181
+ An error with status code 400 if there is a validation error.
182
+ An error with status code 500 for any other server-side error.
183
+ """
184
+ try:
185
+ return runner_service.get_run_details_by_runner(runner_id, run_id)
186
+ except ServiceException as e:
187
+ if e.error_code == "FileNotFound":
188
+ raise HTTPException(
189
+ status_code=404,
190
+ detail=f"Failed to get run details from runner: {e.msg}",
191
+ )
192
+ elif e.error_code == "ValidationError":
193
+ raise HTTPException(
194
+ status_code=400,
195
+ detail=f"Failed to get run details from runner: {e.msg}",
196
+ )
197
+ else:
198
+ raise HTTPException(
199
+ status_code=500,
200
+ detail=f"Failed to get run details from runner: {e.msg}",
201
+ )
202
+
203
+
204
+ @router.get("/api/v1/runners/{runner_id}/runs")
205
+ @inject
206
+ def get_runs_id_in_runner(
207
+ runner_id: str,
208
+ runner_service: RunnerService = Depends(Provide[Container.runner_service]),
209
+ ) -> list[int]:
210
+ """
211
+ Retrieve a list of run identifiers associated with a specific runner.
212
+
213
+ Args:
214
+ runner_id (str): The unique identifier of the runner.
215
+ runner_service (RunnerService): The service responsible for retrieving the list of runs.
216
+
217
+ Returns:
218
+ List[str]: A list of run identifiers.
219
+
220
+ Raises:
221
+ HTTPException: An error with status code 404 if no runs are found for the runner.
222
+ An error with status code 400 if there is a validation error.
223
+ An error with status code 500 for any other server-side error.
224
+ """
225
+ try:
226
+ return runner_service.get_runs_id_in_runner(runner_id)
227
+ except ServiceException as e:
228
+ if e.error_code == "FileNotFound":
229
+ raise HTTPException(
230
+ status_code=404, detail=f"Failed to get runs from runner: {e.msg}"
231
+ )
232
+ elif e.error_code == "ValidationError":
233
+ raise HTTPException(
234
+ status_code=400, detail=f"Failed to get runs from runner: {e.msg}"
235
+ )
236
+ else:
237
+ raise HTTPException(
238
+ status_code=500, detail=f"Failed to get runs from runner: {e.msg}"
239
+ )
File without changes
@@ -0,0 +1,13 @@
1
+ from pydantic import BaseModel, ConfigDict
2
+
3
+
4
+ class BenchmarkRunnerDTO(BaseModel):
5
+ model_config = ConfigDict(from_attributes=True)
6
+ run_name: str
7
+ description: str
8
+ endpoints: list[str]
9
+ inputs: list[str]
10
+ num_of_prompts: int
11
+ random_seed: int
12
+ system_prompt: str
13
+ runner_processing_module: str
@@ -0,0 +1,19 @@
1
+ from typing import Optional
2
+
3
+ from moonshot.src.cookbooks.cookbook_arguments import (
4
+ CookbookArguments as CookbookPydanticModel,
5
+ )
6
+ from pydantic import Field
7
+
8
+ class CookbookCreateDTO(CookbookPydanticModel):
9
+ id: Optional[str] = None
10
+ name: str = Field(..., min_length=1)
11
+ description: Optional[str] = Field(default="", min_length=1)
12
+ recipes: list[str] = Field(..., min_length=1)
13
+
14
+
15
+ class CookbookUpdateDTO(CookbookPydanticModel):
16
+ id: Optional[str] = None
17
+ name: Optional[str] = Field(default=None, min_length=1)
18
+ description: Optional[str] = Field(default=None, min_length=1)
19
+ recipes: Optional[list[str]] = Field(default=None, min_length=1)
@@ -0,0 +1,9 @@
1
+ from typing import Optional
2
+
3
+ from moonshot.src.cookbooks.cookbook_arguments import (
4
+ CookbookArguments as CookbookPydanticModel,
5
+ )
6
+
7
+
8
+ class CookbookResponseModel(CookbookPydanticModel):
9
+ total_prompt_in_cookbook: Optional[int] = None
@@ -0,0 +1,9 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class DatasetResponseDTO(BaseModel):
5
+ id: str
6
+ name: str
7
+ description: str
8
+ num_of_dataset_prompts: int
9
+ created_date: str
@@ -0,0 +1,21 @@
1
+ from typing import Optional
2
+
3
+ from moonshot.src.connectors_endpoints.connector_endpoint_arguments import (
4
+ ConnectorEndpointArguments as ConnectorEndpointPydanticModel,
5
+ )
6
+
7
+
8
+ class EndpointCreateDTO(ConnectorEndpointPydanticModel):
9
+ id: Optional[str] = None
10
+
11
+
12
+ class EndpointUpdateDTO(ConnectorEndpointPydanticModel):
13
+ id: Optional[str] = None
14
+ name: Optional[str] = None
15
+ connector_type: Optional[str] = None
16
+ uri: Optional[str] = None
17
+ token: Optional[str] = None
18
+ max_calls_per_second: Optional[int] = None
19
+ max_concurrency: Optional[int] = None
20
+ params: Optional[dict] = None
21
+ created_date: Optional[str] = None
@@ -0,0 +1,11 @@
1
+ from moonshot.src.connectors_endpoints.connector_endpoint_arguments import (
2
+ ConnectorEndpointArguments as ConnectorEndpointPydanticModel,
3
+ )
4
+
5
+
6
+ class EndpointDataModel(ConnectorEndpointPydanticModel):
7
+ pass
8
+
9
+ def mask_token(self):
10
+ if self.token:
11
+ self.token = "*" * len(self.token)
@@ -0,0 +1,14 @@
1
+ from pydantic import BaseModel, RootModel
2
+
3
+ from ..schemas.session_response_model import ChatRecord
4
+
5
+
6
+
7
+ class PromptInfo(BaseModel):
8
+ current_runner_id: str
9
+ current_chats: dict[str, list[ChatRecord]]
10
+ current_batch_size: int
11
+ current_status: str
12
+
13
+
14
+ PromptResponseModel = RootModel[PromptInfo]
@@ -0,0 +1,10 @@
1
+ from pydantic import BaseModel, RootModel
2
+
3
+
4
+ class PromptTemplate(BaseModel):
5
+ name: str
6
+ description: str
7
+ template: str
8
+
9
+
10
+ PromptTemplatesResponseModel = RootModel[list[PromptTemplate]]
@@ -0,0 +1,32 @@
1
+ from typing import Optional
2
+
3
+ from moonshot.src.recipes.recipe_arguments import RecipeArguments as RecipePydanticModel
4
+
5
+ from pydantic import Field
6
+
7
+ class RecipeCreateDTO(RecipePydanticModel):
8
+ id: Optional[str] = None
9
+ name: str = Field(..., min_length=1)
10
+ description: Optional[str] = Field(default="", min_length=1)
11
+ tags: Optional[list[str]] = None
12
+ categories: Optional[list[str]] = None
13
+ datasets: list[str] = Field(..., min_length=1)
14
+ metrics: list[str] = Field(..., min_length=1)
15
+ prompt_templates: Optional[list[str]] = None
16
+ attack_modules: Optional[list[str]] = None
17
+ grading_scale: Optional[dict[str, list[int]]] = None
18
+ stats: Optional[dict] = None
19
+
20
+
21
+ class RecipeUpdateDTO(RecipePydanticModel):
22
+ id: Optional[str] = None
23
+ name: Optional[str] = None
24
+ description: Optional[str] = Field(default="", min_length=1)
25
+ tags: Optional[list[str]] = None
26
+ categories: Optional[list[str]] = None
27
+ datasets: Optional[list[str]] = None
28
+ prompt_templates: Optional[list[str]] = None
29
+ metrics: Optional[list[str]] = None
30
+ attack_modules: Optional[list[str]] = None
31
+ grading_scale: Optional[dict[str, list[int]]] = None
32
+ stats: Optional[dict] = None
@@ -0,0 +1,7 @@
1
+ from typing import Optional
2
+
3
+ from moonshot.src.recipes.recipe_arguments import RecipeArguments as RecipePydanticModel
4
+
5
+
6
+ class RecipeResponseModel(RecipePydanticModel):
7
+ total_prompt_in_recipe: Optional[int] = None
@@ -0,0 +1,16 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, Field
4
+
5
+
6
+ class SessionCreateDTO(BaseModel):
7
+ model_config = ConfigDict(from_attributes=True)
8
+ name: str = Field(min_length=3)
9
+ description: Optional[str] = Field(default="", max_length=1000)
10
+ endpoints: list[str] = Field(min_length=1)
11
+ context_strategy: str = ""
12
+ prompt_template: str = ""
13
+ attack_module: str = ""
14
+ metric: str = ""
15
+ system_prompt: str = ""
16
+ cs_num_of_prev_prompts: int = 5
@@ -0,0 +1,7 @@
1
+ from pydantic import BaseModel, ConfigDict, Field
2
+
3
+
4
+ class SessionPromptDTO(BaseModel):
5
+ model_config = ConfigDict(from_attributes=True)
6
+ history_length: int | None = 10
7
+ user_prompt: str = Field(min_length=1)
@@ -0,0 +1,38 @@
1
+ from typing import Dict, List, Optional
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class ChatRecord(BaseModel):
7
+ conn_id: str
8
+ context_strategy: Optional[str]
9
+ prompt_template: Optional[str]
10
+ attack_module: Optional[str]
11
+ metric: Optional[str]
12
+ prompt: str
13
+ prepared_prompt: str
14
+ system_prompt: Optional[str]
15
+ predicted_result: str
16
+ duration: str
17
+ prompt_time: str
18
+
19
+
20
+ class SessionMetadataModel(BaseModel):
21
+ session_id: str = Field(min_length=1)
22
+ description: Optional[str] = ""
23
+ endpoints: List[str] = Field(min_length=1)
24
+ created_epoch: str
25
+ created_datetime: str = Field(min_length=1)
26
+ prompt_template: Optional[str]
27
+ context_strategy: Optional[str]
28
+ cs_num_of_prev_prompts: int | None = 5
29
+ attack_module: Optional[str]
30
+ metric: Optional[str]
31
+ system_prompt: Optional[str]
32
+
33
+
34
+ class SessionResponseModel(BaseModel):
35
+ session_name: str
36
+ session_description: str
37
+ session: SessionMetadataModel
38
+ chat_records: Optional[Dict[str, List[ChatRecord]]]
File without changes
@@ -0,0 +1,34 @@
1
+ from .... import api as moonshot_api
2
+ from .base_service import BaseService
3
+ from .utils.exceptions_handler import exception_handler
4
+
5
+
6
+ class AttackModuleService(BaseService):
7
+ @exception_handler
8
+ def get_all_attack_module(self) -> list[str]:
9
+ """
10
+ Retrieves a list of all available attack modules.
11
+
12
+ This method wraps the `api_get_all_attack_modules` function from the moonshot API and returns
13
+ a list of attack module names.
14
+
15
+ Returns:
16
+ list[str]: A list of strings, each denoting the name of an attack module.
17
+ """
18
+ attack_modules = moonshot_api.api_get_all_attack_modules()
19
+ return attack_modules
20
+
21
+ @exception_handler
22
+ def get_all_attack_module_metadata(self) -> list[dict]:
23
+ """
24
+ Retrieves metadata for all available attack modules.
25
+
26
+ This method calls the `api_get_all_attack_module_metadata` function from the moonshot API. It collects
27
+ metadata for each attack module, which includes details such as the module's name, description, and
28
+ any other relevant information provided by the module's `get_metadata` method.
29
+
30
+ Returns:
31
+ list[dict]: A list of dictionaries, each containing metadata of an attack module.
32
+ """
33
+ am_metadata = moonshot_api.api_get_all_attack_module_metadata()
34
+ return am_metadata
@@ -0,0 +1,86 @@
1
+ import asyncio
2
+ import uuid
3
+ from typing import Any
4
+
5
+ from dependency_injector.wiring import inject
6
+
7
+ from moonshot.src.runners.runner import Runner
8
+
9
+ from ..services.auto_red_team_test_state import AutoRedTeamTestState
10
+ from ..services.base_service import BaseService
11
+ from ..services.runner_service import RunnerService
12
+ from ..status_updater.interface.redteam_progress_callback import (
13
+ InterfaceRedTeamProgressCallback,
14
+ )
15
+ from ..types.types import RedTeamTestProgress
16
+
17
+
18
+ class AutoRedTeamTestManager(BaseService):
19
+ @inject
20
+ def __init__(
21
+ self,
22
+ auto_red_team_test_state: AutoRedTeamTestState,
23
+ progress_status_updater: InterfaceRedTeamProgressCallback,
24
+ runner_service: RunnerService,
25
+ ) -> None:
26
+ """
27
+ Initialize the SessionService with dependencies.
28
+
29
+ Args:
30
+ progress_status_updater (InterfaceRedTeamProgressCallback): The callback interface for progress updates.
31
+ runner_service (RunnerService): The service for managing runners.
32
+ """
33
+ self.auto_red_team_test_state = auto_red_team_test_state
34
+ self.progress_status_updater = progress_status_updater
35
+ self.runner_service = runner_service
36
+ super().__init__()
37
+
38
+ def generate_unique_task_id(self) -> str:
39
+ unique_id = str(uuid.uuid4())
40
+ return f"task_{unique_id}"
41
+
42
+ def add_task(
43
+ self, executor_id: str, task: asyncio.Task[Any], moonshot_runner: Runner
44
+ ) -> None:
45
+ self.auto_red_team_test_state.add_task(executor_id, task, moonshot_runner)
46
+
47
+ def remove_task(self, executor_id: str) -> None:
48
+ self.auto_red_team_test_state.remove_task(executor_id)
49
+
50
+ async def cancel_task(self, executor_id: str) -> None:
51
+ await self.auto_red_team_test_state.cancel_task(executor_id)
52
+
53
+ def update_progress_status(self, updates: RedTeamTestProgress):
54
+ self.auto_red_team_test_state.update_progress_status(updates)
55
+
56
+ def on_task_completed(self, task: asyncio.Task[Any]) -> None:
57
+ self.logger.debug(f"Task {task.get_name()} has completed")
58
+
59
+ async def schedule_art_task(
60
+ self, art_args: dict, active_runner: Runner, batch_size: int
61
+ ) -> str:
62
+ task_id = self.generate_unique_task_id()
63
+
64
+ auto_redteam_coroutine = self.send_art_prompt(
65
+ art_args, active_runner, batch_size
66
+ )
67
+
68
+ task = asyncio.create_task(auto_redteam_coroutine, name=task_id)
69
+
70
+ def on_executor_completion(task: asyncio.Task[Any]):
71
+ if task.exception():
72
+ self.logger.error(
73
+ f"Executor {task.get_name()} has failed - {task.exception()}"
74
+ )
75
+ else:
76
+ self.logger.debug(f"Executor {task.get_name()} has completed")
77
+
78
+ task.add_done_callback(on_executor_completion)
79
+
80
+ self.add_task(active_runner.id, task, active_runner)
81
+ return active_runner.id
82
+
83
+ async def send_art_prompt(self, art_args, active_runner: Runner, batch_size: int):
84
+ await active_runner.run_red_teaming(
85
+ {"attack_strategies": [art_args], "chat_batch_size": batch_size}
86
+ )
@@ -0,0 +1,57 @@
1
+ import asyncio
2
+ from typing import Any, TypedDict
3
+
4
+ from moonshot.integrations.web_api.services.base_service import BaseService
5
+ from moonshot.integrations.web_api.types.types import RedTeamTestProgress
6
+ from moonshot.src.runners.runner import Runner
7
+
8
+
9
+ class AutoRedTeamTaskInfo(TypedDict):
10
+ async_task: asyncio.Task[Any]
11
+ moonshot_runner: Runner
12
+ status: RedTeamTestProgress | None
13
+
14
+
15
+ class AutoRedTeamTestState(BaseService):
16
+ state: dict[str, AutoRedTeamTaskInfo] = {}
17
+
18
+ def add_task(
19
+ self, id: str, task: asyncio.Task[Any], moonshot_runner: Runner
20
+ ) -> None:
21
+ self.state[id] = {
22
+ "async_task": task,
23
+ "moonshot_runner": moonshot_runner,
24
+ "status": None,
25
+ }
26
+
27
+ def remove_task(self, id: str) -> AutoRedTeamTaskInfo:
28
+ return self.state.pop(id)
29
+
30
+ async def cancel_task(self, id: str) -> None:
31
+ task_info = self.state[id]
32
+ if task_info and not task_info["async_task"].done():
33
+ if task_info["moonshot_runner"]:
34
+ await task_info["moonshot_runner"].cancel()
35
+ task_info["async_task"].cancel()
36
+ self.logger.debug(f"Task {id} has been cancelled")
37
+ else:
38
+ self.logger.debug(f"Task {id} is already completed or does not exist.")
39
+
40
+ def update_progress_status(self, updates: RedTeamTestProgress) -> None:
41
+ self.logger.debug(updates)
42
+ self.state[updates["current_runner_id"]]["status"] = updates
43
+
44
+ def get_state(self) -> dict[str, AutoRedTeamTaskInfo]:
45
+ return self.state
46
+
47
+ def get_progress_status(self, id: str) -> RedTeamTestProgress | None:
48
+ if id in self.state:
49
+ return self.state[id]["status"]
50
+ return None
51
+
52
+ def get_all_progress_status(self) -> dict[str, RedTeamTestProgress]:
53
+ return {
54
+ id: task_info["status"]
55
+ for id, task_info in self.state.items()
56
+ if task_info["status"] is not None
57
+ }
@@ -0,0 +1,8 @@
1
+ import logging
2
+
3
+
4
+ class BaseService:
5
+ def __init__(self) -> None:
6
+ self.logger = logging.getLogger(
7
+ f"{__name__}.{self.__class__.__name__}",
8
+ )
@@ -0,0 +1,25 @@
1
+ from .... import api as moonshot_api
2
+ from ..services.base_service import BaseService
3
+ from ..services.utils.exceptions_handler import exception_handler
4
+ from ..types.types import BenchmarkResult
5
+
6
+
7
+ class BenchmarkResultService(BaseService):
8
+ @exception_handler
9
+ def get_all_results(self) -> list[BenchmarkResult]:
10
+ results = moonshot_api.api_get_all_result()
11
+ return [BenchmarkResult(**result) for result in results]
12
+
13
+ @exception_handler
14
+ def get_all_result_name(self) -> list[str] | None:
15
+ results = moonshot_api.api_get_all_result_name()
16
+ return results
17
+
18
+ @exception_handler
19
+ def get_result_by_id(self, result_id: str) -> BenchmarkResult:
20
+ result = moonshot_api.api_read_result(result_id)
21
+ return BenchmarkResult(**result)
22
+
23
+ @exception_handler
24
+ def delete_result(self, result_id: str) -> None:
25
+ moonshot_api.api_delete_result(result_id)