diff --git a/src/crewai/flow/flow.py b/src/crewai/flow/flow.py index b744ba6ad..382a792e5 100644 --- a/src/crewai/flow/flow.py +++ b/src/crewai/flow/flow.py @@ -600,7 +600,7 @@ class Flow(Generic[T], metaclass=FlowMeta): ``` """ try: - if not hasattr(self, '_state'): + if not hasattr(self, "_state"): return "" if isinstance(self._state, dict): @@ -706,26 +706,31 @@ class Flow(Generic[T], metaclass=FlowMeta): inputs: Optional dictionary containing input values and potentially a state ID to restore """ # Handle state restoration if ID is provided in inputs - if inputs and 'id' in inputs and self._persistence is not None: - restore_uuid = inputs['id'] + if inputs and "id" in inputs and self._persistence is not None: + restore_uuid = inputs["id"] stored_state = self._persistence.load_state(restore_uuid) # Override the id in the state if it exists in inputs - if 'id' in inputs: + if "id" in inputs: if isinstance(self._state, dict): - self._state['id'] = inputs['id'] + self._state["id"] = inputs["id"] elif isinstance(self._state, BaseModel): - setattr(self._state, 'id', inputs['id']) + setattr(self._state, "id", inputs["id"]) if stored_state: - self._log_flow_event(f"Loading flow state from memory for UUID: {restore_uuid}", color="yellow") + self._log_flow_event( + f"Loading flow state from memory for UUID: {restore_uuid}", + color="yellow", + ) # Restore the state self._restore_state(stored_state) else: - self._log_flow_event(f"No flow state found for UUID: {restore_uuid}", color="red") + self._log_flow_event( + f"No flow state found for UUID: {restore_uuid}", color="red" + ) # Apply any additional inputs after restoration - filtered_inputs = {k: v for k, v in inputs.items() if k != 'id'} + filtered_inputs = {k: v for k, v in inputs.items() if k != "id"} if filtered_inputs: self._initialize_state(filtered_inputs) @@ -737,9 +742,11 @@ class Flow(Generic[T], metaclass=FlowMeta): flow_name=self.__class__.__name__, ), ) - self._log_flow_event(f"Flow started with ID: {self.flow_id}", color="bold_magenta") + self._log_flow_event( + f"Flow started with ID: {self.flow_id}", color="bold_magenta" + ) - if inputs is not None and 'id' not in inputs: + if inputs is not None and "id" not in inputs: self._initialize_state(inputs) return asyncio.run(self.kickoff_async()) @@ -984,7 +991,9 @@ class Flow(Generic[T], metaclass=FlowMeta): traceback.print_exc() - def _log_flow_event(self, message: str, color: str = "yellow", level: str = "info") -> None: + def _log_flow_event( + self, message: str, color: str = "yellow", level: str = "info" + ) -> None: """Centralized logging method for flow events. This method provides a consistent interface for logging flow-related events, diff --git a/src/crewai/translations/en.json b/src/crewai/translations/en.json index 0c45321ea..f09f1dba0 100644 --- a/src/crewai/translations/en.json +++ b/src/crewai/translations/en.json @@ -15,7 +15,7 @@ "final_answer_format": "If you don't need to use any more tools, you must give your best complete final answer, make sure it satisfies the expected criteria, use the EXACT format below:\n\n```\nThought: I now can give a great answer\nFinal Answer: my best complete final answer to the task.\n\n```", "format_without_tools": "\nSorry, I didn't use the right format. I MUST either use a tool (among the available ones), OR give my best final answer.\nHere is the expected format I must follow:\n\n```\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [{tool_names}]\nAction Input: the input to the action\nObservation: the result of the action\n```\n This Thought/Action/Action Input/Result process can repeat N times. Once I know the final answer, I must return the following format:\n\n```\nThought: I now can give a great answer\nFinal Answer: Your final answer must be the great and the most complete as possible, it must be outcome described\n\n```", "task_with_context": "{task}\n\nThis is the context you're working with:\n{context}", - "expected_output": "\nThis is the expect criteria for your final answer: {expected_output}\nyou MUST return the actual complete content as the final answer, not a summary.", + "expected_output": "\nThis is the expected criteria for your final answer: {expected_output}\nyou MUST return the actual complete content as the final answer, not a summary.", "human_feedback": "You got human feedback on your work, re-evaluate it and give a new Final Answer when ready.\n {human_feedback}", "getting_input": "This is the agent's final answer: {final_answer}\n\n", "summarizer_system_message": "You are a helpful assistant that summarizes text.", diff --git a/tests/agent_test.py b/tests/agent_test.py index b0efef82b..e67a7454a 100644 --- a/tests/agent_test.py +++ b/tests/agent_test.py @@ -1183,7 +1183,7 @@ def test_agent_max_retry_limit(): [ mock.call( { - "input": "Say the word: Hi\n\nThis is the expect criteria for your final answer: The word: Hi\nyou MUST return the actual complete content as the final answer, not a summary.", + "input": "Say the word: Hi\n\nThis is the expected criteria for your final answer: The word: Hi\nyou MUST return the actual complete content as the final answer, not a summary.", "tool_names": "", "tools": "", "ask_for_human_input": True, @@ -1191,7 +1191,7 @@ def test_agent_max_retry_limit(): ), mock.call( { - "input": "Say the word: Hi\n\nThis is the expect criteria for your final answer: The word: Hi\nyou MUST return the actual complete content as the final answer, not a summary.", + "input": "Say the word: Hi\n\nThis is the expected criteria for your final answer: The word: Hi\nyou MUST return the actual complete content as the final answer, not a summary.", "tool_names": "", "tools": "", "ask_for_human_input": True,