Skip to content

Commit cacf98a

Browse files
committed
added project and ontology creation for prompt response projects
1 parent 4dcef3e commit cacf98a

File tree

8 files changed

+670
-31
lines changed

8 files changed

+670
-31
lines changed

libs/labelbox/src/labelbox/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
from labelbox.schema.asset_attachment import AssetAttachment
2424
from labelbox.schema.webhook import Webhook
2525
from labelbox.schema.ontology import Ontology, OntologyBuilder, Classification, Option, Tool, FeatureSchema
26+
from labelbox.schema.ontology import PromptResponseClassification
27+
from labelbox.schema.ontology import ResponseOption
2628
from labelbox.schema.role import Role, ProjectRole
2729
from labelbox.schema.invite import Invite, InviteLimit
2830
from labelbox.schema.data_row_metadata import DataRowMetadataOntology, DataRowMetadataField, DataRowMetadata, DeleteDataRowMetadata

libs/labelbox/src/labelbox/client.py

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from labelbox.schema.model_config import ModelConfig
4242
from labelbox.schema.model_run import ModelRun
4343
from labelbox.schema.ontology import Ontology, DeleteFeatureFromOntologyResult
44-
from labelbox.schema.ontology import Tool, Classification, FeatureSchema
44+
from labelbox.schema.ontology import Tool, Classification, FeatureSchema, PromptResponseClassification
4545
from labelbox.schema.organization import Organization
4646
from labelbox.schema.project import Project
4747
from labelbox.schema.quality_mode import QualityMode, BENCHMARK_AUTO_AUDIT_NUMBER_OF_LABELS, \
@@ -855,6 +855,99 @@ def create_offline_model_evaluation_project(self, **kwargs) -> Project:
855855
kwargs.pop("data_row_count", None)
856856

857857
return self._create_project(**kwargs)
858+
859+
@overload
860+
def create_prompt_response_generation_project(self,
861+
dataset_name: str,
862+
dataset_id: str = None,
863+
data_row_count: int = 100,
864+
**kwargs) -> Project:
865+
pass
866+
867+
@overload
868+
def create_prompt_response_generation_project(self,
869+
dataset_id: str,
870+
dataset_name: str = None,
871+
data_row_count: int = 100,
872+
**kwargs) -> Project:
873+
pass
874+
875+
def create_prompt_response_generation_project(self,
876+
dataset_id: Optional[str] = None,
877+
dataset_name: Optional[str] = None,
878+
data_row_count: int = 100,
879+
**kwargs) -> Project:
880+
"""
881+
Use this method exclusively to create a prompt and response generation project.
882+
883+
Args:
884+
dataset_name: When creating a new dataset, pass the name
885+
dataset_id: When using an existing dataset, pass the id
886+
data_row_count: The number of data row assets to use for the project
887+
**kwargs: Additional parameters to pass to the the create_project method
888+
Returns:
889+
Project: The created project
890+
891+
Examples:
892+
>>> client.create_prompt_response_generation_project(name=project_name, dataset_name="new data set", project_kind=MediaType.LLMPromptResponseCreation)
893+
>>> 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.
894+
895+
>>> client.create_prompt_response_generation_project(name=project_name, dataset_name="new data set", data_row_count=10, project_kind=MediaType.LLMPromptCreation)
896+
>>> This creates a new dataset with 10 data rows, creates new project and assigns a batch of the newly created datarows to the project.
897+
898+
>>> client.create_prompt_response_generation_project(name=project_name, dataset_id="clr00u8j0j0j0", project_kind=MediaType.LLMPromptCreation)
899+
>>> 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.
900+
901+
>>> client.create_prompt_response_generation_project(name=project_name, dataset_id="clr00u8j0j0j0", data_row_count=10, project_kind=MediaType.LLMPromptCreation)
902+
>>> 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.
903+
904+
"""
905+
if not dataset_id and not dataset_name:
906+
raise ValueError(
907+
"dataset_name or data_set_id must be present and not be an empty string."
908+
)
909+
if data_row_count <= 0:
910+
raise ValueError("data_row_count must be a positive integer.")
911+
912+
if dataset_id:
913+
append_to_existing_dataset = True
914+
dataset_name_or_id = dataset_id
915+
else:
916+
append_to_existing_dataset = False
917+
dataset_name_or_id = dataset_name
918+
919+
if "media_type" in kwargs and kwargs.get("media_type") not in [MediaType.LLMPromptCreation, MediaType.LLMPromptResponseCreation]:
920+
raise ValueError(
921+
"media_type must be either LLMPromptCreation or LLMPromptResponseCreation"
922+
)
923+
924+
kwargs["dataset_name_or_id"] = dataset_name_or_id
925+
kwargs["append_to_existing_dataset"] = append_to_existing_dataset
926+
kwargs["data_row_count"] = data_row_count
927+
928+
kwargs.pop("editor_task_type", None)
929+
930+
return self._create_project(**kwargs)
931+
932+
def create_response_creation_project(self, **kwargs) -> Project:
933+
"""
934+
Creates a project for response creation.
935+
Args:
936+
**kwargs: Additional parameters to pass see the create_project method
937+
Returns:
938+
Project: The created project
939+
"""
940+
kwargs[
941+
"media_type"] = MediaType.Text # Only Text is supported
942+
kwargs[
943+
"editor_task_type"] = EditorTaskType.ResponseCreation.value # Special editor task type for offline model evaluation
944+
945+
# The following arguments are not supported for offline model evaluation
946+
kwargs.pop("dataset_name_or_id", None)
947+
kwargs.pop("append_to_existing_dataset", None)
948+
kwargs.pop("data_row_count", None)
949+
950+
return self._create_project(**kwargs)
858951

