From a9ec4586a2d04ceab445a3f6bcc8387bf7f1467b Mon Sep 17 00:00:00 2001 From: harshalmore31 <86048671+harshalmore31@users.noreply.github.com> Date: Sat, 28 Dec 2024 01:20:59 +0530 Subject: [PATCH] ui-v10 --- swarms/structs/ui/agent_prompts.json | 33 +- swarms/structs/ui/ui.py | 942 +++++++++++++++++++-------- 2 files changed, 672 insertions(+), 303 deletions(-) diff --git a/swarms/structs/ui/agent_prompts.json b/swarms/structs/ui/agent_prompts.json index 75f57e29..0a3bd3cc 100644 --- a/swarms/structs/ui/agent_prompts.json +++ b/swarms/structs/ui/agent_prompts.json @@ -1,47 +1,50 @@ { - "Agent_Data_Extractor": { + "Agent-Data_Extractor": { "system_prompt": "You are a data extraction agent. Your primary role is to retrieve and organize relevant data from diverse sources accurately and efficiently. You specialize in parsing structured and unstructured data, ensuring its integrity and usability for analysis or reporting." }, - "Agent_Summarizer": { + "Agent-Summarizer": { "system_prompt": "You are a summarization agent. Your main function is to condense large volumes of information into concise, clear, and meaningful summaries. You ensure that the key points are captured without losing the essence or context of the original content." }, - "Agent_Onboarding_Agent": { + "Agent-Onboarding_Agent": { "system_prompt": "You are an onboarding agent. Your focus is to guide new users through processes, systems, or platforms seamlessly. You provide step-by-step assistance, clarify complex concepts, and ensure users feel confident and well-informed throughout the onboarding journey." }, - "Agent_Finance_Agent": { + "Agent-Finance_Agent": { "system_prompt": "You are a seasoned finance analyst AI assistant. Your primary goal is to compose comprehensive, astute, impartial, and methodically arranged financial reports based on provided data and trends." }, - "Agent_Travel_Agent": { + "Agent-Travel_Agent": { "system_prompt": "You are a world-travelled AI tour guide assistant. Your main purpose is to draft engaging, insightful, unbiased, and well-structured travel reports on given locations, including history, attractions, and cultural insights." }, - "Agent_Academic_Research_Agent": { + "Agent-Academic_Research_Agent": { "system_prompt": "You are an AI academic research assistant. Your primary responsibility is to create thorough, academically rigorous, unbiased, and systematically organized reports on a given research topic, following the standards of scholarly work." }, - "Agent_Default_Agent": { + "Agent-Default_Agent": { "system_prompt": "You are an AI critical thinker research assistant. Your sole purpose is to write well-written, critically acclaimed, objective and structured reports on given text." }, - "Agent_Health_Security_Agent": { + "Agent-Health_Security_Agent": { "system_prompt": "Conduct a thorough analysis of the factory's working conditions focusing on health and safety standards. Examine the cleanliness of the workspace, the adequacy of ventilation systems, the appropriate spacing between workstations, and the availability and use of personal protective equipment by workers. Evaluate the compliance of these aspects with health and safety regulations. Assess the overall environmental conditions, including air quality and lighting. Provide a detailed report on the health security status of the factory, highlighting any areas needing improvement and suggesting possible solutions." }, - "Agent_Quality_Control_Agent": { + "Agent-Quality_Control_Agent": { "system_prompt": "Scrutinize the quality of products manufactured in the factory. Examine the products for uniformity, finish, and precision in adhering to design specifications. Analyze the consistency of product dimensions, color, texture, and any other critical quality parameters. Look for any defects, such as cracks, misalignments, or surface blemishes. Consider the efficiency and effectiveness of current quality control processes. Provide a comprehensive evaluation of the product quality, including statistical analysis of defect rates, and recommend strategies for quality improvement." }, - "Agent_Productivity_Agent": { + "Agent-Productivity_Agent": { "system_prompt": "Evaluate the factory's overall productivity by analyzing workflow efficiency, machine utilization, and employee engagement. Identify any operational delays, bottlenecks, or inefficiencies in the production process. Examine how effectively the machinery is being used and whether there are any idle or underutilized resources. Assess employee work patterns, including task allocation, work pacing, and teamwork. Look for signs of overwork or underutilization of human resources. Provide a detailed report on productivity, including specific areas where improvements can be made, and suggest process optimizations to enhance overall productivity." }, - "Agent_Safety_Agent": { + "Agent-Safety_Agent": { "system_prompt": "Inspect the factory's adherence to safety standards and protocols. Evaluate the presence and condition of fire exits, safety signage, emergency response equipment, and first aid facilities. Check for clear and unobstructed access to emergency exits. Assess the visibility and clarity of safety signs and instructions. Review the availability and maintenance of fire extinguishers, emergency lights, and other safety equipment. Ensure compliance with workplace safety regulations. Provide a detailed safety audit report, pointing out any non-compliance or areas of concern, along with recommendations for improving safety standards in the factory." }, - "Agent_Security_Agent": { + "Agent-Security_Agent": { "system_prompt": "Assess the factory's security measures and systems. Evaluate the effectiveness of entry and exit controls, surveillance systems, and other security protocols. Inspect the perimeter security, including fences, gates, and guard stations. Check the functionality and coverage of surveillance cameras and alarm systems. Analyze access control measures for both personnel and vehicles. Identify potential security vulnerabilities or breaches. Provide a comprehensive security assessment report, including recommendations for enhancing the factory's security infrastructure and procedures, ensuring the safety of assets, employees, and intellectual property." }, - "Agent_Sustainability_Agent": { + "Agent-Sustainability_Agent": { "system_prompt": "Examine the factory's sustainability practices with a focus on waste management, energy usage, and implementation of eco-friendly processes. Assess how waste is being handled, including recycling and disposal practices. Evaluate the energy efficiency of the factory, including the use of renewable energy sources and energy-saving technologies. Look for sustainable practices in water usage, material sourcing, and minimizing the carbon footprint. Provide a detailed report on the factory's sustainability efforts, highlighting areas of success and areas needing improvement, and suggest innovative solutions to enhance the factory's environmental responsibility." }, - "Agent_Efficiency_Agent": { + "Agent-Efficiency_Agent": { "system_prompt": "Analyze the efficiency of the factory's manufacturing process, focusing on the layout, logistics, and level of automation. Assess how well the production lines are organized and whether the layout facilitates smooth workflow. Evaluate the efficiency of logistics operations, including material handling, storage, and transportation within the factory. Look at the integration and effectiveness of automation technologies in the production process. Identify any areas causing delays or inefficiencies. Provide an in-depth analysis of manufacturing efficiency, offering actionable insights and recommendations for optimizing the layout, logistics, and automation to improve overall operational efficiency." }, - "Agent_Hello": { + "Agent-Hello": { "system_prompt": "print(\"Hello_World\")\n\nKonichiwa" + }, + "Hello": { + "system_prompt": "Hi I love coding" } } \ No newline at end of file diff --git a/swarms/structs/ui/ui.py b/swarms/structs/ui/ui.py index 004e7f12..dcfb19b6 100644 --- a/swarms/structs/ui/ui.py +++ b/swarms/structs/ui/ui.py @@ -7,69 +7,73 @@ import asyncio import gradio as gr from swarms.structs.agent import Agent from swarms.structs.swarm_router import SwarmRouter +# from swarms.structs.rearrange import AgentRearrange from swarms.utils.loguru_logger import initialize_logger import re -import csv # Import the csv module for csv parsing +import csv # Import the csv module for csv parsing from swarms.utils.litellm_wrapper import LiteLLM from litellm import models_by_provider from dotenv import set_key, find_dotenv -# Initialize logger -logger = initialize_logger(log_folder="swarm_ui") -# Load environment variables +# Initialize logger load_dotenv() -# Get the OpenAI API key from the environment variable -api_key = os.getenv("GROQ_API_KEY") +# Initialize logger +logger = initialize_logger(log_folder="swarm_ui") # Define the path to agent_prompts.json -# locates the json file and then fetches the promopts - -PROMPT_JSON_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "agent_prompts.json") +PROMPT_JSON_PATH = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "agent_prompts.json" +) logger.info(f"Loading prompts from: {PROMPT_JSON_PATH}") +# Load prompts first so its available for create_app + def load_prompts_from_json() -> Dict[str, str]: try: if not os.path.exists(PROMPT_JSON_PATH): # Load default prompts return { - "agent.Agent_Data_Extractor": "You are a data extraction agent...", - "agent.Agent_Summarizer": "You are a summarization agent...", - "agent.Agent_Onboarding_Agent": "You are an onboarding agent..." + "Agent-Data_Extractor": "You are a data extraction agent...", + "Agent-Summarizer": "You are a summarization agent...", + "Agent-Onboarding_Agent": "You are an onboarding agent...", } - with open(PROMPT_JSON_PATH, 'r', encoding='utf-8') as f: + with open(PROMPT_JSON_PATH, "r", encoding="utf-8") as f: try: data = json.load(f) except json.JSONDecodeError: # Load default prompts return { - "agent.Agent_Data_Extractor": "You are a data extraction agent...", - "agent.Agent_Summarizer": "You are a summarization agent...", - "agent.Agent_Onboarding_Agent": "You are an onboarding agent..." + "Agent-Data_Extractor": "You are a data extraction agent...", + "Agent-Summarizer": "You are a summarization agent...", + "Agent-Onboarding_Agent": "You are an onboarding agent...", } if not isinstance(data, dict): # Load default prompts - return { - "agent.Agent_Data_Extractor": "You are a data extraction agent...", - "agent.Agent_Summarizer": "You are a summarization agent...", - "agent.Agent_Onboarding_Agent": "You are an onboarding agent..." + return { + "Agent-Data_Extractor": "You are a data extraction agent...", + "Agent-Summarizer": "You are a summarization agent...", + "Agent-Onboarding_Agent": "You are an onboarding agent...", } prompts = {} for agent_name, details in data.items(): - if not isinstance(details, dict) or "system_prompt" not in details: - continue - - prompts[f"agent.{agent_name}"] = details["system_prompt"] + if ( + not isinstance(details, dict) + or "system_prompt" not in details + ): + continue + + prompts[agent_name] = details["system_prompt"] if not prompts: - # Load default prompts + # Load default prompts return { - "agent.Agent_Data_Extractor": "You are a data extraction agent...", - "agent.Agent_Summarizer": "You are a summarization agent...", - "agent.Agent_Onboarding_Agent": "You are an onboarding agent..." + "Agent-Data_Extractor": "You are a data extraction agent...", + "Agent-Summarizer": "You are a summarization agent...", + "Agent-Onboarding_Agent": "You are an onboarding agent...", } return prompts @@ -77,15 +81,22 @@ def load_prompts_from_json() -> Dict[str, str]: except Exception: # Load default prompts return { - "agent.Agent_Data_Extractor": "You are a data extraction agent...", - "agent.Agent_Summarizer": "You are a summarization agent...", - "agent.Agent_Onboarding_Agent": "You are an onboarding agent..." + "Agent-Data_Extractor": "You are a data extraction agent...", + "Agent-Summarizer": "You are a summarization agent...", + "Agent-Onboarding_Agent": "You are an onboarding agent...", } AGENT_PROMPTS = load_prompts_from_json() -def initialize_agents(dynamic_temp: float, agent_keys: List[str], model_name: str, - provider: str, api_key: str, temperature:float, max_tokens:int) -> List[Agent]: +def initialize_agents( + dynamic_temp: float, + agent_keys: List[str], + model_name: str, + provider: str, + api_key: str, + temperature: float, + max_tokens: int, +) -> List[Agent]: agents = [] seen_names = set() for agent_key in agent_keys: @@ -93,7 +104,7 @@ def initialize_agents(dynamic_temp: float, agent_keys: List[str], model_name: st raise ValueError(f"Invalid agent key: {agent_key}") agent_prompt = AGENT_PROMPTS[agent_key] - agent_name = agent_key.split('.')[-1] + agent_name = agent_key # Ensure unique agent names base_name = agent_name @@ -107,12 +118,11 @@ def initialize_agents(dynamic_temp: float, agent_keys: List[str], model_name: st model_name=model_name, system_prompt=agent_prompt, temperature=temperature, - max_tokens = max_tokens, + max_tokens=max_tokens, ) - agent = Agent( - agent_name=f"Agent-{agent_name}", + agent_name=agent_name, system_prompt=agent_prompt, llm=llm, max_loops=1, @@ -126,17 +136,49 @@ def initialize_agents(dynamic_temp: float, agent_keys: List[str], model_name: st output_type="string", # here is the output type which is string temperature=dynamic_temp, ) + print( + f"Agent created: {agent.agent_name}" + ) # Debug: Print agent name agents.append(agent) return agents -async def execute_task(task: str, max_loops: int, dynamic_temp: float, - swarm_type: str, agent_keys: List[str], flow: str = None, model_name:str = "gpt-4o", - provider:str = "openai", api_key:str=None, temperature:float=0.5, max_tokens:int=4000) -> Tuple[Any, 'SwarmRouter', str]: +def validate_flow(flow, agents_dict): + agent_names = flow.split("->") + for agent in agent_names: + agent = agent.strip() + if agent not in agents_dict: + raise ValueError( + f"Agent '{agent}' specified in the flow does not exist." + ) + +async def execute_task( + task: str, + max_loops: int, + dynamic_temp: float, + swarm_type: str, + agent_keys: List[str], + flow: str = None, + model_name: str = "gpt-4o", + provider: str = "openai", + api_key: str = None, + temperature: float = 0.5, + max_tokens: int = 4000, + agents: dict = None, +) -> Tuple[Any, "SwarmRouter", str]: # Changed the return type here try: # Initialize agents try: - agents = initialize_agents(dynamic_temp, agent_keys, model_name, provider, api_key, temperature, max_tokens) + if not agents: + agents = initialize_agents( + dynamic_temp, + agent_keys, + model_name, + provider, + api_key, + temperature, + max_tokens, + ) except Exception as e: return None, None, str(e) @@ -145,48 +187,123 @@ async def execute_task(task: str, max_loops: int, dynamic_temp: float, "name": "multi-agent-workflow", "description": f"Executing {swarm_type} workflow", "max_loops": max_loops, - "agents": agents, + "agents": list(agents.values()), "autosave": True, "return_json": True, - "output_type": "string", + "output_type": "string", # Default output type "swarm_type": swarm_type, # Pass swarm_type here } if swarm_type == "AgentRearrange": if not flow: - return None, None, "Flow configuration is required for AgentRearrange" + return ( + None, + None, + "Flow configuration is required for AgentRearrange", + ) + + # Generate unique agent names in the flow + flow_agents = [] + used_agent_names = set() + for agent_key in flow.split("->"): + agent_key = agent_key.strip() + base_agent_name = agent_key + count = 1 + while agent_key in used_agent_names: + agent_key = f"{base_agent_name}_{count}" + count += 1 + used_agent_names.add(agent_key) + flow_agents.append(agent_key) + + # Update the flow string with unique names + flow = " -> ".join(flow_agents) + print(f"Updated Flow string: {flow}") router_kwargs["flow"] = flow + router_kwargs["output_type"] = "string" # Changed output type here + + if swarm_type == "MixtureOfAgents": if len(agents) < 2: - return None, None, "MixtureOfAgents requires at least 2 agents" - + return ( + None, + None, + "MixtureOfAgents requires at least 2 agents", + ) + if swarm_type == "SequentialWorkflow": if len(agents) < 2: - return None, None, "SequentialWorkflow requires at least 2 agents" + return ( + None, + None, + "SequentialWorkflow requires at least 2 agents", + ) + if swarm_type == "ConcurrentWorkflow": + pass + + if swarm_type == "SpreadSheetSwarm": + pass + + if swarm_type == "auto": + pass # Create and execute SwarmRouter try: - timeout = 450 if swarm_type != "SpreadSheetSwarm" else 900 # SpreadSheetSwarm will have different timeout. - router = SwarmRouter(**router_kwargs) + timeout = ( + 450 if swarm_type != "SpreadSheetSwarm" else 900 + ) # SpreadSheetSwarm will have different timeout. if swarm_type == "AgentRearrange": - result = await asyncio.wait_for( - asyncio.to_thread(router._run, task), - timeout=timeout + # result = await asyncio.wait_for( + # asyncio.to_thread(router._run, task), + # timeout=timeout + # ) + # return result, router, "" + from swarms.structs.rearrange import AgentRearrange + router = AgentRearrange( + agents=list(agents.values()), + flow=flow, + max_loops=max_loops, + name="multi-agent-workflow", + description=f"Executing {swarm_type} workflow", + # autosave=True, + return_json=True, + output_type="string", # Changed output type according to agent rearrange ) + result = router(task) # Changed run method return result, router, "" - - result = await asyncio.wait_for( - asyncio.to_thread(router.run, task), - timeout=timeout - ) - - return result, router, "" - + + # For other swarm types use the SwarmRouter and its run method + router = SwarmRouter(**router_kwargs) # Initialize SwarmRouter + if swarm_type == "ConcurrentWorkflow": + async def run_agent_task(agent, task_): + return agent.run(task_) + + tasks = [ + run_agent_task(agent, task) + for agent in list(agents.values()) + ] + responses = await asyncio.gather(*tasks) + result = {} + for agent, response in zip(list(agents.values()), responses): + result[agent.agent_name] = response + + # Convert the result to JSON string for parsing + result = json.dumps(result) + return result, router, "" + else: + result = await asyncio.wait_for( + asyncio.to_thread(router.run, task), + timeout=timeout + ) + return result, router, "" except asyncio.TimeoutError: - return None, None, f"Task execution timed out after {timeout} seconds" + return ( + None, + None, + f"Task execution timed out after {timeout} seconds", + ) except Exception as e: return None, None, str(e) @@ -200,32 +317,48 @@ def parse_agent_rearrange_output(data: Optional[str]) -> str: if data is None: return "Error: No data provided for parsing." - print(f"Raw data received for parsing:\n{data}") # Debug: Print raw data + print( + f"Raw data received for parsing:\n{data}" + ) # Debug: Print raw data try: parsed_data = json.loads(data) + errors = [] + + if ( + "input" not in parsed_data + or not isinstance(parsed_data.get("input"), dict) + ): + errors.append( + "Error: 'input' data is missing or not a dictionary." + ) + else: + if "swarm_id" not in parsed_data["input"]: + errors.append( + "Error: 'swarm_id' key is missing in the 'input'." + ) - if "input" not in parsed_data or not isinstance(parsed_data.get("input"), dict): - return "Error: 'input' data is missing or not a dictionary." - - if "swarm_id" not in parsed_data["input"] : - return "Error: 'swarm_id' key is missing in the 'input'." - - if "name" not in parsed_data["input"]: - return "Error: 'name' key is missing in the 'input'." - - if "flow" not in parsed_data["input"]: - return "Error: 'flow' key is missing in the 'input'." - - if "time" not in parsed_data : - return "Error: 'time' key is missing." + if "name" not in parsed_data["input"]: + errors.append( + "Error: 'name' key is missing in the 'input'." + ) + + if "flow" not in parsed_data["input"]: + errors.append( + "Error: 'flow' key is missing in the 'input'." + ) + + if "time" not in parsed_data: + errors.append("Error: 'time' key is missing.") + + if errors: + return "\n".join(errors) swarm_id = parsed_data["input"]["swarm_id"] swarm_name = parsed_data["input"]["name"] agent_flow = parsed_data["input"]["flow"] overall_time = parsed_data["time"] - output = f"Workflow Execution Details\n\n" output += f"Swarm ID: `{swarm_id}`\n" output += f"Swarm Name: `{swarm_name}`\n" @@ -233,29 +366,56 @@ def parse_agent_rearrange_output(data: Optional[str]) -> str: output += f"Agent Task Execution\n\n" if "outputs" not in parsed_data: - return "Error: 'outputs' key is missing" - - if parsed_data["outputs"] is None: - return "Error: 'outputs' data is None" - - if not isinstance(parsed_data["outputs"], list): - return "Error: 'outputs' data is not a list." - - for i, agent_output in enumerate(parsed_data["outputs"], start=3): + errors.append("Error: 'outputs' key is missing") + elif parsed_data["outputs"] is None: + errors.append("Error: 'outputs' data is None") + elif not isinstance(parsed_data["outputs"], list): + errors.append("Error: 'outputs' data is not a list.") + elif not parsed_data["outputs"]: + errors.append("Error: 'outputs' list is empty.") + + if errors: + return "\n".join(errors) + + for i, agent_output in enumerate( + parsed_data["outputs"], start=3 + ): if not isinstance(agent_output, dict): - return f"Error: Agent output at index {i} is not a dictionary" - + errors.append( + f"Error: Agent output at index {i} is not a" + " dictionary" + ) + continue + if "agent_name" not in agent_output: - return f"Error: 'agent_name' key is missing at index {i}" - + errors.append( + f"Error: 'agent_name' key is missing at index {i}" + ) + continue + if "steps" not in agent_output: - return f"Error: 'steps' key is missing at index {i}" - + errors.append( + f"Error: 'steps' key is missing at index {i}" + ) + continue + if agent_output["steps"] is None: - return f"Error: 'steps' data is None at index {i}" - + errors.append( + f"Error: 'steps' data is None at index {i}" + ) + continue + if not isinstance(agent_output["steps"], list): - return f"Error: 'steps' data is not a list at index {i}" + errors.append( + f"Error: 'steps' data is not a list at index {i}" + ) + continue + + if not agent_output["steps"]: + errors.append( + f"Error: 'steps' list is empty at index {i}" + ) + continue agent_name = agent_output["agent_name"] output += f"Run {(3-i)} (Agent: `{agent_name}`)**\n\n" @@ -263,31 +423,51 @@ def parse_agent_rearrange_output(data: Optional[str]) -> str: # Iterate over steps for j, step in enumerate(agent_output["steps"], start=3): - if not isinstance(step, dict): - return f"Error: step at index {j} is not a dictionary at {i} agent output." - - if step is None: - return f"Error: step at index {j} is None at {i} agent output" + if not isinstance(step, dict): + errors.append( + f"Error: step at index {j} is not a dictionary" + f" at {i} agent output." + ) + continue - if "role" not in step: - return f"Error: 'role' key missing at step {j} at {i} agent output." - - if "content" not in step: - return f"Error: 'content' key missing at step {j} at {i} agent output." - - if step["role"].strip() != "System:": # Filter out system prompts + if step is None: + errors.append( + f"Error: step at index {j} is None at {i} agent" + " output" + ) + continue + + if "role" not in step: + errors.append( + f"Error: 'role' key missing at step {j} at {i}" + " agent output." + ) + continue + + if "content" not in step: + errors.append( + f"Error: 'content' key missing at step {j} at" + f" {i} agent output." + ) + continue + + if step["role"].strip() != "System:": # Filter out system prompts # role = step["role"] - content = step["content"] - output += f"Step {(3-j)}: \n" - output += f"Response :\n {content}\n\n" + content = step["content"] + output += f"Step {(3-j)}: \n" + output += f"Response :\n {content}\n\n" # output += "\n\n---\n" output += f"Overall Completion Time: `{overall_time}`" - return output - except json.JSONDecodeError as e : - return f"Error during parsing: json.JSONDecodeError {e}" - + + if errors: + return "\n".join(errors) + else: + return output + except json.JSONDecodeError as e: + return f"Error during parsing: json.JSONDecodeError {e}" + except Exception as e: return f"Error during parsing: {str(e)}" @@ -335,7 +515,6 @@ def parse_mixture_of_agents_output(data: Optional[str]) -> str: output += f"Agent: `{agent_name}`\n" # output += f"* **System Prompt:** `{system_prompt}`\n\n" - if "normal_agent_outputs" not in parsed_data or not isinstance(parsed_data["normal_agent_outputs"], list) : return "Error: 'normal_agent_outputs' key is missing or not a list." @@ -417,7 +596,6 @@ def parse_sequential_workflow_output(data: Optional[str]) -> str: agent_flow = parsed_data["input"]["flow"] overall_time = parsed_data["time"] - output = f"Workflow Execution Details\n\n" output += f"Swarm ID: `{swarm_id}`\n" output += f"Swarm Name: `{swarm_name}`\n" @@ -484,7 +662,6 @@ def parse_sequential_workflow_output(data: Optional[str]) -> str: except Exception as e: return f"Error during parsing: {str(e)}" - def parse_spreadsheet_swarm_output(file_path: str) -> str: """Parses the SpreadSheetSwarm output CSV file and formats it for display.""" if not file_path: @@ -556,10 +733,16 @@ class UI: def create_markdown(self, text, is_header=False): if is_header: - markdown = gr.Markdown(f"
{text}
") - self.components[f'markdown_{text}'] = markdown + markdown = gr.Markdown( + f"{text}
" + ) + self.components[f"markdown_{text}"] = markdown return markdown def create_text_input(self, label, lines=3, placeholder=""): @@ -569,10 +752,12 @@ class UI: placeholder=placeholder, elem_classes=["custom-input"], ) - self.components[f'text_input_{label}'] = text_input + self.components[f"text_input_{label}"] = text_input return text_input - def create_slider(self, label, minimum=0, maximum=1, value=0.5, step=0.1): + def create_slider( + self, label, minimum=0, maximum=1, value=0.5, step=0.1 + ): slider = gr.Slider( minimum=minimum, maximum=maximum, @@ -581,10 +766,12 @@ class UI: label=label, interactive=True, ) - self.components[f'slider_{label}'] = slider + self.components[f"slider_{label}"] = slider return slider - def create_dropdown(self, label, choices, value=None, multiselect=False): + def create_dropdown( + self, label, choices, value=None, multiselect=False + ): if not choices: choices = ["No options available"] if value is None and choices: @@ -597,12 +784,12 @@ class UI: interactive=True, multiselect=multiselect, ) - self.components[f'dropdown_{label}'] = dropdown + self.components[f"dropdown_{label}"] = dropdown return dropdown def create_button(self, text, variant="primary"): button = gr.Button(text, variant=variant) - self.components[f'button_{text}'] = button + self.components[f"button_{text}"] = button return button def create_text_output(self, label, lines=10, placeholder=""): @@ -613,7 +800,7 @@ class UI: lines=lines, elem_classes=["custom-output"], ) - self.components[f'text_output_{label}'] = text_output + self.components[f"text_output_{label}"] = text_output return text_output def create_tab(self, label, content_function): @@ -634,18 +821,20 @@ class UI: value={}, elem_classes=["custom-output"], ) - self.components[f'json_output_{label}'] = json_output + self.components[f"json_output_{label}"] = json_output return json_output def build(self): return self.blocks - def create_conditional_input(self, component, visible_when, watch_component): + def create_conditional_input( + self, component, visible_when, watch_component + ): """Create an input that's only visible under certain conditions""" watch_component.change( fn=lambda x: gr.update(visible=visible_when(x)), inputs=[watch_component], - outputs=[component] + outputs=[component], ) @staticmethod @@ -668,11 +857,11 @@ class UI: """Create the agent details tab content.""" with gr.Column(): gr.Markdown("### Agent Details") - gr.Markdown(""" + gr.Markdown( + """ **Available Agent Types:** - Data Extraction Agent: Specialized in extracting relevant information - - Summary Agent: Creates concise summaries of information - - Analysis Agent: Performs detailed analysis of data + - Summary Agent - Analysis Agent: Performs detailed analysis of data **Swarm Types:** - ConcurrentWorkflow: Agents work in parallel @@ -681,7 +870,8 @@ class UI: - MixtureOfAgents: Combines multiple agents with an aggregator - SpreadSheetSwarm: Specialized for spreadsheet operations - Auto: Automatically determines optimal workflow - """) + """ + ) return gr.Column() def create_logs_tab(self): @@ -692,15 +882,30 @@ class UI: label="System Logs", placeholder="Execution logs will appear here...", interactive=False, - lines=10 + lines=10, ) return logs_display +def update_flow_agents(agent_keys): + """Update flow agents based on selected agent prompts.""" + if not agent_keys: + return [], "No agents selected" + agent_names = [key for key in agent_keys] + print(f"Flow agents: {agent_names}") # Debug: Print flow agents + return agent_names, "Select agents in execution order" + +def update_flow_preview(selected_flow_agents): + """Update flow preview based on selected agents.""" + if not selected_flow_agents: + return "Flow will be shown here..." + flow = " -> ".join(selected_flow_agents) + return flow + def create_app(): # Initialize UI theme = UI.create_ui_theme(primary_color="red") ui = UI(theme=theme) - + global AGENT_PROMPTS # Available providers and models providers = [ "openai", @@ -711,7 +916,7 @@ def create_app(): "groq", "nvidia_nim", "huggingface", - "perplexity" + "perplexity", ] filtered_models = {} @@ -719,13 +924,13 @@ def create_app(): for provider in providers: filtered_models[provider] = models_by_provider.get(provider, []) - with ui.blocks: with gr.Row(): with gr.Column(scale=4): # Left column (80% width) ui.create_markdown("Swarms", is_header=True) ui.create_markdown( - "The Enterprise-Grade Production-Ready Multi-Agent Orchestration Framework" + "The Enterprise-Grade Production-Ready Multi-Agent" + " Orchestration Framework" ) with gr.Row(): with gr.Column(scale=4): @@ -733,17 +938,18 @@ def create_app(): task_input = gr.Textbox( label="Task Description", placeholder="Describe your task here...", - lines=3 + lines=3, ) with gr.Row(): - with gr.Column(scale=1): with gr.Row(): - # Provider selection dropdown + # Provider selection dropdown provider_dropdown = gr.Dropdown( label="Select Provider", choices=providers, - value=providers[0] if providers else None, + value=providers[0] + if providers + else None, interactive=True, ) # with gr.Row(): @@ -767,9 +973,9 @@ def create_app(): minimum=0, maximum=1, value=0.1, - step=0.01 + step=0.01, ) - + # with gr.Row(): # max tokens slider max_loops_slider = gr.Slider( @@ -777,9 +983,8 @@ def create_app(): minimum=1, maximum=10, value=1, - step=1 + step=1, ) - with gr.Row(): # max tokens slider @@ -792,60 +997,85 @@ def create_app(): ) with gr.Column(scale=2, min_width=200): - with gr.Column(scale=1): - # Get available agent prompts - available_prompts = list(AGENT_PROMPTS.keys()) if AGENT_PROMPTS else ["No agents available"] - agent_prompt_selector = gr.Dropdown( - label="Select Agent Prompts", - choices=available_prompts, - value=[available_prompts[0]] if available_prompts else None, - multiselect=True, - interactive=True - ) + with gr.Column(scale=1): + # Get available agent prompts + available_prompts = ( + list(AGENT_PROMPTS.keys()) + if AGENT_PROMPTS + else ["No agents available"] + ) + agent_prompt_selector = gr.Dropdown( + label="Select Agent Prompts", + choices=available_prompts, + value=[available_prompts[0]] + if available_prompts + else None, + multiselect=True, + interactive=True, + ) # with gr.Column(scale=1): - # Get available swarm types - swarm_types = [ - "SequentialWorkflow", "ConcurrentWorkflow","AgentRearrange", - "MixtureOfAgents", "SpreadSheetSwarm", "auto" - ] - agent_selector = gr.Dropdown( - label="Select Swarm", - choices=swarm_types, - value=swarm_types[0], - multiselect=False, - interactive=True - ) + # Get available swarm types + swarm_types = [ + "SequentialWorkflow", + "ConcurrentWorkflow", + "AgentRearrange", + "MixtureOfAgents", + "SpreadSheetSwarm", + "auto", + ] + agent_selector = gr.Dropdown( + label="Select Swarm", + choices=swarm_types, + value=swarm_types[0], + multiselect=False, + interactive=True, + ) - # Flow configuration components for AgentRearrange - with gr.Column(visible=False) as flow_config: - flow_text = gr.Textbox( - label="Agent Flow Configuration", - placeholder="Enter agent flow !", - lines=2 - ) - gr.Markdown( - """ + # Flow configuration components for AgentRearrange + with gr.Column(visible=False) as flow_config: + flow_text = gr.Textbox( + label="Agent Flow Configuration", + placeholder="Enter agent flow !", + lines=2, + ) + gr.Markdown( + """ **Flow Configuration Help:** - Enter agent names separated by ' -> ' - Example: Agent1 -> Agent2 -> Agent3 - Use exact agent names from the prompts above """ - ) - # Create Agent Prompt Section - with gr.Accordion("Create Agent Prompt", open=False) as create_prompt_accordion: - with gr.Row(): - with gr.Column(): - new_agent_name_input = gr.Textbox(label="New Agent Name") - with gr.Column(): - new_agent_prompt_input = gr.Textbox(label="New Agent Prompt", lines=3) - with gr.Row(): - with gr.Column(): - create_agent_button = gr.Button("Save New Prompt") - generate_agent_button = gr.Button("Generate_Final_p") - with gr.Column(): - create_agent_status = gr.Textbox(label="Status", interactive=False) - - + ) + # Create Agent Prompt Section + with gr.Accordion( + "Create Agent Prompt", open=False + ) as create_prompt_accordion: + with gr.Row(): + with gr.Column(): + new_agent_name_input = gr.Textbox( + label="New Agent Name" + ) + with gr.Column(): + new_agent_prompt_input = ( + gr.Textbox( + label="New Agent Prompt", + lines=3, + ) + ) + with gr.Row(): + with gr.Column(): + create_agent_button = gr.Button( + "Save New Prompt" + ) + generate_agent_button = gr.Button( + "Generate_Final_p" + ) + with gr.Column(): + create_agent_status = gr.Textbox( + label="Status", + interactive=False, + ) + # with gr.Row(): # temperature_slider = gr.Slider( # label="Temperature", @@ -854,57 +1084,52 @@ def create_app(): # value=0.1, # step=0.01 # ) - - #Hidden textbox to store API Key - env_api_key_textbox = gr.Textbox( - value="", - visible=False + + # Hidden textbox to store API Key + env_api_key_textbox = gr.Textbox( + value="", visible=False ) with gr.Row(): with gr.Column(scale=1): - run_button = gr.Button("Run Task", variant="primary") - cancel_button = gr.Button("Cancel", variant="secondary") + run_button = gr.Button( + "Run Task", variant="primary" + ) + cancel_button = gr.Button( + "Cancel", variant="secondary" + ) with gr.Column(scale=1): with gr.Row(): loading_status = gr.Textbox( label="Status", value="Ready", - interactive=False + interactive=False, ) - # Add loading indicator and status with gr.Row(): agent_output_display = gr.Textbox( label="Agent Responses", placeholder="Responses will appear here...", interactive=False, - lines=10 + lines=10, ) - - - def update_flow_agents(agent_keys): - """Update flow agents based on selected agent prompts.""" - if not agent_keys: - return [], "No agents selected" - agent_names = [key.split('.')[-1] for key in agent_keys] - return agent_names, "Select agents in execution order" - - def update_flow_preview(selected_flow_agents): - """Update flow preview based on selected agents.""" - if not selected_flow_agents: - return "Flow will be shown here..." - flow = " -> ".join(selected_flow_agents) - return flow - def update_agent_dropdown(): """Update agent dropdown when a new agent is added""" global AGENT_PROMPTS AGENT_PROMPTS = load_prompts_from_json() - available_prompts = list(AGENT_PROMPTS.keys()) if AGENT_PROMPTS else ["No agents available"] - return gr.update(choices = available_prompts, value = available_prompts[0] if available_prompts else None) + available_prompts = ( + list(AGENT_PROMPTS.keys()) + if AGENT_PROMPTS + else ["No agents available"] + ) + return gr.update( + choices=available_prompts, + value=available_prompts[0] + if available_prompts + else None, + ) def update_ui_for_swarm_type(swarm_type): """Update UI components based on selected swarm type.""" @@ -912,38 +1137,61 @@ def create_app(): is_mixture = swarm_type == "MixtureOfAgents" is_spreadsheet = swarm_type == "SpreadSheetSwarm" - max_loops = 5 if is_mixture or is_spreadsheet else 10 + max_loops = ( + 5 if is_mixture or is_spreadsheet else 10 + ) # Return visibility state for flow configuration and max loops update return ( gr.update(visible=is_agent_rearrange), # For flow_config - gr.update(maximum=max_loops), # For max_loops_slider - f"Selected {swarm_type}" # For loading_status + gr.update( + maximum=max_loops + ), # For max_loops_slider + f"Selected {swarm_type}", # For loading_status ) + def update_model_dropdown(provider): """Update model dropdown based on selected provider.""" models = filtered_models.get(provider, []) - return gr.update(choices=models, value=models[0] if models else None) - + if provider == "huggingface": + models = [f"huggingface/{model}" for model in models] + return gr.update( + choices=models, + value=models[0] if models else None, + ) + def save_new_agent_prompt(agent_name, agent_prompt): """Saves a new agent prompt to the JSON file.""" try: if not agent_name or not agent_prompt: - return "Error: Agent name and prompt cannot be empty." + return ( + "Error: Agent name and prompt cannot be" + " empty." + ) - if not agent_name.isalnum() and not "_" in agent_name: - return "Error : Agent name must be alphanumeric or underscore(_) " - - if "agent."+agent_name in AGENT_PROMPTS: + if ( + not agent_name.isalnum() + and "_" not in agent_name + ): + return ( + "Error : Agent name must be alphanumeric or" + " underscore(_) " + ) + + if "agent." + agent_name in AGENT_PROMPTS: return "Error : Agent name already exists" - with open(PROMPT_JSON_PATH, 'r+', encoding='utf-8') as f: + with open( + PROMPT_JSON_PATH, "r+", encoding="utf-8" + ) as f: try: data = json.load(f) except json.JSONDecodeError: data = {} - data[agent_name] = {"system_prompt": agent_prompt} + data[agent_name] = { + "system_prompt": agent_prompt + } f.seek(0) json.dump(data, f, indent=4) f.truncate() @@ -951,32 +1199,67 @@ def create_app(): return "New agent prompt saved successfully" except Exception as e: - return f"Error saving agent prompt {str(e)}" - - async def run_task_wrapper(task, max_loops, dynamic_temp, swarm_type, agent_prompt_selector, flow_text, - provider, model_name, api_key, temperature, max_tokens): + return f"Error saving agent prompt {str(e)}" + + async def run_task_wrapper( + task, + max_loops, + dynamic_temp, + swarm_type, + agent_prompt_selector, + flow_text, + provider, + model_name, + api_key, + temperature, + max_tokens, + ): """Execute the task and update the UI with progress.""" try: if not task: - yield "Please provide a task description.", "Error: Missing task", "" + yield ( + "Please provide a task description.", + "Error: Missing task", + "", + ) return - if not agent_prompt_selector or len(agent_prompt_selector) == 0: - yield "Please select at least one agent.", "Error: No agents selected", "" + if ( + not agent_prompt_selector + or len(agent_prompt_selector) == 0 + ): + yield ( + "Please select at least one agent.", + "Error: No agents selected", + "", + ) return - + if not provider: - yield "Please select a provider.", "Error: No provider selected", "" - return - + yield ( + "Please select a provider.", + "Error: No provider selected", + "", + ) + return + if not model_name: - yield "Please select a model.", "Error: No model selected", "" - return - - if not api_key: - yield "Please enter an API Key", "Error: API Key is required", "" - return + yield ( + "Please select a model.", + "Error: No model selected", + "", + ) + if provider == "huggingface": + model_name = f"huggingface/{model_name}" + return + if not api_key: + yield ( + "Please enter an API Key", + "Error: API Key is required", + "", + ) + return # Update status yield "Processing...", "Running task...", "" @@ -985,34 +1268,75 @@ def create_app(): flow = None if swarm_type == "AgentRearrange": if not flow_text: - yield "Please provide the agent flow configuration.", "Error: Flow not configured", "" + yield ( + "Please provide the agent flow" + " configuration.", + "Error: Flow not configured", + "", + ) return flow = flow_text + print( + f"Flow string: {flow}" + ) # Debug: Print flow string + # Save API key to .env env_path = find_dotenv() if provider == "openai": - set_key(env_path, "OPENAI_API_KEY", api_key) + set_key(env_path, "OPENAI_API_KEY", api_key) elif provider == "anthropic": - set_key(env_path, "ANTHROPIC_API_KEY", api_key) + set_key( + env_path, "ANTHROPIC_API_KEY", api_key + ) elif provider == "cohere": - set_key(env_path, "COHERE_API_KEY", api_key) + set_key(env_path, "COHERE_API_KEY", api_key) elif provider == "gemini": - set_key(env_path, "GEMINI_API_KEY", api_key) + set_key(env_path, "GEMINI_API_KEY", api_key) elif provider == "mistral": - set_key(env_path, "MISTRAL_API_KEY", api_key) + set_key(env_path, "MISTRAL_API_KEY", api_key) elif provider == "groq": - set_key(env_path, "GROQ_API_KEY", api_key) + set_key(env_path, "GROQ_API_KEY", api_key) elif provider == "nvidia_nim": - set_key(env_path, "NVIDIA_NIM_API_KEY", api_key) + set_key( + env_path, "NVIDIA_NIM_API_KEY", api_key + ) elif provider == "huggingface": - set_key(env_path, "HUGGINGFACE_API_KEY", api_key) + set_key( + env_path, "HUGGINGFACE_API_KEY", api_key + ) elif provider == "perplexity": - set_key(env_path, "PERPLEXITY_API_KEY", api_key) + set_key( + env_path, "PERPLEXITY_API_KEY", api_key + ) else: - yield f"Error: {provider} this provider is not present", f"Error: {provider} not supported", "" + yield ( + f"Error: {provider} this provider is not" + " present", + f"Error: {provider} not supported", + "", + ) return + agents = initialize_agents( + dynamic_temp, + agent_prompt_selector, + model_name, + provider, + api_key, + temperature, + max_tokens, + ) + print( + "Agents passed to SwarmRouter:" + f" {[agent.agent_name for agent in agents]}" + ) # Debug: Print agent list + + # Convert agent list to dictionary + agents_dict = { + agent.agent_name: agent for agent in agents + } + # Execute task result, router, error = await execute_task( task=task, @@ -1025,74 +1349,104 @@ def create_app(): provider=provider, api_key=api_key, temperature=temperature, - max_tokens = max_tokens, + max_tokens=max_tokens, + agents=agents_dict, # Changed here ) if error: yield f"Error: {error}", f"Error: {error}", "" return + + if result is None: + yield "Error: No output from swarm.", f"Error: {error}", "" + return # Format output based on swarm type output_lines = [] if swarm_type == "SpreadSheetSwarm": - # Check if the result is a file path or JSON - if os.path.exists(result): - parsed_output = parse_spreadsheet_swarm_output(result) + # Check if the result is a file path or JSON + if os.path.exists(result): + parsed_output = ( + parse_spreadsheet_swarm_output(result) + ) output_lines.append(parsed_output) - else: + else: parsed_output = parse_json_output(result) output_lines.append(parsed_output) elif swarm_type == "AgentRearrange": - parsed_output = parse_agent_rearrange_output(result) - output_lines.append(parsed_output) + try: + parsed_output = ( + parse_agent_rearrange_output(result) + ) + except ValueError as e: + parsed_output = ( + f"Error during parsing: {e}" + ) # Handle ValueError + output_lines.append(parsed_output) elif swarm_type == "MixtureOfAgents": - parsed_output = parse_mixture_of_agents_output(result) - output_lines.append(parsed_output) + parsed_output = ( + parse_mixture_of_agents_output(result) + ) + output_lines.append(parsed_output) elif swarm_type == "SequentialWorkflow": - parsed_output = parse_sequential_workflow_output(result) - output_lines.append(parsed_output) - elif isinstance(result, dict): # checking if result is dict or string. - + parsed_output = ( + parse_sequential_workflow_output(result) + ) + output_lines.append(parsed_output) + elif isinstance( + result, dict + ): # checking if result is dict or string. if swarm_type == "MixtureOfAgents": # Add individual agent outputs for key, value in result.items(): if key != "Aggregated Summary": - output_lines.append(f"### {key} ###\n{value}\n") + output_lines.append( + f"### {key} ###\n{value}\n" + ) # Add aggregated summary at the end if "Aggregated Summary" in result: - output_lines.append(f"\n### Aggregated Summary ###\n{result['Aggregated Summary']}\n{'=' * 50}\n") + output_lines.append( + "\n### Aggregated Summary" + f" ###\n{result['Aggregated Summary']}\n{'=' * 50}\n" + ) else: # SequentialWorkflow, ConcurrentWorkflow, Auto for key, value in result.items(): - output_lines.append(f"### {key} ###\n{value}\n{'=' * 50}\n") + output_lines.append( + f"### {key} ###\n{value}\n{'=' * 50}\n" + ) elif isinstance(result, str): output_lines.append(str(result)) yield "\n".join(output_lines), "Completed", api_key - + except Exception as e: - yield f"Error: {str(e)}", f"Error: {str(e)}", "" + yield f"Error: {str(e)}", f"Error: {str(e)}", "" # Connect the update functions agent_selector.change( fn=update_ui_for_swarm_type, inputs=[agent_selector], - outputs=[flow_config, max_loops_slider, loading_status] + outputs=[ + flow_config, + max_loops_slider, + loading_status, + ], ) provider_dropdown.change( fn=update_model_dropdown, inputs=[provider_dropdown], - outputs=[model_dropdown] + outputs=[model_dropdown], ) # Event for creating new agent prompts create_agent_button.click( fn=save_new_agent_prompt, inputs=[new_agent_name_input, new_agent_prompt_input], - outputs=[create_agent_status] + outputs=[create_agent_status], ).then( fn=update_agent_dropdown, inputs=None, - outputs=[agent_prompt_selector] + outputs=[agent_prompt_selector], ) # Create event trigger @@ -1111,7 +1465,11 @@ def create_app(): api_key_input, max_tokens_slider ], - outputs=[agent_output_display, loading_status, env_api_key_textbox] + outputs=[ + agent_output_display, + loading_status, + env_api_key_textbox, + ], ) # Connect cancel button to interrupt processing @@ -1121,8 +1479,12 @@ def create_app(): cancel_button.click( fn=cancel_task, inputs=None, - outputs=[agent_output_display, loading_status, env_api_key_textbox], - cancels=run_event + outputs=[ + agent_output_display, + loading_status, + env_api_key_textbox, + ], + cancels=run_event, ) with gr.Column(scale=1): # Right column @@ -1139,7 +1501,11 @@ def create_app(): # Update logs when tab is selected logs_tab = gr.Tab("Logs") - logs_tab.select(fn=update_logs_display, inputs=None, outputs=[logs_display]) + logs_tab.select( + fn=update_logs_display, + inputs=None, + outputs=[logs_display], + ) return ui.build()