Skip to content

Commit 1d49d35

Browse files
committed
Merge branch 'sdubinin/model-1448' of https://github.com/Labelbox/labelbox-python into sdubinin/model-1448
2 parents 55c710b + 2c2d070 commit 1d49d35

File tree

13 files changed

+148
-348
lines changed

13 files changed

+148
-348
lines changed

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
project = 'Python SDK reference'
1717
copyright = '2024, Labelbox'
1818
author = 'Labelbox'
19-
release = '3.72.2'
19+
release = '3.73.0'
2020

2121
# -- General configuration ---------------------------------------------------
2222

libs/labelbox/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# Changelog
2+
# Version 3.73.0 (2024-06-20)
3+
## Added
4+
* Conversational data row checks (#1678)
5+
* UI ontology mode support (#1676)
6+
* Empty data row validation (#1667)
7+
8+
## Fixed
9+
* Numpy semver locked to < 2.0.0 (#1681)
10+
111
# Changelog
212
# Version 3.72.2 (2024-06-10)
313
## Added

libs/labelbox/pyproject.toml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
[project]
22
name = "labelbox"
3-
version = "3.72.2"
3+
version = "3.73.0"
44
description = "Labelbox Python API"
5-
authors = [
6-
{ name = "Labelbox", email = "engineering@labelbox.com" }
7-
]
5+
authors = [{ name = "Labelbox", email = "engineering@labelbox.com" }]
86
dependencies = [
97
"google-api-core>=1.22.1",
108
"pydantic>=1.8",
@@ -16,7 +14,7 @@ dependencies = [
1614
]
1715
readme = "README.md"
1816
requires-python = ">=3.8"
19-
classifiers=[
17+
classifiers = [
2018
# How mature is this project?
2119
"Development Status :: 5 - Production/Stable",
2220
# Indicate who your project is intended for
@@ -27,7 +25,7 @@ classifiers=[
2725
"Intended Audience :: Education",
2826
# Pick your license as you wish
2927
"License :: OSI Approved :: Apache Software License",
30-
# Specify the Python versions you support here.
28+
# Specify the Python versions you support here.
3129
"Programming Language :: Python :: 3",
3230
"Programming Language :: Python :: 3.8",
3331
"Programming Language :: Python :: 3.9",
@@ -47,7 +45,8 @@ Changelog = "https://github.com/Labelbox/labelbox-python/blob/develop/libs/label
4745
[project.optional-dependencies]
4846
data = [
4947
"shapely>=2.0.3",
50-
"numpy>=1.24.4",
48+
# numpy v2 breaks package since it only supports python >3.9
49+
"numpy>=1.24.4, <2.0.0",
5150
"pillow>=10.2.0",
5251
"typeguard>=4.1.5",
5352
"imagesize>=1.4.1",
@@ -85,12 +84,12 @@ unit = "pytest tests/unit"
8584
# LABELBOX_TEST_ENVIRON="ephemeral" \
8685
# SERVICE_API_KEY=${SERVICE_API_KEY} \
8786
# LABELBOX_TEST_BASE_URL="http://host.docker.internal:8080" \
88-
integration = { cmd = "pytest tests/integration" }
87+
integration = { cmd = "pytest tests/integration" }
8988
data = { cmd = "pytest tests/data" }
9089
yapf-lint = "yapf tests src -i --verbose --recursive --parallel --style \"google\""
9190
mypy-lint = "mypy src --pretty --show-error-codes --non-interactive --install-types"
9291
lint = { chain = ["yapf-lint", "mypy-lint"] }
93-
test = { chain = ["lint", "unit", "integration" ] }
92+
test = { chain = ["lint", "unit", "integration"] }
9493

9594
[tool.hatch.metadata]
9695
allow-direct-references = true

libs/labelbox/src/labelbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "labelbox"
22

3-
__version__ = "3.72.2"
3+
__version__ = "3.73.0"
44

55
from labelbox.client import Client
66
from labelbox.schema.project import Project

libs/labelbox/src/labelbox/client.py

Lines changed: 80 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -653,8 +653,7 @@ def delete_model_config(self, id: str) -> bool:
653653
params = {"id": id}
654654
result = self.execute(query, params)
655655
if not result:
656-
raise labelbox.exceptions.ResourceNotFoundError(
657-
Entity.ModelConfig, params)
656+
raise labelbox.exceptions.ResourceNotFoundError(Entity.ModelConfig, params)
658657
return result['deleteModelConfig']['success']
659658

660659
def create_dataset(self,
@@ -742,17 +741,85 @@ def create_project(self, **kwargs) -> Project:
742741
Raises:
743742
InvalidAttributeError: If the Project type does not contain
744743
any of the attribute names given in kwargs.
745-
746-
NOTE: the following attributes are used only in chat model evaluation projects:
747-
dataset_name_or_id, append_to_existing_dataset, data_row_count, editor_task_type
748-
They are not used for general projects and not supported in this method
749744
"""
750-
# The following arguments are not supported for general projects, only for chat model evaluation projects
751-
kwargs.pop("dataset_name_or_id", None)
752-
kwargs.pop("append_to_existing_dataset", None)
753-
kwargs.pop("data_row_count", None)
754-
kwargs.pop("editor_task_type", None)
755-
return self._create_project(**kwargs)
745+
746+
auto_audit_percentage = kwargs.get("auto_audit_percentage")
747+
auto_audit_number_of_labels = kwargs.get("auto_audit_number_of_labels")
748+
if auto_audit_percentage is not None or auto_audit_number_of_labels is not None:
749+
raise ValueError(
750+
"quality_mode must be set instead of auto_audit_percentage or auto_audit_number_of_labels."
751+
)
752+
753+
name = kwargs.get("name")
754+
if name is None or not name.strip():
755+
raise ValueError("project name must be a valid string.")
756+
757+
queue_mode = kwargs.get("queue_mode")
758+
if queue_mode is QueueMode.Dataset:
759+
raise ValueError(
760+
"Dataset queue mode is deprecated. Please prefer Batch queue mode."
761+
)
762+
elif queue_mode is QueueMode.Batch:
763+
logger.warning(
764+
"Passing a queue mode of batch is redundant and will soon no longer be supported."
765+
)
766+
767+
media_type = kwargs.get("media_type")
768+
if media_type and MediaType.is_supported(media_type):
769+
media_type_value = media_type.value
770+
elif media_type:
771+
raise TypeError(f"{media_type} is not a valid media type. Use"
772+
f" any of {MediaType.get_supported_members()}"
773+
" from MediaType. Example: MediaType.Image.")
774+
else:
775+
logger.warning(
776+
"Creating a project without specifying media_type"
777+
" through this method will soon no longer be supported.")
778+
media_type_value = None
779+
780+
ontology_kind = kwargs.pop("ontology_kind", None)
781+
if ontology_kind and OntologyKind.is_supported(ontology_kind):
782+
editor_task_type_value = EditorTaskTypeMapper.to_editor_task_type(
783+
ontology_kind, media_type).value
784+
elif ontology_kind:
785+
raise OntologyKind.get_ontology_kind_validation_error(ontology_kind)
786+
else:
787+
editor_task_type_value = None
788+
789+
quality_mode = kwargs.get("quality_mode")
790+
if not quality_mode:
791+
logger.info("Defaulting quality mode to Benchmark.")
792+
793+
data = kwargs
794+
data.pop("quality_mode", None)
795+
if quality_mode is None or quality_mode is QualityMode.Benchmark:
796+
data[
797+
"auto_audit_number_of_labels"] = BENCHMARK_AUTO_AUDIT_NUMBER_OF_LABELS
798+
data["auto_audit_percentage"] = BENCHMARK_AUTO_AUDIT_PERCENTAGE
799+
elif quality_mode is QualityMode.Consensus:
800+
data[
801+
"auto_audit_number_of_labels"] = CONSENSUS_AUTO_AUDIT_NUMBER_OF_LABELS
802+
data["auto_audit_percentage"] = CONSENSUS_AUTO_AUDIT_PERCENTAGE
803+
else:
804+
raise ValueError(f"{quality_mode} is not a valid quality mode.")
805+
806+
params = {**data}
807+
if media_type_value:
808+
params["media_type"] = media_type_value
809+
if editor_task_type_value:
810+
params["editor_task_type"] = editor_task_type_value
811+
812+
extra_params = {
813+
Field.String("dataset_name_or_id"):
814+
params.pop("dataset_name_or_id", None),
815+
Field.Boolean("append_to_existing_dataset"):
816+
params.pop("append_to_existing_dataset", None),
817+
Field.Int("data_row_count"):
818+
params.pop("data_row_count", None),
819+
}
820+
extra_params = {k: v for k, v in extra_params.items() if v is not None}
821+
822+
return self._create(Entity.Project, params, extra_params)
756823

757824
@overload
758825
def create_model_evaluation_project(self,
@@ -815,99 +882,13 @@ def create_model_evaluation_project(self,
815882
dataset_name_or_id = dataset_name
816883

817884
kwargs["media_type"] = MediaType.Conversational
885+
kwargs["ontology_kind"] = OntologyKind.ModelEvaluation
818886
kwargs["dataset_name_or_id"] = dataset_name_or_id
819887
kwargs["append_to_existing_dataset"] = append_to_existing_dataset
820888
kwargs["data_row_count"] = data_row_count
821-
kwargs["editor_task_type"] = EditorTaskType.ModelChatEvaluation.value
822-
823-
return self._create_project(**kwargs)
824-
825-
def create_offline_model_evaluation_project(self, **kwargs) -> Project:
826-
"""
827-
Creates a project for offline model evaluation.
828-
Args:
829-
**kwargs: Additional parameters to pass see the create_project method
830-
Returns:
831-
Project: The created project
832-
"""
833-
kwargs[
834-
"media_type"] = MediaType.Conversational # Only Conversational is supported
835-
kwargs[
836-
"editor_task_type"] = EditorTaskType.OfflineModelChatEvaluation.value # Special editor task type for offline model evaluation
837-
838-
# The following arguments are not supported for offline model evaluation
839-
kwargs.pop("dataset_name_or_id", None)
840-
kwargs.pop("append_to_existing_dataset", None)
841-
kwargs.pop("data_row_count", None)
842889

843890
return self.create_project(**kwargs)
844891

845-
def _create_project(self, **kwargs) -> Project:
846-
auto_audit_percentage = kwargs.get("auto_audit_percentage")
847-
auto_audit_number_of_labels = kwargs.get("auto_audit_number_of_labels")
848-
if auto_audit_percentage is not None or auto_audit_number_of_labels is not None:
849-
raise ValueError(
850-
"quality_mode must be set instead of auto_audit_percentage or auto_audit_number_of_labels."
851-
)
852-
853-
name = kwargs.get("name")
854-
if name is None or not name.strip():
855-
raise ValueError("project name must be a valid string.")
856-
857-
queue_mode = kwargs.get("queue_mode")
858-
if queue_mode is QueueMode.Dataset:
859-
raise ValueError(
860-
"Dataset queue mode is deprecated. Please prefer Batch queue mode."
861-
)
862-
elif queue_mode is QueueMode.Batch:
863-
logger.warning(
864-
"Passing a queue mode of batch is redundant and will soon no longer be supported."
865-
)
866-
867-
media_type = kwargs.get("media_type")
868-
if media_type and MediaType.is_supported(media_type):
869-
media_type_value = media_type.value
870-
elif media_type:
871-
raise TypeError(f"{media_type} is not a valid media type. Use"
872-
f" any of {MediaType.get_supported_members()}"
873-
" from MediaType. Example: MediaType.Image.")
874-
else:
875-
logger.warning(
876-
"Creating a project without specifying media_type"
877-
" through this method will soon no longer be supported.")
878-
media_type_value = None
879-
880-
quality_mode = kwargs.get("quality_mode")
881-
if not quality_mode:
882-
logger.info("Defaulting quality mode to Benchmark.")
883-
884-
data = kwargs
885-
data.pop("quality_mode", None)
886-
if quality_mode is None or quality_mode is QualityMode.Benchmark:
887-
data[
888-
"auto_audit_number_of_labels"] = BENCHMARK_AUTO_AUDIT_NUMBER_OF_LABELS
889-
data["auto_audit_percentage"] = BENCHMARK_AUTO_AUDIT_PERCENTAGE
890-
elif quality_mode is QualityMode.Consensus:
891-
data[
892-
"auto_audit_number_of_labels"] = CONSENSUS_AUTO_AUDIT_NUMBER_OF_LABELS
893-
data["auto_audit_percentage"] = CONSENSUS_AUTO_AUDIT_PERCENTAGE
894-
else:
895-
raise ValueError(f"{quality_mode} is not a valid quality mode.")
896-
897-
params = {**data}
898-
if media_type_value:
899-
params["media_type"] = media_type_value
900-
901-
extra_params = {
902-
Field.String("dataset_name_or_id"):
903-
params.pop("dataset_name_or_id", None),
904-
Field.Boolean("append_to_existing_dataset"):
905-
params.pop("append_to_existing_dataset", None),
906-
}
907-
extra_params = {k: v for k, v in extra_params.items() if v is not None}
908-
909-
return self._create(Entity.Project, params, extra_params)
910-
911892
def get_roles(self) -> List[Role]:
912893
"""
913894
Returns:

libs/labelbox/src/labelbox/schema/ontology_kind.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,12 @@ def get_ontology_kind_validation_error(cls, ontology_kind):
2626
class EditorTaskType(Enum):
2727
ModelChatEvaluation = "MODEL_CHAT_EVALUATION"
2828
ResponseCreation = "RESPONSE_CREATION"
29-
OfflineModelChatEvaluation = "OFFLINE_MODEL_CHAT_EVALUATION"
3029
Missing = None
3130

3231
@classmethod
3332
def is_supported(cls, value):
3433
return isinstance(value, cls)
3534

36-
@classmethod
37-
def _missing_(cls, name) -> 'EditorTaskType':
38-
"""Handle missing null new task types
39-
Handle upper case names for compatibility with
40-
the GraphQL"""
41-
42-
if name is None:
43-
return cls.Missing
44-
45-
for name, member in cls.__members__.items():
46-
if name == name.upper():
47-
return member
48-
49-
return cls.Missing
50-
5135

5236
class EditorTaskTypeMapper:
5337

libs/labelbox/src/labelbox/schema/project.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ class Project(DbObject, Updateable, Deletable):
121121
# Bind data_type and allowedMediaTYpe using the GraphQL type MediaType
122122
media_type = Field.Enum(MediaType, "media_type", "allowedMediaType")
123123
editor_task_type = Field.Enum(EditorTaskType, "editor_task_type")
124-
data_row_count = Field.Int("data_row_count")
125124

126125
# Relationships
127126
created_by = Relationship.ToOne("User", False, "created_by")

0 commit comments

Comments
 (0)