Skip to content

Commit f1b42d8

Browse files
authored
Improve usability of create_project for chat evaluation and add basic validations (#1599)
2 parents a4970e7 + 6a89814 commit f1b42d8

File tree

5 files changed

+104
-22
lines changed

5 files changed

+104
-22
lines changed

.github/workflows/python-package-develop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ concurrency:
1010
group: ${{ github.workflow }}-${{ github.ref }}
1111
cancel-in-progress: true
1212

13+
permissions:
14+
id-token: write
15+
1316
jobs:
1417
build:
1518
strategy:

libs/labelbox/src/labelbox/client.py

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import urllib.parse
1010
from collections import defaultdict
1111
from datetime import datetime, timezone
12-
from typing import Any, List, Dict, Union, Optional
12+
from typing import Any, List, Dict, Union, Optional, overload
1313

1414
import requests
1515
import requests.exceptions
@@ -310,9 +310,10 @@ def get_error_status_code(error: dict) -> int:
310310
if internal_server_error is not None:
311311
message = internal_server_error.get("message")
312312
error_status_code = get_error_status_code(internal_server_error)
313-
314313
if error_status_code == 400:
315314
raise labelbox.exceptions.InvalidQueryError(message)
315+
elif error_status_code == 422:
316+
raise labelbox.exceptions.UnprocessableEntityError(message)
316317
elif error_status_code == 426:
317318
raise labelbox.exceptions.OperationNotAllowedException(message)
318319
elif error_status_code == 500:
@@ -596,7 +597,8 @@ def _create(self, db_object_type, data, extra_params={}):
596597
res = res["create%s" % db_object_type.type_name()]
597598
return db_object_type(self, res)
598599

599-
def create_model_config(self, name: str, model_id: str, inference_params: dict) -> ModelConfig:
600+
def create_model_config(self, name: str, model_id: str,
601+
inference_params: dict) -> ModelConfig:
600602
""" Creates a new model config with the given params.
601603
Model configs are scoped to organizations, and can be reused between projects.
602604
@@ -608,6 +610,8 @@ def create_model_config(self, name: str, model_id: str, inference_params: dict)
608610
Returns:
609611
str, id of the created model config
610612
"""
613+
if not name:
614+
raise ValueError("Model config name must not be an empty string.")
611615

612616
query = """mutation CreateModelConfigPyApi($modelId: ID!, $inferenceParams: Json!, $name: String!) {
613617
createModelConfig(input: {modelId: $modelId, inferenceParams: $inferenceParams, name: $name}) {
@@ -640,9 +644,7 @@ def delete_model_config(self, id: str) -> bool:
640644
success
641645
}
642646
}"""
643-
params = {
644-
"id": id
645-
}
647+
params = {"id": id}
646648
result = self.execute(query, params)
647649
return result['deleteModelConfig']['success']
648650

@@ -811,22 +813,66 @@ def create_project(self, **kwargs) -> Project:
811813

812814
return self._create(Entity.Project, params, extra_params)
813815

814-
def create_model_evaluation_project(
815-
self,
816-
dataset_name_or_id: str,
817-
append_to_existing_dataset: bool = False,
818-
data_row_count: int = 100,
819-
**kwargs) -> Project:
816+
@overload
817+
def create_model_evaluation_project(self,
818+
dataset_name: str,
819+
dataset_id: str = None,
820+
data_row_count: int = 100,
821+
**kwargs) -> Project:
822+
pass
823+
824+
@overload
825+
def create_model_evaluation_project(self,
826+
dataset_id: str,
827+
dataset_name: str = None,
828+
data_row_count: int = 100,
829+
**kwargs) -> Project:
830+
pass
831+
832+
def create_model_evaluation_project(self,
833+
dataset_id: Optional[str] = None,
834+
dataset_name: Optional[str] = None,
835+
data_row_count: int = 100,
836+
**kwargs) -> Project:
820837
"""
821838
Use this method exclusively to create a chat model evaluation project.
822839
Args:
823-
dataset_name_or_id: The name or id of the dataset to use for the project
824-
append_to_existing_dataset: If True, the project will append assets (data rows) to the existing dataset
840+
dataset_name: When creating a new dataset, pass the name
841+
dataset_id: When using an existing dataset, pass the id
825842
data_row_count: The number of data row assets to use for the project
826843
**kwargs: Additional parameters to pass to the the create_project method
827844
Returns:
828845
Project: The created project
846+
847+
Examples:
848+
>>> client.create_model_evaluation_project(name=project_name, dataset_name="new data set")
849+
>>> This creates a new dataset with a default number of rows (100), creates new project and assigns a batch of the newly created datarows to the project.
850+
851+
>>> client.create_model_evaluation_project(name=project_name, dataset_name="new data set", data_row_count=10)
852+
>>> This creates a new dataset with 10 data rows, creates new project and assigns a batch of the newly created datarows to the project.
853+
854+
>>> client.create_model_evaluation_project(name=project_name, dataset_id="clr00u8j0j0j0")
855+
>>> This creates a new project, and adds 100 datarows to the dataset with id "clr00u8j0j0j0" and assigns a batch of the newly created data rows to the project.
856+
857+
>>> client.create_model_evaluation_project(name=project_name, dataset_id="clr00u8j0j0j0", data_row_count=10)
858+
>>> This creates a new project, and adds 100 datarows to the dataset with id "clr00u8j0j0j0" and assigns a batch of the newly created 10 data rows to the project.
859+
860+
829861
"""
862+
if not dataset_id and not dataset_name:
863+
raise ValueError(
864+
"dataset_name or data_set_id must be present and not be an empty string."
865+
)
866+
if data_row_count <= 0:
867+
raise ValueError("data_row_count must be a positive integer.")
868+
869+
if dataset_id:
870+
append_to_existing_dataset = True
871+
dataset_name_or_id = dataset_id
872+
else:
873+
append_to_existing_dataset = False
874+
dataset_name_or_id = dataset_name
875+
830876
kwargs["media_type"] = MediaType.Conversational
831877
kwargs["ontology_kind"] = OntologyKind.ModelEvaluation
832878
kwargs["dataset_name_or_id"] = dataset_name_or_id

libs/labelbox/src/labelbox/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ class InvalidQueryError(LabelboxError):
7171
pass
7272

7373

74+
class UnprocessableEntityError(LabelboxError):
75+
""" Indicates that a resource could not be created in the server side
76+
due to a validation or transaction error"""
77+
pass
78+
79+
7480
class ResourceCreationError(LabelboxError):
7581
""" Indicates that a resource could not be created in the server side
7682
due to a validation or transaction error"""

libs/labelbox/tests/integration/conftest.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,25 @@ def chat_evaluation_ontology(client, rand_gen):
363363

364364

365365
@pytest.fixture
366-
def chat_evaluation_project(client, rand_gen):
366+
def chat_evaluation_project_create_dataset(client, rand_gen):
367367
project_name = f"test-model-evaluation-project-{rand_gen(str)}"
368-
dataset_name_or_id = f"test-model-evaluation-dataset-{rand_gen(str)}"
369-
project = client.create_model_evaluation_project(
370-
name=project_name, dataset_name_or_id=dataset_name_or_id)
368+
dataset_name = f"test-model-evaluation-dataset-{rand_gen(str)}"
369+
project = client.create_model_evaluation_project(name=project_name,
370+
dataset_name=dataset_name,
371+
data_row_count=1)
372+
373+
yield project
374+
375+
project.delete()
376+
377+
378+
@pytest.fixture
379+
def chat_evaluation_project_append_to_dataset(client, dataset, rand_gen):
380+
project_name = f"test-model-evaluation-project-{rand_gen(str)}"
381+
dataset_id = dataset.uid
382+
project = client.create_model_evaluation_project(name=project_name,
383+
dataset_id=dataset_id,
384+
data_row_count=1)
371385

372386
yield project
373387

libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
from labelbox.schema.labeling_frontend import LabelingFrontend
66

77

8-
def test_create_chat_evaluation_ontology_project(client,
9-
chat_evaluation_ontology,
10-
chat_evaluation_project):
8+
def test_create_chat_evaluation_ontology_project(
9+
client, chat_evaluation_ontology,
10+
chat_evaluation_project_create_dataset):
1111
ontology = chat_evaluation_ontology
1212

1313
# here we are essentially testing the ontology creation which is a fixture
@@ -18,7 +18,20 @@ def test_create_chat_evaluation_ontology_project(client,
1818
assert tool.schema_id
1919
assert tool.feature_schema_id
2020

21-
project = chat_evaluation_project
21+
project = chat_evaluation_project_create_dataset
22+
project.setup_editor(ontology)
23+
24+
assert project.labeling_frontend().name == "Editor"
25+
assert project.ontology().name == ontology.name
26+
27+
28+
def test_create_chat_evaluation_ontology_project_existing_dataset(
29+
client, chat_evaluation_ontology,
30+
chat_evaluation_project_append_to_dataset):
31+
ontology = chat_evaluation_ontology
32+
33+
project = chat_evaluation_project_append_to_dataset
34+
assert project
2235
project.setup_editor(ontology)
2336

2437
assert project.labeling_frontend().name == "Editor"

0 commit comments

Comments
 (0)