mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: openai updates (#388)
* openai updates * rebuild of openai structure * updated responses structure * renamed sample * added file id support to code interpreter * added hosted file ids to code interpretor * mypy fixes * removed default az cred from codebase * updated agent name setup * added kwargs to entra methods * and further kwargs * extra comment * updated all samples * readded custom get methods for responses * updated int tests with ad credential * missed one
This commit is contained in:
committed by
GitHub
Unverified
parent
19676978e9
commit
df9d85d1f0
@@ -13,6 +13,7 @@ from agent_framework import (
|
||||
TextContent,
|
||||
)
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from pydantic import Field
|
||||
|
||||
from agent_framework_azure import AzureAssistantsClient
|
||||
@@ -259,7 +260,7 @@ def get_weather(
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_assistants_client_get_response() -> None:
|
||||
"""Test Azure Assistants Client response."""
|
||||
async with AzureAssistantsClient() as azure_assistants_client:
|
||||
async with AzureAssistantsClient(ad_credential=DefaultAzureCredential()) as azure_assistants_client:
|
||||
assert isinstance(azure_assistants_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -283,7 +284,7 @@ async def test_azure_assistants_client_get_response() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_assistants_client_get_response_tools() -> None:
|
||||
"""Test Azure Assistants Client response with tools."""
|
||||
async with AzureAssistantsClient() as azure_assistants_client:
|
||||
async with AzureAssistantsClient(ad_credential=DefaultAzureCredential()) as azure_assistants_client:
|
||||
assert isinstance(azure_assistants_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -304,7 +305,7 @@ async def test_azure_assistants_client_get_response_tools() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_assistants_client_streaming() -> None:
|
||||
"""Test Azure Assistants Client streaming response."""
|
||||
async with AzureAssistantsClient() as azure_assistants_client:
|
||||
async with AzureAssistantsClient(ad_credential=DefaultAzureCredential()) as azure_assistants_client:
|
||||
assert isinstance(azure_assistants_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -334,7 +335,7 @@ async def test_azure_assistants_client_streaming() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_assistants_client_streaming_tools() -> None:
|
||||
"""Test Azure Assistants Client streaming response with tools."""
|
||||
async with AzureAssistantsClient() as azure_assistants_client:
|
||||
async with AzureAssistantsClient(ad_credential=DefaultAzureCredential()) as azure_assistants_client:
|
||||
assert isinstance(azure_assistants_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -361,14 +362,16 @@ async def test_azure_assistants_client_streaming_tools() -> None:
|
||||
async def test_azure_assistants_client_with_existing_assistant() -> None:
|
||||
"""Test Azure Assistants Client with existing assistant ID."""
|
||||
# First create an assistant to use in the test
|
||||
async with AzureAssistantsClient() as temp_client:
|
||||
async with AzureAssistantsClient(ad_credential=DefaultAzureCredential()) as temp_client:
|
||||
# Get the assistant ID by triggering assistant creation
|
||||
messages = [ChatMessage(role="user", text="Hello")]
|
||||
await temp_client.get_response(messages=messages)
|
||||
assistant_id = temp_client.assistant_id
|
||||
|
||||
# Now test using the existing assistant
|
||||
async with AzureAssistantsClient(assistant_id=assistant_id) as azure_assistants_client:
|
||||
async with AzureAssistantsClient(
|
||||
assistant_id=assistant_id, ad_credential=DefaultAzureCredential()
|
||||
) as azure_assistants_client:
|
||||
assert isinstance(azure_assistants_client, ChatClient)
|
||||
assert azure_assistants_client.assistant_id == assistant_id
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ from agent_framework import (
|
||||
ChatMessage,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
TextContent,
|
||||
ai_function,
|
||||
)
|
||||
@@ -23,6 +21,7 @@ from agent_framework.openai import (
|
||||
OpenAIContentFilterException,
|
||||
)
|
||||
from agent_framework.telemetry import USER_AGENT_KEY
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from httpx import Request, Response
|
||||
from openai import AsyncAzureOpenAI, AsyncStream
|
||||
from openai.resources.chat.completions import AsyncCompletions as AsyncChatCompletions
|
||||
@@ -123,6 +122,7 @@ def test_serialize(azure_openai_unit_test_env: dict[str, str]) -> None:
|
||||
"api_key": azure_openai_unit_test_env["AZURE_OPENAI_API_KEY"],
|
||||
"api_version": azure_openai_unit_test_env["AZURE_OPENAI_API_VERSION"],
|
||||
"default_headers": default_headers,
|
||||
"env_file_path": "test.env",
|
||||
}
|
||||
|
||||
azure_chat_client = AzureChatClient.from_dict(settings)
|
||||
@@ -258,13 +258,15 @@ async def test_azure_on_your_data(
|
||||
content="test",
|
||||
role="assistant",
|
||||
context={ # type: ignore
|
||||
"citations": {
|
||||
"content": "test content",
|
||||
"title": "test title",
|
||||
"url": "test url",
|
||||
"filepath": "test filepath",
|
||||
"chunk_id": "test chunk_id",
|
||||
},
|
||||
"citations": [
|
||||
{
|
||||
"content": "test content",
|
||||
"title": "test title",
|
||||
"url": "test url",
|
||||
"filepath": "test filepath",
|
||||
"chunk_id": "test chunk_id",
|
||||
}
|
||||
],
|
||||
"intent": "query used",
|
||||
},
|
||||
),
|
||||
@@ -298,11 +300,11 @@ async def test_azure_on_your_data(
|
||||
additional_properties={"extra_body": expected_data_settings},
|
||||
)
|
||||
assert len(content.messages) == 1
|
||||
assert len(content.messages[0].contents) == 3
|
||||
assert isinstance(content.messages[0].contents[0], FunctionCallContent)
|
||||
assert isinstance(content.messages[0].contents[1], FunctionResultContent)
|
||||
assert isinstance(content.messages[0].contents[2], TextContent)
|
||||
assert content.messages[0].contents[2].text == "test"
|
||||
assert len(content.messages[0].contents) == 1
|
||||
assert isinstance(content.messages[0].contents[0], TextContent)
|
||||
assert len(content.messages[0].contents[0].annotations) == 1
|
||||
assert content.messages[0].contents[0].annotations[0].title == "test title"
|
||||
assert content.messages[0].contents[0].text == "test"
|
||||
|
||||
mock_create.assert_awaited_once_with(
|
||||
model=azure_openai_unit_test_env["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"],
|
||||
@@ -326,13 +328,15 @@ async def test_azure_on_your_data_string(
|
||||
content="test",
|
||||
role="assistant",
|
||||
context=json.dumps({ # type: ignore
|
||||
"citations": {
|
||||
"content": "test content",
|
||||
"title": "test title",
|
||||
"url": "test url",
|
||||
"filepath": "test filepath",
|
||||
"chunk_id": "test chunk_id",
|
||||
},
|
||||
"citations": [
|
||||
{
|
||||
"content": "test content",
|
||||
"title": "test title",
|
||||
"url": "test url",
|
||||
"filepath": "test filepath",
|
||||
"chunk_id": "test chunk_id",
|
||||
}
|
||||
],
|
||||
"intent": "query used",
|
||||
}),
|
||||
),
|
||||
@@ -366,11 +370,11 @@ async def test_azure_on_your_data_string(
|
||||
additional_properties={"extra_body": expected_data_settings},
|
||||
)
|
||||
assert len(content.messages) == 1
|
||||
assert len(content.messages[0].contents) == 3
|
||||
assert isinstance(content.messages[0].contents[0], FunctionCallContent)
|
||||
assert isinstance(content.messages[0].contents[1], FunctionResultContent)
|
||||
assert isinstance(content.messages[0].contents[2], TextContent)
|
||||
assert content.messages[0].contents[2].text == "test"
|
||||
assert len(content.messages[0].contents) == 1
|
||||
assert isinstance(content.messages[0].contents[0], TextContent)
|
||||
assert len(content.messages[0].contents[0].annotations) == 1
|
||||
assert content.messages[0].contents[0].annotations[0].title == "test title"
|
||||
assert content.messages[0].contents[0].text == "test"
|
||||
|
||||
mock_create.assert_awaited_once_with(
|
||||
model=azure_openai_unit_test_env["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"],
|
||||
@@ -437,55 +441,6 @@ async def test_azure_on_your_data_fail(
|
||||
)
|
||||
|
||||
|
||||
@patch.object(AsyncChatCompletions, "create", new_callable=AsyncMock)
|
||||
async def test_azure_on_your_data_split_messages(
|
||||
mock_create: AsyncMock,
|
||||
azure_openai_unit_test_env: dict[str, str],
|
||||
chat_history: list[ChatMessage],
|
||||
mock_chat_completion_response: ChatCompletion,
|
||||
) -> None:
|
||||
mock_chat_completion_response.choices = [
|
||||
Choice(
|
||||
index=0,
|
||||
message=ChatCompletionMessage(
|
||||
content="test",
|
||||
role="assistant",
|
||||
context={ # type: ignore
|
||||
"citations": {
|
||||
"content": "test content",
|
||||
"title": "test title",
|
||||
"url": "test url",
|
||||
"filepath": "test filepath",
|
||||
"chunk_id": "test chunk_id",
|
||||
},
|
||||
"intent": "query used",
|
||||
},
|
||||
),
|
||||
finish_reason="stop",
|
||||
)
|
||||
]
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
prompt = "hello world"
|
||||
messages_in = chat_history
|
||||
messages_in.append(ChatMessage(text=prompt, role="user"))
|
||||
messages_out: list[ChatMessage] = []
|
||||
messages_out.append(ChatMessage(text=prompt, role="user"))
|
||||
|
||||
azure_chat_client = AzureChatClient()
|
||||
|
||||
content = await azure_chat_client.get_response(
|
||||
messages=messages_in,
|
||||
)
|
||||
message = azure_chat_client._split_message(content)
|
||||
assert len(content.messages) == 1
|
||||
assert len(content.messages[0].contents) == 3
|
||||
assert isinstance(content.messages[0].contents[0], FunctionCallContent)
|
||||
assert isinstance(content.messages[0].contents[1], FunctionResultContent)
|
||||
assert isinstance(content.messages[0].contents[2], TextContent)
|
||||
assert content.messages[0].contents[2].text == "test"
|
||||
assert message.messages[0].contents == [content.messages[0].contents[0]]
|
||||
|
||||
|
||||
CONTENT_FILTERED_ERROR_MESSAGE = (
|
||||
"The response was filtered due to the prompt triggering Azure OpenAI's content management policy. Please "
|
||||
"modify your prompt and retry. To learn more about our content filtering policies please read our "
|
||||
@@ -607,7 +562,7 @@ async def test_bad_request_non_content_filter(
|
||||
|
||||
|
||||
@patch.object(AsyncChatCompletions, "create", new_callable=AsyncMock)
|
||||
async def test_cmc_streaming(
|
||||
async def test_get_streaming(
|
||||
mock_create: AsyncMock,
|
||||
azure_openai_unit_test_env: dict[str, str],
|
||||
chat_history: list[ChatMessage],
|
||||
@@ -646,7 +601,7 @@ def get_story_text() -> str:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_openai_chat_client_response() -> None:
|
||||
"""Test Azure OpenAI chat completion responses."""
|
||||
azure_chat_client = AzureChatClient()
|
||||
azure_chat_client = AzureChatClient(ad_credential=DefaultAzureCredential())
|
||||
assert isinstance(azure_chat_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -672,7 +627,7 @@ async def test_azure_openai_chat_client_response() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_openai_chat_client_response_tools() -> None:
|
||||
"""Test AzureOpenAI chat completion responses."""
|
||||
azure_chat_client = AzureChatClient()
|
||||
azure_chat_client = AzureChatClient(ad_credential=DefaultAzureCredential())
|
||||
assert isinstance(azure_chat_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -693,7 +648,7 @@ async def test_azure_openai_chat_client_response_tools() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_openai_chat_client_streaming() -> None:
|
||||
"""Test Azure OpenAI chat completion responses."""
|
||||
azure_chat_client = AzureChatClient()
|
||||
azure_chat_client = AzureChatClient(ad_credential=DefaultAzureCredential())
|
||||
assert isinstance(azure_chat_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
@@ -725,7 +680,7 @@ async def test_azure_openai_chat_client_streaming() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_openai_chat_client_streaming_tools() -> None:
|
||||
"""Test AzureOpenAI chat completion responses."""
|
||||
azure_chat_client = AzureChatClient()
|
||||
azure_chat_client = AzureChatClient(ad_credential=DefaultAzureCredential())
|
||||
assert isinstance(azure_chat_client, ChatClient)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
|
||||
@@ -6,7 +6,8 @@ from typing import Annotated
|
||||
import pytest
|
||||
from agent_framework import ChatClient, ChatMessage, ChatResponse, ChatResponseUpdate, TextContent, ai_function
|
||||
from agent_framework.azure import AzureResponsesClient
|
||||
from agent_framework.exceptions import ServiceInitializationError, ServiceResponseException
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from pydantic import BaseModel
|
||||
|
||||
skip_if_azure_integration_tests_disabled = pytest.mark.skipif(
|
||||
@@ -104,7 +105,7 @@ def test_serialize(azure_openai_unit_test_env: dict[str, str]) -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_responses_client_response() -> None:
|
||||
"""Test azure responses client responses."""
|
||||
azure_responses_client = AzureResponsesClient()
|
||||
azure_responses_client = AzureResponsesClient(ad_credential=DefaultAzureCredential())
|
||||
|
||||
assert isinstance(azure_responses_client, ChatClient)
|
||||
|
||||
@@ -147,7 +148,7 @@ async def test_azure_responses_client_response() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_responses_client_response_tools() -> None:
|
||||
"""Test azure responses client tools."""
|
||||
azure_responses_client = AzureResponsesClient()
|
||||
azure_responses_client = AzureResponsesClient(ad_credential=DefaultAzureCredential())
|
||||
|
||||
assert isinstance(azure_responses_client, ChatClient)
|
||||
|
||||
@@ -186,7 +187,7 @@ async def test_azure_responses_client_response_tools() -> None:
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_responses_client_streaming() -> None:
|
||||
"""Test Azure azure responses client streaming responses."""
|
||||
azure_responses_client = AzureResponsesClient()
|
||||
azure_responses_client = AzureResponsesClient(ad_credential=DefaultAzureCredential())
|
||||
|
||||
assert isinstance(azure_responses_client, ChatClient)
|
||||
|
||||
@@ -219,29 +220,27 @@ async def test_azure_responses_client_streaming() -> None:
|
||||
messages.append(ChatMessage(role="user", text="The weather in Seattle is sunny"))
|
||||
messages.append(ChatMessage(role="user", text="What is the weather in Seattle?"))
|
||||
|
||||
# This is currently broken. See https://github.com/azure/azure-python/issues/2305
|
||||
with pytest.raises(ServiceResponseException):
|
||||
response = azure_responses_client.get_streaming_response(
|
||||
messages=messages,
|
||||
response_format=OutputStruct,
|
||||
)
|
||||
full_message = ""
|
||||
async for chunk in response:
|
||||
assert chunk is not None
|
||||
assert isinstance(chunk, ChatResponseUpdate)
|
||||
for content in chunk.contents:
|
||||
if isinstance(content, TextContent) and content.text:
|
||||
full_message += content.text
|
||||
response = azure_responses_client.get_streaming_response(
|
||||
messages=messages,
|
||||
response_format=OutputStruct,
|
||||
)
|
||||
full_message = ""
|
||||
async for chunk in response:
|
||||
assert chunk is not None
|
||||
assert isinstance(chunk, ChatResponseUpdate)
|
||||
for content in chunk.contents:
|
||||
if isinstance(content, TextContent) and content.text:
|
||||
full_message += content.text
|
||||
|
||||
output = OutputStruct.model_validate_json(full_message)
|
||||
assert "Seattle" in output.location
|
||||
assert "sunny" in output.weather.lower()
|
||||
output = OutputStruct.model_validate_json(full_message)
|
||||
assert "Seattle" in output.location
|
||||
assert "sunny" in output.weather.lower()
|
||||
|
||||
|
||||
@skip_if_azure_integration_tests_disabled
|
||||
async def test_azure_responses_client_streaming_tools() -> None:
|
||||
"""Test azure responses client streaming tools."""
|
||||
azure_responses_client = AzureResponsesClient()
|
||||
azure_responses_client = AzureResponsesClient(ad_credential=DefaultAzureCredential())
|
||||
|
||||
assert isinstance(azure_responses_client, ChatClient)
|
||||
|
||||
@@ -266,22 +265,20 @@ async def test_azure_responses_client_streaming_tools() -> None:
|
||||
messages.clear()
|
||||
messages.append(ChatMessage(role="user", text="What is the weather in Seattle?"))
|
||||
|
||||
# This is currently broken. See https://github.com/azure/azure-python/issues/2305
|
||||
with pytest.raises(ServiceResponseException):
|
||||
response = azure_responses_client.get_streaming_response(
|
||||
messages=messages,
|
||||
tools=[get_weather],
|
||||
tool_choice="auto",
|
||||
response_format=OutputStruct,
|
||||
)
|
||||
full_message = ""
|
||||
async for chunk in response:
|
||||
assert chunk is not None
|
||||
assert isinstance(chunk, ChatResponseUpdate)
|
||||
for content in chunk.contents:
|
||||
if isinstance(content, TextContent) and content.text:
|
||||
full_message += content.text
|
||||
response = azure_responses_client.get_streaming_response(
|
||||
messages=messages,
|
||||
tools=[get_weather],
|
||||
tool_choice="auto",
|
||||
response_format=OutputStruct,
|
||||
)
|
||||
full_message = ""
|
||||
async for chunk in response:
|
||||
assert chunk is not None
|
||||
assert isinstance(chunk, ChatResponseUpdate)
|
||||
for content in chunk.contents:
|
||||
if isinstance(content, TextContent) and content.text:
|
||||
full_message += content.text
|
||||
|
||||
output = OutputStruct.model_validate_json(full_message)
|
||||
assert "Seattle" in output.location
|
||||
assert "sunny" in output.weather.lower()
|
||||
output = OutputStruct.model_validate_json(full_message)
|
||||
assert "Seattle" in output.location
|
||||
assert "sunny" in output.weather.lower()
|
||||
|
||||
Reference in New Issue
Block a user