diff --git a/examples/MotleyTool for AutoGen agents.ipynb b/examples/MotleyTool for AutoGen agents.ipynb new file mode 100644 index 00000000..731b85bb --- /dev/null +++ b/examples/MotleyTool for AutoGen agents.ipynb @@ -0,0 +1,24 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/_test_single_llama_index.py b/examples/_test_single_llama_index.py index c4f9df60..80998dc0 100644 --- a/examples/_test_single_llama_index.py +++ b/examples/_test_single_llama_index.py @@ -6,7 +6,7 @@ from motleycrew import MotleyCrew from motleycrew.agents.llama_index import ReActLlamaIndexMotleyAgent from motleycrew.common.utils import configure_logging -from motleycrew.tasks import SimpleTaskRecipe +from motleycrew.tasks import SimpleTask def main(): @@ -23,7 +23,7 @@ def main(): crew = MotleyCrew() # Create tasks for your agents - task = SimpleTaskRecipe( + task = SimpleTask( crew=crew, name="produce comprehensive analysis report on AI advancements", description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. diff --git a/examples/_test_single_openai_tools_react.py b/examples/_test_single_openai_tools_react.py index 761cba62..aa3d80aa 100644 --- a/examples/_test_single_openai_tools_react.py +++ b/examples/_test_single_openai_tools_react.py @@ -5,7 +5,7 @@ from motleycrew.agents.langchain.openai_tools_react import ReactOpenAIToolsAgent from motleycrew.agents.langchain.react import ReactMotleyAgent from motleycrew.common.utils import configure_logging -from motleycrew.tasks import SimpleTaskRecipe +from motleycrew.tasks import SimpleTask from motleycrew.caching import enable_cache @@ -21,7 +21,7 @@ def main(): for r in [researcher, researcher2]: crew = MotleyCrew() - task = SimpleTaskRecipe( + task = SimpleTask( crew=crew, name="produce comprehensive analysis report on AI advancements", description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. diff --git a/examples/blog_post/blog_post.py b/examples/blog_post/blog_post.py index 97ebe403..10e59660 100644 --- a/examples/blog_post/blog_post.py +++ b/examples/blog_post/blog_post.py @@ -7,7 +7,7 @@ from motleycrew.agents.langchain.react import ReactMotleyAgent from motleycrew.tools.llm_tool import LLMTool -from motleycrew import MotleyCrew, TaskRecipe +from motleycrew import MotleyCrew, Task from .blog_post_input import text @@ -110,7 +110,7 @@ # Create tasks for your agents crew = MotleyCrew() -task1 = TaskRecipe( +task1 = Task( crew=crew, name="Write a blog post from the provided information", description=f"""Write a blog post of at most {max_words} words and at least {min_words} diff --git a/examples/delegation_crewai.py b/examples/delegation_crewai.py index 9642c296..aa5f7358 100644 --- a/examples/delegation_crewai.py +++ b/examples/delegation_crewai.py @@ -13,7 +13,7 @@ from motleycrew.agents.crewai import CrewAIMotleyAgent from motleycrew.agents.langchain.react import ReactMotleyAgent from motleycrew.common.utils import configure_logging -from motleycrew.tasks import SimpleTaskRecipe +from motleycrew.tasks import SimpleTask WORKING_DIR = Path(os.path.realpath(".")) @@ -55,7 +55,7 @@ def main(): # Create tasks for your agents - analysis_report_task = SimpleTaskRecipe( + analysis_report_task = SimpleTask( crew=crew, name="produce comprehensive analysis report on AI advancements", description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. @@ -64,7 +64,7 @@ def main(): agent=researcher, ) - literature_summary_task = SimpleTaskRecipe( + literature_summary_task = SimpleTask( crew=crew, name="provide a literature summary of recent papers on AI", description="""Conduct a comprehensive literature review of the latest advancements in AI in 2024. @@ -73,7 +73,7 @@ def main(): agent=researcher, ) - blog_post_task = SimpleTaskRecipe( + blog_post_task = SimpleTask( crew=crew, name="produce blog post on AI advancements", description="""Using the insights provided by a thorough web search, develop an engaging blog diff --git a/examples/delegation_demo.py b/examples/delegation_demo.py index 0b975ab1..cba4edfe 100644 --- a/examples/delegation_demo.py +++ b/examples/delegation_demo.py @@ -15,7 +15,7 @@ from motleycrew.agents.llama_index import ReActLlamaIndexMotleyAgent from motleycrew.tools.image_generation import DallEImageGeneratorTool from motleycrew.common.utils import configure_logging -from motleycrew.tasks import SimpleTaskRecipe +from motleycrew.tasks import SimpleTask WORKING_DIR = Path(os.path.realpath(".")) @@ -68,7 +68,7 @@ def main(): tools=[DallEImageGeneratorTool(os.path.realpath("./images"))], ) - blog_post_task = SimpleTaskRecipe( + blog_post_task = SimpleTask( crew=crew, name="produce blog post on AI advancements", description="""Using the insights provided by a thorough web search, develop an engaging blog @@ -79,7 +79,7 @@ def main(): agent=writer, ) - illustration_task = SimpleTaskRecipe( + illustration_task = SimpleTask( crew=crew, name="create an illustration for the blog post", description="""Create beautiful and insightful illustrations to accompany the blog post on AI advancements. diff --git a/examples/image_generation_crewai.py b/examples/image_generation_crewai.py index 89d3fff0..39a9435c 100644 --- a/examples/image_generation_crewai.py +++ b/examples/image_generation_crewai.py @@ -1,6 +1,6 @@ from dotenv import load_dotenv -from motleycrew import MotleyCrew, TaskRecipe +from motleycrew import MotleyCrew, Task from motleycrew.agents.crewai import CrewAIMotleyAgent from motleycrew.tools.image_generation import DallEImageGeneratorTool from motleycrew.common.utils import configure_logging diff --git a/examples/math_crewai.py b/examples/math_crewai.py index 2515b03e..bd9d4413 100644 --- a/examples/math_crewai.py +++ b/examples/math_crewai.py @@ -1,6 +1,6 @@ from dotenv import load_dotenv -from motleycrew import MotleyCrew, TaskRecipe +from motleycrew import MotleyCrew, Task from motleycrew.agents.crewai import CrewAIMotleyAgent from motleycrew.tools.python_repl import create_repl_tool from motleycrew.common.utils import configure_logging diff --git a/examples/research_agent/research_agent_main.py b/examples/research_agent/research_agent_main.py index f2ab8f06..72df7891 100644 --- a/examples/research_agent/research_agent_main.py +++ b/examples/research_agent/research_agent_main.py @@ -9,8 +9,8 @@ from motleycrew import MotleyCrew from motleycrew.storage import MotleyKuzuGraphStore from motleycrew.common.utils import configure_logging -from motleycrew.applications.research_agent.question_task_recipe import QuestionTaskRecipe -from motleycrew.applications.research_agent.answer_task_recipe import AnswerTaskRecipe +from motleycrew.applications.research_agent.question_task import QuestionTask +from motleycrew.applications.research_agent.answer_task import AnswerTask from motleycrew.tools.simple_retriever_tool import SimpleRetrieverTool @@ -42,12 +42,12 @@ def main(): graph_store = MotleyKuzuGraphStore(db) crew = MotleyCrew(graph_store=graph_store) - question_recipe = QuestionTaskRecipe( + question_task = QuestionTask( crew=crew, question=QUESTION, query_tool=query_tool, max_iter=MAX_ITER ) - answer_recipe = AnswerTaskRecipe(answer_length=ANSWER_LENGTH, crew=crew) + answer_task = AnswerTask(answer_length=ANSWER_LENGTH, crew=crew) - question_recipe >> answer_recipe + question_task >> answer_task done_tasks = crew.run() diff --git a/motleycrew/__init__.py b/motleycrew/__init__.py index 327b157a..7ab45cfb 100644 --- a/motleycrew/__init__.py +++ b/motleycrew/__init__.py @@ -1,2 +1,2 @@ from .crew import MotleyCrew -from .tasks import TaskRecipe +from .tasks import Task diff --git a/motleycrew/agents/llama_index/llama_index.py b/motleycrew/agents/llama_index/llama_index.py index 03b0d912..85cecee8 100644 --- a/motleycrew/agents/llama_index/llama_index.py +++ b/motleycrew/agents/llama_index/llama_index.py @@ -9,7 +9,7 @@ from motleycrew.agents.parent import MotleyAgentParent from motleycrew.agents.abstract_parent import MotleyAgentAbstractParent -from motleycrew.tasks import Task +from motleycrew.tasks import TaskUnit from motleycrew.common import MotleySupportedTool from motleycrew.common import MotleyAgentFactory from motleycrew.common.utils import ensure_module_is_installed diff --git a/motleycrew/applications/research_agent/answer_task_recipe.py b/motleycrew/applications/research_agent/answer_task.py similarity index 80% rename from motleycrew/applications/research_agent/answer_task_recipe.py rename to motleycrew/applications/research_agent/answer_task.py index dd171917..bac21874 100644 --- a/motleycrew/applications/research_agent/answer_task_recipe.py +++ b/motleycrew/applications/research_agent/answer_task.py @@ -4,27 +4,27 @@ from motleycrew.crew import MotleyCrew from motleycrew.tools import MotleyTool -from motleycrew.tasks import TaskRecipe -from motleycrew.tasks.task import TaskType from motleycrew.tasks import Task -from motleycrew.applications.research_agent.question import Question, QuestionAnsweringTask +from motleycrew.tasks.task_unit import TaskUnitType +from motleycrew.tasks import TaskUnit +from motleycrew.applications.research_agent.question import Question, QuestionAnsweringTaskUnit from motleycrew.applications.research_agent.question_answerer import AnswerSubQuestionTool from motleycrew.storage import MotleyGraphStore -class AnswerTaskRecipe(TaskRecipe): +class AnswerTask(Task): def __init__( self, crew: MotleyCrew, answer_length: int = 1000, ): - super().__init__("AnswerTaskRecipe", crew) + super().__init__("AnswerTask", crew) self.answer_length = answer_length self.answerer = AnswerSubQuestionTool( graph=self.graph_store, answer_length=self.answer_length ) - def get_next_task(self) -> QuestionAnsweringTask | None: + def get_next_unit(self) -> QuestionAnsweringTaskUnit | None: query = ( "MATCH (n1:{}) " "WHERE n1.answer IS NULL AND n1.context IS NOT NULL " @@ -38,7 +38,7 @@ def get_next_task(self) -> QuestionAnsweringTask | None: if not query_result: return None else: - return QuestionAnsweringTask(question=query_result[0]) + return QuestionAnsweringTaskUnit(question=query_result[0]) def get_worker(self, tools: Optional[List[MotleyTool]]) -> Runnable: return self.answerer diff --git a/motleycrew/applications/research_agent/question.py b/motleycrew/applications/research_agent/question.py index 2d649b14..8aa70c73 100644 --- a/motleycrew/applications/research_agent/question.py +++ b/motleycrew/applications/research_agent/question.py @@ -3,7 +3,7 @@ import json from motleycrew.storage.graph_node import MotleyGraphNode -from motleycrew.tasks import Task +from motleycrew.tasks import TaskUnit REPR_CONTEXT_LENGTH_LIMIT = 30 @@ -28,9 +28,9 @@ def __repr__(self): ) -class QuestionGenerationTask(Task): +class QuestionGenerationTaskUnit(TaskUnit): question: Question -class QuestionAnsweringTask(Task): +class QuestionAnsweringTaskUnit(TaskUnit): question: Question diff --git a/motleycrew/applications/research_agent/question_answerer.py b/motleycrew/applications/research_agent/question_answerer.py index 41264f44..8301fac7 100644 --- a/motleycrew/applications/research_agent/question_answerer.py +++ b/motleycrew/applications/research_agent/question_answerer.py @@ -12,7 +12,7 @@ from motleycrew.storage import MotleyGraphStore from motleycrew.common.utils import print_passthrough -from motleycrew.applications.research_agent.question import Question, QuestionAnsweringTask +from motleycrew.applications.research_agent.question import Question, QuestionAnsweringTaskUnit _default_prompt = PromptTemplate.from_template( diff --git a/motleycrew/applications/research_agent/question_generator.py b/motleycrew/applications/research_agent/question_generator.py index 961dc428..1dae75e3 100644 --- a/motleycrew/applications/research_agent/question_generator.py +++ b/motleycrew/applications/research_agent/question_generator.py @@ -20,7 +20,7 @@ from motleycrew.storage import MotleyGraphStore -from motleycrew.applications.research_agent.question import Question, QuestionGenerationTask +from motleycrew.applications.research_agent.question import Question, QuestionGenerationTaskUnit IS_SUBQUESTION_PREDICATE = "is_subquestion" diff --git a/motleycrew/applications/research_agent/question_task_recipe.py b/motleycrew/applications/research_agent/question_task.py similarity index 85% rename from motleycrew/applications/research_agent/question_task_recipe.py rename to motleycrew/applications/research_agent/question_task.py index f043a011..0bdaae40 100644 --- a/motleycrew/applications/research_agent/question_task_recipe.py +++ b/motleycrew/applications/research_agent/question_task.py @@ -3,23 +3,23 @@ from langchain_core.runnables import Runnable -from motleycrew.tasks import TaskRecipe -from ...tasks.task import TaskType +from motleycrew.tasks import Task +from ...tasks.task_unit import TaskUnitType from motleycrew.tools import MotleyTool from motleycrew.crew import MotleyCrew -from .question import Question, QuestionGenerationTask +from .question import Question, QuestionGenerationTaskUnit from .question_generator import QuestionGeneratorTool from .question_prioritizer import QuestionPrioritizerTool -class QuestionTaskRecipe(TaskRecipe): +class QuestionTask(Task): def __init__( self, question: str, query_tool: MotleyTool, crew: MotleyCrew, max_iter: int = 10, - name: str = "QuestionTaskRecipe", + name: str = "QuestionTask", ): # Need to supply the crew already at this stage # because need to use the graph store in constructor @@ -34,7 +34,7 @@ def __init__( query_tool=query_tool, graph=self.graph_store ) - def get_next_task(self) -> QuestionGenerationTask | None: + def get_next_unit(self) -> QuestionGenerationTaskUnit | None: if self.done: return None @@ -51,9 +51,9 @@ def get_next_task(self) -> QuestionGenerationTask | None: } ) logging.info("Most pertinent question according to the tool: %s", most_pertinent_question) - return QuestionGenerationTask(question=most_pertinent_question) + return QuestionGenerationTaskUnit(question=most_pertinent_question) - def register_completed_task(self, task: TaskType) -> None: + def register_completed_unit(self, task: TaskUnitType) -> None: logging.info("==== Completed iteration %s of %s ====", self.n_iter + 1, self.max_iter) self.n_iter += 1 if self.n_iter >= self.max_iter: diff --git a/motleycrew/common/__init__.py b/motleycrew/common/__init__.py index ef1850e1..7ef77538 100644 --- a/motleycrew/common/__init__.py +++ b/motleycrew/common/__init__.py @@ -1,7 +1,7 @@ from .enums import LLMFamily from .enums import LLMFramework from .enums import GraphStoreType -from .enums import TaskStatus +from .enums import TaskUnitStatus from .enums import LunaryRunType from .enums import LunaryEventName diff --git a/motleycrew/common/enums.py b/motleycrew/common/enums.py index 24a2d044..d02ffd7b 100644 --- a/motleycrew/common/enums.py +++ b/motleycrew/common/enums.py @@ -11,7 +11,7 @@ class GraphStoreType: KUZU = "kuzu" -class TaskStatus: +class TaskUnitStatus: PENDING = "pending" RUNNING = "running" DONE = "done" diff --git a/motleycrew/crew.py b/motleycrew/crew.py index 8aabf8ed..5a2276f0 100644 --- a/motleycrew/crew.py +++ b/motleycrew/crew.py @@ -3,7 +3,7 @@ import os from motleycrew.agents.parent import MotleyAgentParent -from motleycrew.tasks import TaskRecipe, Task, SimpleTaskRecipe +from motleycrew.tasks import Task, TaskUnit, SimpleTask from motleycrew.storage import MotleyGraphStore from motleycrew.storage.graph_store_utils import init_graph_store from motleycrew.tools import MotleyTool @@ -17,7 +17,7 @@ def __init__(self, graph_store: Optional[MotleyGraphStore] = None): self.single_thread = os.environ.get("MC_SINGLE_THREAD", False) self.tools = [] - self.task_recipes = [] + self.tasks = [] def create_simple_task( self, @@ -26,87 +26,87 @@ def create_simple_task( name: Optional[str] = None, generate_name: bool = False, tools: Optional[Sequence[MotleyTool]] = None, - ) -> SimpleTaskRecipe: + ) -> SimpleTask: """ - Basic method for creating a simple task recipe + Basic method for creating a simple task """ if name is None and generate_name: # Call llm to generate a name raise NotImplementedError("Name generation not yet implemented") - task_recipe = SimpleTaskRecipe(name=name, description=description, agent=agent, tools=tools) - self.register_task_recipes([task_recipe]) - return task_recipe + task = SimpleTask(name=name, description=description, agent=agent, tools=tools) + self.register_tasks([task]) + return task - def run(self) -> list[Task]: + def run(self) -> list[TaskUnit]: if not self.single_thread: logging.warning("Multithreading is not implemented yet, will run in single thread") return self._run_sync() - def add_dependency(self, upstream: TaskRecipe, downstream: TaskRecipe): + def add_dependency(self, upstream: Task, downstream: Task): self.graph_store.create_relation( - upstream.node, downstream.node, label=TaskRecipe.TASK_RECIPE_IS_UPSTREAM_LABEL + upstream.node, downstream.node, label=Task.TASK_IS_UPSTREAM_LABEL ) # # TODO: rollback if bad? # self.check_cyclical_dependencies() - def register_task_recipes(self, task_recipes: Collection[TaskRecipe]): - for task_recipe in task_recipes: - if task_recipe not in self.task_recipes: - self.task_recipes.append(task_recipe) - task_recipe.crew = self - self.graph_store.insert_node(task_recipe.node) + def register_tasks(self, tasks: Collection[Task]): + for task in tasks: + if task not in self.tasks: + self.tasks.append(task) + task.crew = self + self.graph_store.insert_node(task.node) self.graph_store.ensure_relation_table( - from_class=type(task_recipe.node), - to_class=type(task_recipe.node), - label=TaskRecipe.TASK_RECIPE_IS_UPSTREAM_LABEL, + from_class=type(task.node), + to_class=type(task.node), + label=Task.TASK_IS_UPSTREAM_LABEL, ) # TODO: remove this workaround, https://github.com/kuzudb/kuzu/issues/3488 - def _run_sync(self) -> list[Task]: - done_tasks = [] + def _run_sync(self) -> list[TaskUnit]: + done_units = [] while True: did_something = False - available_task_recipes = self.get_available_task_recipes() - logging.info("Available task recipes: %s", available_task_recipes) + available_tasks = self.get_available_tasks() + logging.info("Available tasks: %s", available_tasks) - for recipe in available_task_recipes: - logging.info("Processing recipe: %s", recipe) + for task in available_tasks: + logging.info("Processing task: %s", task) - next_task = recipe.get_next_task() + next_unit = task.get_next_unit() - if next_task is None: - logging.info("Got no matching tasks for recipe %s", recipe) + if next_unit is None: + logging.info("Got no matching units for task %s", task) else: - logging.info("Got a matching task for recipe %s", recipe) - current_task = next_task - logging.info("Processing task: %s", current_task) + logging.info("Got a matching unit for task %s", task) + current_unit = next_unit + logging.info("Processing task: %s", current_unit) - extra_tools = self.get_extra_tools(recipe) + extra_tools = self.get_extra_tools(task) - agent = recipe.get_worker(extra_tools) - logging.info("Assigned task %s to agent %s, dispatching", current_task, agent) - current_task.set_running() - self.graph_store.insert_node(current_task) + agent = task.get_worker(extra_tools) + logging.info("Assigned unit %s to agent %s, dispatching", current_unit, agent) + current_unit.set_running() + self.graph_store.insert_node(current_unit) # TODO: accept and handle some sort of return value? Or just the final state of the task? - result = agent.invoke(current_task.as_dict()) - current_task.output = result + result = agent.invoke(current_unit.as_dict()) + current_unit.output = result - logging.info("Task %s completed, marking as done", current_task) - current_task.set_done() - recipe.register_completed_task(current_task) - done_tasks.append(current_task) + logging.info("Task unit %s completed, marking as done", current_unit) + current_unit.set_done() + task.register_completed_unit(current_unit) + done_units.append(current_unit) did_something = True continue if not did_something: logging.info("Nothing left to do, exiting") - return done_tasks + return done_units - def get_available_task_recipes(self) -> list[TaskRecipe]: + def get_available_tasks(self) -> list[Task]: query = ( "MATCH (downstream:{}) " "WHERE NOT downstream.done " @@ -114,16 +114,12 @@ def get_available_task_recipes(self) -> list[TaskRecipe]: "WHERE NOT upstream.done}} " "RETURN downstream" ).format( - TaskRecipe.NODE_CLASS.get_label(), - TaskRecipe.NODE_CLASS.get_label(), - TaskRecipe.TASK_RECIPE_IS_UPSTREAM_LABEL, + Task.NODE_CLASS.get_label(), + Task.NODE_CLASS.get_label(), + Task.TASK_IS_UPSTREAM_LABEL, ) - available_task_recipe_nodes = self.graph_store.run_cypher_query( - query, container=TaskRecipe.NODE_CLASS - ) - return [ - recipe for recipe in self.task_recipes if recipe.node in available_task_recipe_nodes - ] + available_task_nodes = self.graph_store.run_cypher_query(query, container=Task.NODE_CLASS) + return [task for task in self.tasks if task.node in available_task_nodes] # def _run_async(self): # tasks = self.task_graph @@ -162,11 +158,11 @@ def get_available_task_recipes(self) -> list[TaskRecipe]: # self.futures.add(future) # future.mc_task = t - def get_extra_tools(self, task_recipe: TaskRecipe) -> list[MotleyTool]: + def get_extra_tools(self, task: Task) -> list[MotleyTool]: # TODO: Smart tool selection goes here tools = [] tools += self.tools or [] - # tools += task_recipe.tools or [] + # tools += task.tools or [] return tools diff --git a/motleycrew/tasks/__init__.py b/motleycrew/tasks/__init__.py index c2653744..6916196a 100644 --- a/motleycrew/tasks/__init__.py +++ b/motleycrew/tasks/__init__.py @@ -1,6 +1,6 @@ +from motleycrew.tasks.task_unit import TaskUnit +from motleycrew.tasks.task_unit import TaskUnitType from motleycrew.tasks.task import Task -from motleycrew.tasks.task import TaskType -from motleycrew.tasks.task_recipe import TaskRecipe -from motleycrew.tasks.simple import SimpleTaskRecipe +from motleycrew.tasks.simple import SimpleTask -__all__ = ["Task", "TaskType", "TaskRecipe", "SimpleTaskRecipe"] +__all__ = ["TaskUnit", "TaskUnitType", "Task", "SimpleTask"] diff --git a/motleycrew/tasks/simple.py b/motleycrew/tasks/simple.py index 4d4adc4b..19d0fff3 100644 --- a/motleycrew/tasks/simple.py +++ b/motleycrew/tasks/simple.py @@ -2,8 +2,8 @@ import logging from typing import TYPE_CHECKING, Any, Sequence, List, Optional -from motleycrew.tasks.task_recipe import TaskRecipe -from motleycrew.tasks import Task +from motleycrew.tasks.task import Task +from motleycrew.tasks import TaskUnit from motleycrew.agents.abstract_parent import MotleyAgentAbstractParent from motleycrew.tools import MotleyTool @@ -22,15 +22,15 @@ def compose_simple_task_prompt_with_dependencies( - description: str, upstream_tasks: List[Task], default_task_name: str = "Unnamed task" + description: str, upstream_task_units: List[TaskUnit], default_task_name: str = "Unnamed task" ) -> str: upstream_results = [] - for task in upstream_tasks: - if not task.output: + for unit in upstream_task_units: + if not unit.output: continue - task_name = getattr(task, "name", default_task_name) - upstream_results.append(f"##{task_name}\n" + "\n".join(str(out) for out in task.output)) + unit_name = getattr(unit, "name", default_task_name) + upstream_results.append(f"##{unit_name}\n" + "\n".join(str(out) for out in unit.output)) if not upstream_results: return description @@ -42,13 +42,13 @@ def compose_simple_task_prompt_with_dependencies( ) -class SimpleTask(Task): +class SimpleTaskUnit(TaskUnit): name: str prompt: str message_history: List[str] = [] -class SimpleTaskRecipe(TaskRecipe): +class SimpleTask(Task): def __init__( self, crew: MotleyCrew, @@ -74,29 +74,29 @@ def __init__( # This will be set by MotleyCrew.register_task self.crew = crew - self.crew.register_task_recipes([self]) + self.crew.register_tasks([self]) - def register_completed_task(self, task: SimpleTask) -> None: - assert isinstance(task, SimpleTask) + def register_completed_unit(self, task: SimpleTaskUnit) -> None: + assert isinstance(task, SimpleTaskUnit) assert task.done self.output = task.output self.set_done() - def get_next_task(self) -> SimpleTask | None: + def get_next_unit(self) -> SimpleTaskUnit | None: if self.done: logging.info("Task %s is already done", self) return None - upstream_task_recipes = self.get_upstream_task_recipes() - if not all(recipe.done for recipe in upstream_task_recipes): + upstream_tasks = self.get_upstream_tasks() + if not all(task.done for task in upstream_tasks): return None - upstream_tasks = [task for recipe in upstream_task_recipes for task in recipe.get_tasks()] + upstream_task_units = [unit for task in upstream_tasks for unit in task.get_units()] # print(upstream_tasks) - prompt = compose_simple_task_prompt_with_dependencies(self.description, upstream_tasks) + prompt = compose_simple_task_prompt_with_dependencies(self.description, upstream_task_units) # print(prompt) - return SimpleTask( + return SimpleTaskUnit( name=self.name, prompt=prompt, ) diff --git a/motleycrew/tasks/task.py b/motleycrew/tasks/task.py index 8565fe53..3a6618ab 100644 --- a/motleycrew/tasks/task.py +++ b/motleycrew/tasks/task.py @@ -1,49 +1,142 @@ from __future__ import annotations -from abc import ABC -from typing import Optional, Any, TypeVar +from abc import ABC, abstractmethod +from typing import Optional, Sequence, List, Type, TypeVar, Generic, TYPE_CHECKING -from motleycrew.common import TaskStatus -from motleycrew.storage import MotleyGraphNode +from langchain_core.runnables import Runnable +from motleycrew.common.exceptions import TaskDependencyCycleError +from motleycrew.storage import MotleyGraphStore, MotleyGraphNode +from motleycrew.tasks import TaskUnit, TaskUnitType +from motleycrew.tools import MotleyTool +if TYPE_CHECKING: + from motleycrew.crew import MotleyCrew -class Task(MotleyGraphNode, ABC): - status: str = TaskStatus.PENDING - output: Optional[Any] = None - def __repr__(self) -> str: - return f"Task(status={self.status})" +class TaskNode(MotleyGraphNode): + __label__ = "TaskNode" + name: str + done: bool = False - def __str__(self) -> str: - return self.__repr__() + def __eq__(self, other): + return self.id is not None and self.get_label() == other.get_label() and self.id == other.id - def __eq__(self, other: Task): - return self.id is not None and self.get_label() == other.get_label and self.id == other.id - @property - def pending(self): - return self.status == TaskStatus.PENDING +TaskNodeType = TypeVar("TaskNodeType", bound=TaskNode) - @property - def running(self): - return self.status == TaskStatus.RUNNING - @property - def done(self): - return self.status == TaskStatus.DONE +class Task(ABC, Generic[TaskUnitType]): + NODE_CLASS: Type[TaskNodeType] = TaskNode + TASK_UNIT_CLASS: Type[TaskUnitType] = TaskUnit + TASK_IS_UPSTREAM_LABEL = "task_is_upstream" + TASK_UNIT_BELONGS_LABEL = "task_unit_belongs" - def set_pending(self): - self.status = TaskStatus.PENDING + def __init__(self, name: str, crew: Optional[MotleyCrew] = None): + self.name = name + self.done = False + self.node = self.NODE_CLASS(name=name, done=self.done) + self.crew = crew + if crew is not None: + crew.register_tasks([self]) - def set_running(self): - self.status = TaskStatus.RUNNING - - def set_done(self): - self.status = TaskStatus.DONE + @property + def graph_store(self) -> MotleyGraphStore: + if self.crew is None: + raise ValueError("Task must be registered with a crew for accessing graph store") + return self.crew.graph_store - def as_dict(self): - """Represent the task as a dictionary for passing to invoke() methods of runnables.""" - return dict(self) + def __repr__(self) -> str: + return f"{self.__class__.__name__}(name={self.name}, done={self.done})" + def __str__(self) -> str: + return self.__repr__() -TaskType = TypeVar("TaskType", bound=Task) + def set_upstream(self, task: Task) -> Task: + if self.crew is None or task.crew is None: + raise ValueError("Both tasks must be registered with a crew") + + if task is self: + raise TaskDependencyCycleError(f"Task {self.name} can not depend on itself") + + self.crew.add_dependency(upstream=task, downstream=self) + + return self + + def __rshift__(self, other: Task | Sequence[Task]) -> Task: + if isinstance(other, Task): + tasks = {other} + else: + tasks = other + + for task in tasks: + task.set_upstream(self) + + return self + + def __rrshift__(self, other: Sequence[Task]) -> Sequence[Task]: + for task in other: + self.set_upstream(task) + return other + + def get_units(self) -> List[TaskUnitType]: + assert self.crew is not None, "Task must be registered with a crew for accessing task units" + + query = "MATCH (unit)-[{}]->(task:{}) WHERE task.id = $self_id RETURN unit".format( + self.TASK_UNIT_BELONGS_LABEL, + self.NODE_CLASS.get_label(), + ) + task_units = self.crew.graph_store.run_cypher_query( + query, parameters={"self_id": self.node.id}, container=self.TASK_UNIT_CLASS + ) + return task_units + + def get_upstream_tasks(self) -> List[Task]: + assert ( + self.crew is not None and self.node.is_inserted + ), "Task must be registered with a crew for accessing upstream tasks" + + query = ( + "MATCH (upstream)-[:{}]->(downstream:{}) " + "WHERE downstream.id = $self_id " + "RETURN upstream" + ).format( + self.TASK_IS_UPSTREAM_LABEL, + self.NODE_CLASS.get_label(), + ) + upstream_task_nodes = self.crew.graph_store.run_cypher_query( + query, parameters={"self_id": self.node.id}, container=self.NODE_CLASS + ) + return [task for task in self.crew.tasks if task.node in upstream_task_nodes] + + def get_downstream_tasks(self) -> List[Task]: + assert ( + self.crew is not None and self.node.is_inserted + ), "Task must be registered with a crew for accessing downstream tasks" + + query = ( + "MATCH (upstream:{})-[:{}]->(downstream) " + "WHERE upstream.id = $self_id " + "RETURN downstream" + ).format( + self.NODE_CLASS.get_label(), + self.TASK_IS_UPSTREAM_LABEL, + ) + downstream_task_nodes = self.crew.graph_store.run_cypher_query( + query, parameters={"self_id": self.node.id}, container=self.NODE_CLASS + ) + return [task for task in self.crew.tasks if task.node in downstream_task_nodes] + + def set_done(self, value: bool = True): + self.done = value + self.node.done = value + + def register_completed_unit(self, task: TaskUnitType) -> None: + pass + + @abstractmethod + def get_next_unit(self) -> TaskUnitType | None: + pass + + @abstractmethod + def get_worker(self, tools: Optional[List[MotleyTool]]) -> Runnable: + pass diff --git a/motleycrew/tasks/task_recipe.py b/motleycrew/tasks/task_recipe.py deleted file mode 100644 index 25668d94..00000000 --- a/motleycrew/tasks/task_recipe.py +++ /dev/null @@ -1,150 +0,0 @@ -from __future__ import annotations - -from abc import ABC, abstractmethod -from typing import Optional, Sequence, List, Type, TypeVar, Generic, TYPE_CHECKING - -from langchain_core.runnables import Runnable -from motleycrew.common.exceptions import TaskDependencyCycleError -from motleycrew.storage import MotleyGraphStore, MotleyGraphNode -from motleycrew.tasks import Task, TaskType -from motleycrew.tools import MotleyTool - -if TYPE_CHECKING: - from motleycrew.crew import MotleyCrew - - -class TaskRecipeNode(MotleyGraphNode): - __label__ = "TaskRecipeNode" - name: str - done: bool = False - - def __eq__(self, other): - return self.id is not None and self.get_label() == other.get_label() and self.id == other.id - - -TaskRecipeNodeType = TypeVar("TaskRecipeNodeType", bound=TaskRecipeNode) - - -class TaskRecipe(ABC, Generic[TaskType]): - NODE_CLASS: Type[TaskRecipeNodeType] = TaskRecipeNode - TASK_CLASS: Type[TaskType] = Task - TASK_RECIPE_IS_UPSTREAM_LABEL = "task_recipe_is_upstream" - TASK_BELONGS_LABEL = "task_belongs" - - def __init__(self, name: str, crew: Optional[MotleyCrew] = None): - self.name = name - self.done = False - self.node = self.NODE_CLASS(name=name, done=self.done) - self.crew = crew - if crew is not None: - crew.register_task_recipes([self]) - - @property - def graph_store(self) -> MotleyGraphStore: - if self.crew is None: - raise ValueError("TaskRecipe must be registered with a crew for accessing graph store") - return self.crew.graph_store - - def __repr__(self) -> str: - return f"{self.__class__.__name__}(name={self.name}, done={self.done})" - - def __str__(self) -> str: - return self.__repr__() - - def set_upstream(self, task_recipe: TaskRecipe) -> TaskRecipe: - if self.crew is None or task_recipe.crew is None: - raise ValueError("Both tasks must be registered with a crew") - - if task_recipe is self: - raise TaskDependencyCycleError(f"Task {self.name} can not depend on itself") - - self.crew.add_dependency(upstream=task_recipe, downstream=self) - - return self - - def __rshift__(self, other: TaskRecipe | Sequence[TaskRecipe]) -> TaskRecipe: - if isinstance(other, TaskRecipe): - tasks = {other} - else: - tasks = other - - for task in tasks: - task.set_upstream(self) - - return self - - def __rrshift__(self, other: Sequence[TaskRecipe]) -> Sequence[TaskRecipe]: - for task in other: - self.set_upstream(task) - return other - - def get_tasks(self) -> List[TaskType]: - assert ( - self.crew is not None - ), "TaskRecipe must be registered with a crew for accessing tasks" - - query = "MATCH (task)-[{}]->(recipe:{}) WHERE recipe.id = $self_id RETURN task".format( - self.TASK_BELONGS_LABEL, - self.NODE_CLASS.get_label(), - ) - tasks = self.crew.graph_store.run_cypher_query( - query, parameters={"self_id": self.node.id}, container=self.TASK_CLASS - ) - return tasks - - def get_upstream_task_recipes(self) -> List[TaskRecipe]: - assert ( - self.crew is not None and self.node.is_inserted - ), "TaskRecipe must be registered with a crew for accessing upstream tasks" - - query = ( - "MATCH (upstream)-[:{}]->(downstream:{}) " - "WHERE downstream.id = $self_id " - "RETURN upstream" - ).format( - self.TASK_RECIPE_IS_UPSTREAM_LABEL, - self.NODE_CLASS.get_label(), - ) - upstream_task_recipe_nodes = self.crew.graph_store.run_cypher_query( - query, parameters={"self_id": self.node.id}, container=self.NODE_CLASS - ) - return [ - recipe for recipe in self.crew.task_recipes if recipe.node in upstream_task_recipe_nodes - ] - - def get_downstream_task_recipes(self) -> List[TaskRecipe]: - assert ( - self.crew is not None and self.node.is_inserted - ), "TaskRecipe must be registered with a crew for accessing upstream tasks" - - query = ( - "MATCH (upstream:{})-[:{}]->(downstream) " - "WHERE upstream.id = $self_id " - "RETURN downstream" - ).format( - self.NODE_CLASS.get_label(), - self.TASK_RECIPE_IS_UPSTREAM_LABEL, - ) - downstream_task_recipe_nodes = self.crew.graph_store.run_cypher_query( - query, parameters={"self_id": self.node.id}, container=self.NODE_CLASS - ) - return [ - recipe - for recipe in self.crew.task_recipes - if recipe.node in downstream_task_recipe_nodes - ] - - def set_done(self, value: bool = True): - self.done = value - self.node.done = value - - def register_completed_task(self, task: TaskType) -> None: - pass - - @abstractmethod - def get_next_task(self) -> TaskType | None: - pass - - @abstractmethod - def get_worker(self, tools: Optional[List[MotleyTool]]) -> Runnable: - pass diff --git a/motleycrew/tasks/task_unit.py b/motleycrew/tasks/task_unit.py new file mode 100644 index 00000000..3f704cd1 --- /dev/null +++ b/motleycrew/tasks/task_unit.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from abc import ABC +from typing import Optional, Any, TypeVar + +from motleycrew.common import TaskUnitStatus +from motleycrew.storage import MotleyGraphNode + + +class TaskUnit(MotleyGraphNode, ABC): + status: str = TaskUnitStatus.PENDING + output: Optional[Any] = None + + def __repr__(self) -> str: + return f"TaskUnit(status={self.status})" + + def __str__(self) -> str: + return self.__repr__() + + def __eq__(self, other: TaskUnit): + return self.id is not None and self.get_label() == other.get_label and self.id == other.id + + @property + def pending(self): + return self.status == TaskUnitStatus.PENDING + + @property + def running(self): + return self.status == TaskUnitStatus.RUNNING + + @property + def done(self): + return self.status == TaskUnitStatus.DONE + + def set_pending(self): + self.status = TaskUnitStatus.PENDING + + def set_running(self): + self.status = TaskUnitStatus.RUNNING + + def set_done(self): + self.status = TaskUnitStatus.DONE + + def as_dict(self): + """Represent the task as a dictionary for passing to invoke() methods of runnables.""" + return dict(self) + + +TaskUnitType = TypeVar("TaskUnitType", bound=TaskUnit) diff --git a/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl b/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl new file mode 100644 index 00000000..91292f6f Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react_d15fe3c426f1c4b3f37c9198853e4a86e20c425ca7f4752ec0c9b0e97ca7ea4d/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl b/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react_d15fe3c426f1c4b3f37c9198853e4a86e20c425ca7f4752ec0c9b0e97ca7ea4d/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl new file mode 100644 index 00000000..12c6060b Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.hub.langchain.com/commits_hwchase17_react_d15fe3c426f1c4b3f37c9198853e4a86e20c425ca7f4752ec0c9b0e97ca7ea4d/d41d8cd98f00b204e9800998ecf8427e2373cdbd094ee29f581a554324127ac6a03108a0f70dd94aa1f1ba035d8396d3.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/2fac8d27d824f67993f09fcb41d9f8cfd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/2fac8d27d824f67993f09fcb41d9f8cfd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index 69731b0d..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/2fac8d27d824f67993f09fcb41d9f8cfd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/35875d4c36fd7b22dce04da6d4b581a1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/35875d4c36fd7b22dce04da6d4b581a1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..01b8d1eb Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/35875d4c36fd7b22dce04da6d4b581a1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3bad6b46c418bfa69ade7106608c9b1fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3bad6b46c418bfa69ade7106608c9b1fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..5629ac6d Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3bad6b46c418bfa69ade7106608c9b1fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3c6ddb54c9aa9ce455d183db36305dc7d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3c6ddb54c9aa9ce455d183db36305dc7d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index d7750167..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3c6ddb54c9aa9ce455d183db36305dc7d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3e1fbbff2036ca11baae9090c535f31fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3e1fbbff2036ca11baae9090c535f31fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index 7c9bbc21..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/3e1fbbff2036ca11baae9090c535f31fd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4a264628c775d4db62ba8ce634ffd0a2d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4a264628c775d4db62ba8ce634ffd0a2d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index 1bee0953..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4a264628c775d4db62ba8ce634ffd0a2d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4e218f52d166b5a852d1bbe1199ca0b4d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4e218f52d166b5a852d1bbe1199ca0b4d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..46ae3419 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/4e218f52d166b5a852d1bbe1199ca0b4d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/5d93be3cc6f44d6d2fdc7e56c4c87e7cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/5d93be3cc6f44d6d2fdc7e56c4c87e7cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..37fe2f91 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/5d93be3cc6f44d6d2fdc7e56c4c87e7cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/689d8f5af1d85260be2e2b638103466bd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/689d8f5af1d85260be2e2b638103466bd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..629407d5 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/689d8f5af1d85260be2e2b638103466bd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/6c4217a9787f0725f05f9719e6b170aad41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/6c4217a9787f0725f05f9719e6b170aad41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..63b49719 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/6c4217a9787f0725f05f9719e6b170aad41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/743e31bc3589127519c06726b269f601d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/743e31bc3589127519c06726b269f601d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index 31c10cf8..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/743e31bc3589127519c06726b269f601d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/77320898f688f5a89db9d509597b6c03d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/77320898f688f5a89db9d509597b6c03d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..2b308185 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/77320898f688f5a89db9d509597b6c03d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/b39ddaa72db8b64f5c85a09bb8a4e259d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/b39ddaa72db8b64f5c85a09bb8a4e259d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index 1e912087..00000000 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/b39ddaa72db8b64f5c85a09bb8a4e259d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d051cc084c585101fcccf54359433221d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d051cc084c585101fcccf54359433221d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..32bc2205 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d051cc084c585101fcccf54359433221d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d15341942c36d10a016144f42d4a59c1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d15341942c36d10a016144f42d4a59c1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..4532d9de Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d15341942c36d10a016144f42d4a59c1d41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d2b1db6240390c1234c4f08da46774fdd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d2b1db6240390c1234c4f08da46774fdd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl index 6dde8e6d..80de4c9b 100644 Binary files a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d2b1db6240390c1234c4f08da46774fdd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/d2b1db6240390c1234c4f08da46774fdd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/ff08c62c45f5d6ea16873f6b892f2a6cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/ff08c62c45f5d6ea16873f6b892f2a6cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..8aa39a06 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/api.openai.com/v1_chat_completions/ff08c62c45f5d6ea16873f6b892f2a6cd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/delegation_crewai/duckduckgo.com/5c91e40b895aeb593d5ca0018ad5b0b1618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/duckduckgo.com/5c91e40b895aeb593d5ca0018ad5b0b1618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl deleted file mode 100644 index 7e828ca0..00000000 Binary files a/tests/itest_cache/delegation_crewai/duckduckgo.com/5c91e40b895aeb593d5ca0018ad5b0b1618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/duckduckgo.com/b4a53c404fed2ae23b74a7da093e1822618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/duckduckgo.com/b4a53c404fed2ae23b74a7da093e1822618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..09c2a86d Binary files /dev/null and b/tests/itest_cache/delegation_crewai/duckduckgo.com/b4a53c404fed2ae23b74a7da093e1822618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/delegation_crewai/duckduckgo.com/c5b2d38b3e696e9db10ebe19cbe8f96a618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/duckduckgo.com/c5b2d38b3e696e9db10ebe19cbe8f96a618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..ae201d65 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/duckduckgo.com/c5b2d38b3e696e9db10ebe19cbe8f96a618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/delegation_crewai/duckduckgo.com/cb1db10aaec90382fa1923f51556405f618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/duckduckgo.com/cb1db10aaec90382fa1923f51556405f618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl index b3fb74e5..6069754f 100644 Binary files a/tests/itest_cache/delegation_crewai/duckduckgo.com/cb1db10aaec90382fa1923f51556405f618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and b/tests/itest_cache/delegation_crewai/duckduckgo.com/cb1db10aaec90382fa1923f51556405f618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/131204e4fbc47670c669b56037db53d2618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/131204e4fbc47670c669b56037db53d2618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..457d1825 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/131204e4fbc47670c669b56037db53d2618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b34764ecede55639940743a23b990105618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b34764ecede55639940743a23b990105618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..f373f19a Binary files /dev/null and b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b34764ecede55639940743a23b990105618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b5724b65ccc680292c993230e8c3fdac618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b5724b65ccc680292c993230e8c3fdac618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl deleted file mode 100644 index 9982e823..00000000 Binary files a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/b5724b65ccc680292c993230e8c3fdac618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/bbb3fc335deea15d50776ebc7b18bbe9618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/bbb3fc335deea15d50776ebc7b18bbe9618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl deleted file mode 100644 index 63e21bc1..00000000 Binary files a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/bbb3fc335deea15d50776ebc7b18bbe9618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and /dev/null differ diff --git a/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/f124555f25507ab4078336a42709b4a6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/f124555f25507ab4078336a42709b4a6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..3af970c5 Binary files /dev/null and b/tests/itest_cache/delegation_crewai/links.duckduckgo.com/d.js/f124555f25507ab4078336a42709b4a6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/9a9f10525ef474effb9fbd57e1af29eed41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/9a9f10525ef474effb9fbd57e1af29eed41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl index 72b31c98..36c57858 100644 Binary files a/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/9a9f10525ef474effb9fbd57e1af29eed41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and b/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/9a9f10525ef474effb9fbd57e1af29eed41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/d2746804673be3f3c22aa12d4ea91cabd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/d2746804673be3f3c22aa12d4ea91cabd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl new file mode 100644 index 00000000..77c88c68 Binary files /dev/null and b/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/d2746804673be3f3c22aa12d4ea91cabd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl differ diff --git a/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/ef424a0e9d1b29abbcaa56032a9ccf0dd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl b/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/ef424a0e9d1b29abbcaa56032a9ccf0dd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl deleted file mode 100644 index b4a1578e..00000000 Binary files a/tests/itest_cache/single_llama_index/api.openai.com/v1_chat_completions/ef424a0e9d1b29abbcaa56032a9ccf0dd41d8cd98f00b204e9800998ecf8427ef6bfa7aa5512fbf52a0935a74f6edf99.pkl and /dev/null differ diff --git a/tests/itest_cache/single_llama_index/duckduckgo.com/f597f38a20a58ae7bd858fb5331cb803618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/single_llama_index/duckduckgo.com/f597f38a20a58ae7bd858fb5331cb803618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl index 3db9d9c0..069df75e 100644 Binary files a/tests/itest_cache/single_llama_index/duckduckgo.com/f597f38a20a58ae7bd858fb5331cb803618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and b/tests/itest_cache/single_llama_index/duckduckgo.com/f597f38a20a58ae7bd858fb5331cb803618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/642fd20817e26e317b394e951b11d099618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/642fd20817e26e317b394e951b11d099618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl new file mode 100644 index 00000000..1d5937da Binary files /dev/null and b/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/642fd20817e26e317b394e951b11d099618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl differ diff --git a/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/edab2c7b1703a97e6222e1c1131628c6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl b/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/edab2c7b1703a97e6222e1c1131628c6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl deleted file mode 100644 index a0f2384a..00000000 Binary files a/tests/itest_cache/single_llama_index/links.duckduckgo.com/d.js/edab2c7b1703a97e6222e1c1131628c6618dfcfae621d5a630fd8fcadb941e05bc53b2207da1e8b50d90365cf30ba38c.pkl and /dev/null differ diff --git a/tests/itest_golden_data/delegation_crewai.json b/tests/itest_golden_data/delegation_crewai.json index 8ab2b55b..d2345ce2 100644 --- a/tests/itest_golden_data/delegation_crewai.json +++ b/tests/itest_golden_data/delegation_crewai.json @@ -1 +1 @@ -"Unveiling the Future: Top AI Breakthroughs Shaping Our World\n\nIn the ever-evolving realm of technology, artificial intelligence (AI) continues to be a beacon of innovation, pushing the boundaries of what machines can do. From revolutionizing healthcare to transforming how we interact with our devices, AI advancements are not just futuristic concepts but are becoming integral parts of our daily lives. Let\u2019s dive into some of the most groundbreaking AI developments that are setting the stage for a smarter tomorrow.\n\nOne of the most exciting advancements in AI is the enhancement of natural language processing (NLP). Imagine conversing with a machine as naturally as you would with a friend. Recent breakthroughs in NLP are making this a reality, enabling AI to understand and generate human language in ways that are more nuanced and context-aware than ever before. This leap in capability is powering everything from more responsive voice-activated assistants to tools that can write articles or generate creative content, blurring the lines between human and machine-generated communication.\n\nAnother transformative area is AI in healthcare. AI algorithms are now able to analyze complex medical data and provide diagnostics with astonishing accuracy. For instance, AI-powered systems are being developed to detect diseases such as cancer more quickly and accurately than traditional methods, potentially saving lives through earlier intervention. Moreover, AI is personalizing patient care by analyzing data to predict individual health risks and suggesting customized treatment plans. This not only enhances the effectiveness of treatments but also improves the overall patient experience.\n\nAI is also making significant strides in the field of autonomous vehicles. Self-driving cars, once a staple of science fiction, are rapidly approaching mainstream reality. Advances in AI have led to improvements in machine vision, sensor technology, and decision-making algorithms, allowing vehicles to navigate complex environments safely. This technology promises to reduce traffic accidents, improve mobility for the elderly and disabled, and even reshape urban planning.\n\nIn conclusion, AI is not just a tool of the future; it is actively shaping our present in profound ways. As we continue to explore and integrate these advancements, the potential to enhance and enrich human life seems limitless. Whether it\u2019s through smarter communication, groundbreaking healthcare developments, or safer transportation, AI is undoubtedly leading us into a new era of innovation and discovery.\n```" \ No newline at end of file +"**Title: Unveiling 2023's Game-Changing AI Innovations: A Leap into the Future**\n\n**Introduction:**\nAs we navigate through 2023, the landscape of artificial intelligence (AI) continues to evolve at an exhilarating pace. From groundbreaking models to innovative applications, AI is not just reshaping industries; it's redefining the very fabric of how we interact with technology. Let's dive into some of the most significant AI advancements this year that are setting the stage for a smarter tomorrow.\n\n**Gemini Ultra: The New Frontier in Language Models:**\nOne of the most remarkable breakthroughs this year has been the introduction of Gemini Ultra, a large language model that has taken the AI community by storm. Achieving a record-breaking score of 90.04% on the MMLU benchmark, Gemini Ultra has demonstrated capabilities that surpass even human experts. This model represents a significant leap forward in our quest to develop AI that can understand and generate human-like text, opening new avenues for AI applications in education, customer service, and beyond.\n\n**Generative AI: Transforming Business Landscapes:**\nThe rise of generative AI tools has been another highlight of the year. A recent McKinsey Global Survey revealed that a third of businesses are now regularly using generative AI to enhance their operations. These tools are not just about automating tasks; they are about creating new ways to engage customers, streamline decision-making, and foster innovation. As AI continues to permeate various sectors, the potential for transformative change is immense, making it an exciting time for tech enthusiasts and industry professionals alike.\n\n**Ethical AI: Navigating the New Challenges:**\nWith great power comes great responsibility. As AI technologies become more integrated into our daily lives, the ethical considerations surrounding their use have become more pressing. From privacy concerns to bias in AI algorithms, the community is actively engaging in discussions and research to ensure that AI development is aligned with ethical standards. This ongoing dialogue is crucial as it guides the responsible deployment of AI technologies, ensuring they benefit society as a whole.\n\n**Conclusion:**\nThe advancements in AI in 2023 are not just technological achievements; they are milestones that are shaping the future of how we interact with machines. As we continue to explore the vast potentials of AI, staying informed and engaged with these developments is essential for anyone keen on technology. The journey of AI is far from over, and what we see today is just the tip of the iceberg. The future is here, and it's powered by AI.\n\nThis blog post aims to capture the essence of the latest AI advancements in a manner that is both informative and captivating for those with a keen interest in technology." \ No newline at end of file diff --git a/tests/itest_golden_data/single_llama_index.json b/tests/itest_golden_data/single_llama_index.json index a5b342f3..58e68ab4 100644 --- a/tests/itest_golden_data/single_llama_index.json +++ b/tests/itest_golden_data/single_llama_index.json @@ -1 +1 @@ -"The comprehensive analysis of the latest advancements in AI as of 2024 reveals several key trends and breakthrough technologies that are poised to impact various industries significantly. Here is a detailed report:\n\n1. **Realistic Expectations**: There is a shift towards setting more realistic expectations for AI capabilities, moving away from overhyped promises to practical, achievable goals.\n\n2. **Multimodal AI**: This trend involves AI systems that can understand and analyze multiple types of data inputs (e.g., text, audio, visual) simultaneously, enhancing their applicability and effectiveness in complex scenarios.\n\n3. **Smaller Language Models and Open Source Advancements**: The focus is shifting towards developing smaller, more efficient language models. Additionally, there is significant growth in open-source projects, which democratize AI advancements and encourage community-driven innovation.\n\n4. **GPU Shortages and Cloud Costs**: The AI industry faces challenges such as GPU shortages and rising cloud service costs, which could affect the development and deployment of AI models.\n\n5. **Model Optimization**: Tools and techniques for optimizing AI models are becoming more accessible, allowing for enhanced performance with lower resource consumption.\n\n6. **Customized Local Models and Data Pipelines**: There is an increasing trend towards developing customized AI models and data pipelines tailored for specific local needs, enhancing their effectiveness and efficiency.\n\n7. **Generative AI**: 2024 is expected to be a pivotal year for generative AI, with its potential becoming more accessible and useful to the general public. This technology is anticipated to transform various sectors by enabling the creation of content and solutions directly from AI models.\n\n8. **Integration of AI Leadership**: There is a noticeable trend of organizations consolidating roles such as Chief Data Officers and Chief AI Officers, reflecting a more integrated approach to AI governance and strategy within businesses.\n\n9. **Economic Impact of Generative AI**: The broad potential of generative AI is expected to trigger a significant transformation across the global economic landscape, as businesses begin to leverage these technologies for a wide range of applications.\n\nThese trends and technologies indicate a maturing AI landscape where practicality, efficiency, and broad accessibility are becoming the focal points. The impact on industries will likely be profound, as companies integrate AI more deeply into their operational, strategic, and creative processes." \ No newline at end of file +"The advancements in AI in 2024 are marked by significant trends and breakthrough technologies that have the potential to impact various industries profoundly. Here is a comprehensive analysis report:\n\n**1. Key Trends in AI for 2024:**\n - **Explosive Growth of Generative AI and Multimodal AI:** These technologies are becoming more accessible and useful for the general public, not just tech enthusiasts. This trend indicates a shift towards more creative and diverse applications of AI across different media types.\n - **Quantum AI Emergence:** Quantum computing is beginning to integrate with AI, promising substantial leaps in processing power and capabilities.\n - **Explainable AI (XAI):** There's a growing emphasis on making AI systems more transparent and understandable, which is crucial for trust and regulatory compliance.\n - **Evolving Landscape of Edge AI:** This involves processing AI algorithms locally on devices, reducing latency and privacy concerns, which is crucial for applications like autonomous vehicles and IoT devices.\n - **AI Governance:** As AI becomes more pervasive, there is an increasing focus on governance and regulation to ensure ethical use and mitigate risks.\n - **AI and Sustainability:** There is a notable intersection of AI with sustainability efforts, aiming to tackle environmental challenges using AI-driven solutions.\n\n**2. Breakthrough Technologies:**\n - **Generative AI:** Reaching new heights, generative AI is set to revolutionize content creation, design, and interaction by enabling more sophisticated and nuanced outputs.\n - **Multimodal AI:** This technology combines different forms of data (e.g., text, image, sound) to create more comprehensive AI models that better mimic human sensory and cognitive capabilities.\n - **Quantum AI and Edge AI:** These technologies are expected to drastically enhance computational efficiencies and enable real-time AI applications in ways previously not possible.\n\n**3. Potential Industry Impacts:**\n - **Healthcare:** Improved diagnostic tools, personalized medicine, and efficient patient management systems.\n - **Automotive:** Advancements in autonomous driving technologies and better integration of AI in vehicle management systems.\n - **Finance:** Enhanced fraud detection systems, algorithmic trading, and personalized customer services.\n - **Entertainment and Media:** Revolutionized content creation processes and personalized user experiences.\n - **Manufacturing:** Increased automation, improved quality control, and optimized supply chain management.\n\nIn conclusion, the landscape of AI in 2024 is characterized by a blend of technological innovation and increasing integration into everyday life, promising significant transformations across multiple sectors." \ No newline at end of file diff --git a/tests/run_integration_tests.py b/tests/run_integration_tests.py index d357f71d..626baa0e 100644 --- a/tests/run_integration_tests.py +++ b/tests/run_integration_tests.py @@ -25,7 +25,7 @@ ) from examples.delegation_crewai import main as delegation_crewai_main -from examples.single_llama_index import main as single_llama_index_main +from examples._test_single_llama_index import main as single_llama_index_main INTEGRATION_TESTS = { @@ -82,10 +82,7 @@ def get_args_parser(): help="Update reference data together with the cache", ) parser.add_argument( - "--minimal_only", - default=False, - action="store_true", - help="Run minimal tests" + "--minimal_only", default=False, action="store_true", help="Run minimal tests" ) return parser @@ -174,7 +171,7 @@ def run_integration_tests( golden_dir: str, update_golden: bool = False, test_name: Optional[str] = None, - minimal_only: bool = False + minimal_only: bool = False, ): failed_tests = {} @@ -250,7 +247,7 @@ def main(): golden_dir=args.golden_dir, update_golden=args.update_golden, test_name=args.test_name, - minimal_only=args.minimal_only + minimal_only=args.minimal_only, ) diff --git a/tests/test_tasks/test_task.py b/tests/test_tasks/test_task.py new file mode 100644 index 00000000..c13468cb --- /dev/null +++ b/tests/test_tasks/test_task.py @@ -0,0 +1,133 @@ +from typing import List, Optional + +import pytest + +import kuzu +from langchain_core.runnables import Runnable + +from motleycrew import MotleyCrew +from motleycrew.tools import MotleyTool +from motleycrew.tasks import Task, TaskUnitType +from motleycrew.storage import MotleyKuzuGraphStore +from motleycrew.common.exceptions import TaskDependencyCycleError + + +class TaskMock(Task): + def get_next_unit(self) -> List[TaskUnitType]: + pass + + def get_worker(self, tools: Optional[List[MotleyTool]]) -> Runnable: + pass + + +def create_dummy_task(crew: MotleyCrew, name: str): + return TaskMock( + name=name, + crew=crew, + ) + + +@pytest.fixture +def graph_store(tmpdir): + db_path = tmpdir / "test_db" + db = kuzu.Database(str(db_path)) + graph_store = MotleyKuzuGraphStore(db) + return graph_store + + +@pytest.fixture +def crew(graph_store): + return MotleyCrew(graph_store=graph_store) + + +@pytest.fixture +def task_1(crew): + return create_dummy_task(crew, "1") + + +@pytest.fixture +def task_2(crew): + return create_dummy_task(crew, "2") + + +@pytest.fixture +def task_3(crew): + return create_dummy_task(crew, "3") + + +class TestSetUpstream: + def test_set_upstream_returns_self(self, task_1, task_2): + result = task_2.set_upstream(task_1) + + assert result is task_2 + + def test_set_upstream_sets_upstream(self, task_1, task_2): + task_2.set_upstream(task_1) + + assert task_1.get_upstream_tasks() == [] + assert task_2.get_upstream_tasks() == [task_1] + + def test_set_upstream_sets_downstreams(self, task_1, task_2): + task_2.set_upstream(task_1) + + assert task_1.get_downstream_tasks() == [task_2] + assert task_2.get_downstream_tasks() == [] + + def test_rshift_returns_left(self, task_1, task_2): + result = task_1 >> task_2 + + assert result is task_1 + + def test_rshift_sets_downstream(self, task_1, task_2): + task_1 >> task_2 + + assert task_1.get_downstream_tasks() == [task_2] + assert task_2.get_downstream_tasks() == [] + + def test_rshift_sets_upstream(self, task_1, task_2): + task_1 >> task_2 + + assert task_1.get_upstream_tasks() == [] + assert task_2.get_upstream_tasks() == [task_1] + + def test_rshift_set_multiple_downstream(self, task_1, task_2, task_3): + task_1 >> [task_2, task_3] + + assert set(task_1.get_downstream_tasks()) == {task_2, task_3} + assert task_2.get_downstream_tasks() == [] + assert task_3.get_downstream_tasks() == [] + + def test_rshift_set_multiple_upstream(self, task_1, task_2, task_3): + task_1 >> [task_2, task_3] + + assert task_1.get_upstream_tasks() == [] + assert task_2.get_upstream_tasks() == [task_1] + assert task_3.get_upstream_tasks() == [task_1] + + def test_sequence_on_left_returns_sequence(self, task_1, task_2, task_3): + result = [task_1, task_2] >> task_3 + + assert result == [task_1, task_2] + + def test_sequence_on_left_sets_downstream(self, task_1, task_2, task_3): + [task_1, task_2] >> task_3 + + assert task_1.get_downstream_tasks() == [task_3] + assert task_2.get_downstream_tasks() == [task_3] + assert task_3.get_downstream_tasks() == [] + + def test_sequence_on_left_sets_upstream(self, task_1, task_2, task_3): + [task_1, task_2] >> task_3 + + assert task_1.get_upstream_tasks() == [] + assert task_2.get_upstream_tasks() == [] + assert set(task_3.get_upstream_tasks()) == {task_1, task_2} + + def test_deduplicates(self, task_1, task_2): + task_1 >> [task_2, task_2] + + assert task_1.get_downstream_tasks() == [task_2] + + def test_error_on_direct_dependency_cycle(self, task_1): + with pytest.raises(TaskDependencyCycleError): + task_1 >> task_1 diff --git a/tests/test_tasks/test_task_recipe.py b/tests/test_tasks/test_task_recipe.py deleted file mode 100644 index 721f4b44..00000000 --- a/tests/test_tasks/test_task_recipe.py +++ /dev/null @@ -1,133 +0,0 @@ -from typing import List, Optional - -import pytest - -import kuzu -from langchain_core.runnables import Runnable - -from motleycrew import MotleyCrew -from motleycrew.tools import MotleyTool -from motleycrew.tasks import TaskRecipe, TaskType -from motleycrew.storage import MotleyKuzuGraphStore -from motleycrew.common.exceptions import TaskDependencyCycleError - - -class TaskRecipeMock(TaskRecipe): - def get_next_task(self) -> TaskType | None: - pass - - def get_worker(self, tools: Optional[List[MotleyTool]]) -> Runnable: - pass - - -def create_dummy_task_recipe(crew: MotleyCrew, name: str): - return TaskRecipeMock( - name=name, - crew=crew, - ) - - -@pytest.fixture -def graph_store(tmpdir): - db_path = tmpdir / "test_db" - db = kuzu.Database(str(db_path)) - graph_store = MotleyKuzuGraphStore(db) - return graph_store - - -@pytest.fixture -def crew(graph_store): - return MotleyCrew(graph_store=graph_store) - - -@pytest.fixture -def task_recipe_1(crew): - return create_dummy_task_recipe(crew, "1") - - -@pytest.fixture -def task_recipe_2(crew): - return create_dummy_task_recipe(crew, "2") - - -@pytest.fixture -def task_recipe_3(crew): - return create_dummy_task_recipe(crew, "3") - - -class TestSetUpstream: - def test_set_upstream_returns_self(self, task_recipe_1, task_recipe_2): - result = task_recipe_2.set_upstream(task_recipe_1) - - assert result is task_recipe_2 - - def test_set_upstream_sets_upstream(self, task_recipe_1, task_recipe_2): - task_recipe_2.set_upstream(task_recipe_1) - - assert task_recipe_1.get_upstream_task_recipes() == [] - assert task_recipe_2.get_upstream_task_recipes() == [task_recipe_1] - - def test_set_upstream_sets_downstreams(self, task_recipe_1, task_recipe_2): - task_recipe_2.set_upstream(task_recipe_1) - - assert task_recipe_1.get_downstream_task_recipes() == [task_recipe_2] - assert task_recipe_2.get_downstream_task_recipes() == [] - - def test_rshift_returns_left(self, task_recipe_1, task_recipe_2): - result = task_recipe_1 >> task_recipe_2 - - assert result is task_recipe_1 - - def test_rshift_sets_downstream(self, task_recipe_1, task_recipe_2): - task_recipe_1 >> task_recipe_2 - - assert task_recipe_1.get_downstream_task_recipes() == [task_recipe_2] - assert task_recipe_2.get_downstream_task_recipes() == [] - - def test_rshift_sets_upstream(self, task_recipe_1, task_recipe_2): - task_recipe_1 >> task_recipe_2 - - assert task_recipe_1.get_upstream_task_recipes() == [] - assert task_recipe_2.get_upstream_task_recipes() == [task_recipe_1] - - def test_rshift_set_multiple_downstream(self, task_recipe_1, task_recipe_2, task_recipe_3): - task_recipe_1 >> [task_recipe_2, task_recipe_3] - - assert set(task_recipe_1.get_downstream_task_recipes()) == {task_recipe_2, task_recipe_3} - assert task_recipe_2.get_downstream_task_recipes() == [] - assert task_recipe_3.get_downstream_task_recipes() == [] - - def test_rshift_set_multiple_upstream(self, task_recipe_1, task_recipe_2, task_recipe_3): - task_recipe_1 >> [task_recipe_2, task_recipe_3] - - assert task_recipe_1.get_upstream_task_recipes() == [] - assert task_recipe_2.get_upstream_task_recipes() == [task_recipe_1] - assert task_recipe_3.get_upstream_task_recipes() == [task_recipe_1] - - def test_sequence_on_left_returns_sequence(self, task_recipe_1, task_recipe_2, task_recipe_3): - result = [task_recipe_1, task_recipe_2] >> task_recipe_3 - - assert result == [task_recipe_1, task_recipe_2] - - def test_sequence_on_left_sets_downstream(self, task_recipe_1, task_recipe_2, task_recipe_3): - [task_recipe_1, task_recipe_2] >> task_recipe_3 - - assert task_recipe_1.get_downstream_task_recipes() == [task_recipe_3] - assert task_recipe_2.get_downstream_task_recipes() == [task_recipe_3] - assert task_recipe_3.get_downstream_task_recipes() == [] - - def test_sequence_on_left_sets_upstream(self, task_recipe_1, task_recipe_2, task_recipe_3): - [task_recipe_1, task_recipe_2] >> task_recipe_3 - - assert task_recipe_1.get_upstream_task_recipes() == [] - assert task_recipe_2.get_upstream_task_recipes() == [] - assert set(task_recipe_3.get_upstream_task_recipes()) == {task_recipe_1, task_recipe_2} - - def test_deduplicates(self, task_recipe_1, task_recipe_2): - task_recipe_1 >> [task_recipe_2, task_recipe_2] - - assert task_recipe_1.get_downstream_task_recipes() == [task_recipe_2] - - def test_error_on_direct_dependency_cycle(self, task_recipe_1): - with pytest.raises(TaskDependencyCycleError): - task_recipe_1 >> task_recipe_1