iatoolkit 2.4.1__tar.gz → 2.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iatoolkit-2.4.1/src/iatoolkit.egg-info → iatoolkit-2.5.1}/PKG-INFO +2 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/pyproject.toml +1 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/requirements.txt +1 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/__init__.py +1 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/core.py +2 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +10 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +16 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/openai_adapter.py +11 -3
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +8 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_proxy.py +64 -31
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/locales/en.yaml +7 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/locales/es.yaml +7 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/configuration_service.py +66 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/llm_client_service.py +55 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/prompt_service.py +10 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/query_service.py +54 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/system_prompt_catalog.py +6 -2
- iatoolkit-2.5.1/src/iatoolkit/services/telemetry_service.py +484 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1/src/iatoolkit.egg-info}/PKG-INFO +2 -1
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit.egg-info/SOURCES.txt +20 -19
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit.egg-info/requires.txt +1 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/LICENSE +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/readme.md +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/setup.cfg +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-2.4.1/src/iatoolkit → iatoolkit-2.5.1/src/iatoolkit/config}/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/memory_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/models.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/company_context_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/context_builder_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/knowledge_base_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/memory_compiler_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/memory_lint_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/memory_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/memory_wiki_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/tool_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/system_prompts/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/chat.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.4.1 → iatoolkit-2.5.1}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iatoolkit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.1
|
|
4
4
|
Summary: IAToolkit
|
|
5
5
|
Author: Fernando Libedinsky
|
|
6
6
|
License-Expression: MIT
|
|
@@ -12,6 +12,7 @@ Requires-Dist: bcrypt==4.2.1
|
|
|
12
12
|
Requires-Dist: anthropic>=0.83.0
|
|
13
13
|
Requires-Dist: boto3==1.36.22
|
|
14
14
|
Requires-Dist: botocore==1.36.22
|
|
15
|
+
Requires-Dist: braintrust>=0.17.0
|
|
15
16
|
Requires-Dist: build==1.2.2.post1
|
|
16
17
|
Requires-Dist: click==8.1.8
|
|
17
18
|
Requires-Dist: cryptography==44.0.3
|
|
@@ -29,4 +29,4 @@ version = { attr = "iatoolkit.__version__" }
|
|
|
29
29
|
dependencies = { file = ["requirements.txt"] }
|
|
30
30
|
|
|
31
31
|
[tool.setuptools.package-data]
|
|
32
|
-
iatoolkit = ["
|
|
32
|
+
iatoolkit = ["templates/**/*", "static/**/*", "locales/*.yaml", "config/*.yaml", "config/system_prompts/*.prompt"]
|
|
@@ -402,6 +402,7 @@ class IAToolkit:
|
|
|
402
402
|
from iatoolkit.services.i18n_service import I18nService
|
|
403
403
|
from iatoolkit.services.language_service import LanguageService
|
|
404
404
|
from iatoolkit.services.configuration_service import ConfigurationService
|
|
405
|
+
from iatoolkit.services.telemetry_service import TelemetryService
|
|
405
406
|
from iatoolkit.services.embedding_service import EmbeddingService
|
|
406
407
|
from iatoolkit.services.history_manager_service import HistoryManagerService
|
|
407
408
|
from iatoolkit.services.tool_service import ToolService
|
|
@@ -443,6 +444,7 @@ class IAToolkit:
|
|
|
443
444
|
binder.bind(I18nService, to=I18nService)
|
|
444
445
|
binder.bind(LanguageService, to=LanguageService)
|
|
445
446
|
binder.bind(ConfigurationService, to=ConfigurationService)
|
|
447
|
+
binder.bind(TelemetryService, to=TelemetryService)
|
|
446
448
|
binder.bind(EmbeddingService, to=EmbeddingService)
|
|
447
449
|
binder.bind(HistoryManagerService, to=HistoryManagerService)
|
|
448
450
|
binder.bind(ToolService, to=ToolService)
|
|
@@ -33,7 +33,8 @@ class AnthropicAdapter:
|
|
|
33
33
|
images: Optional[List[Dict]] = None,
|
|
34
34
|
attachments: Optional[List[Dict]] = None,
|
|
35
35
|
store: Optional[bool] = None,
|
|
36
|
-
metadata: Optional[Dict[str, str]] = None
|
|
36
|
+
metadata: Optional[Dict[str, str]] = None,
|
|
37
|
+
telemetry_execution: Any = None) -> LLMResponse:
|
|
37
38
|
"""
|
|
38
39
|
Calls Anthropic Messages API and maps the response to common LLMResponse.
|
|
39
40
|
|
|
@@ -76,6 +77,8 @@ class AnthropicAdapter:
|
|
|
76
77
|
if tool_choice_payload:
|
|
77
78
|
params["tool_choice"] = tool_choice_payload
|
|
78
79
|
|
|
80
|
+
self._record_telemetry_input(telemetry_execution, params)
|
|
81
|
+
|
|
79
82
|
anthropic_response = self.client.messages.create(**params)
|
|
80
83
|
return self._map_anthropic_response(anthropic_response, model)
|
|
81
84
|
|
|
@@ -87,6 +90,12 @@ class AnthropicAdapter:
|
|
|
87
90
|
error_message
|
|
88
91
|
) from e
|
|
89
92
|
|
|
93
|
+
@staticmethod
|
|
94
|
+
def _record_telemetry_input(telemetry_execution: Any, payload: Dict[str, Any]) -> None:
|
|
95
|
+
record_input = getattr(telemetry_execution, "record_input", None)
|
|
96
|
+
if callable(record_input):
|
|
97
|
+
record_input(payload)
|
|
98
|
+
|
|
90
99
|
def _prepare_messages(self, input_items: List[Dict], images: List[Dict]) -> tuple[Optional[str], List[Dict]]:
|
|
91
100
|
system_parts: List[str] = []
|
|
92
101
|
messages: List[Dict] = []
|
|
@@ -53,6 +53,7 @@ class GeminiAdapter:
|
|
|
53
53
|
attachments: Optional[List[Dict]] = None,
|
|
54
54
|
store: Optional[bool] = None,
|
|
55
55
|
metadata: Optional[Dict[str, str]] = None,
|
|
56
|
+
telemetry_execution: Any = None,
|
|
56
57
|
) -> LLMResponse:
|
|
57
58
|
try:
|
|
58
59
|
_ = store
|
|
@@ -105,6 +106,15 @@ class GeminiAdapter:
|
|
|
105
106
|
else:
|
|
106
107
|
raise
|
|
107
108
|
|
|
109
|
+
self._record_telemetry_input(
|
|
110
|
+
telemetry_execution,
|
|
111
|
+
{
|
|
112
|
+
"model": model,
|
|
113
|
+
"contents": contents,
|
|
114
|
+
"config": dict(config_kwargs),
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
|
|
108
118
|
# call the new SDK
|
|
109
119
|
response = self.client.models.generate_content(
|
|
110
120
|
model=model,
|
|
@@ -144,6 +154,12 @@ class GeminiAdapter:
|
|
|
144
154
|
|
|
145
155
|
raise IAToolkitException(IAToolkitException.ErrorType.LLM_ERROR, error_message)
|
|
146
156
|
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _record_telemetry_input(telemetry_execution: Any, payload: Dict[str, Any]) -> None:
|
|
159
|
+
record_input = getattr(telemetry_execution, "record_input", None)
|
|
160
|
+
if callable(record_input):
|
|
161
|
+
record_input(payload)
|
|
162
|
+
|
|
147
163
|
def _extract_system_and_filter_input(self, input_list: List[Dict]) -> tuple[Optional[str], List[Dict]]:
|
|
148
164
|
"""Extrae el mensaje de sistema para usarlo en system_instruction."""
|
|
149
165
|
system_parts = []
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
|
-
from typing import Dict, List, Optional
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
8
|
from iatoolkit.infra.llm_response import LLMResponse, ToolCall, Usage
|
|
9
9
|
from iatoolkit.common.exceptions import IAToolkitException
|
|
10
|
-
from typing import List
|
|
11
10
|
import mimetypes
|
|
12
11
|
import re
|
|
13
12
|
import base64
|
|
@@ -31,7 +30,8 @@ class OpenAIAdapter:
|
|
|
31
30
|
images: Optional[List[Dict]] = None,
|
|
32
31
|
attachments: Optional[List[Dict]] = None,
|
|
33
32
|
store: Optional[bool] = None,
|
|
34
|
-
metadata: Optional[Dict[str, str]] = None
|
|
33
|
+
metadata: Optional[Dict[str, str]] = None,
|
|
34
|
+
telemetry_execution: Any = None) -> LLMResponse:
|
|
35
35
|
"""Llamada a la API de OpenAI y mapeo a estructura común"""
|
|
36
36
|
try:
|
|
37
37
|
# Handle multimodal input if images are present
|
|
@@ -64,6 +64,8 @@ class OpenAIAdapter:
|
|
|
64
64
|
if tool_choice_payload is not None:
|
|
65
65
|
params['tool_choice'] = tool_choice_payload
|
|
66
66
|
|
|
67
|
+
self._record_telemetry_input(telemetry_execution, params)
|
|
68
|
+
|
|
67
69
|
# Llamar a la API de OpenAI
|
|
68
70
|
openai_response = self.client.responses.create(**params)
|
|
69
71
|
|
|
@@ -76,6 +78,12 @@ class OpenAIAdapter:
|
|
|
76
78
|
|
|
77
79
|
raise IAToolkitException(IAToolkitException.ErrorType.LLM_ERROR, error_message)
|
|
78
80
|
|
|
81
|
+
@staticmethod
|
|
82
|
+
def _record_telemetry_input(telemetry_execution: Any, payload: Dict[str, Any]) -> None:
|
|
83
|
+
record_input = getattr(telemetry_execution, "record_input", None)
|
|
84
|
+
if callable(record_input):
|
|
85
|
+
record_input(payload)
|
|
86
|
+
|
|
79
87
|
@staticmethod
|
|
80
88
|
def _map_tool_choice(tool_choice: str, tools_payload: List[Dict]) -> Optional[Dict | str]:
|
|
81
89
|
if tool_choice in ("", None, "auto"):
|
|
@@ -48,6 +48,7 @@ class OpenAICompatibleChatAdapter:
|
|
|
48
48
|
text = kwargs.get("text") or {}
|
|
49
49
|
reasoning = kwargs.get("reasoning")
|
|
50
50
|
metadata = kwargs.get("metadata")
|
|
51
|
+
telemetry_execution = kwargs.get("telemetry_execution")
|
|
51
52
|
|
|
52
53
|
try:
|
|
53
54
|
messages: List[Dict[str, Any]] = []
|
|
@@ -111,6 +112,7 @@ class OpenAICompatibleChatAdapter:
|
|
|
111
112
|
call_kwargs["parallel_tool_calls"] = bool(kwargs.get("parallel_tool_calls"))
|
|
112
113
|
|
|
113
114
|
self._extend_call_kwargs(call_kwargs, kwargs)
|
|
115
|
+
self._record_telemetry_input(telemetry_execution, call_kwargs)
|
|
114
116
|
|
|
115
117
|
logging.debug(
|
|
116
118
|
"[%sAdapter] Calling chat.completions API with %s messages.",
|
|
@@ -130,6 +132,12 @@ class OpenAICompatibleChatAdapter:
|
|
|
130
132
|
f"{self.provider_label} error: {ex}"
|
|
131
133
|
) from ex
|
|
132
134
|
|
|
135
|
+
@staticmethod
|
|
136
|
+
def _record_telemetry_input(telemetry_execution: Any, payload: Dict[str, Any]) -> None:
|
|
137
|
+
record_input = getattr(telemetry_execution, "record_input", None)
|
|
138
|
+
if callable(record_input):
|
|
139
|
+
record_input(payload)
|
|
140
|
+
|
|
133
141
|
def _extend_call_kwargs(self, call_kwargs: Dict[str, Any], kwargs: Dict[str, Any]) -> None:
|
|
134
142
|
_ = call_kwargs
|
|
135
143
|
_ = kwargs
|
|
@@ -17,6 +17,7 @@ from iatoolkit.infra.llm_response import LLMResponse
|
|
|
17
17
|
from iatoolkit.common.model_registry import ModelRegistry
|
|
18
18
|
from iatoolkit.common.interfaces.secret_provider import SecretProvider
|
|
19
19
|
from iatoolkit.common.secret_resolver import resolve_secret
|
|
20
|
+
from iatoolkit.services.telemetry_service import NoopTelemetryService
|
|
20
21
|
|
|
21
22
|
from openai import OpenAI, Timeout # For OpenAI and xAI (OpenAI-compatible)
|
|
22
23
|
|
|
@@ -53,6 +54,7 @@ class LLMProxy:
|
|
|
53
54
|
configuration_service: ConfigurationService,
|
|
54
55
|
model_registry: ModelRegistry,
|
|
55
56
|
secret_provider: SecretProvider,
|
|
57
|
+
telemetry_service=None,
|
|
56
58
|
):
|
|
57
59
|
"""
|
|
58
60
|
Init a new instance of the proxy. It can be a base factory or a working instance with configured clients.
|
|
@@ -62,10 +64,23 @@ class LLMProxy:
|
|
|
62
64
|
self.configuration_service = configuration_service
|
|
63
65
|
self.model_registry = model_registry
|
|
64
66
|
self.secret_provider = secret_provider
|
|
67
|
+
self._telemetry_service = telemetry_service
|
|
65
68
|
|
|
66
69
|
# adapter cache by (provider, api_key, base_url)
|
|
67
70
|
self.adapters: Dict[Tuple[Any, ...], Any] = {}
|
|
68
71
|
|
|
72
|
+
@property
|
|
73
|
+
def telemetry_service(self):
|
|
74
|
+
if self._telemetry_service is None:
|
|
75
|
+
try:
|
|
76
|
+
from iatoolkit import current_iatoolkit
|
|
77
|
+
from iatoolkit.services.telemetry_service import TelemetryService
|
|
78
|
+
|
|
79
|
+
self._telemetry_service = current_iatoolkit().get_injector().get(TelemetryService)
|
|
80
|
+
except Exception:
|
|
81
|
+
self._telemetry_service = NoopTelemetryService()
|
|
82
|
+
return self._telemetry_service
|
|
83
|
+
|
|
69
84
|
# -------------------------------------------------------------------------
|
|
70
85
|
# Public API
|
|
71
86
|
# -------------------------------------------------------------------------
|
|
@@ -81,6 +96,9 @@ class LLMProxy:
|
|
|
81
96
|
"company_short_name is required in kwargs to resolve LLM credentials."
|
|
82
97
|
)
|
|
83
98
|
|
|
99
|
+
telemetry_request = kwargs.pop("telemetry_request", None)
|
|
100
|
+
telemetry_execution = kwargs.pop("telemetry_execution", None)
|
|
101
|
+
|
|
84
102
|
# Determine the provider based on the model name
|
|
85
103
|
provider = self._resolve_provider_for_company_model(
|
|
86
104
|
company_short_name=company_short_name,
|
|
@@ -92,6 +110,7 @@ class LLMProxy:
|
|
|
92
110
|
adapter = self._get_or_create_adapter(
|
|
93
111
|
provider=provider,
|
|
94
112
|
company_short_name=company_short_name,
|
|
113
|
+
telemetry_request=telemetry_request,
|
|
95
114
|
)
|
|
96
115
|
|
|
97
116
|
request_kwargs = self._apply_provider_request_overrides(
|
|
@@ -104,6 +123,8 @@ class LLMProxy:
|
|
|
104
123
|
model_config=model_config,
|
|
105
124
|
request_kwargs=request_kwargs,
|
|
106
125
|
)
|
|
126
|
+
if telemetry_execution is not None:
|
|
127
|
+
request_kwargs["telemetry_execution"] = telemetry_execution
|
|
107
128
|
|
|
108
129
|
# Delegate to the adapter (OpenAI, Gemini, DeepSeek, xAI, Anthropic, etc.)
|
|
109
130
|
return adapter.create_response(model=model, input=input, **request_kwargs)
|
|
@@ -146,7 +167,12 @@ class LLMProxy:
|
|
|
146
167
|
# Adapter management
|
|
147
168
|
# -------------------------------------------------------------------------
|
|
148
169
|
|
|
149
|
-
def _get_or_create_adapter(
|
|
170
|
+
def _get_or_create_adapter(
|
|
171
|
+
self,
|
|
172
|
+
provider: str,
|
|
173
|
+
company_short_name: str,
|
|
174
|
+
telemetry_request: Dict[str, Any] | None = None,
|
|
175
|
+
) -> Any:
|
|
150
176
|
"""
|
|
151
177
|
Return an adapter instance for the given provider.
|
|
152
178
|
If none exists yet, create it using a cached or new low-level client.
|
|
@@ -158,6 +184,24 @@ class LLMProxy:
|
|
|
158
184
|
connect_timeout_seconds = client_config["connect_timeout_seconds"]
|
|
159
185
|
read_timeout_seconds = client_config["read_timeout_seconds"]
|
|
160
186
|
max_retries = client_config["max_retries"]
|
|
187
|
+
client = self._get_or_create_client(
|
|
188
|
+
provider,
|
|
189
|
+
api_key,
|
|
190
|
+
base_url=base_url,
|
|
191
|
+
default_headers=default_headers,
|
|
192
|
+
connect_timeout_seconds=connect_timeout_seconds,
|
|
193
|
+
read_timeout_seconds=read_timeout_seconds,
|
|
194
|
+
max_retries=max_retries,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
wrapped_client = self.telemetry_service.wrap_client_for_request(
|
|
198
|
+
llm_provider=provider,
|
|
199
|
+
client=client,
|
|
200
|
+
request=telemetry_request,
|
|
201
|
+
)
|
|
202
|
+
if wrapped_client is not client:
|
|
203
|
+
return self._build_adapter(provider, wrapped_client)
|
|
204
|
+
|
|
161
205
|
adapter_cache_key = (
|
|
162
206
|
provider,
|
|
163
207
|
api_key or "",
|
|
@@ -168,42 +212,31 @@ class LLMProxy:
|
|
|
168
212
|
max_retries,
|
|
169
213
|
)
|
|
170
214
|
|
|
171
|
-
# If already created for this provider+key, just return it
|
|
172
215
|
if adapter_cache_key in self.adapters and self.adapters[adapter_cache_key] is not None:
|
|
173
216
|
return self.adapters[adapter_cache_key]
|
|
174
217
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
api_key,
|
|
179
|
-
base_url=base_url,
|
|
180
|
-
default_headers=default_headers,
|
|
181
|
-
connect_timeout_seconds=connect_timeout_seconds,
|
|
182
|
-
read_timeout_seconds=read_timeout_seconds,
|
|
183
|
-
max_retries=max_retries,
|
|
184
|
-
)
|
|
218
|
+
adapter = self._build_adapter(provider, client)
|
|
219
|
+
self.adapters[adapter_cache_key] = adapter
|
|
220
|
+
return adapter
|
|
185
221
|
|
|
186
|
-
|
|
222
|
+
def _build_adapter(self, provider: str, client: Any) -> Any:
|
|
187
223
|
if provider == self.PROVIDER_OPENAI:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
else:
|
|
200
|
-
raise IAToolkitException(
|
|
201
|
-
IAToolkitException.ErrorType.MODEL,
|
|
202
|
-
f"Provider not supported in _get_or_create_adapter: {provider}"
|
|
203
|
-
)
|
|
224
|
+
return OpenAIAdapter(client)
|
|
225
|
+
if provider == self.PROVIDER_GEMINI:
|
|
226
|
+
return GeminiAdapter(client)
|
|
227
|
+
if provider == self.PROVIDER_DEEPSEEK:
|
|
228
|
+
return DeepseekAdapter(client)
|
|
229
|
+
if provider == self.PROVIDER_OPENAI_COMPATIBLE:
|
|
230
|
+
return OpenAICompatibleChatAdapter(client, provider_label="OpenAI-compatible")
|
|
231
|
+
if provider == self.PROVIDER_OPENROUTER:
|
|
232
|
+
return OpenRouterAdapter(client)
|
|
233
|
+
if provider == self.PROVIDER_ANTHROPIC:
|
|
234
|
+
return AnthropicAdapter(client)
|
|
204
235
|
|
|
205
|
-
|
|
206
|
-
|
|
236
|
+
raise IAToolkitException(
|
|
237
|
+
IAToolkitException.ErrorType.MODEL,
|
|
238
|
+
f"Provider not supported in _get_or_create_adapter: {provider}"
|
|
239
|
+
)
|
|
207
240
|
|
|
208
241
|
def _apply_provider_request_overrides(
|
|
209
242
|
self,
|
|
@@ -69,6 +69,11 @@ ui:
|
|
|
69
69
|
primary_input: "Primary Input"
|
|
70
70
|
prompt_args: "Prompt Arguments (Client Data)"
|
|
71
71
|
llm_output: "LLM Output (Raw JSON)"
|
|
72
|
+
telemetry_label: "Telemetry"
|
|
73
|
+
telemetry_open_trace: "Open Trace"
|
|
74
|
+
telemetry_not_recorded: "Not recorded"
|
|
75
|
+
telemetry_disabled: "Disabled"
|
|
76
|
+
telemetry_unknown_provider: "unknown provider"
|
|
72
77
|
|
|
73
78
|
login_widget:
|
|
74
79
|
title: "Sign In"
|
|
@@ -1041,6 +1046,8 @@ ui:
|
|
|
1041
1046
|
store_response_default: "Provider default"
|
|
1042
1047
|
store_response_true: "Yes"
|
|
1043
1048
|
store_response_false: "No"
|
|
1049
|
+
telemetry_enabled_label: "LLM Telemetry"
|
|
1050
|
+
telemetry_enabled_help: "Send this agent's LLM runs to the company telemetry backend when telemetry is enabled in company configuration."
|
|
1044
1051
|
tools_title: "Tool Selection"
|
|
1045
1052
|
tools_mode_label: "Tools Mode"
|
|
1046
1053
|
tools_mode_inherit: "Automatic"
|
|
@@ -70,6 +70,11 @@ ui:
|
|
|
70
70
|
primary_input: "Entrada Principal"
|
|
71
71
|
prompt_args: "Argumentos del Prompt (Client Data)"
|
|
72
72
|
llm_output: "Salida LLM (JSON Crudo)"
|
|
73
|
+
telemetry_label: "Telemetría"
|
|
74
|
+
telemetry_open_trace: "Abrir traza"
|
|
75
|
+
telemetry_not_recorded: "No registrada"
|
|
76
|
+
telemetry_disabled: "Deshabilitada"
|
|
77
|
+
telemetry_unknown_provider: "provider desconocido"
|
|
73
78
|
|
|
74
79
|
|
|
75
80
|
login_widget:
|
|
@@ -1044,6 +1049,8 @@ ui:
|
|
|
1044
1049
|
store_response_default: "Por defecto del provider"
|
|
1045
1050
|
store_response_true: "Sí"
|
|
1046
1051
|
store_response_false: "No"
|
|
1052
|
+
telemetry_enabled_label: "Telemetría LLM"
|
|
1053
|
+
telemetry_enabled_help: "Envía las ejecuciones LLM de este agente al backend de telemetría de la empresa cuando la telemetría esté habilitada en la configuración de la compañía."
|
|
1047
1054
|
tools_title: "Selección de Tools"
|
|
1048
1055
|
tools_mode_label: "Modo de Tools"
|
|
1049
1056
|
tools_mode_inherit: "Automático"
|
|
@@ -521,6 +521,56 @@ class ConfigurationService:
|
|
|
521
521
|
if raw_x_title is not None and (not isinstance(raw_x_title, str) or not raw_x_title.strip()):
|
|
522
522
|
add_error("llm.openrouter.x_title", "Must be a non-empty string.")
|
|
523
523
|
|
|
524
|
+
telemetry_cfg = config.get("llm", {}).get("telemetry")
|
|
525
|
+
if telemetry_cfg is not None:
|
|
526
|
+
if not isinstance(telemetry_cfg, dict):
|
|
527
|
+
add_error("llm.telemetry", "Must be a dictionary.")
|
|
528
|
+
else:
|
|
529
|
+
telemetry_enabled = telemetry_cfg.get("enabled", False)
|
|
530
|
+
if not isinstance(telemetry_enabled, bool):
|
|
531
|
+
add_error("llm.telemetry.enabled", "Must be a boolean.")
|
|
532
|
+
|
|
533
|
+
telemetry_provider = telemetry_cfg.get("provider")
|
|
534
|
+
normalized_telemetry_provider = ""
|
|
535
|
+
if telemetry_provider is not None:
|
|
536
|
+
if not isinstance(telemetry_provider, str) or not telemetry_provider.strip():
|
|
537
|
+
add_error("llm.telemetry.provider", "Must be a non-empty string.")
|
|
538
|
+
else:
|
|
539
|
+
normalized_telemetry_provider = telemetry_provider.strip().lower()
|
|
540
|
+
if normalized_telemetry_provider not in {"braintrust"}:
|
|
541
|
+
add_error(
|
|
542
|
+
"llm.telemetry.provider",
|
|
543
|
+
"Unsupported provider. Must be 'braintrust'.",
|
|
544
|
+
)
|
|
545
|
+
elif telemetry_enabled:
|
|
546
|
+
add_error("llm.telemetry.provider", "Missing required key: 'provider'.")
|
|
547
|
+
|
|
548
|
+
if normalized_telemetry_provider == "braintrust":
|
|
549
|
+
braintrust_cfg = telemetry_cfg.get("braintrust")
|
|
550
|
+
if not isinstance(braintrust_cfg, dict):
|
|
551
|
+
add_error("llm.telemetry.braintrust", "Must be a dictionary.")
|
|
552
|
+
else:
|
|
553
|
+
if telemetry_enabled:
|
|
554
|
+
project = braintrust_cfg.get("project")
|
|
555
|
+
if not isinstance(project, str) or not project.strip():
|
|
556
|
+
add_error("llm.telemetry.braintrust.project", "Must be a non-empty string.")
|
|
557
|
+
|
|
558
|
+
api_key = braintrust_cfg.get("api_key")
|
|
559
|
+
if not isinstance(api_key, str) or not api_key.strip():
|
|
560
|
+
add_error("llm.telemetry.braintrust.api_key", "Must be a non-empty string.")
|
|
561
|
+
|
|
562
|
+
api_url = braintrust_cfg.get("api_url")
|
|
563
|
+
if api_url is not None:
|
|
564
|
+
if not isinstance(api_url, str) or not api_url.strip():
|
|
565
|
+
add_error("llm.telemetry.braintrust.api_url", "Must be a non-empty string.")
|
|
566
|
+
else:
|
|
567
|
+
parsed = urlparse(api_url.strip())
|
|
568
|
+
if parsed.scheme.lower() not in {"http", "https"} or not parsed.netloc:
|
|
569
|
+
add_error(
|
|
570
|
+
"llm.telemetry.braintrust.api_url",
|
|
571
|
+
"Must be an absolute HTTP or HTTPS URL.",
|
|
572
|
+
)
|
|
573
|
+
|
|
524
574
|
# 3. Embedding Provider
|
|
525
575
|
if isinstance(config.get("embedding_provider"), dict):
|
|
526
576
|
if not config.get("embedding_provider", {}).get("provider"):
|
|
@@ -678,6 +728,7 @@ class ConfigurationService:
|
|
|
678
728
|
"text_verbosity",
|
|
679
729
|
"prompt_version",
|
|
680
730
|
"prompt_variant",
|
|
731
|
+
"telemetry_enabled",
|
|
681
732
|
}
|
|
682
733
|
unknown_option_keys = sorted(
|
|
683
734
|
key for key in llm_request_options.keys() if key not in allowed_option_keys
|
|
@@ -724,6 +775,15 @@ class ConfigurationService:
|
|
|
724
775
|
"Must be a non-empty string.",
|
|
725
776
|
)
|
|
726
777
|
|
|
778
|
+
if "telemetry_enabled" in llm_request_options and not isinstance(
|
|
779
|
+
llm_request_options.get("telemetry_enabled"),
|
|
780
|
+
bool,
|
|
781
|
+
):
|
|
782
|
+
add_error(
|
|
783
|
+
f"prompts[{i}].llm_request_options.telemetry_enabled",
|
|
784
|
+
"Must be a boolean.",
|
|
785
|
+
)
|
|
786
|
+
|
|
727
787
|
tool_policy = prompt.get("tool_policy")
|
|
728
788
|
if tool_policy is not None:
|
|
729
789
|
if not isinstance(tool_policy, dict):
|
|
@@ -1110,6 +1170,12 @@ class ConfigurationService:
|
|
|
1110
1170
|
provider_cfg = providers_cfg.get(candidate)
|
|
1111
1171
|
return dict(provider_cfg) if isinstance(provider_cfg, dict) else {}
|
|
1112
1172
|
|
|
1173
|
+
def get_llm_telemetry_config(self, company_short_name: str) -> dict:
|
|
1174
|
+
self._ensure_config_loaded(company_short_name)
|
|
1175
|
+
llm_config = self._loaded_configs[company_short_name].get("llm") or {}
|
|
1176
|
+
telemetry_cfg = llm_config.get("telemetry")
|
|
1177
|
+
return dict(telemetry_cfg) if isinstance(telemetry_cfg, dict) else {}
|
|
1178
|
+
|
|
1113
1179
|
|
|
1114
1180
|
def _load_and_merge_configs(self, company_short_name: str) -> dict:
|
|
1115
1181
|
"""
|
|
@@ -23,6 +23,7 @@ from typing import Dict, Optional, List, Any
|
|
|
23
23
|
from iatoolkit.services.dispatcher_service import Dispatcher
|
|
24
24
|
from iatoolkit.services.storage_service import StorageService
|
|
25
25
|
from iatoolkit.services.structured_output_service import StructuredOutputService
|
|
26
|
+
from iatoolkit.services.telemetry_service import NoopTelemetryService
|
|
26
27
|
|
|
27
28
|
CONTEXT_ERROR_MESSAGE = 'Tu consulta supera el límite de contexto, utiliza el boton de recarga de contexto.'
|
|
28
29
|
|
|
@@ -36,7 +37,8 @@ class llmClient:
|
|
|
36
37
|
llm_proxy: LLMProxy,
|
|
37
38
|
model_registry: ModelRegistry,
|
|
38
39
|
storage_service: StorageService,
|
|
39
|
-
util: Utility
|
|
40
|
+
util: Utility,
|
|
41
|
+
telemetry_service=None,
|
|
40
42
|
):
|
|
41
43
|
self.llmquery_repo = llmquery_repo
|
|
42
44
|
self.llm_proxy = llm_proxy
|
|
@@ -44,6 +46,7 @@ class llmClient:
|
|
|
44
46
|
self.storage_service = storage_service
|
|
45
47
|
self.util = util
|
|
46
48
|
self._dispatcher = None # Cache for the lazy-loaded dispatcher
|
|
49
|
+
self._telemetry_service = telemetry_service
|
|
47
50
|
|
|
48
51
|
# Lazy init to avoid network/bootstrap failures during app startup.
|
|
49
52
|
self.encoding = None
|
|
@@ -62,6 +65,18 @@ class llmClient:
|
|
|
62
65
|
self._dispatcher = current_iatoolkit().get_injector().get(Dispatcher)
|
|
63
66
|
return self._dispatcher
|
|
64
67
|
|
|
68
|
+
@property
|
|
69
|
+
def telemetry_service(self):
|
|
70
|
+
if self._telemetry_service is None:
|
|
71
|
+
try:
|
|
72
|
+
from iatoolkit import current_iatoolkit
|
|
73
|
+
from iatoolkit.services.telemetry_service import TelemetryService
|
|
74
|
+
|
|
75
|
+
self._telemetry_service = current_iatoolkit().get_injector().get(TelemetryService)
|
|
76
|
+
except Exception:
|
|
77
|
+
self._telemetry_service = NoopTelemetryService()
|
|
78
|
+
return self._telemetry_service
|
|
79
|
+
|
|
65
80
|
|
|
66
81
|
def invoke(self,
|
|
67
82
|
company: Company,
|
|
@@ -81,6 +96,7 @@ class llmClient:
|
|
|
81
96
|
task_id: Optional[int] = None,
|
|
82
97
|
execution_metadata: Optional[Dict[str, Any]] = None,
|
|
83
98
|
request_metadata: Optional[Dict[str, str]] = None,
|
|
99
|
+
telemetry_request: Optional[Dict[str, Any]] = None,
|
|
84
100
|
response_contract: Optional[Dict[str, Any]] = None
|
|
85
101
|
) -> dict:
|
|
86
102
|
|
|
@@ -102,6 +118,7 @@ class llmClient:
|
|
|
102
118
|
)
|
|
103
119
|
text_payload = request_params["text"]
|
|
104
120
|
reasoning_payload = request_params["reasoning"]
|
|
121
|
+
telemetry_execution = self.telemetry_service.start_execution(telemetry_request)
|
|
105
122
|
|
|
106
123
|
try:
|
|
107
124
|
start_time = time.time()
|
|
@@ -138,6 +155,8 @@ class llmClient:
|
|
|
138
155
|
attachments=active_attachments,
|
|
139
156
|
store=store,
|
|
140
157
|
metadata=request_metadata,
|
|
158
|
+
telemetry_request=telemetry_request,
|
|
159
|
+
telemetry_execution=telemetry_execution,
|
|
141
160
|
)
|
|
142
161
|
stats = self.get_stats(response)
|
|
143
162
|
|
|
@@ -246,6 +265,8 @@ class llmClient:
|
|
|
246
265
|
attachments=active_attachments,
|
|
247
266
|
store=store,
|
|
248
267
|
metadata=request_metadata,
|
|
268
|
+
telemetry_request=telemetry_request,
|
|
269
|
+
telemetry_execution=telemetry_execution,
|
|
249
270
|
)
|
|
250
271
|
stats_fcall = self.add_stats(stats_fcall, self.get_stats(response))
|
|
251
272
|
|
|
@@ -285,6 +306,22 @@ class llmClient:
|
|
|
285
306
|
answer_time=stats['response_time']
|
|
286
307
|
)
|
|
287
308
|
self.llmquery_repo.add_query(query)
|
|
309
|
+
telemetry_execution.finalize(
|
|
310
|
+
query_id=query.id,
|
|
311
|
+
success=decoded_response.get('status', False),
|
|
312
|
+
answer_preview=decoded_response.get('answer', ''),
|
|
313
|
+
metrics={
|
|
314
|
+
"total_tokens": combined_stats.get("total_tokens"),
|
|
315
|
+
"response_time": combined_stats.get("response_time"),
|
|
316
|
+
"sql_retry_count": combined_stats.get("sql_retry_count"),
|
|
317
|
+
},
|
|
318
|
+
)
|
|
319
|
+
telemetry_stats = telemetry_execution.build_stats()
|
|
320
|
+
if telemetry_stats:
|
|
321
|
+
query.stats = dict(query.stats or {})
|
|
322
|
+
query.stats["telemetry"] = telemetry_stats
|
|
323
|
+
self.llmquery_repo.commit()
|
|
324
|
+
combined_stats = dict(query.stats or {})
|
|
288
325
|
logging.info(f"finish llm call in {int(time.time() - start_time)} secs..")
|
|
289
326
|
if function_calls:
|
|
290
327
|
logging.info(f"time within the function calls {f_call_time:.1f} secs.")
|
|
@@ -312,9 +349,17 @@ class llmClient:
|
|
|
312
349
|
except SQLAlchemyError as db_error:
|
|
313
350
|
# rollback
|
|
314
351
|
self.llmquery_repo.session.rollback()
|
|
352
|
+
telemetry_execution.finalize(
|
|
353
|
+
success=False,
|
|
354
|
+
error_message=str(db_error),
|
|
355
|
+
)
|
|
315
356
|
logging.error(f"Error de base de datos: {str(db_error)}")
|
|
316
357
|
raise db_error
|
|
317
358
|
except OperationalError as e:
|
|
359
|
+
telemetry_execution.finalize(
|
|
360
|
+
success=False,
|
|
361
|
+
error_message=str(e),
|
|
362
|
+
)
|
|
318
363
|
logging.error(f"Operational error: {str(e)}")
|
|
319
364
|
raise e
|
|
320
365
|
except Exception as e:
|
|
@@ -331,6 +376,15 @@ class llmClient:
|
|
|
331
376
|
function_calls=f_calls,
|
|
332
377
|
)
|
|
333
378
|
self.llmquery_repo.add_query(query)
|
|
379
|
+
telemetry_execution.finalize(
|
|
380
|
+
query_id=query.id,
|
|
381
|
+
success=False,
|
|
382
|
+
error_message=error_message,
|
|
383
|
+
)
|
|
384
|
+
telemetry_stats = telemetry_execution.build_stats()
|
|
385
|
+
if telemetry_stats:
|
|
386
|
+
query.stats = {"telemetry": telemetry_stats}
|
|
387
|
+
self.llmquery_repo.commit()
|
|
334
388
|
|
|
335
389
|
# in case of context error
|
|
336
390
|
if "context_length_exceeded" in str(e):
|
|
@@ -345,6 +345,7 @@ class PromptService:
|
|
|
345
345
|
"text_verbosity",
|
|
346
346
|
"prompt_version",
|
|
347
347
|
"prompt_variant",
|
|
348
|
+
"telemetry_enabled",
|
|
348
349
|
}
|
|
349
350
|
unknown_keys = sorted(
|
|
350
351
|
key for key in llm_request_options.keys() if key not in allowed_keys
|
|
@@ -422,6 +423,15 @@ class PromptService:
|
|
|
422
423
|
)
|
|
423
424
|
normalized_options["prompt_variant"] = candidate_prompt_variant
|
|
424
425
|
|
|
426
|
+
raw_telemetry_enabled = llm_request_options.get("telemetry_enabled")
|
|
427
|
+
if raw_telemetry_enabled is not None:
|
|
428
|
+
if not isinstance(raw_telemetry_enabled, bool):
|
|
429
|
+
raise IAToolkitException(
|
|
430
|
+
IAToolkitException.ErrorType.INVALID_PARAMETER,
|
|
431
|
+
"llm_request_options.telemetry_enabled must be a boolean.",
|
|
432
|
+
)
|
|
433
|
+
normalized_options["telemetry_enabled"] = raw_telemetry_enabled
|
|
434
|
+
|
|
425
435
|
return normalized_options
|
|
426
436
|
|
|
427
437
|
def get_prompts(self, company_short_name: str, include_all: bool = False) -> dict:
|