iatoolkit 2.29.0__tar.gz → 2.30.0__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.
Files changed (250) hide show
  1. {iatoolkit-2.29.0/src/iatoolkit.egg-info → iatoolkit-2.30.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/core.py +14 -0
  4. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/vs_repo.py +3 -1
  5. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/configuration_service.py +17 -0
  6. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/inference_service.py +64 -6
  7. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/knowledge_base_service.py +4 -1
  8. iatoolkit-2.30.0/src/iatoolkit/services/warmup_service.py +196 -0
  9. {iatoolkit-2.29.0 → iatoolkit-2.30.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  10. iatoolkit-2.29.0/src/iatoolkit/services/warmup_service.py +0 -108
  11. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/LICENSE +0 -0
  12. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/LICENSE_COMMUNITY.md +0 -0
  13. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/pyproject.toml +0 -0
  14. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/readme.md +0 -0
  15. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/requirements.txt +0 -0
  16. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/setup.cfg +0 -0
  17. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/base_company.py +0 -0
  18. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/cli_commands.py +0 -0
  19. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/__init__.py +0 -0
  20. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/exceptions.py +0 -0
  21. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  22. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  23. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  24. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  25. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
  26. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  27. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  28. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  29. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/model_registry.py +0 -0
  30. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/routes.py +0 -0
  31. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  32. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/session_manager.py +0 -0
  33. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/common/util.py +0 -0
  34. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/company_registry.py +0 -0
  35. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/__init__.py +0 -0
  36. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  37. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  38. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  39. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  40. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  41. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  42. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  43. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  44. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  45. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  46. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  47. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  48. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  49. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  50. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  51. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  52. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  53. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  54. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  55. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  56. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  57. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  58. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  59. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  60. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  61. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  62. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  63. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  64. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  65. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/__init__.py +0 -0
  66. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  67. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/call_service.py +0 -0
  68. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  69. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  70. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  71. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  72. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  73. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  74. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  75. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  76. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  77. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  78. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  79. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  80. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  81. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  82. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  83. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  84. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  85. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  86. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  87. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  88. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  89. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/llm_response.py +0 -0
  90. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  91. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/locales/en.yaml +0 -0
  92. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/locales/es.yaml +0 -0
  93. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/__init__.py +0 -0
  94. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  95. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  96. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  97. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  98. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  99. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  100. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  101. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  102. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  103. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/models.py +0 -0
  104. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  105. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  106. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  107. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  108. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/runtime_logging.py +0 -0
  109. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/__init__.py +0 -0
  110. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/api_key_service.py +0 -0
  111. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  112. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/auth_service.py +0 -0
  113. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  114. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/branding_service.py +0 -0
  115. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/company_context_service.py +0 -0
  116. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/context_builder_service.py +0 -0
  117. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  118. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/embedding_service.py +0 -0
  119. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/excel_service.py +0 -0
  120. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  121. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  122. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  123. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/i18n_service.py +0 -0
  124. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/jwt_service.py +0 -0
  125. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/language_service.py +0 -0
  126. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/license_service.py +0 -0
  127. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/llm_client_service.py +0 -0
  128. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/mail_service.py +0 -0
  129. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  130. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
  131. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  132. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
  133. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  134. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/memory_service.py +0 -0
  135. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  136. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  137. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
  138. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  139. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  140. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  141. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  142. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  143. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  144. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  145. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  146. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  147. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  148. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  149. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/pdf_service.py +0 -0
  150. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/profile_service.py +0 -0
  151. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  152. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/prompt_service.py +0 -0
  153. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/query_service.py +0 -0
  154. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  155. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  156. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/sql_service.py +0 -0
  157. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  158. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/storage_service.py +0 -0
  159. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  160. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  161. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/system_tools.py +0 -0
  162. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/telemetry_service.py +0 -0
  163. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  164. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/tool_output_contract.py +0 -0
  165. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/tool_service.py +0 -0
  166. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  167. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  168. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  169. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  170. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  171. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  172. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  173. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  174. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/services/web_search_service.py +0 -0
  175. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  176. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  177. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  178. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  179. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  180. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  181. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  182. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  183. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  184. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  185. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  186. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  187. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  188. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  189. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  190. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  191. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  192. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/documents.css +0 -0
  193. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  194. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  195. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  196. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/_company_header.html +0 -0
  197. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  198. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/account.html +0 -0
  199. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/base.html +0 -0
  200. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/change_password.html +0 -0
  201. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/chat.html +0 -0
  202. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  203. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  204. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/error.html +0 -0
  205. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  206. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  207. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  208. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  209. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  210. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  211. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  212. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  213. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/templates/signup.html +0 -0
  214. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/__init__.py +0 -0
  215. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/account_view.py +0 -0
  216. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  217. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/base_login_view.py +0 -0
  218. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  219. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/change_password_view.py +0 -0
  220. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  221. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/chat_view.py +0 -0
  222. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  223. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  224. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  225. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  226. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  227. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/history_api_view.py +0 -0
  228. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/home_view.py +0 -0
  229. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  230. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  231. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  232. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/login_view.py +0 -0
  233. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  234. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  235. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  236. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  237. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  238. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  239. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  240. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  241. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/signup_view.py +0 -0
  242. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/static_page_view.py +0 -0
  243. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  244. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  245. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/users_api_view.py +0 -0
  246. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  247. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  248. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  249. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  250. {iatoolkit-2.29.0 → iatoolkit-2.30.0}/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.29.0
3
+ Version: 2.30.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "2.29.0"
6
+ __version__ = "2.30.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -115,6 +115,7 @@ class IAToolkit:
115
115
  self._setup_request_globals()
116
116
  self._setup_context_processors()
117
117
  self._sync_system_tools_on_boot()
118
+ self._run_configured_startup_warmup()
118
119
 
119
120
  # register data sources
120
121
  if start:
@@ -149,6 +150,19 @@ class IAToolkit:
149
150
  except Exception as exc:
150
151
  logging.warning("⚠️ Unable to sync system tools on boot: %s", exc)
151
152
 
153
+ def _run_configured_startup_warmup(self):
154
+ from iatoolkit.services.warmup_service import WarmupService
155
+
156
+ try:
157
+ warmup_service = self._injector.get(WarmupService)
158
+ warmed_companies = warmup_service.warmup_startup_configured_companies(trigger="core_startup")
159
+ if warmed_companies:
160
+ logging.info("🔥 Startup warm-up completed for companies=%s", warmed_companies)
161
+ else:
162
+ logging.info("🔥 Startup warm-up skipped: no embedding provider enabled warmup_on_startup.")
163
+ except Exception:
164
+ logging.exception("⚠️ Startup warm-up failed.")
165
+
152
166
  def _get_config_value(self, key: str, default=None):
153
167
  # get a value from the config dict or the environment variable
154
168
  return self.config.get(key, os.getenv(key, default))
@@ -86,6 +86,7 @@ class VSRepo:
86
86
  n_results=5,
87
87
  metadata_filter=None,
88
88
  collection_ids: List[int] | None = None,
89
+ include_urls: bool = True,
89
90
  ) -> list[Dict]:
90
91
  """
91
92
  search documents similar to the query for a company
@@ -95,6 +96,7 @@ class VSRepo:
95
96
  query_text: query text
96
97
  n_results: max number of results to return
97
98
  metadata_filter: (e.g., {"document_type": "certificate"})
99
+ include_urls: Generate storage URLs for returned chunks when true.
98
100
 
99
101
  Returns:
100
102
  list of documents matching the query and filters
@@ -185,7 +187,7 @@ class VSRepo:
185
187
  # get the url of the document
186
188
  storage_key = row[3] if len(row) > 3 and row[3] is not None else None
187
189
  url = None
188
- if storage_key:
190
+ if include_urls and storage_key:
189
191
  url = self.storage_service.generate_presigned_url(company_short_name, storage_key)
190
192
 
191
193
  vs_documents.append(
@@ -717,6 +717,23 @@ class ConfigurationService:
717
717
  add_error("embedding_provider", "Missing required key: 'provider'")
718
718
  if not config.get("embedding_provider", {}).get("model"):
719
719
  add_error("embedding_provider", "Missing required key: 'model'")
720
+ if (
721
+ "warmup_on_startup" in config.get("embedding_provider", {})
722
+ and not isinstance(config.get("embedding_provider", {}).get("warmup_on_startup"), bool)
723
+ ):
724
+ add_error("embedding_provider.warmup_on_startup", "Must be a boolean.")
725
+
726
+ embedding_providers_cfg = config.get("embedding_providers")
727
+ if embedding_providers_cfg is not None:
728
+ if not isinstance(embedding_providers_cfg, dict):
729
+ add_error("embedding_providers", "Section must be a dictionary.")
730
+ else:
731
+ for provider_key, provider_cfg in embedding_providers_cfg.items():
732
+ if not isinstance(provider_cfg, dict):
733
+ add_error(f"embedding_providers.{provider_key}", "Provider configuration must be a dictionary.")
734
+ continue
735
+ if "warmup_on_startup" in provider_cfg and not isinstance(provider_cfg.get("warmup_on_startup"), bool):
736
+ add_error(f"embedding_providers.{provider_key}.warmup_on_startup", "Must be a boolean.")
720
737
 
721
738
  # 3b. Visual Embedding Provider (Optional)
722
739
  if config.get("visual_embedding_provider"):
@@ -25,9 +25,12 @@ class InferenceService:
25
25
 
26
26
  DEFAULT_CONNECT_TIMEOUT_SECONDS = 5.0
27
27
  DEFAULT_READ_TIMEOUT_SECONDS = 300.0
28
+ DEFAULT_RETRY_BUDGET_SECONDS = 30.0
28
29
  DEFAULT_RETRY_INITIAL_DELAY_SECONDS = 5.0
29
30
  DEFAULT_RETRY_MAX_DELAY_SECONDS = 30.0
30
- RETRYABLE_STATUS_CODES = {408, 429, 502, 503, 504}
31
+ # Inference POSTs are idempotent. Hosted model runtimes can emit transient
32
+ # generic 500 responses while recovering, so configured retry budgets may retry them.
33
+ RETRYABLE_STATUS_CODES = {408, 429, 500, 502, 503, 504}
31
34
 
32
35
  @inject
33
36
  def __init__(self,
@@ -251,7 +254,7 @@ class InferenceService:
251
254
  return self._resolve_float_config(
252
255
  config,
253
256
  "retry_budget_seconds",
254
- 0.0,
257
+ self.DEFAULT_RETRY_BUDGET_SECONDS,
255
258
  minimum=0.0,
256
259
  )
257
260
 
@@ -307,16 +310,47 @@ class InferenceService:
307
310
  attempt: int,
308
311
  delay_seconds: float,
309
312
  reason: str,
313
+ attempt_duration_seconds: float | None = None,
314
+ elapsed_seconds: float | None = None,
310
315
  suppress_error_logging: bool = False
311
316
  ) -> None:
312
317
  log_fn = logging.debug if suppress_error_logging else logging.warning
318
+ if attempt_duration_seconds is None or elapsed_seconds is None:
319
+ log_fn(
320
+ "Inference request retry %s scheduled in %.1fs: %s",
321
+ attempt,
322
+ delay_seconds,
323
+ reason,
324
+ )
325
+ return
326
+
313
327
  log_fn(
314
- "Inference request retry %s scheduled in %.1fs: %s",
328
+ "Inference request retry %s scheduled in %.1fs after %.1fs attempt (elapsed %.1fs): %s",
315
329
  attempt,
316
330
  delay_seconds,
331
+ attempt_duration_seconds,
332
+ elapsed_seconds,
317
333
  reason,
318
334
  )
319
335
 
336
+ def _timeout_for_attempt(
337
+ self,
338
+ *,
339
+ timeout: tuple[float, float],
340
+ deadline: float | None,
341
+ attempt: int,
342
+ ) -> tuple[float, float] | None:
343
+ if deadline is None or attempt == 1:
344
+ return timeout
345
+
346
+ remaining_seconds = deadline - time.monotonic()
347
+ if remaining_seconds <= 0:
348
+ return None
349
+
350
+ connect_timeout, read_timeout = timeout
351
+ bounded_timeout = max(0.1, remaining_seconds)
352
+ return min(connect_timeout, bounded_timeout), min(read_timeout, bounded_timeout)
353
+
320
354
  def _call_endpoint(
321
355
  self,
322
356
  url: str,
@@ -324,35 +358,51 @@ class InferenceService:
324
358
  payload: dict,
325
359
  suppress_error_logging: bool = False,
326
360
  timeout: tuple[float, float] = (DEFAULT_CONNECT_TIMEOUT_SECONDS, DEFAULT_READ_TIMEOUT_SECONDS),
327
- retry_budget_seconds: float = 0.0,
361
+ retry_budget_seconds: float = DEFAULT_RETRY_BUDGET_SECONDS,
328
362
  ) -> Any:
329
363
  """Performs the POST request to the HF Endpoint."""
330
364
  headers = {
331
365
  "Authorization": f"Bearer {api_key}",
332
366
  "Content-Type": "application/json",
333
367
  }
334
- deadline = time.monotonic() + retry_budget_seconds if retry_budget_seconds > 0 else None
368
+ started_at = time.monotonic()
369
+ deadline = started_at + retry_budget_seconds if retry_budget_seconds > 0 else None
335
370
  attempt = 1
336
371
  delay_seconds = self.DEFAULT_RETRY_INITIAL_DELAY_SECONDS
337
372
 
338
373
  while True:
374
+ attempt_timeout = self._timeout_for_attempt(timeout=timeout, deadline=deadline, attempt=attempt)
375
+ if attempt_timeout is None:
376
+ error_msg = "Inference retry budget exhausted before next attempt."
377
+ if not suppress_error_logging:
378
+ logging.error(error_msg)
379
+ raise ValueError(error_msg)
380
+
381
+ attempt_started_at = time.monotonic()
339
382
  try:
340
383
  resp, status = self.call_service.post(
341
384
  url,
342
385
  json_dict=payload,
343
386
  headers=headers,
344
- timeout=timeout
387
+ timeout=attempt_timeout
345
388
  )
346
389
  except Exception as exc:
390
+ attempt_duration = time.monotonic() - attempt_started_at
347
391
  next_delay = self._next_retry_delay(delay_seconds=delay_seconds, deadline=deadline)
348
392
  if self._is_retryable_request_exception(exc) and next_delay is not None:
349
393
  self._log_retry_attempt(
350
394
  attempt=attempt,
351
395
  delay_seconds=next_delay,
352
396
  reason=str(exc),
397
+ attempt_duration_seconds=attempt_duration,
398
+ elapsed_seconds=time.monotonic() - started_at,
353
399
  suppress_error_logging=suppress_error_logging,
354
400
  )
355
401
  time.sleep(next_delay)
402
+ if deadline is not None and time.monotonic() >= deadline:
403
+ if not suppress_error_logging:
404
+ logging.error(f"Failed to call inference endpoint: {exc}")
405
+ raise
356
406
  attempt += 1
357
407
  delay_seconds = min(delay_seconds * 2, self.DEFAULT_RETRY_MAX_DELAY_SECONDS)
358
408
  continue
@@ -364,6 +414,7 @@ class InferenceService:
364
414
  if status == 200:
365
415
  return resp
366
416
 
417
+ attempt_duration = time.monotonic() - attempt_started_at
367
418
  error_msg = f"Inference Endpoint Error {status}"
368
419
  if isinstance(resp, dict) and 'error' in resp:
369
420
  error_msg += f": {resp['error']}"
@@ -374,9 +425,16 @@ class InferenceService:
374
425
  attempt=attempt,
375
426
  delay_seconds=next_delay,
376
427
  reason=error_msg,
428
+ attempt_duration_seconds=attempt_duration,
429
+ elapsed_seconds=time.monotonic() - started_at,
377
430
  suppress_error_logging=suppress_error_logging,
378
431
  )
379
432
  time.sleep(next_delay)
433
+ if deadline is not None and time.monotonic() >= deadline:
434
+ if not suppress_error_logging:
435
+ logging.error(f"{error_msg} | Payload keys: {list(payload.keys())}")
436
+ logging.error(f"Failed to call inference endpoint: {error_msg}")
437
+ raise ValueError(error_msg)
380
438
  attempt += 1
381
439
  delay_seconds = min(delay_seconds * 2, self.DEFAULT_RETRY_MAX_DELAY_SECONDS)
382
440
  continue
@@ -488,7 +488,8 @@ class KnowledgeBaseService:
488
488
  query: str,
489
489
  n_results: int = 5,
490
490
  collection: str | list[str] | None = None,
491
- metadata_filter: dict = None
491
+ metadata_filter: dict = None,
492
+ include_urls: bool = True,
492
493
  ):
493
494
  """
494
495
  Performs a semantic search and returns the list of Document objects (chunks).
@@ -500,6 +501,7 @@ class KnowledgeBaseService:
500
501
  n_results: Max number of chunks to retrieve.
501
502
  metadata_filter: Optional filter for document metadata.
502
503
  collection: Optional collection name or list of collection names.
504
+ include_urls: Generate storage URLs for returned chunks when true.
503
505
 
504
506
  Returns:
505
507
  List of Document objects found.
@@ -532,6 +534,7 @@ class KnowledgeBaseService:
532
534
  n_results=n_results,
533
535
  metadata_filter=metadata_filter,
534
536
  collection_ids=collection_ids,
537
+ include_urls=include_urls,
535
538
  )
