feat(runtime): implement single-article consolidation runtime and modularize codebase
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
"""Unit tests for ECP models, schema validation, and structured error handling."""
|
||||
|
||||
import pytest
|
||||
|
||||
from src.tools.models import (
|
||||
ClassificationError,
|
||||
ClassificationResult,
|
||||
DecisionCategory,
|
||||
ECPSnapshot,
|
||||
ErrorCode,
|
||||
)
|
||||
from src.tools.parser import extract_evidence_snippets, strip_markdown
|
||||
|
||||
|
||||
def test_ecp_snapshot_valid():
|
||||
data = {
|
||||
"target_entity_id": "ent_123",
|
||||
"target_name": "Petrobras",
|
||||
"aliases": ["Petróleo Brasileiro S.A.", "Petrobras"],
|
||||
"domain": "Oil & Gas",
|
||||
"anchors": ["pré-sal", "refinaria", "combustíveis"],
|
||||
"negative_anchors": ["petrobras posto pirata"],
|
||||
"graph_version": "1.0.0",
|
||||
"related_entities": [
|
||||
{
|
||||
"entity_id": "ent_456",
|
||||
"name": "Transpetro",
|
||||
"relation_type": "SUBSIDIARY_OF",
|
||||
"weight": 0.9,
|
||||
"aliases": ["Transpetro Logística"],
|
||||
"scope": "logistics",
|
||||
"confidence": 0.95,
|
||||
}
|
||||
],
|
||||
}
|
||||
snapshot = ECPSnapshot.from_dict(data)
|
||||
assert snapshot.target_entity_id == "ent_123"
|
||||
assert snapshot.target_name == "Petrobras"
|
||||
assert len(snapshot.aliases) == 2
|
||||
assert len(snapshot.related_entities) == 1
|
||||
assert snapshot.related_entities[0].name == "Transpetro"
|
||||
assert snapshot.related_entities[0].weight == 0.9
|
||||
|
||||
|
||||
def test_ecp_snapshot_defaults():
|
||||
data = {
|
||||
"target_entity_id": "ent_123",
|
||||
"target_name": "Petrobras",
|
||||
"aliases": ["Petrobras"],
|
||||
"domain": "Oil & Gas",
|
||||
"anchors": ["energia"],
|
||||
}
|
||||
snapshot = ECPSnapshot.from_dict(data)
|
||||
assert snapshot.negative_anchors == []
|
||||
assert snapshot.graph_version == "1.0.0"
|
||||
assert snapshot.related_entities == []
|
||||
|
||||
|
||||
def test_ecp_snapshot_missing_required():
|
||||
data = {
|
||||
"target_entity_id": "ent_123",
|
||||
"aliases": ["Petrobras"],
|
||||
"domain": "Oil & Gas",
|
||||
"anchors": ["energia"],
|
||||
}
|
||||
with pytest.raises(ValueError, match="Missing required field"):
|
||||
ECPSnapshot.from_dict(data)
|
||||
|
||||
|
||||
def test_classification_result_serialization():
|
||||
res = ClassificationResult(
|
||||
decision=DecisionCategory.DIRECT_INHERENT,
|
||||
is_inherent=True,
|
||||
confidence=0.95,
|
||||
detected_language="pt",
|
||||
matched_anchors=["Petrobras"],
|
||||
evidence=["Petrobras anunciou investimentos no pré-sal."],
|
||||
rationale="Match forte da entidade alvo.",
|
||||
)
|
||||
d = res.to_dict()
|
||||
assert d["decision"] == "DIRECT_INHERENT"
|
||||
assert d["is_inherent"] is True
|
||||
assert d["confidence"] == 0.95
|
||||
assert d["detected_language"] == "pt"
|
||||
assert "Petrobras" in d["matched_anchors"]
|
||||
|
||||
|
||||
def test_classification_error_serialization():
|
||||
err = ClassificationError(
|
||||
error_code=ErrorCode.INVALID_ECP_JSON,
|
||||
message="Malformed JSON syntax",
|
||||
details={"path": "snapshot.json"},
|
||||
)
|
||||
d = err.to_dict()
|
||||
assert d["error_code"] == "invalid_ecp_json"
|
||||
assert d["message"] == "Malformed JSON syntax"
|
||||
assert d["details"]["path"] == "snapshot.json"
|
||||
|
||||
|
||||
def test_parser_strip_markdown():
|
||||
md = "# Title\n\nThis is **bold** text and [link](https://example.com).\n- item 1\n- item 2"
|
||||
plain = strip_markdown(md)
|
||||
assert "Title" in plain
|
||||
assert "bold text" in plain
|
||||
assert "link" in plain
|
||||
assert "[" not in plain
|
||||
assert "*" not in plain
|
||||
|
||||
|
||||
def test_extract_evidence_snippets():
|
||||
md = "O pré-sal brasileiro é uma das maiores reservas de petróleo. A Petrobras lidera a exploração técnica."
|
||||
snippets = extract_evidence_snippets(md, ["Petrobras"])
|
||||
assert len(snippets) > 0
|
||||
assert "Petrobras lidera" in snippets[0]
|
||||
Reference in New Issue
Block a user