adaptive-sdk 0.1.0b1__tar.gz
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.
- adaptive_sdk-0.1.0b1/PKG-INFO +109 -0
- adaptive_sdk-0.1.0b1/README.md +79 -0
- adaptive_sdk-0.1.0b1/pyproject.toml +77 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/__init__.py +15 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/base_client.py +133 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/client.py +117 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/error_handling.py +86 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/__init__.py +24 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/base_model.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/constants.py +8 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/requests_journal.py +132 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/reward_client.py +169 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/reward_server.py +214 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/reward_types.py +87 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/external/websocket_utils.py +39 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/__init__.py +74 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/add_external_model.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/add_hf_model.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/add_model.py +18 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/add_remote_env.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/async_base_client_open_telemetry.py +309 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/async_client.py +557 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/attach_model_to_use_case.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/base_client_open_telemetry.py +150 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/base_model.py +22 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/base_operation.py +92 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/cancel_ab_campaign.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/cancel_evaluation_job.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/cancel_training_job.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/client.py +557 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_ab_campaign.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_custom_recipe_training_job.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_custom_script.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_evaluation_job.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_judge.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_metric.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_prebuilt_judge.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_role.py +16 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_team.py +15 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_training_job.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/create_use_case.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/custom_fields.py +2289 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/custom_mutations.py +308 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/custom_queries.py +244 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/custom_typing_fields.py +874 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/delete_judge.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/deploy_model.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_ab_campaign.py +18 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_dataset.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_evaluation_job.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_interaction.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_metric.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_metric_admin.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_model.py +17 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_model_admin.py +17 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_training_job.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/describe_use_case.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/enums.py +270 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/exceptions.py +65 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/fragments.py +727 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/generate_dataset.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/get_judge.py +11 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/input_types.py +716 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/link_metric.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_ab_campaigns.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_compute_pools.py +24 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_custom_scripts.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_datasets.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_evaluation_jobs.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_grouped_interactions.py +55 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_interactions.py +25 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_judge_versions.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_judges.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_metrics.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_models.py +17 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_partitions.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_permissions.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_remote_envs.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_roles.py +16 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_teams.py +15 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_training_jobs.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_use_cases.py +13 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/list_users.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/load_dataset.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/me.py +19 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/remove_remote_env.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/remove_team_member.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/terminate_model.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/test_remote_env.py +20 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/unlink_metric.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/update_judge.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/update_model.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/update_model_compute_config.py +12 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/graphql_client/update_user.py +35 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/input_types/__init__.py +79 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/input_types/typed_dicts.py +320 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/openapi.json +1 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/patch.py +9 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/__init__.py +74 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/abtests.py +209 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/base_resource.py +36 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/chat.py +296 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/completions.py +83 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/compute_pools.py +35 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/custom_recipe.py +151 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/datasets.py +242 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/embeddings.py +99 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/evaluation/__init__.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/evaluation/evaluation.py +17 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/evaluation/jobs.py +289 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/feedback.py +364 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/interactions.py +289 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/judges.py +258 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/models.py +480 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/permissions.py +35 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/reward_servers.py +90 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/roles.py +63 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/teams.py +43 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/training/__init__.py +6 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/training/constants.py +9 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/training/defaults.py +179 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/training/jobs.py +279 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/training/training.py +17 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/use_cases.py +115 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/resources/users.py +109 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/rest/__init__.py +36 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/rest/base_model.py +21 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/rest/rest_types.py +223 -0
- adaptive_sdk-0.1.0b1/src/adaptive_sdk/utils.py +41 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adaptive-sdk
|
|
3
|
+
Version: 0.1.0b1
|
|
4
|
+
Summary: Python SDK for Adaptive Engine
|
|
5
|
+
Author-email: Vincent Debergue <vincent@adaptive-ml.com>, Joao Moura <joao@adaptive-ml.com>, Yacine Bouraoui <yacine@adaptive-ml.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: httpx >= 0.27.2
|
|
9
|
+
Requires-Dist: gql >= 3.5.0
|
|
10
|
+
Requires-Dist: pydantic[email] >= 2.9.0
|
|
11
|
+
Requires-Dist: pyhumps >= 3.8.0
|
|
12
|
+
Requires-Dist: fastapi >= 0.115.8
|
|
13
|
+
Requires-Dist: uvicorn >= 0.34.0
|
|
14
|
+
Requires-Dist: jsonschema==4.24.0
|
|
15
|
+
Requires-Dist: websockets==15.0.1
|
|
16
|
+
Requires-Dist: types-jsonschema==4.23.0.20241208
|
|
17
|
+
Requires-Dist: loguru >= 0.7.0
|
|
18
|
+
Requires-Dist: ariadne-codegen ; extra == "dev"
|
|
19
|
+
Requires-Dist: datamodel-code-generator == 0.31.2 ; extra == "dev"
|
|
20
|
+
Requires-Dist: astor >= 0.8.1 ; extra == "dev"
|
|
21
|
+
Requires-Dist: pdoc >= 15.0.1 ; extra == "dev"
|
|
22
|
+
Requires-Dist: toml>=0.10.2 ; extra == "dev"
|
|
23
|
+
Requires-Dist: black==25.1.0 ; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest==8.4.1 ; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-asyncio==0.26.0 ; extra == "dev"
|
|
26
|
+
Requires-Dist: mypy==1.16.0 ; extra == "dev"
|
|
27
|
+
Requires-Dist: tenacity==9.1.2 ; extra == "dev"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
|
|
30
|
+
# adaptive-sdk
|
|
31
|
+
|
|
32
|
+
The Python Client SDK for Adaptive Engine
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install -e .
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from adaptive_sdk import Adaptive, AsyncAdaptive
|
|
45
|
+
|
|
46
|
+
client = Adaptive("http://localhost:9000", "key-kitt")
|
|
47
|
+
# aclient = AsyncAdaptive("http://localhost:9000", "key-kitt") # all the same methods as Adaptive, but async
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
use_case = client.create_use_case(name="Open Assistant", key="open_assistant")
|
|
51
|
+
print(f"Use case created id={use_case.id} key={use_case.key}")
|
|
52
|
+
except:
|
|
53
|
+
use_case = client.get_use_case("open_assistant")
|
|
54
|
+
|
|
55
|
+
if use_case is None:
|
|
56
|
+
raise Exception("Could not get or create a use case")
|
|
57
|
+
|
|
58
|
+
metrics = client.list_metrics()
|
|
59
|
+
if not any(metric.key == "accepted" for metric in metrics):
|
|
60
|
+
client.create_metric(name="accepted", key="accepted", kind="BOOL")
|
|
61
|
+
|
|
62
|
+
client.link_metric(use_case="open_assistant", metric="accepted")
|
|
63
|
+
|
|
64
|
+
model_attached = any(srv.model.key == "minimal" for srv in use_case.model_services)
|
|
65
|
+
if not model_attached:
|
|
66
|
+
client.attach_model(model="minimal", use_case="open_assistant", wait=False)
|
|
67
|
+
|
|
68
|
+
response = client.add_interactions(
|
|
69
|
+
model="minimal",
|
|
70
|
+
use_case=str(use_case.id),
|
|
71
|
+
messages=[{"role":"user", "content":"Prompt here"}],
|
|
72
|
+
completion="Completion here",
|
|
73
|
+
feedbacks=[{"metric":"accepted", "value":1, "details":"This was a good completion"}],
|
|
74
|
+
ab_campaign=None,
|
|
75
|
+
labels={"country": "Argentina"},
|
|
76
|
+
)
|
|
77
|
+
print(f"Interaction stored completion_id={response.completion_id}")
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
- Install dev dependencies
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install -e '.[dev]'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- Download new REST/GQL schemas, generate types, and format the resulting files
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
CONCORDE_URL="http://localhost:9000"
|
|
93
|
+
python generate_gql_pt_datamodel.py --base-url $CONCORDE_URL
|
|
94
|
+
python generate_openapi_datamodel.py --base-url $CONCORDE_URL
|
|
95
|
+
black src/adaptive_sdk/graphql_client
|
|
96
|
+
black src/adaptive_sdk/rest
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### How to add a new graphql query and/or new SDK methods/resources
|
|
100
|
+
|
|
101
|
+
1. Add the query or mutation in the file `src/adaptive_sdk/queries.graphql` (if REST schema changed, no need to write queries)
|
|
102
|
+
2. Regenerate graphql or REST types with the scripts above, depending on what has changed
|
|
103
|
+
3. If new REST types have been added or renamed, make sure to export them in `src/adaptive_sdk/rest/__init__.py` for the automatic SDK reference docs generator to pick up on.
|
|
104
|
+
3. Wrap the new queries/types in a nice, user-facing method respecting the existing naming conventions,
|
|
105
|
+
within the appropriate resource in `src/adaptive_sdk/resources` (create a new resource if needed).
|
|
106
|
+
4. If the input types for the new method are too complicated/nested, help the user by creating new TypedDict(s) and using them as input function parameter type hints, which enables nice suggestion for your new method, and self-documenting of methods. You can add these in `src/adaptive_sdk/input_types/typed_dicts.py`. If you add new typed dicts, make sure to export them in `src/adaptive_sdk/input_types/__init__.py`, so the automatic SDK reference docs generator picks up on them.
|
|
107
|
+
5. If you create a new resource, make sure to export it in `src/adaptive_sdk/resources/__init__.py`, and then add it without disrupting the alphabetical order of resources
|
|
108
|
+
in `src/adaptive_sdk/client.py`. Always add a new sync and async resource.
|
|
109
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# adaptive-sdk
|
|
2
|
+
|
|
3
|
+
The Python Client SDK for Adaptive Engine
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install -e .
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from adaptive_sdk import Adaptive, AsyncAdaptive
|
|
16
|
+
|
|
17
|
+
client = Adaptive("http://localhost:9000", "key-kitt")
|
|
18
|
+
# aclient = AsyncAdaptive("http://localhost:9000", "key-kitt") # all the same methods as Adaptive, but async
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
use_case = client.create_use_case(name="Open Assistant", key="open_assistant")
|
|
22
|
+
print(f"Use case created id={use_case.id} key={use_case.key}")
|
|
23
|
+
except:
|
|
24
|
+
use_case = client.get_use_case("open_assistant")
|
|
25
|
+
|
|
26
|
+
if use_case is None:
|
|
27
|
+
raise Exception("Could not get or create a use case")
|
|
28
|
+
|
|
29
|
+
metrics = client.list_metrics()
|
|
30
|
+
if not any(metric.key == "accepted" for metric in metrics):
|
|
31
|
+
client.create_metric(name="accepted", key="accepted", kind="BOOL")
|
|
32
|
+
|
|
33
|
+
client.link_metric(use_case="open_assistant", metric="accepted")
|
|
34
|
+
|
|
35
|
+
model_attached = any(srv.model.key == "minimal" for srv in use_case.model_services)
|
|
36
|
+
if not model_attached:
|
|
37
|
+
client.attach_model(model="minimal", use_case="open_assistant", wait=False)
|
|
38
|
+
|
|
39
|
+
response = client.add_interactions(
|
|
40
|
+
model="minimal",
|
|
41
|
+
use_case=str(use_case.id),
|
|
42
|
+
messages=[{"role":"user", "content":"Prompt here"}],
|
|
43
|
+
completion="Completion here",
|
|
44
|
+
feedbacks=[{"metric":"accepted", "value":1, "details":"This was a good completion"}],
|
|
45
|
+
ab_campaign=None,
|
|
46
|
+
labels={"country": "Argentina"},
|
|
47
|
+
)
|
|
48
|
+
print(f"Interaction stored completion_id={response.completion_id}")
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
- Install dev dependencies
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install -e '.[dev]'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Download new REST/GQL schemas, generate types, and format the resulting files
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
CONCORDE_URL="http://localhost:9000"
|
|
64
|
+
python generate_gql_pt_datamodel.py --base-url $CONCORDE_URL
|
|
65
|
+
python generate_openapi_datamodel.py --base-url $CONCORDE_URL
|
|
66
|
+
black src/adaptive_sdk/graphql_client
|
|
67
|
+
black src/adaptive_sdk/rest
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### How to add a new graphql query and/or new SDK methods/resources
|
|
71
|
+
|
|
72
|
+
1. Add the query or mutation in the file `src/adaptive_sdk/queries.graphql` (if REST schema changed, no need to write queries)
|
|
73
|
+
2. Regenerate graphql or REST types with the scripts above, depending on what has changed
|
|
74
|
+
3. If new REST types have been added or renamed, make sure to export them in `src/adaptive_sdk/rest/__init__.py` for the automatic SDK reference docs generator to pick up on.
|
|
75
|
+
3. Wrap the new queries/types in a nice, user-facing method respecting the existing naming conventions,
|
|
76
|
+
within the appropriate resource in `src/adaptive_sdk/resources` (create a new resource if needed).
|
|
77
|
+
4. If the input types for the new method are too complicated/nested, help the user by creating new TypedDict(s) and using them as input function parameter type hints, which enables nice suggestion for your new method, and self-documenting of methods. You can add these in `src/adaptive_sdk/input_types/typed_dicts.py`. If you add new typed dicts, make sure to export them in `src/adaptive_sdk/input_types/__init__.py`, so the automatic SDK reference docs generator picks up on them.
|
|
78
|
+
5. If you create a new resource, make sure to export it in `src/adaptive_sdk/resources/__init__.py`, and then add it without disrupting the alphabetical order of resources
|
|
79
|
+
in `src/adaptive_sdk/client.py`. Always add a new sync and async resource.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core>=3.4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "adaptive-sdk"
|
|
8
|
+
version = "0.1.0b1"
|
|
9
|
+
description = "Python SDK for Adaptive Engine"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Vincent Debergue", email = "vincent@adaptive-ml.com" },
|
|
12
|
+
{ name = "Joao Moura", email = "joao@adaptive-ml.com" },
|
|
13
|
+
{ name = "Yacine Bouraoui", email = "yacine@adaptive-ml.com" },
|
|
14
|
+
|
|
15
|
+
]
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
requires-python = ">=3.10"
|
|
18
|
+
dependencies = [
|
|
19
|
+
"httpx >= 0.27.2",
|
|
20
|
+
"gql >= 3.5.0",
|
|
21
|
+
"pydantic[email] >= 2.9.0",
|
|
22
|
+
"pyhumps >= 3.8.0",
|
|
23
|
+
"fastapi >= 0.115.8",
|
|
24
|
+
"uvicorn >= 0.34.0",
|
|
25
|
+
"jsonschema==4.24.0",
|
|
26
|
+
"websockets==15.0.1",
|
|
27
|
+
"types-jsonschema==4.23.0.20241208",
|
|
28
|
+
"loguru >= 0.7.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"ariadne-codegen",
|
|
34
|
+
"datamodel-code-generator == 0.31.2",
|
|
35
|
+
"astor >= 0.8.1",
|
|
36
|
+
"pdoc >= 15.0.1",
|
|
37
|
+
"toml>=0.10.2",
|
|
38
|
+
"black==25.1.0",
|
|
39
|
+
"pytest==8.4.1",
|
|
40
|
+
"pytest-asyncio==0.26.0",
|
|
41
|
+
"mypy==1.16.0",
|
|
42
|
+
"tenacity==9.1.2",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.ariadne-codegen]
|
|
46
|
+
schema_path = "schema.graphql"
|
|
47
|
+
queries_path = "queries.graphql"
|
|
48
|
+
target_package_name = "graphql_client"
|
|
49
|
+
target_package_path = "src/adaptive_sdk"
|
|
50
|
+
client_name = "GQLClient"
|
|
51
|
+
async_client = false
|
|
52
|
+
opentelemetry_client = true
|
|
53
|
+
enable_custom_operations = true
|
|
54
|
+
|
|
55
|
+
[tool.ariadne-codegen.scalars.IdOrKey]
|
|
56
|
+
type = "str"
|
|
57
|
+
[tool.ariadne-codegen.scalars.Timestamp]
|
|
58
|
+
type = "int"
|
|
59
|
+
[tool.ariadne-codegen.scalars.InputDatetime]
|
|
60
|
+
type = "int | str"
|
|
61
|
+
[tool.ariadne-codegen.scalars.TimestampSec]
|
|
62
|
+
type = "int"
|
|
63
|
+
|
|
64
|
+
[tool.mypy]
|
|
65
|
+
# Ignore missing type hints in imported libraries
|
|
66
|
+
ignore_missing_imports = true
|
|
67
|
+
|
|
68
|
+
files = "src/adaptive_sdk"
|
|
69
|
+
exclude = "src/adaptive_sdk/graphql_client/|src/adaptive_sdk/rest/"
|
|
70
|
+
allow_redefinition = true
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[tool.black]
|
|
74
|
+
required-version = '25.1.0'
|
|
75
|
+
|
|
76
|
+
[tool.uv.sources]
|
|
77
|
+
ariadne-codegen = { git = "https://github.com/adaptive-ml/ariadne-codegen", branch = "stabilise-output" }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .patch import *
|
|
2
|
+
from .client import Adaptive, AsyncAdaptive
|
|
3
|
+
from adaptive_sdk import resources, input_types, graphql_client, rest, external
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
__version__ = "0.0.1b1"
|
|
7
|
+
__all__ = [
|
|
8
|
+
"Adaptive",
|
|
9
|
+
"AsyncAdaptive",
|
|
10
|
+
"resources",
|
|
11
|
+
"input_types",
|
|
12
|
+
"graphql_client",
|
|
13
|
+
"rest",
|
|
14
|
+
"external",
|
|
15
|
+
]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
import os
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Optional, Dict
|
|
5
|
+
import httpx
|
|
6
|
+
from urllib.parse import urlparse
|
|
7
|
+
|
|
8
|
+
from .graphql_client import GQLClient, AsyncGQLClient
|
|
9
|
+
from .error_handling import graphql_multi_error_handler
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_version():
|
|
13
|
+
import importlib
|
|
14
|
+
|
|
15
|
+
return importlib.import_module("adaptive_sdk").__version__
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Routes(Enum):
|
|
19
|
+
GQL = "/api/graphql"
|
|
20
|
+
REST = "/api/v1"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_api_key(api_key: Optional[str] = None) -> str:
|
|
24
|
+
if api_key:
|
|
25
|
+
return api_key
|
|
26
|
+
|
|
27
|
+
env_api_key = os.environ.get("ADAPTIVE_API_KEY")
|
|
28
|
+
if env_api_key:
|
|
29
|
+
return env_api_key
|
|
30
|
+
|
|
31
|
+
raise ValueError("API key not found. Please provide an API KEY or set ADAPTIVE_API_KEY environment variable.")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_valid_url(url):
|
|
35
|
+
parsed_url = urlparse(url)
|
|
36
|
+
return bool(parsed_url.scheme) and bool(parsed_url.netloc)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class BaseSyncClient:
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
base_url: str,
|
|
43
|
+
api_key: Optional[str] = None,
|
|
44
|
+
default_headers: Dict[str, str] | None = None,
|
|
45
|
+
timeout_secs: float = 90.0,
|
|
46
|
+
):
|
|
47
|
+
"""
|
|
48
|
+
Construct a new synchronous client instance.
|
|
49
|
+
"""
|
|
50
|
+
if not base_url:
|
|
51
|
+
raise ValueError("base_url must be provided")
|
|
52
|
+
else:
|
|
53
|
+
if is_valid_url(base_url):
|
|
54
|
+
base_url = base_url.rstrip("/")
|
|
55
|
+
else:
|
|
56
|
+
raise ValueError(
|
|
57
|
+
f"Provided base_url {base_url} is invalid. It should be a well-formed url like https://api-adaptive-ml.com"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
self.api_key = _get_api_key(api_key)
|
|
61
|
+
self.base_url = base_url
|
|
62
|
+
custom_headers = (default_headers or {}).copy()
|
|
63
|
+
headers = {
|
|
64
|
+
**custom_headers,
|
|
65
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
66
|
+
"User-Agent": f"adaptive_sdk/{get_version()}",
|
|
67
|
+
}
|
|
68
|
+
self._gql_client = GQLClient(base_url + Routes.GQL.value, headers=headers)
|
|
69
|
+
self._gql_client.get_data = graphql_multi_error_handler(self._gql_client.get_data) # type: ignore[method-assign]
|
|
70
|
+
|
|
71
|
+
timeout = httpx.Timeout(timeout=timeout_secs)
|
|
72
|
+
|
|
73
|
+
self._gql_client.http_client.timeout = timeout
|
|
74
|
+
self._rest_client = httpx.Client(headers=headers, base_url=base_url + Routes.REST.value, timeout=timeout)
|
|
75
|
+
|
|
76
|
+
def close(self) -> None:
|
|
77
|
+
self._rest_client.close()
|
|
78
|
+
self._gql_client.http_client.close()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class BaseAsyncClient:
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
base_url: str,
|
|
85
|
+
api_key: Optional[str] = None,
|
|
86
|
+
default_headers: Dict[str, str] | None = None,
|
|
87
|
+
timeout_secs: float = 90.0,
|
|
88
|
+
):
|
|
89
|
+
"""
|
|
90
|
+
Construct a new asynchronous client instance.
|
|
91
|
+
"""
|
|
92
|
+
if not base_url:
|
|
93
|
+
raise ValueError("base_url must be provided")
|
|
94
|
+
else:
|
|
95
|
+
if is_valid_url(base_url):
|
|
96
|
+
base_url = base_url.rstrip("/")
|
|
97
|
+
else:
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"Provided base_url {base_url} is invalid. It should be a well-formed url like https://api.adaptive-ml.com"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
self.api_key = _get_api_key(api_key)
|
|
103
|
+
self.base_url = base_url
|
|
104
|
+
custom_headers = (default_headers or {}).copy()
|
|
105
|
+
headers = {
|
|
106
|
+
**custom_headers,
|
|
107
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
108
|
+
"User-Agent": f"adaptive_sdk/{get_version()}",
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
self._gql_client = AsyncGQLClient(base_url + Routes.GQL.value, headers=headers)
|
|
112
|
+
self._gql_client.get_data = graphql_multi_error_handler(self._gql_client.get_data) # type: ignore[method-assign]
|
|
113
|
+
|
|
114
|
+
timeout = httpx.Timeout(timeout=timeout_secs)
|
|
115
|
+
self._gql_client.http_client.timeout = timeout
|
|
116
|
+
self._rest_client = httpx.AsyncClient(headers=headers, base_url=base_url + Routes.REST.value, timeout=timeout)
|
|
117
|
+
|
|
118
|
+
async def close(self) -> None:
|
|
119
|
+
await self._rest_client.aclose()
|
|
120
|
+
await self._gql_client.http_client.aclose()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class UseCaseClient(ABC):
|
|
124
|
+
@property
|
|
125
|
+
@abstractmethod
|
|
126
|
+
def default_use_case(self) -> str | None:
|
|
127
|
+
"""Get the current default use case key."""
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
@abstractmethod
|
|
131
|
+
def set_default_use_case(self, use_case: str) -> None:
|
|
132
|
+
"""Set the default use case key."""
|
|
133
|
+
pass
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
from .base_client import BaseSyncClient, BaseAsyncClient, UseCaseClient
|
|
3
|
+
from . import resources
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Adaptive(BaseSyncClient, UseCaseClient):
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
base_url: str,
|
|
10
|
+
api_key: str | None = None,
|
|
11
|
+
default_headers: Dict[str, str] | None = None,
|
|
12
|
+
) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Instantiates a new synchronous Adaptive client bounded to a use case.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
use_case (str): A unique use case key; the client is bounded to this use case.
|
|
18
|
+
base_url (str): The base URL for the Adaptive API.
|
|
19
|
+
api_key (str, optional): API key for authentication.
|
|
20
|
+
Defaults to None, in which case environment variable `ADAPTIVE_API_KEY` needs to be set.
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
super().__init__(base_url, api_key, default_headers)
|
|
24
|
+
self.__use_case_key = None
|
|
25
|
+
|
|
26
|
+
self.ab_tests: resources.ABTests = resources.ABTests(self)
|
|
27
|
+
self.chat: resources.Chat = resources.Chat(self)
|
|
28
|
+
self.completions: resources.Completions = resources.Completions(self)
|
|
29
|
+
self.compute_pools: resources.ComputePools = resources.ComputePools(self)
|
|
30
|
+
self.custom_recipes: resources.CustomRecipes = resources.CustomRecipes(self)
|
|
31
|
+
self.datasets: resources.Datasets = resources.Datasets(self)
|
|
32
|
+
self.embeddings: resources.Embeddings = resources.Embeddings(self)
|
|
33
|
+
self.evaluation: resources.Evaluation = resources.Evaluation(self)
|
|
34
|
+
self.judges: resources.Judges = resources.Judges(self)
|
|
35
|
+
self.feedback: resources.Feedback = resources.Feedback(self)
|
|
36
|
+
self.interactions: resources.Interactions = resources.Interactions(self)
|
|
37
|
+
self.models: resources.Models = resources.Models(self)
|
|
38
|
+
self.permissions: resources.Permissions = resources.Permissions(self)
|
|
39
|
+
self.reward_servers: resources.RewardServers = resources.RewardServers(self)
|
|
40
|
+
self.roles: resources.Roles = resources.Roles(self)
|
|
41
|
+
self.teams: resources.Teams = resources.Teams(self)
|
|
42
|
+
self.training: resources.Training = resources.Training(self)
|
|
43
|
+
self.use_cases: resources.UseCase = resources.UseCase(self)
|
|
44
|
+
self.users: resources.Users = resources.Users(self)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def default_use_case(self) -> str | None:
|
|
48
|
+
"""
|
|
49
|
+
Get the current default use case key.
|
|
50
|
+
"""
|
|
51
|
+
return self.__use_case_key
|
|
52
|
+
|
|
53
|
+
def set_default_use_case(self, use_case: str) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Set a default use case key to be used for use case-specific operations.
|
|
56
|
+
"""
|
|
57
|
+
if not (isinstance(use_case, str) and bool(use_case.strip())):
|
|
58
|
+
raise ValueError("use_case must be a non-empty string")
|
|
59
|
+
self.__use_case_key = use_case # type: ignore[assignment]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class AsyncAdaptive(BaseAsyncClient, UseCaseClient):
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
base_url: str,
|
|
66
|
+
api_key: str | None = None,
|
|
67
|
+
default_headers: Dict[str, str] | None = None,
|
|
68
|
+
) -> None:
|
|
69
|
+
"""
|
|
70
|
+
Instantiates a new asynchronous Adaptive client bounded to a use case.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
use_case (str): A unique use case key; the client is bounded to this use case.
|
|
74
|
+
base_url (str): The base URL for the Adaptive API.
|
|
75
|
+
api_key (str, optional): API key for authentication.
|
|
76
|
+
Defaults to None, in which case environment variable `ADAPTIVE_API_KEY` needs to be set.
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
super().__init__(base_url, api_key, default_headers)
|
|
80
|
+
self.__use_case_key = None
|
|
81
|
+
|
|
82
|
+
self.ab_tests: resources.AsyncABTests = resources.AsyncABTests(self)
|
|
83
|
+
self.chat: resources.AsyncChat = resources.AsyncChat(self)
|
|
84
|
+
self.completions: resources.AsyncCompletions = resources.AsyncCompletions(self)
|
|
85
|
+
self.compute_pools: resources.AsyncComputePools = resources.AsyncComputePools(self)
|
|
86
|
+
self.custom_recipes: resources.AsyncCustomRecipes = resources.AsyncCustomRecipes(self)
|
|
87
|
+
self.datasets: resources.AsyncDatasets = resources.AsyncDatasets(self)
|
|
88
|
+
self.embeddings: resources.AsyncEmbeddings = resources.AsyncEmbeddings(self)
|
|
89
|
+
self.evaluation: resources.AsyncEvaluation = resources.AsyncEvaluation(self)
|
|
90
|
+
self.judges: resources.AsyncJudges = resources.AsyncJudges(self)
|
|
91
|
+
self.feedback: resources.AsyncFeedback = resources.AsyncFeedback(self)
|
|
92
|
+
self.interactions: resources.AsyncInteractions = resources.AsyncInteractions(self)
|
|
93
|
+
self.models: resources.AsyncModels = resources.AsyncModels(self)
|
|
94
|
+
self.permissions: resources.AsyncPermissions = resources.AsyncPermissions(self)
|
|
95
|
+
self.reward_servers: resources.AsyncRewardServers = resources.AsyncRewardServers(self)
|
|
96
|
+
self.roles: resources.AsyncRoles = resources.AsyncRoles(self)
|
|
97
|
+
self.teams: resources.AsyncTeams = resources.AsyncTeams(self)
|
|
98
|
+
self.training: resources.AsyncTraining = resources.AsyncTraining(self)
|
|
99
|
+
self.use_cases: resources.AsyncUseCase = resources.AsyncUseCase(self)
|
|
100
|
+
self.users: resources.AsyncUsers = resources.AsyncUsers(self)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def default_use_case(self) -> str | None:
|
|
104
|
+
"""
|
|
105
|
+
Get the current default use case key.
|
|
106
|
+
"""
|
|
107
|
+
return self.__use_case_key
|
|
108
|
+
|
|
109
|
+
def set_default_use_case(self, use_case: str) -> None:
|
|
110
|
+
"""
|
|
111
|
+
Set a default use case key to be used for use case-specific operations.
|
|
112
|
+
"""
|
|
113
|
+
if not isinstance(use_case, str):
|
|
114
|
+
raise TypeError("use_case must be a string")
|
|
115
|
+
if not use_case.strip():
|
|
116
|
+
raise ValueError("use_case cannot be empty or whitespace")
|
|
117
|
+
self.__use_case_key = use_case # type: ignore[assignment]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Callable
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from .graphql_client.exceptions import GraphQLClientGraphQLMultiError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EntityNotFoundDescriptor(BaseModel):
|
|
8
|
+
entity: str
|
|
9
|
+
error_message: str
|
|
10
|
+
code_suggestions: list[str]
|
|
11
|
+
|
|
12
|
+
def __post_init__(self):
|
|
13
|
+
if self.error_message.count("{}") != len(self.code_suggestions):
|
|
14
|
+
raise ValueError("# of code suggestions must match # of placeholders in error message template")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AdaptiveEntityNotFoundError(Exception):
|
|
18
|
+
def __init__(self, original_error: str):
|
|
19
|
+
self.entity_descriptors = [
|
|
20
|
+
EntityNotFoundDescriptor(
|
|
21
|
+
entity="use_case",
|
|
22
|
+
error_message="Use case key does not exist. You can create it with `{}`",
|
|
23
|
+
code_suggestions=["client.use_cases.create"],
|
|
24
|
+
),
|
|
25
|
+
EntityNotFoundDescriptor(
|
|
26
|
+
entity="metric",
|
|
27
|
+
error_message="Feedback key does not exist, or is not linked to the target use case. You can create it with `{}` or link it with `{}`",
|
|
28
|
+
code_suggestions=[
|
|
29
|
+
"client.feedback.register_key",
|
|
30
|
+
"client.feedback.link",
|
|
31
|
+
],
|
|
32
|
+
),
|
|
33
|
+
EntityNotFoundDescriptor(
|
|
34
|
+
entity="model",
|
|
35
|
+
error_message="Model key does not exist, or is not attached to the target use case. You can attach it with `{}`",
|
|
36
|
+
code_suggestions=["client.models.attach"],
|
|
37
|
+
),
|
|
38
|
+
EntityNotFoundDescriptor(entity="user", error_message="User does not exist.", code_suggestions=[]),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
new_error_message = None
|
|
42
|
+
for descriptor in self.entity_descriptors:
|
|
43
|
+
if descriptor.entity in original_error.lower():
|
|
44
|
+
new_error_message = descriptor.error_message.format(*descriptor.code_suggestions)
|
|
45
|
+
break
|
|
46
|
+
|
|
47
|
+
super().__init__(new_error_message or original_error)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def adaptive_error_message_triage(error_message: str) -> Callable | None:
|
|
51
|
+
if "EntityNotFound:" in error_message:
|
|
52
|
+
return AdaptiveEntityNotFoundError
|
|
53
|
+
else:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def graphql_multi_error_handler(fn: Callable) -> Callable:
|
|
58
|
+
def wrapper(*args, **kwargs):
|
|
59
|
+
try:
|
|
60
|
+
return fn(*args, **kwargs)
|
|
61
|
+
except GraphQLClientGraphQLMultiError as e:
|
|
62
|
+
error_message = str(e.errors[0])
|
|
63
|
+
exception_type = adaptive_error_message_triage(error_message)
|
|
64
|
+
if exception_type is not None:
|
|
65
|
+
raise exception_type(error_message)
|
|
66
|
+
else:
|
|
67
|
+
raise
|
|
68
|
+
|
|
69
|
+
return wrapper
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def rest_error_handler(response: httpx.Response):
|
|
73
|
+
if response.is_client_error:
|
|
74
|
+
try:
|
|
75
|
+
response_json = response.json()
|
|
76
|
+
error_message = response_json.get("error", f"Unknown error: {response.text}")
|
|
77
|
+
exception_type = adaptive_error_message_triage(error_message)
|
|
78
|
+
if exception_type is not None:
|
|
79
|
+
raise exception_type(error_message)
|
|
80
|
+
else:
|
|
81
|
+
raise Exception(f"Client error {response.status_code}: {error_message}")
|
|
82
|
+
except Exception:
|
|
83
|
+
# Handle any exception when processing the response
|
|
84
|
+
raise Exception(f"Client error {response.status_code}: {response.text}")
|
|
85
|
+
else:
|
|
86
|
+
response.raise_for_status()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from .reward_client import RewardClient
|
|
2
|
+
from .reward_server import RewardServer, EmptyMetadata
|
|
3
|
+
from .reward_types import (
|
|
4
|
+
Request,
|
|
5
|
+
ValidatedRequest,
|
|
6
|
+
Response,
|
|
7
|
+
BatchedRequest,
|
|
8
|
+
BatchedResponse,
|
|
9
|
+
ServerInfo,
|
|
10
|
+
Turn,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"RewardClient",
|
|
15
|
+
"RewardServer",
|
|
16
|
+
"EmptyMetadata",
|
|
17
|
+
"ValidatedRequest",
|
|
18
|
+
"Request",
|
|
19
|
+
"Response",
|
|
20
|
+
"BatchedRequest",
|
|
21
|
+
"BatchedResponse",
|
|
22
|
+
"ServerInfo",
|
|
23
|
+
"Turn",
|
|
24
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from pydantic import BaseModel as PydanticBaseModel, ConfigDict
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BaseModel(PydanticBaseModel):
|
|
5
|
+
"""@private"""
|
|
6
|
+
|
|
7
|
+
model_config = ConfigDict(
|
|
8
|
+
populate_by_name=True,
|
|
9
|
+
validate_assignment=True,
|
|
10
|
+
arbitrary_types_allowed=True,
|
|
11
|
+
protected_namespaces=(),
|
|
12
|
+
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
SCORE_PATH: Final = "/score"
|
|
4
|
+
BATCH_SCORE_PATH: Final = "/batch_score"
|
|
5
|
+
INFO_PATH: Final = "/info"
|
|
6
|
+
VALIDATE_METADATA: Final = "/validate_metadata"
|
|
7
|
+
BATCH_VALIDATE_METADATA: Final = "/batch_validate_metadata"
|
|
8
|
+
METADATA_SCHEMA_PATH: Final = "/metadata_schema"
|