536
539
 
537
540
  return chunk_list
@@ -0,0 +1,196 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from __future__ import annotations
7
+
8
+ import logging
9
+ import time
10
+ from injector import inject
11
+
12
+ from iatoolkit.common.interfaces.secret_provider import SecretProvider
13
+ from iatoolkit.common.secret_resolver import resolve_secret
14
+ from iatoolkit.company_registry import get_registered_companies
15
+ from iatoolkit.services.configuration_service import ConfigurationService
16
+ from iatoolkit.services.embedding_service import EmbeddingService
17
+
18
+
19
+ class WarmupService:
20
+ """
21
+ Lightweight warm-up orchestrator.
22
+ Keep it simple: no shared state, no locking, no dedup.
23
+ """
24
+
25
+ @inject
26
+ def __init__(self,
27
+ config_service: ConfigurationService,
28
+ embedding_service: EmbeddingService,
29
+ secret_provider: SecretProvider):
30
+ self.config_service = config_service
31
+ self.embedding_service = embedding_service
32
+ self.secret_provider = secret_provider
33
+
34
+ def warmup_company(self, company_short_name: str, trigger: str = "manual"):
35
+ start = time.perf_counter()
36
+ try:
37
+ self._warmup_remote_text_embeddings(company_short_name)
38
+ elapsed_ms = (time.perf_counter() - start) * 1000
39
+ logging.info(
40
+ "🔥 Warm-up done for company='%s' trigger='%s' in %.2f ms",
41
+ company_short_name,
42
+ trigger,
43
+ elapsed_ms
44
+ )
45
+ except Exception as e:
46
+ elapsed_ms = (time.perf_counter() - start) * 1000
47
+ logging.debug(
48
+ "⚠️ Warm-up failed for company='%s' trigger='%s' in %.2f ms: %s",
49
+ company_short_name,
50
+ trigger,
51
+ elapsed_ms,
52
+ e
53
+ )
54
+
55
+ def warmup_registered_companies(self, trigger: str = "manual"):
56
+ for company_short_name in get_registered_companies().keys():
57
+ self.warmup_company(company_short_name, trigger=trigger)
58
+
59
+ def warmup_startup_configured_companies(self, trigger: str = "startup") -> list[str]:
60
+ warmed_companies: list[str] = []
61
+ for company_short_name in get_registered_companies().keys():
62
+ warmed_profiles = self._warmup_remote_text_embeddings(company_short_name, startup_only=True)
63
+ if not warmed_profiles:
64
+ logging.debug(
65
+ "Startup warm-up skipped for company='%s': no embedding provider enabled warmup_on_startup.",
66
+ company_short_name,
67
+ )
68
+ continue
69
+
70
+ warmed_companies.append(company_short_name)
71
+
72
+ return warmed_companies
73
+
74
+ def is_startup_warmup_enabled(self, company_short_name: str) -> bool:
75
+ return bool(self._get_remote_text_embedding_profiles(company_short_name, startup_only=True))
76
+
77
+ def _warmup_remote_text_embeddings(self, company_short_name: str, startup_only: bool = False) -> list[tuple[str, str, str]]:
78
+ profiles = self._get_remote_text_embedding_profiles(company_short_name, startup_only=startup_only)
79
+ if not profiles:
80
+ logging.debug(
81
+ "Warm-up skipped for company='%s': no remote embedding inference configured.",
82
+ company_short_name
83
+ )
84
+ return []
85
+
86
+ warmed_profiles = []
87
+ for model_type, config_section, tool_name in profiles:
88
+ try:
89
+ # Prime the remote model/container and download/cache model weights.
90
+ self.embedding_service.embed_text(
91
+ company_short_name,
92
+ "hello",
93
+ model_type=model_type,
94
+ suppress_error_logging=True,
95
+ )
96
+ logging.debug(
97
+ "Warm-up primed remote embedding profile company='%s' section='%s' model_type='%s' tool='%s'.",
98
+ company_short_name,
99
+ config_section,
100
+ model_type,
101
+ tool_name,
102
+ )
103
+ warmed_profiles.append((model_type, config_section, tool_name))
104
+ except Exception as e:
105
+ logging.debug(
106
+ "Warm-up failed for remote embedding profile company='%s' section='%s' model_type='%s' tool='%s': %s",
107
+ company_short_name,
108
+ config_section,
109
+ model_type,
110
+ tool_name,
111
+ e,
112
+ )
113
+
114
+ return warmed_profiles
115
+
116
+ def _uses_remote_text_inference(self, company_short_name: str) -> bool:
117
+ return bool(self._get_remote_text_embedding_profiles(company_short_name))
118
+
119
+ def _get_remote_text_embedding_profiles(
120
+ self,
121
+ company_short_name: str,
122
+ startup_only: bool = False,
123
+ ) -> list[tuple[str, str, str]]:
124
+ profiles: list[tuple[str, str, str, dict]] = []
125
+
126
+ embedding_cfg = self.config_service.get_configuration(company_short_name, "embedding_provider") or {}
127
+ if isinstance(embedding_cfg, dict):
128
+ profiles.append(("text", "embedding_provider", embedding_cfg.get("tool_name") or "text_embeddings", embedding_cfg))
129
+
130
+ embedding_providers = self.config_service.get_configuration(company_short_name, "embedding_providers") or {}
131
+ if isinstance(embedding_providers, dict):
132
+ for model_type, embedding_provider_cfg in embedding_providers.items():
133
+ if not isinstance(embedding_provider_cfg, dict):
134
+ continue
135
+ normalized_model_type = str(model_type or "").strip()
136
+ if not normalized_model_type:
137
+ continue
138
+ profiles.append((
139
+ normalized_model_type,
140
+ f"embedding_providers.{normalized_model_type}",
141
+ embedding_provider_cfg.get("tool_name") or normalized_model_type,
142
+ embedding_provider_cfg,
143
+ ))
144
+
145
+ inference_tools = self.config_service.get_configuration(company_short_name, "inference_tools") or {}
146
+ if not isinstance(inference_tools, dict):
147
+ return []
148
+
149
+ remote_profiles = [
150
+ (model_type, config_section, str(tool_name or "").strip())
151
+ for model_type, config_section, tool_name, embedding_cfg in profiles
152
+ if self._is_remote_embedding_profile(company_short_name, embedding_cfg, inference_tools, str(tool_name or "").strip())
153
+ and (not startup_only or bool(embedding_cfg.get("warmup_on_startup")))
154
+ ]
155
+
156
+ # Leave the default text profile warm last. It is the profile used by rag_search.
157
+ return sorted(remote_profiles, key=lambda item: 1 if item[0] == "text" else 0)
158
+
159
+ def _is_remote_embedding_profile(
160
+ self,
161
+ company_short_name: str,
162
+ embedding_cfg: dict,
163
+ inference_tools: dict,
164
+ tool_name: str,
165
+ ) -> bool:
166
+ provider = (embedding_cfg.get("provider") or "").strip().lower()
167
+ if provider != "huggingface":
168
+ return False
169
+
170
+ if not tool_name:
171
+ return False
172
+
173
+ defaults = inference_tools.get("_defaults") or {}
174
+ if not isinstance(defaults, dict):
175
+ defaults = {}
176
+
177
+ tool_cfg = inference_tools.get(tool_name) or {}
178
+ if not isinstance(tool_cfg, dict):
179
+ return False
180
+
181
+ resolved_cfg = {**defaults, **tool_cfg}
182
+ endpoint_url = (resolved_cfg.get("endpoint_url") or "").strip()
183
+ if not endpoint_url:
184
+ endpoint_url_secret_ref = (resolved_cfg.get("endpoint_url_secret_ref") or "").strip()
185
+ if endpoint_url_secret_ref:
186
+ endpoint_url = (
187
+ resolve_secret(self.secret_provider, company_short_name, endpoint_url_secret_ref, default="") or ""
188
+ ).strip()
189
+ if not endpoint_url:
190
+ endpoint_url_env = (resolved_cfg.get("endpoint_url_env") or "").strip()
191
+ if endpoint_url_env:
192
+ endpoint_url = (
193
+ resolve_secret(self.secret_provider, company_short_name, endpoint_url_env, default="") or ""
194
+ ).strip()
195
+
196
+ return bool(endpoint_url)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.29.0
3
+ Version: 2.30.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -1,108 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from __future__ import annotations
7
-
8
- import logging
9
- import time
10
- from injector import inject
11
-
12
- from iatoolkit.common.interfaces.secret_provider import SecretProvider
13
- from iatoolkit.common.secret_resolver import resolve_secret
14
- from iatoolkit.company_registry import get_registered_companies
15
- from iatoolkit.services.configuration_service import ConfigurationService
16
- from iatoolkit.services.embedding_service import EmbeddingService
17
-
18
-
19
- class WarmupService:
20
- """
21
- Lightweight warm-up orchestrator.
22
- Keep it simple: no shared state, no locking, no dedup.
23
- """
24
-
25
- @inject
26
- def __init__(self,
27
- config_service: ConfigurationService,
28
- embedding_service: EmbeddingService,
29
- secret_provider: SecretProvider):
30
- self.config_service = config_service
31
- self.embedding_service = embedding_service
32
- self.secret_provider = secret_provider
33
-
34
- def warmup_company(self, company_short_name: str, trigger: str = "manual"):
35
- start = time.perf_counter()
36
- try:
37
- self._warmup_remote_text_embeddings(company_short_name)
38
- elapsed_ms = (time.perf_counter() - start) * 1000
39
- logging.info(
40
- "🔥 Warm-up done for company='%s' trigger='%s' in %.2f ms",
41
- company_short_name,
42
- trigger,
43
- elapsed_ms
44
- )
45
- except Exception as e:
46
- elapsed_ms = (time.perf_counter() - start) * 1000
47
- logging.debug(
48
- "⚠️ Warm-up failed for company='%s' trigger='%s' in %.2f ms: %s",
49
- company_short_name,
50
- trigger,
51
- elapsed_ms,
52
- e
53
- )
54
-
55
- def warmup_registered_companies(self, trigger: str = "manual"):
56
- for company_short_name in get_registered_companies().keys():
57
- self.warmup_company(company_short_name, trigger=trigger)
58
-
59
- def _warmup_remote_text_embeddings(self, company_short_name: str):
60
- if not self._uses_remote_text_inference(company_short_name):
61
- logging.debug(
62
- "Warm-up skipped for company='%s': no remote embedding inference configured.",
63
- company_short_name
64
- )
65
- return
66
-
67
- # Prime the remote model/container.
68
- self.embedding_service.embed_text(
69
- company_short_name,
70
- "hello",
71
- suppress_error_logging=True,
72
- )
73
-
74
- def _uses_remote_text_inference(self, company_short_name: str) -> bool:
75
- embedding_cfg = self.config_service.get_configuration(company_short_name, "embedding_provider") or {}
76
- provider = (embedding_cfg.get("provider") or "").strip().lower()
77
- if provider != "huggingface":
78
- return False
79
-
80
- tool_name = (embedding_cfg.get("tool_name") or "text_embeddings").strip()
81
- if not tool_name:
82
- return False
83
-
84
- inference_tools = self.config_service.get_configuration(company_short_name, "inference_tools") or {}
85
- defaults = inference_tools.get("_defaults") or {}
86
- if not isinstance(defaults, dict):
87
- defaults = {}
88
-
89
- tool_cfg = inference_tools.get(tool_name) or {}
90
- if not isinstance(tool_cfg, dict):
91
- return False
92
-
93
- resolved_cfg = {**defaults, **tool_cfg}
94
- endpoint_url = (resolved_cfg.get("endpoint_url") or "").strip()
95
- if not endpoint_url:
96
- endpoint_url_secret_ref = (resolved_cfg.get("endpoint_url_secret_ref") or "").strip()
97
- if endpoint_url_secret_ref:
98
- endpoint_url = (
99
- resolve_secret(self.secret_provider, company_short_name, endpoint_url_secret_ref, default="") or ""
100
- ).strip()
101
- if not endpoint_url:
102
- endpoint_url_env = (resolved_cfg.get("endpoint_url_env") or "").strip()
103
- if endpoint_url_env:
104
- endpoint_url = (
105
- resolve_secret(self.secret_provider, company_short_name, endpoint_url_env, default="") or ""
106
- ).strip()
107
-
108
- return bool(endpoint_url)
File without changes
File without changes
File without changes
File without changes
File without changes