Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 62 additions & 65 deletions azure/functions/decorators/function_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
parse_iterable_param_to_enums, StringifyEnumJsonEncoder
from azure.functions.http import HttpRequest
from .generic import GenericInputBinding, GenericTrigger, GenericOutputBinding
from .openai import AssistantSkillTrigger, OpenAIModels, TextCompletionInput, \
AssistantCreateOutput, \
AssistantQueryInput, AssistantPostInput, InputType, EmbeddingsInput, \
from .openai import _AssistantSkillTrigger, OpenAIModels, _TextCompletionInput, \
_AssistantCreateOutput, \
_AssistantQueryInput, _AssistantPostInput, InputType, _EmbeddingsInput, \
semantic_search_system_prompt, \
SemanticSearchInput, EmbeddingsStoreOutput
from .mcp import MCPToolTrigger, build_property_metadata
_SemanticSearchInput, _EmbeddingsStoreOutput
from .mcp import _MCPToolTrigger, build_property_metadata
from .retry_policy import RetryPolicy
from .function_name import FunctionName
from .warmup import WarmUpTrigger
Expand Down Expand Up @@ -1533,8 +1533,7 @@ def mcp_tool_trigger(self,
tool_properties: Optional[str] = None,
data_type: Optional[Union[DataType, str]] = None,
**kwargs) -> Callable[..., Any]:
"""
The `mcp_tool_trigger` decorator adds :class:`MCPToolTrigger` to the
"""The `mcp_tool_trigger` decorator adds :class:`MCPToolTrigger` to the
:class:`FunctionBuilder` object for building a :class:`Function` object
used in the worker function indexing model.

