diff --git a/lib/crewai/src/crewai/agents/crew_agent_executor.py b/lib/crewai/src/crewai/agents/crew_agent_executor.py index 8bb27b3950..b7d61044cb 100644 --- a/lib/crewai/src/crewai/agents/crew_agent_executor.py +++ b/lib/crewai/src/crewai/agents/crew_agent_executor.py @@ -1536,14 +1536,15 @@ def _handle_crew_training_output( agent_training_data = training_data.get(agent_id, {}) + iteration_key = str(train_iteration) if human_feedback is not None: - agent_training_data[train_iteration] = { + agent_training_data[iteration_key] = { "initial_output": result.output, "human_feedback": human_feedback, } else: - if train_iteration in agent_training_data: - agent_training_data[train_iteration]["improved_output"] = result.output + if iteration_key in agent_training_data: + agent_training_data[iteration_key]["improved_output"] = result.output else: if self.agent.verbose: PRINTER.print( diff --git a/lib/crewai/src/crewai/tools/base_tool.py b/lib/crewai/src/crewai/tools/base_tool.py index e1dc8f2ee6..c6ad551364 100644 --- a/lib/crewai/src/crewai/tools/base_tool.py +++ b/lib/crewai/src/crewai/tools/base_tool.py @@ -37,7 +37,7 @@ _serialize_schema, build_schema_hint, ) -from crewai.types.callback import SerializableCallable, _resolve_dotted_path +from crewai.types.callback import SerializableCallable, _resolve_dotted_path, string_to_callable from crewai.utilities.pydantic_schema_utils import generate_model_description from crewai.utilities.string_utils import sanitize_tool_name @@ -70,7 +70,7 @@ def _resolve_tool_dict(value: dict[str, Any]) -> Any: val = data.get(key) if isinstance(val, str): try: - data[key] = _resolve_dotted_path(val) + data[key] = string_to_callable(val) except (ValueError, ImportError): data.pop(key) diff --git a/lib/crewai/src/crewai/utilities/file_handler.py b/lib/crewai/src/crewai/utilities/file_handler.py index c456d58df7..9f0bda470b 100644 --- a/lib/crewai/src/crewai/utilities/file_handler.py +++ b/lib/crewai/src/crewai/utilities/file_handler.py @@ -1,7 +1,6 @@ from datetime import datetime import json import os -import pickle from typing import Any, TypedDict from typing_extensions import Unpack @@ -128,10 +127,10 @@ def log(self, **kwargs: Unpack[LogEntry]) -> None: class PickleHandler: - """Handler for saving and loading data using pickle. + """Handler for saving and loading data using JSON. Attributes: - file_path: The path to the pickle file. + file_path: The path to the data file. """ def __init__(self, file_name: str) -> None: @@ -153,17 +152,17 @@ def initialize_file(self) -> None: def save(self, data: Any) -> None: """ - Save the data to the specified file using pickle. + Save the data to the specified file using JSON. Args: data: The data to be saved to the file. """ with store_lock(f"file:{os.path.realpath(self.file_path)}"): - with open(self.file_path, "wb") as f: - pickle.dump(obj=data, file=f) + with open(self.file_path, "w", encoding="utf-8") as f: + json.dump(data, f) def load(self) -> Any: - """Load the data from the specified file using pickle. + """Load the data from the specified file using JSON. Returns: The data loaded from the file. @@ -175,10 +174,8 @@ def load(self) -> Any: ): return {} - with open(self.file_path, "rb") as file: + with open(self.file_path, "r", encoding="utf-8") as file: try: - return pickle.load(file) # noqa: S301 - except EOFError: - return {} + return json.load(file) except Exception: raise diff --git a/lib/crewai/src/crewai/utilities/training_handler.py b/lib/crewai/src/crewai/utilities/training_handler.py index 98d781e11e..c24790c1e1 100644 --- a/lib/crewai/src/crewai/utilities/training_handler.py +++ b/lib/crewai/src/crewai/utilities/training_handler.py @@ -27,7 +27,7 @@ def append(self, train_iteration: int, agent_id: str, new_data: Any) -> None: data = self.load() if agent_id not in data: data[agent_id] = {} - data[agent_id][train_iteration] = new_data + data[agent_id][str(train_iteration)] = new_data self.save(data) def clear(self) -> None: diff --git a/lib/crewai/tests/utilities/test_file_handler.py b/lib/crewai/tests/utilities/test_file_handler.py index 1e1cbfba8c..65fb9d9a74 100644 --- a/lib/crewai/tests/utilities/test_file_handler.py +++ b/lib/crewai/tests/utilities/test_file_handler.py @@ -45,5 +45,4 @@ def test_load_corrupted_file(self): with pytest.raises(Exception) as exc: self.handler.load() - assert str(exc.value) == "pickle data was truncated" - assert "" == str(exc.type) + assert "" == str(exc.type) diff --git a/lib/crewai/tests/utilities/test_training_handler.py b/lib/crewai/tests/utilities/test_training_handler.py index beca43b0a2..418a3ded20 100644 --- a/lib/crewai/tests/utilities/test_training_handler.py +++ b/lib/crewai/tests/utilities/test_training_handler.py @@ -39,10 +39,10 @@ def test_append_existing_agent(self): # Assert that the new data is appended correctly to the existing agent data = self.handler.load() assert agent_id in data - assert initial_iteration in data[agent_id] - assert train_iteration in data[agent_id] - assert data[agent_id][initial_iteration] == initial_data - assert data[agent_id][train_iteration] == new_data + assert str(initial_iteration) in data[agent_id] + assert str(train_iteration) in data[agent_id] + assert data[agent_id][str(initial_iteration)] == initial_data + assert data[agent_id][str(train_iteration)] == new_data def test_append_new_agent(self): train_iteration = 1 @@ -52,4 +52,4 @@ def test_append_new_agent(self): # Assert that the new agent and data are appended correctly data = self.handler.load() - assert data[agent_id][train_iteration] == new_data + assert data[agent_id][str(train_iteration)] == new_data