Skip to content

Commit d2e4e57

Browse files
author
Sentience Dev
committed
support for reranker
1 parent 5a58daf commit d2e4e57

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

sentience/models.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Pydantic models for Sentience SDK - matches spec/snapshot.schema.json
33
"""
44

5-
from typing import Literal
5+
from typing import Literal, Optional
66

77
from pydantic import BaseModel, Field
88

@@ -44,6 +44,12 @@ class Element(BaseModel):
4444
is_occluded: bool = False
4545
z_index: int = 0
4646

47+
# ML reranking metadata (optional - can be absent or null)
48+
rerank_index: Optional[int] = None # 0-based, The rank after ML reranking
49+
heuristic_index: Optional[int] = None # 0-based, Where it would have been without ML
50+
ml_probability: Optional[float] = None # Confidence score from ONNX model (0.0 - 1.0)
51+
ml_score: Optional[float] = None # Raw logit score (optional, for debugging)
52+
4753

4854
class Snapshot(BaseModel):
4955
"""Snapshot response from extension"""

tests/test_snapshot.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,65 @@ def test_snapshot_with_goal():
134134
]
135135
for el in snap.elements
136136
)
137+
138+
139+
def test_element_ml_fields_optional():
140+
"""Test that Element model accepts optional ML reranking fields"""
141+
from sentience.models import Element, BBox, VisualCues
142+
143+
# Test element without ML fields
144+
element_without_ml = Element(
145+
id=1,
146+
role="button",
147+
text="Click me",
148+
importance=100,
149+
bbox=BBox(x=10, y=20, width=100, height=50),
150+
visual_cues=VisualCues(is_primary=True, background_color_name="blue", is_clickable=True),
151+
in_viewport=True,
152+
is_occluded=False,
153+
z_index=0,
154+
)
155+
assert element_without_ml.rerank_index is None
156+
assert element_without_ml.heuristic_index is None
157+
assert element_without_ml.ml_probability is None
158+
assert element_without_ml.ml_score is None
159+
160+
# Test element with ML fields
161+
element_with_ml = Element(
162+
id=2,
163+
role="link",
164+
text="Learn more",
165+
importance=80,
166+
bbox=BBox(x=15, y=25, width=120, height=40),
167+
visual_cues=VisualCues(is_primary=False, background_color_name="white", is_clickable=True),
168+
in_viewport=True,
169+
is_occluded=False,
170+
z_index=1,
171+
rerank_index=0,
172+
heuristic_index=5,
173+
ml_probability=0.95,
174+
ml_score=2.34,
175+
)
176+
assert element_with_ml.rerank_index == 0
177+
assert element_with_ml.heuristic_index == 5
178+
assert element_with_ml.ml_probability == 0.95
179+
assert element_with_ml.ml_score == 2.34
180+
181+
# Test element with partial ML fields
182+
element_partial = Element(
183+
id=3,
184+
role="textbox",
185+
text=None,
186+
importance=60,
187+
bbox=BBox(x=20, y=30, width=200, height=30),
188+
visual_cues=VisualCues(is_primary=False, background_color_name=None, is_clickable=True),
189+
in_viewport=True,
190+
is_occluded=False,
191+
z_index=0,
192+
rerank_index=1,
193+
ml_probability=0.87,
194+
)
195+
assert element_partial.rerank_index == 1
196+
assert element_partial.heuristic_index is None
197+
assert element_partial.ml_probability == 0.87
198+
assert element_partial.ml_score is None

0 commit comments

Comments
 (0)