From fa8caa3afb3f8ee8612de555a054d4b033a8eb35 Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Fri, 2 May 2025 16:30:01 -0700 Subject: [PATCH 1/9] update decorators for openai extension --- azure/functions/decorators/function_app.py | 101 +++++++++++++++------ tests/decorators/test_openai.py | 42 ++++++--- 2 files changed, 101 insertions(+), 42 deletions(-) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index f0feb470..5b2b29ea 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -1694,7 +1694,6 @@ def assistant_skill_trigger(self, function_description: str, function_name: Optional[str] = None, parameter_description_json: Optional[str] = None, # NoQA - model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA data_type: Optional[ Union[DataType, str]] = None, **kwargs: Any) -> Callable[..., Any]: @@ -1723,7 +1722,6 @@ def assistant_skill_trigger(self, :param parameter_description_json: A JSON description of the function parameter, which is provided to the LLM. If no description is provided, the description will be autogenerated. - :param model: The OpenAI chat model to use. :param data_type: Defines how Functions runtime should treat the parameter value. :param kwargs: Keyword arguments for specifying additional binding @@ -1741,7 +1739,6 @@ def decorator(): function_description=function_description, function_name=function_name, parameter_description_json=parameter_description_json, - model=model, data_type=parse_singular_param_to_enum(data_type, DataType), **kwargs)) @@ -3220,10 +3217,11 @@ def decorator(): def text_completion_input(self, arg_name: str, prompt: str, - model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA + chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[Union[DataType, str]] = None, **kwargs) \ -> Callable[..., Any]: @@ -3255,7 +3253,10 @@ def text_completion_input(self, :param max_tokens: The maximum number of tokens to generate in the completion. The token count of your prompt plus max_tokens cannot exceed the model's context length. Most models have a context length of - 2048 tokens (except for the newest models, which support 4096). + 2048 tokens (except for the newest models, which support 4096) + :param is_reasoning_model: Whether the configured chat completion model + is a reasoning model or not. Properties max_tokens and temperature are not + supported for reasoning models. :param data_type: Defines how Functions runtime should treat the parameter value :param kwargs: Keyword arguments for specifying additional binding @@ -3271,10 +3272,11 @@ def decorator(): binding=TextCompletionInput( name=arg_name, prompt=prompt, - model=model, + chat_model=chat_model, temperature=temperature, top_p=top_p, max_tokens=max_tokens, + is_reasoning_model=is_reasoning_model, data_type=parse_singular_param_to_enum(data_type, DataType), **kwargs)) @@ -3371,9 +3373,13 @@ def decorator(): def assistant_post_input(self, arg_name: str, id: str, user_message: str, - model: Optional[str] = None, + chat_model: Optional[str] = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 - collection_name: Optional[str] = "ChatState", # noqa: E501 + collection_name: Optional[str] = "ChatState", # noqa: E501 + temperature: Optional[str] = "0.5", + top_p: Optional[str] = None, + max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[ Union[DataType, str]] = None, **kwargs) \ @@ -3386,12 +3392,27 @@ def assistant_post_input(self, arg_name: str, :param id: The ID of the assistant to update. :param user_message: The user message that user has entered for assistant to respond to. - :param model: The OpenAI chat model to use. + :param chat_model: The deployment name or model name of OpenAI Chat Completion API. :param chat_storage_connection_setting: The configuration section name for the table settings for assistant chat storage. The default value is "AzureWebJobsStorage". :param collection_name: The table collection name for assistant chat storage. The default value is "ChatState". + :param temperature: The sampling temperature to use, between 0 and 2. + Higher values like 0.8 will make the output more random, while lower + values like 0.2 will make it more focused and deterministic. + :param top_p: An alternative to sampling with temperature, called + nucleus sampling, where the model considers the results of the tokens + with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. It's generally recommend + to use this or temperature + :param max_tokens: The maximum number of tokens to generate in the + completion. The token count of your prompt plus max_tokens cannot + exceed the model's context length. Most models have a context length of + 2048 tokens (except for the newest models, which support 4096) + :param is_reasoning_model: Whether the configured chat completion model + is a reasoning model or not. Properties max_tokens and temperature are not + supported for reasoning models. :param data_type: Defines how Functions runtime should treat the parameter value :param kwargs: Keyword arguments for specifying additional binding @@ -3408,9 +3429,13 @@ def decorator(): name=arg_name, id=id, user_message=user_message, - model=model, + chat_model=chat_model, chat_storage_connection_setting=chat_storage_connection_setting, # noqa: E501 collection_name=collection_name, + temperature=temperature, + top_p=top_p, + max_tokens=max_tokens, + is_reasoning_model=is_reasoning_model, data_type=parse_singular_param_to_enum(data_type, DataType), **kwargs)) @@ -3424,7 +3449,7 @@ def embeddings_input(self, arg_name: str, input: str, input_type: InputType, - model: Optional[str] = None, + embeddings_model: Optional[str] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ @@ -3441,7 +3466,7 @@ def embeddings_input(self, :param input: The input source containing the data to generate embeddings for. :param input_type: The type of the input. - :param model: The ID of the model to use. + :param embeddings_model: The deployment name or model name for OpenAI Embeddings. :param max_chunk_length: The maximum number of characters to chunk the input into. Default value: 8 * 1024 :param max_overlap: The maximum number of characters to overlap @@ -3462,7 +3487,7 @@ def decorator(): name=arg_name, input=input, input_type=input_type, - model=model, + embeddings_model=embeddings_model, max_chunk_length=max_chunk_length, max_overlap=max_overlap, data_type=parse_singular_param_to_enum(data_type, @@ -3476,13 +3501,17 @@ def decorator(): def semantic_search_input(self, arg_name: str, - connection_name: str, + search_connection_name: str, collection: str, query: Optional[str] = None, embeddings_model: Optional[OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, # NoQA chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA system_prompt: Optional[str] = semantic_search_system_prompt, # NoQA max_knowledge_count: Optional[int] = 1, + temperature: Optional[str] = "0.5", + top_p: Optional[str] = None, + max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[ Union[DataType, str]] = None, **kwargs) \ @@ -3499,19 +3528,33 @@ def semantic_search_input(self, Ref: https://platform.openai.com/docs/guides/embeddings :param arg_name: The name of binding parameter in the function code. - :param connection_name: app setting or environment variable which - contains a connection string value. + :param search_connection_name: app setting or environment variable which + contains a vector search connection setting value. :param collection: The name of the collection or table to search or store. :param query: The semantic query text to use for searching. - :param embeddings_model: The ID of the model to use for embeddings. + :param embeddings_model: The deployment name or model name for OpenAI Embeddings. The default value is "text-embedding-ada-002". - :param chat_model: The name of the Large Language Model to invoke for - chat responses. The default value is "gpt-3.5-turbo". + :param chat_model: The deployment name or model name of OpenAI Chat Completion API. :param system_prompt: Optional. The system prompt to use for prompting the large language model. :param max_knowledge_count: Optional. The number of knowledge items to inject into the SystemPrompt. Default value: 1 + :param temperature: The sampling temperature to use, between 0 and 2. + Higher values like 0.8 will make the output more random, while lower + values like 0.2 will make it more focused and deterministic. + :param top_p: An alternative to sampling with temperature, called + nucleus sampling, where the model considers the results of the tokens + with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. It's generally recommend + to use this or temperature + :param max_tokens: The maximum number of tokens to generate in the + completion. The token count of your prompt plus max_tokens cannot + exceed the model's context length. Most models have a context length of + 2048 tokens (except for the newest models, which support 4096) + :param is_reasoning_model: Whether the configured chat completion model + is a reasoning model or not. Properties max_tokens and temperature are not + supported for reasoning models. :param data_type: Optional. Defines how Functions runtime should treat the parameter value. Default value: None :param kwargs: Keyword arguments for specifying additional binding @@ -3526,13 +3569,17 @@ def decorator(): fb.add_binding( binding=SemanticSearchInput( name=arg_name, - connection_name=connection_name, + search_connection_name=search_connection_name, collection=collection, query=query, embeddings_model=embeddings_model, chat_model=chat_model, system_prompt=system_prompt, max_knowledge_count=max_knowledge_count, + temperature=temperature, + top_p=top_p, + max_tokens=max_tokens, + is_reasoning_model=is_reasoning_model, data_type=parse_singular_param_to_enum(data_type, DataType), **kwargs)) @@ -3546,9 +3593,9 @@ def embeddings_store_output(self, arg_name: str, input: str, input_type: InputType, - connection_name: str, + store_connection_name: str, collection: str, - model: Optional[OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, # NoQA + embeddings_model: Optional[OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, # NoQA max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ @@ -3568,10 +3615,10 @@ def embeddings_store_output(self, :param arg_name: The name of binding parameter in the function code. :param input: The input to generate embeddings for. :param input_type: The type of the input. - :param connection_name: The name of an app setting or environment - variable which contains a connection string value + :param store_connection_name: The name of an app setting or environment + variable which contains a vectore store connection setting value :param collection: The collection or table to search. - :param model: The ID of the model to use. + :param embeddings_model: The deployment name or model name for OpenAI Embeddings. :param max_chunk_length: The maximum number of characters to chunk the input into. :param max_overlap: The maximum number of characters to overlap between @@ -3592,9 +3639,9 @@ def decorator(): name=arg_name, input=input, input_type=input_type, - connection_name=connection_name, + store_connection_name=store_connection_name, collection=collection, - model=model, + embeddings_model=embeddings_model, max_chunk_length=max_chunk_length, max_overlap=max_overlap, data_type=parse_singular_param_to_enum(data_type, diff --git a/tests/decorators/test_openai.py b/tests/decorators/test_openai.py index c2009c72..3c1b83a7 100644 --- a/tests/decorators/test_openai.py +++ b/tests/decorators/test_openai.py @@ -15,7 +15,6 @@ def test_assistant_skill_trigger_valid_creation(self): function_description="description", function_name="test_function_name", parameter_description_json="test_json", - model=OpenAIModels.DefaultChatModel, data_type=DataType.UNDEFINED, dummy_field="dummy") self.assertEqual(trigger.get_binding_name(), @@ -24,8 +23,7 @@ def test_assistant_skill_trigger_valid_creation(self): trigger.get_dict_repr(), {"name": "test", "functionDescription": "description", "functionName": "test_function_name", - "parameterDescriptionJson": "test_json", - "model": OpenAIModels.DefaultChatModel, + "parameterDescriptionJson": "test_json" "dataType": DataType.UNDEFINED, 'type': 'assistantSkillTrigger', 'dummyField': 'dummy', @@ -37,8 +35,9 @@ def test_text_completion_input_valid_creation(self): prompt="test_prompt", temperature="1", max_tokens="1", + is_reasoning_model=False, data_type=DataType.UNDEFINED, - model=OpenAIModels.DefaultChatModel, + chat_model=OpenAIModels.DefaultChatModel, dummy_field="dummy") self.assertEqual(input.get_binding_name(), "textCompletion") @@ -51,7 +50,8 @@ def test_text_completion_input_valid_creation(self): "dummyField": "dummy", "prompt": "test_prompt", "direction": BindingDirection.IN, - "model": OpenAIModels.DefaultChatModel + "chatModel": OpenAIModels.DefaultChatModel, + "isReasoningModel": False, }) def test_assistant_query_input_valid_creation(self): @@ -82,7 +82,7 @@ def test_embeddings_input_valid_creation(self): data_type=DataType.UNDEFINED, input="test_input", input_type="test_input_type", - model="test_model", + embeddings_model="test_model", max_overlap=1, max_chunk_length=1, dummy_field="dummy") @@ -94,7 +94,7 @@ def test_embeddings_input_valid_creation(self): "dataType": DataType.UNDEFINED, "input": "test_input", "inputType": "test_input_type", - "model": "test_model", + "embeddingsModel": "test_model", "maxOverlap": 1, "maxChunkLength": 1, "direction": BindingDirection.IN, @@ -114,10 +114,13 @@ def test_assistant_create_output_valid_creation(self): def test_assistant_post_input_valid_creation(self): input = AssistantPostInput(name="test", id="test_id", - model="test_model", + chat_model="test_model", chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 collection_name="ChatState", user_message="test_message", + temperature="1", + max_tokens="1", + is_reasoning_model=False data_type=DataType.UNDEFINED, dummy_field="dummy") self.assertEqual(input.get_binding_name(), @@ -125,10 +128,13 @@ def test_assistant_post_input_valid_creation(self): self.assertEqual(input.get_dict_repr(), {"name": "test", "id": "test_id", - "model": "test_model", + "chatModel": "test_model", "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 "collectionName": "ChatState", "userMessage": "test_message", + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": False, "dataType": DataType.UNDEFINED, "direction": BindingDirection.IN, "dummyField": "dummy", @@ -140,10 +146,13 @@ def test_semantic_search_input_valid_creation(self): chat_model=OpenAIModels.DefaultChatModel, embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # NoQA collection="test_collection", - connection_name="test_connection", + search_connection_name="test_connection", system_prompt="test_prompt", query="test_query", max_knowledge_count=1, + temperature="1", + max_tokens="1", + is_reasoning_model=False dummy_field="dummy_field") self.assertEqual(input.get_binding_name(), "semanticSearch") @@ -156,9 +165,12 @@ def test_semantic_search_input_valid_creation(self): "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # NoQA "type": "semanticSearch", "collection": "test_collection", - "connectionName": "test_connection", + "searchconnectionName": "test_connection", "systemPrompt": "test_prompt", "maxKnowledgeCount": 1, + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": False, "query": "test_query"}) def test_embeddings_store_output_valid_creation(self): @@ -166,11 +178,11 @@ def test_embeddings_store_output_valid_creation(self): data_type=DataType.UNDEFINED, input="test_input", input_type="test_input_type", - connection_name="test_connection", + store_connection_name="test_connection", max_overlap=1, max_chunk_length=1, collection="test_collection", - model=OpenAIModels.DefaultChatModel, + embeddings_model=OpenAIModels.DefaultEmbeddingsModel, dummy_field="dummy_field") self.assertEqual(output.get_binding_name(), "embeddingsStore") @@ -182,8 +194,8 @@ def test_embeddings_store_output_valid_creation(self): "input": "test_input", "inputType": "test_input_type", "collection": "test_collection", - "model": OpenAIModels.DefaultChatModel, - "connectionName": "test_connection", + "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, + "storeconnectionName": "test_connection", "maxOverlap": 1, "maxChunkLength": 1, "type": "embeddingsStore"}) From 603d3a709dd053904a2c12b481e0401c2ab39815 Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Mon, 5 May 2025 14:23:10 -0700 Subject: [PATCH 2/9] add commas --- tests/decorators/test_openai.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/decorators/test_openai.py b/tests/decorators/test_openai.py index 3c1b83a7..420ec630 100644 --- a/tests/decorators/test_openai.py +++ b/tests/decorators/test_openai.py @@ -23,7 +23,7 @@ def test_assistant_skill_trigger_valid_creation(self): trigger.get_dict_repr(), {"name": "test", "functionDescription": "description", "functionName": "test_function_name", - "parameterDescriptionJson": "test_json" + "parameterDescriptionJson": "test_json", "dataType": DataType.UNDEFINED, 'type': 'assistantSkillTrigger', 'dummyField': 'dummy', @@ -120,7 +120,7 @@ def test_assistant_post_input_valid_creation(self): user_message="test_message", temperature="1", max_tokens="1", - is_reasoning_model=False + is_reasoning_model=False, data_type=DataType.UNDEFINED, dummy_field="dummy") self.assertEqual(input.get_binding_name(), @@ -152,7 +152,7 @@ def test_semantic_search_input_valid_creation(self): max_knowledge_count=1, temperature="1", max_tokens="1", - is_reasoning_model=False + is_reasoning_model=False, dummy_field="dummy_field") self.assertEqual(input.get_binding_name(), "semanticSearch") From 0794adb5c65b170922cf2106464d94ef8b96517d Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Mon, 5 May 2025 14:51:49 -0700 Subject: [PATCH 3/9] update openai file --- azure/functions/decorators/openai.py | 46 +++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/azure/functions/decorators/openai.py b/azure/functions/decorators/openai.py index 2563a78e..4f2f34f4 100644 --- a/azure/functions/decorators/openai.py +++ b/azure/functions/decorators/openai.py @@ -34,13 +34,11 @@ def __init__(self, function_description: str, function_name: Optional[str] = None, parameter_description_json: Optional[str] = None, - model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, data_type: Optional[DataType] = None, **kwargs): self.function_description = function_description self.function_name = function_name self.parameter_description_json = parameter_description_json - self.model = model super().__init__(name=name, data_type=data_type) @@ -53,17 +51,19 @@ def get_binding_name() -> str: def __init__(self, name: str, prompt: str, - model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[DataType] = None, **kwargs): self.prompt = prompt - self.model = model + self.model = chat_model self.temperature = temperature self.top_p = top_p self.max_tokens = max_tokens + self.is_reasoning_model = is_reasoning_model super().__init__(name=name, data_type=data_type) @@ -98,7 +98,8 @@ def __init__(self, name: str, input: str, input_type: InputType, - model: Optional[str] = None, + embeddings_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[DataType] = None, @@ -106,7 +107,7 @@ def __init__(self, self.name = name self.input = input self.input_type = input_type - self.model = model + self.embeddings_model = embeddings_model self.max_chunk_length = max_chunk_length self.max_overlap = max_overlap super().__init__(name=name, data_type=data_type) @@ -137,7 +138,7 @@ def get_binding_name() -> str: def __init__(self, name: str, - connection_name: str, + search_connection_name: str, collection: str, query: Optional[str] = None, embeddings_model: Optional[ @@ -146,16 +147,24 @@ def __init__(self, OpenAIModels] = OpenAIModels.DefaultChatModel, system_prompt: Optional[str] = semantic_search_system_prompt, max_knowledge_count: Optional[int] = 1, + temperature: Optional[str] = "0.5", + top_p: Optional[str] = None, + max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[DataType] = None, **kwargs): self.name = name - self.connection_name = connection_name + self.search_connection_name = search_connection_name self.collection = collection self.query = query self.embeddings_model = embeddings_model self.chat_model = chat_model self.system_prompt = system_prompt self.max_knowledge_count = max_knowledge_count + self.temperature = temperature + self.top_p = top_p + self.max_tokens = max_tokens + self.is_reasoning_model = is_reasoning_model super().__init__(name=name, data_type=data_type) @@ -168,17 +177,26 @@ def get_binding_name(): def __init__(self, name: str, id: str, user_message: str, - model: Optional[str] = None, + chat_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 collection_name: Optional[str] = "ChatState", + temperature: Optional[str] = "0.5", + top_p: Optional[str] = None, + max_tokens: Optional[str] = "100", + is_reasoning_model: Optional[bool] = False, data_type: Optional[DataType] = None, **kwargs): self.name = name self.id = id self.user_message = user_message - self.model = model + self.model = chat_model self.chat_storage_connection_setting = chat_storage_connection_setting self.collection_name = collection_name + self.temperature = temperature + self.top_p = top_p + self.max_tokens = max_tokens + self.is_reasoning_model = is_reasoning_model super().__init__(name=name, data_type=data_type) @@ -192,9 +210,9 @@ def __init__(self, name: str, input: str, input_type: InputType, - connection_name: str, + store_connection_name: str, collection: str, - model: Optional[ + embeddings_model: Optional[ OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, @@ -203,9 +221,9 @@ def __init__(self, self.name = name self.input = input self.input_type = input_type - self.connection_name = connection_name + self.store_connection_name = store_connection_name self.collection = collection - self.model = model + self.embeddings_model = embeddings_model self.max_chunk_length = max_chunk_length self.max_overlap = max_overlap super().__init__(name=name, data_type=data_type) From 8a715e6ba349005174df87f9c66fb6656740abfc Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Mon, 5 May 2025 15:31:59 -0700 Subject: [PATCH 4/9] update casing error --- tests/decorators/test_openai.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/decorators/test_openai.py b/tests/decorators/test_openai.py index 420ec630..14588dc6 100644 --- a/tests/decorators/test_openai.py +++ b/tests/decorators/test_openai.py @@ -165,7 +165,7 @@ def test_semantic_search_input_valid_creation(self): "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # NoQA "type": "semanticSearch", "collection": "test_collection", - "searchconnectionName": "test_connection", + "searchConnectionName": "test_connection", "systemPrompt": "test_prompt", "maxKnowledgeCount": 1, "temperature": "1", @@ -195,7 +195,7 @@ def test_embeddings_store_output_valid_creation(self): "inputType": "test_input_type", "collection": "test_collection", "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, - "storeconnectionName": "test_connection", + "storeConnectionName": "test_connection", "maxOverlap": 1, "maxChunkLength": 1, "type": "embeddingsStore"}) From f848161509c45c5ef8482d674650c2aeb650fb94 Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Mon, 5 May 2025 16:14:52 -0700 Subject: [PATCH 5/9] qa validations --- azure/functions/decorators/function_app.py | 20 +++++++++++++------- azure/functions/decorators/openai.py | 3 ++- tests/decorators/test_openai.py | 4 ++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index 5b2b29ea..1c4d219a 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -3217,7 +3217,8 @@ def decorator(): def text_completion_input(self, arg_name: str, prompt: str, - chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA + chat_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", @@ -3373,7 +3374,8 @@ def decorator(): def assistant_post_input(self, arg_name: str, id: str, user_message: str, - chat_model: Optional[str] = OpenAIModels.DefaultChatModel, + chat_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 collection_name: Optional[str] = "ChatState", # noqa: E501 temperature: Optional[str] = "0.5", @@ -3409,7 +3411,7 @@ def assistant_post_input(self, arg_name: str, :param max_tokens: The maximum number of tokens to generate in the completion. The token count of your prompt plus max_tokens cannot exceed the model's context length. Most models have a context length of - 2048 tokens (except for the newest models, which support 4096) + 2048 tokens (except for the newest models, which support 4096) :param is_reasoning_model: Whether the configured chat completion model is a reasoning model or not. Properties max_tokens and temperature are not supported for reasoning models. @@ -3449,7 +3451,8 @@ def embeddings_input(self, arg_name: str, input: str, input_type: InputType, - embeddings_model: Optional[str] = OpenAIModels.DefaultEmbeddingsModel, + embeddings_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ @@ -3504,8 +3507,10 @@ def semantic_search_input(self, search_connection_name: str, collection: str, query: Optional[str] = None, - embeddings_model: Optional[OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, # NoQA - chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, # NoQA + embeddings_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, + chat_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultChatModel, system_prompt: Optional[str] = semantic_search_system_prompt, # NoQA max_knowledge_count: Optional[int] = 1, temperature: Optional[str] = "0.5", @@ -3595,7 +3600,8 @@ def embeddings_store_output(self, input_type: InputType, store_connection_name: str, collection: str, - embeddings_model: Optional[OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, # NoQA + embeddings_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ diff --git a/azure/functions/decorators/openai.py b/azure/functions/decorators/openai.py index 4f2f34f4..1f7ad7a4 100644 --- a/azure/functions/decorators/openai.py +++ b/azure/functions/decorators/openai.py @@ -51,7 +51,8 @@ def get_binding_name() -> str: def __init__(self, name: str, prompt: str, - chat_model: Optional[OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional[ + OpenAIModels] = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", diff --git a/tests/decorators/test_openai.py b/tests/decorators/test_openai.py index 14588dc6..ae0d89da 100644 --- a/tests/decorators/test_openai.py +++ b/tests/decorators/test_openai.py @@ -182,7 +182,7 @@ def test_embeddings_store_output_valid_creation(self): max_overlap=1, max_chunk_length=1, collection="test_collection", - embeddings_model=OpenAIModels.DefaultEmbeddingsModel, + embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 dummy_field="dummy_field") self.assertEqual(output.get_binding_name(), "embeddingsStore") @@ -194,7 +194,7 @@ def test_embeddings_store_output_valid_creation(self): "input": "test_input", "inputType": "test_input_type", "collection": "test_collection", - "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, + "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 "storeConnectionName": "test_connection", "maxOverlap": 1, "maxChunkLength": 1, From c33bd767f4ee93879881e2773b1dda648013982a Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Mon, 5 May 2025 17:37:09 -0700 Subject: [PATCH 6/9] fix flake8 validations --- azure/functions/decorators/function_app.py | 60 +++++++++++++--------- azure/functions/decorators/openai.py | 5 +- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index 1c4d219a..e5c5caa5 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -3217,8 +3217,9 @@ def decorator(): def text_completion_input(self, arg_name: str, prompt: str, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", @@ -3374,8 +3375,9 @@ def decorator(): def assistant_post_input(self, arg_name: str, id: str, user_message: str, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 collection_name: Optional[str] = "ChatState", # noqa: E501 temperature: Optional[str] = "0.5", @@ -3394,7 +3396,8 @@ def assistant_post_input(self, arg_name: str, :param id: The ID of the assistant to update. :param user_message: The user message that user has entered for assistant to respond to. - :param chat_model: The deployment name or model name of OpenAI Chat Completion API. + :param chat_model: The deployment name or model name of OpenAI Chat + Completion API. :param chat_storage_connection_setting: The configuration section name for the table settings for assistant chat storage. The default value is "AzureWebJobsStorage". @@ -3413,8 +3416,8 @@ def assistant_post_input(self, arg_name: str, exceed the model's context length. Most models have a context length of 2048 tokens (except for the newest models, which support 4096) :param is_reasoning_model: Whether the configured chat completion model - is a reasoning model or not. Properties max_tokens and temperature are not - supported for reasoning models. + is a reasoning model or not. Properties max_tokens and temperature are + not supported for reasoning models. :param data_type: Defines how Functions runtime should treat the parameter value :param kwargs: Keyword arguments for specifying additional binding @@ -3451,8 +3454,9 @@ def embeddings_input(self, arg_name: str, input: str, input_type: InputType, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, + embeddings_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ @@ -3469,7 +3473,8 @@ def embeddings_input(self, :param input: The input source containing the data to generate embeddings for. :param input_type: The type of the input. - :param embeddings_model: The deployment name or model name for OpenAI Embeddings. + :param embeddings_model: The deployment name or model name for OpenAI + Embeddings. :param max_chunk_length: The maximum number of characters to chunk the input into. Default value: 8 * 1024 :param max_overlap: The maximum number of characters to overlap @@ -3507,10 +3512,12 @@ def semantic_search_input(self, search_connection_name: str, collection: str, query: Optional[str] = None, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + embeddings_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultEmbeddingsModel, + chat_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultChatModel, system_prompt: Optional[str] = semantic_search_system_prompt, # NoQA max_knowledge_count: Optional[int] = 1, temperature: Optional[str] = "0.5", @@ -3533,14 +3540,15 @@ def semantic_search_input(self, Ref: https://platform.openai.com/docs/guides/embeddings :param arg_name: The name of binding parameter in the function code. - :param search_connection_name: app setting or environment variable which - contains a vector search connection setting value. + :param search_connection_name: app setting or environment variable + which contains a vector search connection setting value. :param collection: The name of the collection or table to search or store. :param query: The semantic query text to use for searching. - :param embeddings_model: The deployment name or model name for OpenAI Embeddings. - The default value is "text-embedding-ada-002". - :param chat_model: The deployment name or model name of OpenAI Chat Completion API. + :param embeddings_model: The deployment name or model name for OpenAI + Embeddings. The default value is "text-embedding-ada-002". + :param chat_model: The deployment name or model name of OpenAI Chat + Completion API. :param system_prompt: Optional. The system prompt to use for prompting the large language model. :param max_knowledge_count: Optional. The number of knowledge items to @@ -3556,10 +3564,10 @@ def semantic_search_input(self, :param max_tokens: The maximum number of tokens to generate in the completion. The token count of your prompt plus max_tokens cannot exceed the model's context length. Most models have a context length of - 2048 tokens (except for the newest models, which support 4096) + 2048 tokens (except for the newest models, which support 4096) :param is_reasoning_model: Whether the configured chat completion model - is a reasoning model or not. Properties max_tokens and temperature are not - supported for reasoning models. + is a reasoning model or not. Properties max_tokens and temperature are + not supported for reasoning models. :param data_type: Optional. Defines how Functions runtime should treat the parameter value. Default value: None :param kwargs: Keyword arguments for specifying additional binding @@ -3600,8 +3608,9 @@ def embeddings_store_output(self, input_type: InputType, store_connection_name: str, collection: str, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, + embeddings_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[ @@ -3624,7 +3633,8 @@ def embeddings_store_output(self, :param store_connection_name: The name of an app setting or environment variable which contains a vectore store connection setting value :param collection: The collection or table to search. - :param embeddings_model: The deployment name or model name for OpenAI Embeddings. + :param embeddings_model: The deployment name or model name for OpenAI + Embeddings. :param max_chunk_length: The maximum number of characters to chunk the input into. :param max_overlap: The maximum number of characters to overlap between diff --git a/azure/functions/decorators/openai.py b/azure/functions/decorators/openai.py index 1f7ad7a4..2315c40e 100644 --- a/azure/functions/decorators/openai.py +++ b/azure/functions/decorators/openai.py @@ -51,8 +51,9 @@ def get_binding_name() -> str: def __init__(self, name: str, prompt: str, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional + [OpenAIModels] + = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, max_tokens: Optional[str] = "100", From 158a42f3835f29b8dba9bb6328f8cfe5cb633c8a Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Tue, 6 May 2025 13:25:27 -0700 Subject: [PATCH 7/9] use union for acceptable type --- azure/functions/decorators/function_app.py | 12 ++++++------ azure/functions/decorators/openai.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index e5c5caa5..0f65dd58 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -3218,7 +3218,7 @@ def text_completion_input(self, arg_name: str, prompt: str, chat_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, @@ -3376,7 +3376,7 @@ def assistant_post_input(self, arg_name: str, id: str, user_message: str, chat_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 collection_name: Optional[str] = "ChatState", # noqa: E501 @@ -3455,7 +3455,7 @@ def embeddings_input(self, input: str, input_type: InputType, embeddings_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, @@ -3513,10 +3513,10 @@ def semantic_search_input(self, collection: str, query: Optional[str] = None, embeddings_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultEmbeddingsModel, chat_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultChatModel, system_prompt: Optional[str] = semantic_search_system_prompt, # NoQA max_knowledge_count: Optional[int] = 1, @@ -3609,7 +3609,7 @@ def embeddings_store_output(self, store_connection_name: str, collection: str, embeddings_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, diff --git a/azure/functions/decorators/openai.py b/azure/functions/decorators/openai.py index 2315c40e..6302fad4 100644 --- a/azure/functions/decorators/openai.py +++ b/azure/functions/decorators/openai.py @@ -52,7 +52,7 @@ def __init__(self, name: str, prompt: str, chat_model: Optional - [OpenAIModels] + [Union[str, OpenAIModels]] = OpenAIModels.DefaultChatModel, temperature: Optional[str] = "0.5", top_p: Optional[str] = None, From 859fe88752e75a82195b24d2ac9f40ff9cc8f785 Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Tue, 6 May 2025 14:12:38 -0700 Subject: [PATCH 8/9] address review comments --- azure/functions/decorators/function_app.py | 11 +- azure/functions/decorators/openai.py | 31 +- tests/decorators/test_openai.py | 557 ++++++++++++++------- 3 files changed, 404 insertions(+), 195 deletions(-) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index 0f65dd58..22bb0820 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -3243,7 +3243,8 @@ def text_completion_input(self, :param arg_name: The name of binding parameter in the function code. :param prompt: The prompt to generate completions for, encoded as a string. - :param model: the ID of the model to use. + :param chat_model: The deployment name or model name of OpenAI Chat + Completion API. The default value is "gpt-3.5-turbo". :param temperature: The sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. @@ -3397,7 +3398,7 @@ def assistant_post_input(self, arg_name: str, :param user_message: The user message that user has entered for assistant to respond to. :param chat_model: The deployment name or model name of OpenAI Chat - Completion API. + Completion API. The default value is "gpt-3.5-turbo". :param chat_storage_connection_setting: The configuration section name for the table settings for assistant chat storage. The default value is "AzureWebJobsStorage". @@ -3474,7 +3475,7 @@ def embeddings_input(self, embeddings for. :param input_type: The type of the input. :param embeddings_model: The deployment name or model name for OpenAI - Embeddings. + Embeddings. The default value is "text-embedding-ada-002". :param max_chunk_length: The maximum number of characters to chunk the input into. Default value: 8 * 1024 :param max_overlap: The maximum number of characters to overlap @@ -3548,7 +3549,7 @@ def semantic_search_input(self, :param embeddings_model: The deployment name or model name for OpenAI Embeddings. The default value is "text-embedding-ada-002". :param chat_model: The deployment name or model name of OpenAI Chat - Completion API. + Completion API. The default value is "gpt-3.5-turbo". :param system_prompt: Optional. The system prompt to use for prompting the large language model. :param max_knowledge_count: Optional. The number of knowledge items to @@ -3634,7 +3635,7 @@ def embeddings_store_output(self, variable which contains a vectore store connection setting value :param collection: The collection or table to search. :param embeddings_model: The deployment name or model name for OpenAI - Embeddings. + Embeddings. The default value is "text-embedding-ada-002". :param max_chunk_length: The maximum number of characters to chunk the input into. :param max_overlap: The maximum number of characters to overlap between diff --git a/azure/functions/decorators/openai.py b/azure/functions/decorators/openai.py index 6302fad4..31306c67 100644 --- a/azure/functions/decorators/openai.py +++ b/azure/functions/decorators/openai.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Union from azure.functions.decorators.constants import (ASSISTANT_SKILL_TRIGGER, TEXT_COMPLETION, @@ -61,7 +61,7 @@ def __init__(self, data_type: Optional[DataType] = None, **kwargs): self.prompt = prompt - self.model = chat_model + self.chat_model = chat_model self.temperature = temperature self.top_p = top_p self.max_tokens = max_tokens @@ -100,8 +100,9 @@ def __init__(self, name: str, input: str, input_type: InputType, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, + embeddings_model: Optional + [Union[str, OpenAIModels]] + = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[DataType] = None, @@ -143,10 +144,12 @@ def __init__(self, search_connection_name: str, collection: str, query: Optional[str] = None, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + embeddings_model: Optional + [Union[str, OpenAIModels]] + = OpenAIModels.DefaultEmbeddingsModel, + chat_model: Optional + [Union[str, OpenAIModels]] + = OpenAIModels.DefaultChatModel, system_prompt: Optional[str] = semantic_search_system_prompt, max_knowledge_count: Optional[int] = 1, temperature: Optional[str] = "0.5", @@ -179,8 +182,9 @@ def get_binding_name(): def __init__(self, name: str, id: str, user_message: str, - chat_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultChatModel, + chat_model: Optional + [Union[str, OpenAIModels]] + = OpenAIModels.DefaultChatModel, chat_storage_connection_setting: Optional[str] = "AzureWebJobsStorage", # noqa: E501 collection_name: Optional[str] = "ChatState", temperature: Optional[str] = "0.5", @@ -192,7 +196,7 @@ def __init__(self, name: str, self.name = name self.id = id self.user_message = user_message - self.model = chat_model + self.chat_model = chat_model self.chat_storage_connection_setting = chat_storage_connection_setting self.collection_name = collection_name self.temperature = temperature @@ -214,8 +218,9 @@ def __init__(self, input_type: InputType, store_connection_name: str, collection: str, - embeddings_model: Optional[ - OpenAIModels] = OpenAIModels.DefaultEmbeddingsModel, + embeddings_model: Optional + [Union[str, OpenAIModels]] + = OpenAIModels.DefaultEmbeddingsModel, max_chunk_length: Optional[int] = 8 * 1024, max_overlap: Optional[int] = 128, data_type: Optional[DataType] = None, diff --git a/tests/decorators/test_openai.py b/tests/decorators/test_openai.py index ae0d89da..78b4e0da 100644 --- a/tests/decorators/test_openai.py +++ b/tests/decorators/test_openai.py @@ -2,200 +2,403 @@ from azure.functions import DataType from azure.functions.decorators.core import BindingDirection -from azure.functions.decorators.openai import AssistantSkillTrigger, \ - TextCompletionInput, OpenAIModels, AssistantQueryInput, EmbeddingsInput, \ - AssistantCreateOutput, SemanticSearchInput, EmbeddingsStoreOutput, \ - AssistantPostInput +from azure.functions.decorators.openai import ( + AssistantSkillTrigger, + TextCompletionInput, + OpenAIModels, + AssistantQueryInput, + EmbeddingsInput, + AssistantCreateOutput, + SemanticSearchInput, + EmbeddingsStoreOutput, + AssistantPostInput, +) class TestOpenAI(unittest.TestCase): def test_assistant_skill_trigger_valid_creation(self): - trigger = AssistantSkillTrigger(name="test", - function_description="description", - function_name="test_function_name", - parameter_description_json="test_json", - data_type=DataType.UNDEFINED, - dummy_field="dummy") - self.assertEqual(trigger.get_binding_name(), - "assistantSkillTrigger") + trigger = AssistantSkillTrigger( + name="test", + function_description="description", + function_name="test_function_name", + parameter_description_json="test_json", + data_type=DataType.UNDEFINED, + dummy_field="dummy", + ) + self.assertEqual(trigger.get_binding_name(), "assistantSkillTrigger") self.assertEqual( - trigger.get_dict_repr(), {"name": "test", - "functionDescription": "description", - "functionName": "test_function_name", - "parameterDescriptionJson": "test_json", - "dataType": DataType.UNDEFINED, - 'type': 'assistantSkillTrigger', - 'dummyField': 'dummy', - "direction": BindingDirection.IN, - }) + trigger.get_dict_repr(), + { + "name": "test", + "functionDescription": "description", + "functionName": "test_function_name", + "parameterDescriptionJson": "test_json", + "dataType": DataType.UNDEFINED, + "type": "assistantSkillTrigger", + "dummyField": "dummy", + "direction": BindingDirection.IN, + }, + ) def test_text_completion_input_valid_creation(self): - input = TextCompletionInput(name="test", - prompt="test_prompt", - temperature="1", - max_tokens="1", - is_reasoning_model=False, - data_type=DataType.UNDEFINED, - chat_model=OpenAIModels.DefaultChatModel, - dummy_field="dummy") - self.assertEqual(input.get_binding_name(), - "textCompletion") - self.assertEqual(input.get_dict_repr(), - {"name": "test", - "temperature": "1", - "maxTokens": "1", - 'type': 'textCompletion', - "dataType": DataType.UNDEFINED, - "dummyField": "dummy", - "prompt": "test_prompt", - "direction": BindingDirection.IN, - "chatModel": OpenAIModels.DefaultChatModel, - "isReasoningModel": False, - }) + input = TextCompletionInput( + name="test", + prompt="test_prompt", + temperature="1", + max_tokens="1", + is_reasoning_model=False, + data_type=DataType.UNDEFINED, + chat_model=OpenAIModels.DefaultChatModel, + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "textCompletion") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "temperature": "1", + "maxTokens": "1", + "type": "textCompletion", + "dataType": DataType.UNDEFINED, + "dummyField": "dummy", + "prompt": "test_prompt", + "direction": BindingDirection.IN, + "chatModel": OpenAIModels.DefaultChatModel, + "isReasoningModel": False, + }, + ) + + def test_text_completion_input_with_string_chat_model(self): + input = TextCompletionInput( + name="test", + prompt="test_prompt", + temperature="1", + max_tokens="1", + is_reasoning_model=True, + data_type=DataType.UNDEFINED, + chat_model="gpt-4o", + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "textCompletion") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "temperature": "1", + "maxTokens": "1", + "type": "textCompletion", + "dataType": DataType.UNDEFINED, + "dummyField": "dummy", + "prompt": "test_prompt", + "direction": BindingDirection.IN, + "chatModel": "gpt-4o", + "isReasoningModel": True, + }, + ) def test_assistant_query_input_valid_creation(self): - input = AssistantQueryInput(name="test", - timestamp_utc="timestamp_utc", - chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 - collection_name="ChatState", - data_type=DataType.UNDEFINED, - id="test_id", - type="assistantQueryInput", - dummy_field="dummy") - self.assertEqual(input.get_binding_name(), - "assistantQuery") - self.assertEqual(input.get_dict_repr(), - {"name": "test", - "timestampUtc": "timestamp_utc", - "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 - "collectionName": "ChatState", - "dataType": DataType.UNDEFINED, - "direction": BindingDirection.IN, - "type": "assistantQuery", - "id": "test_id", - "dummyField": "dummy" - }) + input = AssistantQueryInput( + name="test", + timestamp_utc="timestamp_utc", + chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 + collection_name="ChatState", + data_type=DataType.UNDEFINED, + id="test_id", + type="assistantQueryInput", + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "assistantQuery") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "timestampUtc": "timestamp_utc", + "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 + "collectionName": "ChatState", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.IN, + "type": "assistantQuery", + "id": "test_id", + "dummyField": "dummy", + }, + ) def test_embeddings_input_valid_creation(self): - input = EmbeddingsInput(name="test", - data_type=DataType.UNDEFINED, - input="test_input", - input_type="test_input_type", - embeddings_model="test_model", - max_overlap=1, - max_chunk_length=1, - dummy_field="dummy") - self.assertEqual(input.get_binding_name(), - "embeddings") - self.assertEqual(input.get_dict_repr(), - {"name": "test", - "type": "embeddings", - "dataType": DataType.UNDEFINED, - "input": "test_input", - "inputType": "test_input_type", - "embeddingsModel": "test_model", - "maxOverlap": 1, - "maxChunkLength": 1, - "direction": BindingDirection.IN, - "dummyField": "dummy"}) + input = EmbeddingsInput( + name="test", + data_type=DataType.UNDEFINED, + input="test_input", + input_type="test_input_type", + embeddings_model="test_model", + max_overlap=1, + max_chunk_length=1, + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "embeddings") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "type": "embeddings", + "dataType": DataType.UNDEFINED, + "input": "test_input", + "inputType": "test_input_type", + "embeddingsModel": "test_model", + "maxOverlap": 1, + "maxChunkLength": 1, + "direction": BindingDirection.IN, + "dummyField": "dummy", + }, + ) + + def test_embeddings_input_with_enum_embeddings_model(self): + input = EmbeddingsInput( + name="test", + data_type=DataType.UNDEFINED, + input="test_input", + input_type="test_input_type", + embeddings_model=OpenAIModels.DefaultEmbeddingsModel, + max_overlap=1, + max_chunk_length=1, + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "embeddings") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "type": "embeddings", + "dataType": DataType.UNDEFINED, + "input": "test_input", + "inputType": "test_input_type", + "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, + "maxOverlap": 1, + "maxChunkLength": 1, + "direction": BindingDirection.IN, + "dummyField": "dummy", + }, + ) def test_assistant_create_output_valid_creation(self): - output = AssistantCreateOutput(name="test", - data_type=DataType.UNDEFINED) - self.assertEqual(output.get_binding_name(), - "assistantCreate") - self.assertEqual(output.get_dict_repr(), - {"name": "test", - "dataType": DataType.UNDEFINED, - "direction": BindingDirection.OUT, - "type": "assistantCreate"}) + output = AssistantCreateOutput( + name="test", data_type=DataType.UNDEFINED + ) + self.assertEqual(output.get_binding_name(), "assistantCreate") + self.assertEqual( + output.get_dict_repr(), + { + "name": "test", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.OUT, + "type": "assistantCreate", + }, + ) def test_assistant_post_input_valid_creation(self): - input = AssistantPostInput(name="test", - id="test_id", - chat_model="test_model", - chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 - collection_name="ChatState", - user_message="test_message", - temperature="1", - max_tokens="1", - is_reasoning_model=False, - data_type=DataType.UNDEFINED, - dummy_field="dummy") - self.assertEqual(input.get_binding_name(), - "assistantPost") - self.assertEqual(input.get_dict_repr(), - {"name": "test", - "id": "test_id", - "chatModel": "test_model", - "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 - "collectionName": "ChatState", - "userMessage": "test_message", - "temperature": "1", - "maxTokens": "1", - "isReasoningModel": False, - "dataType": DataType.UNDEFINED, - "direction": BindingDirection.IN, - "dummyField": "dummy", - "type": "assistantPost"}) + input = AssistantPostInput( + name="test", + id="test_id", + chat_model="test_model", + chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 + collection_name="ChatState", + user_message="test_message", + temperature="1", + max_tokens="1", + is_reasoning_model=False, + data_type=DataType.UNDEFINED, + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "assistantPost") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "id": "test_id", + "chatModel": "test_model", + "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 + "collectionName": "ChatState", + "userMessage": "test_message", + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": False, + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.IN, + "dummyField": "dummy", + "type": "assistantPost", + }, + ) + + def test_assistant_post_input_with_enum_chat_model(self): + input = AssistantPostInput( + name="test", + id="test_id", + chat_model=OpenAIModels.DefaultChatModel, + chat_storage_connection_setting="AzureWebJobsStorage", # noqa: E501 + collection_name="ChatState", + user_message="test_message", + temperature="1", + max_tokens="1", + is_reasoning_model=False, + data_type=DataType.UNDEFINED, + dummy_field="dummy", + ) + self.assertEqual(input.get_binding_name(), "assistantPost") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "id": "test_id", + "chatModel": OpenAIModels.DefaultChatModel, + "chatStorageConnectionSetting": "AzureWebJobsStorage", # noqa: E501 + "collectionName": "ChatState", + "userMessage": "test_message", + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": False, + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.IN, + "dummyField": "dummy", + "type": "assistantPost", + }, + ) def test_semantic_search_input_valid_creation(self): - input = SemanticSearchInput(name="test", - data_type=DataType.UNDEFINED, - chat_model=OpenAIModels.DefaultChatModel, - embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # NoQA - collection="test_collection", - search_connection_name="test_connection", - system_prompt="test_prompt", - query="test_query", - max_knowledge_count=1, - temperature="1", - max_tokens="1", - is_reasoning_model=False, - dummy_field="dummy_field") - self.assertEqual(input.get_binding_name(), - "semanticSearch") - self.assertEqual(input.get_dict_repr(), - {"name": "test", - "dataType": DataType.UNDEFINED, - "direction": BindingDirection.IN, - "dummyField": "dummy_field", - "chatModel": OpenAIModels.DefaultChatModel, - "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # NoQA - "type": "semanticSearch", - "collection": "test_collection", - "searchConnectionName": "test_connection", - "systemPrompt": "test_prompt", - "maxKnowledgeCount": 1, - "temperature": "1", - "maxTokens": "1", - "isReasoningModel": False, - "query": "test_query"}) + input = SemanticSearchInput( + name="test", + data_type=DataType.UNDEFINED, + chat_model=OpenAIModels.DefaultChatModel, + embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # NoQA + collection="test_collection", + search_connection_name="test_connection", + system_prompt="test_prompt", + query="test_query", + max_knowledge_count=1, + temperature="1", + max_tokens="1", + is_reasoning_model=False, + dummy_field="dummy_field", + ) + self.assertEqual(input.get_binding_name(), "semanticSearch") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.IN, + "dummyField": "dummy_field", + "chatModel": OpenAIModels.DefaultChatModel, + "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # NoQA + "type": "semanticSearch", + "collection": "test_collection", + "searchConnectionName": "test_connection", + "systemPrompt": "test_prompt", + "maxKnowledgeCount": 1, + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": False, + "query": "test_query", + }, + ) + + def test_semantic_search_input_with_string_models(self): + input = SemanticSearchInput( + name="test", + data_type=DataType.UNDEFINED, + chat_model="gpt-4o", + embeddings_model="text-embedding-3-large", + collection="test_collection", + search_connection_name="test_connection", + system_prompt="test_prompt", + query="test_query", + max_knowledge_count=1, + temperature="1", + max_tokens="1", + is_reasoning_model=True, + dummy_field="dummy_field", + ) + self.assertEqual(input.get_binding_name(), "semanticSearch") + self.assertEqual( + input.get_dict_repr(), + { + "name": "test", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.IN, + "dummyField": "dummy_field", + "chatModel": "gpt-4o", + "embeddingsModel": "text-embedding-3-large", + "type": "semanticSearch", + "collection": "test_collection", + "searchConnectionName": "test_connection", + "systemPrompt": "test_prompt", + "maxKnowledgeCount": 1, + "temperature": "1", + "maxTokens": "1", + "isReasoningModel": True, + "query": "test_query", + }, + ) def test_embeddings_store_output_valid_creation(self): - output = EmbeddingsStoreOutput(name="test", - data_type=DataType.UNDEFINED, - input="test_input", - input_type="test_input_type", - store_connection_name="test_connection", - max_overlap=1, - max_chunk_length=1, - collection="test_collection", - embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 - dummy_field="dummy_field") - self.assertEqual(output.get_binding_name(), - "embeddingsStore") - self.assertEqual(output.get_dict_repr(), - {"name": "test", - "dataType": DataType.UNDEFINED, - "direction": BindingDirection.OUT, - "dummyField": "dummy_field", - "input": "test_input", - "inputType": "test_input_type", - "collection": "test_collection", - "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 - "storeConnectionName": "test_connection", - "maxOverlap": 1, - "maxChunkLength": 1, - "type": "embeddingsStore"}) + output = EmbeddingsStoreOutput( + name="test", + data_type=DataType.UNDEFINED, + input="test_input", + input_type="test_input_type", + store_connection_name="test_connection", + max_overlap=1, + max_chunk_length=1, + collection="test_collection", + embeddings_model=OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 + dummy_field="dummy_field", + ) + self.assertEqual(output.get_binding_name(), "embeddingsStore") + self.assertEqual( + output.get_dict_repr(), + { + "name": "test", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.OUT, + "dummyField": "dummy_field", + "input": "test_input", + "inputType": "test_input_type", + "collection": "test_collection", + "embeddingsModel": OpenAIModels.DefaultEmbeddingsModel, # noqa: E501 + "storeConnectionName": "test_connection", + "maxOverlap": 1, + "maxChunkLength": 1, + "type": "embeddingsStore", + }, + ) + + def test_embeddings_store_output_with_string_embeddings_model(self): + output = EmbeddingsStoreOutput( + name="test", + data_type=DataType.UNDEFINED, + input="test_input", + input_type="test_input_type", + store_connection_name="test_connection", + max_overlap=1, + max_chunk_length=1, + collection="test_collection", + embeddings_model="text-embedding-3-small", + dummy_field="dummy_field", + ) + self.assertEqual(output.get_binding_name(), "embeddingsStore") + self.assertEqual( + output.get_dict_repr(), + { + "name": "test", + "dataType": DataType.UNDEFINED, + "direction": BindingDirection.OUT, + "dummyField": "dummy_field", + "input": "test_input", + "inputType": "test_input_type", + "collection": "test_collection", + "embeddingsModel": "text-embedding-3-small", + "storeConnectionName": "test_connection", + "maxOverlap": 1, + "maxChunkLength": 1, + "type": "embeddingsStore", + }, + ) From 397505ef7952c05c30c14e53a842958b00655f61 Mon Sep 17 00:00:00 2001 From: manvkaur <67894494+manvkaur@users.noreply.github.com> Date: Thu, 8 May 2025 17:49:43 -0700 Subject: [PATCH 9/9] add deprecation information --- azure/functions/decorators/function_app.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/azure/functions/decorators/function_app.py b/azure/functions/decorators/function_app.py index 22bb0820..488f997f 100644 --- a/azure/functions/decorators/function_app.py +++ b/azure/functions/decorators/function_app.py @@ -3243,6 +3243,8 @@ def text_completion_input(self, :param arg_name: The name of binding parameter in the function code. :param prompt: The prompt to generate completions for, encoded as a string. + :param model: @deprecated. Use chat_model instead. The model parameter + is unused and will be removed in future versions. :param chat_model: The deployment name or model name of OpenAI Chat Completion API. The default value is "gpt-3.5-turbo". :param temperature: The sampling temperature to use, between 0 and 2. @@ -3397,6 +3399,8 @@ def assistant_post_input(self, arg_name: str, :param id: The ID of the assistant to update. :param user_message: The user message that user has entered for assistant to respond to. + :param model: @deprecated. Use chat_model instead. The model parameter + is unused and will be removed in future versions. :param chat_model: The deployment name or model name of OpenAI Chat Completion API. The default value is "gpt-3.5-turbo". :param chat_storage_connection_setting: The configuration section name @@ -3474,6 +3478,8 @@ def embeddings_input(self, :param input: The input source containing the data to generate embeddings for. :param input_type: The type of the input. + :param model: @deprecated. Use embeddings_model instead. The model + parameter is unused and will be removed in future versions. :param embeddings_model: The deployment name or model name for OpenAI Embeddings. The default value is "text-embedding-ada-002". :param max_chunk_length: The maximum number of characters to chunk the @@ -3634,6 +3640,8 @@ def embeddings_store_output(self, :param store_connection_name: The name of an app setting or environment variable which contains a vectore store connection setting value :param collection: The collection or table to search. + :param model: @deprecated. Use embeddings_model instead. The model + parameter is unused and will be removed in future versions. :param embeddings_model: The deployment name or model name for OpenAI Embeddings. The default value is "text-embedding-ada-002". :param max_chunk_length: The maximum number of characters to chunk the