iatoolkit 0.66.4__tar.gz → 0.67.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 (128) hide show
  1. iatoolkit-0.67.0/LICENSE +21 -0
  2. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/PKG-INFO +40 -22
  3. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/pyproject.toml +1 -1
  4. iatoolkit-0.67.0/readme.md +65 -0
  5. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/__init__.py +2 -0
  6. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/base_company.py +1 -20
  7. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/company_registry.py +1 -2
  8. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/iatoolkit.py +7 -3
  9. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/database_manager.py +2 -2
  10. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/models.py +0 -3
  11. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/profile_repo.py +0 -4
  12. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/branding_service.py +6 -3
  13. iatoolkit-0.67.0/src/iatoolkit/services/configuration_service.py +140 -0
  14. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/dispatcher_service.py +12 -9
  15. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/i18n_service.py +2 -2
  16. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/language_service.py +22 -20
  17. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/onboarding_service.py +10 -4
  18. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/profile_service.py +2 -2
  19. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +37 -47
  20. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/chat.html +11 -4
  21. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/help_content_api_view.py +8 -8
  22. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit.egg-info/PKG-INFO +40 -22
  23. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit.egg-info/SOURCES.txt +2 -1
  24. iatoolkit-0.66.4/readme.md +0 -49
  25. iatoolkit-0.66.4/src/iatoolkit/services/help_content_service.py +0 -30
  26. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/requirements.txt +0 -0
  27. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/setup.cfg +0 -0
  28. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/cli_commands.py +0 -0
  29. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/common/__init__.py +0 -0
  30. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/common/exceptions.py +0 -0
  31. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/common/routes.py +0 -0
  32. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/common/session_manager.py +0 -0
  33. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/common/util.py +0 -0
  34. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/__init__.py +0 -0
  35. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/call_service.py +0 -0
  36. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  37. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  38. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  39. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  40. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  41. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  42. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  43. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/gemini_adapter.py +0 -0
  44. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  45. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/llm_client.py +0 -0
  46. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  47. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/llm_response.py +0 -0
  48. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/mail_app.py +0 -0
  49. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/openai_adapter.py +0 -0
  50. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  51. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/locales/en.yaml +0 -0
  52. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/locales/es.yaml +0 -0
  53. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/__init__.py +0 -0
  54. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  55. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  56. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/tasks_repo.py +0 -0
  57. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  58. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/__init__.py +0 -0
  59. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/auth_service.py +0 -0
  60. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  61. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/document_service.py +0 -0
  62. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/excel_service.py +0 -0
  63. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  64. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/history_service.py +0 -0
  65. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/jwt_service.py +0 -0
  66. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/load_documents_service.py +0 -0
  67. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/mail_service.py +0 -0
  68. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/prompt_manager_service.py +0 -0
  69. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/query_service.py +0 -0
  70. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/search_service.py +0 -0
  71. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/sql_service.py +0 -0
  72. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/tasks_service.py +0 -0
  73. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  74. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  75. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  76. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  77. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  78. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  79. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  80. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  81. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  82. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  83. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  84. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  85. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  86. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  87. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  88. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  89. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  90. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  91. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  92. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  93. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/_company_header.html +0 -0
  94. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  95. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/about.html +0 -0
  96. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/base.html +0 -0
  97. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/change_password.html +0 -0
  98. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  99. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/error.html +0 -0
  100. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  101. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/index.html +0 -0
  102. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/login_simulation.html +0 -0
  103. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  104. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/templates/signup.html +0 -0
  105. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/__init__.py +0 -0
  106. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/base_login_view.py +0 -0
  107. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/change_password_view.py +0 -0
  108. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/external_login_view.py +0 -0
  109. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/file_store_api_view.py +0 -0
  110. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  111. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/history_api_view.py +0 -0
  112. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/home_view.py +0 -0
  113. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/index_view.py +0 -0
  114. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  115. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  116. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/login_simulation_view.py +0 -0
  117. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/login_view.py +0 -0
  118. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  119. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  120. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  121. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/signup_view.py +0 -0
  122. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/tasks_api_view.py +0 -0
  123. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/tasks_review_api_view.py +0 -0
  124. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  125. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  126. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  127. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  128. {iatoolkit-0.66.4 → iatoolkit-0.67.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fernando Libedinsky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.66.4
3
+ Version: 0.67.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
7
7
  Requires-Python: >=3.12
8
8
  Description-Content-Type: text/markdown
9
+ License-File: LICENSE
9
10
  Requires-Dist: aiohappyeyeballs==2.4.4
10
11
  Requires-Dist: aiohttp==3.11.9
11
12
  Requires-Dist: aiosignal==1.3.1
@@ -206,47 +207,64 @@ Requires-Dist: wrapt==1.17.0
206
207
  Requires-Dist: yarl==1.18.3
207
208
  Requires-Dist: zipp==3.21.0
208
209
  Requires-Dist: zstandard==0.23.0
210
+ Dynamic: license-file
209
211
 
210
212
 
211
213
  <div align="center">
212
- <h1>IAToolkit</h1>
214
+ <h1>
215
+ IAToolkit
216
+ </h1>
217
+
213
218
  <p><strong>The Open-Source Framework for Building AI Chatbots on Your Private Data.</strong></p>
219
+ <h4>
220
+ <a href="https://www.iatoolkit.com" target="_blank" style="text-decoration: none; color: inherit;">
221
+ www.iatoolkit.com
222
+ </a>
223
+ </h4>
214
224
  </div>
215
225
 
216
- IAToolkit is a comprehensive, open-source framework designed for building enterprise-grade
217
- AI chatbots and conversational applications.
226
+ IAToolkit is a comprehensive, Python open-source framework designed for building enterprise-grade
227
+ AI chatbots and conversational applications. It bridges the gap between the power of
228
+ Large Language Models (LLMs) and the valuable,
229
+ private data locked within your organization's databases and documents.
230
+
218
231
  With IAToolkit, you can build production-ready, context-aware chatbots and agents that
219
232
  can query relational databases, perform semantic searches on documents,
220
233
  and connect to your internal APIs in minutes.
221
234
 
222
- IAToolkit bridges the gap between powerful LLMs and your company's data.
235
+ Create secure, branded chat interfaces that can reason over your data, answer questions, and execute custom business logic,
236
+ all powered by leading models from OpenAI, Google Gemini, and more.
223
237
 
224
238
 
225
239
  ## 🚀 Key Features
226
240
 
227
- * **🔗 Unified Data Connection**:
228
- * **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
229
- * **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
241
+ * **🔗 Unified Data Connection**
242
+ * **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
243
+ * **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
230
244
 
231
- * **🏢 Enterprise-Ready Multi-Tenancy**:
232
- * Deploy isolated "Company" modules, each with its own data, tools, and context. Perfect for SaaS products or internal departmental agents.
245
+ * **🏢 Enterprise-Ready Multi-Tenancy**
246
+ * Deploy isolated "Company" modules, each with its own data, tools, and context.
247
+ * Perfect for SaaS products or internal departmental agents.
233
248
 
234
- * **🧠 LLM Agnostic**:
235
- * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration. No code refactoring needed.
249
+ * **🎨 Fully Brandable UI**
250
+ * Customize the look and feel for each "Company" with its own logos, colors, and even language settings (i18n).
251
+ * Provides a white-labeled experience for your users.
236
252
 
237
- * **🛠️ Developer-First Experience**:
238
- * Built with a clean, **Dependency Injection** architecture.
239
- * High-quality code base with **90%+ test coverage**.
240
- * Powerful Flask-based **CLI** for database setup, API key generation, and more.
253
+ * **🧠 LLM Agnostic**
254
+ * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration.
255
+ * No code refactoring needed.
241
256
 
242
- * **🔒 Security & Observability Built-In**:
243
- * Comes with JWT-based authentication, user management, and secure session handling out of the box.
244
- * Full traceability with detailed logging of all queries, function calls, token usage, and costs.
257
+ * **🛠️ Developer-First Experience**
258
+ * Built with a clean **Dependency Injection** architecture.
259
+ * High-quality code base with **90%+ test coverage**.
245
260
 
246
- ## Quick Start: Create a Custom Tool in 30 Seconds
261
+ * **🔒 Security & Observability Built-In**
262
+ * Comes with integrated user authentication, API keys, and secure session handling out of the box.
263
+ * Full traceability with detailed logging of all queries, function calls, token usage, and costs.
264
+ ## ⚡ Quick Start: Try our 'hello world' example
247
265
 
248
- See how easy it is to give your AI a new skill. Just define a method inside your Company class and describe it.
249
- IAToolkit handles the rest.
266
+ Ready to see it in action? Our Quickstart Guide will walk you through downloading, configuring, and launching your first AI assistant in just a few minutes.
267
+ It's the best way to experience the toolkit's capabilities firsthand.
250
268
 
251
269
  ## 🤝 Contributing
252
270
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iatoolkit"
7
- version = "0.66.4"
7
+ version = "0.67.0"
8
8
  requires-python = ">=3.12"
9
9
  description = "IAToolkit"
10
10
  readme = "readme.md"
@@ -0,0 +1,65 @@
1
+
2
+ <div align="center">
3
+ <h1>
4
+ IAToolkit
5
+ </h1>
6
+
7
+ <p><strong>The Open-Source Framework for Building AI Chatbots on Your Private Data.</strong></p>
8
+ <h4>
9
+ <a href="https://www.iatoolkit.com" target="_blank" style="text-decoration: none; color: inherit;">
10
+ www.iatoolkit.com
11
+ </a>
12
+ </h4>
13
+ </div>
14
+
15
+ IAToolkit is a comprehensive, Python open-source framework designed for building enterprise-grade
16
+ AI chatbots and conversational applications. It bridges the gap between the power of
17
+ Large Language Models (LLMs) and the valuable,
18
+ private data locked within your organization's databases and documents.
19
+
20
+ With IAToolkit, you can build production-ready, context-aware chatbots and agents that
21
+ can query relational databases, perform semantic searches on documents,
22
+ and connect to your internal APIs in minutes.
23
+
24
+ Create secure, branded chat interfaces that can reason over your data, answer questions, and execute custom business logic,
25
+ all powered by leading models from OpenAI, Google Gemini, and more.
26
+
27
+
28
+ ## 🚀 Key Features
29
+
30
+ * **🔗 Unified Data Connection**
31
+ * **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
32
+ * **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
33
+
34
+ * **🏢 Enterprise-Ready Multi-Tenancy**
35
+ * Deploy isolated "Company" modules, each with its own data, tools, and context.
36
+ * Perfect for SaaS products or internal departmental agents.
37
+
38
+ * **🎨 Fully Brandable UI**
39
+ * Customize the look and feel for each "Company" with its own logos, colors, and even language settings (i18n).
40
+ * Provides a white-labeled experience for your users.
41
+
42
+ * **🧠 LLM Agnostic**
43
+ * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration.
44
+ * No code refactoring needed.
45
+
46
+ * **🛠️ Developer-First Experience**
47
+ * Built with a clean **Dependency Injection** architecture.
48
+ * High-quality code base with **90%+ test coverage**.
49
+
50
+ * **🔒 Security & Observability Built-In**
51
+ * Comes with integrated user authentication, API keys, and secure session handling out of the box.
52
+ * Full traceability with detailed logging of all queries, function calls, token usage, and costs.
53
+ ## ⚡ Quick Start: Try our 'hello world' example
54
+
55
+ Ready to see it in action? Our Quickstart Guide will walk you through downloading, configuring, and launching your first AI assistant in just a few minutes.
56
+ It's the best way to experience the toolkit's capabilities firsthand.
57
+
58
+ ## 🤝 Contributing
59
+
60
+ We welcome contributions! Whether it's adding a new feature, improving documentation, or fixing a bug,
61
+ please feel free to open a pull request.
62
+
63
+ ## 📄 License
64
+
65
+ IAToolkit is open-source and licensed under the [MIT License](LICENSE).
@@ -13,6 +13,7 @@ from .base_company import BaseCompany
13
13
  from iatoolkit.repositories.database_manager import DatabaseManager
14
14
 
15
15
  # --- Services ---
16
+ from iatoolkit.services.configuration_service import ConfigurationService
16
17
  from iatoolkit.services.query_service import QueryService
17
18
  from iatoolkit.services.sql_service import SqlService
18
19
  from iatoolkit.services.document_service import DocumentService
@@ -29,6 +30,7 @@ __all__ = [
29
30
  'BaseCompany',
30
31
  'DatabaseManager',
31
32
  'QueryService',
33
+ 'ConfigurationService',
32
34
  'SqlService',
33
35
  'ExcelService',
34
36
  'DocumentService',
@@ -7,7 +7,6 @@
7
7
  from abc import ABC, abstractmethod
8
8
  from iatoolkit.repositories.profile_repo import ProfileRepo
9
9
  from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
10
-
11
10
  from iatoolkit.services.prompt_manager_service import PromptService
12
11
  from iatoolkit.repositories.models import Company, Function, PromptCategory
13
12
  from iatoolkit import IAToolkit
@@ -22,22 +21,14 @@ class BaseCompany(ABC):
22
21
  self.prompt_service: PromptService = injector.get(PromptService)
23
22
  self.company: Company | None = None
24
23
 
25
- def _load_company_by_short_name(self, short_name: str) -> Company:
26
- self.company = self.profile_repo.get_company_by_short_name(short_name)
27
- return self.company
28
-
29
24
  def _create_company(self,
30
25
  short_name: str,
31
26
  name: str,
32
27
  parameters: dict | None = None,
33
- branding: dict | None = None,
34
- onboarding_cards: dict | None = None,
35
28
  ) -> Company:
36
29
  company_obj = Company(short_name=short_name,
37
30
  name=name,
38
- parameters=parameters,
39
- branding=branding,
40
- onboarding_cards=onboarding_cards)
31
+ parameters=parameters)
41
32
  self.company = self.profile_repo.create_company(company_obj)
42
33
  return self.company
43
34
 
@@ -78,11 +69,6 @@ class BaseCompany(ABC):
78
69
  )
