From 670ce0500d9f8e3c6444dadf4da5c39a149ee708 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 18:41:45 +1100 Subject: [PATCH 01/11] Update crewai-autocrew.py --- crewai-autocrew.py | 152 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 25 deletions(-) diff --git a/crewai-autocrew.py b/crewai-autocrew.py index f0e7099..6d18385 100644 --- a/crewai-autocrew.py +++ b/crewai-autocrew.py @@ -11,7 +11,7 @@ from crewai import Agent, Task, Crew, Process # Autocrew version -autocrew_version = "1.0.4" +autocrew_version = "1.0.4.9" # Initialize Ollama def initialize_ollama(model='openhermes'): @@ -19,7 +19,6 @@ def initialize_ollama(model='openhermes'): # Get agent data from Ollama def get_agent_data(ollama, overall_goal, delimiter): - print("Autocrew: Sending request to LLM...") instruction = ( f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' f'Use the delimiter "{delimiter}" to separate the fields. ' @@ -28,8 +27,6 @@ def get_agent_data(ollama, overall_goal, delimiter): 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' ) response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) - print("\nOllama's CSV Output:") - print(response) return response # Save Ollama's CSV output to a file @@ -39,14 +36,13 @@ def save_csv_output(response, overall_goal, index): file_path = os.path.join(os.getcwd(), file_name) with open(file_path, 'w') as file: file.write(response) - print(f'\nOllama\'s CSV output saved as {file_path}') + return file_path # Parse CSV data from Ollama's response -def parse_csv_data(response, delimiter=','): - header = ['role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] agents_data = [] - # Use the csv module to handle parsing csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) lines = list(csv_data) @@ -62,6 +58,7 @@ def parse_csv_data(response, delimiter=','): agent_data[header_name] = value.strip('"') if 'role' not in agent_data or not agent_data['role']: raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data agents_data.append(agent_data) return agents_data @@ -90,11 +87,10 @@ def define_task(agent): ')\n\n') # Write the CrewAI script based on the agent and task data -def write_crewai_script(agents_data, crew_tasks, file_name, ollama_openhermes, search_tool): +def write_crewai_script(agents_data, crew_tasks, file_name): crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) with open(file_name, 'w') as file: - # Writing imports and initializations file.write( 'import os\n' 'from langchain_community.chat_models import ChatOpenAI\n' @@ -144,6 +140,60 @@ def check_latest_version(): print(f'Error checking the latest version: {e}') return None +# Rank the crews based on their likelihood of success +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + ranked_crew = ollama.invoke(concatenated_csv_data) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + # Main function def main(): print() @@ -157,31 +207,63 @@ def main(): print() parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') - group = parser.add_mutually_exclusive_group() - group.add_argument('-a', '--autorun', action='store_true', help='Run the generated script automatically at the end') - group.add_argument('-m', '--multiple', type=int, metavar='NUM_SCRIPTS', help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') args = parser.parse_args() - if args.autorun and args.multiple: - parser.error("The options -a/--autorun and -m/--multiple cannot be used together. Please choose one or the other.") + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) - overall_goal = args.overall_goal - if not overall_goal: + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal - num_scripts = args.multiple or 1 + num_scripts = 1 try: - ollama = initialize_ollama() delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script response = get_agent_data(ollama, overall_goal, delimiter) if not response: raise ValueError('No response from Ollama') - save_csv_output(response, overall_goal, i+1) + file_path = save_csv_output(response, overall_goal, i+1) - agents_data = parse_csv_data(response, delimiter) + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function if not agents_data: raise ValueError('No agent data parsed') @@ -192,13 +274,33 @@ def main(): crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) - write_crewai_script(agents_data, crew_tasks, crewai_script_path, ollama, DuckDuckGoSearchRun()) + write_crewai_script(agents_data, crew_tasks, crewai_script_path) print(f'\nScript {i+1} written to {crewai_script_path}') - if args.autorun: - print('\nAutocrew: Running the generated CrewAI script...') - os.system(f'python3 {crewai_script_path}') + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) except Exception as e: print(f'Error: {e}') From d6d2ba2b66ae3a75eb07a2fd8584ad5ead7721c8 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 19:47:55 +1100 Subject: [PATCH 02/11] Adding -m function to the rest --- crewai-autocrew.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crewai-autocrew.py b/crewai-autocrew.py index 6d18385..4305e06 100644 --- a/crewai-autocrew.py +++ b/crewai-autocrew.py @@ -11,7 +11,7 @@ from crewai import Agent, Task, Crew, Process # Autocrew version -autocrew_version = "1.0.4.9" +autocrew_version = "1.0.4" # Initialize Ollama def initialize_ollama(model='openhermes'): @@ -74,7 +74,7 @@ def define_agent(agent, search_tool): ' verbose=True,\n' f' allow_delegation={delegation},\n' ' llm=ollama_openhermes,\n' - ' tools=[search_tool]\n' + f' tools=[{search_tool}]\n' ')\n\n') # Define a task for the CrewAI script @@ -103,7 +103,7 @@ def write_crewai_script(agents_data, crew_tasks, file_name): ) for agent in agents_data: - file.write(define_agent(agent, search_tool)) + file.write(define_agent(agent, "search_tool")) file.write('\n') for agent in agents_data: @@ -208,6 +208,7 @@ def main(): parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', action='store_true', help='Create multiple CrewAI scripts for the same overall goal') args = parser.parse_args() if args.ranking: @@ -251,6 +252,8 @@ def main(): overall_goal = args.overall_goal num_scripts = 1 + if args.multiple: + num_scripts = int(input('\033[1mPlease enter the number of different CrewAI scripts to create:\033[0m ')) try: delimiter = ',' From e2042cb0a45c9303db818515ef927ebbccdf8335 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 21:53:45 +1100 Subject: [PATCH 03/11] Create arm-working-328lines.py --- arm-working-328lines.py | 327 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 arm-working-328lines.py diff --git a/arm-working-328lines.py b/arm-working-328lines.py new file mode 100644 index 0000000..e5ac877 --- /dev/null +++ b/arm-working-328lines.py @@ -0,0 +1,327 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '_') + role_value = agent['role'].replace('"', '\"') + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{agent["backstory"]}",\n' + ' verbose=True,\n' + f' allow_delegation={delegation},\n' + ' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def define_task(agent): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '') + return ( + f'task{role_var} = Task(\n' + f' description="{agent["assigned_task"].strip()}",\n' + f' agent={role_var},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '').replace('-', '').replace('.', '_') for agent in agents_data]) + + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + ranked_crew = ollama.invoke(concatenated_csv_data) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', action='store_true', help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + num_scripts = 1 + if args.multiple: + num_scripts = int(input('\033[1mPlease enter the number of different CrewAI scripts to create:\033[0m ')) + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From d66ef99763b525cfb8c97064d6a884f24db973d0 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 22:01:56 +1100 Subject: [PATCH 04/11] Create arm(n)-working-332lines.py --- arm(n)-working-332lines.py | 332 +++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 arm(n)-working-332lines.py diff --git a/arm(n)-working-332lines.py b/arm(n)-working-332lines.py new file mode 100644 index 0000000..145f65d --- /dev/null +++ b/arm(n)-working-332lines.py @@ -0,0 +1,332 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '_') + role_value = agent['role'].replace('"', '\"') + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{agent["backstory"]}",\n' + ' verbose=True,\n' + f' allow_delegation={delegation},\n' + ' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def define_task(agent): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '') + return ( + f'task{role_var} = Task(\n' + f' description="{agent["assigned_task"].strip()}",\n' + f' agent={role_var},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '').replace('-', '').replace('.', '_') for agent in agents_data]) + + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + ranked_crew = ollama.invoke(concatenated_csv_data) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', type=int, help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() + + +if __name__ == '__main__': + main() From 3c69241577762ba603125f3df34e0ef03091b899 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 22:21:45 +1100 Subject: [PATCH 05/11] Create arm(n)-working-R-prompt-present.py --- arm(n)-working-R-prompt-present.py | 339 +++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 arm(n)-working-R-prompt-present.py diff --git a/arm(n)-working-R-prompt-present.py b/arm(n)-working-R-prompt-present.py new file mode 100644 index 0000000..bdbef26 --- /dev/null +++ b/arm(n)-working-R-prompt-present.py @@ -0,0 +1,339 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '_') + role_value = agent['role'].replace('"', '\"') + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{agent["backstory"]}",\n' + ' verbose=True,\n' + f' allow_delegation={delegation},\n' + ' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def define_task(agent): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '') + return ( + f'task{role_var} = Task(\n' + f' description="{agent["assigned_task"].strip()}",\n' + f' agent={role_var},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '').replace('-', '').replace('.', '_') for agent in agents_data]) + + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', type=int, help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From 422a773dd7ce7764513be7b73ee6ba063dd35893 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 22:28:54 +1100 Subject: [PATCH 06/11] Create arm(n)-working-339-debugging.py --- arm(n)-working-339-debugging.py | 339 ++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 arm(n)-working-339-debugging.py diff --git a/arm(n)-working-339-debugging.py b/arm(n)-working-339-debugging.py new file mode 100644 index 0000000..01d15d2 --- /dev/null +++ b/arm(n)-working-339-debugging.py @@ -0,0 +1,339 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '_') + role_value = agent['role'].replace('"', '\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{agent["backstory"]}",\n' + ' verbose=True,\n' + f' allow_delegation={delegation},\n' + ' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def define_task(agent): + role_var = agent['role'].replace(' ', '').replace('-', '').replace('.', '') + return ( + f'task{role_var} = Task(\n' + f' description="{agent["assigned_task"].strip()}",\n' + f' agent={role_var},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '').replace('-', '').replace('.', '_') for agent in agents_data]) + + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', type=int, help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From 8158725253ee2c926795c2a59b9aaa5fe2e8b829 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Tue, 16 Jan 2024 23:27:44 +1100 Subject: [PATCH 07/11] Create 1.0.4.1 --- 1.0.4.1 | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 1.0.4.1 diff --git a/1.0.4.1 b/1.0.4.1 new file mode 100644 index 0000000..468f8db --- /dev/null +++ b/1.0.4.1 @@ -0,0 +1,346 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') + role_value = agent['role'].replace('"', '\\"').replace("'", "\\'") + backstory = agent['backstory'].replace('"', '\\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{backstory}",\n' + f' verbose=True,\n' + f' allow_delegation={delegation},\n' + f' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def get_task_var_name(role): + return f'task_{role.replace(" ", "_").replace("-", "_").replace(".", "_")}' + + +def define_task(agent): + task_var = get_task_var_name(agent['role']) + + # Escape double quotes in assigned_task if needed + task_description = agent["assigned_task"].strip().replace('"', '\\"') + + return ( + f'{task_var} = Task(\n' + f' description="{task_description}",\n' + f' agent={agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + +def rank_crews(csv_file_paths): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', type=int, help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + overall_goal = args.overall_goal[:50].replace(' ', '-') + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {args.overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From 532c0851f861dfdef6dca85cc44682c7079affb7 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Wed, 17 Jan 2024 00:00:16 +1100 Subject: [PATCH 08/11] Create 1.0.4.2 --- 1.0.4.2 | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 1.0.4.2 diff --git a/1.0.4.2 b/1.0.4.2 new file mode 100644 index 0000000..41ec79d --- /dev/null +++ b/1.0.4.2 @@ -0,0 +1,360 @@ +import csv +import io +import os +import traceback +import sys +from datetime import datetime +import argparse +import requests +from packaging import version +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from crewai import Agent, Task, Crew, Process + +# Autocrew version +autocrew_version = "1.0.4.2" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') + role_value = agent['role'].replace('"', '\\"').replace("'", "\\'") + backstory = agent['backstory'].replace('"', '\\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{backstory}",\n' + f' verbose=True,\n' + f' allow_delegation={delegation},\n' + f' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def get_task_var_name(role): + return f'task_{role.replace(" ", "_").replace("-", "_").replace(".", "_")}' + + +def define_task(agent): + task_var = get_task_var_name(agent['role']) + + # Escape double quotes in assigned_task if needed + task_description = agent["assigned_task"].strip().replace('"', '\\"') + + return ( + f'{task_var} = Task(\n' + f' description="{task_description}",\n' + f' agent={agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + +def rank_crews(csv_file_paths, overall_goal): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files') + parser.add_argument('-m', '--multiple', type=int, help='Create multiple CrewAI scripts for the same overall goal') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + if args.overall_goal: + overall_goal = args.overall_goal + else: + overall_goal = input('Please specify the overall goal: ') + + + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + # ... [Rest of the code for processing the ranking] ... + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal.replace('-', '_') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From 42c721fcc36e2f5ef8d1961136750025b705ff29 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Wed, 17 Jan 2024 00:31:44 +1100 Subject: [PATCH 09/11] Create 1.0.5 --- 1.0.5 | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 1.0.5 diff --git a/1.0.5 b/1.0.5 new file mode 100644 index 0000000..e75f436 --- /dev/null +++ b/1.0.5 @@ -0,0 +1,334 @@ +import argparse +import csv +import io +import os +import sys +import traceback +from datetime import datetime + +import requests +from crewai import Agent, Crew, Process, Task +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from packaging import version + +# Autocrew version +autocrew_version = "1.0.5" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') + role_value = agent['role'].replace('"', '\\"').replace("'", "\\'") + backstory = agent['backstory'].replace('"', '\\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{backstory}",\n' + f' verbose=True,\n' + f' allow_delegation={delegation},\n' + f' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def get_task_var_name(role): + return f'task_{role.replace(" ", "_").replace("-", "_").replace(".", "_")}' + + +def define_task(agent): + task_var = get_task_var_name(agent['role']) + + # Escape double quotes in assigned_task if needed + task_description = agent["assigned_task"].strip().replace('"', '\\"') + + return ( + f'{task_var} = Task(\n' + f' description="{task_description}",\n' + f' agent={agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths, overall_goal): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + parser.add_argument('-m', '--multiple', type=int, metavar='NUM', help='Create NUM number of CrewAI scripts for the same overall goal. Example: -m 3') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files --> currently EXPERIMENTAL') + + + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + if args.overall_goal: + overall_goal = args.overall_goal + else: + overall_goal = input('Please specify the overall goal: ') + + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + # ... [Rest of the code for processing the ranking] ... + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + +if __name__ == '__main__': + main() From 51ee05f6718bec7865cb4c0cd5561150299e2a34 Mon Sep 17 00:00:00 2001 From: yanniedog Date: Wed, 17 Jan 2024 15:48:21 +1100 Subject: [PATCH 10/11] Initial sync from GH desktop --- .gitignore | 3 + crewai-autocrew.py | 156 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a1f3a3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.csv +Inactive/*.* +crewai-autocrew-202*.* \ No newline at end of file diff --git a/crewai-autocrew.py b/crewai-autocrew.py index 4305e06..3f814c6 100644 --- a/crewai-autocrew.py +++ b/crewai-autocrew.py @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream import csv import io import os @@ -18,6 +19,30 @@ def initialize_ollama(model='openhermes'): return Ollama(model=model, verbose=True) # Get agent data from Ollama +======= +import argparse +import csv +import io +import os +import sys +import traceback +from datetime import datetime + +import requests +from crewai import Agent, Crew, Process, Task +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from packaging import version + +# Autocrew version +autocrew_version = "1.1.1" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +>>>>>>> Stashed changes def get_agent_data(ollama, overall_goal, delimiter): instruction = ( f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' @@ -29,7 +54,11 @@ def get_agent_data(ollama, overall_goal, delimiter): response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) return response +<<<<<<< Updated upstream # Save Ollama's CSV output to a file +======= + +>>>>>>> Stashed changes def save_csv_output(response, overall_goal, index): timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' @@ -38,7 +67,11 @@ def save_csv_output(response, overall_goal, index): file.write(response) return file_path +<<<<<<< Updated upstream # Parse CSV data from Ollama's response +======= + +>>>>>>> Stashed changes def parse_csv_data(response, delimiter=',', filename=''): header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] agents_data = [] @@ -62,6 +95,7 @@ def parse_csv_data(response, delimiter=',', filename=''): agents_data.append(agent_data) return agents_data +<<<<<<< Updated upstream # Define an agent for the CrewAI script def define_agent(agent, search_tool): role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') @@ -90,6 +124,48 @@ def define_task(agent): def write_crewai_script(agents_data, crew_tasks, file_name): crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) +======= + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') + role_value = agent['role'].replace('"', '\\"').replace("'", "\\'") + backstory = agent['backstory'].replace('"', '\\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{backstory}",\n' + f' verbose=True,\n' + f' allow_delegation={delegation},\n' + f' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def get_task_var_name(role): + return f'task_{role.replace(" ", "_").replace("-", "_").replace(".", "_")}' + + +def define_task(agent): + task_var = get_task_var_name(agent['role']) + + # Escape double quotes in assigned_task if needed + task_description = agent["assigned_task"].strip().replace('"', '\\"') + + return ( + f'{task_var} = Task(\n' + f' description="{task_description}",\n' + f' agent={agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) +>>>>>>> Stashed changes with open(file_name, 'w') as file: file.write( 'import os\n' @@ -122,7 +198,11 @@ def write_crewai_script(agents_data, crew_tasks, file_name): '# Handle the "result" as needed\n' ) +<<<<<<< Updated upstream # Check the latest version of the script on GitHub +======= + +>>>>>>> Stashed changes def check_latest_version(): try: response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') @@ -140,8 +220,13 @@ def check_latest_version(): print(f'Error checking the latest version: {e}') return None +<<<<<<< Updated upstream # Rank the crews based on their likelihood of success def rank_crews(csv_file_paths): +======= + +def rank_crews(csv_file_paths, overall_goal): +>>>>>>> Stashed changes ranked_crews = [] overall_summary = "" @@ -172,7 +257,21 @@ def rank_crews(csv_file_paths): print('\nConcatenated CSV Data:') print(concatenated_csv_data) +<<<<<<< Updated upstream ranked_crew = ollama.invoke(concatenated_csv_data) +======= + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) +>>>>>>> Stashed changes print('\nOllama Ranking:') print(ranked_crew) @@ -194,7 +293,11 @@ def rank_crews(csv_file_paths): return ranked_crews, overall_summary +<<<<<<< Updated upstream # Main function +======= + +>>>>>>> Stashed changes def main(): print() print(f"Autocrew (v{autocrew_version}) for CrewAI ") @@ -203,6 +306,7 @@ def main(): if latest_version and latest_version != autocrew_version: print(f'\n\033[1mNew version available: {latest_version}\033[0m') +<<<<<<< Updated upstream print("\nTo see the available command line parameters, type: python crewai-autocrew.py -h") print() parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') @@ -240,6 +344,36 @@ def main(): ollama = initialize_ollama() ollama.invoke(overall_summary) +======= + print("\nTo see the available command line parameters, type: python3 crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + parser.add_argument('-m', '--multiple', type=int, metavar='NUM', help='Create NUM number of CrewAI scripts for the same overall goal. Example: -m 3') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files --> currently EXPERIMENTAL') + + + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + if args.overall_goal: + overall_goal = args.overall_goal + else: + overall_goal = input('Please specify the overall goal: ') + + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + # ... [Rest of the code for processing the ranking] ... +>>>>>>> Stashed changes except Exception as e: print(f'Error: {e}') traceback.print_exc() @@ -251,9 +385,16 @@ def main(): else: overall_goal = args.overall_goal +<<<<<<< Updated upstream num_scripts = 1 if args.multiple: num_scripts = int(input('\033[1mPlease enter the number of different CrewAI scripts to create:\033[0m ')) +======= + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 +>>>>>>> Stashed changes try: delimiter = ',' @@ -283,8 +424,17 @@ def main(): csv_file_paths.append(file_path) # Add the CSV file path to the list +<<<<<<< Updated upstream if num_scripts > 1: ranked_crews, overall_summary = rank_crews(csv_file_paths) +======= + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) +>>>>>>> Stashed changes timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") overall_goal_filename = overall_goal[:50].replace(' ', '-') @@ -309,5 +459,11 @@ def main(): print(f'Error: {e}') traceback.print_exc() +<<<<<<< Updated upstream +if __name__ == '__main__': + main() +======= + if __name__ == '__main__': main() +>>>>>>> Stashed changes From f0e5405189c2e18f37ee8c1cedb14e4013c6cd8c Mon Sep 17 00:00:00 2001 From: yanniedog Date: Wed, 17 Jan 2024 16:10:53 +1100 Subject: [PATCH 11/11] commit --- README.md | 102 ++++++++++++++ crewai-autocrew.py | 337 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 + 3 files changed, 443 insertions(+) create mode 100644 requirements.txt diff --git a/README.md b/README.md index 91eecc5..b3a174d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream # Autocrew for CrewAI This script automates the process of creating a CrewAI team with agents, tasks, and tools, using the Ollama language model to generate the required data in CSV format. The script then parses the CSV data, defines agents and tasks, and writes a CrewAI script that can be executed to run the generated team. @@ -74,3 +75,104 @@ You can modify the script to use different models, tools, or processes for the C ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. +======= +# CrewAI AutoCrew Script + +## Introduction +Welcome to the CrewAI AutoCrew Script, an innovative Python tool designed to automate the creation and evaluation of virtual agent teams. Integrating with Ollama for AI-driven decision-making, this script streamlines processes within the CrewAI framework, making it an indispensable resource for developers and researchers in AI and machine learning. + +## Table of Contents +- [Introduction](#introduction) +- [Features](#features) +- [Prerequisites](#prerequisites) +- [Installation](#installation) +- [Usage](#usage) +- [Examples](#examples) +- [Troubleshooting](#troubleshooting) +- [FAQ](#faq) +- [Contributing](#contributing) +- [License](#license) +- [Acknowledgments](#acknowledgments) +- [Versioning and Updates](#versioning-and-updates) + +## Features +- **Agent Team Creation**: Automates generation of agent teams with specified roles and tasks. +- **Integration with Ollama and CrewAI**: Leverages Ollama for decision-making and CrewAI for agent management. +- **CSV Data Management**: Facilitates agent data handling in CSV format. +- **Multiple Script Generation**: Supports creation of various scripts for different objectives. +- **Team Ranking Functionality**: Evaluates and ranks agent teams based on effectiveness and goal alignment. + +## Prerequisites +- Python 3.x +- OpenAI API key (for Ollama interactions) +- Basic knowledge of Python and command-line operations. + +## Installation +1. Clone the repository to your local machine. +2. Install Python 3.x if not already installed: [Python Installation Guide](https://www.python.org/downloads/). +3. Obtain an OpenAI API key from [OpenAI](https://openai.com/). +4. Install necessary dependencies: + ``` + pip install -r requirements.txt + ``` + +## Usage +Execute the script in a terminal as follows: +``` +python3 crewai-autocrew.py [options] "overall_goal" +``` + +### Options +- `"overall_goal"`: Main objective for the agent crew (in quotes). +- `-a`: Automatically run the generated script. +- `-m[NUM]`: Create multiple crews for the same goal. Replace `[NUM]` with the number required. +- `-r`: (*experimental*): Rank crews generated with the "-m" option. + +## Examples +### Basic Command +``` +python3 crewai-autocrew.py "create a smartphone app with a Voice Chatbot for scam calls" +``` + +### Automatic Execution +``` +python3 crewai-autocrew.py "Summarise the latest tech news" -a +``` + +### Multiple Scripts +``` +python3 crewai-autocrew.py "Develop a handheld quantum computer" -m3 +``` + +### Ranking Crews +``` +python3 crewai-autocrew.py "Environmental Cleanup" -r +``` + +## Troubleshooting +For common issues, refer to the [Troubleshooting Guide](Troubleshooting.md). + +## FAQ +Answers to frequently asked questions can be found in the [FAQ section](FAQ.md). + +## Contributing +Contributions are welcome. Please fork the repository and submit pull requests for enhancements. + +## License +This project is under the MIT License - see the [LICENSE](LICENSE) file for details. + +## Acknowledgments +Special thanks to all contributors and users of the CrewAI community. + +## Versioning and Updates +Regular updates are made to this script. Check the [Releases](https://github.com/yourrepository/crewai-autocrew/releases) page for the latest version. + +--- + +**Disclaimer**: This script is updated regularly. Ensure you're using the latest version for optimal functionality. + +--- +``` + +Please make sure to add the correct link to the CrewAI GitHub repository and any other specific links you wish to include in the README. +>>>>>>> Stashed changes diff --git a/crewai-autocrew.py b/crewai-autocrew.py index 3f814c6..e560e9d 100644 --- a/crewai-autocrew.py +++ b/crewai-autocrew.py @@ -1,4 +1,5 @@ <<<<<<< Updated upstream +<<<<<<< Updated upstream import csv import io import os @@ -464,6 +465,342 @@ def main(): main() ======= +if __name__ == '__main__': + main() +>>>>>>> Stashed changes +======= +import argparse +import csv +import io +import os +import sys +import traceback +from datetime import datetime + +import requests +from crewai import Agent, Crew, Process, Task +from langchain_community.llms import Ollama +from langchain_community.tools import DuckDuckGoSearchRun +from packaging import version + +# Autocrew version +autocrew_version = "1.1.1" + + +def initialize_ollama(model='openhermes'): + return Ollama(model=model, verbose=True) + + +def get_agent_data(ollama, overall_goal, delimiter): + instruction = ( + f'Create a dataset in a CSV format with each field enclosed in double quotes, for a team of agents with the goal: "{overall_goal}". ' + f'Use the delimiter "{delimiter}" to separate the fields. ' + 'Include columns "role", "goal", "backstory", "assigned_task", "allow_delegation". ' + 'Each agent\'s details should be in quotes to avoid confusion with the delimiter. ' + 'Provide a single-word role, specific goal, brief backstory, assigned task, and delegation ability (True/False) for each agent.' + ) + response = ollama.invoke(instruction.format(overall_goal=overall_goal, delimiter=delimiter)) + return response + + +def save_csv_output(response, overall_goal, index): + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + file_name = f'crewai-autocrew-{timestamp}-{overall_goal[:40].replace(" ", "-")}-{index}.csv' + file_path = os.path.join(os.getcwd(), file_name) + with open(file_path, 'w') as file: + file.write(response) + return file_path + + +def parse_csv_data(response, delimiter=',', filename=''): + header = ['filename', 'role', 'goal', 'backstory', 'assigned_task', 'allow_delegation'] + agents_data = [] + + csv_data = csv.reader(io.StringIO(response), delimiter=delimiter) + lines = list(csv_data) + + header_line = lines[0] + header_mapping = {h.lower(): h for h in header} + header_indices = [header_mapping.get(h.lower()) for h in header_line] + + for line in lines[1:]: + agent_data = {} + for i, value in enumerate(line): + header_name = header_indices[i] + if header_name: + agent_data[header_name] = value.strip('"') + if 'role' not in agent_data or not agent_data['role']: + raise ValueError('Role component missing in CSV data') + agent_data['filename'] = filename # Add the filename to the agent data + agents_data.append(agent_data) + return agents_data + + +def define_agent(agent, search_tool): + role_var = agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') + role_value = agent['role'].replace('"', '\\"').replace("'", "\\'") + backstory = agent['backstory'].replace('"', '\\"').replace("'", "\\'") + delegation = 'True' if agent['allow_delegation'] == 'True' else 'False' + return ( + f'{role_var} = Agent(\n' + f' role="{role_value}",\n' + f' goal="{agent["goal"]}",\n' + f' backstory="{backstory}",\n' + f' verbose=True,\n' + f' allow_delegation={delegation},\n' + f' llm=ollama_openhermes,\n' + f' tools=[{search_tool}]\n' + ')\n\n' + ) + + +def get_task_var_name(role): + return f'task_{role.replace(" ", "_").replace("-", "_").replace(".", "_")}' + + +def define_task(agent): + task_var = get_task_var_name(agent['role']) + + # Escape double quotes in assigned_task if needed + task_description = agent["assigned_task"].strip().replace('"', '\\"') + + return ( + f'{task_var} = Task(\n' + f' description="{task_description}",\n' + f' agent={agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")},\n' + ' verbose=True,\n' + ')\n\n' + ) + + +def write_crewai_script(agents_data, crew_tasks, file_name): + crew_agents = ', '.join([agent['role'].replace(' ', '_').replace('-', '_').replace('.', '_') for agent in agents_data]) + with open(file_name, 'w') as file: + file.write( + 'import os\n' + 'from langchain_community.chat_models import ChatOpenAI\n' + 'from langchain_community.llms import Ollama\n' + 'from langchain_community.tools import DuckDuckGoSearchRun\n' + 'from crewai import Agent, Task, Crew, Process\n\n' + 'os.environ["OPENAI_API_KEY"] = "your_OPENAI_api_key_here"\n\n' + 'ollama_openhermes = Ollama(model="openhermes")\n' + 'search_tool = DuckDuckGoSearchRun()\n\n' + ) + + for agent in agents_data: + file.write(define_agent(agent, "search_tool")) + file.write('\n') + + for agent in agents_data: + file.write(define_task(agent)) + file.write('\n') + + file.write( + 'crew = Crew(\n' + f' agents=[{crew_agents}],\n' + f' tasks=[{crew_tasks}],\n' + ' verbose=True,\n' + ' process=Process.sequential,\n' + ')\n\n' + '# Kickoff the crew tasks\n' + 'result = crew.kickoff()\n\n' + '# Handle the "result" as needed\n' + ) + + +def check_latest_version(): + try: + response = requests.get('https://raw.githubusercontent.com/yanniedog/crewai-autocrew/main/crewai-autocrew.py') + response.raise_for_status() + script_content = response.text + version_line = next(line for line in script_content.split('\n') if line.startswith('autocrew_version = ')) + latest_version = version_line.split('=')[1].strip().strip('"') + + if version.parse(latest_version) > version.parse(autocrew_version): + return latest_version + else: + return None + + except Exception as e: + print(f'Error checking the latest version: {e}') + return None + + +def rank_crews(csv_file_paths, overall_goal): + ranked_crews = [] + overall_summary = "" + + ollama = initialize_ollama() # Initialize Ollama once + + csv_file_paths = list(set(csv_file_paths)) # Remove duplicate file paths + + print('Invoking Ollama...') + + concatenated_csv_data = 'filename,role,goal,backstory,assigned_task,allow_delegation\n' # Initialize the concatenated CSV data string + + for file_path in csv_file_paths: + if "ranking" in file_path.lower(): + continue # Skip processing if the filename contains "ranking" + + print(f'\nProcessing CSV: {file_path}') + + with open(file_path, 'r') as file: + csv_data = file.read() + + filename = os.path.basename(file_path) # Get the filename of the original CSV + + # Append the filename to each row in the CSV data + csv_data_with_filename = '\n'.join([f'{filename},{row}' for row in csv_data.strip().split('\n')]) + + concatenated_csv_data += csv_data_with_filename + '\n' # Append the CSV data to the concatenated CSV + + print('\nConcatenated CSV Data:') + print(concatenated_csv_data) + + # Updated prompt for Ollama + prompt = ( + f'From a list of crews, you need to provide identify which crew is most likely to successfully complete the task: {overall_goal}. ' + f'Each crew contains agents and tasks. The list of all agents is here: {concatenated_csv_data}. ' + f'In this list, the information in the filename column is the crew name. ' + f'I want you to return a CSV with the following columns: crewname, rank, explanation, recommendation. ' + f'In rank, assign 1 to your preferred crew. In explanation, explain why you assigned this rank to this particular crew. ' + f'In recommendation, outline changes that would further improve the performance of this crew.' + ) + + ranked_crew = ollama.invoke(prompt) + print('\nOllama Ranking:') + print(ranked_crew) + + critique = ranked_crew # Use the ranked_crew output as the critique + print('\nOllama Critique:') + print(critique) + + ranked_crews.append((csv_file_paths, ranked_crew, critique)) + overall_summary += f'\n\nCrews in the following CSV files:\n' + for file_path in csv_file_paths: + overall_summary += f'{file_path}\n' + overall_summary += f'Ranking: {ranked_crew}\n' + overall_summary += f'Critique: {critique}\n' + + overall_summary += f'\nOverall Summary:\n' + overall_summary += f'Ollama has ranked the crews based on their likelihood of success.\n' + overall_summary += f'It has provided a critique for each crew, highlighting their strengths and weaknesses.\n' + overall_summary += f'The ranking and critique can be used to make informed decisions about the crews.\n' + + return ranked_crews, overall_summary + + +def main(): + print() + print(f"Autocrew (v{autocrew_version}) for CrewAI ") + + latest_version = check_latest_version() + if latest_version and latest_version != autocrew_version: + print(f'\n\033[1mNew version available: {latest_version}\033[0m') + + print("\nTo see the available command line parameters, type: python3 crewai-autocrew.py -h") + print() + parser = argparse.ArgumentParser(description='CrewAI Autocrew Script') + parser.add_argument('overall_goal', nargs='?', type=str, help='The overall goal for the crew') + parser.add_argument('-a', '--auto_run', action='store_true', help='Automatically run the generated script') + parser.add_argument('-m', '--multiple', type=int, metavar='NUM', help='Create NUM number of CrewAI scripts for the same overall goal. Example: -m 3') + parser.add_argument('-r', '--ranking', action='store_true', help='Perform ranking only based on existing CSV files --> currently EXPERIMENTAL') + + + args = parser.parse_args() + + if args.multiple and args.auto_run: + raise ValueError("The -m and -a command line parameters must not be used simultaneously") + + if args.ranking: + if args.overall_goal: + overall_goal = args.overall_goal + else: + overall_goal = input('Please specify the overall goal: ') + + csv_file_paths = [file for file in os.listdir() if file.startswith(f'crewai-autocrew-') and file.endswith('.csv') and overall_goal in file] + if not csv_file_paths: + print(f'No CSV files found for the provided overall goal: {overall_goal}') + return + + try: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + # ... [Rest of the code for processing the ranking] ... + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + return + + if args.overall_goal is None: + overall_goal = input('\033[1mPlease specify the overall goal:\033[0m ') + else: + overall_goal = args.overall_goal + + if args.multiple: + num_scripts = args.multiple + else: + num_scripts = 1 + + try: + delimiter = ',' + csv_file_paths = [] # Initialize the list of CSV file paths + for i in range(num_scripts): + ollama = initialize_ollama() # Initialize Ollama for each script + response = get_agent_data(ollama, overall_goal, delimiter) + if not response: + raise ValueError('No response from Ollama') + + file_path = save_csv_output(response, overall_goal, i+1) + + agents_data = parse_csv_data(response, delimiter, filename=file_path) # Pass the filename to the parse_csv_data function + if not agents_data: + raise ValueError('No agent data parsed') + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-{i+1}.py' + crewai_script_path = os.path.join(os.getcwd(), file_name) + + crew_tasks = ', '.join([f'task_{agent["role"].replace(" ", "_").replace("-", "_").replace(".", "_")}' for agent in agents_data]) + + write_crewai_script(agents_data, crew_tasks, crewai_script_path) + + print(f'\nScript {i+1} written to {crewai_script_path}') + + csv_file_paths.append(file_path) # Add the CSV file path to the list + + if args.auto_run: + print(f'\nRunning script {i+1}...') + os.system(f'python3 {crewai_script_path}') + + if num_scripts > 1: + ranked_crews, overall_summary = rank_crews(csv_file_paths, overall_goal) + + timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") + overall_goal_filename = overall_goal[:50].replace(' ', '-') + ranked_crews_file_name = f'crewai-autocrew-{timestamp}-{overall_goal_filename}-ranking.csv' + ranked_crews_file_path = os.path.join(os.getcwd(), ranked_crews_file_name) + + with open(ranked_crews_file_path, 'w') as file: + writer = csv.writer(file) + writer.writerow(['CSV File', 'Ranking', 'Critique']) + for crew in ranked_crews: + writer.writerow([crew[0], crew[1], crew[2]]) + + print(f'\nRanked crews saved as {ranked_crews_file_path}') + print(f'\nOverall Summary:') + print(overall_summary) + + # Provide the prompt to Ollama + ollama = initialize_ollama() + ollama.invoke(overall_summary) + + except Exception as e: + print(f'Error: {e}') + traceback.print_exc() + + if __name__ == '__main__': main() >>>>>>> Stashed changes diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3574d4f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +requests>=2.25.1 +langchain-community>=0.1.0 +crewai>=0.1.32 +packaging>=20.9