parent
36a092f6e6
commit
b4f923f1fb
@ -1,22 +0,0 @@
|
|||||||
mkdocs
|
|
||||||
mkdocs-material
|
|
||||||
mkdocs-glightbox
|
|
||||||
mkdocs-git-authors-plugin
|
|
||||||
mkdocs-git-revision-date-plugin
|
|
||||||
mkdocs-git-committers-plugin
|
|
||||||
mkdocstrings
|
|
||||||
mike
|
|
||||||
mkdocs-jupyter
|
|
||||||
mkdocs-git-committers-plugin-2
|
|
||||||
mkdocs-git-revision-date-localized-plugin
|
|
||||||
mkdocs-redirects
|
|
||||||
mkdocs-material-extensions
|
|
||||||
mkdocs-simple-hooks
|
|
||||||
mkdocs-awesome-pages-plugin
|
|
||||||
mkdocs-versioning
|
|
||||||
mkdocs-mermaid2-plugin
|
|
||||||
mkdocs-include-markdown-plugin
|
|
||||||
mkdocs-enumerate-headings-plugin
|
|
||||||
mkdocs-autolinks-plugin
|
|
||||||
mkdocs-minify-html-plugin
|
|
||||||
mkdocs-autolinks-plugin
|
|
@ -0,0 +1,77 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
tool decorated func [search_api] -> agent which parses the docs of the tool func
|
||||||
|
-> injected into prompt -> agent will output json containing tool usage -> agent output will be parsed -> tool executed
|
||||||
|
-> terminal response can be returned to agent for self-healing
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Import the OpenAIChat model and the Agent struct
|
||||||
|
from swarms import Agent, llama3Hosted
|
||||||
|
|
||||||
|
# Load the environment variables
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
|
# Define a tool
|
||||||
|
def search_api(query: str, description: str):
|
||||||
|
"""Search the web for the query
|
||||||
|
|
||||||
|
Args:
|
||||||
|
query (str): _description_
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
|
return f"Search results for {query}"
|
||||||
|
|
||||||
|
|
||||||
|
def weather_api(
|
||||||
|
query: str,
|
||||||
|
):
|
||||||
|
"""_summary_
|
||||||
|
|
||||||
|
Args:
|
||||||
|
query (str): _description_
|
||||||
|
"""
|
||||||
|
print(f"Getting the weather for {query}")
|
||||||
|
|
||||||
|
|
||||||
|
def rapid_api(query: str):
|
||||||
|
"""_summary_
|
||||||
|
|
||||||
|
Args:
|
||||||
|
query (str): _description_
|
||||||
|
"""
|
||||||
|
print(f"Getting the weather for {query}")
|
||||||
|
|
||||||
|
|
||||||
|
# Get the API key from the environment
|
||||||
|
api_key = os.environ.get("OPENAI_API_KEY")
|
||||||
|
|
||||||
|
# Initialize the language model
|
||||||
|
llm = llama3Hosted(
|
||||||
|
temperature=0.5,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
## Initialize the workflow
|
||||||
|
agent = Agent(
|
||||||
|
agent_name="Research Agent",
|
||||||
|
llm=llm,
|
||||||
|
max_loops=3,
|
||||||
|
dashboard=True,
|
||||||
|
tools=[search_api, weather_api, rapid_api],
|
||||||
|
interactive=True,
|
||||||
|
execute_tool=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Run the workflow on a task
|
||||||
|
out = agent.run("Use the weather tool in Miami")
|
||||||
|
print(out)
|
@ -1,39 +0,0 @@
|
|||||||
import json
|
|
||||||
import requests
|
|
||||||
from typing import Dict, Any
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_weather_data(city: str) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Fetch near real-time weather data for a city using wttr.in.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
city (str): The name of the city (e.g., "Austin, Tx").
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict[str, Any]: Weather data for the specified city.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Exception: If the request fails or the response is invalid.
|
|
||||||
"""
|
|
||||||
url = f"http://wttr.in/{city}"
|
|
||||||
params = {"format": "j1"} # JSON format
|
|
||||||
try:
|
|
||||||
response = requests.get(url, params=params)
|
|
||||||
response.raise_for_status()
|
|
||||||
response = json.dumps(response.json(), indent=2)
|
|
||||||
return response
|
|
||||||
except requests.RequestException as e:
|
|
||||||
raise Exception(f"Failed to fetch weather data: {e}")
|
|
||||||
except ValueError:
|
|
||||||
raise Exception("Invalid response format.")
|
|
||||||
|
|
||||||
|
|
||||||
# # Example usage
|
|
||||||
# city = "Huntsville, AL"
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# weather_data = fetch_weather_data(city)
|
|
||||||
# print("Weather Data:", weather_data)
|
|
||||||
# except Exception as e:
|
|
||||||
# print(e)
|
|
@ -0,0 +1,117 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from playground.demos.plant_biologist_swarm.prompts import (
|
||||||
|
diagnoser_agent,
|
||||||
|
disease_detector_agent,
|
||||||
|
growth_predictor_agent,
|
||||||
|
harvester_agent,
|
||||||
|
treatment_recommender_agent,
|
||||||
|
)
|
||||||
|
|
||||||
|
from swarms import Agent, GPT4VisionAPI
|
||||||
|
|
||||||
|
|
||||||
|
# Load the OpenAI API key from the .env file
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Initialize the OpenAI API key
|
||||||
|
api_key = os.environ.get("OPENAI_API_KEY")
|
||||||
|
|
||||||
|
|
||||||
|
# llm = llm,
|
||||||
|
llm = GPT4VisionAPI(
|
||||||
|
max_tokens=4000,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize Diagnoser Agent
|
||||||
|
diagnoser_agent = Agent(
|
||||||
|
agent_name="Diagnoser Agent",
|
||||||
|
system_prompt=diagnoser_agent(),
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
streaming_on=True,
|
||||||
|
verbose=True,
|
||||||
|
# saved_state_path="diagnoser.json",
|
||||||
|
multi_modal=True,
|
||||||
|
autosave=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize Harvester Agent
|
||||||
|
harvester_agent = Agent(
|
||||||
|
agent_name="Harvester Agent",
|
||||||
|
system_prompt=harvester_agent(),
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
streaming_on=True,
|
||||||
|
verbose=True,
|
||||||
|
# saved_state_path="harvester.json",
|
||||||
|
multi_modal=True,
|
||||||
|
autosave=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize Growth Predictor Agent
|
||||||
|
growth_predictor_agent = Agent(
|
||||||
|
agent_name="Growth Predictor Agent",
|
||||||
|
system_prompt=growth_predictor_agent(),
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
streaming_on=True,
|
||||||
|
verbose=True,
|
||||||
|
# saved_state_path="growth_predictor.json",
|
||||||
|
multi_modal=True,
|
||||||
|
autosave=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize Treatment Recommender Agent
|
||||||
|
treatment_recommender_agent = Agent(
|
||||||
|
agent_name="Treatment Recommender Agent",
|
||||||
|
system_prompt=treatment_recommender_agent(),
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
streaming_on=True,
|
||||||
|
verbose=True,
|
||||||
|
# saved_state_path="treatment_recommender.json",
|
||||||
|
multi_modal=True,
|
||||||
|
autosave=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize Disease Detector Agent
|
||||||
|
disease_detector_agent = Agent(
|
||||||
|
agent_name="Disease Detector Agent",
|
||||||
|
system_prompt=disease_detector_agent(),
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
streaming_on=True,
|
||||||
|
verbose=True,
|
||||||
|
# saved_state_path="disease_detector.json",
|
||||||
|
multi_modal=True,
|
||||||
|
autosave=True,
|
||||||
|
)
|
||||||
|
agents = [
|
||||||
|
diagnoser_agent,
|
||||||
|
disease_detector_agent,
|
||||||
|
treatment_recommender_agent,
|
||||||
|
growth_predictor_agent,
|
||||||
|
harvester_agent,
|
||||||
|
]
|
||||||
|
|
||||||
|
task = "Conduct a diagnosis on the patient's symptoms."
|
||||||
|
img = "tomato.jpg"
|
||||||
|
|
||||||
|
loop = 0
|
||||||
|
for i in range(len(agents)):
|
||||||
|
if i == 0:
|
||||||
|
output = agents[i].run(task, img)
|
||||||
|
|
||||||
|
else:
|
||||||
|
output = agents[i].run(output, img)
|
||||||
|
|
||||||
|
# Add extensive logging for each agent
|
||||||
|
print(f"Agent {i+1} - {agents[i].agent_name}")
|
||||||
|
print("-----------------------------------")
|
After Width: | Height: | Size: 1.9 MiB |
@ -0,0 +1,34 @@
|
|||||||
|
from swarms import Agent, llama3Hosted
|
||||||
|
from swarms.structs.swarm_load_balancer import AgentLoadBalancer
|
||||||
|
|
||||||
|
# Initialize the language model agent (e.g., GPT-3)
|
||||||
|
llm = llama3Hosted()
|
||||||
|
|
||||||
|
# Initialize agents for individual tasks
|
||||||
|
agent1 = Agent(
|
||||||
|
agent_name="Blog generator",
|
||||||
|
system_prompt="Generate a blog post like stephen king",
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
tools=[],
|
||||||
|
)
|
||||||
|
agent2 = Agent(
|
||||||
|
agent_name="Summarizer",
|
||||||
|
system_prompt="Sumamrize the blog post",
|
||||||
|
llm=llm,
|
||||||
|
max_loops=1,
|
||||||
|
dashboard=False,
|
||||||
|
tools=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create the Sequential workflow
|
||||||
|
workflow = AgentLoadBalancer(
|
||||||
|
agents=[agent1, agent2],
|
||||||
|
max_loops=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Run the workflow
|
||||||
|
workflow.run(
|
||||||
|
"Generate a blog post on how swarms of agents can help businesses grow."
|
||||||
|
)
|
@ -1,29 +0,0 @@
|
|||||||
torch>=2.1.1,<3.0
|
|
||||||
transformers>=4.39.0,<5.0.0
|
|
||||||
asyncio>=3.4.3,<4.0
|
|
||||||
langchain-community==0.0.29
|
|
||||||
langchain-experimental==0.0.55
|
|
||||||
backoff==2.2.1
|
|
||||||
toml
|
|
||||||
pypdf==4.1.0
|
|
||||||
ratelimit==2.2.1
|
|
||||||
loguru==0.7.2
|
|
||||||
pydantic==2.7.1
|
|
||||||
tenacity==8.2.3
|
|
||||||
Pillow==10.3.0
|
|
||||||
psutil
|
|
||||||
sentry-sdk
|
|
||||||
python-dotenv
|
|
||||||
opencv-python-headless
|
|
||||||
PyYAML
|
|
||||||
docstring_parser==0.16
|
|
||||||
black>=23.1,<25.0
|
|
||||||
ruff>=0.0.249,<0.4.5
|
|
||||||
types-toml>=0.10.8.1
|
|
||||||
types-pytz>=2023.3,<2025.0
|
|
||||||
types-chardet>=5.0.4.6
|
|
||||||
mypy-protobuf>=3.0.0
|
|
||||||
pytest>=8.1.1
|
|
||||||
termcolor>=2.4.0
|
|
||||||
pandas>=2.2.2
|
|
||||||
fastapi>=0.110.1
|
|
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find and delete all __pycache__ directories
|
||||||
|
find . -type d -name "__pycache__" -exec rm -r {} +
|
||||||
|
|
||||||
|
# Find and delete all .pyc files
|
||||||
|
find . -type f -name "*.pyc" -delete
|
||||||
|
|
||||||
|
# Find and delete all dist directories
|
||||||
|
find . -type d -name "dist" -exec rm -r {} +
|
||||||
|
|
||||||
|
# Find and delete all .ruff directories
|
||||||
|
find . -type d -name ".ruff" -exec rm -r {} +
|
||||||
|
|
||||||
|
# Find and delete all .egg-info directories
|
||||||
|
find . -type d -name "*.egg-info" -exec rm -r {} +
|
||||||
|
|
||||||
|
# Find and delete all .pyo files
|
||||||
|
find . -type f -name "*.pyo" -delete
|
||||||
|
|
||||||
|
# Find and delete all .pyd files
|
||||||
|
find . -type f -name "*.pyd" -delete
|
||||||
|
|
||||||
|
# Find and delete all .so files
|
||||||
|
find . -type f -name "*.so" -delete
|
@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find and delete all __pycache__ directories
|
|
||||||
find . -type d -name "__pycache__" -exec rm -r {} +
|
|
||||||
|
|
||||||
# Find and delete all .pyc files
|
|
||||||
find . -type f -name "*.pyc" -delete
|
|
@ -0,0 +1,115 @@
|
|||||||
|
from swarms.utils.loguru_logger import logger
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import List
|
||||||
|
from swarms.structs.agent import Agent
|
||||||
|
|
||||||
|
|
||||||
|
class HaSAgentSchema(BaseModel):
|
||||||
|
name: str = Field(
|
||||||
|
...,
|
||||||
|
title="Name of the agent",
|
||||||
|
description="Name of the agent",
|
||||||
|
)
|
||||||
|
system_prompt: str = (
|
||||||
|
Field(
|
||||||
|
...,
|
||||||
|
title="System prompt for the agent",
|
||||||
|
description="System prompt for the agent",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
rules: str = Field(
|
||||||
|
...,
|
||||||
|
title="Rules",
|
||||||
|
description="Rules for the agent",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HassSchema(BaseModel):
|
||||||
|
agents: List[HaSAgentSchema] = Field(
|
||||||
|
...,
|
||||||
|
title="List of agents to use for the problem",
|
||||||
|
description="List of agents to use for the problem",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# import json
|
||||||
|
def parse_json_from_input(input_str: str = None):
|
||||||
|
"""
|
||||||
|
Parses a JSON string from the input and returns the parsed data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_str (str): The input string containing the JSON.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple containing the parsed data. The tuple contains three elements:
|
||||||
|
- The plan extracted from the JSON.
|
||||||
|
- The agents extracted from the JSON.
|
||||||
|
- The rules extracted from the JSON.
|
||||||
|
|
||||||
|
If the input string is None or empty, or if the JSON decoding fails, all elements of the tuple will be None.
|
||||||
|
"""
|
||||||
|
# Validate input is not None or empty
|
||||||
|
if not input_str:
|
||||||
|
logger.info("Error: Input string is None or empty.")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
# Attempt to extract JSON from markdown using regular expression
|
||||||
|
json_pattern = re.compile(r"```json\n(.*?)\n```", re.DOTALL)
|
||||||
|
match = json_pattern.search(input_str)
|
||||||
|
json_str = match.group(1).strip() if match else input_str.strip()
|
||||||
|
|
||||||
|
# Attempt to parse the JSON string
|
||||||
|
try:
|
||||||
|
data = json.loads(json_str)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logger.info(f"Error: JSON decoding failed with message '{e}'")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
hass_schema = HassSchema(**data)
|
||||||
|
return (hass_schema.agents,)
|
||||||
|
|
||||||
|
|
||||||
|
## [Create the agents]
|
||||||
|
def create_worker_agents(
|
||||||
|
agents: List[HassSchema],
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
) -> List[Agent]:
|
||||||
|
"""
|
||||||
|
Create and initialize agents based on the provided AgentSchema objects.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
agents (List[AgentSchema]): A list of AgentSchema objects containing agent information.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[Agent]: The initialized Agent objects.
|
||||||
|
|
||||||
|
"""
|
||||||
|
agent_list = []
|
||||||
|
for agent in agents:
|
||||||
|
name = agent.name
|
||||||
|
system_prompt = agent.system_prompt
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Creating agent: {name} with system prompt:"
|
||||||
|
f" {system_prompt}"
|
||||||
|
)
|
||||||
|
|
||||||
|
out = Agent(
|
||||||
|
agent_name=name,
|
||||||
|
system_prompt=system_prompt,
|
||||||
|
max_loops=1,
|
||||||
|
autosave=True,
|
||||||
|
dashboard=False,
|
||||||
|
verbose=True,
|
||||||
|
stopping_token="<DONE>",
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the long term memory system of every agent to long term memory system
|
||||||
|
agent_list.append(out)
|
||||||
|
|
||||||
|
return agent_list
|
@ -0,0 +1,121 @@
|
|||||||
|
import logging
|
||||||
|
import networkx as nx
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from typing import List, Tuple
|
||||||
|
from swarms import Agent
|
||||||
|
|
||||||
|
# Setup basic configuration for logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AgentDFS:
|
||||||
|
"""
|
||||||
|
A DFS search class that uses a single Agent to generate and manually evaluate text states.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
agent: Agent,
|
||||||
|
evaluator: Agent,
|
||||||
|
initial_prompt: str,
|
||||||
|
num_thoughts: int,
|
||||||
|
max_steps: int,
|
||||||
|
max_states: int,
|
||||||
|
pruning_threshold: float,
|
||||||
|
):
|
||||||
|
self.agent = agent
|
||||||
|
self.initial_prompt = initial_prompt
|
||||||
|
self.num_thoughts = num_thoughts
|
||||||
|
self.max_steps = max_steps
|
||||||
|
self.max_states = max_states
|
||||||
|
self.pruning_threshold = pruning_threshold
|
||||||
|
self.visited = {}
|
||||||
|
self.graph = nx.DiGraph()
|
||||||
|
|
||||||
|
def search(self) -> List[Tuple[str, float]]:
|
||||||
|
stack = [(self.initial_prompt, 0.0)]
|
||||||
|
self.graph.add_node(self.initial_prompt, score=0.0)
|
||||||
|
results = []
|
||||||
|
|
||||||
|
while stack and len(results) < self.max_steps:
|
||||||
|
current_prompt, _ = stack.pop()
|
||||||
|
logging.info(f"Generating from: {current_prompt}")
|
||||||
|
|
||||||
|
# Use agent to generate a response
|
||||||
|
out = self.agent.run(current_prompt)
|
||||||
|
|
||||||
|
# Retrieve and split generated text into segments (assuming `agent.response` holds the text)
|
||||||
|
generated_texts = self.split_into_thoughts(
|
||||||
|
out, self.num_thoughts
|
||||||
|
)
|
||||||
|
|
||||||
|
for text, score in generated_texts:
|
||||||
|
if score >= self.pruning_threshold:
|
||||||
|
stack.append((text, score))
|
||||||
|
results.append((text, score))
|
||||||
|
self.graph.add_node(text, score=score)
|
||||||
|
self.graph.add_edge(current_prompt, text)
|
||||||
|
logging.info(f"Added node: {text} with score: {score}")
|
||||||
|
|
||||||
|
results.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
results = results[: self.max_states]
|
||||||
|
|
||||||
|
logging.info("Search completed")
|
||||||
|
return results
|
||||||
|
|
||||||
|
def split_into_thoughts(
|
||||||
|
self, text: str, num_thoughts: int
|
||||||
|
) -> List[Tuple[str, float]]:
|
||||||
|
"""Simulate the split of text into thoughts and assign random scores."""
|
||||||
|
import random
|
||||||
|
|
||||||
|
# Simple split based on punctuation or predefined length
|
||||||
|
thoughts = text.split(".")[:num_thoughts]
|
||||||
|
return [
|
||||||
|
(thought.strip(), random.random())
|
||||||
|
for thought in thoughts
|
||||||
|
if thought.strip()
|
||||||
|
]
|
||||||
|
|
||||||
|
def visualize(self):
|
||||||
|
pos = nx.spring_layout(self.graph, seed=42)
|
||||||
|
labels = {
|
||||||
|
node: f"{node[:15]}...: {self.graph.nodes[node]['score']:.2f}"
|
||||||
|
for node in self.graph.nodes()
|
||||||
|
}
|
||||||
|
nx.draw(
|
||||||
|
self.graph,
|
||||||
|
pos,
|
||||||
|
with_labels=True,
|
||||||
|
labels=labels,
|
||||||
|
node_size=7000,
|
||||||
|
node_color="skyblue",
|
||||||
|
font_size=8,
|
||||||
|
font_weight="bold",
|
||||||
|
edge_color="gray",
|
||||||
|
)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
# Example usage setup remains the same as before
|
||||||
|
|
||||||
|
|
||||||
|
# Example usage setup remains the same as before, simply instantiate two agents: one for generation and one for evaluation
|
||||||
|
# # Example usage
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# load_dotenv()
|
||||||
|
# api_key = os.environ.get("OPENAI_API_KEY")
|
||||||
|
# llm = llama3Hosted(max_tokens=400)
|
||||||
|
# agent = Agent(llm=llm, max_loops=1, autosave=True, dashboard=True)
|
||||||
|
# dfs_agent = AgentDFS(
|
||||||
|
# agent=agent,
|
||||||
|
# initial_prompt="Explore the benefits of regular exercise.",
|
||||||
|
# num_thoughts=5,
|
||||||
|
# max_steps=20,
|
||||||
|
# max_states=10,
|
||||||
|
# pruning_threshold=0.3,
|
||||||
|
# )
|
||||||
|
# results = dfs_agent.search()
|
||||||
|
# dfs_agent.visualize()
|
@ -1,168 +0,0 @@
|
|||||||
import json
|
|
||||||
import concurrent.futures
|
|
||||||
import re
|
|
||||||
from abc import abstractmethod
|
|
||||||
from typing import Dict, List, NamedTuple
|
|
||||||
|
|
||||||
from langchain.schema import BaseOutputParser
|
|
||||||
from pydantic import ValidationError
|
|
||||||
|
|
||||||
from swarms.tools.base_tool import BaseTool
|
|
||||||
|
|
||||||
from swarms.utils.loguru_logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
class AgentAction(NamedTuple):
|
|
||||||
"""Action returned by AgentOutputParser."""
|
|
||||||
|
|
||||||
name: str
|
|
||||||
args: Dict
|
|
||||||
|
|
||||||
|
|
||||||
class BaseAgentOutputParser(BaseOutputParser):
|
|
||||||
"""Base Output parser for Agent."""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def parse(self, text: str) -> AgentAction:
|
|
||||||
"""Return AgentAction"""
|
|
||||||
|
|
||||||
|
|
||||||
def preprocess_json_input(input_str: str) -> str:
|
|
||||||
"""Preprocesses a string to be parsed as json.
|
|
||||||
|
|
||||||
Replace single backslashes with double backslashes,
|
|
||||||
while leaving already escaped ones intact.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
input_str: String to be preprocessed
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Preprocessed string
|
|
||||||
"""
|
|
||||||
corrected_str = re.sub(
|
|
||||||
r'(?<!\\)\\(?!["\\/bfnrt]|u[0-9a-fA-F]{4})',
|
|
||||||
r"\\\\",
|
|
||||||
input_str,
|
|
||||||
)
|
|
||||||
return corrected_str
|
|
||||||
|
|
||||||
|
|
||||||
class AgentOutputParser(BaseAgentOutputParser):
|
|
||||||
"""Output parser for Agent."""
|
|
||||||
|
|
||||||
def parse(self, text: str) -> AgentAction:
|
|
||||||
try:
|
|
||||||
parsed = json.loads(text, strict=False)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
preprocessed_text = preprocess_json_input(text)
|
|
||||||
try:
|
|
||||||
parsed = json.loads(preprocessed_text, strict=False)
|
|
||||||
except Exception:
|
|
||||||
return AgentAction(
|
|
||||||
name="ERROR",
|
|
||||||
args={
|
|
||||||
"error": (f"Could not parse invalid json: {text}")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
return AgentAction(
|
|
||||||
name=parsed["command"]["name"],
|
|
||||||
args=parsed["command"]["args"],
|
|
||||||
)
|
|
||||||
except (KeyError, TypeError):
|
|
||||||
# If the command is null or incomplete, return an erroneous tool
|
|
||||||
return AgentAction(
|
|
||||||
name="ERROR",
|
|
||||||
args={"error": f"Incomplete command args: {parsed}"},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def execute_tool_by_name(
|
|
||||||
text: str,
|
|
||||||
tools: List[BaseTool],
|
|
||||||
stop_token: str = "finish",
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Executes a tool based on the given text command.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text (str): The text command to be executed.
|
|
||||||
tools (List[BaseTool]): A list of available tools.
|
|
||||||
stop_token (str, optional): The stop token to terminate the execution. Defaults to "finish".
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The result of the command execution.
|
|
||||||
"""
|
|
||||||
output_parser = AgentOutputParser()
|
|
||||||
# Get command name and arguments
|
|
||||||
action = output_parser.parse(text)
|
|
||||||
tools = {t.name: t for t in tools}
|
|
||||||
|
|
||||||
# logger.info(f"Tools available: {tools}")
|
|
||||||
|
|
||||||
if action.name == stop_token:
|
|
||||||
return action.args["response"]
|
|
||||||
if action.name in tools:
|
|
||||||
tool = tools[action.name]
|
|
||||||
try:
|
|
||||||
# Check if multiple tools are used
|
|
||||||
tool_names = [name for name in tools if name in text]
|
|
||||||
if len(tool_names) > 1:
|
|
||||||
# Execute tools concurrently
|
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
||||||
futures = []
|
|
||||||
for tool_name in tool_names:
|
|
||||||
logger.info(f"Executing tool: {tool_name}")
|
|
||||||
futures.append(
|
|
||||||
executor.submit(
|
|
||||||
tools[tool_name].run, action.args
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Wait for all futures to complete
|
|
||||||
concurrent.futures.wait(futures)
|
|
||||||
|
|
||||||
# Get results from completed futures
|
|
||||||
results = [
|
|
||||||
future.result()
|
|
||||||
for future in futures
|
|
||||||
if future.done()
|
|
||||||
]
|
|
||||||
|
|
||||||
# Process results
|
|
||||||
for result in results:
|
|
||||||
# Handle errors
|
|
||||||
if isinstance(result, Exception):
|
|
||||||
result = (
|
|
||||||
f"Error: {str(result)},"
|
|
||||||
f" {type(result).__name__}, args:"
|
|
||||||
f" {action.args}"
|
|
||||||
)
|
|
||||||
# Handle successful execution
|
|
||||||
else:
|
|
||||||
result = (
|
|
||||||
f"Command {tool.name} returned:"
|
|
||||||
f" {result}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
observation = tool.run(action.args)
|
|
||||||
except ValidationError as e:
|
|
||||||
observation = (
|
|
||||||
f"Validation Error in args: {str(e)}, args:"
|
|
||||||
f" {action.args}"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
observation = (
|
|
||||||
f"Error: {str(e)}, {type(e).__name__}, args:"
|
|
||||||
f" {action.args}"
|
|
||||||
)
|
|
||||||
result = f"Command {tool.name} returned: {observation}"
|
|
||||||
elif action.name == "ERROR":
|
|
||||||
result = f"Error: {action.args}. "
|
|
||||||
else:
|
|
||||||
result = (
|
|
||||||
f"Unknown command '{action.name}'. "
|
|
||||||
"Please refer to the 'COMMANDS' list for available "
|
|
||||||
"commands and only respond in the specified JSON format."
|
|
||||||
)
|
|
||||||
return result
|
|
@ -0,0 +1,176 @@
|
|||||||
|
import concurrent.futures
|
||||||
|
from typing import Callable, Any, Dict, List
|
||||||
|
from swarms.utils.loguru_logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
def openai_tool_executor(
|
||||||
|
tools: List[Dict[str, Any]],
|
||||||
|
function_map: Dict[str, Callable],
|
||||||
|
verbose: bool = True,
|
||||||
|
return_as_string: bool = False,
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
) -> Callable:
|
||||||
|
"""
|
||||||
|
Creates a function that dynamically and concurrently executes multiple functions based on parameters specified
|
||||||
|
in a list of tool dictionaries, with extensive error handling and validation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tools (List[Dict[str, Any]]): A list of dictionaries, each containing configuration for a tool, including parameters.
|
||||||
|
function_map (Dict[str, Callable]): A dictionary mapping function names to their corresponding callable functions.
|
||||||
|
verbose (bool): If True, enables verbose logging.
|
||||||
|
return_as_string (bool): If True, returns the results as a concatenated string.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Callable: A function that, when called, executes the specified functions concurrently with the parameters given.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> def test_function(param1: int, param2: str) -> str:
|
||||||
|
... return f"Test function called with parameters: {param1}, {param2}"
|
||||||
|
|
||||||
|
>>> tool_executor = openai_tool_executor(
|
||||||
|
... tools=[
|
||||||
|
... {
|
||||||
|
... "type": "function",
|
||||||
|
... "function": {
|
||||||
|
... "name": "test_function",
|
||||||
|
... "parameters": {
|
||||||
|
... "param1": 1,
|
||||||
|
... "param2": "example"
|
||||||
|
... }
|
||||||
|
... }
|
||||||
|
... }
|
||||||
|
... ],
|
||||||
|
... function_map={
|
||||||
|
... "test_function": test_function
|
||||||
|
... },
|
||||||
|
... return_as_string=True
|
||||||
|
... )
|
||||||
|
>>> results = tool_executor()
|
||||||
|
>>> print(results)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def tool_executor():
|
||||||
|
# Prepare tasks for concurrent execution
|
||||||
|
results = []
|
||||||
|
logger.info(f"Executing {len(tools)} tools concurrently.")
|
||||||
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
|
futures = []
|
||||||
|
for tool in tools:
|
||||||
|
if tool.get("type") != "function":
|
||||||
|
continue # Skip non-function tool entries
|
||||||
|
|
||||||
|
function_info = tool.get("function", {})
|
||||||
|
func_name = function_info.get("name")
|
||||||
|
logger.info(f"Executing function: {func_name}")
|
||||||
|
|
||||||
|
# Check if the function name is mapped to an actual function
|
||||||
|
if func_name not in function_map:
|
||||||
|
error_message = f"Function '{func_name}' not found in function map."
|
||||||
|
logger.error(error_message)
|
||||||
|
results.append(error_message)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Validate parameters
|
||||||
|
params = function_info.get("parameters", {})
|
||||||
|
if not params:
|
||||||
|
error_message = f"No parameters specified for function '{func_name}'."
|
||||||
|
logger.error(error_message)
|
||||||
|
results.append(error_message)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Submit the function for execution
|
||||||
|
try:
|
||||||
|
future = executor.submit(
|
||||||
|
function_map[func_name], **params
|
||||||
|
)
|
||||||
|
futures.append((func_name, future))
|
||||||
|
except Exception as e:
|
||||||
|
error_message = f"Failed to submit the function '{func_name}' for execution: {e}"
|
||||||
|
logger.error(error_message)
|
||||||
|
results.append(error_message)
|
||||||
|
|
||||||
|
# Gather results from all futures
|
||||||
|
for func_name, future in futures:
|
||||||
|
try:
|
||||||
|
result = future.result() # Collect result from future
|
||||||
|
results.append(f"{func_name}: {result}")
|
||||||
|
except Exception as e:
|
||||||
|
error_message = f"Error during execution of function '{func_name}': {e}"
|
||||||
|
logger.error(error_message)
|
||||||
|
results.append(error_message)
|
||||||
|
|
||||||
|
if return_as_string:
|
||||||
|
return "\n".join(results)
|
||||||
|
|
||||||
|
logger.info(f"Results: {results}")
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
return tool_executor
|
||||||
|
|
||||||
|
|
||||||
|
# # Example
|
||||||
|
# @tool(
|
||||||
|
# name="test_function",
|
||||||
|
# description="A test function that takes two parameters and returns a string.",
|
||||||
|
# )
|
||||||
|
# def test_function(param1: int, param2: str) -> str:
|
||||||
|
# return f"Test function called with parameters: {param1}, {param2}"
|
||||||
|
|
||||||
|
|
||||||
|
# @tool(
|
||||||
|
# name="test_function2",
|
||||||
|
# description="A test function that takes two parameters and returns a string.",
|
||||||
|
# )
|
||||||
|
# def test_function2(param1: int, param2: str) -> str:
|
||||||
|
# return f"Test function 2 called with parameters: {param1}, {param2}"
|
||||||
|
|
||||||
|
|
||||||
|
# # Example execution
|
||||||
|
# out = openai_tool_executor(
|
||||||
|
# tools=[
|
||||||
|
# {
|
||||||
|
# "type": "function",
|
||||||
|
# "function": {
|
||||||
|
# "name": "test_function",
|
||||||
|
# "parameters": {
|
||||||
|
# "properties": {
|
||||||
|
# "param1": {
|
||||||
|
# "type": "int",
|
||||||
|
# "description": "An integer parameter.",
|
||||||
|
# },
|
||||||
|
# "param2": {
|
||||||
|
# "type": "str",
|
||||||
|
# "description": "A string parameter.",
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "type": "function",
|
||||||
|
# "function": {
|
||||||
|
# "name": "test_function2",
|
||||||
|
# "parameters": {
|
||||||
|
# "properties": {
|
||||||
|
# "param1": {
|
||||||
|
# "type": "int",
|
||||||
|
# "description": "An integer parameter.",
|
||||||
|
# },
|
||||||
|
# "param2": {
|
||||||
|
# "type": "str",
|
||||||
|
# "description": "A string parameter.",
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# ],
|
||||||
|
# function_map={
|
||||||
|
# "test_function": test_function,
|
||||||
|
# "test_function2": test_function2,
|
||||||
|
# },
|
||||||
|
# return_as_string=True,
|
||||||
|
# )
|
||||||
|
# print(out)
|
@ -0,0 +1,40 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def function_to_str(function: dict[str, Any]) -> str:
|
||||||
|
"""
|
||||||
|
Convert a function dictionary to a string representation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
function (dict[str, Any]): The function dictionary to convert.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The string representation of the function.
|
||||||
|
|
||||||
|
"""
|
||||||
|
function_str = f"Function: {function['name']}\n"
|
||||||
|
function_str += f"Description: {function['description']}\n"
|
||||||
|
function_str += "Parameters:\n"
|
||||||
|
|
||||||
|
for param, details in function["parameters"]["properties"].items():
|
||||||
|
function_str += f" {param} ({details['type']}): {details.get('description', '')}\n"
|
||||||
|
|
||||||
|
return function_str
|
||||||
|
|
||||||
|
|
||||||
|
def functions_to_str(functions: list[dict[str, Any]]) -> str:
|
||||||
|
"""
|
||||||
|
Convert a list of function dictionaries to a string representation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
functions (list[dict[str, Any]]): The list of function dictionaries to convert.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The string representation of the functions.
|
||||||
|
|
||||||
|
"""
|
||||||
|
functions_str = ""
|
||||||
|
for function in functions:
|
||||||
|
functions_str += function_to_str(function) + "\n"
|
||||||
|
|
||||||
|
return functions_str
|
@ -0,0 +1,9 @@
|
|||||||
|
from swarms.tools.prebuilt.code_interpreter import (
|
||||||
|
SubprocessCodeInterpreter,
|
||||||
|
)
|
||||||
|
from swarms.tools.prebuilt.math_eval import math_eval
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"SubprocessCodeInterpreter",
|
||||||
|
"math_eval",
|
||||||
|
]
|
@ -1,8 +0,0 @@
|
|||||||
from langchain.tools import (
|
|
||||||
BaseTool,
|
|
||||||
Tool,
|
|
||||||
StructuredTool,
|
|
||||||
tool,
|
|
||||||
) # noqa F401
|
|
||||||
|
|
||||||
__all__ = ["BaseTool", "Tool", "StructuredTool", "tool"]
|
|
Loading…
Reference in new issue