Source code for agentscope.formatter._formatter_base

# -*- coding: utf-8 -*-
"""The formatter module."""

from abc import abstractmethod
from typing import Any, List

from .._utils._common import _save_base64_data
from ..message import Msg, AudioBlock, ImageBlock, TextBlock


[docs] class FormatterBase: """The base class for formatters."""
[docs] @abstractmethod async def format(self, *args: Any, **kwargs: Any) -> list[dict[str, Any]]: """Format the Msg objects to a list of dictionaries that satisfy the API requirements."""
[docs] @staticmethod def assert_list_of_msgs(msgs: list[Msg]) -> None: """Assert that the input is a list of Msg objects. Args: msgs (`list[Msg]`): A list of Msg objects to be validated. """ if not isinstance(msgs, list): raise TypeError("Input must be a list of Msg objects.") for msg in msgs: if not isinstance(msg, Msg): raise TypeError( f"Expected Msg object, got {type(msg)} instead.", )
[docs] @staticmethod def convert_tool_result_to_string( output: List[TextBlock | ImageBlock | AudioBlock], ) -> str: """Turn the tool result list into a textual output to be compatible with the LLM API that doesn't support multimodal data. Args: output (`List[TextBlock | ImageBlock | AudioBlock]`): The output of the tool response, including text and multimodal data like images and audio. Returns: `str`: A string representation of the tool result, with text blocks concatenated and multimodal data represented by file paths or URLs. """ textual_output = [] for block in output: assert isinstance(block, dict) and "type" in block, ( f"Invalid block: {block}, a TextBlock, ImageBlock, or " f"AudioBlock is expected." ) if block["type"] == "text": textual_output.append(block["text"]) elif block["type"] in ["image", "audio", "video"]: assert "source" in block, ( f"Invalid {block['type']} block: {block}, 'source' key " "is required." ) source = block["source"] # Save the image locally and return the file path if source["type"] == "url": textual_output.append( f"The returned {block['type']} can be found " f"at: {source['url']}", ) elif source["type"] == "base64": path_temp_file = _save_base64_data( source["media_type"], source["data"], ) textual_output.append( f"The returned {block['type']} can be found " f"at: {path_temp_file}", ) else: raise ValueError( f"Invalid image source: {block['source']}, " "expected 'url' or 'base64'.", ) else: raise ValueError( f"Unsupported block type: {block['type']}, " "expected 'text', 'image', 'audio', or 'video'.", ) if len(textual_output) == 1: return textual_output[0] else: return "\n".join("- " + _ for _ in textual_output)