mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: fix string parsing in azure openai client (#1023)
* fix string parsing in azure openai client * test fix * changed setup func name and check if there is a conn string * redid parsing in safe way
This commit is contained in:
committed by
GitHub
Unverified
parent
f7e9490494
commit
3eb26632ce
@@ -83,7 +83,7 @@ from azure.ai.agents.models import (
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
from azure.ai.projects.models import ConnectionType
|
||||
from azure.core.credentials_async import AsyncTokenCredential
|
||||
from azure.core.exceptions import HttpResponseError
|
||||
from azure.core.exceptions import HttpResponseError, ResourceNotFoundError
|
||||
from pydantic import BaseModel, Field, PrivateAttr, ValidationError
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
@@ -216,17 +216,25 @@ class AzureAIAgentClient(BaseChatClient):
|
||||
)
|
||||
self._should_close_client = should_close_client
|
||||
|
||||
async def setup_observability(self) -> None:
|
||||
async def setup_azure_ai_observability(self, enable_sensitive_data: bool | None = None) -> None:
|
||||
"""Use this method to setup tracing in your Azure AI Project.
|
||||
|
||||
This will take the connection string from the project project_client.
|
||||
It will override any connection string that is set in the environment variables.
|
||||
It will disable any OTLP endpoint that might have been set.
|
||||
"""
|
||||
try:
|
||||
conn_string = await self.project_client.telemetry.get_application_insights_connection_string()
|
||||
except ResourceNotFoundError:
|
||||
logger.warning(
|
||||
"No Application Insights connection string found for the Azure AI Project, "
|
||||
"please call setup_observability() manually."
|
||||
)
|
||||
return
|
||||
from agent_framework.observability import setup_observability
|
||||
|
||||
setup_observability(
|
||||
applicationinsights_connection_string=await self.project_client.telemetry.get_application_insights_connection_string(), # noqa: E501
|
||||
applicationinsights_connection_string=conn_string, enable_sensitive_data=enable_sensitive_data
|
||||
)
|
||||
|
||||
async def __aenter__(self) -> "Self":
|
||||
|
||||
@@ -4,8 +4,7 @@ from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any, ClassVar
|
||||
|
||||
from openai.lib.azure import AsyncAzureADTokenProvider, AsyncAzureOpenAI
|
||||
from pydantic import SecretStr, ValidationError
|
||||
from pydantic.networks import AnyUrl
|
||||
from pydantic import ValidationError
|
||||
|
||||
from ..exceptions import ServiceInitializationError
|
||||
from ..openai import OpenAIAssistantsClient
|
||||
@@ -72,9 +71,10 @@ class AzureOpenAIAssistantsClient(OpenAIAssistantsClient):
|
||||
"""
|
||||
try:
|
||||
azure_openai_settings = AzureOpenAISettings(
|
||||
api_key=SecretStr(api_key) if api_key else None,
|
||||
base_url=AnyUrl(base_url) if base_url else None,
|
||||
endpoint=AnyUrl(endpoint) if endpoint else None,
|
||||
# pydantic settings will see if there is a value, if not, will try the env var or .env file
|
||||
api_key=api_key, # type: ignore
|
||||
base_url=base_url, # type: ignore
|
||||
endpoint=endpoint, # type: ignore
|
||||
chat_deployment_name=deployment_name,
|
||||
api_version=api_version,
|
||||
env_file_path=env_file_path,
|
||||
|
||||
@@ -10,8 +10,7 @@ from azure.core.credentials import TokenCredential
|
||||
from openai.lib.azure import AsyncAzureADTokenProvider, AsyncAzureOpenAI
|
||||
from openai.types.chat.chat_completion import Choice
|
||||
from openai.types.chat.chat_completion_chunk import Choice as ChunkChoice
|
||||
from pydantic import SecretStr, ValidationError
|
||||
from pydantic.networks import AnyUrl
|
||||
from pydantic import ValidationError
|
||||
|
||||
from agent_framework import (
|
||||
ChatResponse,
|
||||
@@ -92,9 +91,10 @@ class AzureOpenAIChatClient(AzureOpenAIConfigMixin, OpenAIBaseChatClient):
|
||||
try:
|
||||
# Filter out any None values from the arguments
|
||||
azure_openai_settings = AzureOpenAISettings(
|
||||
api_key=SecretStr(api_key) if api_key else None,
|
||||
base_url=AnyUrl(base_url) if base_url else None,
|
||||
endpoint=AnyUrl(endpoint) if endpoint else None,
|
||||
# pydantic settings will see if there is a value, if not, will try the env var or .env file
|
||||
api_key=api_key, # type: ignore
|
||||
base_url=base_url, # type: ignore
|
||||
endpoint=endpoint, # type: ignore
|
||||
chat_deployment_name=deployment_name,
|
||||
api_version=api_version,
|
||||
env_file_path=env_file_path,
|
||||
|
||||
@@ -6,8 +6,7 @@ from urllib.parse import urljoin
|
||||
|
||||
from azure.core.credentials import TokenCredential
|
||||
from openai.lib.azure import AsyncAzureADTokenProvider, AsyncAzureOpenAI
|
||||
from pydantic import SecretStr, ValidationError
|
||||
from pydantic.networks import AnyUrl
|
||||
from pydantic import ValidationError
|
||||
|
||||
from agent_framework import use_chat_middleware, use_function_invocation
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
@@ -71,11 +70,11 @@ class AzureOpenAIResponsesClient(AzureOpenAIConfigMixin, OpenAIBaseResponsesClie
|
||||
prompts could use `developer` or `system`. (Optional)
|
||||
"""
|
||||
try:
|
||||
# Filter out any None values from the arguments
|
||||
azure_openai_settings = AzureOpenAISettings(
|
||||
api_key=SecretStr(api_key) if api_key else None,
|
||||
base_url=AnyUrl(base_url) if base_url else None,
|
||||
endpoint=AnyUrl(endpoint) if endpoint else None,
|
||||
# pydantic settings will see if there is a value, if not, will try the env var or .env file
|
||||
api_key=api_key, # type: ignore
|
||||
base_url=base_url, # type: ignore
|
||||
endpoint=endpoint, # type: ignore
|
||||
responses_deployment_name=deployment_name,
|
||||
api_version=api_version,
|
||||
env_file_path=env_file_path,
|
||||
@@ -89,9 +88,10 @@ class AzureOpenAIResponsesClient(AzureOpenAIConfigMixin, OpenAIBaseResponsesClie
|
||||
if (
|
||||
not azure_openai_settings.base_url
|
||||
and azure_openai_settings.endpoint
|
||||
and str(azure_openai_settings.endpoint).rstrip("/").endswith("openai.azure.com")
|
||||
and azure_openai_settings.endpoint.host
|
||||
and azure_openai_settings.endpoint.host.endswith(".openai.azure.com")
|
||||
):
|
||||
azure_openai_settings.base_url = AnyUrl(urljoin(str(azure_openai_settings.endpoint), "/openai/v1/"))
|
||||
azure_openai_settings.base_url = urljoin(str(azure_openai_settings.endpoint), "/openai/v1/") # type: ignore
|
||||
except ValidationError as exc:
|
||||
raise ServiceInitializationError(f"Failed to validate settings: {exc}") from exc
|
||||
|
||||
|
||||
@@ -131,7 +131,6 @@ def test_serialize(azure_openai_unit_test_env: dict[str, str]) -> None:
|
||||
azure_chat_client = AzureOpenAIChatClient.from_dict(settings)
|
||||
dumped_settings = azure_chat_client.to_dict()
|
||||
assert dumped_settings["ai_model_id"] == settings["deployment_name"]
|
||||
assert str(settings["endpoint"]) in str(dumped_settings["base_url"])
|
||||
assert str(settings["deployment_name"]) in str(dumped_settings["base_url"])
|
||||
assert settings["api_key"] == dumped_settings["api_key"]
|
||||
assert settings["api_version"] == dumped_settings["api_version"]
|
||||
|
||||
@@ -38,7 +38,7 @@ async def main() -> None:
|
||||
AzureAIAgentClient(async_credential=credential) as chat_client,
|
||||
):
|
||||
# enable azure-ai observability
|
||||
await chat_client.setup_observability()
|
||||
await chat_client.setup_azure_ai_observability()
|
||||
agent = chat_client.create_agent(
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
|
||||
@@ -50,7 +50,7 @@ async def main() -> None:
|
||||
AzureAIAgentClient(async_credential=credential) as chat_client,
|
||||
):
|
||||
# enable azure-ai observability
|
||||
await chat_client.setup_observability()
|
||||
await chat_client.setup_azure_ai_observability()
|
||||
agent = chat_client.create_agent(
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
|
||||
@@ -47,7 +47,7 @@ async def main():
|
||||
# This will enable tracing and configure the application to send telemetry data to the
|
||||
# Application Insights instance attached to the Azure AI project.
|
||||
# This will override any existing configuration.
|
||||
await client.setup_observability()
|
||||
await client.setup_azure_ai_observability()
|
||||
|
||||
questions = ["What's the weather in Amsterdam?", "and in Paris, and which is better?", "Why is the sky blue?"]
|
||||
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ async def main() -> None:
|
||||
# This will enable tracing and configure the application to send telemetry data to the
|
||||
# Application Insights instance attached to the Azure AI project.
|
||||
# This will override any existing configuration.
|
||||
await client.setup_observability()
|
||||
await client.setup_azure_ai_observability()
|
||||
|
||||
with get_tracer().start_as_current_span(
|
||||
name="Foundry Telemetry from Agent Framework", kind=SpanKind.CLIENT
|
||||
|
||||
Reference in New Issue
Block a user