From fb3c20df6ca09181c93d587fa088fa03fab1d6a7 Mon Sep 17 00:00:00 2001 From: makseq-ubnt Date: Wed, 16 Aug 2023 01:35:24 +0100 Subject: [PATCH 1/3] fix: Migration script with full user list --- examples/migrate_ls_to_ls/migrate-ls-to-ls.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/migrate_ls_to_ls/migrate-ls-to-ls.py b/examples/migrate_ls_to_ls/migrate-ls-to-ls.py index 58bc5d38d..9b7244a46 100644 --- a/examples/migrate_ls_to_ls/migrate-ls-to-ls.py +++ b/examples/migrate_ls_to_ls/migrate-ls-to-ls.py @@ -38,7 +38,7 @@ def set_project_ids(self, project_ids=None): def run(self, project_ids=None): projects = self.get_projects(project_ids) - users = self.get_users(projects) + users = self.get_users() # self.get_users(projects) self.create_users(users) # start exporting projects @@ -139,10 +139,10 @@ def get_projects(self, project_ids): return self.projects - def get_users(self, projects: [Project]) -> [User]: + def get_users(self, projects) -> [User]: """Get users that are members of all projects at the source instance""" # enterprise instance - if self.src_ls.is_enterprise: + if self.src_ls.is_enterprise and projects: users = {} for project in projects: members = project.get_members() From 75cde4b047a06c5b4dc911fccc8bb1df2f2e4c85 Mon Sep 17 00:00:00 2001 From: makseq-ubnt Date: Wed, 6 Mar 2024 17:41:36 +0000 Subject: [PATCH 2/3] Fixes --- Makefile | 3 +- .../assign_10_percent_of_tasks.py | 116 ++++++++++++++++++ examples/migrate_ls_to_ls/migrate-ls-to-ls.py | 4 - 3 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 examples/label_studio_enterprise/assign_10_percent_of_tasks.py diff --git a/Makefile b/Makefile index abafdfb46..ab251f19d 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,11 @@ watch: pdoc label_studio_sdk docs --http localhost:9999 --template-dir docs/pdoc_templates/ build: + # wget http://localhost:4000/header.html -O docs/pdoc_templates/head.mako pdoc label_studio_sdk docs --template-dir docs/pdoc_templates/ --html --force deploy: python3 deploy.py test: - pytest tests + pytest tests \ No newline at end of file diff --git a/examples/label_studio_enterprise/assign_10_percent_of_tasks.py b/examples/label_studio_enterprise/assign_10_percent_of_tasks.py new file mode 100644 index 000000000..0cabe5f1b --- /dev/null +++ b/examples/label_studio_enterprise/assign_10_percent_of_tasks.py @@ -0,0 +1,116 @@ +""" +This script is meant to automatically tag tasks within a project using a random distribution and +then assign those that receive a specific tag to a reviewer for further reviewing. +""" +from label_studio_sdk import Client +from label_studio_sdk.data_manager import Filters, Column, Operator, Type + +# Initialize the Label Studio SDK Client +LABEL_STUDIO_URL = 'https://app.heartex.com' # Replace with your Label Studio URL +API_KEY = '' # Replace with your API key +ls = Client(url=LABEL_STUDIO_URL, api_key=API_KEY) + + +def create_tags_with_random_distribution(project_id: int, column_name: str, choices: list, weights: list): + """Generate a new task column with tags randomly distributed by weights (percents). + For example, if column_name='tags', choices=['to-be-reviewed', 'others'] and weights=[0.1, 0.9], + 10% of tasks will have 'to-be-reviewed' in newly created 'tags' column. + + Note: this API call uses experimental feature, use this with caution because you can overwrite + your task columns with this command. + + :param project_id: project id + :param column_name: string, a new column name to be created + :param choices: array of strings, tag names + :param weights: sampling for tag names, values should be from 0.0 to 10 and sum(weights) should be 1.0 + :return: API response for sampling + """ + + assert len(choices) == len(weights) + data = { + "ordering": [], + "selectedItems": { + "all": True, + "excluded": [] + }, + "filters": { + "conjunction": "and", + "items": [] + }, + "value_name": column_name, + "value_type": "Expression", + "value": f"choices({choices}, {weights})", + "project": project_id + } + response = ls.make_request( + 'post', + f'/api/dm/actions?id=add_data_field&project={project_id}', + json=data + ) + print('Tag sampling is done') + return response + + +def assign_reviewer_by_tag(project_id: int, reviewer_email: str, filter_column: str, filter_value: str): + """ Function to assign a reviewer to tasks filtered by a specific tag + + :param project_id: project id + :param reviewer_email: user email to be a reviewer + :param filter_column: column name to use in the filter + :param filter_value: value name to use in the filter + :return: API response for the reviewer assignment + """ + # Get the user ID of the reviewer by their email + users = ls.get_users() + reviewer = next((user for user in users if user.email == reviewer_email), None) + if not reviewer: + raise ValueError(f"Reviewer with email {reviewer_email} not found.") + + # Create a filter for tasks with the specified tag + filters = Filters.create(Filters.AND, [ + Filters.item( + Column.data(filter_column), + Operator.EQUAL, + Type.String, + Filters.value(filter_value) + ) + ]) + + # Retrieve the filtered tasks + project = ls.get_project(project_id) + task_ids = project.get_tasks_ids(filters=filters) + + # Assign the reviewer to the filtered tasks + response = project.assign_reviewers([reviewer], task_ids) + print(f"Assigned reviewer {reviewer_email} to {len(task_ids)} tasks") + return response + + +def run(): + """ This function acts as the main entry point for running the defined operations. + + It specifies the project ID and reviewer's email, and then: + 1. Calls create_tags_with_random_distribution to add a 'tags' column to the project's tasks + with tags 'to-be-reviewed' or 'other', distributed according to the specified weights + 2. Calls assign_reviewer_by_tag to assign the specified reviewer to all tasks + that have been tagged as 'to-be-reviewed'. + """ + project_id = 12716 # Replace with your actual project ID + reviewer_email = 'your@email.com' # Replace with the reviewer's email + + create_tags_with_random_distribution( + project_id, + 'tags', + choices=['to-be-reviewed', 'other'], + weights=[0.1, 0.9] + ) + assign_reviewer_by_tag( + project_id, + reviewer_email, + filter_column='tags', + filter_value='to-be-reviewed' + ) + + +if __name__ == '__main__': + run() diff --git a/examples/migrate_ls_to_ls/migrate-ls-to-ls.py b/examples/migrate_ls_to_ls/migrate-ls-to-ls.py index d806c1384..980484643 100644 --- a/examples/migrate_ls_to_ls/migrate-ls-to-ls.py +++ b/examples/migrate_ls_to_ls/migrate-ls-to-ls.py @@ -228,11 +228,7 @@ def get_projects(self, project_ids): return self.projects -<<<<<<< HEAD - def get_users(self, projects) -> [User]: -======= def get_users(self, projects=None) -> [User]: ->>>>>>> 7ec493e6e9ff128e089553c25f866f80dab26023 """Get users that are members of all projects at the source instance""" # enterprise instance if self.src_ls.is_enterprise and projects: From 4c621c8626220953390fae7602b12ea8e958d4d6 Mon Sep 17 00:00:00 2001 From: makseq-ubnt Date: Wed, 6 Mar 2024 17:46:52 +0000 Subject: [PATCH 3/3] Black --- .../assign_10_percent_of_tasks.py | 68 +++++++++---------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/examples/label_studio_enterprise/assign_10_percent_of_tasks.py b/examples/label_studio_enterprise/assign_10_percent_of_tasks.py index 0cabe5f1b..558b1fddd 100644 --- a/examples/label_studio_enterprise/assign_10_percent_of_tasks.py +++ b/examples/label_studio_enterprise/assign_10_percent_of_tasks.py @@ -2,16 +2,19 @@ This script is meant to automatically tag tasks within a project using a random distribution and then assign those that receive a specific tag to a reviewer for further reviewing. """ + from label_studio_sdk import Client from label_studio_sdk.data_manager import Filters, Column, Operator, Type # Initialize the Label Studio SDK Client -LABEL_STUDIO_URL = 'https://app.heartex.com' # Replace with your Label Studio URL -API_KEY = '' # Replace with your API key +LABEL_STUDIO_URL = "https://app.heartex.com" # Replace with your Label Studio URL +API_KEY = "" # Replace with your API key ls = Client(url=LABEL_STUDIO_URL, api_key=API_KEY) -def create_tags_with_random_distribution(project_id: int, column_name: str, choices: list, weights: list): +def create_tags_with_random_distribution( + project_id: int, column_name: str, choices: list, weights: list +): """Generate a new task column with tags randomly distributed by weights (percents). For example, if column_name='tags', choices=['to-be-reviewed', 'others'] and weights=[0.1, 0.9], 10% of tasks will have 'to-be-reviewed' in newly created 'tags' column. @@ -29,30 +32,24 @@ def create_tags_with_random_distribution(project_id: int, column_name: str, choi assert len(choices) == len(weights) data = { "ordering": [], - "selectedItems": { - "all": True, - "excluded": [] - }, - "filters": { - "conjunction": "and", - "items": [] - }, + "selectedItems": {"all": True, "excluded": []}, + "filters": {"conjunction": "and", "items": []}, "value_name": column_name, "value_type": "Expression", "value": f"choices({choices}, {weights})", - "project": project_id + "project": project_id, } response = ls.make_request( - 'post', - f'/api/dm/actions?id=add_data_field&project={project_id}', - json=data + "post", f"/api/dm/actions?id=add_data_field&project={project_id}", json=data ) - print('Tag sampling is done') + print("Tag sampling is done") return response -def assign_reviewer_by_tag(project_id: int, reviewer_email: str, filter_column: str, filter_value: str): - """ Function to assign a reviewer to tasks filtered by a specific tag +def assign_reviewer_by_tag( + project_id: int, reviewer_email: str, filter_column: str, filter_value: str +): + """Function to assign a reviewer to tasks filtered by a specific tag :param project_id: project id :param reviewer_email: user email to be a reviewer @@ -67,14 +64,17 @@ def assign_reviewer_by_tag(project_id: int, reviewer_email: str, filter_column: raise ValueError(f"Reviewer with email {reviewer_email} not found.") # Create a filter for tasks with the specified tag - filters = Filters.create(Filters.AND, [ - Filters.item( - Column.data(filter_column), - Operator.EQUAL, - Type.String, - Filters.value(filter_value) - ) - ]) + filters = Filters.create( + Filters.AND, + [ + Filters.item( + Column.data(filter_column), + Operator.EQUAL, + Type.String, + Filters.value(filter_value), + ) + ], + ) # Retrieve the filtered tasks project = ls.get_project(project_id) @@ -87,7 +87,7 @@ def assign_reviewer_by_tag(project_id: int, reviewer_email: str, filter_column: def run(): - """ This function acts as the main entry point for running the defined operations. + """This function acts as the main entry point for running the defined operations. It specifies the project ID and reviewer's email, and then: 1. Calls create_tags_with_random_distribution to add a 'tags' column to the project's tasks @@ -96,21 +96,15 @@ def run(): that have been tagged as 'to-be-reviewed'. """ project_id = 12716 # Replace with your actual project ID - reviewer_email = 'your@email.com' # Replace with the reviewer's email + reviewer_email = "your@email.com" # Replace with the reviewer's email create_tags_with_random_distribution( - project_id, - 'tags', - choices=['to-be-reviewed', 'other'], - weights=[0.1, 0.9] + project_id, "tags", choices=["to-be-reviewed", "other"], weights=[0.1, 0.9] ) assign_reviewer_by_tag( - project_id, - reviewer_email, - filter_column='tags', - filter_value='to-be-reviewed' + project_id, reviewer_email, filter_column="tags", filter_value="to-be-reviewed" ) -if __name__ == '__main__': +if __name__ == "__main__": run()