diff --git a/.gitignore b/.gitignore index 45c9133..89514cb 100644 --- a/.gitignore +++ b/.gitignore @@ -332,4 +332,6 @@ test_json/ logs/json/ logs/temp/ logs/usage/ -*.ignore.* \ No newline at end of file +*.ignore.* +a.json +a.py \ No newline at end of file diff --git a/conf/config_models.py b/conf/config_models.py index 11c9a3f..ec5c546 100644 --- a/conf/config_models.py +++ b/conf/config_models.py @@ -46,7 +46,7 @@ class AppConfig: sentry: SentryConfig otel: OTELConfig environment: str = "development" - mongo: UsageCollectionMongoConfig = UsageCollectionMongoConfig() + mongo: UsageCollectionMongoConfig | None = None def New() -> AppConfig: diff --git a/conf/logger_conf.py b/conf/logger_conf.py index c7cebef..60726bb 100644 --- a/conf/logger_conf.py +++ b/conf/logger_conf.py @@ -25,22 +25,21 @@ def setup_logging(logfile: str) -> structlog.stdlib.BoundLogger: # --- 1. Create handlers --- console_handler = logging.StreamHandler(sys.stdout) + log_level = logging.DEBUG if os.getenv("ENVIRONMENT", "development").lower() == "development": - console_handler.setLevel(logging.INFO) + log_level = logging.DEBUG else: - console_handler.setLevel(logging.INFO) + log_level = logging.INFO + console_handler.setLevel(log_level) console_handler.setFormatter(logging.Formatter(fmt="%(message)s")) file_handler = logging.FileHandler(logfile) - if os.getenv("ENVIRONMENT", "development").lower() == "development": - file_handler.setLevel(logging.INFO) - else: - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(log_level) file_handler.setFormatter(logging.Formatter(fmt="%(message)s")) # --- 2. Set up root logger --- root_logger = logging.getLogger() - root_logger.setLevel(logging.DEBUG) + root_logger.setLevel(log_level) root_logger.handlers = [] # clear default handlers root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) @@ -57,7 +56,7 @@ def setup_logging(logfile: str) -> structlog.stdlib.BoundLogger: structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], logger_factory=structlog.stdlib.LoggerFactory(), - wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG), + wrapper_class=structlog.make_filtering_bound_logger(log_level), cache_logger_on_first_use=True, ) diff --git a/functions_to_format/functions/__init__.py b/functions_to_format/functions/__init__.py index 10f8fa0..e650872 100644 --- a/functions_to_format/functions/__init__.py +++ b/functions_to_format/functions/__init__.py @@ -7,6 +7,7 @@ get_suppliers_by_category, get_number_by_receiver_name, send_money_to_someone_via_card, + pay_for_home_utility, ) from .contact import build_contact_widget, get_contact from .news import build_news_widget, get_news @@ -52,4 +53,5 @@ "send_money_to_someone_via_card": send_money_to_someone_via_card, "get_home_balances": get_home_balances, "build_contacts_list": build_contacts_list, + "pay_for_home_utility": pay_for_home_utility, } diff --git a/functions_to_format/functions/balance.py b/functions_to_format/functions/balance.py index b986d1c..c85aea9 100644 --- a/functions_to_format/functions/balance.py +++ b/functions_to_format/functions/balance.py @@ -505,7 +505,7 @@ def build_balance_ui( margins=dv.DivEdgeInsets(bottom=8), ) ) - main_items.extend([card_block(c) for c in cards]) + main_items.extend([card_block(c, language) for c in cards]) # Сообщение и кнопки # main_items.append( diff --git a/functions_to_format/functions/functions.py b/functions_to_format/functions/functions.py index 4873cd8..f59a2ea 100644 --- a/functions_to_format/functions/functions.py +++ b/functions_to_format/functions/functions.py @@ -201,7 +201,7 @@ def build_contacts_list(context) -> BuildOutput: ), build_buttons_row: WidgetInput( widget=buttons, - args={"button_texts": ["cancel"]}, + args={"button_texts": ["cancel"], "language": language}, ), # build_text_widget: WidgetInput( # widget=text_widget, diff --git a/functions_to_format/functions/general/__init__.py b/functions_to_format/functions/general/__init__.py index 5d19f4d..dab58fe 100644 --- a/functions_to_format/functions/general/__init__.py +++ b/functions_to_format/functions/general/__init__.py @@ -3,6 +3,7 @@ from .buttons import build_buttons_row, ButtonsWidget from models.widget import Widget from pydantic import BaseModel +from conf import logger class WidgetInput(BaseModel): @@ -16,13 +17,17 @@ def add_ui_to_widget( ): if version == "v3": for sdui_function, widget_input in widget_inputs.items(): - if ( - sdui_function.__name__ == "build_text_widget" - and len(widget_input.args["text"]) == 0 - ): + try: + if ( + sdui_function.__name__ == "build_text_widget" + and len(widget_input.args["text"]) == 0 + ): + continue + widget_args = widget_input.args + widget_input.widget.build_ui(sdui_function, **widget_args) + except Exception as e: + logger.exception("Error building widget", error=e) continue - widget_args = widget_input.args - widget_input.widget.build_ui(sdui_function, **widget_args) widgets: List[Widget] = [] for widget_input in widget_inputs.values(): widgets.append(widget_input.widget) diff --git a/functions_to_format/functions/general/buttons.py b/functions_to_format/functions/general/buttons.py index a398c50..ac440c0 100644 --- a/functions_to_format/functions/general/buttons.py +++ b/functions_to_format/functions/general/buttons.py @@ -2,6 +2,7 @@ import json from models.widget import Widget from .const_values import WidgetMargins, WidgetPaddings, ButtonInRowMargins +from .const_values import LanguageOptions class ButtonsWidget(Widget): @@ -25,7 +26,7 @@ def make_contacts_search_button(txt, receiver_name): payload={"name": [receiver_name]}, # Optional: structured access ) return dv.DivText( - text="Qidirish", + text=txt, font_size=14, text_color="#2563EB", border=dv.DivBorder(corner_radius=8, stroke=dv.DivStroke(color="#3B82F6")), @@ -42,15 +43,38 @@ def make_contacts_search_button(txt, receiver_name): ) -def build_buttons_row(button_texts: list, receiver_name: str | None = None): +def build_buttons_row( + button_texts: list, + receiver_name: str | None = None, + language: LanguageOptions = LanguageOptions.RUSSIAN, +): items = [] + + texts_map = { + LanguageOptions.RUSSIAN: { + "search": "Поиск", + "cancel": "Отмена", + }, + LanguageOptions.ENGLISH: { + "search": "Search", + "cancel": "Cancel", + }, + LanguageOptions.UZBEK: { + "search": "Qidirish", + "cancel": "Bekor qilish", + }, + } + for txt in button_texts: if txt == "search": - items.append(make_contacts_search_button(txt, receiver_name)) + items.append( + make_contacts_search_button(texts_map[language][txt], receiver_name) + ) + else: items.append( dv.DivText( - text=txt, + text=texts_map[language][txt], font_size=14, text_color="#2563EB", border=dv.DivBorder( @@ -84,7 +108,7 @@ def build_buttons_row(button_texts: list, receiver_name: str | None = None): ), ) ) - with open("logs/build_buttons.json", "w") as f: + with open("logs/json/build_buttons.json", "w") as f: json.dump(div, f, indent=2, ensure_ascii=False) return div diff --git a/functions_to_format/functions/general/utils.py b/functions_to_format/functions/general/utils.py index 32bfa50..b867012 100644 --- a/functions_to_format/functions/general/utils.py +++ b/functions_to_format/functions/general/utils.py @@ -41,18 +41,16 @@ async def load_usages_async(collection: AsyncCollection, file_path: str): else: await collection.insert_one(usage) - logger.debug(f"Usage uploaded: {request_id}") - except Exception as e: logger.error(f"Error loading usages: {e}") async def upload_usages_async() -> None: try: - client = AsyncMongoClient(config.mongo.mongo_uri) + client = AsyncMongoClient(config.mongo.mongo_uri) # pyright: ignore[reportOptionalMemberAccess] collection: AsyncCollection = client.get_database( - config.mongo.database_name - ).get_collection(config.mongo.collection_name) + config.mongo.database_name # pyright: ignore[reportOptionalMemberAccess] + ).get_collection(config.mongo.collection_name) # pyright: ignore[reportOptionalMemberAccess] tasks = [] for file in os.listdir("logs/usage"): tasks.append(load_usages_async(collection, f"logs/usage/{file}")) diff --git a/functions_to_format/functions/payment.py b/functions_to_format/functions/payment.py index cc3b98a..408a3a1 100644 --- a/functions_to_format/functions/payment.py +++ b/functions_to_format/functions/payment.py @@ -1,4 +1,5 @@ import json + from .general import ( add_ui_to_widget, Widget, @@ -16,6 +17,7 @@ from tool_call_models.cards import CardsByPhoneNumberResponse, CardInfoByPhoneNumber from tool_call_models.paynet import ( CategoriesResponse, + PaymentManagerPaymentResponse, SupplierByCategoryResponse, Supplier, Category, @@ -27,6 +29,322 @@ from models.context import Context, LoggerContext +def build_pay_for_home_utility_ui( + payment_response: PaymentManagerPaymentResponse, + language: LanguageOptions = LanguageOptions.UZBEK, +): + """Build a payment success card UI using pydivkit""" + + texts_map = { + LanguageOptions.UZBEK: { + "payment_status": "To'lov miqdori", + "currency": "so'm", + "payment_description": "Mahsulot va xizmatlar uchun to'lov", + "transaction_details": "Tranzaksiya raqami:", + "date": "O'tkazish vaqti:", + "sender": "Jo'natuvchi:", + "receiver": "Qabul qiluvchi:", + }, + LanguageOptions.RUSSIAN: { + "payment_status": "Сумма платежа", + "currency": "cумм.", + "payment_description": "Платеж за товары и услуги", + "transaction_details": "Номер транзакции:", + "date": "Время перевода:", + "sender": "Отправитель:", + "receiver": "Получатель:", + }, + LanguageOptions.ENGLISH: { + "payment_status": "Payment amount", + "currency": "USD", + "payment_description": "Payment for goods and services", + "transaction_details": "Transaction number:", + "date": "Transfer time:", + "sender": "Sender:", + "receiver": "Receiver:", + }, + } + + # get receiver name ---- receiver name is the item in data.response where item["order"] == 1 + receiver_name = "" + for item in payment_response.data.response: + if item.order == 1: + receiver_name = item.value + break + + # Create payment details items from response + payment_items = [] + for item in payment_response.data.response: + payment_items.append( + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivText( + text=item.name, + text_color="#666666", + font_size=14, + font_weight=dv.DivFontWeight.REGULAR, + width=dv.DivWrapContentSize(), + margins=dv.DivEdgeInsets(right=8), + ), + dv.DivText( + text=item.value, + text_color="#000000", + font_size=14, + font_weight=dv.DivFontWeight.MEDIUM, + width=dv.DivMatchParentSize(), + text_alignment_horizontal=dv.DivAlignmentHorizontal.END, + ), + ], + margins=dv.DivEdgeInsets(bottom=12), + ) + ) + + # Create success card matching the image design + success_card = dv.DivContainer( + orientation=dv.DivContainerOrientation.VERTICAL, + background=[ + dv.DivSolidBackground( + color="#FFFFFF", + ) + ], + border=dv.DivBorder( + corner_radius=16, + ), + paddings=dv.DivEdgeInsets(left=24, top=32, right=24, bottom=32), + margins=dv.DivEdgeInsets(left=16, top=16, right=16, bottom=16), + items=[ + # Success checkmark icon + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivContainer( + background=[ + dv.DivSolidBackground( + color="#E8F5E8", + ) + ], + border=dv.DivBorder( + corner_radius=50, + ), + width=dv.DivFixedSize(value=80), + height=dv.DivFixedSize(value=80), + items=[ + dv.DivText( + text="✓", + text_color="#4CAF50", + font_size=36, + font_weight=dv.DivFontWeight.BOLD, + text_alignment_horizontal=dv.DivAlignmentHorizontal.CENTER, + text_alignment_vertical=dv.DivAlignmentVertical.CENTER, + ), + ], + ), + ], + content_alignment_horizontal=dv.DivContentAlignmentHorizontal.CENTER, + margins=dv.DivEdgeInsets(bottom=24), + ), + # Payment success title + dv.DivText( + text=texts_map[language]["payment_status"], + text_color="#666666", + font_size=16, + font_weight=dv.DivFontWeight.REGULAR, + text_alignment_horizontal=dv.DivAlignmentHorizontal.CENTER, + margins=dv.DivEdgeInsets(bottom=8), + ), + # Amount + dv.DivText( + text=f"{payment_response.additional.amount if payment_response.additional else '0'} {texts_map[language]['currency']}", + text_color="#000000", + font_size=32, + font_weight=dv.DivFontWeight.BOLD, + text_alignment_horizontal=dv.DivAlignmentHorizontal.CENTER, + margins=dv.DivEdgeInsets(bottom=8), + ), + # Service description + dv.DivContainer( + background=[ + dv.DivSolidBackground( + color="#E8F5E8", + ) + ], + border=dv.DivBorder( + corner_radius=8, + ), + paddings=dv.DivEdgeInsets(left=12, top=8, right=12, bottom=8), + margins=dv.DivEdgeInsets(bottom=32), + items=[ + dv.DivText( + text=texts_map[language]["payment_description"], + text_color="#4CAF50", + font_size=14, + font_weight=dv.DivFontWeight.MEDIUM, + text_alignment_horizontal=dv.DivAlignmentHorizontal.CENTER, + ), + ], + ), + # Transaction details + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivText( + text=texts_map[language]["transaction_details"], + text_color="#666666", + font_size=14, + font_weight=dv.DivFontWeight.REGULAR, + width=dv.DivWrapContentSize(), + ), + ], + margins=dv.DivEdgeInsets(bottom=8), + ), + # Separator line + dv.DivSeparator( + delimiter_style=dv.DivSeparatorDelimiterStyle( + color="#E0E0E0", + ), + margins=dv.DivEdgeInsets(bottom=16), + ), + # Date + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivText( + text=texts_map[language]["date"], + text_color="#666666", + font_size=14, + font_weight=dv.DivFontWeight.REGULAR, + width=dv.DivWrapContentSize(), + ), + dv.DivText( + text=payment_response.additional.date + if payment_response.additional + else "", + text_color="#000000", + font_size=14, + font_weight=dv.DivFontWeight.MEDIUM, + width=dv.DivMatchParentSize(), + text_alignment_horizontal=dv.DivAlignmentHorizontal.END, + ), + ], + margins=dv.DivEdgeInsets(bottom=16), + ), + # Recipient + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivText( + text=texts_map[language]["sender"], + text_color="#666666", + font_size=14, + font_weight=dv.DivFontWeight.REGULAR, + width=dv.DivWrapContentSize(), + ), + dv.DivContainer( + orientation=dv.DivContainerOrientation.VERTICAL, + width=dv.DivMatchParentSize(), + items=[ + dv.DivText( + text=payment_response.additional.sender_name + if payment_response.additional + else "", + text_color="#000000", + font_size=14, + font_weight=dv.DivFontWeight.MEDIUM, + text_alignment_horizontal=dv.DivAlignmentHorizontal.END, + ), + dv.DivText( + text=payment_response.additional.sender_masked_pan + if payment_response.additional + else "**** **** **** ****", + text_color="#666666", + font_size=12, + font_weight=dv.DivFontWeight.REGULAR, + text_alignment_horizontal=dv.DivAlignmentHorizontal.END, + ), + ], + ), + ], + margins=dv.DivEdgeInsets(bottom=16), + ), + # Receiver + dv.DivContainer( + orientation=dv.DivContainerOrientation.HORIZONTAL, + items=[ + dv.DivText( + text=texts_map[language]["receiver"], + text_color="#666666", + font_size=14, + font_weight=dv.DivFontWeight.REGULAR, + width=dv.DivWrapContentSize(), + ), + dv.DivText( + text=receiver_name, + text_color="#000000", + font_size=14, + font_weight=dv.DivFontWeight.MEDIUM, + width=dv.DivMatchParentSize(), + text_alignment_horizontal=dv.DivAlignmentHorizontal.END, + ), + ], + margins=dv.DivEdgeInsets(bottom=16), + ), + ], + ) + + return dv.make_div(success_card) + + +def pay_for_home_utility(context: Context) -> BuildOutput: + llm_output = context.llm_output + backend_output = context.backend_output + version = context.version + language = context.language + chat_id = context.logger_context.chat_id + api_key = context.api_key + logger = context.logger_context.logger + + backend_output = PaymentManagerPaymentResponse.model_validate(backend_output) + + logger.info("pay_for_home_utility") + + text_widget = TextWidget( + order=1, + values=[{"text": llm_output}], + ) + payment_status_widget = Widget( + order=2, + type="payment_status_widget", + name="payment_status_widget", + layout="vertical", + fields=["payment_status"], + values=[backend_output.model_dump()], + ) + + widgets = add_ui_to_widget( + { + build_text_widget: WidgetInput( + widget=text_widget, + args={ + "text": llm_output, + }, + ), + build_pay_for_home_utility_ui: WidgetInput( + widget=payment_status_widget, + args={"payment_response": backend_output}, + ), + }, + version, + ) + output = BuildOutput( + widgets_count=len(widgets), + widgets=[widget.model_dump(exclude_none=True) for widget in widgets], + ) + + save_builder_output(context, output) + return output + + def send_money_to_someone_via_card(context: Context) -> BuildOutput: # Extract values from context llm_output = context.llm_output @@ -123,7 +441,11 @@ def get_number_by_receiver_name(context) -> BuildOutput: # ), build_buttons_row: WidgetInput( widget=buttons, - args={"button_texts": ["cancel", "search"], "receiver_name": names}, + args={ + "button_texts": ["cancel", "search"], + "receiver_name": names, + "language": language, + }, ), }, version, @@ -170,9 +492,7 @@ def get_number_by_reciver_number_ui(receiver_name: Union[str, List[str]]): return div -def get_receiver_id_by_receiver_phone_number(context) -> BuildOutput: - from models.context import Context - +def get_receiver_id_by_receiver_phone_number(context: Context) -> BuildOutput: # Extract values from context llm_output = context.llm_output backend_output = context.backend_output @@ -213,7 +533,10 @@ def get_receiver_id_by_receiver_phone_number(context) -> BuildOutput: ), build_buttons_row: WidgetInput( widget=buttons, - args={"button_texts": ["cancel"]}, + args={ + "button_texts": ["cancel"], + "language": language, + }, ), build_text_widget: WidgetInput( widget=text_widget, @@ -421,7 +744,10 @@ def get_categories(context) -> BuildOutput: ), build_buttons_row: WidgetInput( widget=buttons, - args={"button_texts": ["cancel"]}, + args={ + "button_texts": ["cancel"], + "language": language, + }, ), build_text_widget: WidgetInput( widget=text_widget, @@ -539,7 +865,10 @@ def get_suppliers_by_category(context) -> BuildOutput: ), build_buttons_row: WidgetInput( widget=buttons_widget, - args={"button_texts": ["cancel"]}, + args={ + "button_texts": ["cancel"], + "language": language, + }, ), build_text_widget: WidgetInput( widget=text_widget, @@ -712,8 +1041,9 @@ def get_fields_of_supplier(context) -> BuildOutput: widget=button_widget, args={ "button_texts": [ - "Cancel", - ] + "cancel", + ], + "language": language, }, ), build_text_widget: WidgetInput( diff --git a/pyproject.toml b/pyproject.toml index 45d746e..1c6b6de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ dependencies = [ "requests==2.32.3", "sentry-sdk>=2.44.0", "structlog>=25.5.0", - "tool-call-models==0.1.35", + "tool-call-models==0.1.40", ] [dependency-groups] diff --git a/src/server.py b/src/server.py index 275c036..7d3e08e 100644 --- a/src/server.py +++ b/src/server.py @@ -83,10 +83,17 @@ class InputV2(BaseModel): backend_output: Union[Dict, List, None] = None +health_counter = 0 + + @app.get("/health") async def health(): # here I need function to upload logs/usage to somewhere - can be [s3, mongo] - await upload_usages_async() + # every health check is in 30 seconds so for 30 minutes I need to upload usages every 60 health checks + global health_counter + if health_counter % 60 == 0: + await upload_usages_async() + health_counter += 1 return "Ok" @@ -116,13 +123,14 @@ async def format_data(request: Request): async def format_data_v3(request: Request, input_data: InputV3): global logger version = "v3" - logger.debug("BUILD UI V3") + start_time = time.time() logger = logger.bind(chat_id=input_data.chat_id) + logger.info("BUILD UI V3") with tracer.start_as_current_span("build_ui_v3") as span: try: - logger.debug("Step 1: Entering /chat/v3/build_ui") + logger.info("Step 1: Entering /chat/v3/build_ui") language = LanguageOptions(request.headers.get("language", "ru")) func_name = input_data.function_name llm_output = input_data.llm_output or "" @@ -136,12 +144,11 @@ async def format_data_v3(request: Request, input_data: InputV3): span.set_attribute("function.version", version) span.set_attribute("language", language.value) - logger.debug( + logger.info( "Received request parameters", function_name=func_name, llm_output=llm_output, backend_output=backend_output, - chat_id=input_data.chat_id, api_key=input_data.api_key, ) @@ -156,7 +163,7 @@ async def format_data_v3(request: Request, input_data: InputV3): ).model_dump(), ) - logger.debug(f"Step 2: Found function {func_name}, invoking now") + logger.info(f"Step 2: Found function {func_name}, invoking now") # Time function execution func_start = time.time() @@ -185,7 +192,7 @@ async def format_data_v3(request: Request, input_data: InputV3): ) span.set_attribute("function.duration_ms", func_duration) - logger.debug(f"Step 3: Function result={result}") + logger.info(f"Step 3: Function result={result}") return result except Exception as e: diff --git a/telemetry/middleware.py b/telemetry/middleware.py index 9efaa29..d09b80d 100644 --- a/telemetry/middleware.py +++ b/telemetry/middleware.py @@ -90,15 +90,6 @@ async def dispatch(self, request: Request, call_next: Callable) -> Response: self.metrics_collector.decrement_active_requests() # Log request details - logger.debug( - "Request processed", - method=request.method, - path=request.url.path, - status_code=response.status_code, - duration_ms=duration_ms, - trace_id=format(span.get_span_context().trace_id, "032x"), - span_id=format(span.get_span_context().span_id, "016x"), - ) return response diff --git a/test.py b/test.py deleted file mode 100644 index df463ca..0000000 --- a/test.py +++ /dev/null @@ -1,908 +0,0 @@ -import json -from functions_to_format.functions import functions_mapper -from tool_call_models.cards import CardsByPhoneNumberResponse -from tool_call_models.paynet import ( - CategoriesResponse, - SupplierByCategoryResponse, - SupplierFieldsResponse, - Supplier, - Category, - SuppliersField, - FieldOptions, -) -from tool_call_models.weather import WeatherResponse - - -# functions_mapper = { -# "get_balance": get_balance, # ready -# "get_weather": get_weather_info, -# "get_news": get_news, -# "get_products": get_products, # ready -# "search_products": search_products, # ready -# "get_notifications": get_notifications, -# "get_contact": get_contact, # not ready -# "chatbot_answer": chatbot_answer, # ready -# "unauthorized_response": unauthorized_response, -# "get_number_by_receiver_name": get_number_by_receiver_name, # ready or not -- IDK -# "get_receiver_id_by_reciver_phone_number": get_receiver_id_by_receiver_phone_number, # not required -# "get_receiver_id_by_receiver_phone_number": get_receiver_id_by_receiver_phone_number, # not required -# "get_categories": get_categories, # ready -# "get_fields_of_supplier": get_fields_of_supplier, # not ready -# "get_suppliers_by_category": get_suppliers_by_category, # ready -# "start_page_widget": start_page_widget, # not ready -# "send_money_to_someone_via_card": send_money_to_someone_via_card # not ready -# "get_home_balances": get_home_balances, # ready -# } - -# get_weather_info -sample_data = WeatherResponse( - **{ - "location": { - "name": "Tashkent", - "region": "Toshkent", - "country": "Uzbekistan", - "lat": 41.3167, - "lon": 69.25, - "tz_id": "Asia/Tashkent", - "localtime_epoch": 1753078603, - "localtime": "2025-07-21 11:16", - }, - "current": { - "last_updated_epoch": 1753078500, - "last_updated": "2025-07-21 11:15", - "temp_c": 35.4, - "temp_f": 95.7, - "is_day": 1, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "wind_mph": 5.4, - "wind_kph": 8.6, - "wind_degree": 275, - "wind_dir": "W", - "pressure_mb": 1004.0, - "pressure_in": 29.65, - "precip_mm": 0.0, - "precip_in": 0.0, - "humidity": 28, - "cloud": 0, - "feelslike_c": 33.7, - "feelslike_f": 92.6, - "windchill_c": 38.8, - "windchill_f": 101.8, - "heatindex_c": 38.2, - "heatindex_f": 100.7, - "dewpoint_c": 6.6, - "dewpoint_f": 43.8, - "vis_km": 10.0, - "vis_miles": 6.0, - "uv": 8.7, - "gust_mph": 6.2, - "gust_kph": 9.9, - }, - "forecast": { - "forecastday": [ - { - "date": "2025-07-21", - "date_epoch": 1753056000, - "day": { - "maxtemp_c": 43.2, - "maxtemp_f": 109.7, - "mintemp_c": 27.5, - "mintemp_f": 81.5, - "avgtemp_c": 35.7, - "avgtemp_f": 96.2, - "maxwind_mph": 9.6, - "maxwind_kph": 15.5, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 16, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 2.7, - }, - "astro": { - "sunrise": "05:08 AM", - "sunset": "07:51 PM", - "moonrise": "12:58 AM", - "moonset": "05:08 PM", - "moon_phase": "Waning Crescent", - "moon_illumination": 18, - "is_moon_up": 0, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-22", - "date_epoch": 1753142400, - "day": { - "maxtemp_c": 44.0, - "maxtemp_f": 111.2, - "mintemp_c": 27.7, - "mintemp_f": 81.9, - "avgtemp_c": 35.7, - "avgtemp_f": 96.3, - "maxwind_mph": 11.2, - "maxwind_kph": 18.0, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 12, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 2.6, - }, - "astro": { - "sunrise": "05:09 AM", - "sunset": "07:50 PM", - "moonrise": "01:50 AM", - "moonset": "06:16 PM", - "moon_phase": "Waning Crescent", - "moon_illumination": 10, - "is_moon_up": 1, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-23", - "date_epoch": 1753228800, - "day": { - "maxtemp_c": 43.4, - "maxtemp_f": 110.2, - "mintemp_c": 28.2, - "mintemp_f": 82.7, - "avgtemp_c": 35.8, - "avgtemp_f": 96.4, - "maxwind_mph": 13.6, - "maxwind_kph": 22.0, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 10, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 2.7, - }, - "astro": { - "sunrise": "05:10 AM", - "sunset": "07:49 PM", - "moonrise": "02:53 AM", - "moonset": "07:12 PM", - "moon_phase": "Waning Crescent", - "moon_illumination": 4, - "is_moon_up": 1, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-24", - "date_epoch": 1753315200, - "day": { - "maxtemp_c": 41.2, - "maxtemp_f": 106.2, - "mintemp_c": 23.9, - "mintemp_f": 75.0, - "avgtemp_c": 33.1, - "avgtemp_f": 91.5, - "maxwind_mph": 13.9, - "maxwind_kph": 22.3, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 10, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 2.6, - }, - "astro": { - "sunrise": "05:11 AM", - "sunset": "07:48 PM", - "moonrise": "04:05 AM", - "moonset": "07:55 PM", - "moon_phase": "New Moon", - "moon_illumination": 1, - "is_moon_up": 1, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-25", - "date_epoch": 1753401600, - "day": { - "maxtemp_c": 41.3, - "maxtemp_f": 106.4, - "mintemp_c": 24.7, - "mintemp_f": 76.4, - "avgtemp_c": 33.5, - "avgtemp_f": 92.4, - "maxwind_mph": 13.2, - "maxwind_kph": 21.2, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 10, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 3.5, - }, - "astro": { - "sunrise": "05:12 AM", - "sunset": "07:47 PM", - "moonrise": "05:20 AM", - "moonset": "08:29 PM", - "moon_phase": "Waxing Crescent", - "moon_illumination": 0, - "is_moon_up": 0, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-26", - "date_epoch": 1753488000, - "day": { - "maxtemp_c": 42.1, - "maxtemp_f": 107.8, - "mintemp_c": 26.9, - "mintemp_f": 80.4, - "avgtemp_c": 35.0, - "avgtemp_f": 95.1, - "maxwind_mph": 13.0, - "maxwind_kph": 20.9, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 12, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 9.0, - }, - "astro": { - "sunrise": "05:13 AM", - "sunset": "07:46 PM", - "moonrise": "06:34 AM", - "moonset": "08:56 PM", - "moon_phase": "Waxing Crescent", - "moon_illumination": 2, - "is_moon_up": 0, - "is_sun_up": 0, - }, - }, - { - "date": "2025-07-27", - "date_epoch": 1753574400, - "day": { - "maxtemp_c": 38.8, - "maxtemp_f": 101.9, - "mintemp_c": 27.3, - "mintemp_f": 81.1, - "avgtemp_c": 33.3, - "avgtemp_f": 91.9, - "maxwind_mph": 13.4, - "maxwind_kph": 21.6, - "totalprecip_mm": 0.0, - "totalprecip_in": 0.0, - "totalsnow_cm": 0.0, - "avgvis_km": 10.0, - "avgvis_miles": 6.0, - "avghumidity": 19, - "daily_will_it_rain": 0, - "daily_chance_of_rain": 0, - "daily_will_it_snow": 0, - "daily_chance_of_snow": 0, - "condition": { - "text": "Sunny", - "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", - "code": 1000, - }, - "uv": 8.0, - }, - "astro": { - "sunrise": "05:14 AM", - "sunset": "07:45 PM", - "moonrise": "07:44 AM", - "moonset": "09:19 PM", - "moon_phase": "Waxing Crescent", - "moon_illumination": 6, - "is_moon_up": 0, - "is_sun_up": 0, - }, - }, - ] - }, - } -) - -functions_mapper["get_weather_info"]( - llm_output="Hello", backend_output=sample_data.model_dump(), version="v3" -) - - -#################### -#################### -#################### - - -contacts = [ - { - "first_name": "John", - "last_name": "Doe", - "phone": "1234567890", - }, - { - "first_name": "Jane", - "last_name": "Smith", - "phone": "0987654321", - }, - { - "first_name": "Jim", - "last_name": "Beam", - "phone": "1234567890", - }, -] - -build_contacts_list = functions_mapper["build_contacts_list"]( - llm_output="Hello world", - backend_output=contacts, - version="v3", -) - -# get categories json -get_categories = functions_mapper["get_categories"]( - llm_output="Hello world", - backend_output=CategoriesResponse( - payload=[ - Category( - id=1, - name="Category 1", - s3Url="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - imagePath="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - ), - Category( - id=2, - name="Category 2", - s3Url="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - imagePath="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - ), - Category( - id=3, - name="Category 3", - s3Url="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - imagePath="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - ), - Category( - id=4, - name="Category 4", - s3Url="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - imagePath="https://img.icons8.com/?size=100&id=64062&format=png&color=000000", - ), - ] - ).model_dump(), - version="v3", -) - - -# get_categories - show categories widget -from tool_call_models.paynet import CategoriesResponse, Category - -categories = [ - { - "id": 1, - "name": "Uyali aloqa", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056545-57d63349-cdc1-4438-982f-23ae508dd782", - }, - { - "id": 2, - "name": "Uy telefoni", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056505-ad89d454-3f47-4e68-bc26-74fd2d32c5e2", - }, - { - "id": 3, - "name": "Internet", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056578-a950e105-f0f2-4b8f-af05-766d730593e9", - }, - { - "id": 4, - "name": "Xizmatlar", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056264-e1c665dc-ed0e-4617-9835-ddac232a1ffe", - }, - { - "id": 5, - "name": "Televidenie", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056745-0899c2dc-f194-41e2-9a30-b1c16d45ef3e", - }, - { - "id": 6, - "name": "Taxi", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056657-eb712c52-a9ee-4293-b6ff-38eaaa052401", - }, - { - "id": 7, - "name": "Kommunal xizmatlar", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056712-902ee66f-9ad1-4d73-940a-c5f174b01ae0", - }, - { - "id": 9, - "name": "Online platformalar", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671057830-ef6d3711-ff17-44b3-9107-1a3e8f6085aa", - }, - { - "id": 11, - "name": "Ta`lim", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671058625-3b117d55-22a0-42e6-aed0-a48c995586c3", - }, - { - "id": 18, - "name": "Xayriya", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671056624-ea0e5f25-4998-4e49-9129-f8f6fed1fe94", - }, - { - "id": 23, - "name": "Muddatli to'lovlar", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671057272-e9da9dfc-c49b-47eb-9592-a201866ab5fe", - }, - { - "id": 26, - "name": "Sport", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1ff1f772-fae4-44f3-b5d2-a20554966b5c", - }, - { - "id": 27, - "name": "Mehmonxonalar va turizm", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/58cbc39e-3906-4c97-b8ec-af9ece6d0d23", - }, - { - "id": 28, - "name": "Sug'urta", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/5ab0d1bc-c3e7-4098-bd03-449ea84e74c5", - }, - { - "id": 29, - "name": "Tibbiyot", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/2c365621-57e2-4a6a-b895-f76716bb0033", - }, - { - "id": 30, - "name": "Yuridik xizmatlar", - "imagePath": None, - "s3Url": "https://s3.smartbank.uz/mobile-ui/4edc3627-310d-4773-a2f6-8e358b4f5e07", - }, -] -categories = CategoriesResponse( - payload=[Category(**c) for c in categories] -).model_dump() - -get_categories = functions_mapper["get_categories"]( - llm_output="Hello world", - backend_output=categories, - version="v3", -) - -## get_fields_of_supplier - to show fiellds of supplier -from tool_call_models.paynet import Field, SupplierFieldsResponse - -paylad = { - "checkUp": True, - "checkUpWithResponse": True, - "checkUpAfterPayment": False, - "fieldList": [ - { - "identName": "paymentNo1", - "name": "TETK", - "order": 1, - "type": "COMBOBOX", - "pattern": "FILIALS", - "minValue": None, - "maxValue": None, - "fieldSize": 5, - "isMain": None, - "valueList": [ - str({"value": 6204, "name": "Olot TETK"}), - str({"value": 6207, "name": "Buxoro TETK"}), - str({"value": 6212, "name": "Vobkent TETK"}), - str({"value": 6215, "name": "G'ijduvon TETK"}), - str({"value": 6219, "name": "Kogon TETK"}), - str({"value": 6230, "name": "Qorako'l TETK"}), - str({"value": 6232, "name": "Qorovulbozor TETK"}), - str({"value": 6240, "name": "Peshku TETK"}), - str({"value": 6242, "name": "Romitan TETK"}), - str({"value": 6246, "name": "Jondor TETK"}), - str({"value": 6258, "name": "Shofirkon TETK"}), - str({"value": 6401, "name": "Buxoro ShETK"}), - ], - }, - { - "identName": "amount", - "name": "Summa", - "order": 3, - "type": "MONEY", - "pattern": None, - "minValue": 500, - "maxValue": 5000000, - "fieldSize": 12, - "isMain": None, - "valueList": [], - }, - { - "identName": "paymentNo", - "name": "Shaxsiy raqami", - "order": 2, - "type": "STRING", - "pattern": None, - "minValue": None, - "maxValue": None, - "fieldSize": 8, - "isMain": True, - "valueList": [], - }, - ], -} -fields = SupplierFieldsResponse(payload=SuppliersField(**paylad)).model_dump() - -get_fields_of_supplier = functions_mapper["get_fields_of_supplier"]( - llm_output="Hello world", - backend_output=fields, - version="v3", -) - - -## get suppliers by category json - get_suppliers_by_category -suppliers = { - "payload": [ - { - "id": 932, - "name": "Elektr energiya", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671090211-0992368e-af07-49ff-a384-0a4641b377be", - }, - { - "id": 933, - "name": "Tabiiy gaz", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671091467-5f760f9b-67a6-41a5-8ffe-3117a6da8618", - }, - { - "id": 933, - "name": "Suyultirilgan Gaz", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671091550-b8aee728-c600-4c05-b1b5-3f131eba9bf0", - }, - { - "id": 934, - "name": "HGT Gaz servis", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671091596-2b6e458e-c8a9-4430-a912-3706321f9f2d", - }, - { - "id": 935, - "name": "Chiqindilarni olib ketish", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671091635-55cb00c7-2efb-454c-8ca5-330626a2a9fb", - }, - { - "id": 936, - "name": "Veolia Energy Tashkent", - "categoryId": 7, - "s3Url": "https://s3.smartbank.uz/mobile-ui/1691671091668-b3758fa8-ef28-4a62-b2bf-11e260014581", - }, - ] -} -get_suppliers_by_category = functions_mapper["get_suppliers_by_category"]( - llm_output="Hello world", - backend_output=SupplierByCategoryResponse(**suppliers).model_dump(), # pyright: ignore[reportArgumentType] - version="v3", -) - -from tool_call_models.home_balance import HomeBalance, HomeBalanceDetails - -# home balance widget -get_home_balances = functions_mapper["get_home_balances"]( - llm_output="Hello world", - backend_output=HomeBalance( - **{ - "homeName": "г. Ташкент, Учтепинский район, кв. 31, Д", - "gas": {"balance": 55470000, "details": {"2080": 1676000, "13839": 554700}}, - "electricity": {"balance": 251758006, "details": {"13842": 2517586}}, - "garbage": {"balance": 490000000, "details": {"13841": 4900000}}, - "coldWater": {"balance": 278190000, "details": {"13840": 2781900}}, - "internet": {"balance": 100000000, "details": {"13843": 1000000}}, - }, - ).model_dump(), - version="v3", -) - - -from tool_call_models.cards import CardsBalanceResponse - -# card balance test - build_balance_ui -balance = { - "custNo": "60005982", - "phoneNumber": "998331191213", - "firstname": "ASLONXO‘JA", - "middlename": "JALOLIDDINOVICH", - "lastname": "HAMIDOV", - "birthDate": "2001-12-13", - "pinfl": "51312016860023", - "createdAt": "2024-04-09T20:37:13.764699", - "cardList": [ - { - "panMask": "7478", - "panToken": "87a4be2d-7115-4d63-bf93-d76450b2b1fc", - "requestId": "87a4be2d-7115-4d63-bf93-d76450b2b1fc", - "pan": "************7478", - "expiry": "2604", - "bankIssuer": "SmartBank", - "uzcardToken": None, - "processingSystem": "humo", - "salaryAmount": 500000000, - "isVerified": True, - "createdAt": "2024-04-09T20:42:48.535911", - "cardDetails": { - "cardDetailsId": 7846, - "cardName": "Smartbank Virtual", - "cardColor": "0006", - "cardIsPrimary": False, - }, - "cardBalance": {"balance": "9222", "status": 0}, - "isVirtual": True, - "bankIcon": { - "bankLogo": "https://s3.smartbank.uz/bank-logos/smart.png", - "bankLogoMini": "https://s3.smartbank.uz/bank-logos/smart-mini.png", - "bankWhiteLogo": "https://s3.smartbank.uz/bank-logos/smart-white.png", - "bankWhiteLogoMini": "https://s3.smartbank.uz/bank-logos/smart-mini-white.png", - }, - }, - { - "panMask": "5289", - "panToken": "ea8dc9ea-7aba-4bbc-b219-c37f8b6dcfd5", - "requestId": "ea8dc9ea-7aba-4bbc-b219-c37f8b6dcfd5", - "pan": "************5289", - "expiry": "2602", - "bankIssuer": "Kapital", - "uzcardToken": None, - "processingSystem": "humo", - "salaryAmount": 500000000, - "isVerified": True, - "createdAt": "2024-07-02T10:55:27.266157", - "cardDetails": { - "cardDetailsId": 23192, - "cardName": "kapital", - "cardColor": "0000", - "cardIsPrimary": False, - }, - "cardBalance": {"balance": "0", "status": 0}, - "isVirtual": False, - "bankIcon": { - "bankLogo": "https://s3.smartbank.uz/bank-logos/kapital.png", - "bankLogoMini": "https://s3.smartbank.uz/bank-logos/kapital-mini.png", - "bankWhiteLogo": "https://s3.smartbank.uz/bank-logos/kapital-white.png", - "bankWhiteLogoMini": "https://s3.smartbank.uz/bank-logos/kapital-mini-white.png", - }, - }, - { - "panMask": "7704", - "panToken": "8e96ef48-6c03-431a-bc7b-081af3c98d1d", - "requestId": "8e96ef48-6c03-431a-bc7b-081af3c98d1d", - "pan": "************7704", - "expiry": "2907", - "bankIssuer": "SmartBank", - "uzcardToken": None, - "processingSystem": "humo", - "salaryAmount": 500000000, - "isVerified": True, - "createdAt": "2024-07-16T11:34:28.535018", - "cardDetails": { - "cardDetailsId": 42946, - "cardName": "Smartbank fiz", - "cardColor": "0000", - "cardIsPrimary": False, - }, - "cardBalance": {"balance": "2219330", "status": 0}, - "isVirtual": False, - "bankIcon": { - "bankLogo": "https://s3.smartbank.uz/bank-logos/smart.png", - "bankLogoMini": "https://s3.smartbank.uz/bank-logos/smart-mini.png", - "bankWhiteLogo": "https://s3.smartbank.uz/bank-logos/smart-white.png", - "bankWhiteLogoMini": "https://s3.smartbank.uz/bank-logos/smart-mini-white.png", - }, - }, - { - "panMask": "9710", - "panToken": "c39cef39-07ab-4439-8c2b-25d07a912c28", - "requestId": "c39cef39-07ab-4439-8c2b-25d07a912c28", - "pan": "************9710", - "expiry": "2910", - "bankIssuer": "BRB", - "uzcardToken": None, - "processingSystem": "humo", - "salaryAmount": 500000000, - "isVerified": True, - "createdAt": "2024-10-23T13:00:01.056936", - "cardDetails": { - "cardDetailsId": 166412, - "cardName": "brb", - "cardColor": "0000", - "cardIsPrimary": False, - }, - "cardBalance": {"balance": "50000", "status": 0}, - "isVirtual": False, - "bankIcon": { - "bankLogo": "https://s3.smartbank.uz/bank-logos/brb.png", - "bankLogoMini": "https://s3.smartbank.uz/bank-logos/brb-mini.png", - "bankWhiteLogo": "https://s3.smartbank.uz/bank-logos/brb-white.png", - "bankWhiteLogoMini": "https://s3.smartbank.uz/bank-logos/brb-mini-white.png", - }, - }, - ], -} -get_balance = functions_mapper["get_balance"]( - llm_output="Hello world", - backend_output=CardsBalanceResponse(**balance).model_dump(), - version="v3", -) - - -# get_products --- show products widget -from tool_call_models.smartbazar import ( - SearchProductsResponse, - ProductItem, - Meta, - MainCategory, - MainCategoryParent, - Brand, - Offer, -) - - -category = MainCategory( - id=1, - name="Category 1", - slug="category-1", - depth=1, - parent=MainCategoryParent(id=None, name=None, slug=None, depth=None, parent=None), - exist_children=False, - product_count=10, - order=1, - status=1, - created_at="2024-01-01T00:00:00", - updated_at="2024-01-01T00:00:00", -) -offer = Offer( - id=1, - original_price=1000000, - price=900000, - three_month_price=350000, # pyright: ignore[reportCallIssue] - six_month_price=200000, # pyright: ignore[reportCallIssue] - nine_month_price=150000, # pyright: ignore[reportCallIssue] - twelve_month_price=100000, # pyright: ignore[reportCallIssue] - eighteen_month_price=80000, # pyright: ignore[reportCallIssue] - discount=True, - discount_percent=10, - discount_start_at="2024-01-01T00:00:00", - discount_expire_at="2024-12-31T23:59:59", - merchant=None, - status={"active": True}, - market_type="b2c", -) -product = ProductItem( - id=123, - slug="samsung-galaxy-s21", - brand=Brand( - id=1, - name="Samsung", - ), - created_at="2024-01-15T10:30:00", - updated_at="2024-01-16T15:45:00", - count=50, - tracking=True, - offers=[offer, offer, offer], - view_count=1000, - order_count=25, - like_count=150, - rate=4, - cancelled_count=2, -) - -get_products = functions_mapper["get_products"]( - llm_output="Hello world", - backend_output=SearchProductsResponse( - products=[ - product, - product, - product, - product, - ], - meta=Meta(current_page=1, last_page=1, path=None, per_page=1, to=1, total=1), - ).model_dump(), -) - - -# text widget test -build_text_widget = functions_mapper["chatbot_answer"]( - llm_output="""Вот баланс ваших карт и счетов, хотите произвести оплату за телефон или перевод? - Привет! Я Бек, умный голосовой помощник. - Расскажу про наши продукты и сервисы, а так же помогу с оплатами и переводами. - Просто нажмите на меня и спросите что вас интересует, например: -""", - backend_output=None, - version="v3", -) - - -# get number by receiver name ---- to show contacts after and update the content using custom action of divkit -get_number_by_receiver_name = functions_mapper["get_number_by_receiver_name"]( - llm_output="Aslon", - backend_output={"receiver_name": "Aslon"}, - version="v3", -) diff --git a/uv.lock b/uv.lock index 8ea98ed..18215ea 100644 --- a/uv.lock +++ b/uv.lock @@ -1066,17 +1066,28 @@ wheels = [ [[package]] name = "psutil" -version = "6.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/10/2a30b13c61e7cf937f4adf90710776b7918ed0a9c434e2c38224732af310/psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a", size = 508565, upload-time = "2024-10-17T21:31:45.68Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/01/9e/8be43078a171381953cfee33c07c0d628594b5dbfc5157847b85022c2c1b/psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688", size = 247762, upload-time = "2024-10-17T21:32:05.991Z" }, - { url = "https://files.pythonhosted.org/packages/1d/cb/313e80644ea407f04f6602a9e23096540d9dc1878755f3952ea8d3d104be/psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e", size = 248777, upload-time = "2024-10-17T21:32:07.872Z" }, - { url = "https://files.pythonhosted.org/packages/65/8e/bcbe2025c587b5d703369b6a75b65d41d1367553da6e3f788aff91eaf5bd/psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38", size = 284259, upload-time = "2024-10-17T21:32:10.177Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b", size = 287255, upload-time = "2024-10-17T21:32:11.964Z" }, - { url = "https://files.pythonhosted.org/packages/27/c2/d034856ac47e3b3cdfa9720d0e113902e615f4190d5d1bdb8df4b2015fb2/psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a", size = 288804, upload-time = "2024-10-17T21:32:13.785Z" }, - { url = "https://files.pythonhosted.org/packages/ea/55/5389ed243c878725feffc0d6a3bc5ef6764312b6fc7c081faaa2cfa7ef37/psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e", size = 250386, upload-time = "2024-10-17T21:32:21.399Z" }, - { url = "https://files.pythonhosted.org/packages/11/91/87fa6f060e649b1e1a7b19a4f5869709fbf750b7c8c262ee776ec32f3028/psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be", size = 254228, upload-time = "2024-10-17T21:32:23.88Z" }, +version = "7.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/88/bdd0a41e5857d5d703287598cbf08dad90aed56774ea52ae071bae9071b6/psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", size = 489059, upload-time = "2025-11-02T12:25:54.619Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/93/0c49e776b8734fef56ec9c5c57f923922f2cf0497d62e0f419465f28f3d0/psutil-7.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", size = 239751, upload-time = "2025-11-02T12:25:58.161Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8d/b31e39c769e70780f007969815195a55c81a63efebdd4dbe9e7a113adb2f/psutil-7.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", size = 240368, upload-time = "2025-11-02T12:26:00.491Z" }, + { url = "https://files.pythonhosted.org/packages/62/61/23fd4acc3c9eebbf6b6c78bcd89e5d020cfde4acf0a9233e9d4e3fa698b4/psutil-7.1.3-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", size = 287134, upload-time = "2025-11-02T12:26:02.613Z" }, + { url = "https://files.pythonhosted.org/packages/30/1c/f921a009ea9ceb51aa355cb0cc118f68d354db36eae18174bab63affb3e6/psutil-7.1.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", size = 289904, upload-time = "2025-11-02T12:26:05.207Z" }, + { url = "https://files.pythonhosted.org/packages/a6/82/62d68066e13e46a5116df187d319d1724b3f437ddd0f958756fc052677f4/psutil-7.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", size = 249642, upload-time = "2025-11-02T12:26:07.447Z" }, + { url = "https://files.pythonhosted.org/packages/df/ad/c1cd5fe965c14a0392112f68362cfceb5230819dbb5b1888950d18a11d9f/psutil-7.1.3-cp313-cp313t-win_arm64.whl", hash = "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", size = 245518, upload-time = "2025-11-02T12:26:09.719Z" }, + { url = "https://files.pythonhosted.org/packages/2e/bb/6670bded3e3236eb4287c7bcdc167e9fae6e1e9286e437f7111caed2f909/psutil-7.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", size = 239843, upload-time = "2025-11-02T12:26:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/b8/66/853d50e75a38c9a7370ddbeefabdd3d3116b9c31ef94dc92c6729bc36bec/psutil-7.1.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", size = 240369, upload-time = "2025-11-02T12:26:14.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/bd/313aba97cb5bfb26916dc29cf0646cbe4dd6a89ca69e8c6edce654876d39/psutil-7.1.3-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", size = 288210, upload-time = "2025-11-02T12:26:16.699Z" }, + { url = "https://files.pythonhosted.org/packages/c2/fa/76e3c06e760927a0cfb5705eb38164254de34e9bd86db656d4dbaa228b04/psutil-7.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f", size = 291182, upload-time = "2025-11-02T12:26:18.848Z" }, + { url = "https://files.pythonhosted.org/packages/0f/1d/5774a91607035ee5078b8fd747686ebec28a962f178712de100d00b78a32/psutil-7.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", size = 250466, upload-time = "2025-11-02T12:26:21.183Z" }, + { url = "https://files.pythonhosted.org/packages/00/ca/e426584bacb43a5cb1ac91fae1937f478cd8fbe5e4ff96574e698a2c77cd/psutil-7.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", size = 245756, upload-time = "2025-11-02T12:26:23.148Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/46b9154a800253e7ecff5aaacdf8ebf43db99de4a2dfa18575b02548654e/psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", size = 238359, upload-time = "2025-11-02T12:26:25.284Z" }, + { url = "https://files.pythonhosted.org/packages/68/3a/9f93cff5c025029a36d9a92fef47220ab4692ee7f2be0fba9f92813d0cb8/psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", size = 239171, upload-time = "2025-11-02T12:26:27.23Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b1/5f49af514f76431ba4eea935b8ad3725cdeb397e9245ab919dbc1d1dc20f/psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", size = 263261, upload-time = "2025-11-02T12:26:29.48Z" }, + { url = "https://files.pythonhosted.org/packages/e0/95/992c8816a74016eb095e73585d747e0a8ea21a061ed3689474fabb29a395/psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", size = 264635, upload-time = "2025-11-02T12:26:31.74Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/c3ed1a622b6ae2fd3c945a366e64eb35247a31e4db16cf5095e269e8eb3c/psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", size = 247633, upload-time = "2025-11-02T12:26:33.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ad/33b2ccec09bf96c2b2ef3f9a6f66baac8253d7565d8839e024a6b905d45d/psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", size = 244608, upload-time = "2025-11-02T12:26:36.136Z" }, ] [[package]] @@ -1650,14 +1661,14 @@ wheels = [ [[package]] name = "tool-call-models" -version = "0.1.35" +version = "0.1.40" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/31/d1/2efce88318f87fa06221a853baf7ddcdd7ddd24d7025391cbefe1144d9c1/tool_call_models-0.1.35.tar.gz", hash = "sha256:3b03eeb2c1cfb19756f3c63e7153c4424f2a0468785f0cbbde47d4b5f162ef76", size = 5558, upload-time = "2025-10-23T12:30:28.802Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/2d/47eb29f0643c0e97d288d3873cd70932f3aeb109d14cfb122da75dfd9369/tool_call_models-0.1.40.tar.gz", hash = "sha256:980df59c360721936559ec4724024d3744b5d4441d5f7b8cad7635b18f0ff340", size = 6476, upload-time = "2025-11-13T06:38:54.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/ee/2f78184faebb48c28f62bf84df30e6dd368c539d72b013f775c40432cfb7/tool_call_models-0.1.35-py3-none-any.whl", hash = "sha256:8716e32da02cd92370a13d447e26eebdc151f1f9a8892f6e3ba28997ecd7951a", size = 8038, upload-time = "2025-10-23T12:30:27.759Z" }, + { url = "https://files.pythonhosted.org/packages/c6/80/3478db182a1e3f51fe239df4d309a9c47287cd2eb5c4eaa06f13ff995c6f/tool_call_models-0.1.40-py3-none-any.whl", hash = "sha256:31c2bfe5f73670c3ab5315b5fb1391c2021f946e401c847a4a4250f84fece04d", size = 8942, upload-time = "2025-11-13T06:38:52.995Z" }, ] [[package]] @@ -1793,7 +1804,7 @@ requires-dist = [ { name = "requests", specifier = "==2.32.3" }, { name = "sentry-sdk", specifier = ">=2.44.0" }, { name = "structlog", specifier = ">=25.5.0" }, - { name = "tool-call-models", specifier = "==0.1.35" }, + { name = "tool-call-models", specifier = "==0.1.40" }, ] [package.metadata.requires-dev]