Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions qwen_agent/llm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,18 @@ def retry_model_service(
fn,
max_retries: int = 10,
) -> Any:
"""Retry a function"""
"""Retry a function call with exponential backoff on ModelServiceError.

Args:
fn: The function to retry.
max_retries: Maximum number of retry attempts (default: 10).

Returns:
The result of the function call.

Raises:
ModelServiceError: If all retry attempts fail.
"""

num_retries, delay = 0, 1.0
while True:
Expand All @@ -823,7 +834,18 @@ def retry_model_service_iterator(
it_fn,
max_retries: int = 10,
) -> Iterator:
"""Retry an iterator"""
"""Retry an iterator with exponential backoff on ModelServiceError.

Args:
it_fn: The iterator function to retry.
max_retries: Maximum number of retry attempts (default: 10).

Yields:
The items from the iterator.

Raises:
ModelServiceError: If all retry attempts fail.
"""

num_retries, delay = 0, 1.0
while True:
Expand Down Expand Up @@ -856,11 +878,13 @@ def _raise_or_delay(
# If harmful input or output detected, let it fail
if e.code == 'DataInspectionFailed':
raise e
if 'inappropriate content' in str(e):

error_message = str(e).lower()
if 'inappropriate content' in error_message:
raise e

# Retry is meaningless if the input is too long
if 'maximum context length' in str(e):
if 'maximum context length' in error_message or 'context length' in error_message and 'exceed' in error_message:
raise e

logger.warning('ModelServiceError - ' + str(e).strip('\n'))
Expand Down
8 changes: 7 additions & 1 deletion qwen_agent/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ def setup_logger(level=None):
else:
level = logging.INFO

_logger = logging.getLogger('qwen_agent_logger')

# Avoid adding duplicate handlers if logger is already configured
if _logger.handlers:
_logger.setLevel(level)
return _logger

handler = logging.StreamHandler()
# Do not run handler.setLevel(level) so that users can change the level via logger.setLevel later
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

_logger = logging.getLogger('qwen_agent_logger')
_logger.setLevel(level)
_logger.addHandler(handler)
return _logger
Expand Down
29 changes: 28 additions & 1 deletion qwen_agent/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,20 @@ def extract_code(text: str) -> str:


def json_loads(text: str) -> dict:
"""Parse JSON text with fallback to json5 for more lenient parsing.

This function handles code blocks wrapped in triple backticks and attempts
standard JSON parsing first, then falls back to json5 for more flexible parsing.

Args:
text: The JSON text to parse.

Returns:
The parsed JSON as a dictionary.

Raises:
json.decoder.JSONDecodeError: If both json and json5 parsing fail.
"""
text = text.strip('\n')
if text.startswith('```') and text.endswith('\n```'):
text = '\n'.join(text.split('\n')[1:-1])
Expand Down Expand Up @@ -450,9 +464,22 @@ def save_audio_to_file(base_64: str, file_name: str):

def extract_text_from_message(
msg: Message,
add_upload_info: bool,
add_upload_info: bool = False,
lang: Literal['auto', 'en', 'zh'] = 'auto',
) -> str:
"""Extract text content from a message, handling both string and list content types.

Args:
msg: The message to extract text from.
add_upload_info: Whether to include upload information in the extracted text.
lang: Language for formatting ('auto', 'en', or 'zh').

Returns:
The extracted and stripped text content.

Raises:
TypeError: If msg.content is neither a string nor a list.
"""
if isinstance(msg.content, list):
text = format_as_text_message(msg, add_upload_info=add_upload_info, lang=lang).content
elif isinstance(msg.content, str):
Expand Down