|
11 | 11 |
|
12 | 12 | from opentelemetry import metrics, trace |
13 | 13 | from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE |
14 | | -from pydantic import Field |
| 14 | +from pydantic import BaseModel, Field |
15 | 15 |
|
16 | 16 | from semantic_kernel.filters.filter_types import FilterTypes |
17 | 17 | from semantic_kernel.filters.functions.function_invocation_context import FunctionInvocationContext |
|
35 | 35 | from semantic_kernel.utils.telemetry.model_diagnostics import function_tracer |
36 | 36 | from semantic_kernel.utils.telemetry.model_diagnostics.gen_ai_attributes import TOOL_CALL_ARGUMENTS, TOOL_CALL_RESULT |
37 | 37 |
|
| 38 | +from ..contents.chat_message_content import ChatMessageContent |
| 39 | +from ..contents.text_content import TextContent |
| 40 | + |
38 | 41 | if TYPE_CHECKING: |
39 | 42 | from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings |
40 | 43 | from semantic_kernel.contents.streaming_content_mixin import StreamingContentMixin |
@@ -405,3 +408,76 @@ def _handle_exception(self, current_span: trace.Span, exception: Exception, attr |
405 | 408 | current_span.set_status(trace.StatusCode.ERROR, description=str(exception)) |
406 | 409 |
|
407 | 410 | KernelFunctionLogMessages.log_function_error(logger, exception) |
| 411 | + |
| 412 | + def as_agent_framework_tool( |
| 413 | + self, |
| 414 | + *, |
| 415 | + name: str | None = None, |
| 416 | + description: str | None = None, |
| 417 | + kernel: "Kernel | None" = None, |
| 418 | + ) -> Any: |
| 419 | + """Convert the function to an agent framework tool. |
| 420 | +
|
| 421 | + Args: |
| 422 | + name: The name of the tool, if None, the function name is used. |
| 423 | + description: The description of the tool, if None, the tool description is used. |
| 424 | + kernel: The kernel to use, if None, a kernel is created. |
| 425 | +
|
| 426 | + Returns: |
| 427 | + AIFunction: The agent framework tool. |
| 428 | + """ |
| 429 | + import json |
| 430 | + |
| 431 | + from pydantic import Field, create_model |
| 432 | + |
| 433 | + from semantic_kernel.kernel import Kernel |
| 434 | + |
| 435 | + try: |
| 436 | + from agent_framework import AIFunction |
| 437 | + |
| 438 | + except ImportError as e: |
| 439 | + raise ImportError( |
| 440 | + "agent_framework is not installed. Please install it with 'pip install agent-framework-core'" |
| 441 | + ) from e |
| 442 | + |
| 443 | + if not kernel: |
| 444 | + kernel = Kernel() |
| 445 | + name = name or self.name |
| 446 | + description = description or self.description |
| 447 | + fields = {} |
| 448 | + for param in self.parameters: |
| 449 | + if param.include_in_function_choices: |
| 450 | + if param.default_value is not None: |
| 451 | + fields[param.name] = ( |
| 452 | + param.type_, |
| 453 | + Field(description=param.description, default=param.default_value), |
| 454 | + ) |
| 455 | + fields[param.name] = (param.type_, Field(description=param.description)) |
| 456 | + input_model = create_model("InputModel", **fields) # type: ignore |
| 457 | + |
| 458 | + async def wrapper(*args: Any, **kwargs: Any) -> Any: |
| 459 | + result = await self.invoke(kernel, *args, **kwargs) |
| 460 | + if result and result.value is not None: |
| 461 | + if isinstance(result.value, list): |
| 462 | + results: list[Any] = [] |
| 463 | + for value in result.value: |
| 464 | + if isinstance(value, ChatMessageContent): |
| 465 | + results.append(str(value)) |
| 466 | + continue |
| 467 | + if isinstance(value, TextContent): |
| 468 | + results.append(value.text) |
| 469 | + continue |
| 470 | + if isinstance(value, BaseModel): |
| 471 | + results.append(value.model_dump()) |
| 472 | + continue |
| 473 | + results.append(value) |
| 474 | + return json.dumps(results) if len(results) > 1 else json.dumps(results[0]) |
| 475 | + return json.dumps(result.value) |
| 476 | + return "The function did not return a result." |
| 477 | + |
| 478 | + return AIFunction( |
| 479 | + name=name, |
| 480 | + description=description, |
| 481 | + input_model=input_model, |
| 482 | + func=wrapper, |
| 483 | + ) |
0 commit comments