mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: additional Foundry Tools (#611)
* initial work on additional foundry tools * fixes * fix tests * fix import * updated lock * added hosted MCP for foundry * fixes * fix for test * updated samples * fix result parsing
This commit is contained in:
committed by
GitHub
Unverified
parent
3571a7d321
commit
9eb68ab2f9
@@ -224,11 +224,18 @@ class HostedWebSearchTool(BaseTool):
|
||||
additional_properties: Additional properties associated with the tool
|
||||
(e.g., {"user_location": {"city": "Seattle", "country": "US"}}).
|
||||
**kwargs: Additional keyword arguments to pass to the base class.
|
||||
if additional_properties is not provided, any kwargs will be added to additional_properties.
|
||||
"""
|
||||
args: dict[str, Any] = {
|
||||
"name": "web_search",
|
||||
}
|
||||
super().__init__(**args, **kwargs)
|
||||
if additional_properties is not None:
|
||||
args["additional_properties"] = additional_properties
|
||||
elif kwargs:
|
||||
args["additional_properties"] = kwargs
|
||||
if description is not None:
|
||||
args["description"] = description
|
||||
super().__init__(**args)
|
||||
|
||||
|
||||
class HostedMCPSpecificApproval(TypedDict, total=False):
|
||||
|
||||
@@ -273,7 +273,11 @@ def _process_update(
|
||||
if response.additional_properties is None:
|
||||
response.additional_properties = {}
|
||||
response.additional_properties.update(update.additional_properties)
|
||||
|
||||
if response.raw_representation is None:
|
||||
response.raw_representation = []
|
||||
if not isinstance(response.raw_representation, list):
|
||||
response.raw_representation = [response.raw_representation]
|
||||
response.raw_representation.append(update.raw_representation)
|
||||
if isinstance(response, ChatResponse) and isinstance(update, ChatResponseUpdate):
|
||||
if update.conversation_id is not None:
|
||||
response.conversation_id = update.conversation_id
|
||||
@@ -347,7 +351,7 @@ class BaseAnnotation(AFBaseModel):
|
||||
|
||||
annotated_regions: list[AnnotatedRegions] | None = None
|
||||
additional_properties: dict[str, Any] | None = None
|
||||
raw_representation: Any | None = Field(default=None, repr=False)
|
||||
raw_representation: Any | None = Field(default=None, repr=False, exclude=True)
|
||||
|
||||
|
||||
class CitationAnnotation(BaseAnnotation):
|
||||
|
||||
@@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, Any, ClassVar, Final, TypeVar
|
||||
|
||||
from opentelemetry import metrics, trace
|
||||
from opentelemetry.semconv_ai import GenAISystem, Meters, SpanAttributes
|
||||
from pydantic import PrivateAttr
|
||||
from pydantic import BaseModel, PrivateAttr
|
||||
|
||||
from . import __version__ as version_info
|
||||
from ._logging import get_logger
|
||||
@@ -408,19 +408,14 @@ class OtelSettings(AFBaseSettings):
|
||||
) -> None:
|
||||
"""Setup telemetry based on the settings.
|
||||
|
||||
If both connection_string and otlp_endpoint both will be used.
|
||||
|
||||
Args:
|
||||
credential: The credential to use for Azure Monitor Entra ID authentication. Default is None.
|
||||
additional_exporters: A list of additional exporters to add to the configuration. Default is None.
|
||||
force_setup: Force the setup to be executed even if it has already been executed. Default is False.
|
||||
"""
|
||||
if (not self.ENABLED and not self.ENABLED) or (self._executed_setup and not force_setup):
|
||||
if (not self.ENABLED) or (self._executed_setup and not force_setup):
|
||||
return
|
||||
|
||||
if not self.applicationinsights_connection_string and not self.otlp_endpoint and not additional_exporters:
|
||||
logger.warning("Telemetry is enabled but no connection string or OTLP endpoint is provided.")
|
||||
|
||||
global_logger = logging.getLogger()
|
||||
global_logger.setLevel(logging.NOTSET)
|
||||
exporters: list["LogExporter | SpanExporter | MetricExporter"] = additional_exporters or []
|
||||
@@ -639,11 +634,6 @@ def setup_observability(
|
||||
these will be added directly, and allows you to customize the spans completely
|
||||
|
||||
"""
|
||||
if isinstance(otlp_endpoint, str):
|
||||
otlp_endpoint = [otlp_endpoint]
|
||||
if isinstance(applicationinsights_connection_string, str):
|
||||
applicationinsights_connection_string = [applicationinsights_connection_string]
|
||||
|
||||
global OTEL_SETTINGS
|
||||
# Update the otel settings with the provided values
|
||||
OTEL_SETTINGS.enable_otel = True
|
||||
@@ -654,30 +644,36 @@ def setup_observability(
|
||||
# Run the initial setup, which will create the providers, and add env setting exporters
|
||||
new_exporters: list["LogExporter | SpanExporter | MetricExporter"] = []
|
||||
if OTEL_SETTINGS.ENABLED and (otlp_endpoint or applicationinsights_connection_string or exporters):
|
||||
# check if endpoints or connection strings are already configured
|
||||
# create the exporters, after checking if they are already configured through the env.
|
||||
new_exporters = exporters or []
|
||||
if otlp_endpoint:
|
||||
otlp_endpoint = [
|
||||
endpoint for endpoint in otlp_endpoint if OTEL_SETTINGS.check_endpoint_already_configured(endpoint)
|
||||
]
|
||||
if applicationinsights_connection_string:
|
||||
applicationinsights_connection_string = [
|
||||
conn_str
|
||||
for conn_str in applicationinsights_connection_string
|
||||
if OTEL_SETTINGS.check_connection_string_already_configured(conn_str)
|
||||
]
|
||||
if otlp_endpoint or applicationinsights_connection_string or exporters:
|
||||
new_exporters = exporters or []
|
||||
if isinstance(otlp_endpoint, str):
|
||||
otlp_endpoint = [otlp_endpoint]
|
||||
new_exporters.extend(
|
||||
get_exporters(
|
||||
otlp_endpoints=otlp_endpoint,
|
||||
connection_strings=applicationinsights_connection_string,
|
||||
_get_otlp_exporters(
|
||||
endpoints=[
|
||||
endpoint
|
||||
for endpoint in otlp_endpoint
|
||||
if not OTEL_SETTINGS.check_endpoint_already_configured(endpoint)
|
||||
]
|
||||
)
|
||||
)
|
||||
if applicationinsights_connection_string:
|
||||
if isinstance(applicationinsights_connection_string, str):
|
||||
applicationinsights_connection_string = [applicationinsights_connection_string]
|
||||
new_exporters.extend(
|
||||
_get_azure_monitor_exporters(
|
||||
connection_strings=[
|
||||
conn_str
|
||||
for conn_str in applicationinsights_connection_string
|
||||
if not OTEL_SETTINGS.check_connection_string_already_configured(conn_str)
|
||||
],
|
||||
credential=credential,
|
||||
)
|
||||
)
|
||||
OTEL_SETTINGS.setup_observability(
|
||||
credential=credential, additional_exporters=new_exporters, force_setup=bool(new_exporters)
|
||||
)
|
||||
# Add any additional exporters
|
||||
|
||||
|
||||
# region Chat Client Telemetry
|
||||
@@ -1243,7 +1239,23 @@ def _to_otel_part(content: "Contents") -> dict[str, Any] | None:
|
||||
case "function_call":
|
||||
return {"type": "tool_call", "id": content.call_id, "name": content.name, "arguments": content.arguments}
|
||||
case "function_result":
|
||||
return {"type": "tool_call_response", "id": content.call_id, "response": content.result}
|
||||
response: Any | None = None
|
||||
if content.result:
|
||||
if isinstance(content.result, list):
|
||||
res: list[Any] = []
|
||||
for item in content.result: # type: ignore
|
||||
from ._types import BaseContent
|
||||
|
||||
if isinstance(item, BaseContent):
|
||||
res.append(_to_otel_part(item)) # type: ignore
|
||||
elif isinstance(item, BaseModel):
|
||||
res.append(item.model_dump(exclude_none=True))
|
||||
else:
|
||||
res.append(json.dumps(item))
|
||||
response = json.dumps(res)
|
||||
else:
|
||||
response = json.dumps(content.result)
|
||||
return {"type": "tool_call_response", "id": content.call_id, "response": response}
|
||||
case _:
|
||||
# GenericPart in otel output messages json spec.
|
||||
# just required type, and arbitrary other fields.
|
||||
|
||||
Reference in New Issue
Block a user