Skip to content

Commit 53a56e6

Browse files
qandrewAndrew Xia
andauthored
[gpt-oss][2/N] Support input_messages in responsesRequest (#26962)
Signed-off-by: Andrew Xia <[email protected]> Co-authored-by: Andrew Xia <[email protected]>
1 parent 69f0640 commit 53a56e6

File tree

7 files changed

+481
-17
lines changed

7 files changed

+481
-17
lines changed

tests/entrypoints/openai/test_response_api_with_harmony.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,17 @@ def get_place_to_travel():
535535
return "Paris"
536536

537537

538+
def get_horoscope(sign):
539+
return f"{sign}: Next Tuesday you will befriend a baby otter."
540+
541+
538542
def call_function(name, args):
539543
if name == "get_weather":
540544
return get_weather(**args)
541545
elif name == "get_place_to_travel":
542546
return get_place_to_travel()
547+
elif name == "get_horoscope":
548+
return get_horoscope(**args)
543549
else:
544550
raise ValueError(f"Unknown function: {name}")
545551

@@ -828,3 +834,126 @@ async def test_output_messages_enabled(client: OpenAI, model_name: str, server):
828834
assert response.status == "completed"
829835
assert len(response.input_messages) > 0
830836
assert len(response.output_messages) > 0
837+
838+
839+
@pytest.mark.asyncio
840+
@pytest.mark.parametrize("model_name", [MODEL_NAME])
841+
async def test_function_call_with_previous_input_messages(
842+
client: OpenAI, model_name: str
843+
):
844+
"""Test function calling using previous_input_messages
845+
for multi-turn conversation with a function call"""
846+
847+
# Define the get_horoscope tool
848+
tools = [
849+
{
850+
"type": "function",
851+
"name": "get_horoscope",
852+
"description": "Get today's horoscope for an astrological sign.",
853+
"parameters": {
854+
"type": "object",
855+
"properties": {
856+
"sign": {"type": "string"},
857+
},
858+
"required": ["sign"],
859+
"additionalProperties": False,
860+
},
861+
"strict": True,
862+
}
863+
]
864+
865+
# Step 1: First call with the function tool
866+
stream_response = await client.responses.create(
867+
model=model_name,
868+
input="What is the horoscope for Aquarius today?",
869+
tools=tools,
870+
extra_body={"enable_response_messages": True},
871+
stream=True,
872+
)
873+
874+
response = None
875+
async for event in stream_response:
876+
if event.type == "response.completed":
877+
response = event.response
878+
879+
assert response is not None
880+
assert response.status == "completed"
881+
882+
# Step 2: Parse the first output to find the function_call type
883+
function_call = None
884+
for item in response.output:
885+
if item.type == "function_call":
886+
function_call = item
887+
break
888+
889+
assert function_call is not None, "Expected a function_call in the output"
890+
assert function_call.name == "get_horoscope"
891+
assert function_call.call_id is not None
892+
893+
# Verify the format matches expectations
894+
args = json.loads(function_call.arguments)
895+
assert "sign" in args
896+
897+
# Step 3: Call the get_horoscope function
898+
result = call_function(function_call.name, args)
899+
assert "Aquarius" in result
900+
assert "baby otter" in result
901+
902+
# Get the input_messages and output_messages from the first response
903+
first_input_messages = response.input_messages
904+
first_output_messages = response.output_messages
905+
906+
# Construct the full conversation history using previous_input_messages
907+
previous_messages = (
908+
first_input_messages
909+
+ first_output_messages
910+
+ [
911+
{
912+
"role": "tool",
913+
"name": "functions.get_horoscope",
914+
"content": [{"type": "text", "text": str(result)}],
915+
}
916+
]
917+
)
918+
919+
# Step 4: Make another responses.create() call with previous_input_messages
920+
stream_response_2 = await client.responses.create(
921+
model=model_name,
922+
tools=tools,
923+
input="",
924+
extra_body={
925+
"previous_input_messages": previous_messages,
926+
"enable_response_messages": True,
927+
},
928+
stream=True,
929+
)
930+
931+
async for event in stream_response_2:
932+
if event.type == "response.completed":
933+
response_2 = event.response
934+
935+
assert response_2 is not None
936+
assert response_2.status == "completed"
937+
assert response_2.output_text is not None
938+
939+
# verify only one system message / developer message
940+
num_system_messages_input = 0
941+
num_developer_messages_input = 0
942+
num_function_call_input = 0
943+
for message_dict in response_2.input_messages:
944+
message = Message.from_dict(message_dict)
945+
if message.author.role == "system":
946+
num_system_messages_input += 1
947+
elif message.author.role == "developer":
948+
num_developer_messages_input += 1
949+
elif message.author.role == "tool":
950+
num_function_call_input += 1
951+
assert num_system_messages_input == 1
952+
assert num_developer_messages_input == 1
953+
assert num_function_call_input == 1
954+
955+
# Verify the output makes sense - should contain information about the horoscope
956+
output_text = response_2.output_text.lower()
957+
assert (
958+
"aquarius" in output_text or "otter" in output_text or "tuesday" in output_text
959+
)

tests/entrypoints/openai/test_serving_responses.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ async def test_initialize_tool_sessions(
125125
# Verify that init_tool_sessions was called
126126
assert mock_context.init_tool_sessions_called
127127

128+
def test_validate_create_responses_input(
129+
self, serving_responses_instance, mock_context, mock_exit_stack
130+
):
131+
request = ResponsesRequest(
132+
input="test input",
133+
previous_input_messages=[
134+
{
135+
"role": "user",
136+
"content": [
137+
{
138+
"type": "text",
139+
"text": "What is my horoscope? I am an Aquarius.",
140+
}
141+
],
142+
}
143+
],
144+
previous_response_id="lol",
145+
)
146+
error = serving_responses_instance._validate_create_responses_input(request)
147+
assert error is not None
148+
assert error.error.type == "invalid_request_error"
149+
128150

129151
class TestValidateGeneratorInput:
130152
"""Test class for _validate_generator_input method"""

0 commit comments

Comments
 (0)