"""Locating things with the brain: the question it is asked, and how its answer is read. Shared by the service (vLLM) and the transformers model (in-process), so a box found by one is the box the other finds. """ from __future__ import annotations import json import re from typing import Any try: # the interfaze_lite package, and the HF repo as trust_remote_code imports it from .contracts import _bounds_from_dict, iou, to_bounds except ImportError: # the files run flat, from a checkout from contracts import _bounds_from_dict, iou, to_bounds # type: ignore # A photo's box list is a few hundred tokens; 8192 only gave a degenerate reply room to run (233 boxes). MAX_TOKENS = 1536 # "All buttons" lists every one at ~33 tokens each: 1536 stopped after 46, in the menu bar. interfaze # allows 8192 on this model; a looping reply is cut down, not returned. MAX_TOKENS_UI = 8192 # interfaze's GUI instruction word for word (object-detection-truss, dev_qwen38_gui_main.py), same model. # Asking for each element's visible text instead boxed every piece of text and missed the buy box. UI_INSTRUCTION = ( "Locate every {phrase} in this UI screenshot.\n" "Respond with ONLY a JSON array and nothing else. Each element must be " '{{"bbox_2d": [x1, y1, x2, y2], "label": ""}}.\n' "Coordinates are normalized to a 0-1000 grid, where (0,0) is the top-left corner " "and (1000,1000) is the bottom-right corner, regardless of the image's pixel size.\n" "Return every distinct match, not just the best one. " "If the screenshot contains no such element, respond with exactly []." ) def max_tokens(domain: str) -> int: return MAX_TOKENS_UI if domain == "ui" else MAX_TOKENS _OBJECT = re.compile(r'\{[^{}]*?"bbox_2d"\s*:\s*\[[^\]]*\][^{}]*?\}', re.S) def prompt(prompts: list[str], domain: str = "ui") -> str: """The grounding question for `prompts` in a screenshot ("ui") or a photograph. The wording matters: asked for elements "in this UI screenshot", a photograph often returns []. """ phrase = ", ".join(prompts) if domain == "ui": return UI_INSTRUCTION.format(phrase=phrase) # Ranking took RefCOCOg 77.5% -> 81.2%, but ScreenSpot-v2 fell to 51.2% with empty # replies 1.2% -> 18.8%, so screenshots skip it. return ( f"Locate every {phrase} in this image.\n" "Label each match with the kind of object it is.\n" "Respond with ONLY a JSON array, each element " '{"bbox_2d": [x1,y1,x2,y2], "label": "