|
|
| import json
|
|
|
| def run_agent_safely(agent, max_retries=3, return_string=False, **kwargs):
|
| """
|
| Безопасно запускает агента с повторными попытками при ошибках.
|
|
|
| Args:
|
| agent: Экземпляр агента smolagents
|
| max_retries: Максимальное количество попыток
|
| return_string: Если True, возвращает строку вместо парсинга JSON
|
| **kwargs: Аргументы для передачи агенту
|
|
|
| Returns:
|
| dict или str: Распарсенный JSON ответ или строка (в зависимости от return_string)
|
| """
|
| last_error = None
|
|
|
| for attempt in range(1, max_retries + 1):
|
| try:
|
| result = agent.run(**kwargs)
|
|
|
|
|
|
|
| raw = None
|
|
|
|
|
|
|
| if hasattr(result, 'to_string'):
|
| raw = result.to_string()
|
| elif hasattr(result, 'text'):
|
| raw = result.text
|
| elif hasattr(result, '__getitem__'):
|
|
|
| try:
|
| if 'answer' in result:
|
| raw = result['answer']
|
| except:
|
| pass
|
| elif isinstance(result, dict):
|
|
|
| if "answer" in result:
|
| raw = result["answer"]
|
| elif "content" in result:
|
| raw = result["content"]
|
| elif "text" in result:
|
| raw = result["text"]
|
| elif "response" in result:
|
| raw = result["response"]
|
| else:
|
|
|
| raw = json.dumps(result, ensure_ascii=False)
|
| elif isinstance(result, str):
|
| raw = result
|
| else:
|
|
|
| raw = str(result)
|
|
|
| if not isinstance(raw, str):
|
| raise ValueError(f"Agent output is not a string, got {type(raw)}")
|
|
|
|
|
| raw = raw.strip()
|
|
|
|
|
|
|
| if raw.startswith('{"') and '"answer"' in raw:
|
| try:
|
|
|
| outer_json = json.loads(raw)
|
| if isinstance(outer_json, dict) and "answer" in outer_json:
|
| raw = outer_json["answer"]
|
| except json.JSONDecodeError:
|
|
|
|
|
| pass
|
|
|
|
|
| if return_string:
|
| return raw
|
|
|
|
|
|
|
| if raw.startswith('{') and not raw.rstrip().endswith('}'):
|
|
|
| last_brace = raw.rfind('}')
|
| if last_brace > len(raw) * 0.8:
|
| raw = raw[:last_brace + 1]
|
|
|
|
|
| try:
|
| return json.loads(raw)
|
| except json.JSONDecodeError as e:
|
|
|
|
|
| start_idx = raw.find('{')
|
| end_idx = raw.rfind('}')
|
| if start_idx >= 0 and end_idx > start_idx:
|
| json_part = raw[start_idx:end_idx + 1]
|
| try:
|
| return json.loads(json_part)
|
| except:
|
| pass
|
|
|
|
|
| if not raw.startswith('{') and not raw.startswith('['):
|
| raise ValueError(f"Expected JSON but got plain text (first 200 chars): {raw[:200]}")
|
| raise ValueError(f"JSON decode error: {e}. Raw (first 500 chars): {raw[:500]}")
|
|
|
| except Exception as e:
|
| last_error = e
|
| print(f"[{agent.name}] Attempt {attempt}/{max_retries} failed: {e}")
|
|
|
| raise ValueError(
|
| f"[{agent.name}] Failed after {max_retries} attempts.\nLast error: {last_error}"
|
| )
|
|
|