79
70
 
80
71
 
81
- @abstractmethod
82
- # initialize all the database tables needed
83
- def register_company(self):
84
- raise NotImplementedError("La subclase debe implementar el método create_company()")
85
-
86
72
  @abstractmethod
87
73
  # get context specific for this company
88
74
  def get_company_context(self, **kwargs) -> str:
@@ -98,11 +84,6 @@ class BaseCompany(ABC):
98
84
  def handle_request(self, tag: str, params: dict) -> dict:
99
85
  raise NotImplementedError("La subclase debe implementar el método handle_request()")
100
86
 
101
- @abstractmethod
102
- # get context specific for the query
103
- def start_execution(self):
104
- raise NotImplementedError("La subclase debe implementar el método start_execution()")
105
-
106
87
  @abstractmethod
107
88
  # get context specific for the query
108
89
  def get_metadata_from_filename(self, filename: str) -> dict:
@@ -31,10 +31,9 @@ class CompanyRegistry:
31
31
 
32
32
  # save the created instance in the registry
33
33
  self._company_instances[company_key] = company_instance
34
- logging.info(f"company '{company_key}' instantiated")
35
34
 
36
35
  except Exception as e:
37
- logging.error(f"Error instanciando empresa {company_key}: {e}")
36
+ logging.error(f"Error while creating company instance for {company_key}: {e}")
38
37
  logging.exception(e)
