Skip to content

Commit 55c5a07

Browse files
Fix webhook payload structure handling for project_id extraction and … (#877)
1 parent 5fa2c2a commit 55c5a07

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

label_studio_ml/examples/huggingface_ner/model.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,18 @@ def fit(self, event, data, **kwargs):
143143
logger.info(f"Skip training: event {event} is not supported")
144144
return
145145

146-
project_id = data['annotation']['project']
146+
# Get project from annotation first if present, otherwise fall back to top-level project field
147+
project = data.get('annotation', {}).get('project') or data.get('project')
148+
# Handle both possible formats
149+
if isinstance(project, dict):
150+
project_id = project.get('id')
151+
else:
152+
project_id = project
153+
# If project_id is still None, log and safely exit
154+
if project_id is None:
155+
logger.error(f"Cannot find project_id in webhook payload: {data}")
156+
return
157+
147158
tasks = self._get_tasks(project_id)
148159

149160
if len(tasks) % self.START_TRAINING_EACH_N_UPDATES != 0 and event != 'START_TRAINING':

label_studio_ml/examples/huggingface_ner/test_api.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,33 @@ def test_fit(client, mock_get_labeled_tasks, mock_start_training, mock_baseline_
200200
# remove './results/finetuned_model' directory after testing
201201
import shutil
202202
shutil.rmtree(results_dir)
203+
204+
def test_fit_missing_annotation(monkeypatch):
205+
# Initialize the model
206+
model = HuggingFaceNER()
207+
208+
# Mock label_interface to avoid AttributeError
209+
model.label_interface = mock.MagicMock()
210+
# Mock get_first_tag_occurence to return fake values
211+
model.label_interface.get_first_tag_occurence.return_value = ('Labels', 'Text', 'text_field_name')
212+
213+
# Mock data payload with annotation missing, only project present
214+
payload = {
215+
"action": "ANNOTATION_UPDATED",
216+
"project": {"id": 123, "name": "Test Project"}
217+
}
218+
219+
# Monkeypatch _get_tasks to return one fake task
220+
monkeypatch.setattr(model, "_get_tasks", lambda project_id: [
221+
{
222+
"id": "1",
223+
"data": {"text_field_name": "Hello world"},
224+
"annotations": []
225+
}
226+
])
227+
228+
# Call fit()
229+
try:
230+
model.fit(event="ANNOTATION_UPDATED", data=payload)
231+
except Exception as e:
232+
pytest.fail(f"fit() raised an exception when annotation is missing: {e}")

0 commit comments

Comments
 (0)