fix(agent): 跨上游超时窗调参——主调用单次超时330s→180s(实测最长响应<60s留3倍余量,失败快速返回);会话级重试2→3次+退避15s(3×180+2×15≈9.5分钟跨度可跨分钟级超时窗);llm_call_msgs_native补timeout参数透传_http_chat;回退文本路径同接180s
This commit is contained in:
parent
458736d71e
commit
0964dd2864
@ -108,6 +108,15 @@ class AgentExecutor:
|
||||
_CONTINUE_GATE_MIN_CHARS = 400
|
||||
_CONTINUE_GATE_MAX = 2
|
||||
|
||||
# 主调用单次超时(2026-09-11):端点缺省 330s 太长——上游超时窗内一次失败
|
||||
# 要烧 330s×3 重试。实测最长成功响应 3212 token <60s,180s 留 3 倍余量足够,
|
||||
# 失败快速返回交给会话级重试跨越窗口。
|
||||
_MAIN_TIMEOUT = 180
|
||||
# 会话级重试次数(含首次共 3 次尝试)+ 退避秒数:上游超时窗实测分钟级、
|
||||
# 间歇出现;3 次尝试 × 180s + 2×15s 退避 ≈ 9.5 分钟跨度,可跨越多数窗口。
|
||||
_MAIN_ATTEMPTS = 3
|
||||
_MAIN_RETRY_BACKOFF = 15
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config, # AgentConfig (from pipeline_core)
|
||||
@ -332,7 +341,7 @@ class AgentExecutor:
|
||||
# 重试前向用户透出进度,避免"卡死"观感。
|
||||
resp = None
|
||||
_last_err = None
|
||||
for _attempt in range(2):
|
||||
for _attempt in range(self._MAIN_ATTEMPTS):
|
||||
try:
|
||||
resp = await self._call_llm()
|
||||
break
|
||||
@ -341,14 +350,14 @@ class AgentExecutor:
|
||||
_transient = any(k in type(e).__name__ or k in str(e)
|
||||
for k in ("Timeout", "ClientError", "ServerDisconnected",
|
||||
"ConnectionReset"))
|
||||
if not _transient or _attempt >= 1:
|
||||
if not _transient or _attempt >= self._MAIN_ATTEMPTS - 1:
|
||||
break
|
||||
logger.warning(f"run: LLM 瞬时失败 turn={turn+1} 重试: {e}")
|
||||
logger.warning(f"run: LLM 瞬时失败 turn={turn+1} 重试{_attempt+1}: {e}")
|
||||
yield json.dumps({
|
||||
"type": "progress",
|
||||
"message": "模型上游瞬时超时,正在重试…\n",
|
||||
}, ensure_ascii=False) + "\n"
|
||||
await asyncio.sleep(3)
|
||||
await asyncio.sleep(self._MAIN_RETRY_BACKOFF)
|
||||
if resp is None:
|
||||
logger.error(f"run: LLM 调用失败 turn={turn+1}: {_last_err}")
|
||||
yield json.dumps({"type": "error", "message": str(_last_err)}, ensure_ascii=False) + "\n"
|
||||
@ -868,6 +877,7 @@ class AgentExecutor:
|
||||
temperature=self.config.temperature,
|
||||
org_id=self.org_id,
|
||||
session_id=self.session_id,
|
||||
timeout=self._MAIN_TIMEOUT,
|
||||
)
|
||||
except Exception as e:
|
||||
# 原生视觉降级(2026-09-10):模型不支持多模态 content 数组时
|
||||
@ -893,13 +903,14 @@ class AgentExecutor:
|
||||
temperature=self.config.temperature,
|
||||
org_id=self.org_id,
|
||||
session_id=self.session_id,
|
||||
timeout=self._MAIN_TIMEOUT,
|
||||
)
|
||||
except Exception as e:
|
||||
if self._degrade_images_if_needed(e):
|
||||
content = await llm_call_msgs(
|
||||
self._msgs, model=self.model_name,
|
||||
temperature=self.config.temperature, org_id=self.org_id,
|
||||
session_id=self.session_id)
|
||||
session_id=self.session_id, timeout=self._MAIN_TIMEOUT)
|
||||
else:
|
||||
raise
|
||||
return {"content": content or "", "tool_calls": []}
|
||||
|
||||
@ -194,7 +194,8 @@ async def llm_call_msgs(messages: list, model: str = None, temperature: float =
|
||||
async def llm_call_msgs_native(messages: list, tools: list = None, model: str = None,
|
||||
temperature: float = 0.7, org_id: str = None,
|
||||
user_id: str = None, purpose: str = '',
|
||||
project_id: str = '', session_id: str = '') -> dict:
|
||||
project_id: str = '', session_id: str = '',
|
||||
timeout: int = 0) -> dict:
|
||||
"""Native function calling. 传入 tools JSON schema,返回 message dict。
|
||||
|
||||
Returns:
|
||||
@ -212,7 +213,7 @@ async def llm_call_msgs_native(messages: list, tools: list = None, model: str =
|
||||
if session_id:
|
||||
payload["_session_id"] = session_id
|
||||
data = await _http_chat(payload, org_id or '0', user_id or '', model or '',
|
||||
project_id=project_id or '')
|
||||
timeout=timeout, project_id=project_id or '')
|
||||
try:
|
||||
msg = data["choices"][0]["message"]
|
||||
except (KeyError, IndexError, TypeError) as e:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user