frimeet-api-nlp / tests /test_train_place_intent_bert.py
AlleksDev's picture
Add: Bert
baaa888 unverified
Raw
History Blame Contribute Delete
5.38 kB
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",
]
@pytest.mark.parametrize(
("payload", "error"),
[
({"text": "donas", "spans": "CATEGORY"}, "spans must be a list"),
(
{
"text": "donas",
"spans": [{"start": -1, "end": 5, "slot": "CATEGORY"}],
},
"offsets must satisfy",
),
(
{
"text": "donas",
"spans": [{"start": 0, "end": 5, "slot": "RESTAURANT"}],
},
"unsupported slot",
),
(
{
"text": "donas ricas",
"spans": [
{"start": 0, "end": 7, "slot": "CATEGORY"},
{"start": 6, "end": 11, "slot": "PREFERENCE"},
],
},
"overlapping spans",
),
],
)
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