Spaces:
Sleeping
Sleeping
| import json | |
| import pytest | |
| from scripts.train_place_intent_bert import ( | |
| IGNORED_LABEL_ID, | |
| LABEL_TO_ID, | |
| IntentTrainingExample, | |
| LabeledSpan, | |
| align_spans_to_token_offsets, | |
| build_parser, | |
| encode_examples, | |
| read_jsonl, | |
| validate_training_example, | |
| ) | |
| def test_validate_training_example_preserves_raw_values_and_normalizes_slots() -> None: | |
| text = "Quiero donas artesanales sin ruido cerca de Parque Mexico" | |
| payload = { | |
| "text": text, | |
| "spans": [ | |
| { | |
| "start": text.index("donas"), | |
| "end": text.index("artesanales") + len("artesanales"), | |
| "slot": "category", | |
| }, | |
| { | |
| "start": text.index("ruido"), | |
| "end": text.index("ruido") + len("ruido"), | |
| "label": "EXCLUSION", | |
| }, | |
| { | |
| "start": text.index("Parque"), | |
| "end": len(text), | |
| "slot": "LOCATION", | |
| }, | |
| ], | |
| } | |
| example = validate_training_example(payload, context="line 1") | |
| assert example.text == text | |
| assert [span.slot for span in example.spans] == [ | |
| "CATEGORY", | |
| "EXCLUSION", | |
| "LOCATION", | |
| ] | |
| assert [text[span.start : span.end] for span in example.spans] == [ | |
| "donas artesanales", | |
| "ruido", | |
| "Parque Mexico", | |
| ] | |
| def test_validate_training_example_rejects_invalid_annotations( | |
| payload: object, | |
| error: str, | |
| ) -> None: | |
| with pytest.raises(ValueError, match=error): | |
| validate_training_example(payload) | |
| def test_alignment_assigns_iob_to_subwords_and_ignores_special_tokens() -> None: | |
| text = "Quiero donas sin ruido" | |
| spans = ( | |
| LabeledSpan(start=7, end=12, slot="CATEGORY"), | |
| LabeledSpan(start=17, end=22, slot="EXCLUSION"), | |
| ) | |
| offsets = ( | |
| (0, 0), | |
| (0, 6), | |
| (7, 9), | |
| (9, 12), | |
| (13, 16), | |
| (17, 22), | |
| (0, 0), | |
| ) | |
| labels = align_spans_to_token_offsets(text, spans, offsets) | |
| assert labels == [ | |
| IGNORED_LABEL_ID, | |
| LABEL_TO_ID["O"], | |
| LABEL_TO_ID["B-CATEGORY"], | |
| LABEL_TO_ID["I-CATEGORY"], | |
| LABEL_TO_ID["O"], | |
| LABEL_TO_ID["B-EXCLUSION"], | |
| IGNORED_LABEL_ID, | |
| ] | |
| def test_alignment_rejects_annotations_lost_by_truncation() -> None: | |
| text = "donas cerca del parque" | |
| spans = (LabeledSpan(start=16, end=22, slot="LOCATION"),) | |
| with pytest.raises(ValueError, match="possibly truncated.*LOCATION"): | |
| align_spans_to_token_offsets( | |
| text, | |
| spans, | |
| [(0, 0), (0, 5), (6, 11), (0, 0)], | |
| ) | |
| class FakeFastTokenizer: | |
| is_fast = True | |
| def __init__(self) -> None: | |
| self.calls: list[dict[str, object]] = [] | |
| def __call__(self, text: str, **kwargs: object) -> dict[str, object]: | |
| self.calls.append({"text": text, **kwargs}) | |
| return { | |
| "input_ids": [101, 1001, 102], | |
| "attention_mask": [1, 1, 1], | |
| "offset_mapping": [(0, 0), (0, len(text)), (0, 0)], | |
| } | |
| def test_encode_examples_works_with_an_injected_tokenizer() -> None: | |
| tokenizer = FakeFastTokenizer() | |
| examples = [ | |
| IntentTrainingExample( | |
| text="cafecito", | |
| spans=(LabeledSpan(start=0, end=8, slot="CATEGORY"),), | |
| ) | |
| ] | |
| encoded = encode_examples(examples, tokenizer, max_length=32) | |
| assert encoded == [ | |
| { | |
| "input_ids": [101, 1001, 102], | |
| "attention_mask": [1, 1, 1], | |
| "labels": [ | |
| IGNORED_LABEL_ID, | |
| LABEL_TO_ID["B-CATEGORY"], | |
| IGNORED_LABEL_ID, | |
| ], | |
| } | |
| ] | |
| assert tokenizer.calls == [ | |
| { | |
| "text": "cafecito", | |
| "truncation": True, | |
| "max_length": 32, | |
| "return_offsets_mapping": True, | |
| } | |
| ] | |
| def test_read_jsonl_reports_the_failing_line(tmp_path) -> None: | |
| dataset = tmp_path / "train.jsonl" | |
| dataset.write_text( | |
| json.dumps({"text": "donas", "spans": []}) | |
| + "\n" | |
| + "{invalid-json}\n", | |
| encoding="utf-8", | |
| ) | |
| with pytest.raises(ValueError, match=r"train\.jsonl, line 2: invalid JSON"): | |
| read_jsonl(dataset) | |
| def test_help_is_built_without_importing_optional_ml_dependencies() -> None: | |
| help_text = build_parser().format_help() | |
| assert "--train-file" in help_text | |
| assert "--validation-file" in help_text | |
| assert "--base-model" in help_text | |
| assert "--learning-rate" in help_text | |