mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [Breaking] removed pydantic from types and workflows (#917)
* removed pydantic from types * fix test * fix test * fix tests * fix assistants client * Remove Pydantic usage from workflow code. * updated pydantic removal * updated lock and test fixes * fix mypy * updated build system * updated chat client parsing * fix broken test --------- Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
647db9635a
commit
b4ebafa9b1
@@ -20,7 +20,6 @@ from agent_framework import (
|
||||
ChatOptions,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
ChatToolMode,
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
HostedCodeInterpreterTool,
|
||||
@@ -28,6 +27,7 @@ from agent_framework import (
|
||||
HostedVectorStoreContent,
|
||||
Role,
|
||||
TextContent,
|
||||
ToolMode,
|
||||
UriContent,
|
||||
UsageContent,
|
||||
ai_function,
|
||||
@@ -622,7 +622,7 @@ def test_openai_assistants_client_prepare_options_basic(mock_async_openai: Magic
|
||||
# Create basic chat options
|
||||
chat_options = ChatOptions(
|
||||
max_tokens=100,
|
||||
ai_model_id="gpt-4",
|
||||
model_id="gpt-4",
|
||||
temperature=0.7,
|
||||
top_p=0.9,
|
||||
)
|
||||
@@ -716,7 +716,7 @@ def test_openai_assistants_client_prepare_options_required_function(mock_async_o
|
||||
chat_client = create_test_openai_assistants_client(mock_async_openai)
|
||||
|
||||
# Create a required function tool choice
|
||||
tool_choice = ChatToolMode(mode="required", required_function_name="specific_function")
|
||||
tool_choice = ToolMode(mode="required", required_function_name="specific_function")
|
||||
|
||||
chat_options = ChatOptions(
|
||||
tool_choice=tool_choice,
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from openai import BadRequestError
|
||||
from pydantic import BaseModel
|
||||
|
||||
from agent_framework import (
|
||||
AgentRunResponse,
|
||||
@@ -691,68 +688,6 @@ def test_function_result_exception_handling(openai_unit_test_env: dict[str, str]
|
||||
assert openai_messages[0]["tool_call_id"] == "call-123"
|
||||
|
||||
|
||||
def test_prepare_function_call_results_with_basemodel():
|
||||
"""Test prepare_function_call_results with BaseModel objects."""
|
||||
|
||||
class TestModel(BaseModel):
|
||||
name: str
|
||||
value: int
|
||||
raw_representation: str = "should be excluded"
|
||||
additional_properties: dict = {"should": "be excluded"}
|
||||
|
||||
model_instance = TestModel(name="test", value=42)
|
||||
result = prepare_function_call_results(model_instance)
|
||||
|
||||
assert isinstance(result, str)
|
||||
parsed = json.loads(result)
|
||||
assert parsed["name"] == "test"
|
||||
assert parsed["value"] == 42
|
||||
assert "raw_representation" not in parsed
|
||||
assert "additional_properties" not in parsed
|
||||
|
||||
|
||||
def test_prepare_function_call_results_with_nested_structures():
|
||||
"""Test prepare_function_call_results with complex nested structures."""
|
||||
|
||||
class NestedModel(BaseModel):
|
||||
id: int
|
||||
raw_representation: str = "excluded"
|
||||
|
||||
# Test with list of BaseModel objects
|
||||
models = [NestedModel(id=1), [NestedModel(id=2)]]
|
||||
result = prepare_function_call_results(models)
|
||||
|
||||
assert isinstance(result, str)
|
||||
parsed = json.loads(result)
|
||||
assert len(parsed) == 2
|
||||
assert parsed[0]["id"] == 1
|
||||
assert isinstance(parsed[1], list)
|
||||
assert len(parsed[1]) == 1
|
||||
assert parsed[1][0]["id"] == 2
|
||||
assert "raw_representation" not in parsed[0]
|
||||
assert "raw_representation" not in parsed[1][0]
|
||||
|
||||
|
||||
def test_prepare_function_call_results_with_dict_containing_basemodel():
|
||||
"""Test prepare_function_call_results with dictionary containing BaseModel."""
|
||||
|
||||
class TestModel(BaseModel):
|
||||
value: str
|
||||
raw_representation: str = "excluded"
|
||||
|
||||
# Test with dict containing BaseModel
|
||||
complex_dict = {"model": TestModel(value="test"), "simple": "value", "number": 42}
|
||||
|
||||
result = prepare_function_call_results(complex_dict)
|
||||
|
||||
assert isinstance(result, str)
|
||||
parsed = json.loads(result)
|
||||
assert parsed["model"]["value"] == "test"
|
||||
assert "raw_representation" not in parsed["model"]
|
||||
assert parsed["simple"] == "value"
|
||||
assert parsed["number"] == 42
|
||||
|
||||
|
||||
def test_prepare_function_call_results_string_passthrough():
|
||||
"""Test that string values are passed through directly without JSON encoding."""
|
||||
result = prepare_function_call_results("simple string")
|
||||
@@ -760,28 +695,6 @@ def test_prepare_function_call_results_string_passthrough():
|
||||
assert isinstance(result, str)
|
||||
|
||||
|
||||
def test_prepare_function_call_results_with_none_values():
|
||||
"""Test that None values in BaseModel fields are preserved to avoid validation errors during reloading."""
|
||||
|
||||
class Flight(BaseModel):
|
||||
flight_id: str
|
||||
departure: datetime | None
|
||||
arrival: datetime | None
|
||||
|
||||
# Test single BaseModel with None values (performance shortcut)
|
||||
flight_with_nones = Flight(flight_id="123", departure=None, arrival=None)
|
||||
result = prepare_function_call_results(flight_with_nones)
|
||||
|
||||
assert isinstance(result, str)
|
||||
parsed = json.loads(result)
|
||||
assert parsed["flight_id"] == "123"
|
||||
assert parsed["departure"] is None
|
||||
assert parsed["arrival"] is None
|
||||
|
||||
new_flight = Flight.model_validate_json(result)
|
||||
assert new_flight == flight_with_nones
|
||||
|
||||
|
||||
def test_openai_content_parser_data_content_image(openai_unit_test_env: dict[str, str]) -> None:
|
||||
"""Test _openai_content_parser converts DataContent with image media type to OpenAI format."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
@@ -370,7 +370,7 @@ async def test_response_format_parse_path() -> None:
|
||||
)
|
||||
|
||||
assert response.conversation_id == "parsed_response_123"
|
||||
assert response.ai_model_id == "test-model"
|
||||
assert response.model_id == "test-model"
|
||||
|
||||
|
||||
async def test_bad_request_error_non_content_filter() -> None:
|
||||
@@ -783,7 +783,7 @@ def test_create_streaming_response_content_with_mcp_approval_request() -> None:
|
||||
|
||||
@pytest.mark.parametrize("enable_otel", [False], indirect=True)
|
||||
@pytest.mark.parametrize("enable_sensitive_data", [False], indirect=True)
|
||||
def test_end_to_end_mcp_approval_flow() -> None:
|
||||
def test_end_to_end_mcp_approval_flow(span_exporter) -> None:
|
||||
"""End-to-end mocked test:
|
||||
model issues an mcp_approval_request, user approves, client sends mcp_approval_response.
|
||||
"""
|
||||
@@ -937,7 +937,7 @@ def test_streaming_response_basic_structure() -> None:
|
||||
# Should get a valid ChatResponseUpdate structure
|
||||
assert isinstance(response, ChatResponseUpdate)
|
||||
assert response.role == Role.ASSISTANT
|
||||
assert response.ai_model_id == "test-model"
|
||||
assert response.model_id == "test-model"
|
||||
assert isinstance(response.contents, list)
|
||||
assert response.raw_representation is mock_event
|
||||
|
||||
|
||||
Reference in New Issue
Block a user