Files
AutoGPT/rnd/autogpt_server/test/executor/test_manager.py
Zamil Majdy d407fd101e fix(rnd): Make Agent Server's pin connections become the mandatory source of input (#7539)
### Background

Input from the input pin is consumed only once, and the default input can always be used. So when you have an input pin overriding the default input, the value will be used only once and the following run will always fall back to the default input. This can mislead the user.

Expected behaviour: the node should NOT RUN, making connected pins only use their connection(s) for sources of data.

### Changes 🏗️

* Make pin connection the mandatory source of input and not falling back to default value.
* Fix the type flakiness on block input & output. Unify the typing for BlockInput & BlockOutput using the right alias to avoid wrong typing.
* Add comment on alias
* automated test on the new behaviour.
2024-07-23 09:06:26 +07:00

139 lines
4.7 KiB
Python

import pytest
from autogpt_server.blocks.basic import ObjectLookupBlock, ValueBlock
from autogpt_server.data import execution, graph
from autogpt_server.executor import ExecutionManager
from autogpt_server.server import AgentServer
from autogpt_server.usecases.sample import create_test_graph
from autogpt_server.util.test import wait_execution
async def execute_graph(
test_manager: ExecutionManager,
test_graph: graph.Graph,
input_data: dict[str, str],
num_execs: int = 4,
) -> str:
# --- Test adding new executions --- #
agent_server = AgentServer()
response = await agent_server.execute_graph(test_graph.id, input_data)
graph_exec_id = response["id"]
# Execution queue should be empty
assert await wait_execution(test_manager, test_graph.id, graph_exec_id, num_execs)
return graph_exec_id
async def assert_sample_graph_executions(test_graph: graph.Graph, graph_exec_id: str):
text = "Hello, World!"
agent_server = AgentServer()
executions = await agent_server.get_run_execution_results(
test_graph.id, graph_exec_id
)
# Executing ConstantBlock1
exec = executions[0]
assert exec.status == execution.ExecutionStatus.COMPLETED
assert exec.graph_exec_id == graph_exec_id
assert exec.output_data == {"output": ["Hello, World!"]}
assert exec.input_data == {"input": text}
assert exec.node_id == test_graph.nodes[0].id
# Executing ConstantBlock2
exec = executions[1]
assert exec.status == execution.ExecutionStatus.COMPLETED
assert exec.graph_exec_id == graph_exec_id
assert exec.output_data == {"output": ["Hello, World!"]}
assert exec.input_data == {"input": text}
assert exec.node_id == test_graph.nodes[1].id
# Executing TextFormatterBlock
exec = executions[2]
assert exec.status == execution.ExecutionStatus.COMPLETED
assert exec.graph_exec_id == graph_exec_id
assert exec.output_data == {"output": ["Hello, World!,Hello, World!,!!!"]}
assert exec.input_data == {
"texts_$_1": "Hello, World!",
"texts_$_2": "Hello, World!",
}
assert exec.node_id == test_graph.nodes[2].id
# Executing PrintingBlock
exec = executions[3]
assert exec.status == execution.ExecutionStatus.COMPLETED
assert exec.graph_exec_id == graph_exec_id
assert exec.output_data == {"status": ["printed"]}
assert exec.input_data == {"text": "Hello, World!,Hello, World!,!!!"}
assert exec.node_id == test_graph.nodes[3].id
@pytest.mark.asyncio(scope="session")
async def test_agent_execution(server):
test_graph = create_test_graph()
await graph.create_graph(test_graph)
data = {"input": "Hello, World!"}
graph_exec_id = await execute_graph(server.exec_manager, test_graph, data, 4)
await assert_sample_graph_executions(test_graph, graph_exec_id)
@pytest.mark.asyncio(scope="session")
async def test_input_pin_always_waited(server):
"""
This test is asserting that the input pin should always be waited for the execution,
even when default value on that pin is defined, the value has to be ignored.
Test scenario:
ValueBlock1
\\ input
>------- ObjectLookupBlock | input_default: key: "", input: {}
// key
ValueBlock2
"""
nodes = [
graph.Node(
block_id=ValueBlock().id,
input_default={"input": {"key1": "value1", "key2": "value2"}},
),
graph.Node(
block_id=ValueBlock().id,
input_default={"input": "key2"},
),
graph.Node(
block_id=ObjectLookupBlock().id,
input_default={"key": "", "input": {}},
),
]
links = [
graph.Link(
source_id=nodes[0].id,
sink_id=nodes[2].id,
source_name="output",
sink_name="input",
),
graph.Link(
source_id=nodes[1].id,
sink_id=nodes[2].id,
source_name="output",
sink_name="key",
),
]
test_graph = graph.Graph(
name="TestGraph",
description="Test graph",
nodes=nodes,
links=links,
)
test_graph = await graph.create_graph(test_graph)
graph_exec_id = await execute_graph(server.exec_manager, test_graph, {}, 3)
agent_server = AgentServer()
executions = await agent_server.get_run_execution_results(
test_graph.id, graph_exec_id
)
assert len(executions) == 3
# ObjectLookupBlock should wait for the input pin to be provided,
# Hence executing extraction of "key" from {"key1": "value1", "key2": "value2"}
assert executions[2].status == execution.ExecutionStatus.COMPLETED
assert executions[2].output_data == {"output": ["value2"]}