Expand Down Expand Up @@ -1563,7 +1562,7 @@ def mcp_tool_trigger(self,
def wrap(fb):
def decorator():
fb.add_trigger(
trigger=MCPToolTrigger(
trigger=_MCPToolTrigger(
name=arg_name,
tool_name=tool_name,
description=description,
Expand All @@ -1578,12 +1577,12 @@ def decorator():
return wrap

def mcp_tool(self):
"""
Decorator to register an MCP tool function.
"""Decorator to register an MCP tool function.
Ref: https://aka.ms/remote-mcp-functions-python

Automatically:
This decorator performs the following actions automatically:
- Infers tool name from function name
- Extracts first line of docstring as description
- Extracts docstrings as description
- Extracts parameters and types for tool properties
- Handles MCPToolContext injection
"""
Expand Down Expand Up @@ -1645,7 +1644,7 @@ async def wrapper(context: str, *args, **kwargs):

# Add the MCP trigger
fb.add_trigger(
trigger=MCPToolTrigger(
trigger=_MCPToolTrigger(
name="context",
tool_name=tool_name,
description=description,
Expand All @@ -1663,23 +1662,16 @@ def mcp_tool_property(self, arg_name: str,
as_array: Optional[bool] = False):
"""
Decorator for defining explicit MCP tool property metadata for a specific argument.
Ref: https://aka.ms/remote-mcp-functions-python

:param arg_name: The name of the argument.
:param description: The description of the argument.
:param property_type: The type of the argument.
:param is_required: If the argument is required or not.
:param as_array: If the argument should be passed as an array or not.

:param str arg_name: The name of the argument.
:keyword str description: The description of the argument.
:keyword property_type: The type of the argument.
:type property_type:
~azure.functions.decorators.core.McpPropertyType
:keyword bool is_required: If the argument is required or not.
:keyword bool as_array: If the argument should be passed as an array or not.
:return: Decorator function.

Example:
@app.mcp_tool_property(
arg_name="snippetname",
description="The name of the snippet.",
property_type=func.McpPropertyType.STRING,
is_required=True,
as_array=False
)
"""
def decorator(func):
# If this function is already wrapped by FunctionBuilder or similar, unwrap it
Expand Down Expand Up @@ -1859,43 +1851,44 @@ def assistant_skill_trigger(self,
data_type: Optional[
Union[DataType, str]] = None,
**kwargs: Any) -> Callable[..., Any]:
"""
Assistants build on top of chat functionality by supporting custom skills
"""Assistants build on top of chat functionality by supporting custom skills
defined as functions. This internally uses OpenAI’s function calling
capabilities in GPT models to determine which functions to invoke and when.

Ref: https://platform.openai.com/docs/guides/function-calling

You can define functions to be triggered by assistants using the
`assistantSkillTrigger` trigger binding. These functions are invoked by the
assistantSkillTrigger trigger binding. These functions are invoked by the
extension when an assistant signals it would like to invoke a function in
response to a user prompt.

The function name, its description (provided via the trigger), and the
parameter descriptions are all used as hints by the language model to
determine when and how to invoke an assistant function.

:param arg_name: The name of the trigger parameter in the function code.
:param function_description: A description of the assistant function,
:param str arg_name: The name of the trigger parameter in the function code.
:param str function_description: A description of the assistant function,
which is provided to the model.
:param function_name: The name of the assistant function, which is
:keyword str function_name: The name of the assistant function, which is
passed to the language model.
:param parameter_description_json: A JSON-formatted description of the
:keyword str parameter_description_json: A JSON-formatted description of the
function parameters, provided to the model.
If omitted, the description is autogenerated.
:param data_type: Defines how the Functions runtime should treat the
:keyword data_type: Defines how the Functions runtime should treat the
parameter value.
:param kwargs: Additional keyword arguments for specifying binding fields
:type data_type:
~azure.functions.decorators.core.DataType or
str or None
:keyword kwargs: Additional keyword arguments for specifying binding fields
to include in the `function.json`.

:return: Decorator function.
"""

@self._configure_function_builder
def wrap(fb):
def decorator():
fb.add_trigger(
trigger=AssistantSkillTrigger(
trigger=_AssistantSkillTrigger(
name=arg_name,
function_description=function_description,
function_name=function_name,
Expand Down Expand Up @@ -3413,7 +3406,7 @@ def text_completion_input(self,
def wrap(fb):
def decorator():
fb.add_binding(
binding=TextCompletionInput(
binding=_TextCompletionInput(
name=arg_name,
prompt=prompt,
ai_connection_name=ai_connection_name,
Expand All @@ -3436,22 +3429,24 @@ def assistant_create_output(self, arg_name: str,
Union[DataType, str]] = None,
**kwargs) \
-> Callable[..., Any]:
"""
The `assistantCreate` output binding creates a new assistant with a specified system prompt.

:param arg_name: The name of the binding parameter in the function code.
:param data_type: Defines how the Functions runtime should treat the parameter value.
:param kwargs: Additional keyword arguments for specifying extra binding fields
"""The assistantCreate output binding creates a new assistant with a specified system
prompt.

:param str arg_name: The name of the binding parameter in the function code.
:keyword data_type: Defines how the Functions runtime should treat the parameter value.
:type data_type:
~azure.functions.decorators.core.DataType or
str or None
:keyword kwargs: Additional keyword arguments for specifying extra binding fields
to include in the `function.json`.

:return: Decorator function.
"""

@self._configure_function_builder
def wrap(fb):
def decorator():
fb.add_binding(
binding=AssistantCreateOutput(
binding=_AssistantCreateOutput(
name=arg_name,
data_type=parse_singular_param_to_enum(data_type,
DataType),
Expand All @@ -3472,27 +3467,29 @@ def assistant_query_input(self,
Union[DataType, str]] = None,
**kwargs) \
-> Callable[..., Any]:
"""
The `assistantQuery` input binding retrieves assistant chat history and
"""The `assistantQuery` input binding retrieves assistant chat history and
passes it to the function.

This is typically used to provide the function access to previous messages
in a conversation, enabling more context-aware responses.

:param arg_name: The name of the binding parameter in the function code.
:param timestamp_utc: The earliest timestamp (in UTC) for the messages to
:param str arg_name: The name of the binding parameter in the function code.
:param str id: The unique identifier of the assistant whose history is being
queried.
:param str timestamp_utc: The earliest timestamp (in UTC) for the messages to
retrieve from the chat history. Must be in ISO 8601 format, e.g.,
`"2023-08-01T00:00:00Z"`.
:param chat_storage_connection_setting: The name of the configuration section
:keyword str chat_storage_connection_setting: The name of the configuration section
containing the connection settings for assistant chat storage. Defaults to
`"AzureWebJobsStorage"`.
:param collection_name: The name of the table or collection used for assistant
chat storage. Defaults to `"ChatState"`.
:param id: The unique identifier of the assistant whose history is being
queried.
:param data_type: Defines how the Functions runtime should treat the
"AzureWebJobsStorage".
:keyword str collection_name: The name of the table or collection used for assistant
chat storage. Defaults to "ChatState".
:keyword data_type: Defines how the Functions runtime should treat the
parameter value.
:param kwargs: Additional keyword arguments for specifying binding fields to
:type data_type:
~azure.functions.decorators.core.DataType or
str or None
:keyword kwargs: Additional keyword arguments for specifying binding fields to
include in the `function.json`.

:return: Decorator function.
Expand All @@ -3502,7 +3499,7 @@ def assistant_query_input(self,
def wrap(fb):
def decorator():
fb.add_binding(
binding=AssistantQueryInput(
binding=_AssistantQueryInput(
name=arg_name,
id=id,
timestamp_utc=timestamp_utc,
Expand Down Expand Up @@ -3580,7 +3577,7 @@ def assistant_post_input(self, arg_name: str,
def wrap(fb):
def decorator():
fb.add_binding(
binding=AssistantPostInput(
binding=_AssistantPostInput(
name=arg_name,
id=id,
user_message=user_message,
Expand Down Expand Up @@ -3654,7 +3651,7 @@ def embeddings_input(self,
def wrap(fb):
def decorator():
fb.add_binding(
binding=EmbeddingsInput(
binding=_EmbeddingsInput(
name=arg_name,
input=input,
input_type=input_type,
Expand Down Expand Up @@ -3746,7 +3743,7 @@ def semantic_search_input(self,
def wrap(fb):
def decorator():
fb.add_binding(
binding=SemanticSearchInput(
binding=_SemanticSearchInput(
name=arg_name,
search_connection_name=search_connection_name,
collection=collection,
Expand Down Expand Up @@ -3829,7 +3826,7 @@ def embeddings_store_output(self,
def wrap(fb):
def decorator():
fb.add_binding(
binding=EmbeddingsStoreOutput(
binding=_EmbeddingsStoreOutput(
name=arg_name,
input=input,
input_type=input_type,
Expand Down
2 changes: 1 addition & 1 deletion azure/functions/decorators/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}


class MCPToolTrigger(Trigger):
class _MCPToolTrigger(Trigger):

@staticmethod
def get_binding_name() -> str:
Expand Down
16 changes: 8 additions & 8 deletions azure/functions/decorators/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class OpenAIModels(StringifyEnum):
DefaultEmbeddingsModel = "text-embedding-ada-002"


class AssistantSkillTrigger(Trigger):
class _AssistantSkillTrigger(Trigger):

@staticmethod
def get_binding_name() -> str:
Expand All @@ -42,7 +42,7 @@ def __init__(self,
super().__init__(name=name, data_type=data_type)


class TextCompletionInput(InputBinding):
class _TextCompletionInput(InputBinding):

@staticmethod
def get_binding_name() -> str:
Expand Down Expand Up @@ -71,7 +71,7 @@ def __init__(self,
super().__init__(name=name, data_type=data_type)


class AssistantQueryInput(InputBinding):
class _AssistantQueryInput(InputBinding):

@staticmethod
def get_binding_name():
Expand All @@ -92,7 +92,7 @@ def __init__(self,
super().__init__(name=name, data_type=data_type)


class EmbeddingsInput(InputBinding):
class _EmbeddingsInput(InputBinding):

@staticmethod
def get_binding_name() -> str:
Expand Down Expand Up @@ -137,7 +137,7 @@ def __init__(self,
to the end of your answer on a separate line."""


class SemanticSearchInput(InputBinding):
class _SemanticSearchInput(InputBinding):

@staticmethod
def get_binding_name() -> str:
Expand Down Expand Up @@ -179,7 +179,7 @@ def __init__(self,
super().__init__(name=name, data_type=data_type)


class AssistantPostInput(InputBinding):
class _AssistantPostInput(InputBinding):

@staticmethod
def get_binding_name():
Expand Down Expand Up @@ -214,7 +214,7 @@ def __init__(self, name: str,
super().__init__(name=name, data_type=data_type)


class EmbeddingsStoreOutput(OutputBinding):
class _EmbeddingsStoreOutput(OutputBinding):

@staticmethod
def get_binding_name() -> str:
Expand Down Expand Up @@ -246,7 +246,7 @@ def __init__(self,
super().__init__(name=name, data_type=data_type)


class AssistantCreateOutput(OutputBinding):
class _AssistantCreateOutput(OutputBinding):

@staticmethod
def get_binding_name():
Expand Down
4 changes: 2 additions & 2 deletions azure/functions/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class MCPToolContext(typing.Dict[str, typing.Any]):
pass


class MCPToolTriggerConverter(meta.InConverter, binding='mcpToolTrigger',
trigger=True):
class _MCPToolTriggerConverter(meta.InConverter, binding='mcpToolTrigger',
trigger=True):

@classmethod
def check_input_type_annotation(cls, pytype: type) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion eng/templates/official/jobs/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ jobs:

# Modify SDK Version in pyproject.toml
Write-Host "Replacing SDK version in worker's pyproject.toml"
((Get-Content workers/pyproject.toml) -replace '"azure-functions==(\d)+.(\d)+.*"','"azure-functions==$(NewLibraryVersion)"' -join "`n") + "`n" | Set-Content -NoNewline workers/pyproject.toml
((Get-Content workers/pyproject.toml) -replace '"azure-functions==[\d\.a-z]+; python_version >= ''3\.10''"','"azure-functions==$(NewLibraryVersion); python_version >= ''3.10''"' -join "`n") + "`n" | Set-Content -NoNewline workers/pyproject.toml

# Commit Python Version
Write-Host "Pushing $newBranch to azure-functions-python-worker repo"
Expand Down
Loading