39
38
  raise
40
39
 
@@ -19,7 +19,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
19
19
  from injector import Binder, Injector, singleton
20
20
  from importlib.metadata import version as _pkg_version, PackageNotFoundError
21
21
 
22
- IATOOLKIT_VERSION = "0.66.4"
22
+ IATOOLKIT_VERSION = "0.67.0"
23
23
 
24
24
  # global variable for the unique instance of IAToolkit
25
25
  _iatoolkit_instance: Optional['IAToolkit'] = None
@@ -318,6 +318,8 @@ class IAToolkit:
318
318
  from iatoolkit.services.branding_service import BrandingService
319
319
  from iatoolkit.services.i18n_service import I18nService
320
320
  from iatoolkit.services.language_service import LanguageService
321
+ from iatoolkit.services.onboarding_service import OnboardingService
322
+ from iatoolkit.services.configuration_service import ConfigurationService
321
323
 
322
324
  binder.bind(QueryService, to=QueryService)
323
325
  binder.bind(TaskService, to=TaskService)
@@ -331,8 +333,10 @@ class IAToolkit:
331
333
  binder.bind(JWTService, to=JWTService)
332
334
  binder.bind(Dispatcher, to=Dispatcher)
333
335
  binder.bind(BrandingService, to=BrandingService)
