mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: updated declarative samples and handling of non-pydantic response formats (#5022)
* updated declarative samples and handling of non-pydantic response formats * fixed from comments * update docstring
This commit is contained in:
committed by
GitHub
Unverified
parent
6acab3d1d6
commit
519bb0cb2b
@@ -127,9 +127,7 @@ class MockChatClient:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text("another update")], role="assistant")
|
||||
|
||||
def _finalize(updates: Sequence[ChatResponseUpdate]) -> ChatResponse:
|
||||
response_format = options.get("response_format")
|
||||
output_format_type = response_format if isinstance(response_format, type) else None
|
||||
return ChatResponse.from_updates(updates, output_format_type=output_format_type)
|
||||
return ChatResponse.from_updates(updates, output_format_type=options.get("response_format"))
|
||||
|
||||
return ResponseStream(_stream(), finalizer=_finalize)
|
||||
|
||||
@@ -233,9 +231,7 @@ class MockBaseChatClient(
|
||||
await asyncio.sleep(0)
|
||||
|
||||
def _finalize(updates: Sequence[ChatResponseUpdate]) -> ChatResponse:
|
||||
response_format = options.get("response_format")
|
||||
output_format_type = response_format if isinstance(response_format, type) else None
|
||||
return ChatResponse.from_updates(updates, output_format_type=output_format_type)
|
||||
return ChatResponse.from_updates(updates, output_format_type=options.get("response_format"))
|
||||
|
||||
return ResponseStream(_stream(), finalizer=_finalize)
|
||||
|
||||
|
||||
@@ -301,6 +301,56 @@ async def test_chat_client_agent_streaming_response_format_from_run_options(
|
||||
assert result.value.greeting == "Hi"
|
||||
|
||||
|
||||
async def test_chat_client_agent_response_format_dict_from_default_options(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
"""AgentResponse.value should parse JSON dicts from default_options response_format."""
|
||||
json_text = json.dumps({"greeting": "Hello"})
|
||||
client.responses.append(ChatResponse(messages=Message(role="assistant", text=json_text))) # type: ignore[attr-defined]
|
||||
|
||||
agent = Agent(
|
||||
client=client,
|
||||
default_options={"response_format": {"type": "object", "properties": {"greeting": {"type": "string"}}}},
|
||||
)
|
||||
result = await agent.run("Hello")
|
||||
|
||||
assert result.text == json_text
|
||||
assert result.value is not None
|
||||
assert isinstance(result.value, dict)
|
||||
assert result.value["greeting"] == "Hello"
|
||||
|
||||
|
||||
async def test_chat_client_agent_streaming_response_format_dict_from_run_options(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
"""Agent streaming should preserve mapping response_format and parse the final value as a dict."""
|
||||
json_text = json.dumps({"greeting": "Hi"})
|
||||
client.streaming_responses.append( # type: ignore[attr-defined]
|
||||
[
|
||||
ChatResponseUpdate(
|
||||
contents=[Content.from_text(json_text)],
|
||||
role="assistant",
|
||||
finish_reason="stop",
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
agent = Agent(client=client)
|
||||
stream = agent.run(
|
||||
"Hello",
|
||||
stream=True,
|
||||
options={"response_format": {"type": "object", "properties": {"greeting": {"type": "string"}}}},
|
||||
)
|
||||
async for _ in stream:
|
||||
pass
|
||||
result = await stream.get_final_response()
|
||||
|
||||
assert result.text == json_text
|
||||
assert result.value is not None
|
||||
assert isinstance(result.value, dict)
|
||||
assert result.value["greeting"] == "Hi"
|
||||
|
||||
|
||||
async def test_chat_client_agent_create_session(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
|
||||
@@ -191,9 +191,7 @@ def mock_chat_client():
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(" world")], role="assistant", finish_reason="stop")
|
||||
|
||||
def _finalize(updates: Sequence[ChatResponseUpdate]) -> ChatResponse:
|
||||
response_format = options.get("response_format")
|
||||
output_format_type = response_format if isinstance(response_format, type) else None
|
||||
return ChatResponse.from_updates(updates, output_format_type=output_format_type)
|
||||
return ChatResponse.from_updates(updates, output_format_type=options.get("response_format"))
|
||||
|
||||
return ResponseStream(_stream(), finalizer=_finalize)
|
||||
|
||||
|
||||
@@ -800,6 +800,19 @@ def test_chat_response_with_format_init():
|
||||
assert response.value.response == "Hello"
|
||||
|
||||
|
||||
def test_chat_response_with_mapping_response_format() -> None:
|
||||
"""ChatResponse.value should parse JSON when response_format is a mapping."""
|
||||
message = Message(role="assistant", text='{"response": "Hello"}')
|
||||
response = ChatResponse(
|
||||
messages=message,
|
||||
response_format={"type": "object", "properties": {"response": {"type": "string"}}},
|
||||
)
|
||||
|
||||
assert response.value is not None
|
||||
assert isinstance(response.value, dict)
|
||||
assert response.value["response"] == "Hello"
|
||||
|
||||
|
||||
def test_chat_response_value_raises_on_invalid_schema():
|
||||
"""Test that value property raises ValidationError with field constraint details."""
|
||||
|
||||
@@ -1004,6 +1017,22 @@ async def test_chat_response_from_async_generator_output_format_in_method():
|
||||
assert resp.value.response == "Hello"
|
||||
|
||||
|
||||
async def test_chat_response_from_async_generator_mapping_response_format() -> None:
|
||||
async def gen() -> AsyncIterable[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text('{ "respon')], message_id="1")
|
||||
yield ChatResponseUpdate(contents=[Content.from_text('se": "Hello" }')], message_id="1")
|
||||
|
||||
resp = await ChatResponse.from_update_generator(
|
||||
gen(),
|
||||
output_format_type={"type": "object", "properties": {"response": {"type": "string"}}},
|
||||
)
|
||||
|
||||
assert resp.text == '{ "response": "Hello" }'
|
||||
assert resp.value is not None
|
||||
assert isinstance(resp.value, dict)
|
||||
assert resp.value["response"] == "Hello"
|
||||
|
||||
|
||||
# region ToolMode
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user