diff --git a/examples/xml_output_example.py b/examples/xml_output_example.py new file mode 100644 index 00000000..cdadb17e --- /dev/null +++ b/examples/xml_output_example.py @@ -0,0 +1,43 @@ +from swarms.structs.agent import Agent +import xml.etree.ElementTree as ET + +""" +User-Facing Example: How to get XML output from a Swarms agent +------------------------------------------------------------- +This example demonstrates how to use the Swarms agent framework to generate output in XML format. +You can use this pattern in your own projects to get structured, machine-readable results from any agent. +""" + +if __name__ == "__main__": + # Step 1: Create your agent and specify output_type="xml" + agent = Agent( + agent_name="XML-Output-Agent", + agent_description="Agent that demonstrates XML output support", + max_loops=2, + model_name="gpt-4o-mini", + dynamic_temperature_enabled=True, + interactive=False, + output_type="xml", # Request XML output + ) + + # Step 2: Ask your question or give a task + task = "Summarize the latest trends in AI research." + xml_out = agent.run(task) + + # Step 3: Print the XML output for inspection or downstream use + print("\n===== XML Output from Agent =====\n") + print(xml_out) + + # Step 4: (Optional) Parse the XML output for programmatic use + try: + root = ET.fromstring(xml_out) + print("\nParsed XML Root Tag:", root.tag) + print("Number of top-level children:", len(root)) + # Print the first child tag and text for demonstration + if len(root): + print("First child tag:", root[0].tag) + print("First child text:", root[0].text) + except ET.ParseError as e: + print(f"Failed to parse XML: {e}") + +# You can copy and adapt this example for your own agent workflows! diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py index a38691b2..2dece63b 100644 --- a/swarms/structs/agent.py +++ b/swarms/structs/agent.py @@ -201,7 +201,7 @@ class Agent: limit_tokens_from_string (Callable): The function to limit tokens from a string custom_tools_prompt (Callable): The custom tools prompt tool_schema (ToolUsageType): The tool schema - output_type (agent_output_type): The output type + output_type (agent_output_type): The output type. Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'. function_calling_type (str): The function calling type output_cleaner (Callable): The output cleaner function function_calling_format_type (str): The function calling format type @@ -998,7 +998,7 @@ class Agent: Returns: Any: The output of the agent. - (string, list, json, dict, yaml) + (string, list, json, dict, yaml, xml) Examples: agent(task="What is the capital of France?") @@ -1220,6 +1220,7 @@ class Agent: if self.autosave: self.save() + # Output formatting based on output_type return history_output_formatter( self.short_memory, type=self.output_type ) diff --git a/swarms/structs/output_types.py b/swarms/structs/output_types.py index 5deab2cd..ca1376a6 100644 --- a/swarms/structs/output_types.py +++ b/swarms/structs/output_types.py @@ -3,4 +3,4 @@ from swarms.utils.history_output_formatter import ( ) # Use the OutputType for type annotations -output_type: OutputType +output_type: OutputType # OutputType now includes 'xml' diff --git a/swarms/structs/swarm_router.py b/swarms/structs/swarm_router.py index 6371775f..f73cf7a8 100644 --- a/swarms/structs/swarm_router.py +++ b/swarms/structs/swarm_router.py @@ -121,7 +121,7 @@ class SwarmRouter: shared_memory_system (Any, optional): Shared memory system for agents. Defaults to None. rules (str, optional): Rules to inject into every agent. Defaults to None. documents (List[str], optional): List of document file paths to use. Defaults to empty list. - output_type (str, optional): Output format type. Defaults to "string". + output_type (str, optional): Output format type. Defaults to "string". Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'. Attributes: name (str): Name identifier for the SwarmRouter instance @@ -136,7 +136,7 @@ class SwarmRouter: shared_memory_system (Any): Shared memory system for agents rules (str): Rules injected into every agent documents (List[str]): List of document file paths - output_type (str): Output format type + output_type (str): Output format type. Supported: 'str', 'string', 'list', 'json', 'dict', 'yaml', 'xml'. logs (List[SwarmLog]): List of execution logs swarm: The instantiated swarm object diff --git a/swarms/utils/history_output_formatter.py b/swarms/utils/history_output_formatter.py index 784437ed..2ba42d33 100644 --- a/swarms/utils/history_output_formatter.py +++ b/swarms/utils/history_output_formatter.py @@ -1,7 +1,7 @@ import yaml from swarms.structs.conversation import Conversation - from typing import Literal, Union, List, Dict, Any +from swarms.utils.xml_utils import to_xml_string HistoryOutputType = Literal[ "list", @@ -14,14 +14,12 @@ HistoryOutputType = Literal[ "json", "all", "yaml", + "xml", # "dict-final", "dict-all-except-first", "str-all-except-first", ] -output_type: HistoryOutputType - - def history_output_formatter( conversation: Conversation, type: HistoryOutputType = "list" ) -> Union[List[Dict[str, Any]], Dict[str, Any], str]: @@ -39,11 +37,12 @@ def history_output_formatter( return conversation.get_str() elif type == "yaml": return yaml.safe_dump(conversation.to_dict(), sort_keys=False) - # elif type == "dict-final": - # return conversation.to_dict() elif type == "dict-all-except-first": return conversation.return_all_except_first() elif type == "str-all-except-first": return conversation.return_all_except_first_string() + elif type == "xml": + data = conversation.to_dict() + return to_xml_string(data, root_tag="conversation") else: raise ValueError(f"Invalid type: {type}") diff --git a/swarms/utils/xml_utils.py b/swarms/utils/xml_utils.py new file mode 100644 index 00000000..1e310f51 --- /dev/null +++ b/swarms/utils/xml_utils.py @@ -0,0 +1,40 @@ +import xml.etree.ElementTree as ET +from typing import Any + +def dict_to_xml(tag: str, d: dict) -> ET.Element: + """Convert a dictionary to an XML Element.""" + elem = ET.Element(tag) + for key, val in d.items(): + child = ET.Element(str(key)) + if isinstance(val, dict): + child.append(dict_to_xml(str(key), val)) + elif isinstance(val, list): + for item in val: + if isinstance(item, dict): + child.append(dict_to_xml(str(key), item)) + else: + item_elem = ET.Element("item") + item_elem.text = str(item) + child.append(item_elem) + else: + child.text = str(val) + elem.append(child) + return elem + +def to_xml_string(data: Any, root_tag: str = "root") -> str: + """Convert a dict or list to an XML string.""" + if isinstance(data, dict): + elem = dict_to_xml(root_tag, data) + elif isinstance(data, list): + elem = ET.Element(root_tag) + for item in data: + if isinstance(item, dict): + elem.append(dict_to_xml("item", item)) + else: + item_elem = ET.Element("item") + item_elem.text = str(item) + elem.append(item_elem) + else: + elem = ET.Element(root_tag) + elem.text = str(data) + return ET.tostring(elem, encoding="unicode")