336
+ binder.bind(OnboardingService, to=OnboardingService)
334
337
  binder.bind(I18nService, to=I18nService)
335
338
  binder.bind(LanguageService, to=LanguageService)
339
+ binder.bind(ConfigurationService, to=ConfigurationService)
336
340
 
337
341
  def _bind_infrastructure(self, binder: Binder):
338
342
  from iatoolkit.infra.llm_client import llmClient
@@ -359,9 +363,9 @@ class IAToolkit:
359
363
  # instantiate all the registered companies
360
364
  get_company_registry().instantiate_companies(self._injector)
361
365
 
362
- # use the dispatcher to start the execution of every company
366
+ # use the dispatcher to load the config and prepare the execution
363
367
  dispatcher = self._injector.get(Dispatcher)
364
- dispatcher.start_execution()
368
+ dispatcher.load_company_configs()
365
369
 
366
370
  def _setup_cli_commands(self):
367
371
  from iatoolkit.cli_commands import register_core_commands
@@ -27,8 +27,8 @@ class DatabaseManager:
27
27
  self._engine = create_engine(
28
28
  database_url,
29
29
  echo=False,
30
- pool_size=2, # per worker
31
- max_overflow=3,
30
+ pool_size=10, # per worker
31
+ max_overflow=20,
32
32
  pool_timeout=30,
33
33
  pool_recycle=1800,
34
34
  pool_pre_ping=True,
@@ -58,9 +58,6 @@ class Company(Base):
58
58
  # encrypted api-key
59
59
  openai_api_key = Column(String, nullable=True)
60
60
  gemini_api_key = Column(String, nullable=True)
61
-
62
- branding = Column(JSON, nullable=True)
63
- onboarding_cards = Column(JSON, nullable=True)
64
61
  parameters = Column(JSON, nullable=True)
65
62
  created_at = Column(DateTime, default=datetime.now)
66
63
  allow_jwt = Column(Boolean, default=True, nullable=True)
@@ -74,10 +74,6 @@ class ProfileRepo:
74
74
  if company:
75
75
  if company.parameters != new_company.parameters:
76
76
  company.parameters = new_company.parameters
77
- if company.branding != new_company.branding:
78
- company.branding = new_company.branding
79
- if company.onboarding_cards != new_company.onboarding_cards:
80
- company.onboarding_cards = new_company.onboarding_cards
81
77
  else:
82
78
  # Si la compañía no existe, la añade a la sesión.
83
79
  self.session.add(new_company)
@@ -4,6 +4,7 @@
4
4
  # IAToolkit is open source software.
5
5
 
6
6
  from iatoolkit.repositories.models import Company
7
+ from iatoolkit.services.configuration_service import ConfigurationService
7
8
  from injector import inject
8
9
 
9
10
 
@@ -12,7 +13,8 @@ class BrandingService:
12
13
  Branding configuration for IAToolkit
13
14
  """
14
15
  @inject
15
- def __init__(self):
16
+ def __init__(self, config_service: ConfigurationService):
17
+ self.config_service = config_service
16
18
  """
17
19
  Define los estilos de branding por defecto para la aplicación.
18
20
  """
@@ -74,8 +76,9 @@ class BrandingService:
74
76
  """
75
77
  final_branding_values = self._default_branding.copy()
76
78
 
77
- if company and company.branding:
78
- final_branding_values.update(company.branding)
79
+ if company:
80
+ branding_data = self.config_service.get_company_content(company.short_name, 'branding')
81
+ final_branding_values.update(branding_data)
79
82
 
80
83
  # Función para convertir HEX a RGB
81
84
  def hex_to_rgb(hex_color):
@@ -0,0 +1,140 @@
1
+ # iatoolkit/services/configuration_service.py
2
+ # Copyright (c) 2024 Fernando Libedinsky
3
+ # Product: IAToolkit
4
+
5
+ from pathlib import Path
6
+ from iatoolkit import BaseCompany
7
+ from iatoolkit.repositories.profile_repo import ProfileRepo
8
+ from iatoolkit.repositories.models import Company
9
+ from iatoolkit.common.util import Utility
10
+ from injector import inject
11
+ import logging
12
+
13
+ class ConfigurationService:
14
+ """
15
+ Orchestrates the configuration of a Company by reading its YAML files
16
+ and using the BaseCompany's protected methods to register settings.
17
+ """
18
+
19
+ @inject
20
+ def __init__(self,
21
+ profile_repo: ProfileRepo,
22
+ utility: Utility):
23
+ self.profile_repo = profile_repo
24
+ self.utility = utility
25
+ self._loaded_configs = {} # cache for store loaded configurations
26
+
27
+ def get_company_content(self, company_short_name: str, content_key: str) -> dict | list | None:
28
+ """
29
+ Public method to provide a specific section of a company's configuration.
30
+ It uses a cache to avoid reading files from disk on every call.
31
+ """
32
+ self._ensure_config_loaded(company_short_name)
33
+ return self._loaded_configs[company_short_name].get(content_key)
34
+
35
+ def register_company(self, company_short_name: str, company_instance: BaseCompany):
36
+ """
37
+ Main entry point for configuring a company instance.
38
+ This method is invoked by the dispatcher for each registered company.
39
+ """
40
+ logging.info(f"⚙️ Starting configuration for company '{company_short_name}'...")
41
+
42
+ # 1. identify the instance with his name and load info from database
43
+ company_instance.id = company_short_name
44
+ company_instance.company = self.profile_repo.get_company_by_short_name(company_short_name)
45
+
46
+ # 2. Load the main configuration file and supplementary content files
47
+ config = self._load_and_merge_configs(company_short_name)
48
+
49
+ # 3. Register core company details and get the database object
50
+ company_db_object = self._register_core_details(company_instance, config)
51
+
52
+ # 4. Register tools (functions)
53
+ self._register_tools(company_instance, config.get('tools', []))
54
+
55
+ # 5. Register prompt categories and prompts
56
+ self._register_prompts(company_instance, config)
57
+
58
+ # 6. Link the persisted Company object back to the running instance
59
+ company_instance.company = company_db_object
60
+
61
+ logging.info(f"✅ Company '{company_short_name}' configured successfully.")
62
+
63
+ def _ensure_config_loaded(self, company_short_name: str):
64
+ """
65
+ Checks if the configuration for a company is in the cache.
66
+ If not, it loads it from files and stores it.
67
+ """
68
+ if company_short_name not in self._loaded_configs:
69
+ self._loaded_configs[company_short_name] = self._load_and_merge_configs(company_short_name)
70
+
71
+ def _load_and_merge_configs(self, company_short_name: str) -> dict:
72
+ """
73
+ Loads the main company.yaml and merges data from supplementary files
74
+ specified in the 'content_files' section.
75
+ """
76
+ config_dir = Path("companies") / company_short_name / "config"
77
+ main_config_path = config_dir / "company.yaml"
78
+
79
+ if not main_config_path.exists():
80
+ raise FileNotFoundError(f"Main configuration file not found: {main_config_path}")
81
+
82
+ config = self.utility.load_schema_from_yaml(main_config_path)
83
+
84
+ # Load and merge supplementary content files (e.g., onboarding_cards)
85
+ for key, file_path in config.get('help_files', {}).items():
86
+ supplementary_path = config_dir / file_path
87
+ if supplementary_path.exists():
88
+ config[key] = self.utility.load_schema_from_yaml(supplementary_path)
89
+ else:
90
+ logging.warning(f"⚠️ Warning: Content file not found: {supplementary_path}")
91
+ config[key] = None # Ensure the key exists but is empty
92
+
93
+ return config
94
+
95
+ def _register_core_details(self, company_instance: BaseCompany, config: dict) -> Company:
96
+ """Calls _create_company with data from the merged YAML config."""
97
+ return company_instance._create_company(
98
+ name=config['name'],
99
+ short_name=config['id'],
100
+ parameters=config.get('parameters', {})
101
+ )
102
+
103
+ def _register_tools(self, company_instance: BaseCompany, tools_config: list):
104
+ """Calls _create_function for each tool defined in the YAML."""
105
+ for tool in tools_config:
106
+ company_instance._create_function(
107
+ function_name=tool['function_name'],
108
+ description=tool['description'],
109
+ params=tool['params']
110
+ )
111
+
112
+ def _register_prompts(self, company_instance: BaseCompany, config: dict):
113
+ """
114
+ Creates prompt categories first, then creates each prompt and assigns
115
+ it to its respective category.
116
+ """
117
+ prompts_config = config.get('prompts', [])
118
+ categories_config = config.get('prompt_categories', [])
119
+
120
+ created_categories = {}
121
+ for i, category_name in enumerate(categories_config):
122
+ category_obj = company_instance._create_prompt_category(name=category_name, order=i + 1)
123
+ created_categories[category_name] = category_obj
124
+
125
+ for prompt_data in prompts_config:
126
+ category_name = prompt_data.get('category')
127
+ if not category_name or category_name not in created_categories:
128
+ logging.info(f"⚠️ Warning: Prompt '{prompt_data['name']}' has an invalid or missing category. Skipping.")
129
+ continue
130
+
131
+ category_obj = created_categories[category_name]
132
+
133
+ company_instance._create_prompt(
134
+ prompt_name=prompt_data['name'],
135
+ description=prompt_data['description'],
136
+ order=prompt_data['order'],
137
+ category=category_obj,
138
+ active=prompt_data.get('active', True),
139
+ custom_fields=prompt_data.get('custom_fields', [])
140
+ )
@@ -6,7 +6,7 @@
6
6
  from iatoolkit.common.exceptions import IAToolkitException
7
7
  from iatoolkit.services.prompt_manager_service import PromptService
8
8
  from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
9
-
9
+ from iatoolkit.services.configuration_service import ConfigurationService
10
10
  from iatoolkit.repositories.models import Company, Function
11
11
  from iatoolkit.services.excel_service import ExcelService
12
12
  from iatoolkit.services.mail_service import MailService
@@ -19,11 +19,13 @@ import os
19
19
  class Dispatcher:
20
20
  @inject
21
21
  def __init__(self,
22
+ config_service: ConfigurationService,
22
23
  prompt_service: PromptService,
23
24
  llmquery_repo: LLMQueryRepo,
24
25
  util: Utility,
25
26
  excel_service: ExcelService,
26
27
  mail_service: MailService):
28
+ self.config_service = config_service
27
29
  self.prompt_service = prompt_service
28
30
  self.llmquery_repo = llmquery_repo
29
31
  self.util = util
@@ -55,14 +57,18 @@ class Dispatcher:
55
57
  self._company_instances = self.company_registry.get_all_company_instances()
56
58
  return self._company_instances
57
59
 
58
- def start_execution(self):
60
+ def load_company_configs(self):
59
61
  # initialize the system functions and prompts
60
62
  self.setup_iatoolkit_system()
61
63
 
62
- """Runs the startup logic for all registered companies."""
63
- for company in self.company_instances.values():
64
- company.register_company()
65
- company.start_execution()
64
+ """Loads the configuration of every company"""
65
+ for company_name, company_instance in self.company_instances.items():
66
+ try:
67
+ # register the company configuration
68
+ self.config_service.register_company(company_name, company_instance)
69
+ except Exception as e:
70
+ logging.error(f"❌ Failed to register configuration for '{company_name}': {e}")
71
+ continue
66
72
 
67
73
  return True
68
74
 
@@ -90,9 +96,6 @@ class Dispatcher:
90
96
  )
91
97
  i += 1
92
98
 
93
- # register in the database every company class
94
- for company in self.company_instances.values():
95
- company.register_company()
96
99
 
97
100
  def dispatch(self, company_name: str, action: str, **kwargs) -> dict:
98
101
  company_key = company_name.lower()
@@ -1,11 +1,11 @@
1
1
  # iatoolkit/services/i18n_service.py
2
2
  import os
3
3
  import logging
4
- from injector import inject
4
+ from injector import inject, singleton
5
5
  from iatoolkit.common.util import Utility
6
6
  from iatoolkit.services.language_service import LanguageService
7
7
 
8
-
8
+ @singleton
9
9
  class I18nService:
10
10
  """
11
11
  Servicio centralizado para manejar la internacionalización (i18n).