Graph Mode In Orchestrator Factory: A Deep Dive

by Alex Johnson 48 views

In this comprehensive article, we'll explore the process of adding graph mode support to the orchestrator factory. This enhancement will enable the creation of GraphOrchestrator instances through the factory pattern, providing greater flexibility and control over orchestration processes. We'll cover the necessary modifications to the code, step-by-step instructions, and testing procedures to ensure a successful implementation. This article provides an in-depth look at the changes required, including file modifications, code snippets, and testing strategies, ensuring a smooth integration of graph mode into the orchestrator factory.

Goal: Graph Mode Support for Orchestrator Factory

The primary goal is to extend the orchestrator factory's capabilities to include graph mode. This will allow developers to create GraphOrchestrator instances using the factory pattern, which is a creational design pattern that provides an interface for creating objects without specifying their concrete classes. This approach offers several advantages, such as improved code organization, reduced complexity, and increased flexibility in managing different orchestrator types. By integrating graph mode, the factory can handle a wider range of orchestration scenarios, making it a more versatile tool for managing complex workflows. The addition of graph mode support significantly enhances the orchestrator factory's ability to handle diverse orchestration needs, contributing to a more robust and adaptable system. This enhancement aligns with modern software development practices, promoting modularity and ease of maintenance.

Files to Modify

To achieve this goal, we need to modify two key files:

  1. src/orchestrator_factory.py: This file contains the core logic for the orchestrator factory, including the create_orchestrator function and related utilities.
  2. src/orchestrator/graph_orchestrator.py: This file defines the GraphOrchestrator class and its associated functionalities.

1. src/orchestrator_factory.py

This section focuses on the modifications required in the src/orchestrator_factory.py file. These changes are crucial for integrating graph mode into the factory's functionality. The modifications include updating the function signature of create_orchestrator, adding a new branch for graph mode, and updating the mode detection logic. Each task is explained in detail, with specific instructions and code snippets to guide the implementation process. These adjustments ensure that the factory can correctly handle requests for creating GraphOrchestrator instances and seamlessly integrate them into the existing orchestration framework. The modifications to src/orchestrator_factory.py are central to the enhancement, enabling the factory to support the creation of graph-based orchestrators. These key updates pave the way for more complex orchestration workflows and greater system adaptability.

Task 1.1: Update Function Signature (Lines 31-36)

The first step is to update the function signature of the create_orchestrator function. This involves adding new parameters to support graph mode, ensuring that the factory can accept and process requests for creating GraphOrchestrator instances. The new parameters include graph_mode and use_graph, which provide additional configuration options for graph-based orchestration. Additionally, we need to update the docstring to reflect these new parameters, providing clear documentation for developers using the factory. This ensures that the function remains user-friendly and well-documented, promoting code maintainability and reducing the likelihood of errors. The updated function signature is a fundamental step in integrating graph mode, allowing the factory to accommodate the specific requirements of graph-based orchestrators. The updated signature not only adds new capabilities but also maintains the clarity and usability of the orchestrator factory.

Current:

def create_orchestrator(
 search_handler: SearchHandlerProtocol | None = None,
 judge_handler: JudgeHandlerProtocol | None = None,
 config: OrchestratorConfig | None = None,
 mode: Literal["simple", "magentic", "advanced"] | None = None,
) -> Any:

Target:

def create_orchestrator(
 search_handler: SearchHandlerProtocol | None = None,
 judge_handler: JudgeHandlerProtocol | None = None,
 config: OrchestratorConfig | None = None,
 mode: Literal["simple", "magentic", "advanced", "graph"] | None = None,
 graph_mode: Literal["iterative", "deep", "auto"] | None = None,
 use_graph: bool = True,
) -> Any:

Steps:

  1. Add "graph" to the mode type hint.
  2. Add graph_mode parameter with type Literal["iterative", "deep", "auto"] | None = None.
  3. Add use_graph: bool = True parameter.
  4. Update docstring to document new parameters.

Task 1.2: Add Graph Mode Branch (Lines 52-66)

Next, we need to add a new branch to the create_orchestrator function to handle the creation of GraphOrchestrator instances. This involves adding an elif condition that checks if the effective_mode is set to "graph". If it is, we import the create_graph_orchestrator function from src/orchestrator/graph_orchestrator.py and call it with the appropriate parameters. These parameters include the graph_mode, max_iterations, max_time_minutes, use_graph, search_handler, and judge_handler. This ensures that the GraphOrchestrator is created with the correct configuration and dependencies. This new branch is essential for the factory to recognize and handle graph mode requests effectively. The addition of the graph mode branch is a critical step in enabling the orchestrator factory to create GraphOrchestrator instances.

Location: After the "advanced" mode branch, before the "simple" mode check

Code to Add:

elif effective_mode == "graph":
 from src.orchestrator.graph_orchestrator import create_graph_orchestrator

 return create_graph_orchestrator(
 mode=graph_mode or "auto",
 max_iterations=config.max_iterations if config else 5,
 max_time_minutes=config.max_time_minutes if config else 10,
 use_graph=use_graph,
 search_handler=search_handler,
 judge_handler=judge_handler,
 )

Steps:

  1. Add elif effective_mode == "graph": after line 56.
  2. Import create_graph_orchestrator from src/orchestrator/graph_orchestrator.
  3. Call create_graph_orchestrator() with appropriate parameters.
  4. Pass search_handler and judge_handler to the orchestrator.

Task 1.3: Update Mode Detection (Lines 69-80)

Finally, we need to update the _determine_mode function to correctly identify the "graph" mode. This involves adding a check for explicit_mode == "graph" and returning "graph" if matched. This ensures that the factory can accurately determine the orchestration mode based on the input parameters. Accurate mode detection is crucial for the factory to function correctly, as it dictates which type of orchestrator is created. This update is a key part of the integration process, ensuring that graph mode is properly recognized and handled. Correctly identifying the mode is essential for the orchestrator factory to create the appropriate orchestrator instance.

Current:

def _determine_mode(explicit_mode: str | None) -> str:
 """Determine which mode to use."""
 if explicit_mode:
 if explicit_mode in ("magentic", "advanced"):
 return "advanced"
 return "simple"
 # ...

Target:

def _determine_mode(explicit_mode: str | None) -> str:
 """Determine which mode to use."""
 if explicit_mode:
 if explicit_mode in ("magentic", "advanced"):
 return "advanced"
 if explicit_mode == "graph":
 return "graph"
 return "simple"
 # ...

Steps:

  1. Add check for explicit_mode == "graph" after the advanced check.
  2. Return "graph" if matched.

2. src/orchestrator/graph_orchestrator.py

This section details the modifications needed in the src/orchestrator/graph_orchestrator.py file. These changes are focused on updating the constructor and the factory function to accommodate the search_handler and judge_handler parameters. By adding these handlers to the GraphOrchestrator, we ensure that the orchestrator can effectively interact with search and judgment components, enabling more complex and dynamic orchestration workflows. The adjustments in this file are vital for ensuring that the GraphOrchestrator can function correctly within the factory pattern. These enhancements allow for a more seamless integration of search and judgment processes into graph-based orchestration.

Task 2.1: Update Constructor (Lines 118-124)

We need to update the constructor of the GraphOrchestrator class to accept search_handler and judge_handler parameters. This involves adding these parameters to the constructor signature and storing them as instance variables. This allows the GraphOrchestrator to use these handlers during its execution, enabling it to interact with external search and judgment services. By storing these handlers as instance variables, we ensure that they are accessible throughout the lifecycle of the GraphOrchestrator instance. This update is crucial for the GraphOrchestrator to function correctly within the larger orchestration framework. Updating the constructor to include handlers is a key step in enabling the GraphOrchestrator to interact with external services.

Current:

def __init__(
 self,
 mode: Literal["iterative", "deep", "auto"] = "auto",
 max_iterations: int = 5,
 max_time_minutes: int = 10,
 use_graph: bool = True,
) -> None:

Target:

def __init__(
 self,
 mode: Literal["iterative", "deep", "auto"] = "auto",
 max_iterations: int = 5,
 max_time_minutes: int = 10,
 use_graph: bool = True,
 search_handler: Any | None = None,
 judge_handler: Any | None = None,
) -> None:
 self.mode = mode
 self.max_iterations = max_iterations
 self.max_time_minutes = max_time_minutes
 self.use_graph = use_graph
 self.search_handler = search_handler
 self.judge_handler = judge_handler
 self.logger = logger

Steps:

  1. Add search_handler: Any | None = None parameter.
  2. Add judge_handler: Any | None = None parameter.
  3. Store as self.search_handler and self.judge_handler.
  4. Update docstring to document new parameters.

Task 2.2: Update Factory Function (Lines 951-974)

