Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: LEAP-1354: API for Bulk Annotation #301

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .mock/definition/annotations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -421,5 +421,36 @@ service:
last_created_by: 1
audiences:
- public
createBulk:
path: /api/annotations/bulk
method: POST
auth: true
docs: |
Create multiple annotations for specific tasks in a bulk operation.
display-name: Create annotations in bulk
request:
name: AnnotationsCreateBulkRequest
body:
properties:
tasks: optional<list<integer>>
lead_time: optional<double>
project: optional<integer>
result: optional<map<string, unknown>>
response:
docs: Annotations created successfully
type: list<AnnotationsCreateBulkResponseItem>
examples:
- request: {}
response:
body:
- id: 1
audiences:
- public
source:
openapi: openapi/openapi.yaml
types:
AnnotationsCreateBulkResponseItem:
properties:
id: optional<integer>
source:
openapi: openapi/openapi.yaml
203 changes: 102 additions & 101 deletions poetry.lock

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,98 @@ client.annotations.create(
</dl>


</dd>
</dl>
</details>

<details><summary><code>client.annotations.<a href="src/label_studio_sdk/annotations/client.py">create_bulk</a>(...)</code></summary>
<dl>
<dd>

#### 📝 Description

<dl>
<dd>

<dl>
<dd>

Create multiple annotations for specific tasks in a bulk operation.
</dd>
</dl>
</dd>
</dl>

#### 🔌 Usage

<dl>
<dd>

<dl>
<dd>

```python
from label_studio_sdk.client import LabelStudio

client = LabelStudio(
api_key="YOUR_API_KEY",
)
client.annotations.create_bulk()

```
</dd>
</dl>
</dd>
</dl>

#### ⚙️ Parameters

<dl>
<dd>

<dl>
<dd>

**tasks:** `typing.Optional[typing.Sequence[int]]`

</dd>
</dl>

<dl>
<dd>

**lead_time:** `typing.Optional[float]`

</dd>
</dl>

<dl>
<dd>

**project:** `typing.Optional[int]`

</dd>
</dl>

<dl>
<dd>

**result:** `typing.Optional[typing.Dict[str, typing.Any]]`

</dd>
</dl>

<dl>
<dd>

**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.

</dd>
</dl>
</dd>
</dl>


</dd>
</dl>
</details>
Expand Down
2 changes: 2 additions & 0 deletions src/label_studio_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
ActionsCreateRequestSelectedItemsExcluded,
ActionsCreateRequestSelectedItemsIncluded,
)
from .annotations import AnnotationsCreateBulkResponseItem
from .environment import LabelStudioEnvironment
from .export_storage import ExportStorageListTypesResponseItem
from .import_storage import ImportStorageListTypesResponseItem
Expand Down Expand Up @@ -178,6 +179,7 @@
"Annotation",
"AnnotationFilterOptions",
"AnnotationLastAction",
"AnnotationsCreateBulkResponseItem",
"AnnotationsDmField",
"AnnotationsDmFieldLastAction",
"AzureBlobExportStorage",
Expand Down
3 changes: 3 additions & 0 deletions src/label_studio_sdk/annotations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# This file was auto-generated by Fern from our API Definition.

from .types import AnnotationsCreateBulkResponseItem