859952
def _create_project(self, **kwargs) -> Project:
860953
auto_audit_percentage = kwargs.get("auto_audit_percentage")
@@ -1138,11 +1231,13 @@ def create_ontology_from_feature_schemas(
11381231
name (str): Name of the ontology
11391232
feature_schema_ids (List[str]): List of feature schema ids corresponding to
11401233
top level tools and classifications to include in the ontology
1141-
media_type (MediaType or None): Media type of a new ontology. NOTE for chat evaluation, we currently foce media_type to Conversational
1234+
media_type (MediaType or None): Media type of a new ontology.
11421235
ontology_kind (OntologyKind or None): set to OntologyKind.ModelEvaluation if the ontology is for chat evaluation,
11431236
leave as None otherwise.
11441237
Returns:
11451238
The created Ontology
1239+
1240+
NOTE for chat evaluation, we currently force media_type to Conversational and for response creation, we force media_type to Text.
11461241
"""
11471242
tools, classifications = [], []
11481243
for feature_schema_id in feature_schema_ids:
@@ -1158,10 +1253,13 @@ def create_ontology_from_feature_schemas(
11581253
f"Tool `{tool}` not in list of supported tools.")
11591254
elif 'type' in feature_schema.normalized:
11601255
classification = feature_schema.normalized['type']
1161-
try:
1256+
if classification in Classification.Type._value2member_map_.keys():
11621257
Classification.Type(classification)
11631258
classifications.append(feature_schema.normalized)
1164-
except ValueError:
1259+
elif classification in PromptResponseClassification.Type._value2member_map_.keys():
1260+
PromptResponseClassification.Type(classification)
1261+
classifications.append(feature_schema.normalized)
1262+
else:
11651263
raise ValueError(
11661264
f"Classification `{classification}` not in list of supported classifications."
11671265
)
@@ -1171,15 +1269,7 @@ def create_ontology_from_feature_schemas(
11711269
)
11721270
normalized = {'tools': tools, 'classifications': classifications}
11731271

1174-
if ontology_kind and ontology_kind is OntologyKind.ModelEvaluation:
1175-
if media_type is None:
1176-
media_type = MediaType.Conversational
1177-
else:
1178-
if media_type is not MediaType.Conversational:
1179-
raise ValueError(
1180-
"For chat evaluation, media_type must be Conversational."
1181-
)
1182-
1272+
# validation for ontology_kind and media_type is done within self.create_ontology
11831273
return self.create_ontology(name=name,
11841274
normalized=normalized,
11851275
media_type=media_type,
@@ -1398,7 +1488,7 @@ def create_ontology(self,
13981488
Returns:
13991489
The created Ontology
14001490
1401-
NOTE caller of this method is expected to set media_type to Conversational if ontology_kind is ModelEvaluation
1491+
NOTE for chat evaluation, we currently force media_type to Conversational and for response creation, we force media_type to Text.
14021492
"""
14031493

14041494
media_type_value = None
@@ -1409,6 +1499,7 @@ def create_ontology(self,
14091499
raise get_media_type_validation_error(media_type)
14101500

14111501
if ontology_kind and OntologyKind.is_supported(ontology_kind):
1502+
media_type = OntologyKind.evaluate_ontology_kind_with_media_type(ontology_kind, media_type)
14121503
editor_task_type_value = EditorTaskTypeMapper.to_editor_task_type(
14131504
ontology_kind, media_type).value
14141505
elif ontology_kind:

0 commit comments

Comments
 (0)