prebuilt: remove state_modifier (#4439)

Removes support for `state_modifier` param in `create_react_agent`. To
specify system prompt / instructions use `prompt` parameter.
This commit is contained in:
Vadym Barda
2025-05-05 09:49:28 -04:00
committed by GitHub
parent a0a302dec5
commit 0e61cc2cf6
2 changed files with 29 additions and 80 deletions
@@ -1,4 +1,3 @@
import functools
import inspect
from typing import (
Any,
@@ -141,27 +140,6 @@ def _get_prompt_runnable(prompt: Optional[Prompt]) -> Runnable:
return prompt_runnable
def _convert_modifier_to_prompt(func: F) -> F:
"""Decorator that converts state_modifier kwarg to prompt kwarg."""
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
prompt = kwargs.get("prompt")
state_modifier = kwargs.pop("state_modifier", None)
if sum(p is not None for p in (prompt, state_modifier)) > 1:
raise ValueError(
"Expected only one of (prompt, state_modifier), got multiple values"
)
if state_modifier is not None:
prompt = state_modifier
kwargs["prompt"] = prompt
return func(*args, **kwargs)
return cast(F, wrapper)
def _should_bind_tools(model: LanguageModelLike, tools: Sequence[BaseTool]) -> bool:
if isinstance(model, RunnableSequence):
model = next(
@@ -260,7 +238,6 @@ def _validate_chat_history(
raise ValueError(error_message)
@_convert_modifier_to_prompt
def create_react_agent(
model: Union[str, LanguageModelLike],
tools: Union[Sequence[Union[BaseTool, Callable]], ToolNode],
+29 -57
View File
@@ -141,39 +141,26 @@ async def test_no_prompt_async(checkpointer_name: str) -> None:
assert saved.pending_writes == []
def test_passing_two_modifiers():
model = FakeToolCallingModel()
with pytest.raises(ValueError):
create_react_agent(model, [], state_modifier="Foo", prompt="Bar")
def test_system_message_prompt():
prompt = SystemMessage(content="Foo")
for agent in (
create_react_agent(FakeToolCallingModel(), [], prompt=prompt),
create_react_agent(FakeToolCallingModel(), [], state_modifier=prompt),
):
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Foo-hi?", id="0", tool_calls=[])]
}
assert response == expected_response
agent = create_react_agent(FakeToolCallingModel(), [], prompt=prompt)
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Foo-hi?", id="0", tool_calls=[])]
}
assert response == expected_response
def test_string_prompt():
prompt = "Foo"
for agent in (
create_react_agent(FakeToolCallingModel(), [], prompt=prompt),
create_react_agent(FakeToolCallingModel(), [], state_modifier=prompt),
):
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Foo-hi?", id="0", tool_calls=[])]
}
assert response == expected_response
agent = create_react_agent(FakeToolCallingModel(), [], prompt=prompt)
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Foo-hi?", id="0", tool_calls=[])]
}
assert response == expected_response
def test_callable_prompt():
@@ -181,16 +168,11 @@ def test_callable_prompt():
modified_message = f"Bar {state['messages'][-1].content}"
return [HumanMessage(content=modified_message)]
for agent in (
create_react_agent(FakeToolCallingModel(), [], prompt=prompt),
create_react_agent(FakeToolCallingModel(), [], state_modifier=prompt),
):
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Bar hi?", id="0")]
}
assert response == expected_response
agent = create_react_agent(FakeToolCallingModel(), [], prompt=prompt)
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {"messages": inputs + [AIMessage(content="Bar hi?", id="0")]}
assert response == expected_response
async def test_callable_prompt_async():
@@ -198,16 +180,11 @@ async def test_callable_prompt_async():
modified_message = f"Bar {state['messages'][-1].content}"
return [HumanMessage(content=modified_message)]
for agent in (
create_react_agent(FakeToolCallingModel(), [], prompt=prompt),
create_react_agent(FakeToolCallingModel(), [], state_modifier=prompt),
):
inputs = [HumanMessage("hi?")]
response = await agent.ainvoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Bar hi?", id="0")]
}
assert response == expected_response
agent = create_react_agent(FakeToolCallingModel(), [], prompt=prompt)
inputs = [HumanMessage("hi?")]
response = await agent.ainvoke({"messages": inputs})
expected_response = {"messages": inputs + [AIMessage(content="Bar hi?", id="0")]}
assert response == expected_response
def test_runnable_prompt():
@@ -215,16 +192,11 @@ def test_runnable_prompt():
lambda state: [HumanMessage(content=f"Baz {state['messages'][-1].content}")]
)
for agent in (
create_react_agent(FakeToolCallingModel(), [], prompt=prompt),
create_react_agent(FakeToolCallingModel(), [], state_modifier=prompt),
):
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {
"messages": inputs + [AIMessage(content="Baz hi?", id="0")]
}
assert response == expected_response
agent = create_react_agent(FakeToolCallingModel(), [], prompt=prompt)
inputs = [HumanMessage("hi?")]
response = agent.invoke({"messages": inputs})
expected_response = {"messages": inputs + [AIMessage(content="Baz hi?", id="0")]}
assert response == expected_response
@pytest.mark.parametrize("version", REACT_TOOL_CALL_VERSIONS)