__all__ = ["AnnotationsCreateBulkResponseItem"]
109 changes: 109 additions & 0 deletions src/label_studio_sdk/annotations/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ..core.pydantic_utilities import pydantic_v1
from ..core.request_options import RequestOptions
from ..types.annotation import Annotation
from .types.annotations_create_bulk_response_item import AnnotationsCreateBulkResponseItem

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
Expand Down Expand Up @@ -380,6 +381,60 @@ def create(
raise ApiError(status_code=_response.status_code, body=_response.text)
raise ApiError(status_code=_response.status_code, body=_response_json)

def create_bulk(
self,
*,
tasks: typing.Optional[typing.Sequence[int]] = OMIT,
lead_time: typing.Optional[float] = OMIT,
project: typing.Optional[int] = OMIT,
result: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.List[AnnotationsCreateBulkResponseItem]:
"""
Create multiple annotations for specific tasks in a bulk operation.

Parameters
----------
tasks : typing.Optional[typing.Sequence[int]]

lead_time : typing.Optional[float]

project : typing.Optional[int]

result : typing.Optional[typing.Dict[str, typing.Any]]

request_options : typing.Optional[RequestOptions]
Request-specific configuration.

Returns
-------
typing.List[AnnotationsCreateBulkResponseItem]
Annotations created successfully

Examples
--------
from label_studio_sdk.client import LabelStudio

client = LabelStudio(
api_key="YOUR_API_KEY",
)
client.annotations.create_bulk()
"""
_response = self._client_wrapper.httpx_client.request(
"api/annotations/bulk",
method="POST",
json={"tasks": tasks, "lead_time": lead_time, "project": project, "result": result},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
return pydantic_v1.parse_obj_as(typing.List[AnnotationsCreateBulkResponseItem], _response.json()) # type: ignore
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, body=_response.text)
raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncAnnotationsClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
Expand Down Expand Up @@ -748,3 +803,57 @@ async def create(
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, body=_response.text)
raise ApiError(status_code=_response.status_code, body=_response_json)

async def create_bulk(
self,
*,
tasks: typing.Optional[typing.Sequence[int]] = OMIT,
lead_time: typing.Optional[float] = OMIT,
project: typing.Optional[int] = OMIT,
result: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.List[AnnotationsCreateBulkResponseItem]:
"""
Create multiple annotations for specific tasks in a bulk operation.

Parameters
----------
tasks : typing.Optional[typing.Sequence[int]]

lead_time : typing.Optional[float]

project : typing.Optional[int]

result : typing.Optional[typing.Dict[str, typing.Any]]

request_options : typing.Optional[RequestOptions]
Request-specific configuration.

Returns
-------
typing.List[AnnotationsCreateBulkResponseItem]
Annotations created successfully

Examples
--------
from label_studio_sdk.client import AsyncLabelStudio

client = AsyncLabelStudio(
api_key="YOUR_API_KEY",
)
await client.annotations.create_bulk()
"""
_response = await self._client_wrapper.httpx_client.request(
"api/annotations/bulk",
method="POST",
json={"tasks": tasks, "lead_time": lead_time, "project": project, "result": result},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
return pydantic_v1.parse_obj_as(typing.List[AnnotationsCreateBulkResponseItem], _response.json()) # type: ignore
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, body=_response.text)
raise ApiError(status_code=_response.status_code, body=_response_json)
5 changes: 5 additions & 0 deletions src/label_studio_sdk/annotations/types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This file was auto-generated by Fern from our API Definition.

from .annotations_create_bulk_response_item import AnnotationsCreateBulkResponseItem

__all__ = ["AnnotationsCreateBulkResponseItem"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import typing

from ...core.datetime_utils import serialize_datetime
from ...core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1


class AnnotationsCreateBulkResponseItem(pydantic_v1.BaseModel):
id: typing.Optional[int] = None

def json(self, **kwargs: typing.Any) -> str:
kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
return super().json(**kwargs_with_defaults)

def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs}

return deep_union_pydantic_dicts(
super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none)
)

class Config:
frozen = True
smart_union = True
extra = pydantic_v1.Extra.allow
json_encoders = {dt.datetime: serialize_datetime}
10 changes: 10 additions & 0 deletions tests/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,3 +447,13 @@ async def test_create(client: LabelStudio, async_client: AsyncLabelStudio) -> No
ground_truth=True,
)
validate_response(async_response, expected_response, expected_types)


async def test_create_bulk(client: LabelStudio, async_client: AsyncLabelStudio) -> None:
expected_response: typing.Any = [{"id": 1}]
expected_types: typing.Any = ("list", {0: {"id": "integer"}})
response = client.annotations.create_bulk()
validate_response(response, expected_response, expected_types)

async_response = await async_client.annotations.create_bulk()
validate_response(async_response, expected_response, expected_types)
Loading