aiverify-moonshot 0.4.11__py3-none-any.whl → 0.5.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.
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/METADATA +3 -5
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/RECORD +34 -34
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/WHEEL +1 -1
- moonshot/integrations/cli/benchmark/cookbook.py +1 -5
- moonshot/integrations/cli/benchmark/recipe.py +1 -5
- moonshot/integrations/cli/cli_errors.py +3 -0
- moonshot/integrations/cli/common/connectors.py +22 -10
- moonshot/integrations/web_api/app.py +1 -1
- moonshot/integrations/web_api/schemas/endpoint_create_dto.py +1 -0
- moonshot/integrations/web_api/services/endpoint_service.py +1 -0
- moonshot/src/api/api_bookmark.py +16 -5
- moonshot/src/api/api_connector.py +3 -3
- moonshot/src/api/api_connector_endpoint.py +6 -3
- moonshot/src/api/api_context_strategy.py +2 -2
- moonshot/src/api/api_cookbook.py +6 -6
- moonshot/src/api/api_dataset.py +5 -5
- moonshot/src/api/api_environment_variables.py +3 -0
- moonshot/src/api/api_metrics.py +1 -1
- moonshot/src/api/api_prompt_template.py +9 -0
- moonshot/src/api/api_recipe.py +3 -3
- moonshot/src/api/api_red_teaming.py +4 -8
- moonshot/src/api/api_result.py +10 -6
- moonshot/src/api/api_run.py +3 -3
- moonshot/src/api/api_runner.py +7 -6
- moonshot/src/api/api_session.py +11 -7
- moonshot/src/connectors/connector.py +121 -58
- moonshot/src/connectors/connector_prompt_arguments.py +7 -4
- moonshot/src/connectors/connector_response.py +5 -10
- moonshot/src/connectors_endpoints/connector_endpoint.py +32 -20
- moonshot/src/connectors_endpoints/connector_endpoint_arguments.py +4 -1
- moonshot/src/messages_constants.py +85 -3
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/licenses/AUTHORS.md +0 -0
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/licenses/LICENSE.md +0 -0
- {aiverify_moonshot-0.4.11.dist-info → aiverify_moonshot-0.5.0.dist-info}/licenses/NOTICES.md +0 -0
moonshot/src/api/api_recipe.py
CHANGED
|
@@ -79,7 +79,7 @@ def api_read_recipes(rec_ids: conlist(str, min_length=1)) -> list[dict]:
|
|
|
79
79
|
and returns a list of dictionaries containing each recipe's information.
|
|
80
80
|
|
|
81
81
|
Args:
|
|
82
|
-
rec_ids (
|
|
82
|
+
rec_ids (conlist(str, min_length=1)): The IDs of the recipes.
|
|
83
83
|
|
|
84
84
|
Returns:
|
|
85
85
|
list[dict]: A list of dictionaries, each containing a recipe's information.
|
|
@@ -155,7 +155,7 @@ def api_get_all_recipe() -> list[dict]:
|
|
|
155
155
|
"""
|
|
156
156
|
Retrieves all available recipes.
|
|
157
157
|
|
|
158
|
-
This function calls the
|
|
158
|
+
This function calls the get_available_items method to retrieve all available recipes. It then converts each
|
|
159
159
|
recipe into a dictionary using the to_dict method and returns a list of these dictionaries.
|
|
160
160
|
|
|
161
161
|
Returns:
|
|
@@ -169,7 +169,7 @@ def api_get_all_recipe_name() -> list[str]:
|
|
|
169
169
|
"""
|
|
170
170
|
Retrieves all available recipe names.
|
|
171
171
|
|
|
172
|
-
This function calls the
|
|
172
|
+
This function calls the get_available_items method to retrieve all available recipes. It then extracts the names
|
|
173
173
|
of each recipe and returns a list of these names.
|
|
174
174
|
|
|
175
175
|
Returns:
|
|
@@ -11,9 +11,7 @@ def api_get_all_attack_modules() -> list[str]:
|
|
|
11
11
|
Retrieves all available attack module IDs.
|
|
12
12
|
|
|
13
13
|
This function calls the `get_available_items` method from the `AttackModule` class to retrieve all available
|
|
14
|
-
attack modules.
|
|
15
|
-
|
|
16
|
-
It then extracts the IDs of each attack module and returns a list of these IDs.
|
|
14
|
+
attack modules. It then extracts the IDs of each attack module and returns a list of these IDs.
|
|
17
15
|
|
|
18
16
|
Returns:
|
|
19
17
|
list[str]: A list of strings, each representing an attack module ID.
|
|
@@ -27,10 +25,8 @@ def api_get_all_attack_module_metadata() -> list[dict]:
|
|
|
27
25
|
Retrieves metadata for all available attack modules.
|
|
28
26
|
|
|
29
27
|
This function calls the `get_available_items` method from the `AttackModule` class to retrieve all available
|
|
30
|
-
attack modules metadata
|
|
31
|
-
|
|
32
|
-
It then extracts the metadata for each attack module and returns a list of dictionaries, each containing the
|
|
33
|
-
metadata of an attack module.
|
|
28
|
+
attack modules. It then extracts the metadata for each attack module and returns a list of dictionaries,
|
|
29
|
+
each containing the metadata of an attack module.
|
|
34
30
|
|
|
35
31
|
Returns:
|
|
36
32
|
list[dict]: A list of dictionaries, each representing the metadata of an attack module.
|
|
@@ -44,7 +40,7 @@ def api_delete_attack_module(am_id: str) -> bool:
|
|
|
44
40
|
"""
|
|
45
41
|
Deletes an attack module by its identifier.
|
|
46
42
|
|
|
47
|
-
This function takes an attack module ID as input and calls the delete method from the AttackModule class
|
|
43
|
+
This function takes an attack module ID as input and calls the `delete` method from the `AttackModule` class
|
|
48
44
|
to remove the specified attack module from storage.
|
|
49
45
|
|
|
50
46
|
Args:
|
moonshot/src/api/api_result.py
CHANGED
|
@@ -11,7 +11,7 @@ def api_read_result(res_id: str) -> dict:
|
|
|
11
11
|
"""
|
|
12
12
|
Reads a result and returns its information.
|
|
13
13
|
|
|
14
|
-
This function takes a result ID as input, reads the corresponding
|
|
14
|
+
This function takes a result ID as input, reads the corresponding result from the storage manager,
|
|
15
15
|
and returns a dictionary containing the result's information.
|
|
16
16
|
|
|
17
17
|
Args:
|
|
@@ -28,7 +28,7 @@ def api_read_results(res_ids: conlist(str, min_length=1)) -> list[dict]:
|
|
|
28
28
|
"""
|
|
29
29
|
Reads multiple results and returns their information.
|
|
30
30
|
|
|
31
|
-
This function takes a list of result IDs as input, reads the corresponding
|
|
31
|
+
This function takes a list of result IDs as input, reads the corresponding results from the storage manager,
|
|
32
32
|
and returns a list of dictionaries, each containing a result's information.
|
|
33
33
|
|
|
34
34
|
Args:
|
|
@@ -37,7 +37,6 @@ def api_read_results(res_ids: conlist(str, min_length=1)) -> list[dict]:
|
|
|
37
37
|
Returns:
|
|
38
38
|
list[dict]: A list of dictionaries, each containing a result's information.
|
|
39
39
|
"""
|
|
40
|
-
|
|
41
40
|
return [Result.read(res_id) for res_id in res_ids]
|
|
42
41
|
|
|
43
42
|
|
|
@@ -63,11 +62,13 @@ def api_delete_result(res_id: str) -> bool:
|
|
|
63
62
|
|
|
64
63
|
def api_get_all_result() -> list[dict]:
|
|
65
64
|
"""
|
|
66
|
-
This function retrieves all available results and returns them as a list of dictionaries.
|
|
67
|
-
|
|
65
|
+
This function retrieves all available results and returns them as a list of dictionaries.
|
|
66
|
+
|
|
67
|
+
This function calls the get_available_items method from the Result class to retrieve all available results.
|
|
68
|
+
It then returns a list of dictionaries, each containing the details of a result.
|
|
68
69
|
|
|
69
70
|
Returns:
|
|
70
|
-
list[dict]: A list of dictionaries, each representing a result.
|
|
71
|
+
list[dict]: A list of dictionaries, each representing a result's details.
|
|
71
72
|
"""
|
|
72
73
|
_, results = Result.get_available_items()
|
|
73
74
|
return [result for result in results]
|
|
@@ -77,6 +78,9 @@ def api_get_all_result_name() -> list[str]:
|
|
|
77
78
|
"""
|
|
78
79
|
This function retrieves all available result names and returns them as a list.
|
|
79
80
|
|
|
81
|
+
This function calls the get_available_items method from the Result class to retrieve all available results.
|
|
82
|
+
It then extracts the names of each result and returns a list of these names.
|
|
83
|
+
|
|
80
84
|
Returns:
|
|
81
85
|
list[str]: A list of result names.
|
|
82
86
|
"""
|
moonshot/src/api/api_run.py
CHANGED
|
@@ -14,7 +14,7 @@ def api_get_all_run(runner_id: str = "") -> list[dict]:
|
|
|
14
14
|
|
|
15
15
|
Args:
|
|
16
16
|
runner_id (str, optional): The ID of the runner to retrieve runs for. If empty, runs for all runners
|
|
17
|
-
|
|
17
|
+
are retrieved.
|
|
18
18
|
|
|
19
19
|
Returns:
|
|
20
20
|
list[dict]: A list of dictionaries, each representing a run's data.
|
|
@@ -34,8 +34,8 @@ def _api_get_available_runs(
|
|
|
34
34
|
RunArguments instances representing the runs.
|
|
35
35
|
|
|
36
36
|
Args:
|
|
37
|
-
runner_id (str): The ID of the runner for which to retrieve run information. If empty, information
|
|
38
|
-
|
|
37
|
+
runner_id (str, optional): The ID of the runner for which to retrieve run information. If empty, information
|
|
38
|
+
for all runners is retrieved.
|
|
39
39
|
|
|
40
40
|
Returns:
|
|
41
41
|
tuple[list[str], list[RunArguments]]: A tuple containing a list of runner IDs and a list of RunArguments
|
moonshot/src/api/api_runner.py
CHANGED
|
@@ -20,7 +20,7 @@ def api_create_runner(
|
|
|
20
20
|
Creates a new runner.
|
|
21
21
|
|
|
22
22
|
This function takes the name, endpoints, and an optional progress callback function to create a new Runner instance.
|
|
23
|
-
The
|
|
23
|
+
The ID of the runner is generated from the name of the runner using the slugify function,
|
|
24
24
|
so it does not need to be provided.
|
|
25
25
|
|
|
26
26
|
Args:
|
|
@@ -59,7 +59,8 @@ def api_load_runner(
|
|
|
59
59
|
|
|
60
60
|
Args:
|
|
61
61
|
runner_id (str): The ID of the runner to be loaded.
|
|
62
|
-
progress_callback_func (Callable | None):
|
|
62
|
+
progress_callback_func (Callable | None, optional): An optional progress callback function for the runner.
|
|
63
|
+
Defaults to None.
|
|
63
64
|
|
|
64
65
|
Returns:
|
|
65
66
|
Runner: An initialized Runner object.
|
|
@@ -108,8 +109,8 @@ def api_get_all_runner() -> list[dict]:
|
|
|
108
109
|
"""
|
|
109
110
|
Retrieves all available runners.
|
|
110
111
|
|
|
111
|
-
This function calls the get_available_items method to retrieve all available runners.
|
|
112
|
-
runner into a dictionary using the to_dict method and returns a list of these dictionaries.
|
|
112
|
+
This function calls the get_available_items method from the Runner class to retrieve all available runners.
|
|
113
|
+
It then converts each runner into a dictionary using the to_dict method and returns a list of these dictionaries.
|
|
113
114
|
|
|
114
115
|
Returns:
|
|
115
116
|
list[dict]: A list of dictionaries, each representing a runner.
|
|
@@ -122,8 +123,8 @@ def api_get_all_runner_name() -> list[str]:
|
|
|
122
123
|
"""
|
|
123
124
|
Retrieves all available runner names.
|
|
124
125
|
|
|
125
|
-
This function calls the get_available_items method to retrieve all available runners.
|
|
126
|
-
each runner and returns a list of these names.
|
|
126
|
+
This function calls the get_available_items method from the Runner class to retrieve all available runners.
|
|
127
|
+
It then extracts the names of each runner and returns a list of these names.
|
|
127
128
|
|
|
128
129
|
Returns:
|
|
129
130
|
list[str]: A list of runner names.
|
moonshot/src/api/api_session.py
CHANGED
|
@@ -43,11 +43,14 @@ def api_create_session(
|
|
|
43
43
|
Args:
|
|
44
44
|
runner_id (str): The unique identifier of the runner for which the session is to be created.
|
|
45
45
|
database_instance (Any): The database instance to be used for the session.
|
|
46
|
-
endpoints (list): A list of endpoints for the session.
|
|
46
|
+
endpoints (list[str]): A list of endpoints for the session.
|
|
47
47
|
runner_args (dict): A dictionary of arguments for the runner.
|
|
48
48
|
|
|
49
49
|
Returns:
|
|
50
|
-
Session
|
|
50
|
+
Session: A new Session object.
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
RuntimeError: If the runner_id is empty or if the database_instance is not provided.
|
|
51
54
|
"""
|
|
52
55
|
if isinstance(database_instance, DBInterface):
|
|
53
56
|
if runner_id:
|
|
@@ -86,16 +89,16 @@ def api_get_all_session_names() -> list[str]:
|
|
|
86
89
|
return session_names
|
|
87
90
|
|
|
88
91
|
|
|
89
|
-
def api_get_available_session_info() -> tuple[list, list]:
|
|
92
|
+
def api_get_available_session_info() -> tuple[list[str], list[dict]]:
|
|
90
93
|
"""
|
|
91
|
-
Retrieves the IDs and
|
|
94
|
+
Retrieves the IDs and metadata of runners with active sessions.
|
|
92
95
|
|
|
93
|
-
This function retrieves the IDs and
|
|
96
|
+
This function retrieves the IDs and metadata of runners with active sessions by querying all runners
|
|
94
97
|
and checking if each runner has an active session. It returns a tuple containing a list of runner IDs and a list
|
|
95
98
|
of corresponding session metadata for runners with active sessions.
|
|
96
99
|
|
|
97
100
|
Returns:
|
|
98
|
-
tuple[list[str], list[
|
|
101
|
+
tuple[list[str], list[dict]]: A tuple containing a list of runner IDs and a list of corresponding session
|
|
99
102
|
metadata for runners with active sessions.
|
|
100
103
|
"""
|
|
101
104
|
runners_info = api_get_all_runner()
|
|
@@ -122,7 +125,8 @@ def api_get_all_session_metadata() -> list[dict]:
|
|
|
122
125
|
This function retrieves the metadata for all active sessions by calling the `api_get_available_session_info` method.
|
|
123
126
|
|
|
124
127
|
Returns:
|
|
125
|
-
list: A list containing the metadata for all active sessions, sorted by created datetime in
|
|
128
|
+
list[dict]: A list containing the metadata for all active sessions, sorted by created datetime in
|
|
129
|
+
descending order.
|
|
126
130
|
"""
|
|
127
131
|
_, session_metadata_list = api_get_available_session_info()
|
|
128
132
|
return sorted(
|
|
@@ -3,17 +3,32 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import time
|
|
5
5
|
from abc import abstractmethod
|
|
6
|
-
from
|
|
7
|
-
from functools import wraps
|
|
6
|
+
from functools import partial, wraps
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from typing import Callable
|
|
10
9
|
|
|
10
|
+
from tenacity import RetryCallState, retry, stop_after_attempt, wait_random_exponential
|
|
11
|
+
|
|
11
12
|
from moonshot.src.configs.env_variables import EnvVariables
|
|
12
13
|
from moonshot.src.connectors.connector_prompt_arguments import ConnectorPromptArguments
|
|
13
14
|
from moonshot.src.connectors.connector_response import ConnectorResponse
|
|
14
15
|
from moonshot.src.connectors_endpoints.connector_endpoint_arguments import (
|
|
15
16
|
ConnectorEndpointArguments,
|
|
16
17
|
)
|
|
18
|
+
from moonshot.src.messages_constants import (
|
|
19
|
+
CONNECTOR_CREATE_CONNECTOR_ENDPOINT_ARGUMENTS_VALIDATION_ERROR,
|
|
20
|
+
CONNECTOR_CREATE_ERROR,
|
|
21
|
+
CONNECTOR_GET_AVAILABLE_ITEMS_ERROR,
|
|
22
|
+
CONNECTOR_GET_PREDICTION_ARGUMENTS_CONNECTOR_VALIDATION_ERROR,
|
|
23
|
+
CONNECTOR_GET_PREDICTION_ARGUMENTS_GENERATED_PROMPT_VALIDATION_ERROR,
|
|
24
|
+
CONNECTOR_GET_PREDICTION_ERROR,
|
|
25
|
+
CONNECTOR_GET_PREDICTION_INFO,
|
|
26
|
+
CONNECTOR_GET_PREDICTION_TIME_TAKEN_INFO,
|
|
27
|
+
CONNECTOR_LOAD_CONNECTOR_ENDPOINT_ARGUMENTS_VALIDATION_ERROR,
|
|
28
|
+
CONNECTOR_LOAD_CONNECTOR_INSTANCE_RUNTIME_ERROR,
|
|
29
|
+
CONNECTOR_PERFORM_RETRY_CALLBACK_ERROR,
|
|
30
|
+
CONNECTOR_SET_SYSTEM_PROMPT_VALIDATION_ERROR,
|
|
31
|
+
)
|
|
17
32
|
from moonshot.src.storage.storage import Storage
|
|
18
33
|
from moonshot.src.utils.import_modules import get_instance
|
|
19
34
|
from moonshot.src.utils.log import configure_logger
|
|
@@ -22,43 +37,56 @@ from moonshot.src.utils.log import configure_logger
|
|
|
22
37
|
logger = configure_logger(__name__)
|
|
23
38
|
|
|
24
39
|
|
|
40
|
+
def perform_retry_callback(connector_id: str, retry_state: RetryCallState) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Callback function to log retry attempts with detailed information.
|
|
43
|
+
|
|
44
|
+
This function is called by the tenacity library before each retry attempt.
|
|
45
|
+
It logs the retry attempt number, the sleep time before the next attempt,
|
|
46
|
+
the error message that caused the retry, and the connector ID.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
connector_id (str): The ID of the connector.
|
|
50
|
+
retry_state (RetryCallState): The state of the retry call, which includes
|
|
51
|
+
information about the current attempt, the exception raised, and the next action.
|
|
52
|
+
"""
|
|
53
|
+
sleep_time = retry_state.idle_for if retry_state else 0
|
|
54
|
+
exception = (
|
|
55
|
+
retry_state.outcome.exception() if retry_state.outcome else "Unknown exception"
|
|
56
|
+
)
|
|
57
|
+
logger.error(
|
|
58
|
+
CONNECTOR_PERFORM_RETRY_CALLBACK_ERROR.format(
|
|
59
|
+
connector_id=connector_id,
|
|
60
|
+
attempt_no=retry_state.attempt_number,
|
|
61
|
+
sleep=f"{sleep_time:.2f}",
|
|
62
|
+
message=str(exception),
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
25
67
|
def perform_retry(func):
|
|
26
68
|
"""
|
|
27
|
-
A decorator to perform retries on a function.
|
|
69
|
+
A decorator to perform retries on a function using tenacity.
|
|
28
70
|
|
|
29
|
-
This decorator wraps
|
|
30
|
-
if it fails. The number of
|
|
31
|
-
are determined by the `
|
|
32
|
-
attributes of the class instance.
|
|
71
|
+
This decorator wraps an asynchronous function to enable retrying the function call
|
|
72
|
+
if it fails. The number of attempts and the delay between attempts
|
|
73
|
+
are determined by the `max_attempts` attribute of the class instance.
|
|
33
74
|
|
|
34
|
-
|
|
35
|
-
|
|
75
|
+
Args:
|
|
76
|
+
func (Callable): The asynchronous function to be wrapped and retried.
|
|
36
77
|
|
|
37
78
|
Returns:
|
|
38
|
-
|
|
79
|
+
Callable: A wrapper function that includes retry logic.
|
|
39
80
|
"""
|
|
40
81
|
|
|
41
82
|
async def wrapper(self, *args, **kwargs):
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
except Exception as exc:
|
|
50
|
-
logger.warning(f"Operation failed. {str(exc)} - Retrying...")
|
|
51
|
-
|
|
52
|
-
# Perform retry
|
|
53
|
-
retry_count += 1
|
|
54
|
-
if retry_count <= self.retries_times:
|
|
55
|
-
delay = base_delay * (2**retry_count)
|
|
56
|
-
logger.warning(
|
|
57
|
-
f"Attempt {retry_count}, Retrying in {delay} seconds..."
|
|
58
|
-
)
|
|
59
|
-
await sleep(delay)
|
|
60
|
-
# Raise an exception
|
|
61
|
-
raise ConnectionError("Failed to get response.")
|
|
83
|
+
retry_decorator = retry(
|
|
84
|
+
wait=wait_random_exponential(min=1, max=60),
|
|
85
|
+
stop=stop_after_attempt(self.max_attempts),
|
|
86
|
+
after=partial(perform_retry_callback, self.id),
|
|
87
|
+
reraise=True,
|
|
88
|
+
)
|
|
89
|
+
return await retry_decorator(func)(self, *args, **kwargs)
|
|
62
90
|
|
|
63
91
|
return wrapper
|
|
64
92
|
|
|
@@ -71,6 +99,7 @@ class Connector:
|
|
|
71
99
|
self.token = ep_args.token
|
|
72
100
|
self.max_concurrency = ep_args.max_concurrency
|
|
73
101
|
self.max_calls_per_second = ep_args.max_calls_per_second
|
|
102
|
+
self.model = ep_args.model
|
|
74
103
|
self.params = ep_args.params
|
|
75
104
|
|
|
76
105
|
# Rate limiting
|
|
@@ -80,21 +109,19 @@ class Connector:
|
|
|
80
109
|
self.updated_at = time.time()
|
|
81
110
|
self.semaphore = asyncio.Semaphore(ep_args.max_concurrency)
|
|
82
111
|
|
|
83
|
-
# Set Prompts if they
|
|
112
|
+
# Set Prompts if they exist
|
|
84
113
|
self.pre_prompt = ep_args.params.get("pre_prompt", "")
|
|
85
114
|
self.post_prompt = ep_args.params.get("post_prompt", "")
|
|
86
115
|
self.system_prompt = ep_args.params.get("system_prompt", "")
|
|
87
116
|
|
|
88
117
|
# Connection timeout
|
|
89
118
|
self.timeout = ep_args.params.get("timeout", 600)
|
|
90
|
-
self.
|
|
91
|
-
self.retries_times = ep_args.params.get("num_of_retries", 3)
|
|
119
|
+
self.max_attempts = ep_args.params.get("max_attempts", 3)
|
|
92
120
|
|
|
93
121
|
# Optional params
|
|
94
122
|
excluded_keys = {
|
|
95
|
-
"allow_retries",
|
|
96
123
|
"timeout",
|
|
97
|
-
"
|
|
124
|
+
"max_attempts",
|
|
98
125
|
"pre_prompt",
|
|
99
126
|
"post_prompt",
|
|
100
127
|
"system_prompt",
|
|
@@ -114,10 +141,6 @@ class Connector:
|
|
|
114
141
|
|
|
115
142
|
The method updates the `updated_at` attribute to the current time after tokens are added, ensuring that
|
|
116
143
|
the next token addition will be calculated based on the correct elapsed time.
|
|
117
|
-
|
|
118
|
-
Usage:
|
|
119
|
-
# Assume `self` is an instance of a class with `rate_limiter`, `tokens`, and `updated_at` attributes.
|
|
120
|
-
await self.add_tokens()
|
|
121
144
|
"""
|
|
122
145
|
now = time.time()
|
|
123
146
|
elapsed = now - self.updated_at
|
|
@@ -144,11 +167,6 @@ class Connector:
|
|
|
144
167
|
|
|
145
168
|
Returns:
|
|
146
169
|
Callable: The decorated function wrapped with rate limiting logic.
|
|
147
|
-
|
|
148
|
-
Usage:
|
|
149
|
-
@rate_limited
|
|
150
|
-
async def some_async_function(*args, **kwargs):
|
|
151
|
-
# Function implementation
|
|
152
170
|
"""
|
|
153
171
|
|
|
154
172
|
@wraps(func)
|
|
@@ -187,7 +205,7 @@ class Connector:
|
|
|
187
205
|
@classmethod
|
|
188
206
|
def load(cls, ep_args: ConnectorEndpointArguments) -> Connector:
|
|
189
207
|
"""
|
|
190
|
-
|
|
208
|
+
Dynamically loads a connector instance based on the provided endpoint arguments.
|
|
191
209
|
|
|
192
210
|
The connector type specified in the `ep_args` is used to dynamically load the corresponding
|
|
193
211
|
connector class. The connector is then instantiated with the provided endpoint arguments. If the
|
|
@@ -203,17 +221,24 @@ class Connector:
|
|
|
203
221
|
Raises:
|
|
204
222
|
RuntimeError: If the specified connector type does not match any available connector classes.
|
|
205
223
|
"""
|
|
224
|
+
if ep_args is None or not isinstance(ep_args, ConnectorEndpointArguments):
|
|
225
|
+
raise ValueError(
|
|
226
|
+
CONNECTOR_LOAD_CONNECTOR_ENDPOINT_ARGUMENTS_VALIDATION_ERROR
|
|
227
|
+
)
|
|
228
|
+
|
|
206
229
|
connector_instance = get_instance(
|
|
207
230
|
ep_args.connector_type,
|
|
208
231
|
Storage.get_filepath(
|
|
209
232
|
EnvVariables.CONNECTORS.name, ep_args.connector_type, "py"
|
|
210
233
|
),
|
|
211
234
|
)
|
|
212
|
-
if connector_instance:
|
|
235
|
+
if connector_instance and isinstance(connector_instance, Callable):
|
|
213
236
|
return connector_instance(ep_args)
|
|
214
237
|
else:
|
|
215
238
|
raise RuntimeError(
|
|
216
|
-
|
|
239
|
+
CONNECTOR_LOAD_CONNECTOR_INSTANCE_RUNTIME_ERROR.format(
|
|
240
|
+
message=ep_args.connector_type
|
|
241
|
+
)
|
|
217
242
|
)
|
|
218
243
|
|
|
219
244
|
@staticmethod
|
|
@@ -223,7 +248,7 @@ class Connector:
|
|
|
223
248
|
|
|
224
249
|
This method takes a ConnectorEndpointArguments object, which contains the necessary information
|
|
225
250
|
to initialize and return a Connector object. The Connector object is created by calling the
|
|
226
|
-
`
|
|
251
|
+
`load` method, which dynamically loads and initializes the connector based on the
|
|
227
252
|
endpoint arguments provided.
|
|
228
253
|
|
|
229
254
|
Args:
|
|
@@ -231,12 +256,20 @@ class Connector:
|
|
|
231
256
|
|
|
232
257
|
Returns:
|
|
233
258
|
Connector: An initialized Connector object based on the provided endpoint arguments.
|
|
259
|
+
|
|
260
|
+
Raises:
|
|
261
|
+
ValueError: If the provided endpoint arguments are invalid.
|
|
262
|
+
Exception: If there is an error during the creation of the connector.
|
|
234
263
|
"""
|
|
235
264
|
try:
|
|
265
|
+
if ep_args is None or not isinstance(ep_args, ConnectorEndpointArguments):
|
|
266
|
+
raise ValueError(
|
|
267
|
+
CONNECTOR_CREATE_CONNECTOR_ENDPOINT_ARGUMENTS_VALIDATION_ERROR
|
|
268
|
+
)
|
|
236
269
|
return Connector.load(ep_args)
|
|
237
270
|
|
|
238
271
|
except Exception as e:
|
|
239
|
-
logger.error(
|
|
272
|
+
logger.error(CONNECTOR_CREATE_ERROR.format(message=str(e)))
|
|
240
273
|
raise e
|
|
241
274
|
|
|
242
275
|
@staticmethod
|
|
@@ -245,7 +278,7 @@ class Connector:
|
|
|
245
278
|
Fetches a list of all available connector types.
|
|
246
279
|
|
|
247
280
|
This method employs the `get_connectors` method to locate all Python files in the directory
|
|
248
|
-
defined by the `
|
|
281
|
+
defined by the `EnvVariables.CONNECTORS` environment variable. It subsequently excludes any files that are
|
|
249
282
|
not intended to be exposed as connectors (those containing "__" in their names). The method yields a list of the
|
|
250
283
|
names of these connector types.
|
|
251
284
|
|
|
@@ -263,7 +296,7 @@ class Connector:
|
|
|
263
296
|
]
|
|
264
297
|
|
|
265
298
|
except Exception as e:
|
|
266
|
-
logger.error(
|
|
299
|
+
logger.error(CONNECTOR_GET_AVAILABLE_ITEMS_ERROR.format(message=str(e)))
|
|
267
300
|
raise e
|
|
268
301
|
|
|
269
302
|
@staticmethod
|
|
@@ -299,9 +332,24 @@ class Connector:
|
|
|
299
332
|
Raises:
|
|
300
333
|
Exception: If there is an error during prediction.
|
|
301
334
|
"""
|
|
335
|
+
if generated_prompt is None or not isinstance(
|
|
336
|
+
generated_prompt, ConnectorPromptArguments
|
|
337
|
+
):
|
|
338
|
+
raise ValueError(
|
|
339
|
+
CONNECTOR_GET_PREDICTION_ARGUMENTS_GENERATED_PROMPT_VALIDATION_ERROR
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if connector is None or not isinstance(connector, Connector):
|
|
343
|
+
raise ValueError(
|
|
344
|
+
CONNECTOR_GET_PREDICTION_ARGUMENTS_CONNECTOR_VALIDATION_ERROR
|
|
345
|
+
)
|
|
346
|
+
|
|
302
347
|
try:
|
|
303
348
|
logger.info(
|
|
304
|
-
|
|
349
|
+
CONNECTOR_GET_PREDICTION_INFO.format(
|
|
350
|
+
connector_id=connector.id,
|
|
351
|
+
prompt_index=generated_prompt.prompt_index,
|
|
352
|
+
)
|
|
305
353
|
)
|
|
306
354
|
|
|
307
355
|
start_time = time.perf_counter()
|
|
@@ -310,7 +358,11 @@ class Connector:
|
|
|
310
358
|
)
|
|
311
359
|
generated_prompt.duration = time.perf_counter() - start_time
|
|
312
360
|
logger.debug(
|
|
313
|
-
|
|
361
|
+
CONNECTOR_GET_PREDICTION_TIME_TAKEN_INFO.format(
|
|
362
|
+
connector_id=connector.id,
|
|
363
|
+
prompt_index=generated_prompt.prompt_index,
|
|
364
|
+
prompt_duration=f"{generated_prompt.duration:.4f}",
|
|
365
|
+
)
|
|
314
366
|
)
|
|
315
367
|
|
|
316
368
|
# Call prompt callback
|
|
@@ -321,17 +373,28 @@ class Connector:
|
|
|
321
373
|
return generated_prompt
|
|
322
374
|
|
|
323
375
|
except Exception as e:
|
|
324
|
-
logger.error(
|
|
376
|
+
logger.error(
|
|
377
|
+
CONNECTOR_GET_PREDICTION_ERROR.format(
|
|
378
|
+
connector_id=connector.id,
|
|
379
|
+
prompt_index=generated_prompt.prompt_index,
|
|
380
|
+
message=str(e),
|
|
381
|
+
)
|
|
382
|
+
)
|
|
325
383
|
raise e
|
|
326
384
|
|
|
327
385
|
def set_system_prompt(self, system_prompt: str) -> None:
|
|
328
386
|
"""
|
|
329
|
-
|
|
387
|
+
Sets a new system prompt for this connector instance.
|
|
330
388
|
|
|
331
|
-
The system prompt
|
|
332
|
-
|
|
389
|
+
The system prompt is a predefined message or command that the connector can use to start interactions
|
|
390
|
+
or perform specific tasks.
|
|
333
391
|
|
|
334
|
-
|
|
392
|
+
Args:
|
|
335
393
|
system_prompt (str): The new system prompt to set for this connector.
|
|
394
|
+
|
|
395
|
+
Raises:
|
|
396
|
+
ValueError: If the provided system prompt is not a string or is None.
|
|
336
397
|
"""
|
|
398
|
+
if system_prompt is None or not isinstance(system_prompt, str):
|
|
399
|
+
raise ValueError(CONNECTOR_SET_SYSTEM_PROMPT_VALIDATION_ERROR)
|
|
337
400
|
self.system_prompt = system_prompt
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Annotated, Any
|
|
4
4
|
|
|
5
|
-
from pydantic import BaseModel
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
from moonshot.src.connectors.connector_response import ConnectorResponse
|
|
8
8
|
|
|
@@ -11,7 +11,9 @@ class ConnectorPromptArguments(BaseModel):
|
|
|
11
11
|
class Config:
|
|
12
12
|
arbitrary_types_allowed = True
|
|
13
13
|
|
|
14
|
-
prompt_index:
|
|
14
|
+
prompt_index: Annotated[
|
|
15
|
+
int, Field(strict=True, ge=0)
|
|
16
|
+
] # The index of the prompt in the dataset
|
|
15
17
|
|
|
16
18
|
prompt: str # The actual prompt text
|
|
17
19
|
|
|
@@ -21,4 +23,5 @@ class ConnectorPromptArguments(BaseModel):
|
|
|
21
23
|
None # The predicted results, default is None
|
|
22
24
|
)
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
# The duration it took to get the results, must be a positive float
|
|
27
|
+
duration: Annotated[float, Field(strict=True, ge=0.0)] = 0.0
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
def __init__(self, response: str, context: list = []):
|
|
3
|
-
"""
|
|
4
|
-
Initializes a ConnectorResponse instance.
|
|
1
|
+
from pydantic import BaseModel
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
self.response = response
|
|
11
|
-
self.context = context
|
|
3
|
+
|
|
4
|
+
class ConnectorResponse(BaseModel):
|
|
5
|
+
response: str = ""
|
|
6
|
+
context: list = []
|
|
12
7
|
|
|
13
8
|
def to_dict(self) -> dict:
|
|
14
9
|
"""
|