Skip to content

Commit 9b6f85b

Browse files
committed
Add ambiguous element detection to element finder
- Add ambiguous field to ElementMatch so LLM can flag when multiple elements match equally well (e.g. multiple Like buttons in a feed) - Raise ElementNotFoundError with all candidates and positions when ambiguous - Include full element details in error for index=-1 path - Update element_matcher prompt to teach LLM about ambiguous flag
1 parent d0161d1 commit 9b6f85b

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

connectonion/useful_tools/browser_tools/element_finder.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class ElementMatch(BaseModel):
7777
"""LLM's element selection result."""
7878
index: int = Field(..., description="Index of the matching element, or -1 if no match found")
7979
confidence: float = Field(..., description="Confidence 0-1")
80+
ambiguous: bool = Field(default=False, description="True if multiple elements match equally well and you cannot confidently pick one (e.g. multiple Like buttons in a feed)")
8081
reasoning: str = Field(..., description="Why this element matches, or why no match was found")
8182
alternatives: Optional[List[int]] = Field(default=None, description="List of alternative element indices that might match (if no exact match)")
8283

@@ -195,7 +196,25 @@ def find_element(
195196
)
196197

197198
if result.index == -1:
198-
raise ElementNotFoundError(f"{result.reasoning}\nSuggested alternatives: {result.alternatives}")
199+
alt_str = ""
200+
if result.alternatives:
201+
alt_str = "\nSuggested alternatives:\n" + "\n".join(
202+
f" [{elements[i].index}] {elements[i].tag} text='{elements[i].text}' aria='{elements[i].aria_label}' pos=({elements[i].x},{elements[i].y})"
203+
for i in result.alternatives if 0 <= i < len(elements)
204+
)
205+
raise ElementNotFoundError(f"{result.reasoning}{alt_str}")
206+
207+
if result.ambiguous and result.alternatives:
208+
candidates = [result.index] + result.alternatives
209+
candidates_str = "\n".join(
210+
f" [{elements[i].index}] {elements[i].tag} text='{elements[i].text}' aria='{elements[i].aria_label}' pos=({elements[i].x},{elements[i].y})"
211+
for i in candidates if 0 <= i < len(elements)
212+
)
213+
raise ElementNotFoundError(
214+
f"Ambiguous: multiple elements match '{description}'.\n"
215+
f"Candidates:\n{candidates_str}\n"
216+
f"Be more specific — include author name, position, or a unique attribute."
217+
)
199218

200219
if 0 <= result.index < len(elements):
201220
selected = elements[result.index]

connectonion/useful_tools/browser_tools/prompts/element_matcher.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,10 @@ Consider:
9898
- In reasoning, explain why no match was found
9999
- In alternatives, provide a list of 3-5 element indices that are the closest matches (most similar or most likely what the user meant)
100100

101+
**IMPORTANT: If MULTIPLE elements match equally well (e.g. multiple "Like" buttons in a feed, multiple "Submit" buttons):**
102+
- Set ambiguous=true
103+
- Set index to the best guess
104+
- In alternatives, list ALL matching element indices
105+
- In reasoning, explain why you can't confidently pick one
106+
101107
Return the index of the best matching element, or -1 if no match found.

0 commit comments

Comments
 (0)