brain / tests /test_architect_batch_schema.py
Leon4gr45's picture
Upload folder using huggingface_hub (part 4)
ac68ae4 verified
Raw History Blame Contribute Delete
7.16 kB
from src.core.saving.architect_batch import (
BatchEndpoint,
BatchExtractResponse,
BatchRelationship,
event_leg_incomplete,
validate_batch_extract,
)
def _entity(uuid: str, name: str, type_: str):
return type("E", (), {"uuid": uuid, "name": name, "type": type_})()
def test_validate_accepts_grounded_event_hub():
source = "Alice hired Bob as a contractor in May 2024 for $5000."
entities = [
_entity("u1", "Alice", "PERSON"),
_entity("u2", "Hiring", "EVENT"),
_entity("u3", "Bob", "PERSON"),
]
payload = BatchExtractResponse(
relationships=[
BatchRelationship(
tail=BatchEndpoint(uuid="u1", name="Alice", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Hiring", type="EVENT"),
name="MADE",
description="Alice hired Bob",
amount=5000,
source_span="Alice hired Bob as a contractor",
happened_at="2024-05",
),
BatchRelationship(
tail=BatchEndpoint(uuid="u2", name="Hiring", type="EVENT"),
tip=BatchEndpoint(uuid="u3", name="Bob", type="PERSON"),
name="TARGETED",
description="Alice hired Bob",
amount=5000,
source_span="Alice hired Bob as a contractor in May 2024",
),
]
)
result = validate_batch_extract(
payload, source_text=source, scout_entities=entities
)
assert len(result.accepted) == 2
assert result.rejected == []
assert not event_leg_incomplete(result.accepted, entities)
def test_validate_rejects_type_named_and_ungrounded():
source = "Alice met Bob at the park."
entities = [
_entity("u1", "Alice", "PERSON"),
_entity("u2", "Bob", "PERSON"),
]
payload = BatchExtractResponse(
relationships=[
BatchRelationship(
tail=BatchEndpoint(uuid="u1", name="PERSON", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Bob", type="PERSON"),
name="MET",
source_span="Alice met Bob",
),
BatchRelationship(
tail=BatchEndpoint(uuid="u1", name="Alice", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Bob", type="PERSON"),
name="MET",
source_span="totally fabricated zebra claim",
),
BatchRelationship(
# well-formed unknown endpoint is soft-admitted (no escalate)
tail=BatchEndpoint(uuid="missing", name="Carol", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Bob", type="PERSON"),
name="MET",
source_span="Alice met Bob at the park",
),
]
)
result = validate_batch_extract(
payload, source_text=source, scout_entities=entities
)
reasons = {issue.reason for issue in result.rejected}
assert "type_named_placeholder_endpoint" in reasons
assert "source_span_not_grounded" in reasons
assert "unknown_tail_endpoint" not in reasons
assert len(result.accepted) == 1
assert result.accepted[0].tail.name == "Carol"
assert any(n.name == "Carol" for n in result.new_nodes)
def test_validate_admits_unknown_well_formed_endpoints():
source = "Alice introduced Carol to Bob at the park."
entities = [
_entity("u1", "Alice", "PERSON"),
_entity("u2", "Bob", "PERSON"),
]
payload = BatchExtractResponse(
relationships=[
BatchRelationship(
tail=BatchEndpoint(name="Carol", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Bob", type="PERSON"),
name="MET",
source_span="Alice introduced Carol to Bob at the park",
),
]
)
result = validate_batch_extract(
payload, source_text=source, scout_entities=entities
)
assert result.usable
assert len(result.accepted) == 1
assert result.rejected == []
def test_validate_span_offsets_and_scout_uuid_reuse():
source = "On Tuesday Alice paid Bob 12 dollars."
entities = [_entity("a", "Alice", "PERSON"), _entity("b", "Bob", "PERSON")]
span = "Alice paid Bob 12 dollars"
start = source.index(span)
payload = {
"new_nodes": [],
"relationships": [
{
"tail": {"uuid": "a", "name": "Alice", "type": "PERSON"},
"tip": {"uuid": "b", "name": "Bob", "type": "PERSON"},
"name": "PAID",
"amount": 12,
"source_span": span,
"span_start": start,
"span_end": start + len(span),
}
],
}
result = validate_batch_extract(
payload, source_text=source, scout_entities=entities
)
assert len(result.accepted) == 1
assert result.accepted[0].amount == 12
def test_event_leg_incomplete_detects_untouched_event():
entities = [
_entity("e1", "Trip", "EVENT"),
_entity("p1", "Alice", "PERSON"),
]
rels = [
BatchRelationship(
tail=BatchEndpoint(uuid="p1", name="Alice", type="PERSON"),
tip=BatchEndpoint(uuid="p1", name="Alice", type="PERSON"),
name="SELF",
source_span="Alice",
)
]
assert event_leg_incomplete(rels, entities)
def test_validate_partial_keeps_usable_and_drops_bad_new_nodes():
source = "Alice hired Bob as a contractor in May 2024."
entities = [
_entity("u1", "Alice", "PERSON"),
_entity("u2", "Hiring", "EVENT"),
_entity("u3", "Bob", "PERSON"),
]
payload = BatchExtractResponse(
new_nodes=[
BatchEndpoint(name="PERSON", type="PERSON"),
BatchEndpoint(name="Contract", type="DOCUMENT"),
],
relationships=[
BatchRelationship(
tail=BatchEndpoint(uuid="u1", name="Alice", type="PERSON"),
tip=BatchEndpoint(uuid="u2", name="Hiring", type="EVENT"),
name="MADE",
source_span="Alice hired Bob as a contractor",
),
BatchRelationship(
tail=BatchEndpoint(uuid="u2", name="Hiring", type="EVENT"),
tip=BatchEndpoint(uuid="missing", name="Carol", type="PERSON"),
name="TARGETED",
source_span="Alice hired Bob as a contractor in May 2024",
),
],
)
result = validate_batch_extract(
payload, source_text=source, scout_entities=entities
)
assert result.usable
assert not result.ok
assert len(result.accepted) == 2
assert {r.name for r in result.accepted} == {"MADE", "TARGETED"}
assert len(result.new_nodes) >= 2
assert any(n.name == "Contract" for n in result.new_nodes)
assert any(n.name == "Carol" for n in result.new_nodes)
reasons = {issue.reason for issue in result.rejected}
assert "unknown_tip_endpoint" not in reasons
assert any(r.startswith("new_node_type_named_placeholder:") for r in reasons)