fix timeout for svg and css LLM call (#2662)

Co-authored-by: lawyzheng <lawyzheng1106@gmail.com>
This commit is contained in:
Shuchang Zheng
2025-06-10 00:23:15 -07:00
committed by GitHub
parent 4d397e73b7
commit 09ca00e948
2 changed files with 26 additions and 7 deletions

View File

@@ -26,6 +26,7 @@ from skyvern.webeye.utils.page import SkyvernFrame
LOG = structlog.get_logger() LOG = structlog.get_logger()
_LLM_CALL_TIMEOUT_SECONDS = 60 # 1m
USELESS_SHAPE_ATTRIBUTE = [SKYVERN_ID_ATTR, "id", "aria-describedby"] USELESS_SHAPE_ATTRIBUTE = [SKYVERN_ID_ATTR, "id", "aria-describedby"]
SVG_SHAPE_CONVERTION_ATTEMPTS = 3 SVG_SHAPE_CONVERTION_ATTEMPTS = 3
CSS_SHAPE_CONVERTION_ATTEMPTS = 1 CSS_SHAPE_CONVERTION_ATTEMPTS = 1
@@ -212,9 +213,10 @@ async def _convert_svg_to_string(
for retry in range(SVG_SHAPE_CONVERTION_ATTEMPTS): for retry in range(SVG_SHAPE_CONVERTION_ATTEMPTS):
try: try:
json_response = await app.SECONDARY_LLM_API_HANDLER( async with asyncio.Timeout(_LLM_CALL_TIMEOUT_SECONDS):
prompt=svg_convert_prompt, step=step, prompt_name="svg-convert" json_response = await app.SECONDARY_LLM_API_HANDLER(
) prompt=svg_convert_prompt, step=step, prompt_name="svg-convert"
)
svg_shape = json_response.get("shape", "") svg_shape = json_response.get("shape", "")
recognized = json_response.get("recognized", False) recognized = json_response.get("recognized", False)
if not svg_shape or not recognized: if not svg_shape or not recognized:
@@ -236,6 +238,13 @@ async def _convert_svg_to_string(
# set the invalid css shape to cache to avoid retry in the near future # set the invalid css shape to cache to avoid retry in the near future
await app.CACHE.set(svg_key, INVALID_SHAPE, ex=timedelta(hours=1)) await app.CACHE.set(svg_key, INVALID_SHAPE, ex=timedelta(hours=1))
await asyncio.sleep(3) await asyncio.sleep(3)
except asyncio.TimeoutError:
LOG.warning(
"Timeout to call LLM to parse SVG. Going to stop retrying",
element_id=element_id,
key=svg_key,
)
break
except Exception: except Exception:
LOG.info( LOG.info(
"Failed to convert SVG to string shape by secondary llm. Will retry if haven't met the max try attempt after 3s.", "Failed to convert SVG to string shape by secondary llm. Will retry if haven't met the max try attempt after 3s.",
@@ -358,9 +367,10 @@ async def _convert_css_shape_to_string(
# TODO: we don't retry the css shape conversion today # TODO: we don't retry the css shape conversion today
for retry in range(CSS_SHAPE_CONVERTION_ATTEMPTS): for retry in range(CSS_SHAPE_CONVERTION_ATTEMPTS):
try: try:
json_response = await app.SECONDARY_LLM_API_HANDLER( async with asyncio.Timeout(_LLM_CALL_TIMEOUT_SECONDS):
prompt=prompt, screenshots=[screenshot], step=step, prompt_name="css-shape-convert" json_response = await app.SECONDARY_LLM_API_HANDLER(
) prompt=prompt, screenshots=[screenshot], step=step, prompt_name="css-shape-convert"
)
css_shape = json_response.get("shape", "") css_shape = json_response.get("shape", "")
recognized = json_response.get("recognized", False) recognized = json_response.get("recognized", False)
if not css_shape or not recognized: if not css_shape or not recognized:
@@ -382,6 +392,13 @@ async def _convert_css_shape_to_string(
# set the invalid css shape to cache to avoid retry in the near future # set the invalid css shape to cache to avoid retry in the near future
await app.CACHE.set(shape_key, INVALID_SHAPE, ex=timedelta(hours=1)) await app.CACHE.set(shape_key, INVALID_SHAPE, ex=timedelta(hours=1))
await asyncio.sleep(3) await asyncio.sleep(3)
except asyncio.TimeoutError:
LOG.warning(
"Timeout to call LLM to parse css shape. Going to stop retrying",
element_id=element_id,
key=shape_key,
)
break
except Exception: except Exception:
LOG.info( LOG.info(
"Failed to convert css shape to string shape by secondary llm. Will retry if haven't met the max try attempt after 3s.", "Failed to convert css shape to string shape by secondary llm. Will retry if haven't met the max try attempt after 3s.",

View File

@@ -145,7 +145,9 @@ class LLMAPIHandlerFactory:
ai_suggestion=ai_suggestion, ai_suggestion=ai_suggestion,
) )
try: try:
response = await router.acompletion(model=main_model_group, messages=messages, **parameters) response = await router.acompletion(
model=main_model_group, messages=messages, timeout=settings.LLM_CONFIG_TIMEOUT, **parameters
)
except litellm.exceptions.APIError as e: except litellm.exceptions.APIError as e:
raise LLMProviderErrorRetryableTask(local_llm_key) from e raise LLMProviderErrorRetryableTask(local_llm_key) from e
except litellm.exceptions.ContextWindowExceededError as e: except litellm.exceptions.ContextWindowExceededError as e: