mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
[BREAKING] Python: Remove workflow register factory methods. Update tests and samples (#3781)
* Remove workflow register factory methods. Update tests and samples * Address Copilot feedback
This commit is contained in:
@@ -240,12 +240,9 @@ class TestGroupChatBuilder:
|
||||
builder.build()
|
||||
|
||||
def test_build_without_participants_raises_error(self) -> None:
|
||||
"""Test that constructing without participants raises ValueError."""
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match=r"Either participants or participant_factories must be provided\.",
|
||||
):
|
||||
GroupChatBuilder()
|
||||
"""Test that constructing with empty participants raises ValueError."""
|
||||
with pytest.raises(ValueError):
|
||||
GroupChatBuilder(participants=[])
|
||||
|
||||
def test_duplicate_manager_configuration_raises_error(self) -> None:
|
||||
"""Test that configuring multiple orchestrator options raises ValueError."""
|
||||
@@ -775,150 +772,6 @@ def test_group_chat_builder_with_request_info_returns_self():
|
||||
assert result2 is builder2
|
||||
|
||||
|
||||
# region Participant Factory Tests
|
||||
|
||||
|
||||
def test_group_chat_builder_rejects_empty_participant_factories():
|
||||
"""Test that GroupChatBuilder rejects empty participant_factories list."""
|
||||
|
||||
def selector(state: GroupChatState) -> str:
|
||||
return list(state.participants.keys())[0]
|
||||
|
||||
with pytest.raises(ValueError, match=r"participant_factories cannot be empty"):
|
||||
GroupChatBuilder(participant_factories=[])
|
||||
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match=r"Either participants or participant_factories must be provided\.",
|
||||
):
|
||||
GroupChatBuilder()
|
||||
|
||||
|
||||
def test_group_chat_builder_rejects_mixing_participants_and_factories():
|
||||
"""Test that passing both participants and participant_factories to the constructor raises an error."""
|
||||
alpha = StubAgent("alpha", "reply from alpha")
|
||||
|
||||
with pytest.raises(ValueError, match="Cannot provide both participants and participant_factories"):
|
||||
GroupChatBuilder(
|
||||
participants=[alpha],
|
||||
participant_factories=[lambda: StubAgent("beta", "reply from beta")],
|
||||
)
|
||||
|
||||
|
||||
def test_group_chat_builder_rejects_both_factories_and_participants():
|
||||
"""Test that passing both participant_factories and participants raises an error."""
|
||||
with pytest.raises(ValueError, match="Cannot provide both participants and participant_factories"):
|
||||
GroupChatBuilder(
|
||||
participant_factories=[lambda: StubAgent("alpha", "reply from alpha")],
|
||||
participants=[StubAgent("beta", "reply from beta")],
|
||||
)
|
||||
|
||||
|
||||
def test_group_chat_builder_rejects_both_participants_and_factories():
|
||||
"""Test that passing both participants and participant_factories raises an error."""
|
||||
with pytest.raises(ValueError, match="Cannot provide both participants and participant_factories"):
|
||||
GroupChatBuilder(
|
||||
participants=[StubAgent("alpha", "reply from alpha")],
|
||||
participant_factories=[lambda: StubAgent("beta", "reply from beta")],
|
||||
)
|
||||
|
||||
|
||||
async def test_group_chat_with_participant_factories():
|
||||
"""Test workflow creation using participant_factories."""
|
||||
call_count = 0
|
||||
|
||||
def create_alpha() -> StubAgent:
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return StubAgent("alpha", "reply from alpha")
|
||||
|
||||
def create_beta() -> StubAgent:
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return StubAgent("beta", "reply from beta")
|
||||
|
||||
selector = make_sequence_selector()
|
||||
|
||||
workflow = GroupChatBuilder(
|
||||
participant_factories=[create_alpha, create_beta],
|
||||
max_rounds=2,
|
||||
selection_func=selector,
|
||||
).build()
|
||||
|
||||
# Factories should be called during build
|
||||
assert call_count == 2
|
||||
|
||||
outputs: list[WorkflowEvent] = []
|
||||
async for event in workflow.run("coordinate task", stream=True):
|
||||
if event.type == "output":
|
||||
outputs.append(event)
|
||||
|
||||
assert len(outputs) == 1
|
||||
|
||||
|
||||
async def test_group_chat_participant_factories_reusable_builder():
|
||||
"""Test that the builder can be reused to build multiple workflows with factories."""
|
||||
call_count = 0
|
||||
|
||||
def create_alpha() -> StubAgent:
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return StubAgent("alpha", "reply from alpha")
|
||||
|
||||
def create_beta() -> StubAgent:
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return StubAgent("beta", "reply from beta")
|
||||
|
||||
selector = make_sequence_selector()
|
||||
|
||||
builder = GroupChatBuilder(participant_factories=[create_alpha, create_beta], max_rounds=2, selection_func=selector)
|
||||
|
||||
# Build first workflow
|
||||
wf1 = builder.build()
|
||||
assert call_count == 2
|
||||
|
||||
# Build second workflow
|
||||
wf2 = builder.build()
|
||||
assert call_count == 4
|
||||
|
||||
# Verify that the two workflows have different agent instances
|
||||
assert wf1.executors["alpha"] is not wf2.executors["alpha"]
|
||||
assert wf1.executors["beta"] is not wf2.executors["beta"]
|
||||
|
||||
|
||||
async def test_group_chat_participant_factories_with_checkpointing():
|
||||
"""Test checkpointing with participant_factories."""
|
||||
storage = InMemoryCheckpointStorage()
|
||||
|
||||
def create_alpha() -> StubAgent:
|
||||
return StubAgent("alpha", "reply from alpha")
|
||||
|
||||
def create_beta() -> StubAgent:
|
||||
return StubAgent("beta", "reply from beta")
|
||||
|
||||
selector = make_sequence_selector()
|
||||
|
||||
workflow = GroupChatBuilder(
|
||||
participant_factories=[create_alpha, create_beta],
|
||||
checkpoint_storage=storage,
|
||||
max_rounds=2,
|
||||
selection_func=selector,
|
||||
).build()
|
||||
|
||||
outputs: list[WorkflowEvent] = []
|
||||
async for event in workflow.run("checkpoint test", stream=True):
|
||||
if event.type == "output":
|
||||
outputs.append(event)
|
||||
|
||||
assert outputs, "Should have workflow output"
|
||||
|
||||
checkpoints = await storage.list_checkpoints()
|
||||
assert checkpoints, "Checkpoints should be created during workflow execution"
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region Orchestrator Factory Tests
|
||||
|
||||
|
||||
@@ -1129,77 +982,4 @@ def test_group_chat_orchestrator_factory_invalid_return_type():
|
||||
GroupChatBuilder(participants=[alpha], orchestrator_agent=invalid_factory).build()
|
||||
|
||||
|
||||
def test_group_chat_with_both_participant_and_orchestrator_factories():
|
||||
"""Test workflow creation using both participant_factories and orchestrator_factory."""
|
||||
participant_factory_call_count = 0
|
||||
agent_factory_call_count = 0
|
||||
|
||||
def create_alpha() -> StubAgent:
|
||||
nonlocal participant_factory_call_count
|
||||
participant_factory_call_count += 1
|
||||
return StubAgent("alpha", "reply from alpha")
|
||||
|
||||
def create_beta() -> StubAgent:
|
||||
nonlocal participant_factory_call_count
|
||||
participant_factory_call_count += 1
|
||||
return StubAgent("beta", "reply from beta")
|
||||
|
||||
def agent_factory() -> ChatAgent:
|
||||
nonlocal agent_factory_call_count
|
||||
agent_factory_call_count += 1
|
||||
return cast(ChatAgent, StubManagerAgent())
|
||||
|
||||
workflow = GroupChatBuilder(
|
||||
participant_factories=[create_alpha, create_beta],
|
||||
orchestrator_agent=agent_factory,
|
||||
).build()
|
||||
|
||||
# All factories should be called during build
|
||||
assert participant_factory_call_count == 2
|
||||
assert agent_factory_call_count == 1
|
||||
|
||||
# Verify all executors are present in the workflow
|
||||
assert "alpha" in workflow.executors
|
||||
assert "beta" in workflow.executors
|
||||
assert "manager_agent" in workflow.executors
|
||||
|
||||
|
||||
async def test_group_chat_factories_reusable_for_multiple_workflows():
|
||||
"""Test that both factories are reused correctly for multiple workflow builds."""
|
||||
participant_factory_call_count = 0
|
||||
agent_factory_call_count = 0
|
||||
|
||||
def create_alpha() -> StubAgent:
|
||||
nonlocal participant_factory_call_count
|
||||
participant_factory_call_count += 1
|
||||
return StubAgent("alpha", "reply from alpha")
|
||||
|
||||
def create_beta() -> StubAgent:
|
||||
nonlocal participant_factory_call_count
|
||||
participant_factory_call_count += 1
|
||||
return StubAgent("beta", "reply from beta")
|
||||
|
||||
def agent_factory() -> ChatAgent:
|
||||
nonlocal agent_factory_call_count
|
||||
agent_factory_call_count += 1
|
||||
return cast(ChatAgent, StubManagerAgent())
|
||||
|
||||
builder = GroupChatBuilder(participant_factories=[create_alpha, create_beta], orchestrator_agent=agent_factory)
|
||||
|
||||
# Build first workflow
|
||||
wf1 = builder.build()
|
||||
assert participant_factory_call_count == 2
|
||||
assert agent_factory_call_count == 1
|
||||
|
||||
# Build second workflow
|
||||
wf2 = builder.build()
|
||||
assert participant_factory_call_count == 4
|
||||
assert agent_factory_call_count == 2
|
||||
|
||||
# Verify that the workflows have different agent and orchestrator instances
|
||||
assert wf1.executors["alpha"] is not wf2.executors["alpha"]
|
||||
assert wf1.executors["beta"] is not wf2.executors["beta"]
|
||||
assert wf1.executors["manager_agent"] is not wf2.executors["manager_agent"]
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user