label-studio-sdk 1.0.17__py3-none-any.whl → 1.0.19__py3-none-any.whl
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.
Potentially problematic release.
This version of label-studio-sdk might be problematic. Click here for more details.
- label_studio_sdk/__init__.py +8 -1
- label_studio_sdk/_extensions/label_studio_tools/core/label_config.py +1 -1
- label_studio_sdk/converter/converter.py +57 -25
- label_studio_sdk/files/client.py +2 -2
- label_studio_sdk/projects/__init__.py +8 -1
- label_studio_sdk/projects/client.py +106 -81
- label_studio_sdk/projects/exports/client.py +2 -2
- label_studio_sdk/projects/exports/client_ext.py +2 -2
- label_studio_sdk/projects/types/__init__.py +8 -1
- label_studio_sdk/projects/types/projects_create_response.py +1 -1
- label_studio_sdk/projects/types/projects_list_request_filter.py +5 -0
- label_studio_sdk/projects/types/projects_update_response.py +1 -1
- label_studio_sdk/prompts/client.py +28 -0
- label_studio_sdk/tokens/client_ext.py +0 -1
- label_studio_sdk/types/project.py +1 -1
- {label_studio_sdk-1.0.17.dist-info → label_studio_sdk-1.0.19.dist-info}/METADATA +3 -2
- {label_studio_sdk-1.0.17.dist-info → label_studio_sdk-1.0.19.dist-info}/RECORD +19 -18
- {label_studio_sdk-1.0.17.dist-info → label_studio_sdk-1.0.19.dist-info}/LICENSE +0 -0
- {label_studio_sdk-1.0.17.dist-info → label_studio_sdk-1.0.19.dist-info}/WHEEL +0 -0
label_studio_sdk/__init__.py
CHANGED
|
@@ -159,7 +159,13 @@ from .ml import (
|
|
|
159
159
|
MlUpdateResponse,
|
|
160
160
|
MlUpdateResponseAuthMethod,
|
|
161
161
|
)
|
|
162
|
-
from .projects import
|
|
162
|
+
from .projects import (
|
|
163
|
+
ProjectsCreateResponse,
|
|
164
|
+
ProjectsImportTasksResponse,
|
|
165
|
+
ProjectsListRequestFilter,
|
|
166
|
+
ProjectsListResponse,
|
|
167
|
+
ProjectsUpdateResponse,
|
|
168
|
+
)
|
|
163
169
|
from .prompts import (
|
|
164
170
|
PromptsBatchFailedPredictionsRequestFailedPredictionsItem,
|
|
165
171
|
PromptsBatchFailedPredictionsResponse,
|
|
@@ -293,6 +299,7 @@ __all__ = [
|
|
|
293
299
|
"ProjectSkipQueue",
|
|
294
300
|
"ProjectsCreateResponse",
|
|
295
301
|
"ProjectsImportTasksResponse",
|
|
302
|
+
"ProjectsListRequestFilter",
|
|
296
303
|
"ProjectsListResponse",
|
|
297
304
|
"ProjectsUpdateResponse",
|
|
298
305
|
"Prompt",
|
|
@@ -134,7 +134,7 @@ def has_variable(actual_value):
|
|
|
134
134
|
:param actual_value: value to check
|
|
135
135
|
:return: True if value has variable
|
|
136
136
|
"""
|
|
137
|
-
expression = "^\$[A-Za-z_]+$"
|
|
137
|
+
expression = r"^\$[A-Za-z_]+$"
|
|
138
138
|
pattern = re.compile(expression)
|
|
139
139
|
full_match = pattern.fullmatch(actual_value)
|
|
140
140
|
if full_match:
|
|
@@ -481,6 +481,9 @@ class Converter(object):
|
|
|
481
481
|
then the from_name "my_output_tag_0" should match it, and we should return "my_output_tag_{{idx}}".
|
|
482
482
|
"""
|
|
483
483
|
|
|
484
|
+
best_match = None
|
|
485
|
+
best_match_len = 0
|
|
486
|
+
|
|
484
487
|
for tag_name, tag_info in self._schema.items():
|
|
485
488
|
if tag_name == from_name:
|
|
486
489
|
return tag_name
|
|
@@ -492,10 +495,13 @@ class Converter(object):
|
|
|
492
495
|
for variable, regex in tag_info["regex"].items():
|
|
493
496
|
tag_name_pattern = tag_name_pattern.replace(variable, regex)
|
|
494
497
|
|
|
495
|
-
|
|
496
|
-
|
|
498
|
+
# In some cases there are tags with same prefix - we need to find the best or longest matching pattern
|
|
499
|
+
if r := re.compile(tag_name_pattern).match(from_name):
|
|
500
|
+
if match_len := len(tag_name_pattern) > best_match_len:
|
|
501
|
+
best_match = tag_name
|
|
502
|
+
best_match_len = len(tag_name_pattern)
|
|
497
503
|
|
|
498
|
-
return None
|
|
504
|
+
return best_match if best_match else None
|
|
499
505
|
|
|
500
506
|
def annotation_result_from_task(self, task):
|
|
501
507
|
has_annotations = "completions" in task or "annotations" in task
|
|
@@ -576,13 +582,26 @@ class Converter(object):
|
|
|
576
582
|
self._check_format(Format.JSON)
|
|
577
583
|
ensure_dir(output_dir)
|
|
578
584
|
output_file = os.path.join(output_dir, "result.json")
|
|
579
|
-
|
|
585
|
+
|
|
580
586
|
if is_dir:
|
|
581
|
-
|
|
582
|
-
with io.open(json_file, encoding="utf8") as f:
|
|
583
|
-
records.append(json.load(f))
|
|
587
|
+
# Memory-optimized: stream JSON writing instead of accumulating in memory
|
|
584
588
|
with io.open(output_file, mode="w", encoding="utf8") as fout:
|
|
585
|
-
|
|
589
|
+
fout.write("[\n")
|
|
590
|
+
first_record = True
|
|
591
|
+
|
|
592
|
+
for json_file in glob(os.path.join(input_data, "*.json")):
|
|
593
|
+
with io.open(json_file, encoding="utf8") as f:
|
|
594
|
+
record = json.load(f)
|
|
595
|
+
|
|
596
|
+
if not first_record:
|
|
597
|
+
fout.write(",\n")
|
|
598
|
+
json.dump(record, fout, indent=2, ensure_ascii=False)
|
|
599
|
+
first_record = False
|
|
600
|
+
|
|
601
|
+
# Free memory immediately
|
|
602
|
+
del record
|
|
603
|
+
|
|
604
|
+
fout.write("\n]")
|
|
586
605
|
else:
|
|
587
606
|
copy2(input_data, output_file)
|
|
588
607
|
|
|
@@ -590,26 +609,39 @@ class Converter(object):
|
|
|
590
609
|
self._check_format(Format.JSON_MIN)
|
|
591
610
|
ensure_dir(output_dir)
|
|
592
611
|
output_file = os.path.join(output_dir, "result.json")
|
|
593
|
-
records = []
|
|
594
612
|
item_iterator = self.iter_from_dir if is_dir else self.iter_from_json_file
|
|
595
613
|
|
|
596
|
-
for item in item_iterator(input_data):
|
|
597
|
-
record = deepcopy(item["input"])
|
|
598
|
-
if item.get("id") is not None:
|
|
599
|
-
record["id"] = item["id"]
|
|
600
|
-
for name, value in item["output"].items():
|
|
601
|
-
record[name] = prettify_result(value)
|
|
602
|
-
record["annotator"] = get_annotator(item, int_id=True)
|
|
603
|
-
record["annotation_id"] = item["annotation_id"]
|
|
604
|
-
record["created_at"] = item["created_at"]
|
|
605
|
-
record["updated_at"] = item["updated_at"]
|
|
606
|
-
record["lead_time"] = item["lead_time"]
|
|
607
|
-
if "agreement" in item:
|
|
608
|
-
record["agreement"] = item["agreement"]
|
|
609
|
-
records.append(record)
|
|
610
|
-
|
|
611
614
|
with io.open(output_file, mode="w", encoding="utf8") as fout:
|
|
612
|
-
|
|
615
|
+
fout.write("[\n")
|
|
616
|
+
first_record = True
|
|
617
|
+
|
|
618
|
+
for item in item_iterator(input_data):
|
|
619
|
+
# SAFE memory optimization: use json serialization/deserialization
|
|
620
|
+
# This avoids deepcopy but ensures complete isolation of objects
|
|
621
|
+
record = json.loads(json.dumps(item["input"]))
|
|
622
|
+
|
|
623
|
+
if item.get("id") is not None:
|
|
624
|
+
record["id"] = item["id"]
|
|
625
|
+
for name, value in item["output"].items():
|
|
626
|
+
record[name] = prettify_result(value)
|
|
627
|
+
record["annotator"] = get_annotator(item, int_id=True)
|
|
628
|
+
record["annotation_id"] = item["annotation_id"]
|
|
629
|
+
record["created_at"] = item["created_at"]
|
|
630
|
+
record["updated_at"] = item["updated_at"]
|
|
631
|
+
record["lead_time"] = item["lead_time"]
|
|
632
|
+
if "agreement" in item:
|
|
633
|
+
record["agreement"] = item["agreement"]
|
|
634
|
+
|
|
635
|
+
# Write record to file immediately
|
|
636
|
+
if not first_record:
|
|
637
|
+
fout.write(",\n")
|
|
638
|
+
json.dump(record, fout, indent=2, ensure_ascii=False)
|
|
639
|
+
first_record = False
|
|
640
|
+
|
|
641
|
+
# Explicitly delete record to free memory
|
|
642
|
+
del record
|
|
643
|
+
|
|
644
|
+
fout.write("\n]")
|
|
613
645
|
|
|
614
646
|
def convert_to_csv(self, input_data, output_dir, is_dir=True, **kwargs):
|
|
615
647
|
self._check_format(Format.CSV)
|
label_studio_sdk/files/client.py
CHANGED
|
@@ -119,7 +119,7 @@ class FilesClient:
|
|
|
119
119
|
|
|
120
120
|
You will need to include the file data in the request body. For example:
|
|
121
121
|
```bash
|
|
122
|
-
curl -H 'Authorization: Token abc123'
|
|
122
|
+
curl -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/import/file-upload/245' -F 'file=@path/to/my_file.csv'
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
Parameters
|
|
@@ -445,7 +445,7 @@ class AsyncFilesClient:
|
|
|
445
445
|
|
|
446
446
|
You will need to include the file data in the request body. For example:
|
|
447
447
|
```bash
|
|
448
|
-
curl -H 'Authorization: Token abc123'
|
|
448
|
+
curl -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/import/file-upload/245' -F 'file=@path/to/my_file.csv'
|
|
449
449
|
```
|
|
450
450
|
|
|
451
451
|
Parameters
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
|
-
from .types import
|
|
3
|
+
from .types import (
|
|
4
|
+
ProjectsCreateResponse,
|
|
5
|
+
ProjectsImportTasksResponse,
|
|
6
|
+
ProjectsListRequestFilter,
|
|
7
|
+
ProjectsListResponse,
|
|
8
|
+
ProjectsUpdateResponse,
|
|
9
|
+
)
|
|
4
10
|
from . import exports, pauses
|
|
5
11
|
from .exports import ExportsConvertResponse, ExportsListFormatsResponseItem
|
|
6
12
|
|
|
@@ -9,6 +15,7 @@ __all__ = [
|
|
|
9
15
|
"ExportsListFormatsResponseItem",
|
|
10
16
|
"ProjectsCreateResponse",
|
|
11
17
|
"ProjectsImportTasksResponse",
|
|
18
|
+
"ProjectsListRequestFilter",
|
|
12
19
|
"ProjectsListResponse",
|
|
13
20
|
"ProjectsUpdateResponse",
|
|
14
21
|
"exports",
|
|
@@ -4,6 +4,7 @@ import typing
|
|
|
4
4
|
from ..core.client_wrapper import SyncClientWrapper
|
|
5
5
|
from .pauses.client import PausesClient
|
|
6
6
|
from .exports.client import ExportsClient
|
|
7
|
+
from .types.projects_list_request_filter import ProjectsListRequestFilter
|
|
7
8
|
from ..core.request_options import RequestOptions
|
|
8
9
|
from ..core.pagination import SyncPager
|
|
9
10
|
from ..types.project import Project
|
|
@@ -41,6 +42,8 @@ class ProjectsClient:
|
|
|
41
42
|
page: typing.Optional[int] = None,
|
|
42
43
|
page_size: typing.Optional[int] = None,
|
|
43
44
|
workspaces: typing.Optional[int] = None,
|
|
45
|
+
include: typing.Optional[str] = None,
|
|
46
|
+
filter: typing.Optional[ProjectsListRequestFilter] = None,
|
|
44
47
|
request_options: typing.Optional[RequestOptions] = None,
|
|
45
48
|
) -> SyncPager[Project]:
|
|
46
49
|
"""
|
|
@@ -75,6 +78,12 @@ class ProjectsClient:
|
|
|
75
78
|
workspaces : typing.Optional[int]
|
|
76
79
|
workspaces
|
|
77
80
|
|
|
81
|
+
include : typing.Optional[str]
|
|
82
|
+
Comma-separated list of count fields to include in the response to optimize performance. Available fields: task_number, finished_task_number, total_predictions_number, total_annotations_number, num_tasks_with_annotations, useful_annotation_number, ground_truth_number, skipped_annotations_number. If not specified, all count fields are included.
|
|
83
|
+
|
|
84
|
+
filter : typing.Optional[ProjectsListRequestFilter]
|
|
85
|
+
Filter projects by pinned status. Use 'pinned_only' to return only pinned projects, 'exclude_pinned' to return only non-pinned projects, or 'all' to return all projects.
|
|
86
|
+
|
|
78
87
|
request_options : typing.Optional[RequestOptions]
|
|
79
88
|
Request-specific configuration.
|
|
80
89
|
|
|
@@ -90,7 +99,9 @@ class ProjectsClient:
|
|
|
90
99
|
client = LabelStudio(
|
|
91
100
|
api_key="YOUR_API_KEY",
|
|
92
101
|
)
|
|
93
|
-
response = client.projects.list(
|
|
102
|
+
response = client.projects.list(
|
|
103
|
+
include="task_number,total_annotations_number,num_tasks_with_annotations",
|
|
104
|
+
)
|
|
94
105
|
for item in response:
|
|
95
106
|
yield item
|
|
96
107
|
# alternatively, you can paginate page-by-page
|
|
@@ -108,6 +119,8 @@ class ProjectsClient:
|
|
|
108
119
|
"page": page,
|
|
109
120
|
"page_size": page_size,
|
|
110
121
|
"workspaces": workspaces,
|
|
122
|
+
"include": include,
|
|
123
|
+
"filter": filter,
|
|
111
124
|
},
|
|
112
125
|
request_options=request_options,
|
|
113
126
|
)
|
|
@@ -128,6 +141,8 @@ class ProjectsClient:
|
|
|
128
141
|
page=page + 1,
|
|
129
142
|
page_size=page_size,
|
|
130
143
|
workspaces=workspaces,
|
|
144
|
+
include=include,
|
|
145
|
+
filter=filter,
|
|
131
146
|
request_options=request_options,
|
|
132
147
|
)
|
|
133
148
|
_items = _parsed_response.results
|
|
@@ -207,7 +222,8 @@ class ProjectsClient:
|
|
|
207
222
|
Project color in HEX format
|
|
208
223
|
|
|
209
224
|
control_weights : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
210
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
225
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
226
|
+
|
|
211
227
|
|
|
212
228
|
workspace : typing.Optional[int]
|
|
213
229
|
Workspace ID
|
|
@@ -440,7 +456,8 @@ class ProjectsClient:
|
|
|
440
456
|
Project color in HEX format
|
|
441
457
|
|
|
442
458
|
control_weights : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
443
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
459
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
460
|
+
|
|
444
461
|
|
|
445
462
|
workspace : typing.Optional[int]
|
|
446
463
|
Workspace ID
|
|
@@ -518,84 +535,80 @@ class ProjectsClient:
|
|
|
518
535
|
request_options: typing.Optional[RequestOptions] = None,
|
|
519
536
|
) -> ProjectsImportTasksResponse:
|
|
520
537
|
"""
|
|
521
|
-
|
|
538
|
+
|
|
522
539
|
Use this API endpoint to import labeling tasks in bulk. Note that each POST request is limited at 250K tasks and 200 MB.
|
|
523
|
-
The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../projects/list).
|
|
524
|
-
|
|
540
|
+
The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../projects/list).
|
|
541
|
+
|
|
525
542
|
<Note>
|
|
526
|
-
Imported data is verified against a project *label_config* and must include all variables that were used in the *label_config*.
|
|
527
|
-
|
|
543
|
+
Imported data is verified against a project *label_config* and must include all variables that were used in the *label_config*.
|
|
544
|
+
|
|
528
545
|
For example, if the label configuration has a *$text* variable, then each item in a data object must include a `text` field.
|
|
529
546
|
</Note>
|
|
530
|
-
|
|
547
|
+
|
|
531
548
|
There are three possible ways to import tasks with this endpoint:
|
|
532
|
-
|
|
533
|
-
#### 1
|
|
549
|
+
|
|
550
|
+
#### 1. **POST with data**
|
|
534
551
|
Send JSON tasks as POST data. Only JSON is supported for POSTing files directly.
|
|
535
|
-
|
|
552
|
+
|
|
536
553
|
Update this example to specify your authorization token and Label Studio instance host, then run the following from
|
|
537
554
|
the command line:
|
|
538
|
-
|
|
555
|
+
|
|
539
556
|
```bash
|
|
540
|
-
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123'
|
|
541
|
-
-X POST 'https://localhost:8080/api/projects/1/import' --data '[{"text": "Some text 1"}, {"text": "Some text 2"}]'
|
|
557
|
+
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' --data '[{"text": "Some text 1"}, {"text": "Some text 2"}]'
|
|
542
558
|
```
|
|
543
|
-
|
|
544
|
-
#### 2
|
|
559
|
+
|
|
560
|
+
#### 2. **POST with files**
|
|
545
561
|
Send tasks as files. You can attach multiple files with different names.
|
|
546
|
-
|
|
562
|
+
|
|
547
563
|
- **JSON**: text files in JavaScript object notation format
|
|
548
564
|
- **CSV**: text files with tables in Comma Separated Values format
|
|
549
565
|
- **TSV**: text files with tables in Tab Separated Value format
|
|
550
566
|
- **TXT**: simple text files are similar to CSV with one column and no header, supported for projects with one source only
|
|
551
|
-
|
|
567
|
+
|
|
552
568
|
Update this example to specify your authorization token, Label Studio instance host, and file name and path,
|
|
553
569
|
then run the following from the command line:
|
|
554
|
-
|
|
570
|
+
|
|
555
571
|
```bash
|
|
556
|
-
curl -H 'Authorization: Token abc123'
|
|
557
|
-
-X POST 'https://localhost:8080/api/projects/1/import' -F ‘file=@path/to/my_file.csv’
|
|
572
|
+
curl -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' -F 'file=@path/to/my_file.csv'
|
|
558
573
|
```
|
|
559
|
-
|
|
560
|
-
#### 3
|
|
574
|
+
|
|
575
|
+
#### 3. **POST with URL**
|
|
561
576
|
You can also provide a URL to a file with labeling tasks. Supported file formats are the same as in option 2.
|
|
562
|
-
|
|
577
|
+
|
|
563
578
|
```bash
|
|
564
|
-
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123'
|
|
565
|
-
-X POST 'https://localhost:8080/api/projects/1/import' \
|
|
566
|
-
--data '[{"url": "http://example.com/test1.csv"}, {"url": "http://example.com/test2.csv"}]'
|
|
579
|
+
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' --data '[{"url": "http://example.com/test1.csv"}, {"url": "http://example.com/test2.csv"}]'
|
|
567
580
|
```
|
|
568
|
-
|
|
581
|
+
|
|
569
582
|
<br>
|
|
570
|
-
|
|
583
|
+
|
|
571
584
|
Parameters
|
|
572
585
|
----------
|
|
573
586
|
id : int
|
|
574
587
|
A unique integer value identifying this project.
|
|
575
|
-
|
|
588
|
+
|
|
576
589
|
request : typing.Sequence[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
577
|
-
|
|
590
|
+
|
|
578
591
|
commit_to_project : typing.Optional[bool]
|
|
579
592
|
Set to "true" to immediately commit tasks to the project.
|
|
580
|
-
|
|
593
|
+
|
|
581
594
|
return_task_ids : typing.Optional[bool]
|
|
582
595
|
Set to "true" to return task IDs in the response.
|
|
583
|
-
|
|
596
|
+
|
|
584
597
|
preannotated_from_fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
|
|
585
598
|
List of fields to preannotate from the task data. For example, if you provide a list of `{"text": "text", "prediction": "label"}` items in the request, the system will create a task with the `text` field and a prediction with the `label` field when `preannoted_from_fields=["prediction"]`.
|
|
586
|
-
|
|
599
|
+
|
|
587
600
|
request_options : typing.Optional[RequestOptions]
|
|
588
601
|
Request-specific configuration.
|
|
589
|
-
|
|
602
|
+
|
|
590
603
|
Returns
|
|
591
604
|
-------
|
|
592
605
|
ProjectsImportTasksResponse
|
|
593
606
|
Tasks successfully imported
|
|
594
|
-
|
|
607
|
+
|
|
595
608
|
Examples
|
|
596
609
|
--------
|
|
597
610
|
from label_studio_sdk import LabelStudio
|
|
598
|
-
|
|
611
|
+
|
|
599
612
|
client = LabelStudio(
|
|
600
613
|
api_key="YOUR_API_KEY",
|
|
601
614
|
)
|
|
@@ -716,6 +729,8 @@ class AsyncProjectsClient:
|
|
|
716
729
|
page: typing.Optional[int] = None,
|
|
717
730
|
page_size: typing.Optional[int] = None,
|
|
718
731
|
workspaces: typing.Optional[int] = None,
|
|
732
|
+
include: typing.Optional[str] = None,
|
|
733
|
+
filter: typing.Optional[ProjectsListRequestFilter] = None,
|
|
719
734
|
request_options: typing.Optional[RequestOptions] = None,
|
|
720
735
|
) -> AsyncPager[Project]:
|
|
721
736
|
"""
|
|
@@ -750,6 +765,12 @@ class AsyncProjectsClient:
|
|
|
750
765
|
workspaces : typing.Optional[int]
|
|
751
766
|
workspaces
|
|
752
767
|
|
|
768
|
+
include : typing.Optional[str]
|
|
769
|
+
Comma-separated list of count fields to include in the response to optimize performance. Available fields: task_number, finished_task_number, total_predictions_number, total_annotations_number, num_tasks_with_annotations, useful_annotation_number, ground_truth_number, skipped_annotations_number. If not specified, all count fields are included.
|
|
770
|
+
|
|
771
|
+
filter : typing.Optional[ProjectsListRequestFilter]
|
|
772
|
+
Filter projects by pinned status. Use 'pinned_only' to return only pinned projects, 'exclude_pinned' to return only non-pinned projects, or 'all' to return all projects.
|
|
773
|
+
|
|
753
774
|
request_options : typing.Optional[RequestOptions]
|
|
754
775
|
Request-specific configuration.
|
|
755
776
|
|
|
@@ -770,7 +791,9 @@ class AsyncProjectsClient:
|
|
|
770
791
|
|
|
771
792
|
|
|
772
793
|
async def main() -> None:
|
|
773
|
-
response = await client.projects.list(
|
|
794
|
+
response = await client.projects.list(
|
|
795
|
+
include="task_number,total_annotations_number,num_tasks_with_annotations",
|
|
796
|
+
)
|
|
774
797
|
async for item in response:
|
|
775
798
|
yield item
|
|
776
799
|
# alternatively, you can paginate page-by-page
|
|
@@ -791,6 +814,8 @@ class AsyncProjectsClient:
|
|
|
791
814
|
"page": page,
|
|
792
815
|
"page_size": page_size,
|
|
793
816
|
"workspaces": workspaces,
|
|
817
|
+
"include": include,
|
|
818
|
+
"filter": filter,
|
|
794
819
|
},
|
|
795
820
|
request_options=request_options,
|
|
796
821
|
)
|
|
@@ -811,6 +836,8 @@ class AsyncProjectsClient:
|
|
|
811
836
|
page=page + 1,
|
|
812
837
|
page_size=page_size,
|
|
813
838
|
workspaces=workspaces,
|
|
839
|
+
include=include,
|
|
840
|
+
filter=filter,
|
|
814
841
|
request_options=request_options,
|
|
815
842
|
)
|
|
816
843
|
_items = _parsed_response.results
|
|
@@ -890,7 +917,8 @@ class AsyncProjectsClient:
|
|
|
890
917
|
Project color in HEX format
|
|
891
918
|
|
|
892
919
|
control_weights : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
893
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
920
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
921
|
+
|
|
894
922
|
|
|
895
923
|
workspace : typing.Optional[int]
|
|
896
924
|
Workspace ID
|
|
@@ -1147,7 +1175,8 @@ class AsyncProjectsClient:
|
|
|
1147
1175
|
Project color in HEX format
|
|
1148
1176
|
|
|
1149
1177
|
control_weights : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
1150
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
1178
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
1179
|
+
|
|
1151
1180
|
|
|
1152
1181
|
workspace : typing.Optional[int]
|
|
1153
1182
|
Workspace ID
|
|
@@ -1233,98 +1262,94 @@ class AsyncProjectsClient:
|
|
|
1233
1262
|
request_options: typing.Optional[RequestOptions] = None,
|
|
1234
1263
|
) -> ProjectsImportTasksResponse:
|
|
1235
1264
|
"""
|
|
1236
|
-
|
|
1265
|
+
|
|
1237
1266
|
Use this API endpoint to import labeling tasks in bulk. Note that each POST request is limited at 250K tasks and 200 MB.
|
|
1238
|
-
The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../projects/list).
|
|
1239
|
-
|
|
1267
|
+
The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../projects/list).
|
|
1268
|
+
|
|
1240
1269
|
<Note>
|
|
1241
|
-
Imported data is verified against a project *label_config* and must include all variables that were used in the *label_config*.
|
|
1242
|
-
|
|
1270
|
+
Imported data is verified against a project *label_config* and must include all variables that were used in the *label_config*.
|
|
1271
|
+
|
|
1243
1272
|
For example, if the label configuration has a *$text* variable, then each item in a data object must include a `text` field.
|
|
1244
1273
|
</Note>
|
|
1245
|
-
|
|
1274
|
+
|
|
1246
1275
|
There are three possible ways to import tasks with this endpoint:
|
|
1247
|
-
|
|
1248
|
-
#### 1
|
|
1276
|
+
|
|
1277
|
+
#### 1. **POST with data**
|
|
1249
1278
|
Send JSON tasks as POST data. Only JSON is supported for POSTing files directly.
|
|
1250
|
-
|
|
1279
|
+
|
|
1251
1280
|
Update this example to specify your authorization token and Label Studio instance host, then run the following from
|
|
1252
1281
|
the command line:
|
|
1253
|
-
|
|
1282
|
+
|
|
1254
1283
|
```bash
|
|
1255
|
-
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123'
|
|
1256
|
-
-X POST 'https://localhost:8080/api/projects/1/import' --data '[{"text": "Some text 1"}, {"text": "Some text 2"}]'
|
|
1284
|
+
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' --data '[{"text": "Some text 1"}, {"text": "Some text 2"}]'
|
|
1257
1285
|
```
|
|
1258
|
-
|
|
1259
|
-
#### 2
|
|
1286
|
+
|
|
1287
|
+
#### 2. **POST with files**
|
|
1260
1288
|
Send tasks as files. You can attach multiple files with different names.
|
|
1261
|
-
|
|
1289
|
+
|
|
1262
1290
|
- **JSON**: text files in JavaScript object notation format
|
|
1263
1291
|
- **CSV**: text files with tables in Comma Separated Values format
|
|
1264
1292
|
- **TSV**: text files with tables in Tab Separated Value format
|
|
1265
1293
|
- **TXT**: simple text files are similar to CSV with one column and no header, supported for projects with one source only
|
|
1266
|
-
|
|
1294
|
+
|
|
1267
1295
|
Update this example to specify your authorization token, Label Studio instance host, and file name and path,
|
|
1268
1296
|
then run the following from the command line:
|
|
1269
|
-
|
|
1297
|
+
|
|
1270
1298
|
```bash
|
|
1271
|
-
curl -H 'Authorization: Token abc123'
|
|
1272
|
-
-X POST 'https://localhost:8080/api/projects/1/import' -F ‘file=@path/to/my_file.csv’
|
|
1299
|
+
curl -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' -F 'file=@path/to/my_file.csv'
|
|
1273
1300
|
```
|
|
1274
|
-
|
|
1275
|
-
#### 3
|
|
1301
|
+
|
|
1302
|
+
#### 3. **POST with URL**
|
|
1276
1303
|
You can also provide a URL to a file with labeling tasks. Supported file formats are the same as in option 2.
|
|
1277
|
-
|
|
1304
|
+
|
|
1278
1305
|
```bash
|
|
1279
|
-
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123'
|
|
1280
|
-
-X POST 'https://localhost:8080/api/projects/1/import' \
|
|
1281
|
-
--data '[{"url": "http://example.com/test1.csv"}, {"url": "http://example.com/test2.csv"}]'
|
|
1306
|
+
curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' -X POST 'https://localhost:8080/api/projects/1/import' --data '[{"url": "http://example.com/test1.csv"}, {"url": "http://example.com/test2.csv"}]'
|
|
1282
1307
|
```
|
|
1283
|
-
|
|
1308
|
+
|
|
1284
1309
|
<br>
|
|
1285
|
-
|
|
1310
|
+
|
|
1286
1311
|
Parameters
|
|
1287
1312
|
----------
|
|
1288
1313
|
id : int
|
|
1289
1314
|
A unique integer value identifying this project.
|
|
1290
|
-
|
|
1315
|
+
|
|
1291
1316
|
request : typing.Sequence[typing.Dict[str, typing.Optional[typing.Any]]]
|
|
1292
|
-
|
|
1317
|
+
|
|
1293
1318
|
commit_to_project : typing.Optional[bool]
|
|
1294
1319
|
Set to "true" to immediately commit tasks to the project.
|
|
1295
|
-
|
|
1320
|
+
|
|
1296
1321
|
return_task_ids : typing.Optional[bool]
|
|
1297
1322
|
Set to "true" to return task IDs in the response.
|
|
1298
|
-
|
|
1323
|
+
|
|
1299
1324
|
preannotated_from_fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
|
|
1300
1325
|
List of fields to preannotate from the task data. For example, if you provide a list of `{"text": "text", "prediction": "label"}` items in the request, the system will create a task with the `text` field and a prediction with the `label` field when `preannoted_from_fields=["prediction"]`.
|
|
1301
|
-
|
|
1326
|
+
|
|
1302
1327
|
request_options : typing.Optional[RequestOptions]
|
|
1303
1328
|
Request-specific configuration.
|
|
1304
|
-
|
|
1329
|
+
|
|
1305
1330
|
Returns
|
|
1306
1331
|
-------
|
|
1307
1332
|
ProjectsImportTasksResponse
|
|
1308
1333
|
Tasks successfully imported
|
|
1309
|
-
|
|
1334
|
+
|
|
1310
1335
|
Examples
|
|
1311
1336
|
--------
|
|
1312
1337
|
import asyncio
|
|
1313
|
-
|
|
1338
|
+
|
|
1314
1339
|
from label_studio_sdk import AsyncLabelStudio
|
|
1315
|
-
|
|
1340
|
+
|
|
1316
1341
|
client = AsyncLabelStudio(
|
|
1317
1342
|
api_key="YOUR_API_KEY",
|
|
1318
1343
|
)
|
|
1319
|
-
|
|
1320
|
-
|
|
1344
|
+
|
|
1345
|
+
|
|
1321
1346
|
async def main() -> None:
|
|
1322
1347
|
await client.projects.import_tasks(
|
|
1323
1348
|
id=1,
|
|
1324
1349
|
request=[{"key": "value"}],
|
|
1325
1350
|
)
|
|
1326
|
-
|
|
1327
|
-
|
|
1351
|
+
|
|
1352
|
+
|
|
1328
1353
|
asyncio.run(main())
|
|
1329
1354
|
"""
|
|
1330
1355
|
_response = await self._client_wrapper.httpx_client.request(
|
|
@@ -55,7 +55,7 @@ class ExportsClient:
|
|
|
55
55
|
```
|
|
56
56
|
To export specific tasks with IDs of 123 and 345, run the following from the command line:
|
|
57
57
|
```bash
|
|
58
|
-
curl -X GET https://localhost:8080/api/projects/{id}/export?ids[]=123
|
|
58
|
+
curl -X GET "https://localhost:8080/api/projects/{id}/export?ids[]=123&ids[]=345" -H 'Authorization: Token abc123' --output 'annotations.json'
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
You must provide a project ID. The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../list).
|
|
@@ -604,7 +604,7 @@ class AsyncExportsClient:
|
|
|
604
604
|
```
|
|
605
605
|
To export specific tasks with IDs of 123 and 345, run the following from the command line:
|
|
606
606
|
```bash
|
|
607
|
-
curl -X GET https://localhost:8080/api/projects/{id}/export?ids[]=123
|
|
607
|
+
curl -X GET "https://localhost:8080/api/projects/{id}/export?ids[]=123&ids[]=345" -H 'Authorization: Token abc123' --output 'annotations.json'
|
|
608
608
|
```
|
|
609
609
|
|
|
610
610
|
You must provide a project ID. The project ID can be found in the URL when viewing the project in Label Studio, or you can retrieve all project IDs using [List all projects](../list).
|
|
@@ -15,11 +15,11 @@ class ExportTimeoutError(ApiError):
|
|
|
15
15
|
super().__init__(
|
|
16
16
|
status_code=500,
|
|
17
17
|
body=(
|
|
18
|
-
f"Export job timed out
|
|
18
|
+
f"Export job timed out: "
|
|
19
19
|
f"unable to retrieve export job {export_snapshot.id}. "
|
|
20
20
|
f"Current status: {export_snapshot.status}. "
|
|
21
21
|
f"Try manually checking the running job with "
|
|
22
|
-
f"`ls.projects.exports.get(
|
|
22
|
+
f"`ls.projects.exports.get(id=<PROJECT_ID>, export_pk={export_snapshot.id})`."
|
|
23
23
|
)
|
|
24
24
|
)
|
|
25
25
|
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from .projects_create_response import ProjectsCreateResponse
|
|
4
4
|
from .projects_import_tasks_response import ProjectsImportTasksResponse
|
|
5
|
+
from .projects_list_request_filter import ProjectsListRequestFilter
|
|
5
6
|
from .projects_list_response import ProjectsListResponse
|
|
6
7
|
from .projects_update_response import ProjectsUpdateResponse
|
|
7
8
|
|
|
8
|
-
__all__ = [
|
|
9
|
+
__all__ = [
|
|
10
|
+
"ProjectsCreateResponse",
|
|
11
|
+
"ProjectsImportTasksResponse",
|
|
12
|
+
"ProjectsListRequestFilter",
|
|
13
|
+
"ProjectsListResponse",
|
|
14
|
+
"ProjectsUpdateResponse",
|
|
15
|
+
]
|
|
@@ -78,7 +78,7 @@ class ProjectsCreateResponse(UniversalBaseModel):
|
|
|
78
78
|
|
|
79
79
|
control_weights: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
|
|
80
80
|
"""
|
|
81
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
81
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
82
82
|
"""
|
|
83
83
|
|
|
84
84
|
if IS_PYDANTIC_V2:
|
|
@@ -83,7 +83,7 @@ class ProjectsUpdateResponse(UniversalBaseModel):
|
|
|
83
83
|
|
|
84
84
|
control_weights: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
|
|
85
85
|
"""
|
|
86
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}
|
|
86
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
87
87
|
"""
|
|
88
88
|
|
|
89
89
|
if IS_PYDANTIC_V2:
|
|
@@ -397,6 +397,7 @@ class PromptsClient:
|
|
|
397
397
|
def batch_predictions(
|
|
398
398
|
self,
|
|
399
399
|
*,
|
|
400
|
+
num_predictions: typing.Optional[int] = None,
|
|
400
401
|
modelrun_id: typing.Optional[int] = OMIT,
|
|
401
402
|
results: typing.Optional[typing.Sequence[PromptsBatchPredictionsRequestResultsItem]] = OMIT,
|
|
402
403
|
request_options: typing.Optional[RequestOptions] = None,
|
|
@@ -406,6 +407,9 @@ class PromptsClient:
|
|
|
406
407
|
|
|
407
408
|
Parameters
|
|
408
409
|
----------
|
|
410
|
+
num_predictions : typing.Optional[int]
|
|
411
|
+
Number of predictions being sent
|
|
412
|
+
|
|
409
413
|
modelrun_id : typing.Optional[int]
|
|
410
414
|
Model Run ID to associate the prediction with
|
|
411
415
|
|
|
@@ -431,6 +435,9 @@ class PromptsClient:
|
|
|
431
435
|
_response = self._client_wrapper.httpx_client.request(
|
|
432
436
|
"api/model-run/batch-predictions",
|
|
433
437
|
method="POST",
|
|
438
|
+
params={
|
|
439
|
+
"num_predictions": num_predictions,
|
|
440
|
+
},
|
|
434
441
|
json={
|
|
435
442
|
"modelrun_id": modelrun_id,
|
|
436
443
|
"results": convert_and_respect_annotation_metadata(
|
|
@@ -462,6 +469,7 @@ class PromptsClient:
|
|
|
462
469
|
def batch_failed_predictions(
|
|
463
470
|
self,
|
|
464
471
|
*,
|
|
472
|
+
num_failed_predictions: typing.Optional[int] = None,
|
|
465
473
|
modelrun_id: typing.Optional[int] = OMIT,
|
|
466
474
|
failed_predictions: typing.Optional[
|
|
467
475
|
typing.Sequence[PromptsBatchFailedPredictionsRequestFailedPredictionsItem]
|
|
@@ -473,6 +481,9 @@ class PromptsClient:
|
|
|
473
481
|
|
|
474
482
|
Parameters
|
|
475
483
|
----------
|
|
484
|
+
num_failed_predictions : typing.Optional[int]
|
|
485
|
+
Number of failed predictions being sent
|
|
486
|
+
|
|
476
487
|
modelrun_id : typing.Optional[int]
|
|
477
488
|
Model Run ID where the failed predictions came from
|
|
478
489
|
|
|
@@ -498,6 +509,9 @@ class PromptsClient:
|
|
|
498
509
|
_response = self._client_wrapper.httpx_client.request(
|
|
499
510
|
"api/model-run/batch-failed-predictions",
|
|
500
511
|
method="POST",
|
|
512
|
+
params={
|
|
513
|
+
"num_failed_predictions": num_failed_predictions,
|
|
514
|
+
},
|
|
501
515
|
json={
|
|
502
516
|
"modelrun_id": modelrun_id,
|
|
503
517
|
"failed_predictions": convert_and_respect_annotation_metadata(
|
|
@@ -933,6 +947,7 @@ class AsyncPromptsClient:
|
|
|
933
947
|
async def batch_predictions(
|
|
934
948
|
self,
|
|
935
949
|
*,
|
|
950
|
+
num_predictions: typing.Optional[int] = None,
|
|
936
951
|
modelrun_id: typing.Optional[int] = OMIT,
|
|
937
952
|
results: typing.Optional[typing.Sequence[PromptsBatchPredictionsRequestResultsItem]] = OMIT,
|
|
938
953
|
request_options: typing.Optional[RequestOptions] = None,
|
|
@@ -942,6 +957,9 @@ class AsyncPromptsClient:
|
|
|
942
957
|
|
|
943
958
|
Parameters
|
|
944
959
|
----------
|
|
960
|
+
num_predictions : typing.Optional[int]
|
|
961
|
+
Number of predictions being sent
|
|
962
|
+
|
|
945
963
|
modelrun_id : typing.Optional[int]
|
|
946
964
|
Model Run ID to associate the prediction with
|
|
947
965
|
|
|
@@ -975,6 +993,9 @@ class AsyncPromptsClient:
|
|
|
975
993
|
_response = await self._client_wrapper.httpx_client.request(
|
|
976
994
|
"api/model-run/batch-predictions",
|
|
977
995
|
method="POST",
|
|
996
|
+
params={
|
|
997
|
+
"num_predictions": num_predictions,
|
|
998
|
+
},
|
|
978
999
|
json={
|
|
979
1000
|
"modelrun_id": modelrun_id,
|
|
980
1001
|
"results": convert_and_respect_annotation_metadata(
|
|
@@ -1006,6 +1027,7 @@ class AsyncPromptsClient:
|
|
|
1006
1027
|
async def batch_failed_predictions(
|
|
1007
1028
|
self,
|
|
1008
1029
|
*,
|
|
1030
|
+
num_failed_predictions: typing.Optional[int] = None,
|
|
1009
1031
|
modelrun_id: typing.Optional[int] = OMIT,
|
|
1010
1032
|
failed_predictions: typing.Optional[
|
|
1011
1033
|
typing.Sequence[PromptsBatchFailedPredictionsRequestFailedPredictionsItem]
|
|
@@ -1017,6 +1039,9 @@ class AsyncPromptsClient:
|
|
|
1017
1039
|
|
|
1018
1040
|
Parameters
|
|
1019
1041
|
----------
|
|
1042
|
+
num_failed_predictions : typing.Optional[int]
|
|
1043
|
+
Number of failed predictions being sent
|
|
1044
|
+
|
|
1020
1045
|
modelrun_id : typing.Optional[int]
|
|
1021
1046
|
Model Run ID where the failed predictions came from
|
|
1022
1047
|
|
|
@@ -1050,6 +1075,9 @@ class AsyncPromptsClient:
|
|
|
1050
1075
|
_response = await self._client_wrapper.httpx_client.request(
|
|
1051
1076
|
"api/model-run/batch-failed-predictions",
|
|
1052
1077
|
method="POST",
|
|
1078
|
+
params={
|
|
1079
|
+
"num_failed_predictions": num_failed_predictions,
|
|
1080
|
+
},
|
|
1053
1081
|
json={
|
|
1054
1082
|
"modelrun_id": modelrun_id,
|
|
1055
1083
|
"failed_predictions": convert_and_respect_annotation_metadata(
|
|
@@ -115,7 +115,6 @@ class TokensClientExt:
|
|
|
115
115
|
|
|
116
116
|
# For sync client, use it directly
|
|
117
117
|
if isinstance(existing_client, httpx.Client):
|
|
118
|
-
print(f"\nverify:{existing_client._transport._pool._ssl_context.verify_mode != ssl.CERT_NONE}")
|
|
119
118
|
response = existing_client.request(
|
|
120
119
|
method="POST",
|
|
121
120
|
url=f"{self._base_url}/api/token/refresh/",
|
|
@@ -154,7 +154,7 @@ class Project(UniversalBaseModel):
|
|
|
154
154
|
|
|
155
155
|
control_weights: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
|
|
156
156
|
"""
|
|
157
|
-
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have
|
|
157
|
+
Dict of weights for each control tag in metric calculation. Each control tag (e.g. label or choice) will have its own key in control weight dict with weight for each label and overall weight. For example, if a bounding box annotation with a control tag named my_bbox should be included with 0.33 weight in agreement calculation, and the first label Car should be twice as important as Airplane, then you need to specify: {'my_bbox': {'type': 'RectangleLabels', 'labels': {'Car': 1.0, 'Airplane': 0.5}, 'overall': 0.33}}
|
|
158
158
|
"""
|
|
159
159
|
|
|
160
160
|
parsed_label_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: label-studio-sdk
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.19
|
|
4
4
|
Summary:
|
|
5
5
|
Requires-Python: >=3.9,<4
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.8
|
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
|
-
Requires-Dist: Pillow (>=
|
|
22
|
+
Requires-Dist: Pillow (>=11.3.0)
|
|
23
23
|
Requires-Dist: appdirs (>=1.4.3)
|
|
24
24
|
Requires-Dist: datamodel-code-generator (==0.26.1)
|
|
25
25
|
Requires-Dist: httpx (>=0.21.2)
|
|
@@ -38,6 +38,7 @@ Requires-Dist: requests (>=2.22.0)
|
|
|
38
38
|
Requires-Dist: requests-mock (==1.12.1)
|
|
39
39
|
Requires-Dist: typing_extensions (>=4.0.0)
|
|
40
40
|
Requires-Dist: ujson (>=5.8.0)
|
|
41
|
+
Requires-Dist: urllib3 (>=2.5.0)
|
|
41
42
|
Requires-Dist: xmljson (==0.2.1)
|
|
42
43
|
Project-URL: Repository, https://github.com/HumanSignal/label-studio-sdk
|
|
43
44
|
Description-Content-Type: text/markdown
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
label_studio_sdk/__init__.py,sha256=
|
|
1
|
+
label_studio_sdk/__init__.py,sha256=vNRiBsfE5v5PbMxqdCVVgKfLLzv1XXzE_CrxUXYfgeM,11348
|
|
2
2
|
label_studio_sdk/_extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
label_studio_sdk/_extensions/eval/categorical.py,sha256=MxH2Jl8Mc6HS2byBnlRgABZgwMutSQdH3tgspwCkxqk,2703
|
|
4
4
|
label_studio_sdk/_extensions/label_studio_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
label_studio_sdk/_extensions/label_studio_tools/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
label_studio_sdk/_extensions/label_studio_tools/core/label_config.py,sha256=
|
|
6
|
+
label_studio_sdk/_extensions/label_studio_tools/core/label_config.py,sha256=0wO66cjLOshPYZlt55L6CQqqhaZHdnuB7F56d9TCXxA,6407
|
|
7
7
|
label_studio_sdk/_extensions/label_studio_tools/core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
label_studio_sdk/_extensions/label_studio_tools/core/utils/exceptions.py,sha256=JxaXUMghUp1YvL--s8KFC4mCHVbV39giE3kSBHCmuFU,66
|
|
9
9
|
label_studio_sdk/_extensions/label_studio_tools/core/utils/io.py,sha256=NJHLJA8Q93_MLmo_Yx9F4_Z-kkWCZmF_Ahi3MtDQCPo,14800
|
|
@@ -51,7 +51,7 @@ label_studio_sdk/converter/README.md,sha256=FRUrgLCpVhC4sI5VwVVjuPvmKthnatgyoxhg
|
|
|
51
51
|
label_studio_sdk/converter/__init__.py,sha256=qppSJed16HAiZbGons0yVrPRjszuWFia025Rm477q1c,201
|
|
52
52
|
label_studio_sdk/converter/audio.py,sha256=U9oTULkeimodZhIkB16Gl3eJD8YzsbADWxW_r2tPcxw,1905
|
|
53
53
|
label_studio_sdk/converter/brush.py,sha256=jRL3fLl_J06fVEX7Uat31ru0uUZ71C4zrXnX2qOcrIo,13370
|
|
54
|
-
label_studio_sdk/converter/converter.py,sha256=
|
|
54
|
+
label_studio_sdk/converter/converter.py,sha256=IRqzftLagEFmloWkhwv0yWmBFOdmyFggusAyIzIskx8,51900
|
|
55
55
|
label_studio_sdk/converter/exports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
56
|
label_studio_sdk/converter/exports/brush_to_coco.py,sha256=YeVSyZxmXwLbqox7dS3IRuzR1mYTlUhg6YgK4Txq00U,13355
|
|
57
57
|
label_studio_sdk/converter/exports/csv.py,sha256=F4t04tFsg5gBXTZNmkjw_NeEVsobRH_Y_vfFDi7R0Zw,2865
|
|
@@ -119,7 +119,7 @@ label_studio_sdk/export_storage/s3s/client.py,sha256=re4r1x1TKV03H8ANOCkH-hLJ3hl
|
|
|
119
119
|
label_studio_sdk/export_storage/types/__init__.py,sha256=G7iAfiRBL1WTYsluefJV4ZFUaBmK4mMp9sAMPJ7NZbw,203
|
|
120
120
|
label_studio_sdk/export_storage/types/export_storage_list_types_response_item.py,sha256=DdDwMSOIXIjlAiJFL_6kclDIOvojbOIMuuiE4FgLjyo,642
|
|
121
121
|
label_studio_sdk/files/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
|
122
|
-
label_studio_sdk/files/client.py,sha256=
|
|
122
|
+
label_studio_sdk/files/client.py,sha256=_NbCzzKOeRhaAQgmhE-v31TN8no9T_atBSl7AEPne3s,21159
|
|
123
123
|
label_studio_sdk/import_storage/__init__.py,sha256=uJTTAcQ0OaeBxYNkKf7T4x7fbyL-JqtB_o64M_OF1mk,840
|
|
124
124
|
label_studio_sdk/import_storage/azure/__init__.py,sha256=WflFc5wcr-Pgvi8vGcNCTKOPaIKxy-_RgMx2qttAHYc,183
|
|
125
125
|
label_studio_sdk/import_storage/azure/client.py,sha256=8Ltp-63q7d0qqmReixTVn4JT3YvACdO9sPswcXfsphk,41504
|
|
@@ -176,24 +176,25 @@ label_studio_sdk/model_providers/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-
|
|
|
176
176
|
label_studio_sdk/model_providers/client.py,sha256=-9829DK8F2VG-Oh6H4cYfDzch9CFIwfK5ruEkRD4LL8,29619
|
|
177
177
|
label_studio_sdk/predictions/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
|
178
178
|
label_studio_sdk/predictions/client.py,sha256=E-PsH5iTV84lqJcPccQ4ca0BCfRBqbi_WH5NKwW63r8,28614
|
|
179
|
-
label_studio_sdk/projects/__init__.py,sha256=
|
|
180
|
-
label_studio_sdk/projects/client.py,sha256=
|
|
179
|
+
label_studio_sdk/projects/__init__.py,sha256=DvCQD1lvYyBN03S-wuBuDcNNjeg3J8dlSdgfhPpZ0pc,608
|
|
180
|
+
label_studio_sdk/projects/client.py,sha256=msdt5u6sgFx_al6HtlqCzoRBhgXtGDb92hhgTORFLtw,57510
|
|
181
181
|
label_studio_sdk/projects/client_ext.py,sha256=vZfH4Pk6nnBQyWSHOx-85Ld9i5BoWVZelBrzJRpcwW0,1847
|
|
182
182
|
label_studio_sdk/projects/exports/__init__.py,sha256=wG6u6ZnbKCZkFKWrP1SJ-z86aBMo1z-2Xa0-uEOA8AU,211
|
|
183
|
-
label_studio_sdk/projects/exports/client.py,sha256=
|
|
184
|
-
label_studio_sdk/projects/exports/client_ext.py,sha256=
|
|
183
|
+
label_studio_sdk/projects/exports/client.py,sha256=zA-AC7U6uSKkk6xugSPVkJ5SsB_hSC_7l_aDQjgVBn4,45954
|
|
184
|
+
label_studio_sdk/projects/exports/client_ext.py,sha256=FxyCu63atFmJjBL1MTyqZZFVyMKnY6xsIWCaCzWCEPE,11401
|
|
185
185
|
label_studio_sdk/projects/exports/types/__init__.py,sha256=9VA__mPFYmGOafvVs2rs0zJRBCJP9BWjvEIu_nHowl4,277
|
|
186
186
|
label_studio_sdk/projects/exports/types/exports_convert_response.py,sha256=R2dglNXpebNnpAFzBr29h3BoobTSVpydMpZld-JMav8,779
|
|
187
187
|
label_studio_sdk/projects/exports/types/exports_list_formats_response_item.py,sha256=QivCKxhIGqD80uY_eh40pUIfNydtMSm-UCFE1ByU050,1257
|
|
188
188
|
label_studio_sdk/projects/pauses/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
|
189
189
|
label_studio_sdk/projects/pauses/client.py,sha256=Kh0F5FdibQJts07hIgdg2lsosi5yhQa8L-xwn47NqxI,19903
|
|
190
|
-
label_studio_sdk/projects/types/__init__.py,sha256=
|
|
191
|
-
label_studio_sdk/projects/types/projects_create_response.py,sha256=
|
|
190
|
+
label_studio_sdk/projects/types/__init__.py,sha256=si-2rVuu1TuP6zEOc21WcRo1MTG8FDPjo_s5wR7GPrA,555
|
|
191
|
+
label_studio_sdk/projects/types/projects_create_response.py,sha256=9Q_DvCgFIM_cJyexqWbQorQ2pybNqUF_UP_9qRkOyc8,2905
|
|
192
192
|
label_studio_sdk/projects/types/projects_import_tasks_response.py,sha256=yOEpzLArXDWcoePtOAEYcquLcZ5yypoE9Vvi-E73nyg,1652
|
|
193
|
+
label_studio_sdk/projects/types/projects_list_request_filter.py,sha256=wcCC37Nmk6x1KBV7mGA2DF34npfU7aDNg5W1yOE3i7k,189
|
|
193
194
|
label_studio_sdk/projects/types/projects_list_response.py,sha256=r54zYRG45uQcFoQfD-AsJk76LtMbIQIMqeU_5L95Cpk,717
|
|
194
|
-
label_studio_sdk/projects/types/projects_update_response.py,sha256=
|
|
195
|
+
label_studio_sdk/projects/types/projects_update_response.py,sha256=zOnxxc-7iAXqNzalbVBqF_FhMg2uLo7gzGjs4pxTres,3111
|
|
195
196
|
label_studio_sdk/prompts/__init__.py,sha256=znKhqejZYbD2umWc9tuSD7pm0PyxMw9jmjGzNSUvius,661
|
|
196
|
-
label_studio_sdk/prompts/client.py,sha256=
|
|
197
|
+
label_studio_sdk/prompts/client.py,sha256=HtHlhiR3VQ8arbK5am_stOqChK_mUgI6wiw3pu0BagM,36627
|
|
197
198
|
label_studio_sdk/prompts/indicators/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
|
198
199
|
label_studio_sdk/prompts/indicators/client.py,sha256=yNFhW05eQOe7QNQ7qniewB1kSrg_wtSSnYSAaMaUUds,7188
|
|
199
200
|
label_studio_sdk/prompts/runs/__init__.py,sha256=o6GLzKNZevVPlSvNx_Tdf8xNX51s6gA4SvNL2rUF7bk,157
|
|
@@ -216,7 +217,7 @@ label_studio_sdk/tasks/types/tasks_list_request_fields.py,sha256=5YXxQgyzoaL0QjS
|
|
|
216
217
|
label_studio_sdk/tasks/types/tasks_list_response.py,sha256=j1pNluAWQOQ8-d9YXQyRQAefnrl8uLQEB7_L55Z8DME,1136
|
|
217
218
|
label_studio_sdk/tokens/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
|
218
219
|
label_studio_sdk/tokens/client.py,sha256=SvBcKXIsrTihMJC72Ifxv0U1N3gtLGz3JxqdXYA_hD4,19101
|
|
219
|
-
label_studio_sdk/tokens/client_ext.py,sha256=
|
|
220
|
+
label_studio_sdk/tokens/client_ext.py,sha256=1cXNmCuduZ91oB_3VjL8zEiEWWCQZDrDMoSllUqKp2E,6026
|
|
220
221
|
label_studio_sdk/types/__init__.py,sha256=aPj6Z3mty9ksjj77sJAanHSpP94ieyrWmCyfV-nb19I,9237
|
|
221
222
|
label_studio_sdk/types/access_token_response.py,sha256=RV9FqkIiFR_9kmKueB-KiqjVyneiqUkMVueAlk5fUyc,624
|
|
222
223
|
label_studio_sdk/types/annotation.py,sha256=AnHm2VjMasWZsaNXVSUzLYbpYrmM4NPZgWQh7WGa6ZQ,3157
|
|
@@ -284,7 +285,7 @@ label_studio_sdk/types/model_provider_connection_scope.py,sha256=yi-uNxAvmpe7dvL
|
|
|
284
285
|
label_studio_sdk/types/pause.py,sha256=QTO1uADV2UXczHs2k0vAXCrPDBRC5Go1WKea89Vpd-Q,1103
|
|
285
286
|
label_studio_sdk/types/pause_paused_by.py,sha256=UvdmhKEDKZz2gyy27X8AKavtYn3Bn0bndMWOkBmg0nE,161
|
|
286
287
|
label_studio_sdk/types/prediction.py,sha256=Uv6aT8SKEUebN19LPGAJEuAbXJZkOGjKxsszONKYH4s,2096
|
|
287
|
-
label_studio_sdk/types/project.py,sha256=
|
|
288
|
+
label_studio_sdk/types/project.py,sha256=YO-2D7H4SR9A1WZe5jhIJz436lNElOaJVto63WPK9cY,7139
|
|
288
289
|
label_studio_sdk/types/project_import.py,sha256=VjYbzgov3ni878Suj7zn1K26NU7N5jGEyMzaRaGGwIk,2087
|
|
289
290
|
label_studio_sdk/types/project_import_status.py,sha256=FEFdU3D0_Ga9dDv-yNjcr3ATm8VhmBg5xKYm6DXP_e0,192
|
|
290
291
|
label_studio_sdk/types/project_label_config.py,sha256=-Xp-mJLV0RtVo2PfUs9qv6pDRQiIOBQhzRMCHntYWUo,671
|
|
@@ -367,7 +368,7 @@ label_studio_sdk/workspaces/members/client.py,sha256=IVM52Yq_9zMQ3TUHT0AkZ5BTQ9a
|
|
|
367
368
|
label_studio_sdk/workspaces/members/types/__init__.py,sha256=ZIa_rd7d6K9ZITjTU6fptyGgvjNDySksJ7Rbn4wyhD4,252
|
|
368
369
|
label_studio_sdk/workspaces/members/types/members_create_response.py,sha256=7Hp5FSWm4xR5ZOEmEIglq5HYtM9KWZZBDp87jw7jYFg,668
|
|
369
370
|
label_studio_sdk/workspaces/members/types/members_list_response_item.py,sha256=DIc5DJoVahI9olBis_iFgOJrAf05m2fCE8g4R5ZeDko,712
|
|
370
|
-
label_studio_sdk-1.0.
|
|
371
|
-
label_studio_sdk-1.0.
|
|
372
|
-
label_studio_sdk-1.0.
|
|
373
|
-
label_studio_sdk-1.0.
|
|
371
|
+
label_studio_sdk-1.0.19.dist-info/LICENSE,sha256=ymVrFcHiJGjHeY30NWZgdV-xzNEtfuC63oK9ZeMDjhs,11341
|
|
372
|
+
label_studio_sdk-1.0.19.dist-info/METADATA,sha256=c5gEku_mr-anWXIm1jt2cyLbp63ivylX-I3AeZNQ0Jg,6066
|
|
373
|
+
label_studio_sdk-1.0.19.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
374
|
+
label_studio_sdk-1.0.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|