We also need to update the create_graph_orchestrator factory function to accept the search_handler and judge_handler parameters and pass them to the GraphOrchestrator constructor. This ensures that the handlers are correctly passed when a GraphOrchestrator instance is created through the factory. This update is consistent with the changes made to the create_orchestrator function in src/orchestrator_factory.py, ensuring a unified approach to creating GraphOrchestrator instances. By updating the factory function, we maintain the integrity of the factory pattern and ensure that the GraphOrchestrator is properly initialized. Updating the factory function ensures consistency and proper initialization of the GraphOrchestrator.

Current:

def create_graph_orchestrator(
 mode: Literal["iterative", "deep", "auto"] = "auto",
 max_iterations: int = 5,
 max_time_minutes: int = 10,
 use_graph: bool = True,
) -> GraphOrchestrator:

Target:

def create_graph_orchestrator(
 mode: Literal["iterative", "deep", "auto"] = "auto",
 max_iterations: int = 5,
 max_time_minutes: int = 10,
 use_graph: bool = True,
 search_handler: Any | None = None,
 judge_handler: Any | None = None,
) -> GraphOrchestrator:
 return GraphOrchestrator(
 mode=mode,
 max_iterations=max_iterations,
 max_time_minutes=max_time_minutes,
 use_graph=use_graph,
 search_handler=search_handler,
 judge_handler=judge_handler,
 )

Steps:

  1. Add search_handler and judge_handler parameters.
  2. Pass to GraphOrchestrator constructor.

Testing

To ensure that the changes are implemented correctly, we need to create a unit test for the orchestrator factory. This test will verify that the factory function accepts the mode="graph" parameter, creates GraphOrchestrator instances with the correct parameters, and correctly identifies the "graph" mode. Unit testing is a crucial part of the development process, as it helps to identify and fix bugs early on. By writing comprehensive unit tests, we can ensure that the orchestrator factory functions as expected and that the integration of graph mode is successful. Thorough testing is essential to ensure the reliability and stability of the orchestrator factory.

Unit Test: tests/unit/test_orchestrator_factory.py

Create test file with:

import pytest
from src.orchestrator_factory import create_orchestrator
from src.orchestrator.graph_orchestrator import GraphOrchestrator
from src.legacy_orchestrator import SearchHandlerProtocol, JudgeHandlerProtocol

def test_create_graph_orchestrator(mock_search_handler, mock_judge_handler):
 """Test creating graph orchestrator via factory."""
 orchestrator = create_orchestrator(
 search_handler=mock_search_handler,
 judge_handler=mock_judge_handler,
 mode="graph",
 graph_mode="iterative",
 use_graph=True,
 )

 assert isinstance(orchestrator, GraphOrchestrator)
 assert orchestrator.mode == "iterative"
 assert orchestrator.use_graph is True
 assert orchestrator.search_handler == mock_search_handler
 assert orchestrator.judge_handler == mock_judge_handler

def test_graph_mode_detection():
 """Test graph mode detection."""
 from src.orchestrator_factory import _determine_mode

 assert _determine_mode("graph") == "graph"
 assert _determine_mode("simple") == "simple"
 assert _determine_mode("advanced") == "advanced"

Acceptance Criteria

To ensure the successful implementation of graph mode support in the orchestrator factory, several acceptance criteria must be met. These criteria cover the key functionalities and ensure that the factory operates as expected. Meeting these acceptance criteria signifies that the enhancement is complete and the factory is ready for use in graph-based orchestration scenarios. The following criteria provide a clear checklist for verifying the successful integration of graph mode.

  • [ ] Factory function accepts mode="graph" parameter
  • [ ] Factory function accepts graph_mode and use_graph parameters
  • [ ] GraphOrchestrator created with correct parameters
  • [ ] Search and judge handlers passed to GraphOrchestrator
  • [ ] Mode detection correctly identifies "graph" mode
  • [ ] Unit tests pass

Estimated Effort

4-6 hours

Notes

  • This phase focuses only on factory integration
  • Handler integration in graph execution will be done in Phase 2
  • No UI changes required in this phase

Conclusion

In conclusion, adding graph mode support to the orchestrator factory involves several key steps, including updating the function signature, adding a graph mode branch, updating mode detection, and modifying the GraphOrchestrator constructor and factory function. By following these steps and conducting thorough testing, we can successfully integrate graph mode into the orchestrator factory, providing greater flexibility and control over orchestration processes. This enhancement represents a significant improvement in the factory's capabilities, allowing it to handle a wider range of orchestration scenarios. This integration paves the way for more complex and dynamic workflows, ultimately enhancing the overall system's adaptability and efficiency.

For more information on orchestrator patterns and factory design, you can visit the Microsoft's documentation on the Factory Method pattern.