mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-07 18:27:45 +02:00
[eric] browser: OSW_BROWSER_NO_LEVERS bench flag to A/B the speed levers on/off
This commit is contained in:
@@ -63,6 +63,7 @@ from backend.apps.agents.browser import browser_wait
|
||||
from backend.apps.agents.browser import browser_schema
|
||||
from backend.apps.agents.browser.browser_schema import (
|
||||
_ACTION_TOOLS_REQUIRING_REPORT,
|
||||
_LEVERS_ON,
|
||||
ACTION_MAP,
|
||||
BROWSER_TOOLS_SCHEMA,
|
||||
MAX_TURNS,
|
||||
@@ -802,7 +803,7 @@ async def run_browser_agent(
|
||||
# wording), but a similar verified route may exist; hand it to the model as
|
||||
# advisory text so it follows a known path instead of re-exploring.
|
||||
route_hint_keys: list[tuple] = []
|
||||
if not replay_prefix_note:
|
||||
if _LEVERS_ON and not replay_prefix_note:
|
||||
_h_skill, _h_score = browser_skills.find_similar_skill(replay_host, skill_key_task)
|
||||
if _h_skill:
|
||||
_hint, route_hint_keys = browser_skills.render_route_hint(_h_skill, skill_key_task, _h_score)
|
||||
@@ -816,7 +817,7 @@ async def run_browser_agent(
|
||||
# Pre-nav landed on a results page (the cold entry case): scan it NOW so the
|
||||
# model's very first turn can pick a candidate instead of read-then-decide.
|
||||
_start_url = (current_url or initial_url or "").split("#")[0]
|
||||
if _start_url and _RESULTS_URL_RE.search(_start_url):
|
||||
if _LEVERS_ON and _start_url and _RESULTS_URL_RE.search(_start_url):
|
||||
auto_scanned_urls.add(_start_url)
|
||||
_scan_json, _sc_ms = await _scan_results(task)
|
||||
if _scan_json:
|
||||
@@ -1442,7 +1443,7 @@ async def run_browser_agent(
|
||||
# per URL, only on the tight throwaway-dismiss vocabulary that
|
||||
# never sits on a task-needed control, so it can't close anything
|
||||
# required. After closing, re-list so the model sees the page beneath.
|
||||
if tu.name in _AUTO_STATE_TOOLS and "error" not in result:
|
||||
if _LEVERS_ON and tu.name in _AUTO_STATE_TOOLS and "error" not in result:
|
||||
_pop_url = (result.get("url") or last_seen_url or "").split("#")[0]
|
||||
if _pop_url and _pop_url not in dismissed_popup_urls:
|
||||
_close = interstitial_dismiss_target("\n".join(attached_state_seen))
|
||||
@@ -1464,7 +1465,7 @@ async def run_browser_agent(
|
||||
# costs a read-then-decide turn pair; the cheap aux model reads it
|
||||
# now so the pick happens on this same turn. Capped, per-URL,
|
||||
# fail-silent (a miss just means the old two-turn dance).
|
||||
if (tu.name in _AUTO_STATE_TOOLS and "error" not in result
|
||||
if (_LEVERS_ON and tu.name in _AUTO_STATE_TOOLS and "error" not in result
|
||||
and auto_scan_count < _AUTO_SCAN_MAX_PER_RUN):
|
||||
_scan_url = (result.get("url") or last_seen_url or "").split("#")[0]
|
||||
if _scan_url and _scan_url not in auto_scanned_urls and _RESULTS_URL_RE.search(_scan_url):
|
||||
@@ -1513,7 +1514,7 @@ async def run_browser_agent(
|
||||
if replay_prefix_note:
|
||||
result["text"] = f"{result.get('text') or ''}{replay_prefix_note}"
|
||||
replay_prefix_note = ""
|
||||
elif not route_hint_keys:
|
||||
elif _LEVERS_ON and not route_hint_keys:
|
||||
_h_skill, _h_score = browser_skills.find_similar_skill(cur_host, skill_key_task)
|
||||
if _h_skill:
|
||||
_hint, route_hint_keys = browser_skills.render_route_hint(_h_skill, skill_key_task, _h_score)
|
||||
|
||||
@@ -6,6 +6,30 @@ prompt, and the turn/report invariants. Exceeds the 300-LOC soft ceiling on
|
||||
purpose because it is one cohesive data blob, not multiple responsibilities.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# Bench-only A/B switch: OSW_BROWSER_NO_LEVERS=1 reverts the prompt to its
|
||||
# pre-speed-lever behavior (narration allowed beside actions, no merge-verify
|
||||
# shortcut) so a controlled run can measure whether the levers move the needle.
|
||||
# Default (unset) = levers ON, the shipped behavior.
|
||||
_LEVERS_ON = os.environ.get("OSW_BROWSER_NO_LEVERS", "") not in ("1", "true", "TRUE")
|
||||
|
||||
_THINK_SHORTER = (
|
||||
"Do NOT also write a free-text sentence next to your action tools: your ReportProgress "
|
||||
"fields ARE your thinking, and a separate prose explanation just repeats them and slows "
|
||||
"the turn (it is shown to the user twice). The ONLY time to write a plain message is your "
|
||||
"FINAL turn, when the task is done and you call no action tool: that message is your "
|
||||
"answer to the user (the OUTCOME line). Every other turn: ReportProgress + tools, no prose.\n"
|
||||
) if _LEVERS_ON else ""
|
||||
|
||||
_MERGE_VERIFY = (
|
||||
"When that `expect` CONFIRMS (the result says 'Confirmed: ...'), that IS your "
|
||||
"verification: go STRAIGHT to your final OUTCOME line and cite it. Do NOT spend an "
|
||||
"extra screenshot or read turn to re-check what the confirmation already proved, that "
|
||||
"is a wasted round-trip. Only take a separate verification step when `expect` came "
|
||||
"back 'NOT confirmed' or you forgot to pass one.\n"
|
||||
) if _LEVERS_ON else ""
|
||||
|
||||
MODEL_MAP = {
|
||||
"sonnet": "claude-sonnet-4-6",
|
||||
"opus": "claude-opus-4-6",
|
||||
@@ -621,11 +645,7 @@ SYSTEM_PROMPT = (
|
||||
"needs (the exact selector, index, or value). Each token you write is generated one at a "
|
||||
"time and is the main thing that slows a turn, so write the fewest that still carry the "
|
||||
"plan forward. Only write working_memory when you learn something NEW this turn; else 'none'.\n"
|
||||
"Do NOT also write a free-text sentence next to your action tools: your ReportProgress "
|
||||
"fields ARE your thinking, and a separate prose explanation just repeats them and slows "
|
||||
"the turn (it is shown to the user twice). The ONLY time to write a plain message is your "
|
||||
"FINAL turn, when the task is done and you call no action tool: that message is your "
|
||||
"answer to the user (the OUTCOME line). Every other turn: ReportProgress + tools, no prose.\n"
|
||||
+ _THINK_SHORTER +
|
||||
"Emit ReportProgress and your action tool(s) together in the same response. "
|
||||
"If you skip ReportProgress, your action tools will be REJECTED with an error "
|
||||
"and you will have to retry. This is not optional. Read-only tools "
|
||||
@@ -642,11 +662,7 @@ SYSTEM_PROMPT = (
|
||||
"last one in the thread), pass `expect` set to proof it landed, and NEVER fire it a "
|
||||
"second time unless you have verified the first did NOT go through. This is how you "
|
||||
"avoid both ghost-successes and double-sends.\n"
|
||||
"When that `expect` CONFIRMS (the result says 'Confirmed: ...'), that IS your "
|
||||
"verification: go STRAIGHT to your final OUTCOME line and cite it. Do NOT spend an "
|
||||
"extra screenshot or read turn to re-check what the confirmation already proved, that "
|
||||
"is a wasted round-trip. Only take a separate verification step when `expect` came "
|
||||
"back 'NOT confirmed' or you forgot to pass one.\n\n"
|
||||
+ _MERGE_VERIFY + "\n"
|
||||
|
||||
"## Loop awareness\n"
|
||||
"If you see a tool result containing 'LOOP DETECTED' or '⚠️', it means you "
|
||||
|
||||
Reference in New Issue
Block a user