Skip to content

Commit defa668

Browse files
github-actions[bot]github-actionsAurelien LombardFannyGaudinbaptiste-olivier
authored
chore: merge release/2.162.2 into main (#1817)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Aurelien Lombard <aurelien.lombard@kili-technology.com> Co-authored-by: @fanny.gaudin <fanny.gaudin@kili-technology.com> Co-authored-by: @baptiste33 <baptiste@kili-technology.com>
1 parent 51a231b commit defa668

14 files changed

Lines changed: 243 additions & 57 deletions

File tree

.github/workflows/publish.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,10 @@ jobs:
5050
exit 1
5151
fi
5252
53-
- name: Publish to test PyPI
54-
uses: pypa/gh-action-pypi-publish@release/v1.10
55-
with:
56-
repository-url: https://test.pypi.org/legacy/
57-
5853
- name: Publish to PyPI
5954
uses: pypa/gh-action-pypi-publish@release/v1.10
55+
with:
56+
verbose: true
6057

6158
- name: Slack notification
6259
id: slack

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
33

44
[project]
55
name = "kili"
6-
version = "2.162.1"
6+
version = "2.162.2"
77
description = "Python client for Kili Technology labeling tool"
88
readme = "README.md"
99
authors = [{ name = "Kili Technology", email = "contact@kili-technology.com" }]

src/kili/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Kili Python SDK."""
22

3-
__version__ = "2.162.1"
3+
__version__ = "2.162.2"

src/kili/adapters/kili_api_gateway/project/mappers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def project_data_mapper(data: ProjectDataKiliAPIGatewayInput) -> Dict:
5050
"numberOfRemainingAssets": data.number_of_remaining_assets,
5151
"numberOfReviewedAssets": data.number_of_reviewed_assets,
5252
"reviewCoverage": data.review_coverage,
53+
"secondsToLabelBeforeAutoAssign": data.seconds_to_label_before_auto_assign,
5354
"shouldRelaunchKpiComputation": data.should_relaunch_kpi_computation,
5455
"title": data.title,
5556
"useHoneyPot": data.use_honeypot,

src/kili/adapters/kili_api_gateway/project/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ProjectDataKiliAPIGatewayInput:
3232
number_of_remaining_assets: Optional[int]
3333
number_of_reviewed_assets: Optional[int]
3434
review_coverage: Optional[int]
35+
seconds_to_label_before_auto_assign: Optional[int]
3536
should_relaunch_kpi_computation: Optional[bool]
3637
title: Optional[str]
3738
use_honeypot: Optional[bool]

src/kili/llm/presentation/client/llm.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
)
1212

1313
from kili.adapters.kili_api_gateway.kili_api_gateway import KiliAPIGateway
14-
from kili.domain.asset import AssetExternalId, AssetFilters, AssetId
14+
from kili.domain.asset import AssetExternalId, AssetFilters, AssetId, AssetStatus
1515
from kili.domain.label import LabelType
1616
from kili.domain.llm import (
1717
AzureOpenAICredentials,
@@ -47,6 +47,7 @@ def export(
4747
external_ids: Optional[List[str]] = None,
4848
include_sent_back_labels: Optional[bool] = False,
4949
label_type_in: Optional[List[LabelType]] = None,
50+
status_in: Optional[List[AssetStatus]] = None,
5051
) -> Optional[List[Dict[str, Union[List[str], str]]]]:
5152
# pylint: disable=line-too-long
5253
"""Returns an export of llm assets with valid labels.
@@ -58,6 +59,8 @@ def export(
5859
external_ids: Optional list of the assets external IDs from which to export the labels.
5960
include_sent_back_labels: Include sent back labels if True.
6061
label_type_in: Optional types of label to fetch, by default ["DEFAULT", "REVIEW"].
62+
status_in: Returned assets should have a status that belongs to that list, if given.
63+
Possible choices: `TODO`, `ONGOING`, `LABELED`, `TO_REVIEW` or `REVIEWED`.
6164
!!! Example
6265
```python
6366
kili.llm.export("your_project_id")
@@ -83,6 +86,7 @@ def export(
8386
project_id=ProjectId(project_id),
8487
asset_id_in=resolved_asset_ids,
8588
label_type_in=label_type_in,
89+
status_in=status_in,
8690
)
8791

8892
try:

src/kili/llm/services/export/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ def export( # pylint: disable=too-many-arguments, too-many-locals
7878
input_type = project["inputType"]
7979

8080
fields = get_fields_to_fetch(input_type)
81-
asset_filter.status_in = ["LABELED", "REVIEWED", "TO_REVIEW", "ONGOING"]
8281
assets = list(
8382
kili_api_gateway.list_assets(asset_filter, fields, QueryOptions(disable_tqdm=disable_tqdm))
8483
)

src/kili/llm/services/export/dynamic.py

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
CHAT_ITEMS_NEEDED_FIELDS = [
99
"id",
1010
"content",
11-
"createdAt",
1211
"modelId",
1312
"parentId",
1413
"role",
@@ -123,42 +122,76 @@ def _init_round(self, context):
123122

124123
def _build_rounds(self, chat_items, annotations, json_interface):
125124
"""A round is composed of a prompt with n pre-prompts and n completions."""
126-
ordered_chat_items = sorted(chat_items, key=lambda x: x["createdAt"])
125+
dict_chat_items = {}
126+
for chat_item in chat_items:
127+
if dict_chat_items.get(chat_item["parentId"]) is None:
128+
dict_chat_items[chat_item["parentId"]] = []
129+
dict_chat_items[chat_item["parentId"]].append(chat_item)
127130
rounds = []
131+
parent_target = None
132+
has_children = True
128133
current_round = self._init_round([])
129-
for chat_item in ordered_chat_items:
130-
role = chat_item["role"].lower() if chat_item["role"] else None
131-
if role == "user" or role == "system":
132-
if current_round["prompt"] is not None:
133-
rounds.append(current_round)
134-
new_context = (
135-
current_round["context"]
136-
+ current_round["pre_prompts"]
137-
+ [
138-
current_round["prompt"],
139-
self._get_round_winner(
140-
current_round["completion"],
141-
current_round["annotations"],
142-
json_interface,
143-
),
144-
]
145-
)
146-
current_round = self._init_round(new_context)
147-
148-
if role == "user":
149-
current_round["prompt"] = chat_item
150-
elif role == "system":
151-
current_round["pre_prompts"].append(chat_item)
152-
elif role == "assistant":
153-
current_round["completion"].append(chat_item)
154-
else:
155-
raise ValueError(f"Role {chat_item['role']} not supported")
156-
current_round["annotations"] += [
157-
annotation
158-
for annotation in annotations
159-
if annotation["chatItemId"] == chat_item["id"]
160-
]
161-
rounds.append(current_round)
134+
135+
while has_children:
136+
nodes = dict_chat_items.get(parent_target)
137+
if nodes is None or len(nodes) == 0:
138+
has_children = False
139+
continue
140+
node = nodes[0]
141+
if node["role"].lower() == "system":
142+
current_round["pre_prompts"].append(node)
143+
parent_target = node["id"]
144+
current_round["annotations"] += [
145+
annotation
146+
for annotation in annotations
147+
if annotation["chatItemId"] == node["id"]
148+
]
149+
continue
150+
151+
if node["role"].lower() == "user":
152+
current_round["prompt"] = node
153+
parent_target = node["id"]
154+
current_round["annotations"] += [
155+
annotation
156+
for annotation in annotations
157+
if annotation["chatItemId"] == node["id"]
158+
]
159+
continue
160+
161+
if node["role"].lower() == "assistant":
162+
has_children = False
163+
if dict_chat_items.get(parent_target) is None:
164+
continue
165+
for chat_item in dict_chat_items[parent_target]:
166+
current_round["completion"].append(chat_item)
167+
current_round["annotations"] += [
168+
annotation
169+
for annotation in annotations
170+
if annotation["chatItemId"] == chat_item["id"]
171+
]
172+
if not has_children and dict_chat_items.get(chat_item["id"]) is not None:
173+
has_children = True
174+
parent_target = chat_item["id"]
175+
176+
rounds.append(current_round)
177+
new_context = (
178+
current_round["context"]
179+
+ current_round["pre_prompts"]
180+
+ [
181+
current_round["prompt"],
182+
self._get_round_winner(
183+
current_round["completion"],
184+
current_round["annotations"],
185+
json_interface,
186+
),
187+
]
188+
)
189+
current_round = self._init_round(new_context)
190+
continue
191+
192+
raise ValueError(f"Role {node['role']} not supported")
193+
if current_round["prompt"] is not None:
194+
rounds.append(current_round)
162195
return rounds
163196

164197

src/kili/presentation/client/project.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ def update_properties_in_project(
304304
title: Optional[str] = None,
305305
use_honeypot: Optional[bool] = None,
306306
metadata_types: Optional[dict] = None,
307+
seconds_to_label_before_auto_assign: Optional[int] = None,
307308
) -> Dict[str, Any]:
308309
"""Update properties of a project.
309310
@@ -340,6 +341,9 @@ def update_properties_in_project(
340341
metadata_types: Types of the project metadata.
341342
Should be a `dict` of metadata fields name as keys and metadata types as values.
342343
Currently, possible types are: `string`, `number`
344+
seconds_to_label_before_auto_assign: When a user begins to annotate an asset,
345+
it automatically gets assigned to them.
346+
This ensures the user retains the asset until it is submitted.
343347
344348
Returns:
345349
A dict with the changed properties which indicates if the mutation was successful,
@@ -388,6 +392,7 @@ def update_properties_in_project(
388392
use_honeypot=use_honeypot,
389393
title=title,
390394
metadata_types=metadata_types,
395+
seconds_to_label_before_auto_assign=seconds_to_label_before_auto_assign,
391396
)
392397

393398
@typechecked

src/kili/services/copy_project/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ class ProjectCopier: # pylint: disable=too-few-public-methods
3333
)
3434
FIELDS_JSON_INTERFACE = ("jsonInterface",)
3535
FIELDS_QUALITY_SETTINGS = (
36+
"canSkipAsset",
3637
"consensusTotCoverage",
3738
"minConsensusSize",
38-
"useHoneyPot",
3939
"reviewCoverage",
40+
"secondsToLabelBeforeAutoAssign",
41+
"useHoneyPot",
4042
)
4143

4244
def __init__(self, kili: "Kili") -> None:
@@ -156,10 +158,12 @@ def _copy_members(self, from_project_id: str, new_project_id: str) -> None:
156158
def _copy_quality_settings(self, new_project_id: str, src_project: Dict) -> None:
157159
self.kili.update_properties_in_project(
158160
project_id=new_project_id,
161+
can_skip_asset=src_project["canSkipAsset"],
159162
consensus_tot_coverage=src_project["consensusTotCoverage"],
160163
min_consensus_size=src_project["minConsensusSize"],
161164
use_honeypot=src_project["useHoneyPot"],
162165
review_coverage=src_project["reviewCoverage"],
166+
seconds_to_label_before_auto_assign=src_project["secondsToLabelBeforeAutoAssign"],
163167
)
164168

165169
def _copy_assets(self, from_project_id: str, new_project_id: str) -> None:

0 commit comments

Comments
 (0)