From c0be44e84650e1b558516be4472a5415e6c0715f Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 18:24:50 +0100 Subject: [PATCH 01/24] Refactor (sdk/types): improve sdk types to be compatible with pydantic v2 --- agenta-cli/agenta/sdk/types.py | 148 +++++++++++++++------------------ 1 file changed, 65 insertions(+), 83 deletions(-) diff --git a/agenta-cli/agenta/sdk/types.py b/agenta-cli/agenta/sdk/types.py index 497cbdec39..3f52c165ef 100644 --- a/agenta-cli/agenta/sdk/types.py +++ b/agenta-cli/agenta/sdk/types.py @@ -1,7 +1,7 @@ import json -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional -from pydantic import BaseModel, Extra, HttpUrl, Field +from pydantic import ConfigDict, BaseModel, HttpUrl class InFile: @@ -24,87 +24,75 @@ class FuncResponse(BaseModel): class DictInput(dict): - def __new__(cls, default_keys=None): + def __new__(cls, default_keys: Optional[List[str]] = None): instance = super().__new__(cls, default_keys) if default_keys is None: default_keys = [] - instance.data = [key for key in default_keys] + instance.data = [key for key in default_keys] # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema): - field_schema.update({"x-parameter": "dict"}) + def __schema__(cls) -> dict: + return {"x-parameter": "dict"} class TextParam(str): @classmethod - def __modify_schema__(cls, field_schema): - field_schema.update({"x-parameter": "text"}) + def __schema__(cls) -> dict: + return {"x-parameter": "text", "type": "string"} class BinaryParam(int): def __new__(cls, value: bool = False): instance = super().__new__(cls, int(value)) - instance.default = value + instance.default = value # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema): - field_schema.update( - { - "x-parameter": "bool", - "type": "boolean", - } - ) + def __schema__(cls) -> dict: + return { + "x-parameter": "bool", + "type": "boolean", + } class IntParam(int): def __new__(cls, default: int = 6, minval: float = 1, maxval: float = 10): instance = super().__new__(cls, default) - instance.minval = minval - instance.maxval = maxval + instance.minval = minval # type: ignore + instance.maxval = maxval # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema): - field_schema.update( - { - "x-parameter": "int", - "type": "integer", - "minimum": 1, - "maximum": 10, - } - ) + def __schema__(cls) -> dict: + return {"x-parameter": "int", "type": "integer"} class FloatParam(float): def __new__(cls, default: float = 0.5, minval: float = 0.0, maxval: float = 1.0): instance = super().__new__(cls, default) - instance.minval = minval - instance.maxval = maxval + instance.default = default # type: ignore + instance.minval = minval # type: ignore + instance.maxval = maxval # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema): - field_schema.update( - { - "x-parameter": "float", - "type": "number", - "minimum": 0.0, - "maximum": 1.0, - } - ) + def __schema__(cls) -> dict: + return {"x-parameter": "float", "type": "number"} class MultipleChoiceParam(str): - def __new__(cls, default: str = None, choices: List[str] = None): - if type(default) is list: + def __new__( + cls, default: Optional[str] = None, choices: Optional[List[str]] = None + ): + if default is not None and type(default) is list: raise ValueError( "The order of the parameters for MultipleChoiceParam is wrong! It's MultipleChoiceParam(default, choices) and not the opposite" ) - if default is None and choices: + + if not default and choices is not None: # if a default value is not provided, - # uset the first value in the choices list + # set the first value in the choices list default = choices[0] if default is None and not choices: @@ -112,23 +100,21 @@ def __new__(cls, default: str = None, choices: List[str] = None): raise ValueError("You must provide either a default value or choices") instance = super().__new__(cls, default) - instance.choices = choices - instance.default = default + instance.choices = choices # type: ignore + instance.default = default # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema: dict[str, Any]): - field_schema.update( - { - "x-parameter": "choice", - "type": "string", - "enum": [], - } - ) + def __schema__(cls) -> dict: + return {"x-parameter": "choice", "type": "string", "enum": []} class GroupedMultipleChoiceParam(str): - def __new__(cls, default: str = None, choices: Dict[str, List[str]] = None): + def __new__( + cls, + default: Optional[str] = None, + choices: Optional[Dict[str, List[str]]] = None, + ): if choices is None: choices = {} @@ -143,31 +129,23 @@ def __new__(cls, default: str = None, choices: Dict[str, List[str]] = None): ) if not default: - for choices in choices.values(): - if choices: - default = choices[0] - break + default_selected_choice = next( + (choices for choices in choices.values()), None + ) + if default_selected_choice: + default = default_selected_choice[0] instance = super().__new__(cls, default) - instance.choices = choices - instance.default = default + instance.choices = choices # type: ignore + instance.default = default # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema: dict[str, Any], **kwargs): - choices = kwargs.get("choices", {}) - field_schema.update( - { - "x-parameter": "grouped_choice", - "type": "string", - "choices": choices, - } - ) - - -class Message(BaseModel): - role: str - content: str + def __schema__(cls) -> dict: + return { + "x-parameter": "grouped_choice", + "type": "string", + } class MessagesInput(list): @@ -182,28 +160,32 @@ class MessagesInput(list): """ - def __new__(cls, messages: List[Dict[str, str]] = None): - instance = super().__new__(cls, messages) - instance.default = messages + def __new__(cls, messages: List[Dict[str, str]] = []): + instance = super().__new__(cls) + instance.default = messages # type: ignore return instance @classmethod - def __modify_schema__(cls, field_schema: dict[str, Any]): - field_schema.update({"x-parameter": "messages", "type": "array"}) + def __schema__(cls) -> dict: + return {"x-parameter": "messages", "type": "array"} class FileInputURL(HttpUrl): + def __new__(cls, url: str): + instance = super().__new__(cls, url) + instance.default = url # type: ignore + return instance + @classmethod - def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: - field_schema.update({"x-parameter": "file_url", "type": "string"}) + def __schema__(cls) -> dict: + return {"x-parameter": "file_url", "type": "string"} class Context(BaseModel): - class Config: - extra = Extra.allow + model_config = ConfigDict(extra="allow") def to_json(self): - return self.json() + return self.model_dump() @classmethod def from_json(cls, json_str: str): From 0b3043157b2c22a420a78753c7d85bb4e7b0ecfc Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 18:52:01 +0100 Subject: [PATCH 02/24] Refactor (sdk/types): renamed sdk types classmethod from __schema__ to __schema_type_properties__ for clarity --- agenta-cli/agenta/sdk/types.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/agenta-cli/agenta/sdk/types.py b/agenta-cli/agenta/sdk/types.py index 3f52c165ef..161235621d 100644 --- a/agenta-cli/agenta/sdk/types.py +++ b/agenta-cli/agenta/sdk/types.py @@ -32,13 +32,13 @@ def __new__(cls, default_keys: Optional[List[str]] = None): return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "dict"} class TextParam(str): @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "text", "type": "string"} @@ -49,7 +49,7 @@ def __new__(cls, value: bool = False): return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return { "x-parameter": "bool", "type": "boolean", @@ -64,7 +64,7 @@ def __new__(cls, default: int = 6, minval: float = 1, maxval: float = 10): return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "int", "type": "integer"} @@ -77,7 +77,7 @@ def __new__(cls, default: float = 0.5, minval: float = 0.0, maxval: float = 1.0) return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "float", "type": "number"} @@ -105,7 +105,7 @@ def __new__( return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "choice", "type": "string", "enum": []} @@ -141,7 +141,7 @@ def __new__( return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return { "x-parameter": "grouped_choice", "type": "string", @@ -166,7 +166,7 @@ def __new__(cls, messages: List[Dict[str, str]] = []): return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "messages", "type": "array"} @@ -177,7 +177,7 @@ def __new__(cls, url: str): return instance @classmethod - def __schema__(cls) -> dict: + def __schema_type_properties__(cls) -> dict: return {"x-parameter": "file_url", "type": "string"} From 9c48ee2e90a917b569bffc4c8e37f1b14073a5da Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 18:55:20 +0100 Subject: [PATCH 03/24] Refactor (sdk/agenta_decorator): update function_signature and override_schema to be Pydantic v2 compliance --- agenta-cli/agenta/sdk/agenta_decorator.py | 111 +++++++++++++++------- 1 file changed, 77 insertions(+), 34 deletions(-) diff --git a/agenta-cli/agenta/sdk/agenta_decorator.py b/agenta-cli/agenta/sdk/agenta_decorator.py index 4f5a4e75c7..4e20ff267a 100644 --- a/agenta-cli/agenta/sdk/agenta_decorator.py +++ b/agenta-cli/agenta/sdk/agenta_decorator.py @@ -57,7 +57,7 @@ def ingest_file(upfile: UploadFile): return InFile(file_name=upfile.filename, file_path=temp_file.name) -def entrypoint(func: Callable[..., Any]) -> Callable[..., Any]: +def entrypoint(func: Callable[..., Any]): """ Decorator to wrap a function for HTTP POST and terminal exposure. @@ -97,8 +97,8 @@ async def wrapper(*args, **kwargs) -> Any: # End trace recording tracing.end_recording( - outputs=llm_result.dict(), - span=tracing.active_trace, + outputs=llm_result.model_dump(), + span=tracing.active_trace, # type: ignore ) return llm_result @@ -130,8 +130,8 @@ async def wrapper_deployed(*args, **kwargs) -> Any: # End trace recording tracing.end_recording( - outputs=llm_result.dict(), - span=tracing.active_trace, + outputs=llm_result.model_dump(), + span=tracing.active_trace, # type: ignore ) return llm_result @@ -144,6 +144,7 @@ async def wrapper_deployed(*args, **kwargs) -> Any: func_signature, ingestible_files, ) + route_deployed = f"/{endpoint_name}_deployed" app.post(route_deployed, response_model=FuncResponse)(wrapper_deployed) override_schema( @@ -156,11 +157,10 @@ async def wrapper_deployed(*args, **kwargs) -> Any: if is_main_script(func): handle_terminal_run( func, - func_signature.parameters, + func_signature.parameters, # type: ignore config_params, ingestible_files, ) - return None def extract_ingestible_files( @@ -248,7 +248,7 @@ def update_wrapper_signature(wrapper: Callable[..., Any], updated_params: List): wrapper_signature = inspect.signature(wrapper) wrapper_signature = wrapper_signature.replace(parameters=updated_params) - wrapper.__signature__ = wrapper_signature + wrapper.__signature__ = wrapper_signature # type: ignore def update_function_signature( @@ -259,7 +259,7 @@ def update_function_signature( ) -> None: """Update the function signature to include new parameters.""" - updated_params = [] + updated_params: List[inspect.Parameter] = [] add_config_params_to_parser(updated_params, config_params) add_func_params_to_parser(updated_params, func_signature, ingestible_files) update_wrapper_signature(wrapper, updated_params) @@ -271,7 +271,7 @@ def update_deployed_function_signature( ingestible_files: Dict[str, inspect.Parameter], ) -> None: """Update the function signature to include new parameters.""" - updated_params = [] + updated_params: List[inspect.Parameter] = [] add_func_params_to_parser(updated_params, func_signature, ingestible_files) for param in [ "config", @@ -298,7 +298,11 @@ def add_config_params_to_parser( name, inspect.Parameter.KEYWORD_ONLY, default=Body(param), - annotation=Optional[type(param)], + annotation=param.__class__.__bases__[ + 0 + ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \ + # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (,), \ + # thus, why we are accessing the first item. ) ) @@ -319,8 +323,12 @@ def add_func_params_to_parser( inspect.Parameter( name, inspect.Parameter.KEYWORD_ONLY, - default=Body(..., embed=True), - annotation=param.annotation, + default=Body(param.default), + annotation=param.default.__class__.__bases__[ + 0 + ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \ + # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (,), \ + # thus, why we are accessing the first item. ) ) @@ -375,8 +383,8 @@ def handle_terminal_run( parser.add_argument( f"--{name}", type=str, - default=param.default, - choices=param.choices, + default=param.default, # type: ignore + choices=param.choices, # type: ignore ) else: parser.add_argument( @@ -426,7 +434,7 @@ def override_schema(openapi_schema: dict, func_name: str, endpoint: str, params: params (dict(param_name, param_val)): The dictionary of the parameters for the function """ - def find_in_schema(schema: dict, param_name: str, xparam: str): + def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, xparam: str): """Finds a parameter in the schema based on its name and x-parameter value""" for _, value in schema.items(): value_title_lower = str(value.get("title")).lower() @@ -438,9 +446,17 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): if ( isinstance(value, dict) - and value.get("x-parameter") == xparam + and schema_type_properties.get("x-parameter") == xparam and value_title == param_name ): + # this will update the default type schema with the properties gotten + # from the schema type (param_val) __schema_properties__ classmethod + for type_key, type_value in schema_type_properties.items(): + # BEFORE: + # value = {'temperature': {'title': 'Temperature'}} + value[type_key] = type_value + # AFTER: + # value = {'temperature': { "type": "number", "title": "Temperature", "x-parameter": "float" }} return value schema_to_override = openapi_schema["components"]["schemas"][ @@ -448,16 +464,20 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): ]["properties"] for param_name, param_val in params.items(): if isinstance(param_val, GroupedMultipleChoiceParam): - subschema = find_in_schema(schema_to_override, param_name, "grouped_choice") + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "grouped_choice" + ) assert ( subschema ), f"GroupedMultipleChoiceParam '{param_name}' is in the parameters but could not be found in the openapi.json" - subschema["choices"] = param_val.choices - subschema["default"] = param_val.default + subschema["choices"] = param_val.choices # type: ignore + subschema["default"] = param_val.default # type: ignore if isinstance(param_val, MultipleChoiceParam): - subschema = find_in_schema(schema_to_override, param_name, "choice") + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "choice" + ) default = str(param_val) - param_choices = param_val.choices + param_choices = param_val.choices # type: ignore choices = ( [default] + param_choices if param_val not in param_choices @@ -466,36 +486,59 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): subschema["enum"] = choices subschema["default"] = default if default in param_choices else choices[0] if isinstance(param_val, FloatParam): - subschema = find_in_schema(schema_to_override, param_name, "float") - subschema["minimum"] = param_val.minval - subschema["maximum"] = param_val.maxval + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "float" + ) + subschema["minimum"] = param_val.minval # type: ignore + subschema["maximum"] = param_val.maxval # type: ignore subschema["default"] = param_val if isinstance(param_val, IntParam): - subschema = find_in_schema(schema_to_override, param_name, "int") - subschema["minimum"] = param_val.minval - subschema["maximum"] = param_val.maxval + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "int" + ) + subschema["minimum"] = param_val.minval # type: ignore + subschema["maximum"] = param_val.maxval # type: ignore subschema["default"] = param_val if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is DictInput ): - subschema = find_in_schema(schema_to_override, param_name, "dict") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "dict", + ) subschema["default"] = param_val.default["default_keys"] if isinstance(param_val, TextParam): - subschema = find_in_schema(schema_to_override, param_name, "text") + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "text" + ) subschema["default"] = param_val if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is MessagesInput ): - subschema = find_in_schema(schema_to_override, param_name, "messages") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "messages", + ) subschema["default"] = param_val.default if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is FileInputURL ): - subschema = find_in_schema(schema_to_override, param_name, "file_url") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "file_url", + ) subschema["default"] = "https://example.com" if isinstance(param_val, BinaryParam): - subschema = find_in_schema(schema_to_override, param_name, "bool") - subschema["default"] = param_val.default + subschema = find_in_schema( + param_val.__schema_type_properties__(), schema_to_override, param_name, "bool" + ) + subschema["default"] = param_val.default # type: ignore From 283475fe9dd0353fce90ddf284b43f17845dc2e5 Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 18:56:43 +0100 Subject: [PATCH 04/24] Style: format code with black@23.12.0 --- agenta-cli/agenta/sdk/agenta_decorator.py | 34 ++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/agenta-cli/agenta/sdk/agenta_decorator.py b/agenta-cli/agenta/sdk/agenta_decorator.py index 4e20ff267a..903b4bd5c5 100644 --- a/agenta-cli/agenta/sdk/agenta_decorator.py +++ b/agenta-cli/agenta/sdk/agenta_decorator.py @@ -434,7 +434,9 @@ def override_schema(openapi_schema: dict, func_name: str, endpoint: str, params: params (dict(param_name, param_val)): The dictionary of the parameters for the function """ - def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, xparam: str): + def find_in_schema( + schema_type_properties: dict, schema: dict, param_name: str, xparam: str + ): """Finds a parameter in the schema based on its name and x-parameter value""" for _, value in schema.items(): value_title_lower = str(value.get("title")).lower() @@ -465,7 +467,10 @@ def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, for param_name, param_val in params.items(): if isinstance(param_val, GroupedMultipleChoiceParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "grouped_choice" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "grouped_choice", ) assert ( subschema @@ -474,7 +479,10 @@ def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, subschema["default"] = param_val.default # type: ignore if isinstance(param_val, MultipleChoiceParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "choice" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "choice", ) default = str(param_val) param_choices = param_val.choices # type: ignore @@ -487,14 +495,20 @@ def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, subschema["default"] = default if default in param_choices else choices[0] if isinstance(param_val, FloatParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "float" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "float", ) subschema["minimum"] = param_val.minval # type: ignore subschema["maximum"] = param_val.maxval # type: ignore subschema["default"] = param_val if isinstance(param_val, IntParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "int" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "int", ) subschema["minimum"] = param_val.minval # type: ignore subschema["maximum"] = param_val.maxval # type: ignore @@ -512,7 +526,10 @@ def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, subschema["default"] = param_val.default["default_keys"] if isinstance(param_val, TextParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "text" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "text", ) subschema["default"] = param_val if ( @@ -539,6 +556,9 @@ def find_in_schema(schema_type_properties: dict, schema: dict, param_name: str, subschema["default"] = "https://example.com" if isinstance(param_val, BinaryParam): subschema = find_in_schema( - param_val.__schema_type_properties__(), schema_to_override, param_name, "bool" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "bool", ) subschema["default"] = param_val.default # type: ignore From 9191c4c955dbff769ff7a1c99673760af17a6445 Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 19:03:08 +0100 Subject: [PATCH 05/24] Build: bump pydantic version to 2.7.1 --- agenta-cli/poetry.lock | 155 +++++++++++++++++++++++++++----------- agenta-cli/pyproject.toml | 2 +- 2 files changed, 113 insertions(+), 44 deletions(-) diff --git a/agenta-cli/poetry.lock b/agenta-cli/poetry.lock index 8319af3a35..3f4408969b 100644 --- a/agenta-cli/poetry.lock +++ b/agenta-cli/poetry.lock @@ -1,5 +1,16 @@ # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + [[package]] name = "anyio" version = "4.3.0" @@ -872,55 +883,113 @@ tests = ["pytest"] [[package]] name = "pydantic" -version = "1.10.13" -description = "Data validation and settings management using python type hints" +version = "2.7.1" +description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, - {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, - {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, - {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, - {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, - {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, - {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, - {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, - {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, - {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, + {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, + {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.18.2" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, + {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, + {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, + {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, + {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, + {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, + {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, + {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, + {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, + {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, + {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, + {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, + {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, + {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, + {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, + {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, + {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, + {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, + {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, + {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, + {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, + {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, + {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, + {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, + {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, + {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, + {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, + {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, + {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, + {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, + {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pygments" @@ -1738,4 +1807,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "ac397fd560d9b1bfa5d8ebbbb82b96c7948c345b24ffb0a54b59251db5b65815" +content-hash = "115bd3426f7a08e7df58ea51520f4ac87246705b3512020caaefe3c5b9e67139" diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index 478ea1aea5..2f5645d27a 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -27,7 +27,7 @@ python-dotenv = "^1.0.0" python-multipart = ">=0.0.6,<0.0.10" importlib-metadata = ">=6.7,<8.0" posthog = "^3.1.0" -pydantic = "1.10.13" +pydantic = "^2.7.1" httpx = ">=0.24, <0.28" pymongo = "^4.6.3" cachetools = "^5.3.3" From 90b8f11ecdfe79c9e2be90e13aeb6416741e03fd Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 19:06:39 +0100 Subject: [PATCH 06/24] Build: sync poetry.lock after merge with main changes --- agenta-cli/poetry.lock | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/agenta-cli/poetry.lock b/agenta-cli/poetry.lock index 4bb781b832..73fe479cc8 100644 --- a/agenta-cli/poetry.lock +++ b/agenta-cli/poetry.lock @@ -1199,7 +1199,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1808,4 +1807,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "08fb5e49d58c11148a96f9832200277304ec48e23ef6c0233a34ffc6c13d8a79" +content-hash = "d8588b4cf3cb4746dff1a1042c1e6d72999eaf2c0d82764ec25252ff89a6fdd5" From 8c3992379523b6a801a3d1a6697c16be1e40ea6b Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 20:00:35 +0100 Subject: [PATCH 07/24] Build (docker-assests): ensure installation of user application dependencies comes after agenta installation --- .../agenta/docker/docker-assets/Dockerfile.cloud.template | 2 +- agenta-cli/agenta/docker/docker-assets/Dockerfile.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/agenta-cli/agenta/docker/docker-assets/Dockerfile.cloud.template b/agenta-cli/agenta/docker/docker-assets/Dockerfile.cloud.template index cfbcb8b934..4cf2e59576 100644 --- a/agenta-cli/agenta/docker/docker-assets/Dockerfile.cloud.template +++ b/agenta-cli/agenta/docker/docker-assets/Dockerfile.cloud.template @@ -1,9 +1,9 @@ FROM public.ecr.aws/s2t9a1r1/agentaai/lambda_templates_public:main COPY requirements.txt ${LAMBDA_TASK_ROOT} +RUN pip install --no-cache-dir --disable-pip-version-check -U agenta RUN pip install --no-cache-dir --disable-pip-version-check -r requirements.txt RUN pip install --no-cache-dir --disable-pip-version-check mangum -RUN pip install --no-cache-dir --disable-pip-version-check -U agenta COPY . ${LAMBDA_TASK_ROOT} CMD [ "lambda_function.handler" ] diff --git a/agenta-cli/agenta/docker/docker-assets/Dockerfile.template b/agenta-cli/agenta/docker/docker-assets/Dockerfile.template index e6d613a536..9eb6b06a54 100644 --- a/agenta-cli/agenta/docker/docker-assets/Dockerfile.template +++ b/agenta-cli/agenta/docker/docker-assets/Dockerfile.template @@ -4,8 +4,8 @@ WORKDIR /app COPY . . -RUN pip install --no-cache-dir --disable-pip-version-check -r requirements.txt RUN pip install --no-cache-dir --disable-pip-version-check -U agenta +RUN pip install --no-cache-dir --disable-pip-version-check -r requirements.txt EXPOSE 80 From f57387874a1e2b733e757018404ef0476cf948a8 Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 20:01:16 +0100 Subject: [PATCH 08/24] Refactor (examples): added pydantic>=2 to baby_name_generator requirements.txt --- examples/baby_name_generator/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/baby_name_generator/requirements.txt b/examples/baby_name_generator/requirements.txt index 310f162cec..19c41365c9 100644 --- a/examples/baby_name_generator/requirements.txt +++ b/examples/baby_name_generator/requirements.txt @@ -1,2 +1,3 @@ agenta -openai \ No newline at end of file +openai +pydantic>=2 \ No newline at end of file From 754ead321bbc80bdde9bd22f97a58e717ad50eda Mon Sep 17 00:00:00 2001 From: Abram Date: Sat, 25 May 2024 20:41:00 +0100 Subject: [PATCH 09/24] Refactor (openapi_parser): update getBodySchemaName function to return the appropriate schema due to pydantic v2 upgrade --- agenta-web/src/lib/helpers/openapi_parser.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/agenta-web/src/lib/helpers/openapi_parser.ts b/agenta-web/src/lib/helpers/openapi_parser.ts index 1af5e25d87..a8f27d87eb 100644 --- a/agenta-web/src/lib/helpers/openapi_parser.ts +++ b/agenta-web/src/lib/helpers/openapi_parser.ts @@ -4,7 +4,9 @@ import {GenericObject, Parameter} from "../Types" const getBodySchemaName = (schema: GenericObject): string => { return ( - schema?.paths?.["/generate"]?.post?.requestBody?.content["application/json"]?.schema["$ref"] + schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.[ + "allOf" + ]?.[0]?.["$ref"] ?.split("/") ?.pop() || "" ) @@ -20,6 +22,7 @@ export const detectChatVariantFromOpenAISchema = (schema: GenericObject) => { export const openAISchemaToParameters = (schema: GenericObject): Parameter[] => { const parameters: Parameter[] = [] const bodySchemaName = getBodySchemaName(schema) + console.log("Body Schema Name: ", bodySchemaName) // get the actual schema for the body parameters Object.entries(schema.components.schemas[bodySchemaName].properties || {}).forEach( From b6f6dcce619ae93667f2ece44b32776875670a6c Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 10:31:46 +0100 Subject: [PATCH 10/24] Minor refactor (openapi_parser): remove redundant debug console statement --- agenta-web/src/lib/helpers/openapi_parser.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/agenta-web/src/lib/helpers/openapi_parser.ts b/agenta-web/src/lib/helpers/openapi_parser.ts index a8f27d87eb..c3603393cf 100644 --- a/agenta-web/src/lib/helpers/openapi_parser.ts +++ b/agenta-web/src/lib/helpers/openapi_parser.ts @@ -22,7 +22,6 @@ export const detectChatVariantFromOpenAISchema = (schema: GenericObject) => { export const openAISchemaToParameters = (schema: GenericObject): Parameter[] => { const parameters: Parameter[] = [] const bodySchemaName = getBodySchemaName(schema) - console.log("Body Schema Name: ", bodySchemaName) // get the actual schema for the body parameters Object.entries(schema.components.schemas[bodySchemaName].properties || {}).forEach( From 30e121620717ae05e0948d2162a2c9b21bdad1de Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 10:38:59 +0100 Subject: [PATCH 11/24] Refactor (agenta_decorator): added assertion to ensure length of param __class__ base type --- agenta-cli/agenta/sdk/agenta_decorator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/agenta-cli/agenta/sdk/agenta_decorator.py b/agenta-cli/agenta/sdk/agenta_decorator.py index 903b4bd5c5..b39fdd7766 100644 --- a/agenta-cli/agenta/sdk/agenta_decorator.py +++ b/agenta-cli/agenta/sdk/agenta_decorator.py @@ -293,6 +293,9 @@ def add_config_params_to_parser( ) -> None: """Add configuration parameters to function signature.""" for name, param in config_params.items(): + assert ( + len(param.__class__.__bases__) == 1 + ), f"Inherited standard type of {param.__class__} needs to be one." updated_params.append( inspect.Parameter( name, @@ -319,6 +322,9 @@ def add_func_params_to_parser( inspect.Parameter(name, param.kind, annotation=UploadFile) ) else: + assert ( + len(param.default.__class__.__bases__) == 1 + ), f"Inherited standard type of {param.default.__class__} needs to be one." updated_params.append( inspect.Parameter( name, From 4fcbda9412914942b70177df925c330f8de2a0b6 Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 10:39:59 +0100 Subject: [PATCH 12/24] SDK: bump version to pre-release agenta@0.14.14a0 --- agenta-cli/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index c302267a7a..d9d2fc9181 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agenta" -version = "0.14.14" +version = "0.14.14a0" description = "The SDK for agenta is an open-source LLMOps platform." readme = "README.md" authors = ["Mahmoud Mabrouk "] From 043073ddce29acb8e5b4a83c519723e784c9c1f7 Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 11:15:12 +0100 Subject: [PATCH 13/24] Build: bump version to fastapi to @0.111.0 and sdk to @0.14.14a1 --- agenta-cli/poetry.lock | 2 +- agenta-cli/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/agenta-cli/poetry.lock b/agenta-cli/poetry.lock index 73fe479cc8..49a4dab273 100644 --- a/agenta-cli/poetry.lock +++ b/agenta-cli/poetry.lock @@ -1807,4 +1807,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d8588b4cf3cb4746dff1a1042c1e6d72999eaf2c0d82764ec25252ff89a6fdd5" +content-hash = "29114fc78407faede13ffd2ea66a4cf0844c0f3f6b371f6f80d77412c3e7adde" diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index d9d2fc9181..9110d8ff26 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -19,7 +19,7 @@ keywords = ["LLMOps", "LLM", "evaluation", "prompt engineering"] python = "^3.9" docker = ">=6.1.1,<8.0.0" click = "^8.1.3" -fastapi = ">=0.96.1" +fastapi = "^0.111.0" toml = "^0.10.2" questionary = ">=1.10,<3.0" ipdb = ">=0.13" From 74557590bdb0b2c3c2ea40ed95dcb2c0e26fbc6f Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 11:25:00 +0100 Subject: [PATCH 14/24] SDK: bump pre-release version to @0.14.14a1 --- agenta-cli/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index 9110d8ff26..b2f66b4473 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agenta" -version = "0.14.14a0" +version = "0.14.14a1" description = "The SDK for agenta is an open-source LLMOps platform." readme = "README.md" authors = ["Mahmoud Mabrouk "] From 5de34ae7f597890f5bd147f241dacde09ed99924 Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 11:41:24 +0100 Subject: [PATCH 15/24] SDK: move pre-release version to 0.15.0a0 --- agenta-cli/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index b2f66b4473..62aa056478 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agenta" -version = "0.14.14a1" +version = "0.15.0a0" description = "The SDK for agenta is an open-source LLMOps platform." readme = "README.md" authors = ["Mahmoud Mabrouk "] From 7c9b884d70375a573a7c20cb1b0b0870122ae30b Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 12:06:19 +0100 Subject: [PATCH 16/24] Build & CI: improve test compose to have agenta-web service and update run-frontend-tests workflow --- .github/workflows/run-frontend-tests.yml | 4 ++-- docker-compose.test.yml | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-frontend-tests.yml b/.github/workflows/run-frontend-tests.yml index 010d385bed..b3de5f95af 100644 --- a/.github/workflows/run-frontend-tests.yml +++ b/.github/workflows/run-frontend-tests.yml @@ -33,7 +33,7 @@ jobs: NEXT_PUBLIC_OPENAI_API_KEY: ${{ secrets.NEXT_PUBLIC_OPENAI_API_KEY }} run: | sudo apt install curl -y - docker-compose -f "docker-compose.yml" up -d --build + docker-compose -f "docker-compose.test.yml" up -d --build - name: Restart Backend Service To Fetch Template(s) run: docker container restart agenta_backend_1 @@ -51,7 +51,7 @@ jobs: with: node-version: 18 - - name: Install Frontend Depedencies + - name: Install Frontend Dependencies run: | cd agenta-web/ && npm install diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 061e09d174..61b1a974a2 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -25,7 +25,7 @@ services: - DATABASE_MODE=test - FEATURE_FLAG=oss - OPENAI_API_KEY=${OPENAI_API_KEY} - - AGENTA_TEMPLATE_REPO=agentaai/templates_v2 + - AGENTA_TEMPLATE_REPO=agentaai/stage_templates - POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7 - TEMPLATES_BASE_URL=https://llm-app-json.s3.eu-central-1.amazonaws.com - REGISTRY_REPO_NAME=agentaai @@ -64,6 +64,26 @@ services: networks: - agenta-network + agenta-web: + build: + context: ./agenta-web + dockerfile: dev.Dockerfile + volumes: + - ./agenta-web/src:/app/src + - ./agenta-web/public:/app/public + - .nextjs_cache:/app/.next + ports: + - "3000:3000" + networks: + - agenta-network + labels: + - "traefik.http.routers.agenta-web.rule=PathPrefix(`/`)" + - "traefik.http.routers.agenta-web.entrypoints=web" + - "traefik.http.services.agenta-web.loadbalancer.server.port=3000" + environment: + - NEXT_PUBLIC_POSTHOG_API_KEY=phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7 + restart: always + mongo_express: image: mongo-express:0.54.0 environment: From 8341a8fbb77ef138c969e500aa999e2f2061f3a5 Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 12:13:58 +0100 Subject: [PATCH 17/24] Minor refactor (CI): update fourth step to make use of right backend service --- .github/workflows/run-frontend-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-frontend-tests.yml b/.github/workflows/run-frontend-tests.yml index b3de5f95af..e87e35fa39 100644 --- a/.github/workflows/run-frontend-tests.yml +++ b/.github/workflows/run-frontend-tests.yml @@ -36,7 +36,7 @@ jobs: docker-compose -f "docker-compose.test.yml" up -d --build - name: Restart Backend Service To Fetch Template(s) - run: docker container restart agenta_backend_1 + run: docker container restart agenta-backend-test - name: Wait for Backend Service run: curl http://localhost/api/health/ From 9c05908b6d06f67db8562611f6d9e01f643fca3a Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 27 May 2024 12:37:30 +0100 Subject: [PATCH 18/24] SDK: revert pre-release version back to upstream version 0.14.14 --- agenta-cli/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index 62aa056478..dd674bb544 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agenta" -version = "0.15.0a0" +version = "0.14.14" description = "The SDK for agenta is an open-source LLMOps platform." readme = "README.md" authors = ["Mahmoud Mabrouk "] From 9a26c5459c41ca56dbb926b566492e06c7cceb95 Mon Sep 17 00:00:00 2001 From: Abram Date: Fri, 31 May 2024 11:49:45 +0100 Subject: [PATCH 19/24] Refactor (llm_entrypoint): refactored entrypoint to compatibility with the latest version of pydantic --- .../agenta/sdk/decorators/llm_entrypoint.py | 137 ++++++++++++++---- 1 file changed, 110 insertions(+), 27 deletions(-) diff --git a/agenta-cli/agenta/sdk/decorators/llm_entrypoint.py b/agenta-cli/agenta/sdk/decorators/llm_entrypoint.py index 25b82f38de..53d5035381 100644 --- a/agenta-cli/agenta/sdk/decorators/llm_entrypoint.py +++ b/agenta-cli/agenta/sdk/decorators/llm_entrypoint.py @@ -203,15 +203,22 @@ async def execute_function(self, func: Callable[..., Any], *args, **func_params) if isinstance(result, str): return FuncResponse(message=result, latency=round(latency, 4)) # type: ignore if isinstance(result, int) or isinstance(result, float): - return FuncResponse(message=str(result), latency=round(latency, 4)) + return FuncResponse( + message=str(result), + usage=None, + cost=None, + latency=round(latency, 4), + ) if result is None: return FuncResponse( message="Function executed successfully, but did return None. \n Are you sure you did not forget to return a value?", + usage=None, + cost=None, latency=round(latency, 4), ) except Exception as e: self.handle_exception(e) - return FuncResponse(message="Unexpected error occurred when calling the @entrypoing decorated function", latency=0) # type: ignore + return FuncResponse(message="Unexpected error occurred when calling the @entrypoint decorated function", latency=0) # type: ignore def handle_exception(self, e: Exception): """Handle exceptions.""" @@ -237,7 +244,7 @@ def update_wrapper_signature( wrapper_signature = inspect.signature(wrapper) wrapper_signature = wrapper_signature.replace(parameters=updated_params) - wrapper.__signature__ = wrapper_signature + wrapper.__signature__ = wrapper_signature # type: ignore def update_function_signature( self, @@ -248,7 +255,7 @@ def update_function_signature( ) -> None: """Update the function signature to include new parameters.""" - updated_params = [] + updated_params: List[inspect.Parameter] = [] self.add_config_params_to_parser(updated_params, config_params) self.add_func_params_to_parser(updated_params, func_signature, ingestible_files) self.update_wrapper_signature(wrapper, updated_params) @@ -260,7 +267,8 @@ def update_deployed_function_signature( ingestible_files: Dict[str, inspect.Parameter], ) -> None: """Update the function signature to include new parameters.""" - updated_params = [] + + updated_params: List[inspect.Parameter] = [] self.add_func_params_to_parser(updated_params, func_signature, ingestible_files) for param in [ "config", @@ -281,12 +289,19 @@ def add_config_params_to_parser( ) -> None: """Add configuration parameters to function signature.""" for name, param in config_params.items(): + assert ( + len(param.__class__.__bases__) == 1 + ), f"Inherited standard type of {param.__class__} needs to be one." updated_params.append( inspect.Parameter( name, inspect.Parameter.KEYWORD_ONLY, default=Body(param), - annotation=Optional[type(param)], + annotation=param.__class__.__bases__[ + 0 + ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \ + # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (,), \ + # thus, why we are accessing the first item. ) ) @@ -303,12 +318,19 @@ def add_func_params_to_parser( inspect.Parameter(name, param.kind, annotation=UploadFile) ) else: + assert ( + len(param.default.__class__.__bases__) == 1 + ), f"Inherited standard type of {param.default.__class__} needs to be one." updated_params.append( inspect.Parameter( name, inspect.Parameter.KEYWORD_ONLY, default=Body(..., embed=True), - annotation=param.annotation, + annotation=param.default.__class__.__bases__[ + 0 + ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \ + # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (,), \ + # thus, why we are accessing the first item. ) ) @@ -358,7 +380,7 @@ def handle_terminal_run( f"--{name}", type=str, default=param.default, - choices=param.choices, + choices=param.choices, # type: ignore ) else: parser.add_argument( @@ -420,7 +442,9 @@ def override_schema( params (dict(param_name, param_val)): The dictionary of the parameters for the function """ - def find_in_schema(schema: dict, param_name: str, xparam: str): + def find_in_schema( + schema_type_properties: dict, schema: dict, param_name: str, xparam: str + ): """Finds a parameter in the schema based on its name and x-parameter value""" for _, value in schema.items(): value_title_lower = str(value.get("title")).lower() @@ -432,9 +456,17 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): if ( isinstance(value, dict) - and value.get("x-parameter") == xparam + and schema_type_properties.get("x-parameter") == xparam and value_title == param_name ): + # this will update the default type schema with the properties gotten + # from the schema type (param_val) __schema_properties__ classmethod + for type_key, type_value in schema_type_properties.items(): + # BEFORE: + # value = {'temperature': {'title': 'Temperature'}} + value[type_key] = type_value + # AFTER: + # value = {'temperature': { "type": "number", "title": "Temperature", "x-parameter": "float" }} return value schema_to_override = openapi_schema["components"]["schemas"][ @@ -443,17 +475,26 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): for param_name, param_val in params.items(): if isinstance(param_val, GroupedMultipleChoiceParam): subschema = find_in_schema( - schema_to_override, param_name, "grouped_choice" + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "grouped_choice", ) assert ( subschema ), f"GroupedMultipleChoiceParam '{param_name}' is in the parameters but could not be found in the openapi.json" - subschema["choices"] = param_val.choices - subschema["default"] = param_val.default + subschema["choices"] = param_val.choices # type: ignore + subschema["default"] = param_val.default # type: ignore + if isinstance(param_val, MultipleChoiceParam): - subschema = find_in_schema(schema_to_override, param_name, "choice") + subschema = find_in_schema( + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "choice", + ) default = str(param_val) - param_choices = param_val.choices + param_choices = param_val.choices # type: ignore choices = ( [default] + param_choices if param_val not in param_choices @@ -463,37 +504,79 @@ def find_in_schema(schema: dict, param_name: str, xparam: str): subschema["default"] = ( default if default in param_choices else choices[0] ) + if isinstance(param_val, FloatParam): - subschema = find_in_schema(schema_to_override, param_name, "float") - subschema["minimum"] = param_val.minval - subschema["maximum"] = param_val.maxval + subschema = find_in_schema( + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "float", + ) + subschema["minimum"] = param_val.minval # type: ignore + subschema["maximum"] = param_val.maxval # type: ignore subschema["default"] = param_val + if isinstance(param_val, IntParam): - subschema = find_in_schema(schema_to_override, param_name, "int") - subschema["minimum"] = param_val.minval - subschema["maximum"] = param_val.maxval + subschema = find_in_schema( + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "int", + ) + subschema["minimum"] = param_val.minval # type: ignore + subschema["maximum"] = param_val.maxval # type: ignore subschema["default"] = param_val + if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is DictInput ): - subschema = find_in_schema(schema_to_override, param_name, "dict") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "dict", + ) subschema["default"] = param_val.default["default_keys"] + if isinstance(param_val, TextParam): - subschema = find_in_schema(schema_to_override, param_name, "text") + subschema = find_in_schema( + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "text", + ) subschema["default"] = param_val + if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is MessagesInput ): - subschema = find_in_schema(schema_to_override, param_name, "messages") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "messages", + ) subschema["default"] = param_val.default + if ( isinstance(param_val, inspect.Parameter) and param_val.annotation is FileInputURL ): - subschema = find_in_schema(schema_to_override, param_name, "file_url") + subschema = find_in_schema( + param_val.annotation.__schema_type_properties__(), + schema_to_override, + param_name, + "file_url", + ) subschema["default"] = "https://example.com" + if isinstance(param_val, BinaryParam): - subschema = find_in_schema(schema_to_override, param_name, "bool") - subschema["default"] = param_val.default + subschema = find_in_schema( + param_val.__schema_type_properties__(), + schema_to_override, + param_name, + "bool", + ) + subschema["default"] = param_val.default # type: ignore From eb2e9446f7ce7fbc8017c2ef564dfdb55328e4c6 Mon Sep 17 00:00:00 2001 From: Mahmoud Mabrouk Date: Sun, 2 Jun 2024 18:32:15 +0200 Subject: [PATCH 20/24] fix to the openapi parser --- agenta-web/src/lib/helpers/openapi_parser.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/agenta-web/src/lib/helpers/openapi_parser.ts b/agenta-web/src/lib/helpers/openapi_parser.ts index c3603393cf..7c7e6f6581 100644 --- a/agenta-web/src/lib/helpers/openapi_parser.ts +++ b/agenta-web/src/lib/helpers/openapi_parser.ts @@ -3,13 +3,8 @@ import {GenericObject, Parameter} from "../Types" const getBodySchemaName = (schema: GenericObject): string => { - return ( - schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.[ - "allOf" - ]?.[0]?.["$ref"] - ?.split("/") - ?.pop() || "" - ) + const bodySchemaRef = schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.["$ref"]; + return bodySchemaRef?.split("/")?.pop() || ""; } export const detectChatVariantFromOpenAISchema = (schema: GenericObject) => { From 2af3202051b76e3c8d37f2a81131736fb9ac214e Mon Sep 17 00:00:00 2001 From: Mahmoud Mabrouk Date: Sun, 2 Jun 2024 18:34:30 +0200 Subject: [PATCH 21/24] format --- agenta-web/src/lib/helpers/openapi_parser.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/agenta-web/src/lib/helpers/openapi_parser.ts b/agenta-web/src/lib/helpers/openapi_parser.ts index 7c7e6f6581..a6dbc9a460 100644 --- a/agenta-web/src/lib/helpers/openapi_parser.ts +++ b/agenta-web/src/lib/helpers/openapi_parser.ts @@ -3,8 +3,11 @@ import {GenericObject, Parameter} from "../Types" const getBodySchemaName = (schema: GenericObject): string => { - const bodySchemaRef = schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.["$ref"]; - return bodySchemaRef?.split("/")?.pop() || ""; + const bodySchemaRef = + schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.[ + "$ref" + ] + return bodySchemaRef?.split("/")?.pop() || "" } export const detectChatVariantFromOpenAISchema = (schema: GenericObject) => { From 4d3b256a237fa0b0fb01ae5fd542f2ca6c646609 Mon Sep 17 00:00:00 2001 From: Abram Date: Mon, 3 Jun 2024 16:56:21 +0100 Subject: [PATCH 22/24] Build (poetry): ensure support for fastapi>=0.100.0 & pydantic>=2 --- agenta-cli/poetry.lock | 4 ++-- agenta-cli/pyproject.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/agenta-cli/poetry.lock b/agenta-cli/poetry.lock index 49a4dab273..03f1f86ed9 100644 --- a/agenta-cli/poetry.lock +++ b/agenta-cli/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -1807,4 +1807,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "29114fc78407faede13ffd2ea66a4cf0844c0f3f6b371f6f80d77412c3e7adde" +content-hash = "6d97347e0ac076de0bbaedfc2fb0ef9db603ca17a80d997444501391bf4a5dd8" diff --git a/agenta-cli/pyproject.toml b/agenta-cli/pyproject.toml index 3932ccdd9e..048102172b 100644 --- a/agenta-cli/pyproject.toml +++ b/agenta-cli/pyproject.toml @@ -19,7 +19,7 @@ keywords = ["LLMOps", "LLM", "evaluation", "prompt engineering"] python = "^3.9" docker = ">=6.1.1,<8.0.0" click = "^8.1.3" -fastapi = "^0.111.0" +fastapi = ">=0.100.0" toml = "^0.10.2" questionary = ">=1.10,<3.0" ipdb = ">=0.13" @@ -27,7 +27,7 @@ python-dotenv = "^1.0.0" python-multipart = ">=0.0.6,<0.0.10" importlib-metadata = ">=6.7,<8.0" posthog = "^3.1.0" -pydantic = "^2.7.1" +pydantic = ">=2" httpx = ">=0.24, <0.28" pymongo = "^4.6.3" cachetools = "^5.3.3" From a3a3825947c588a2665d37942c86caf5159ceb00 Mon Sep 17 00:00:00 2001 From: Abram Date: Tue, 4 Jun 2024 09:28:55 +0100 Subject: [PATCH 23/24] Refactor (openapi_parser): ensure backward compatibility for pydantic v1&v2 body schema --- agenta-web/src/lib/helpers/openapi_parser.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/agenta-web/src/lib/helpers/openapi_parser.ts b/agenta-web/src/lib/helpers/openapi_parser.ts index a6dbc9a460..6e6ac0afec 100644 --- a/agenta-web/src/lib/helpers/openapi_parser.ts +++ b/agenta-web/src/lib/helpers/openapi_parser.ts @@ -3,10 +3,22 @@ import {GenericObject, Parameter} from "../Types" const getBodySchemaName = (schema: GenericObject): string => { - const bodySchemaRef = + // Try v2 structure first + const v2BodySchemaRef = + schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.[ + "allOf" + ]?.[0]?.["$ref"] + + // If v2 structure doesn't exist, fall back to v1 structure + const v1BodySchemaRef = schema?.paths?.["/generate"]?.post?.requestBody?.content?.["application/json"]?.schema?.[ "$ref" ] + + // Determine the body schema reference to use + const bodySchemaRef = v2BodySchemaRef || v1BodySchemaRef + + // Return the last part of the reference or an empty string return bodySchemaRef?.split("/")?.pop() || "" } From 3892a1048dd3f9ca7cc5c8cfbf61e870041750e5 Mon Sep 17 00:00:00 2001 From: Abram Date: Tue, 4 Jun 2024 12:23:56 +0100 Subject: [PATCH 24/24] Minor refactor (app): revert requirements back to its previous state --- examples/baby_name_generator/requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/baby_name_generator/requirements.txt b/examples/baby_name_generator/requirements.txt index 19c41365c9..310f162cec 100644 --- a/examples/baby_name_generator/requirements.txt +++ b/examples/baby_name_generator/requirements.txt @@ -1,3 +1,2 @@ agenta -openai -pydantic>=2 \ No newline at end of file +openai \ No newline at end of file