mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-03-09 21:38:14 +00:00
Compare commits
7 Commits
lj/optiona
...
fix/traini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1d8a13f8f | ||
|
|
2b22e5ecd3 | ||
|
|
4bcd1df6bb | ||
|
|
6fae56dd60 | ||
|
|
430f0e9013 | ||
|
|
d7f080a978 | ||
|
|
5d18f73654 |
@@ -27,7 +27,7 @@ class OutputConverter(BaseModel, ABC):
|
||||
llm: Any = Field(description="The language model to be used to convert the text.")
|
||||
model: Any = Field(description="The model to be used to convert the text.")
|
||||
instructions: str = Field(description="Conversion instructions to the LLM.")
|
||||
max_attemps: Optional[int] = Field(
|
||||
max_attempts: Optional[int] = Field(
|
||||
description="Max number of attemps to try to get the output formated.",
|
||||
default=3,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
import json
|
||||
import uuid
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from langchain_core.callbacks import BaseCallbackHandler
|
||||
from pydantic import (
|
||||
@@ -28,6 +28,7 @@ from crewai.task import Task
|
||||
from crewai.telemetry import Telemetry
|
||||
from crewai.tools.agent_tools import AgentTools
|
||||
from crewai.utilities import I18N, FileHandler, Logger, RPMController
|
||||
from crewai.utilities.constants import TRAINED_AGENTS_DATA_FILE, TRAINING_DATA_FILE
|
||||
from crewai.utilities.evaluators.task_evaluator import TaskEvaluator
|
||||
from crewai.utilities.training_handler import CrewTrainingHandler
|
||||
|
||||
@@ -224,6 +225,33 @@ class Crew(BaseModel):
|
||||
agent.set_rpm_controller(self._rpm_controller)
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_tasks(self):
|
||||
if self.process == Process.sequential:
|
||||
for task in self.tasks:
|
||||
if task.agent is None:
|
||||
raise PydanticCustomError(
|
||||
"missing_agent_in_task",
|
||||
f"Sequential process error: Agent is missing in the task with the following description: {task.description}", # type: ignore Argument of type "str" cannot be assigned to parameter "message_template" of type "LiteralString"
|
||||
{},
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def check_tasks_in_hierarchical_process_not_async(self):
|
||||
"""Validates that the tasks in hierarchical process are not flagged with async_execution."""
|
||||
if self.process == Process.hierarchical:
|
||||
for task in self.tasks:
|
||||
if task.async_execution:
|
||||
raise PydanticCustomError(
|
||||
"async_execution_in_hierarchical_process",
|
||||
"Hierarchical process error: Tasks cannot be flagged with async_execution.",
|
||||
{},
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
def _setup_from_config(self):
|
||||
assert self.config is not None, "Config should not be None."
|
||||
|
||||
@@ -262,6 +290,9 @@ class Crew(BaseModel):
|
||||
for agent in self.agents:
|
||||
agent.allow_delegation = False
|
||||
|
||||
CrewTrainingHandler(TRAINING_DATA_FILE).initialize_file()
|
||||
CrewTrainingHandler(TRAINED_AGENTS_DATA_FILE).initialize_file()
|
||||
|
||||
def train(self, n_iterations: int, inputs: Optional[Dict[str, Any]] = {}) -> None:
|
||||
"""Trains the crew for a given number of iterations."""
|
||||
self._setup_for_training()
|
||||
@@ -270,14 +301,14 @@ class Crew(BaseModel):
|
||||
self._train_iteration = n_iteration
|
||||
self.kickoff(inputs=inputs)
|
||||
|
||||
training_data = CrewTrainingHandler("training_data.pkl").load()
|
||||
training_data = CrewTrainingHandler(TRAINING_DATA_FILE).load()
|
||||
|
||||
for agent in self.agents:
|
||||
result = TaskEvaluator(agent).evaluate_training_data(
|
||||
training_data=training_data, agent_id=str(agent.id)
|
||||
)
|
||||
|
||||
CrewTrainingHandler("trained_agents_data.pkl").save_trained_data(
|
||||
CrewTrainingHandler(TRAINED_AGENTS_DATA_FILE).save_trained_data(
|
||||
agent_id=str(agent.role), trained_data=result.model_dump()
|
||||
)
|
||||
|
||||
@@ -315,9 +346,7 @@ class Crew(BaseModel):
|
||||
if self.process == Process.sequential:
|
||||
result = self._run_sequential_process()
|
||||
elif self.process == Process.hierarchical:
|
||||
# type: ignore # Unpacking a string is disallowed
|
||||
result, manager_metrics = self._run_hierarchical_process()
|
||||
# type: ignore # Cannot determine type of "manager_metrics"
|
||||
metrics.append(manager_metrics)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
@@ -433,14 +462,16 @@ class Crew(BaseModel):
|
||||
# type: ignore # Incompatible return value type (got "tuple[str, Any]", expected "str")
|
||||
return self._format_output(task_output, token_usage)
|
||||
|
||||
def _run_hierarchical_process(self) -> Union[str, Dict[str, Any]]:
|
||||
def _run_hierarchical_process(
|
||||
self,
|
||||
) -> Tuple[Union[str, Dict[str, Any]], Dict[str, Any]]:
|
||||
"""Creates and assigns a manager agent to make sure the crew completes the tasks."""
|
||||
|
||||
i18n = I18N(prompt_file=self.prompt_file)
|
||||
if self.manager_agent is not None:
|
||||
self.manager_agent.allow_delegation = True
|
||||
manager = self.manager_agent
|
||||
if len(manager.tools) > 0:
|
||||
if manager.tools is not None and len(manager.tools) > 0:
|
||||
raise Exception("Manager agent should not have tools")
|
||||
manager.tools = self.manager_agent.get_delegation_tools(self.agents)
|
||||
else:
|
||||
@@ -465,6 +496,10 @@ class Crew(BaseModel):
|
||||
agent=manager.role, task=task.description, status="started"
|
||||
)
|
||||
|
||||
if task.agent:
|
||||
manager.tools = task.agent.get_delegation_tools([task.agent])
|
||||
else:
|
||||
manager.tools = manager.get_delegation_tools(self.agents)
|
||||
task_output = task.execute(
|
||||
agent=manager, context=task_output, tools=manager.tools
|
||||
)
|
||||
@@ -554,7 +589,7 @@ class Crew(BaseModel):
|
||||
self._rpm_controller.stop_rpm_counter()
|
||||
if agentops:
|
||||
agentops.end_session(
|
||||
end_state="Success", end_state_reason="Finished Execution", is_auto_end=True
|
||||
end_state="Success", end_state_reason="Finished Execution"
|
||||
)
|
||||
self._telemetry.end_crew(self, output)
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class ToolUsage:
|
||||
self.task.increment_tools_errors()
|
||||
self._printer.print(content=f"\n\n{error}\n", color="red")
|
||||
return error
|
||||
return f"{self._use(tool_string=tool_string, tool=tool, calling=calling)}" # type: ignore # BUG?: "_use" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
return f"{self._use(tool_string=tool_string, tool=tool, calling=calling)}" # type: ignore # BUG?: "_use" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
|
||||
def _use(
|
||||
self,
|
||||
@@ -105,8 +105,8 @@ class ToolUsage:
|
||||
tool: BaseTool,
|
||||
calling: Union[ToolCalling, InstructorToolCalling],
|
||||
) -> str: # TODO: Fix this return type
|
||||
tool_event = agentops.ToolEvent(name=calling.tool_name) if agentops else None
|
||||
if self._check_tool_repeated_usage(calling=calling): # type: ignore # _check_tool_repeated_usage of "ToolUsage" does not return a value (it only ever returns None)
|
||||
tool_event = agentops.ToolEvent(name=calling.tool_name) if agentops else None
|
||||
if self._check_tool_repeated_usage(calling=calling): # type: ignore # _check_tool_repeated_usage of "ToolUsage" does not return a value (it only ever returns None)
|
||||
try:
|
||||
result = self._i18n.errors("task_repeated_usage").format(
|
||||
tool_names=self.tools_names
|
||||
@@ -117,20 +117,20 @@ class ToolUsage:
|
||||
tool_name=tool.name,
|
||||
attempts=self._run_attempts,
|
||||
)
|
||||
result = self._format_result(result=result) # type: ignore # "_format_result" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
result = self._format_result(result=result) # type: ignore # "_format_result" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
return result # type: ignore # Fix the reutrn type of this function
|
||||
|
||||
except Exception:
|
||||
self.task.increment_tools_errors()
|
||||
|
||||
result = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
|
||||
result = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
|
||||
|
||||
if self.tools_handler.cache:
|
||||
result = self.tools_handler.cache.read( # type: ignore # Incompatible types in assignment (expression has type "str | None", variable has type "str")
|
||||
tool=calling.tool_name, input=calling.arguments
|
||||
)
|
||||
|
||||
if result is None: #! finecwg: if not result --> if result is None
|
||||
if result is None: #! finecwg: if not result --> if result is None
|
||||
try:
|
||||
if calling.tool_name in [
|
||||
"Delegate work to coworker",
|
||||
@@ -140,7 +140,7 @@ class ToolUsage:
|
||||
|
||||
if calling.arguments:
|
||||
try:
|
||||
acceptable_args = tool.args_schema.schema()["properties"].keys() # type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "schema"
|
||||
acceptable_args = tool.args_schema.schema()["properties"].keys() # type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "schema"
|
||||
arguments = {
|
||||
k: v
|
||||
for k, v in calling.arguments.items()
|
||||
@@ -152,7 +152,7 @@ class ToolUsage:
|
||||
arguments = calling.arguments
|
||||
result = tool._run(**arguments)
|
||||
else:
|
||||
arguments = calling.arguments.values() # type: ignore # Incompatible types in assignment (expression has type "dict_values[str, Any]", variable has type "dict[str, Any]")
|
||||
arguments = calling.arguments.values() # type: ignore # Incompatible types in assignment (expression has type "dict_values[str, Any]", variable has type "dict[str, Any]")
|
||||
result = tool._run(*arguments)
|
||||
else:
|
||||
result = tool._run()
|
||||
@@ -201,14 +201,14 @@ class ToolUsage:
|
||||
llm=self.function_calling_llm,
|
||||
tool_name=tool.name,
|
||||
attempts=self._run_attempts,
|
||||
)
|
||||
result = self._format_result(result=result) # type: ignore # "_format_result" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
)
|
||||
result = self._format_result(result=result) # type: ignore # "_format_result" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
return result # type: ignore # No return value expected
|
||||
|
||||
def _format_result(self, result: Any) -> None:
|
||||
self.task.used_tools += 1
|
||||
if self._should_remember_format(): # type: ignore # "_should_remember_format" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
result = self._remember_format(result=result) # type: ignore # "_remember_format" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
result = self._remember_format(result=result) # type: ignore # "_remember_format" of "ToolUsage" does not return a value (it only ever returns None)
|
||||
return result
|
||||
|
||||
def _should_remember_format(self) -> None:
|
||||
@@ -303,7 +303,7 @@ class ToolUsage:
|
||||
Example:
|
||||
{"tool_name": "tool name", "arguments": {"arg_name1": "value", "arg_name2": 2}}""",
|
||||
),
|
||||
max_attemps=1,
|
||||
max_attempts=1,
|
||||
)
|
||||
calling = converter.to_pydantic()
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class Converter(OutputConverter):
|
||||
else:
|
||||
return self._create_chain().invoke({})
|
||||
except Exception as e:
|
||||
if current_attempt < self.max_attemps:
|
||||
if current_attempt < self.max_attempts:
|
||||
return self.to_pydantic(current_attempt + 1)
|
||||
return ConverterError(
|
||||
f"Failed to convert text into a pydantic model due to the following error: {e}"
|
||||
@@ -46,7 +46,7 @@ class Converter(OutputConverter):
|
||||
else:
|
||||
return json.dumps(self._create_chain().invoke({}).model_dump())
|
||||
except Exception:
|
||||
if current_attempt < self.max_attemps:
|
||||
if current_attempt < self.max_attempts:
|
||||
return self.to_json(current_attempt + 1)
|
||||
return ConverterError("Failed to convert text into JSON.")
|
||||
|
||||
@@ -56,7 +56,7 @@ class Converter(OutputConverter):
|
||||
|
||||
inst = Instructor(
|
||||
llm=self.llm,
|
||||
max_attemps=self.max_attemps,
|
||||
max_attempts=self.max_attempts,
|
||||
model=self.model,
|
||||
content=self.text,
|
||||
instructions=self.instructions,
|
||||
|
||||
@@ -31,9 +31,8 @@ class PickleHandler:
|
||||
- file_name (str): The name of the file for saving and loading data.
|
||||
"""
|
||||
self.file_path = os.path.join(os.getcwd(), file_name)
|
||||
self._initialize_file()
|
||||
|
||||
def _initialize_file(self) -> None:
|
||||
def initialize_file(self) -> None:
|
||||
"""
|
||||
Initialize the file with an empty dictionary if it does not exist or is empty.
|
||||
"""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,146 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
CtoyCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkSsTIKEgoQY3Jld2FpLnRl
|
||||
bGVtZXRyeRJpChCqSW3lVdefwRBLNXi6Xhm8EgijxkgGOCJOMSoQVG9vbCBVc2FnZSBFcnJvcjAB
|
||||
OQh+giEMv94XQYgthSEMv94XShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMzAuMTF6AhgBhQEAAQAA
|
||||
EmkKEITX9xWzBQ0KqeidbMtD1zESCLEDq6L4lZGPKhBUb29sIFVzYWdlIEVycm9yMAE5OF5weAy/
|
||||
3hdBqOZyeAy/3hdKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4zMC4xMXoCGAGFAQABAAASgAIKEPfc
|
||||
duYrDUwkgj4RUzAtD2cSCFdOYgVbkCuLKg5UYXNrIEV4ZWN1dGlvbjABOciuqqkLv94XQcA1NNcM
|
||||
v94XSjEKB3Rhc2tfaWQSJgokMzg2ZTBkMWQtMWVjNy00M2QzLTg3MWItNWU3ZjBiZjBkOWVmSi0K
|
||||
FWZvcm1hdHRlZF9kZXNjcmlwdGlvbhIUChJIb3cgbXVjaCBpcyAyICsgMj9KQwoZZm9ybWF0dGVk
|
||||
X2V4cGVjdGVkX291dHB1dBImCiRUaGUgcmVzdWx0IG9mIHRoZSBzdW0gYXMgYW4gaW50ZWdlci5K
|
||||
DQoGb3V0cHV0EgMKATR6AhgBhQEAAQAAErYLChC8sKh5qQC3H99eVsmrP4vCEgizWQpCjdW1WSoM
|
||||
Q3JldyBDcmVhdGVkMAE5eIbY2Qy/3hdBSILa2Qy/3hdKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4z
|
||||
MC4xMUoaCg5weXRob25fdmVyc2lvbhIICgYzLjExLjVKMQoHY3Jld19pZBImCiQ1MjA2MDE0Zi0w
|
||||
NDUyLTQzNjQtOWZiMS1lNWM4MzZmNmZiYmJKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxK
|
||||
EQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251
|
||||
bWJlcl9vZl9hZ2VudHMSAhgBStIECgtjcmV3X2FnZW50cxLCBAq/BFt7ImlkIjogIjU2OTBjOGJm
|
||||
LWVkMzEtNGU1OC04NzBhLTE2OWM3OTQ1ODdjOSIsICJyb2xlIjogIlJlc2VhcmNoZXIiLCAiZ29h
|
||||
bCI6ICJNYWtlIHRoZSBiZXN0IHJlc2VhcmNoIGFuZCBhbmFseXNpcyBvbiBjb250ZW50IGFib3V0
|
||||
IEFJIGFuZCBBSSBhZ2VudHMiLCAiYmFja3N0b3J5IjogIllvdSdyZSBhbiBleHBlcnQgcmVzZWFy
|
||||
Y2hlciwgc3BlY2lhbGl6ZWQgaW4gdGVjaG5vbG9neSwgc29mdHdhcmUgZW5naW5lZXJpbmcsIEFJ
|
||||
IGFuZCBzdGFydHVwcy4gWW91IHdvcmsgYXMgYSBmcmVlbGFuY2VyIGFuZCBpcyBub3cgd29ya2lu
|
||||
ZyBvbiBkb2luZyByZXNlYXJjaCBhbmQgYW5hbHlzaXMgZm9yIGEgbmV3IGN1c3RvbWVyLiIsICJ2
|
||||
ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiaTE4biI6
|
||||
IG51bGwsICJsbG0iOiAie1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVcIjogXCJncHQtNG9c
|
||||
IiwgXCJ0ZW1wZXJhdHVyZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3BlbkFJXCJ9IiwgImRl
|
||||
bGVnYXRpb25fZW5hYmxlZD8iOiB0cnVlLCAidG9vbHNfbmFtZXMiOiBbXX1dStACCgpjcmV3X3Rh
|
||||
c2tzEsECCr4CW3siaWQiOiAiZTE5ODM4Y2EtOGNhMi00MzhiLThiNmMtNDFmM2VlYjJmMDA1Iiwg
|
||||
ImRlc2NyaXB0aW9uIjogIkxvb2sgYXQgdGhlIGF2YWlsYWJsZSBkYXRhIG5kIGdpdmUgbWUgYSBz
|
||||
ZW5zZSBvbiB0aGUgdG90YWwgbnVtYmVyIG9mIHNhbGVzLiIsICJleHBlY3RlZF9vdXRwdXQiOiAi
|
||||
VGhlIHRvdGFsIG51bWJlciBvZiBzYWxlcyBhcyBhbiBpbnRlZ2VyIiwgImFzeW5jX2V4ZWN1dGlv
|
||||
bj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJSZXNlYXJj
|
||||
aGVyIiwgImNvbnRleHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbXX1dSioKCHBsYXRmb3JtEh4K
|
||||
HG1hY09TLTE0LjEuMS1hcm02NC1hcm0tNjRiaXRKHAoQcGxhdGZvcm1fcmVsZWFzZRIICgYyMy4x
|
||||
LjBKGwoPcGxhdGZvcm1fc3lzdGVtEggKBkRhcndpbkp7ChBwbGF0Zm9ybV92ZXJzaW9uEmcKZURh
|
||||
cndpbiBLZXJuZWwgVmVyc2lvbiAyMy4xLjA6IE1vbiBPY3QgIDkgMjE6Mjc6MjQgUERUIDIwMjM7
|
||||
IHJvb3Q6eG51LTEwMDAyLjQxLjl+Ni9SRUxFQVNFX0FSTTY0X1Q2MDAwSgoKBGNwdXMSAhgKegIY
|
||||
AYUBAAEAABL/CAoQ96LQBkWdya2FFyVOx27tLRIIXv2S0EgHgE4qDENyZXcgQ3JlYXRlZDABOdDJ
|
||||
bNwMv94XQRiybtwMv94XShsKDmNyZXdhaV92ZXJzaW9uEgkKBzAuMzAuMTFKGgoOcHl0aG9uX3Zl
|
||||
cnNpb24SCAoGMy4xMS41SjEKB2NyZXdfaWQSJgokOGM5OTQzNDMtYzcyYi00MzIwLTlkNTItNzI2
|
||||
MTlkNmNmZTc3ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQ
|
||||
AEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIY
|
||||
AUr+AgoLY3Jld19hZ2VudHMS7gIK6wJbeyJpZCI6ICI1YThjOGRjZS00YmQyLTQyMWEtYjUzZC1k
|
||||
ZjE5ODEzMDFiYjEiLCAicm9sZSI6ICJSZXNlYXJjaGVyIiwgImdvYWwiOiAiQmUgc3VwZXIgZW1w
|
||||
YXRoZXRpYy4iLCAiYmFja3N0b3J5IjogIllvdSdyZSBsb3ZlIHRvIHNleSBob3dkeS4iLCAidmVy
|
||||
Ym9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjUsICJtYXhfcnBtIjogbnVsbCwgImkxOG4iOiBu
|
||||
dWxsLCAibGxtIjogIntcIm5hbWVcIjogbnVsbCwgXCJtb2RlbF9uYW1lXCI6IFwiZ3B0LTRvXCIs
|
||||
IFwidGVtcGVyYXR1cmVcIjogMC43LCBcImNsYXNzXCI6IFwiQ2hhdE9wZW5BSVwifSIsICJkZWxl
|
||||
Z2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJ0b29sc19uYW1lcyI6IFtdfV1K7QEKCmNyZXdfdGFz
|
||||
a3MS3gEK2wFbeyJpZCI6ICJmNWEwMjU3Ni1iNTYxLTRiNzQtOTNhMC0yNmYxMDc2YWI5M2MiLCAi
|
||||
ZGVzY3JpcHRpb24iOiAic2F5IGhvd2R5IiwgImV4cGVjdGVkX291dHB1dCI6ICJIb3dkeSEiLCAi
|
||||
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
|
||||
b2xlIjogIlJlc2VhcmNoZXIiLCAiY29udGV4dCI6IG51bGwsICJ0b29sc19uYW1lcyI6IFtdfV1K
|
||||
KgoIcGxhdGZvcm0SHgocbWFjT1MtMTQuMS4xLWFybTY0LWFybS02NGJpdEocChBwbGF0Zm9ybV9y
|
||||
ZWxlYXNlEggKBjIzLjEuMEobCg9wbGF0Zm9ybV9zeXN0ZW0SCAoGRGFyd2luSnsKEHBsYXRmb3Jt
|
||||
X3ZlcnNpb24SZwplRGFyd2luIEtlcm5lbCBWZXJzaW9uIDIzLjEuMDogTW9uIE9jdCAgOSAyMToy
|
||||
NzoyNCBQRFQgMjAyMzsgcm9vdDp4bnUtMTAwMDIuNDEuOX42L1JFTEVBU0VfQVJNNjRfVDYwMDBK
|
||||
CgoEY3B1cxICGAp6AhgBhQEAAQAAErgCChCZQqdNoQoZm/bgnzRGX2OfEgguN/7szlsLYioOVGFz
|
||||
ayBFeGVjdXRpb24wATmwOXfcDL/eF0FoPgTeDL/eF0oxCgd0YXNrX2lkEiYKJGY1YTAyNTc2LWI1
|
||||
NjEtNGI3NC05M2EwLTI2ZjEwNzZhYjkzY0okChVmb3JtYXR0ZWRfZGVzY3JpcHRpb24SCwoJc2F5
|
||||
IGhvd2R5SiUKGWZvcm1hdHRlZF9leHBlY3RlZF9vdXRwdXQSCAoGSG93ZHkhSmwKBm91dHB1dBJi
|
||||
CmBIb3dkeSEgSSBob3BlIHRoaXMgbWVzc2FnZSBmaW5kcyB5b3Ugd2VsbCBhbmQgYnJpbmdzIGEg
|
||||
c21pbGUgdG8geW91ciBmYWNlLiBIYXZlIGEgZmFudGFzdGljIGRheSF6AhgBhQEAAQAAEv8IChBG
|
||||
RLGvZYMTRLcpQuhEq3MREggMeXM0BUGtiSoMQ3JldyBDcmVhdGVkMAE5KKNZ4Qy/3hdBWI9b4Qy/
|
||||
3hdKGwoOY3Jld2FpX3ZlcnNpb24SCQoHMC4zMC4xMUoaCg5weXRob25fdmVyc2lvbhIICgYzLjEx
|
||||
LjVKMQoHY3Jld19pZBImCiQxN2Q3YmMzYi04MjE2LTQ4MWMtOGU2YS0zN2U4MDA3M2E1YmJKHAoM
|
||||
Y3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVt
|
||||
YmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSv4CCgtjcmV3X2Fn
|
||||
ZW50cxLuAgrrAlt7ImlkIjogIjRiYTAzMmMzLWE1NDktNDQyMS05MjY0LTY1ZmVmODZhMTI3MiIs
|
||||
ICJyb2xlIjogIlJlc2VhcmNoZXIiLCAiZ29hbCI6ICJCZSBzdXBlciBlbXBhdGhldGljLiIsICJi
|
||||
YWNrc3RvcnkiOiAiWW91J3JlIGxvdmUgdG8gc2V5IGhvd2R5LiIsICJ2ZXJib3NlPyI6IGZhbHNl
|
||||
LCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiaTE4biI6IG51bGwsICJsbG0iOiAi
|
||||
e1wibmFtZVwiOiBudWxsLCBcIm1vZGVsX25hbWVcIjogXCJncHQtNG9cIiwgXCJ0ZW1wZXJhdHVy
|
||||
ZVwiOiAwLjcsIFwiY2xhc3NcIjogXCJDaGF0T3BlbkFJXCJ9IiwgImRlbGVnYXRpb25fZW5hYmxl
|
||||
ZD8iOiBmYWxzZSwgInRvb2xzX25hbWVzIjogW119XUrtAQoKY3Jld190YXNrcxLeAQrbAVt7Imlk
|
||||
IjogImJlOGZjMWNmLTVjMTYtNDQ4NS04NDZkLTlmNzkxNjcxZmE0NCIsICJkZXNjcmlwdGlvbiI6
|
||||
ICJzYXkgaG93ZHkiLCAiZXhwZWN0ZWRfb3V0cHV0IjogIkhvd2R5ISIsICJhc3luY19leGVjdXRp
|
||||
b24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiUmVzZWFy
|
||||
Y2hlciIsICJjb250ZXh0IjogbnVsbCwgInRvb2xzX25hbWVzIjogW119XUoqCghwbGF0Zm9ybRIe
|
||||
ChxtYWNPUy0xNC4xLjEtYXJtNjQtYXJtLTY0Yml0ShwKEHBsYXRmb3JtX3JlbGVhc2USCAoGMjMu
|
||||
MS4wShsKD3BsYXRmb3JtX3N5c3RlbRIICgZEYXJ3aW5KewoQcGxhdGZvcm1fdmVyc2lvbhJnCmVE
|
||||
YXJ3aW4gS2VybmVsIFZlcnNpb24gMjMuMS4wOiBNb24gT2N0ICA5IDIxOjI3OjI0IFBEVCAyMDIz
|
||||
OyByb290OnhudS0xMDAwMi40MS45fjYvUkVMRUFTRV9BUk02NF9UNjAwMEoKCgRjcHVzEgIYCnoC
|
||||
GAGFAQABAAAS3gEKEPaxZgbRdGE/aC7TcpTEU3USCO2gTkTtndVwKg5UYXNrIEV4ZWN1dGlvbjAB
|
||||
OSjeZOEMv94XQXgCO+IMv94XSjEKB3Rhc2tfaWQSJgokYmU4ZmMxY2YtNWMxNi00NDg1LTg0NmQt
|
||||
OWY3OTE2NzFmYTQ0SiQKFWZvcm1hdHRlZF9kZXNjcmlwdGlvbhILCglzYXkgaG93ZHlKJQoZZm9y
|
||||
bWF0dGVkX2V4cGVjdGVkX291dHB1dBIICgZIb3dkeSFKEgoGb3V0cHV0EggKBkhvd2R5IXoCGAGF
|
||||
AQABAAAS6AwKEDPpREZrHZXFHl0sOJRtgesSCBN6824xY2RxKgxDcmV3IENyZWF0ZWQwATl40Vfi
|
||||
DL/eF0HQY1niDL/eF0obCg5jcmV3YWlfdmVyc2lvbhIJCgcwLjMwLjExShoKDnB5dGhvbl92ZXJz
|
||||
aW9uEggKBjMuMTEuNUoxCgdjcmV3X2lkEiYKJGU3YjFlNDdjLTM4OTQtNDUyYi1hNzRjLWZiZTU3
|
||||
NDUxOWQxOEocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK
|
||||
0wQKC2NyZXdfYWdlbnRzEsMECsAEW3siaWQiOiAiYzRmZTBkOTYtNzRkMy00MTk4LWI5MDQtYWFi
|
||||
NzBlZGMxYjQ1IiwgInJvbGUiOiAiUmVzZWFyY2hlciIsICJnb2FsIjogIk1ha2UgdGhlIGJlc3Qg
|
||||
cmVzZWFyY2ggYW5kIGFuYWx5c2lzIG9uIGNvbnRlbnQgYWJvdXQgQUkgYW5kIEFJIGFnZW50cyIs
|
||||
ICJiYWNrc3RvcnkiOiAiWW91J3JlIGFuIGV4cGVydCByZXNlYXJjaGVyLCBzcGVjaWFsaXplZCBp
|
||||
biB0ZWNobm9sb2d5LCBzb2Z0d2FyZSBlbmdpbmVlcmluZywgQUkgYW5kIHN0YXJ0dXBzLiBZb3Ug
|
||||
d29yayBhcyBhIGZyZWVsYW5jZXIgYW5kIGlzIG5vdyB3b3JraW5nIG9uIGRvaW5nIHJlc2VhcmNo
|
||||
IGFuZCBhbmFseXNpcyBmb3IgYSBuZXcgY3VzdG9tZXIuIiwgInZlcmJvc2U/IjogZmFsc2UsICJt
|
||||
YXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJpMThuIjogbnVsbCwgImxsbSI6ICJ7XCJu
|
||||
YW1lXCI6IG51bGwsIFwibW9kZWxfbmFtZVwiOiBcImdwdC00b1wiLCBcInRlbXBlcmF0dXJlXCI6
|
||||
IDAuNywgXCJjbGFzc1wiOiBcIkNoYXRPcGVuQUlcIn0iLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6
|
||||
IGZhbHNlLCAidG9vbHNfbmFtZXMiOiBbXX1dSoEECgpjcmV3X3Rhc2tzEvIDCu8DW3siaWQiOiAi
|
||||
YzE2NTkyZjktZDM2Yy00MDFlLWJiMTEtYzdlMGY5ODkxZjA2IiwgImRlc2NyaXB0aW9uIjogIkNv
|
||||
bWUgdXAgd2l0aCBhIGxpc3Qgb2YgNSBpbnRlcmVzdGluZyBpZGVhcyB0byBleHBsb3JlIGZvciBh
|
||||
biBhcnRpY2xlLCB0aGVuIHdyaXRlIG9uZSBhbWF6aW5nIHBhcmFncmFwaCBoaWdobGlnaHQgZm9y
|
||||
IGVhY2ggaWRlYSB0aGF0IHNob3djYXNlcyBob3cgZ29vZCBhbiBhcnRpY2xlIGFib3V0IHRoaXMg
|
||||
dG9waWMgY291bGQgYmUuIFJldHVybiB0aGUgbGlzdCBvZiBpZGVhcyB3aXRoIHRoZWlyIHBhcmFn
|
||||
cmFwaCBhbmQgeW91ciBub3Rlcy4iLCAiZXhwZWN0ZWRfb3V0cHV0IjogIjUgYnVsbGV0IHBvaW50
|
||||
cyB3aXRoIGEgcGFyYWdyYXBoIGZvciBlYWNoIGlkZWEuIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBm
|
||||
YWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJOb25lIiwgImNvbnRl
|
||||
eHQiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbXX1dSioKCHBsYXRmb3JtEh4KHG1hY09TLTE0LjEu
|
||||
MS1hcm02NC1hcm0tNjRiaXRKHAoQcGxhdGZvcm1fcmVsZWFzZRIICgYyMy4xLjBKGwoPcGxhdGZv
|
||||
cm1fc3lzdGVtEggKBkRhcndpbkp7ChBwbGF0Zm9ybV92ZXJzaW9uEmcKZURhcndpbiBLZXJuZWwg
|
||||
VmVyc2lvbiAyMy4xLjA6IE1vbiBPY3QgIDkgMjE6Mjc6MjQgUERUIDIwMjM7IHJvb3Q6eG51LTEw
|
||||
MDAyLjQxLjl+Ni9SRUxFQVNFX0FSTTY0X1Q2MDAwSgoKBGNwdXMSAhgKegIYAYUBAAEAAA==
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate, br
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '6493'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.25.0
|
||||
method: POST
|
||||
uri: https://telemetry.crewai.com:4319/v1/traces
|
||||
response:
|
||||
body:
|
||||
string: "\n\0"
|
||||
headers:
|
||||
Content-Length:
|
||||
- '2'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
Date:
|
||||
- Wed, 03 Jul 2024 15:56:09 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1027,6 +1027,29 @@ def test_agent_usage_metrics_are_captured_for_sequential_process():
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_sequential_crew_creation_tasks_without_agents():
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
# agent=researcher, # not having an agent on the task should throw an error
|
||||
)
|
||||
|
||||
# Expected Output: The sequential crew should fail to create because the task is missing an agent
|
||||
with pytest.raises(pydantic_core._pydantic_core.ValidationError) as exec_info:
|
||||
Crew(
|
||||
tasks=[task],
|
||||
agents=[researcher],
|
||||
process=Process.sequential,
|
||||
)
|
||||
|
||||
assert exec_info.value.errors()[0]["type"] == "missing_agent_in_task"
|
||||
assert (
|
||||
"Agent is missing in the task with the following description"
|
||||
in exec_info.value.errors()[0]["msg"]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_agent_usage_metrics_are_captured_for_hierarchical_process():
|
||||
from langchain_openai import ChatOpenAI
|
||||
@@ -1058,6 +1081,61 @@ def test_agent_usage_metrics_are_captured_for_hierarchical_process():
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_hierarchical_crew_creation_tasks_with_agents():
|
||||
"""
|
||||
Agents are not required for tasks in a hierarchical process but sometimes they are still added
|
||||
This test makes sure that the manager still delegates the task to the agent even if the agent is passed in the task
|
||||
"""
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
task = Task(
|
||||
description="Write one amazing paragraph about AI.",
|
||||
expected_output="A single paragraph with 4 sentences.",
|
||||
agent=writer,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
tasks=[task],
|
||||
agents=[writer, researcher],
|
||||
process=Process.hierarchical,
|
||||
manager_llm=ChatOpenAI(model="gpt-4o"),
|
||||
)
|
||||
crew.kickoff()
|
||||
assert crew.manager_agent is not None
|
||||
assert crew.manager_agent.tools is not None
|
||||
assert crew.manager_agent.tools[0].description.startswith(
|
||||
"Delegate a specific task to one of the following coworkers: [Senior Writer]"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_hierarchical_crew_creation_tasks_without_async_execution():
|
||||
from langchain_openai import ChatOpenAI
|
||||
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
async_execution=True, # should throw an error
|
||||
)
|
||||
|
||||
with pytest.raises(pydantic_core._pydantic_core.ValidationError) as exec_info:
|
||||
Crew(
|
||||
tasks=[task],
|
||||
agents=[researcher],
|
||||
process=Process.hierarchical,
|
||||
manager_llm=ChatOpenAI(model="gpt-4o"),
|
||||
)
|
||||
|
||||
assert (
|
||||
exec_info.value.errors()[0]["type"] == "async_execution_in_hierarchical_process"
|
||||
)
|
||||
assert (
|
||||
"Hierarchical process error: Tasks cannot be flagged with async_execution."
|
||||
in exec_info.value.errors()[0]["msg"]
|
||||
)
|
||||
|
||||
|
||||
def test_crew_inputs_interpolate_both_agents_and_tasks():
|
||||
agent = Agent(
|
||||
role="{topic} Researcher",
|
||||
@@ -1068,9 +1146,10 @@ def test_crew_inputs_interpolate_both_agents_and_tasks():
|
||||
task = Task(
|
||||
description="Give me an analysis around {topic}.",
|
||||
expected_output="{points} bullet points about {topic}.",
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
crew = Crew(agents=[agent], tasks=[task], inputs={"topic": "AI", "points": 5})
|
||||
crew = Crew(agents=[agent], tasks=[task])
|
||||
inputs = {"topic": "AI", "points": 5}
|
||||
crew._interpolate_inputs(inputs=inputs) # Manual call for now
|
||||
|
||||
@@ -1375,6 +1454,7 @@ def test_crew_train_success(task_evaluator, crew_training_handler, kickoff):
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article, then write one amazing paragraph highlight for each idea that showcases how good an article about this topic could be. Return the list of ideas with their paragraph and your notes.",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
@@ -1429,6 +1509,7 @@ def test_crew_train_error():
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
@@ -1450,6 +1531,7 @@ def test__setup_for_training():
|
||||
task = Task(
|
||||
description="Come up with a list of 5 interesting ideas to explore for an article",
|
||||
expected_output="5 bullet points with a paragraph for each idea.",
|
||||
agent=researcher,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
|
||||
@@ -17,6 +17,10 @@ class TestPickleHandler(unittest.TestCase):
|
||||
os.remove(self.file_path)
|
||||
|
||||
def test_initialize_file(self):
|
||||
assert os.path.exists(self.file_path) is False
|
||||
|
||||
self.handler.initialize_file()
|
||||
|
||||
assert os.path.exists(self.file_path) is True
|
||||
assert os.path.getsize(self.file_path) >= 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user