Spaces:
Sleeping
Sleeping
fix: Improve CrewAI output extraction and sequential task execution
Browse files- src/crew.py +73 -1
src/crew.py
CHANGED
|
@@ -308,7 +308,33 @@ class FinResearchCrew:
|
|
| 308 |
logger.info("Kicking off crew execution...")
|
| 309 |
result = self._crew.kickoff()
|
| 310 |
|
| 311 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
|
| 313 |
# Validate the output
|
| 314 |
is_valid, issues = self._validate_report(raw_output)
|
|
@@ -390,6 +416,52 @@ class SequentialFinResearchCrew(FinResearchCrew):
|
|
| 390 |
- Debugging individual agent behavior
|
| 391 |
"""
|
| 392 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
def _create_crew(self) -> Crew:
|
| 394 |
"""Create crew with sequential process."""
|
| 395 |
researcher = self._researcher_factory.create()
|
|
|
|
| 308 |
logger.info("Kicking off crew execution...")
|
| 309 |
result = self._crew.kickoff()
|
| 310 |
|
| 311 |
+
# Extract the actual report content from CrewAI result
|
| 312 |
+
# The result can be a CrewOutput object with various attributes
|
| 313 |
+
raw_output = ""
|
| 314 |
+
|
| 315 |
+
# Try to get the best output from CrewAI result
|
| 316 |
+
if hasattr(result, 'raw'):
|
| 317 |
+
raw_output = str(result.raw)
|
| 318 |
+
logger.info("Using result.raw for output")
|
| 319 |
+
elif hasattr(result, 'output'):
|
| 320 |
+
raw_output = str(result.output)
|
| 321 |
+
logger.info("Using result.output for output")
|
| 322 |
+
elif hasattr(result, 'tasks_output') and result.tasks_output:
|
| 323 |
+
# Get the last task's output (report task)
|
| 324 |
+
last_task_output = result.tasks_output[-1]
|
| 325 |
+
if hasattr(last_task_output, 'raw'):
|
| 326 |
+
raw_output = str(last_task_output.raw)
|
| 327 |
+
elif hasattr(last_task_output, 'output'):
|
| 328 |
+
raw_output = str(last_task_output.output)
|
| 329 |
+
else:
|
| 330 |
+
raw_output = str(last_task_output)
|
| 331 |
+
logger.info("Using last task output for report")
|
| 332 |
+
else:
|
| 333 |
+
raw_output = str(result)
|
| 334 |
+
logger.info("Using str(result) fallback for output")
|
| 335 |
+
|
| 336 |
+
# Log output length for debugging
|
| 337 |
+
logger.info(f"Raw output length: {len(raw_output)} characters")
|
| 338 |
|
| 339 |
# Validate the output
|
| 340 |
is_valid, issues = self._validate_report(raw_output)
|
|
|
|
| 416 |
- Debugging individual agent behavior
|
| 417 |
"""
|
| 418 |
|
| 419 |
+
def _create_tasks(self) -> list[Task]:
|
| 420 |
+
"""
|
| 421 |
+
Create all tasks for sequential workflow.
|
| 422 |
+
|
| 423 |
+
Overrides parent to disable async_execution for sequential process.
|
| 424 |
+
Tasks run one at a time: Research -> Analysis -> Report
|
| 425 |
+
|
| 426 |
+
Returns:
|
| 427 |
+
List of configured Task instances
|
| 428 |
+
"""
|
| 429 |
+
# Get agents
|
| 430 |
+
researcher = self._researcher_factory.create()
|
| 431 |
+
analyst = self._analyst_factory.create()
|
| 432 |
+
reporter = self._reporter_factory.create()
|
| 433 |
+
|
| 434 |
+
# Research Task (runs first, no async)
|
| 435 |
+
research_config = self._tasks_config['research_task']
|
| 436 |
+
research_task = Task(
|
| 437 |
+
description=self._format_task_description(research_config['description']),
|
| 438 |
+
expected_output=research_config['expected_output'].strip(),
|
| 439 |
+
agent=researcher,
|
| 440 |
+
async_execution=False # Force sequential
|
| 441 |
+
)
|
| 442 |
+
|
| 443 |
+
# Analysis Task (runs second, no async)
|
| 444 |
+
analysis_config = self._tasks_config['analysis_task']
|
| 445 |
+
analysis_task = Task(
|
| 446 |
+
description=self._format_task_description(analysis_config['description']),
|
| 447 |
+
expected_output=analysis_config['expected_output'].strip(),
|
| 448 |
+
agent=analyst,
|
| 449 |
+
async_execution=False # Force sequential
|
| 450 |
+
)
|
| 451 |
+
|
| 452 |
+
# Report Task (runs last, uses context from previous tasks)
|
| 453 |
+
report_config = self._tasks_config['report_task']
|
| 454 |
+
report_task = Task(
|
| 455 |
+
description=self._format_task_description(report_config['description']),
|
| 456 |
+
expected_output=report_config['expected_output'].strip(),
|
| 457 |
+
agent=reporter,
|
| 458 |
+
context=[research_task, analysis_task], # Gets output from previous tasks
|
| 459 |
+
async_execution=False
|
| 460 |
+
)
|
| 461 |
+
|
| 462 |
+
logger.info("Created 3 tasks for sequential execution: research -> analysis -> report")
|
| 463 |
+
return [research_task, analysis_task, report_task]
|
| 464 |
+
|
| 465 |
def _create_crew(self) -> Crew:
|
| 466 |
"""Create crew with sequential process."""
|
| 467 |
researcher = self._researcher_factory.create()
|