iatoolkit 0.71.4__py3-none-any.whl → 1.4.2__py3-none-any.whl

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 (114) hide show
  1. iatoolkit/__init__.py +19 -7
  2. iatoolkit/base_company.py +1 -71
  3. iatoolkit/cli_commands.py +9 -21
  4. iatoolkit/common/exceptions.py +2 -0
  5. iatoolkit/common/interfaces/__init__.py +0 -0
  6. iatoolkit/common/interfaces/asset_storage.py +34 -0
  7. iatoolkit/common/interfaces/database_provider.py +38 -0
  8. iatoolkit/common/model_registry.py +159 -0
  9. iatoolkit/common/routes.py +53 -32
  10. iatoolkit/common/util.py +17 -12
  11. iatoolkit/company_registry.py +55 -14
  12. iatoolkit/{iatoolkit.py → core.py} +102 -72
  13. iatoolkit/infra/{mail_app.py → brevo_mail_app.py} +15 -37
  14. iatoolkit/infra/llm_providers/__init__.py +0 -0
  15. iatoolkit/infra/llm_providers/deepseek_adapter.py +278 -0
  16. iatoolkit/infra/{gemini_adapter.py → llm_providers/gemini_adapter.py} +11 -17
  17. iatoolkit/infra/{openai_adapter.py → llm_providers/openai_adapter.py} +41 -7
  18. iatoolkit/infra/llm_proxy.py +235 -134
  19. iatoolkit/infra/llm_response.py +5 -0
  20. iatoolkit/locales/en.yaml +134 -4
  21. iatoolkit/locales/es.yaml +293 -162
  22. iatoolkit/repositories/database_manager.py +92 -22
  23. iatoolkit/repositories/document_repo.py +7 -0
  24. iatoolkit/repositories/filesystem_asset_repository.py +36 -0
  25. iatoolkit/repositories/llm_query_repo.py +36 -22
  26. iatoolkit/repositories/models.py +86 -95
  27. iatoolkit/repositories/profile_repo.py +64 -13
  28. iatoolkit/repositories/vs_repo.py +31 -28
  29. iatoolkit/services/auth_service.py +1 -1
  30. iatoolkit/services/branding_service.py +1 -1
  31. iatoolkit/services/company_context_service.py +96 -39
  32. iatoolkit/services/configuration_service.py +329 -67
  33. iatoolkit/services/dispatcher_service.py +51 -227
  34. iatoolkit/services/document_service.py +10 -1
  35. iatoolkit/services/embedding_service.py +9 -6
  36. iatoolkit/services/excel_service.py +50 -2
  37. iatoolkit/services/file_processor_service.py +0 -5
  38. iatoolkit/services/history_manager_service.py +208 -0
  39. iatoolkit/services/jwt_service.py +1 -1
  40. iatoolkit/services/knowledge_base_service.py +412 -0
  41. iatoolkit/services/language_service.py +8 -2
  42. iatoolkit/services/license_service.py +82 -0
  43. iatoolkit/{infra/llm_client.py → services/llm_client_service.py} +42 -29
  44. iatoolkit/services/load_documents_service.py +18 -47
  45. iatoolkit/services/mail_service.py +171 -25
  46. iatoolkit/services/profile_service.py +69 -36
  47. iatoolkit/services/{prompt_manager_service.py → prompt_service.py} +136 -25
  48. iatoolkit/services/query_service.py +229 -203
  49. iatoolkit/services/sql_service.py +116 -34
  50. iatoolkit/services/tool_service.py +246 -0
  51. iatoolkit/services/user_feedback_service.py +18 -6
  52. iatoolkit/services/user_session_context_service.py +121 -51
  53. iatoolkit/static/images/iatoolkit_core.png +0 -0
  54. iatoolkit/static/images/iatoolkit_logo.png +0 -0
  55. iatoolkit/static/js/chat_feedback_button.js +1 -1
  56. iatoolkit/static/js/chat_help_content.js +4 -4
  57. iatoolkit/static/js/chat_main.js +61 -9
  58. iatoolkit/static/js/chat_model_selector.js +227 -0
  59. iatoolkit/static/js/chat_onboarding_button.js +1 -1
  60. iatoolkit/static/js/chat_reload_button.js +4 -1
  61. iatoolkit/static/styles/chat_iatoolkit.css +59 -3
  62. iatoolkit/static/styles/chat_public.css +28 -0
  63. iatoolkit/static/styles/documents.css +598 -0
  64. iatoolkit/static/styles/landing_page.css +223 -7
  65. iatoolkit/static/styles/llm_output.css +34 -1
  66. iatoolkit/system_prompts/__init__.py +0 -0
  67. iatoolkit/system_prompts/query_main.prompt +28 -3
  68. iatoolkit/system_prompts/sql_rules.prompt +47 -12
  69. iatoolkit/templates/_company_header.html +30 -5
  70. iatoolkit/templates/_login_widget.html +3 -3
  71. iatoolkit/templates/base.html +13 -0
  72. iatoolkit/templates/chat.html +45 -3
  73. iatoolkit/templates/forgot_password.html +3 -2
  74. iatoolkit/templates/onboarding_shell.html +1 -2
  75. iatoolkit/templates/signup.html +3 -0
  76. iatoolkit/views/base_login_view.py +8 -3
  77. iatoolkit/views/change_password_view.py +1 -1
  78. iatoolkit/views/chat_view.py +76 -0
  79. iatoolkit/views/forgot_password_view.py +9 -4
  80. iatoolkit/views/history_api_view.py +3 -3
  81. iatoolkit/views/home_view.py +4 -2
  82. iatoolkit/views/init_context_api_view.py +1 -1
  83. iatoolkit/views/llmquery_api_view.py +4 -3
  84. iatoolkit/views/load_company_configuration_api_view.py +49 -0
  85. iatoolkit/views/{file_store_api_view.py → load_document_api_view.py} +15 -11
  86. iatoolkit/views/login_view.py +25 -8
  87. iatoolkit/views/logout_api_view.py +10 -2
  88. iatoolkit/views/prompt_api_view.py +1 -1
  89. iatoolkit/views/rag_api_view.py +216 -0
  90. iatoolkit/views/root_redirect_view.py +22 -0
  91. iatoolkit/views/signup_view.py +12 -4
  92. iatoolkit/views/static_page_view.py +27 -0
  93. iatoolkit/views/users_api_view.py +33 -0
  94. iatoolkit/views/verify_user_view.py +1 -1
  95. iatoolkit-1.4.2.dist-info/METADATA +268 -0
  96. iatoolkit-1.4.2.dist-info/RECORD +133 -0
  97. iatoolkit-1.4.2.dist-info/licenses/LICENSE_COMMUNITY.md +15 -0
  98. iatoolkit/repositories/tasks_repo.py +0 -52
  99. iatoolkit/services/history_service.py +0 -37
  100. iatoolkit/services/search_service.py +0 -55
  101. iatoolkit/services/tasks_service.py +0 -188
  102. iatoolkit/templates/about.html +0 -13
  103. iatoolkit/templates/index.html +0 -145
  104. iatoolkit/templates/login_simulation.html +0 -45
  105. iatoolkit/views/external_login_view.py +0 -73
  106. iatoolkit/views/index_view.py +0 -14
  107. iatoolkit/views/login_simulation_view.py +0 -93
  108. iatoolkit/views/tasks_api_view.py +0 -72
  109. iatoolkit/views/tasks_review_api_view.py +0 -55
  110. iatoolkit-0.71.4.dist-info/METADATA +0 -276
  111. iatoolkit-0.71.4.dist-info/RECORD +0 -122
  112. {iatoolkit-0.71.4.dist-info → iatoolkit-1.4.2.dist-info}/WHEEL +0 -0
  113. {iatoolkit-0.71.4.dist-info → iatoolkit-1.4.2.dist-info}/licenses/LICENSE +0 -0
  114. {iatoolkit-0.71.4.dist-info → iatoolkit-1.4.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,133 @@
1
+ iatoolkit/__init__.py,sha256=4kPCwhdZff5rt-FhnHfafMCPvD5hDFGEdRwINPm8ATc,1425
2
+ iatoolkit/base_company.py,sha256=TzGvdseDpJMi9fl5nbR2pMARgU6pN6ISatFoMJKtNxw,648
3
+ iatoolkit/cli_commands.py,sha256=EDky1QpvHnatzXsd1evYW0OQt-k3JIbPGMc13vgDvy4,1814
4
+ iatoolkit/company_registry.py,sha256=XopFzqIpUxBtQJzdZwu2-c0v98MLT7SP_xLPxn_iENM,4176
5
+ iatoolkit/core.py,sha256=QKqu-QDrNWunDU9uX96a86kFNv3a_aAxonkpxJptzoE,20885
6
+ iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ iatoolkit/common/exceptions.py,sha256=xmNi5Et13pCvCM1so79z36I-7Kdie8nVUAqW9acGs9k,1202
8
+ iatoolkit/common/model_registry.py,sha256=HiFr1FtRKGjpp3YurkiF4l6sGuirigDVL-b_3_R-vlM,5561
9
+ iatoolkit/common/routes.py,sha256=cJCFLgSqrTXPOC9CraXLQtoOhVCphWXHyFadYiTXQGw,7292
10
+ iatoolkit/common/session_manager.py,sha256=OUYMzT8hN1U-NCUidR5tUAXB1drd8nYTOpo60rUNYeY,532
11
+ iatoolkit/common/util.py,sha256=e000sUjUXeY4BJrJ3HtnsVMMhn8guclRZkl0f2Dmfy0,15270
12
+ iatoolkit/common/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ iatoolkit/common/interfaces/asset_storage.py,sha256=IYXyc73gmwFT7T8RQhC4MymQDW0vGDSEzuKk43w7Ct4,989
14
+ iatoolkit/common/interfaces/database_provider.py,sha256=Cf-33SZ7HPxTv2b_ahew1TcqDmFH442OPwIv6YEiubk,1097
15
+ iatoolkit/infra/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
16
+ iatoolkit/infra/brevo_mail_app.py,sha256=xvy3KxEEgjFpHlIAogP6SU5KXmg3w7lC16nnNmOYU8Y,5323
17
+ iatoolkit/infra/call_service.py,sha256=iRk9VxbXaAwlLIl8fUzGDWIAdzwfsbs1MtP84YeENxg,4929
18
+ iatoolkit/infra/google_chat_app.py,sha256=_uKWxeacHH6C5a4FVx0YZjBn1tL-x_MIQV9gqgWGAjo,1937
19
+ iatoolkit/infra/llm_proxy.py,sha256=6PngfQ4Q-5tLiqdroNCn58kBJh5uZZb_6S98HKH4pQY,10639
20
+ iatoolkit/infra/llm_response.py,sha256=6hSmI909m0Pdgs7UnJHrv_nokbCZLzHpdwBUED6VNck,1062
21
+ iatoolkit/infra/redis_session_manager.py,sha256=EPr3E_g7LHxn6U4SV5lT_L8WQsAwg8VzA_WIEZ3TwOw,3667
22
+ iatoolkit/infra/connectors/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
23
+ iatoolkit/infra/connectors/file_connector.py,sha256=HOjRTFd-WfDOcFyvHncAhnGNZuFgChIwC-P6osPo9ZM,352
24
+ iatoolkit/infra/connectors/file_connector_factory.py,sha256=3qvyfH4ZHKuiMxJFkawOxhW2-TGKKtsBYHgoPpZMuKU,2118
25
+ iatoolkit/infra/connectors/google_cloud_storage_connector.py,sha256=IXpL3HTo7Ft4EQsYiQq5wXRRQK854jzOEB7ZdWjLa4U,2050
26
+ iatoolkit/infra/connectors/google_drive_connector.py,sha256=WR1AlO5-Bl3W89opdja0kKgHTJzVOjTsy3H4SlIvwVg,2537
27
+ iatoolkit/infra/connectors/local_file_connector.py,sha256=hrzIgpMJOTuwTqzlQeTIU_50ZbZ6yl8lcWPv6hMnoqI,1739
28
+ iatoolkit/infra/connectors/s3_connector.py,sha256=Nj4_YaLobjfcnbZewJf21_K2EXohgcc3mJll1Pzn4zg,1123
29
+ iatoolkit/infra/llm_providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ iatoolkit/infra/llm_providers/deepseek_adapter.py,sha256=ui4V05xplUvLWHu7y_dUMKpP4Af-BkZi5tvdgZY16dU,10719
31
+ iatoolkit/infra/llm_providers/gemini_adapter.py,sha256=xjYAMgS4bh7qfpCEv6n92tzpKdjnNBVFfr8GkSrcatM,14555
32
+ iatoolkit/infra/llm_providers/openai_adapter.py,sha256=9SuHYtPJcadWSV_GHfx8DDj9BqkUS3RvLSyDd_ZVB2M,4848
33
+ iatoolkit/locales/en.yaml,sha256=cKPJQB2sV_AuFd80eOK4r-Y08cKlmG9eG7b34iuBqNo,12210
34
+ iatoolkit/locales/es.yaml,sha256=1LT81MPQAW0mhHOVxWtgiOTxYs6B9Jyc6wgQGz04xGo,13027
35
+ iatoolkit/repositories/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
36
+ iatoolkit/repositories/database_manager.py,sha256=JAi-A_siEZlyQeV7xk1NIYFZjfBCCo12RVSV_pLYYhI,6631
37
+ iatoolkit/repositories/document_repo.py,sha256=5oCrq8pjcyOCBrOc4XYeUvza9nUd0VJ4eNL0g1MQb68,1441
38
+ iatoolkit/repositories/filesystem_asset_repository.py,sha256=ZFr_FpHQD5nszZnJSki6nc-W3PKvmhTxKmVZMd2DUbM,1825
39
+ iatoolkit/repositories/llm_query_repo.py,sha256=8rGSVx7WZlGbUfeVw_uGygTUuJXRK5vGfFHj1znc1ss,3981
40
+ iatoolkit/repositories/models.py,sha256=PH8HiMxKDzZ7khDl9dod2XbRrkWlWCThOrRF9BeChPE,13460
41
+ iatoolkit/repositories/profile_repo.py,sha256=zhjTTizhkTaCZvWMCZtTzTTTmx0fsjtao2fKurwP1xE,5838
42
+ iatoolkit/repositories/vs_repo.py,sha256=CzT77B7_kWN5p3QhXgdf5X3JkS_02CwFVhxmp0K3rrc,6140
43
+ iatoolkit/services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
44
+ iatoolkit/services/auth_service.py,sha256=B0gTUHDf56WiTnA5viBEvbmf2A6y_6bkAoFlMvu0IWY,7756
45
+ iatoolkit/services/benchmark_service.py,sha256=CdbFYyS3FHFhNzWQEa9ZNjUlmON10DT1nKNbZQ1EUi8,5880
46
+ iatoolkit/services/branding_service.py,sha256=Fsjcos7hGLx2qhoZ9hTaFCgb7x5eYHMDGvXg4mXx8D0,8120
47
+ iatoolkit/services/company_context_service.py,sha256=MV07jvef_9u_55n92yHCDwThBykn5rQT1tKg51Ebxoo,9339
48
+ iatoolkit/services/configuration_service.py,sha256=bYjhR5cZcJunFr1OtX2ReOJaHbYrxBlxizEdoo52zaw,17933
49
+ iatoolkit/services/dispatcher_service.py,sha256=f3aPbKU9UkNS61dNVZjT-J9hg3x-H2Nb_n-cZRnZ9aI,5247
50
+ iatoolkit/services/document_service.py,sha256=XrAwbNPyhmP94bGdDwHy76Mg_PCg6O2QyZwii1T6kZ8,6469
51
+ iatoolkit/services/embedding_service.py,sha256=ngRnFXEpko-rqpicqbJbVdr91IjSe1jXSYVWprOVlE0,6296
52
+ iatoolkit/services/excel_service.py,sha256=de4fj3klWFWSTdgej8yk0FBuNr1lunyy9cuOyZwl0rI,6221
53
+ iatoolkit/services/file_processor_service.py,sha256=5xS7zrdL_kpCFXQ5seqNl9tiseI7otD8NRIQENuafjE,3628
54
+ iatoolkit/services/history_manager_service.py,sha256=nq1hk39WDbyHG6s8irpIdCS98EBDagF0djH6JHq9WuY,8734
55
+ iatoolkit/services/i18n_service.py,sha256=mR4pS0z56NgZLeSnEvDXiMvVBeOCl5CkUWdYBTVEhyM,3941
56
+ iatoolkit/services/jwt_service.py,sha256=pVoH1rzRwWixpvT3AhFdiE1BDmdbo4KQMyOF0P7tz-Y,2939
57
+ iatoolkit/services/knowledge_base_service.py,sha256=kjVI04WjOf5q_fYEDNkg-lRN1hqbQrS0URzUGy3dkuo,16500
58
+ iatoolkit/services/language_service.py,sha256=ktNzj0hrCPm_VMIpWTxFEpEHKQ1lOHOfuhzCbZud2Dc,3428
59
+ iatoolkit/services/license_service.py,sha256=pdl9szSEPbIu2ISl6g-WIR1p4HQu2gSGdAjViKxY6Hg,2751
60
+ iatoolkit/services/llm_client_service.py,sha256=YSvoNKeBQRGL3znMDIyLH2PGZt4ImmYKD_aBlBeS91k,19024
61
+ iatoolkit/services/load_documents_service.py,sha256=zK1mXsj9aLDDKoV9WKgNuFlg02ROnlf9umcTm_Y4OIs,6761
62
+ iatoolkit/services/mail_service.py,sha256=6Kx1CIbXzAr_ucoqwqTlhhwE6y2Jw64eNDjXysaZP-c,8297
63
+ iatoolkit/services/profile_service.py,sha256=mUXW5dwFF4SBH04adQuoSj-E0FmuLDt_VcPo9oxdr1M,23680
64
+ iatoolkit/services/prompt_service.py,sha256=mr3szmOThNi6MtqCbh4rwJJOlk-Be35bkIJXqh7_hvM,12898
65
+ iatoolkit/services/query_service.py,sha256=aS2-NtEMdu-QViw58d-g9iZI1j3KZIJb0xrN8N_c__U,20406
66
+ iatoolkit/services/sql_service.py,sha256=kgLEE7iiw9WjnyvOBfm4VJ60-F6JAg26cAKF6LlF-zU,7087
67
+ iatoolkit/services/tool_service.py,sha256=FQuplPsgs1AdyOk2pxUBkPIvAvUqJU1ElOpOWz5wkr8,10002
68
+ iatoolkit/services/user_feedback_service.py,sha256=KbjMjl0CDF7WpPHioJ3sqQVwocjfq_cisrpeqYUqtas,5361
69
+ iatoolkit/services/user_session_context_service.py,sha256=RSv_NxOSTVPA6nFLiZKSIuUWa59cmZWBwiN_TWSljBo,9074
70
+ iatoolkit/static/images/fernando.jpeg,sha256=W68TYMuo5hZVpbP-evwH6Nu4xWFv2bc8pJzSKDoLTeQ,100612
71
+ iatoolkit/static/images/iatoolkit_core.png,sha256=EsmhI8ucevGtzWUPtRDUBfoU-1jqXK7ZmQtrZ-cbJO8,42358
72
+ iatoolkit/static/images/iatoolkit_logo.png,sha256=cGSO-06Y8hCwxsnEGbUBjqFmlSA4pm-OOnNypOEAZVs,7563
73
+ iatoolkit/static/js/chat_feedback_button.js,sha256=P0ANiY5tbaEegi7fYg5Y4xFFWd3Ldf86rDu3zwwZd3A,2425
74
+ iatoolkit/static/js/chat_filepond.js,sha256=mzXafm7a506EpM37KATTK3zvAswO1E0KSUY1vKbwuRc,3163
75
+ iatoolkit/static/js/chat_help_content.js,sha256=VwJ4esnrQ2xCP09IhObJyg-sRIJYMGGiAIRF8fX_lE0,5201
76
+ iatoolkit/static/js/chat_history_button.js,sha256=i9EBAWWW2XyQnAuj1b-c8102EG_gDkQ2ElbA8_Nu0yo,3491
77
+ iatoolkit/static/js/chat_logout_button.js,sha256=Of9H6IbAboSBmeqRaurEVW6_dL752L0UeDcDLNBD5Z0,1335
78
+ iatoolkit/static/js/chat_main.js,sha256=9qlBiiR1Xf1iW0kn6W4gkKtk_9mr4ZT5Ib8-Y0GkXr4,14964
79
+ iatoolkit/static/js/chat_model_selector.js,sha256=EJC3GAZK0AXZaYdyYL4oA0NbxAVwK-bV2EyFbtU01RA,7175
80
+ iatoolkit/static/js/chat_onboarding_button.js,sha256=o1lovwq38bENAzSnCi8c0bUgEszq_C49NdzeaAwXthU,3359
81
+ iatoolkit/static/js/chat_prompt_manager.js,sha256=QYki28CpyM2Chn82dnOP2eH6FObxH8eChGFyUxukv1M,3319
82
+ iatoolkit/static/js/chat_reload_button.js,sha256=MFZgtBCZdNpWnx-L1V1M_dUFx0p8lWs_G0LdXFol3gY,1361
83
+ iatoolkit/static/styles/chat_iatoolkit.css,sha256=cGD9riX-4s978XJJKPcyO6qHq1ngKMzNEhsRpimySVs,15926
84
+ iatoolkit/static/styles/chat_modal.css,sha256=9rwWrzL4Vq7AsdiGb3qczyOUf2PJEgLjSLCkSns8dQA,3031
85
+ iatoolkit/static/styles/chat_public.css,sha256=2SDz0gGyTnTn3BUwD--QX-0qEc3eYKXeTTC6h730UCU,4486
86
+ iatoolkit/static/styles/documents.css,sha256=6Yoprc9JHlKdtqUBEGr4r-JCQsK3Bg1ivoxfJyGuKvg,11893
87
+ iatoolkit/static/styles/landing_page.css,sha256=HVYbo9ZqbqsImvMhGBq2dDFkRiRWOtVaZ0IP9QqDquA,8914
88
+ iatoolkit/static/styles/llm_output.css,sha256=EQjfETdViLjIsyUYp3NvlR1fGICUCK531OsRx43dYvk,3131
89
+ iatoolkit/static/styles/onboarding.css,sha256=fNiqT_MMJ6gGhNzfbSZhJwvcCZ_8gibL-MWZwxyAgAs,3749
90
+ iatoolkit/system_prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
+ iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
92
+ iatoolkit/system_prompts/query_main.prompt,sha256=ZiuiRQRkfZn7Su8SilV57LwCdsIyRASrKxdAWi5h27w,2991
93
+ iatoolkit/system_prompts/sql_rules.prompt,sha256=U1Z5BObI-fgkMatcYfx89q2-YmuRNK6OV6q69p-wAFI,60585
94
+ iatoolkit/templates/_company_header.html,sha256=L1QtrMpqYXALqtinCa3WhG4CrgHKLObl_d-jfQYNjhg,1903
95
+ iatoolkit/templates/_login_widget.html,sha256=qziV70-n7SwC11rL4cU1LenJM83jYvuyw2xSz6OORJA,2063
96
+ iatoolkit/templates/base.html,sha256=sRHUnHaKIycLRKZ_PQOTb88kSBC6kigzxlm60vpXj1I,3434
97
+ iatoolkit/templates/change_password.html,sha256=p0GWZ9gldluYQM8OPSz2Q4CYhU8UJmb-72iz_Sl_6Ho,3485
98
+ iatoolkit/templates/chat.html,sha256=HtmTBbbBPvVHscEymSWqAFjCnxE4hlMckzRgdi-1MXs,15642
99
+ iatoolkit/templates/chat_modals.html,sha256=x0Do7I7X9cfgZFHSAwWreIN55nYPCpZK7PTBxGXjrYY,8501
100
+ iatoolkit/templates/error.html,sha256=4aT6cIYQUILciekAceHEiUuZxcAqkmNPUMnB9CD4BNA,1778
101
+ iatoolkit/templates/forgot_password.html,sha256=XLVMmLJK5SAXmPqIH_OyTlSbu5QTAdekO6ggzfcNup0,2376
102
+ iatoolkit/templates/onboarding_shell.html,sha256=GODHz4JrNyZyf9sPq7GNKMoRrLmKn6kZZQBU4HLgyiU,4604
103
+ iatoolkit/templates/signup.html,sha256=kvV9B8M99zMDj4y9up-K5ChzOznSxzZTX4jPShGRBvI,4316
104
+ iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
105
+ iatoolkit/views/base_login_view.py,sha256=l45msQUrLGxxxZrSb5l7tnTLLQyIoPTu4TgbkHBvVlc,3981
106
+ iatoolkit/views/change_password_view.py,sha256=TXFvvtNrR37yrNAHYzcMSSIkV4-MIzmIpwbPffaJJyE,4957
107
+ iatoolkit/views/chat_view.py,sha256=QNlC0n1hxjWbI3wyLhV6D-U2kJZkIqClNg94iQP4PrA,3534
108
+ iatoolkit/views/embedding_api_view.py,sha256=9n5utihq8zHiG0V2sVCOYQ72wOKa4denqE951gqaJWo,2371
109
+ iatoolkit/views/forgot_password_view.py,sha256=C4eJe9GmGrl6M3bTt_anwuPQib9ouXZtKYp6kB2xBeU,3380
110
+ iatoolkit/views/help_content_api_view.py,sha256=8EUw2iSE6X-Lm2dGlYZxSp-29HzaAGwD3CpL4Otqp5k,2011
111
+ iatoolkit/views/history_api_view.py,sha256=oNYfo-fZbz4sY6VpE_goaCFQyH2k9IX85VhPotqQtGc,2015
112
+ iatoolkit/views/home_view.py,sha256=GaU2-qyTnE8jE1ejdNjHW3azo72X_Awhp1y1Zx9BXRg,2662
113
+ iatoolkit/views/init_context_api_view.py,sha256=axfNno8E1v4dCNuXNkdV1XpDZtypICj48hW3cRyl_eA,2961
114
+ iatoolkit/views/llmquery_api_view.py,sha256=ohlYmFcvhvZL2BTMeCzd7ZPeTBzIPcIZbC9CRWqQM70,2290
115
+ iatoolkit/views/load_company_configuration_api_view.py,sha256=ufX_jrSO7NTUsgNJNrAXxFKmyp2JyNYoplMUm4biULs,1902
116
+ iatoolkit/views/load_document_api_view.py,sha256=RaO4KRz19uSOv3LL7Fn8FJSLzHtRkPAIYRPU-yT1nxQ,2485
117
+ iatoolkit/views/login_view.py,sha256=NKPjR9cCOsw7FhOfXCM32m6veKxRdLhsc0H7DLc5_ug,7517
118
+ iatoolkit/views/logout_api_view.py,sha256=7c0rL5sLTuoRPqQs73wlH_7eb3--S6GLcr7Yu4hNOYU,2035
119
+ iatoolkit/views/profile_api_view.py,sha256=qhlmhyygIs5h-OyNDwq1uGUS8S-GxB2zOYY51Hs5prY,1645
120
+ iatoolkit/views/prompt_api_view.py,sha256=WAv4I6WmGfT1TTZ-lml9LaR2wDsSx9mshYcxFAV_wtk,1255
121
+ iatoolkit/views/rag_api_view.py,sha256=zsEdsSMoxBrX3jGFoKWB7oUm_Sp1x6lh2tAy-g_CUiI,8389
122
+ iatoolkit/views/root_redirect_view.py,sha256=t7tqiyJAPffzIuQVwnfgIw3Bo51qkegyMmBTfChsrJk,833
123
+ iatoolkit/views/signup_view.py,sha256=83jgbAuOAETID88TC8h-wCszkkEaFygCH6tTj7XyZYI,4261
124
+ iatoolkit/views/static_page_view.py,sha256=V0oTybQ5lFo3hp5xOKau-yMO8vK8NCM6zWiwVI8lpBQ,881
125
+ iatoolkit/views/user_feedback_api_view.py,sha256=QOTBtpNqYAmewXDgVAoaIprnVjvf1xM0ExWxSFp3ICI,2098
126
+ iatoolkit/views/users_api_view.py,sha256=hVR6rxLNyhGiXhCIHvttUeSinH071Pyk-2_Fcm-v2TM,1139
127
+ iatoolkit/views/verify_user_view.py,sha256=Uc9P2wiRjZ7pMRTjWUn8Y-p0DFqw_AwNYQsdbAwhbg8,2659
128
+ iatoolkit-1.4.2.dist-info/licenses/LICENSE,sha256=5tOLQdjoCvSXEx_7Lr4bSab3ha4NSwzamvua0fwCXi8,1075
129
+ iatoolkit-1.4.2.dist-info/licenses/LICENSE_COMMUNITY.md,sha256=9lVNcggPNUnleMF3_h3zu9PbNTeaRqB1tHAbiBLQJZU,566
130
+ iatoolkit-1.4.2.dist-info/METADATA,sha256=j6HullcLZAkwHSYnpcXew6VVsL6nzFkyoXwpuSBDy1E,8395
131
+ iatoolkit-1.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
132
+ iatoolkit-1.4.2.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
133
+ iatoolkit-1.4.2.dist-info/RECORD,,
@@ -0,0 +1,15 @@
1
+ # IAToolkit Community Edition License
2
+
3
+ The IAToolkit Community Edition is licensed under the MIT License.
4
+
5
+ This edition includes the full open-source IAToolkit Core, with the following usage scope:
6
+
7
+ - Support for **one (1) Company**
8
+ - Unlimited Tools within that Company
9
+ - SQL integration
10
+ - Basic RAG (standard retrieval & embeddings)
11
+ - All Components of the open-source Intelligence Layer and Interfaces
12
+
13
+ No additional technical limits apply beyond the single-Company constraint.
14
+
15
+ This edition is designed for learning, prototyping, and single-business deployments.
@@ -1,52 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from injector import inject
7
- from datetime import datetime
8
- from iatoolkit.repositories.models import Task, TaskStatus, TaskType
9
- from iatoolkit.repositories.database_manager import DatabaseManager
10
- from sqlalchemy import or_
11
-
12
-
13
- class TaskRepo:
14
- @inject
15
- def __init__(self, db_manager: DatabaseManager):
16
- self.session = db_manager.get_session()
17
-
18
- def create_task(self, new_task: Task) -> Task:
19
- self.session.add(new_task)
20
- self.session.commit()
21
- return new_task
22
-
23
- def update_task(self, task: Task) -> Task:
24
- self.session.commit()
25
- return task
26
-
27
- def get_task_by_id(self, task_id: int):
28
- return self.session.query(Task).filter_by(id=task_id).first()
29
-
30
- def create_or_update_task_type(self, new_task_type: TaskType):
31
- task_type = self.session.query(TaskType).filter_by(name=new_task_type.name).first()
32
- if task_type:
33
- task_type.prompt_template = new_task_type.prompt_template
34
- task_type.template_args = new_task_type.template_args
35
- else:
36
- self.session.add(new_task_type)
37
- task_type = new_task_type
38
- self.session.commit()
39
- return task_type
40
-
41
- def get_task_type(self, name: str):
42
- task_type = self.session.query(TaskType).filter_by(name=name).first()
43
- return task_type
44
-
45
- def get_pending_tasks(self, company_id: int):
46
- now = datetime.now()
47
- tasks = self.session.query(Task).filter(
48
- Task.company_id == company_id,
49
- Task.status == TaskStatus.pendiente,
50
- or_(Task.execute_at == None, Task.execute_at <= now)
51
- ).all()
52
- return tasks
@@ -1,37 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from injector import inject
7
- from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
8
- from iatoolkit.repositories.profile_repo import ProfileRepo
9
- from iatoolkit.services.i18n_service import I18nService
10
-
11
-
12
- class HistoryService:
13
- @inject
14
- def __init__(self, llm_query_repo: LLMQueryRepo,
15
- profile_repo: ProfileRepo,
16
- i18n_service: I18nService):
17
- self.llm_query_repo = llm_query_repo
18
- self.profile_repo = profile_repo
19
- self.i18n_service = i18n_service
20
-
21
- def get_history(self,
22
- company_short_name: str,
23
- user_identifier: str) -> dict:
24
- try:
25
- company = self.profile_repo.get_company_by_short_name(company_short_name)
26
- if not company:
27
- return {"error": self.i18n_service.t('errors.company_not_found', company_short_name=company_short_name)}
28
-
29
- history = self.llm_query_repo.get_history(company, user_identifier)
30
- if not history:
31
- return {'message': 'empty history', 'history': []}
32
-
33
- history_list = [query.to_dict() for query in history]
34
- return {'message': 'history loaded ok', 'history': history_list}
35
-
36
- except Exception as e:
37
- return {'error': str(e)}
@@ -1,55 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from iatoolkit.repositories.vs_repo import VSRepo
7
- from iatoolkit.repositories.document_repo import DocumentRepo
8
- from iatoolkit.repositories.profile_repo import ProfileRepo
9
- from iatoolkit.repositories.models import Company
10
- from injector import inject
11
-
12
-
13
- class SearchService:
14
- @inject
15
- def __init__(self,
16
- profile_repo: ProfileRepo,
17
- doc_repo: DocumentRepo,
18
- vs_repo: VSRepo):
19
- self.profile_repo = profile_repo
20
- self.vs_repo = vs_repo
21
- self.doc_repo = doc_repo
22
-
23
- def search(self, company_short_name: str, query: str, metadata_filter: dict = None) -> str:
24
- """
25
- Performs a semantic search for a given query within a company's documents.
26
-
27
- This method queries the vector store for relevant documents based on the
28
- provided query text. It then constructs a formatted string containing the
29
- content of the retrieved documents, which can be used as context for an LLM.
30
-
31
- Args:
32
- company_short_name: The company to search within.
33
- query: The text query to search for.
34
- metadata_filter: An optional dictionary to filter documents by their metadata.
35
-
36
- Returns:
37
- A string containing the concatenated content of the found documents,
38
- formatted to be used as a context.
39
- """
40
- company = self.profile_repo.get_company_by_short_name(company_short_name)
41
- if not company:
42
- return f"error: company {company_short_name} not found"
43
-
44
- document_list = self.vs_repo.query(company_short_name=company_short_name,
45
- query_text=query,
46
- metadata_filter=metadata_filter)
47
-
48
- search_context = ''
49
- for doc in document_list:
50
- search_context += f'documento "{doc.filename}"'
51
- if doc.meta and 'document_type' in doc.meta:
52
- search_context += f' tipo: {doc.meta.get('document_type', '')}'
53
- search_context += f': {doc.content}\n'
54
-
55
- return search_context
@@ -1,188 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from injector import inject
7
- from iatoolkit.repositories.models import Task, TaskStatus
8
- from iatoolkit.services.query_service import QueryService
9
- from iatoolkit.repositories.tasks_repo import TaskRepo
10
- from iatoolkit.repositories.profile_repo import ProfileRepo
11
- from iatoolkit.infra.call_service import CallServiceClient
12
- from iatoolkit.common.exceptions import IAToolkitException
13
- from datetime import datetime
14
- from werkzeug.utils import secure_filename
15
-
16
-
17
- class TaskService:
18
- @inject
19
- def __init__(self,
20
- task_repo: TaskRepo,
21
- query_service: QueryService,
22
- profile_repo: ProfileRepo,
23
- call_service: CallServiceClient):
24
- self.task_repo = task_repo
25
- self.query_service = query_service
26
- self.profile_repo = profile_repo
27
- self.call_service = call_service
28
-
29
- def create_task(self,
30
- company_short_name: str,
31
- task_type_name: str,
32
- client_data: dict,
33
- company_task_id: int= 0,
34
- execute_at: datetime = None,
35
- files: list = []
36
- ) -> Task:
37
-
38
- # validate company
39
- company = self.profile_repo.get_company_by_short_name(company_short_name)
40
- if not company:
41
- raise IAToolkitException(IAToolkitException.ErrorType.INVALID_NAME,
42
- f'No existe la empresa: {company_short_name}')
43
-
44
- # validate task_type
45
- task_type = self.task_repo.get_task_type(task_type_name)
46
- if not task_type:
47
- raise IAToolkitException(IAToolkitException.ErrorType.INVALID_NAME,
48
- f'No existe el task_type: {task_type_name}')
49
-
50
- # process the task files
51
- task_files = self.get_task_files(files)
52
-
53
- # create Task object
54
- new_task = Task(
55
- company_id=company.id,
56
- task_type_id=task_type.id,
57
- company_task_id=company_task_id,
58
- client_data=client_data,
59
- execute_at=execute_at,
60
- files=task_files
61
- )
62
- new_task = self.task_repo.create_task(new_task)
63
- if execute_at and execute_at > datetime.now():
64
- self.execute_task(new_task)
65
-
66
- return new_task
67
-
68
- def review_task(self, task_id: int, review_user: str, approved: bool, comment: str):
69
- # get the task
70
- task = self.task_repo.get_task_by_id(task_id)
71
- if not task:
72
- raise IAToolkitException(IAToolkitException.ErrorType.TASK_NOT_FOUND,
73
- f'No existe la tarea: {task_id}')
74
-
75
- if task.status != TaskStatus.ejecutado:
76
- raise IAToolkitException(IAToolkitException.ErrorType.INVALID_STATE,
77
- f'La tarea debe estar en estado ejecutada: {task_id}')
78
-
79
- # update the task
80
- task.approved = approved
81
- task.status = TaskStatus.aprobada if approved else TaskStatus.rechazada
82
- task.review_user = review_user
83
- task.comment = comment
84
- task.review_date = datetime.now()
85
- self.task_repo.update_task(task)
86
- return task
87
-
88
- def execute_task(self, task: Task):
89
- # in this case do nothing
90
- if (task.status != TaskStatus.pendiente or
91
- (task.execute_at and task.execute_at > datetime.now())):
92
- return task
93
-
94
- # get the Task template prompt
95
- if not task.task_type.prompt_template:
96
- raise IAToolkitException(IAToolkitException.ErrorType.INVALID_NAME,
97
- f'No existe el prompt_template para el task_type: {task.task_type.name}')
98
-
99
- template_dir = f'companies/{task.company.short_name}/prompts'
100
-
101
- # call the IA
102
- response = self.query_service.llm_query(
103
- task=task,
104
- user_identifier='task-monitor',
105
- company_short_name=task.company.short_name,
106
- prompt_name=task.task_type.name,
107
- client_data=task.client_data,
108
- files=task.files
109
- )
110
- if 'error' in response:
111
- raise IAToolkitException(IAToolkitException.ErrorType.LLM_ERROR,
112
- response.get('error'))
113
-
114
- # update the Task with the response from llm_query
115
- task.llm_query_id = response.get('query_id', 0)
116
-
117
- # update task status
118
- if not response.get('valid_response'):
119
- task.status = TaskStatus.fallida
120
- else:
121
- task.status = TaskStatus.ejecutado
122
- self.task_repo.update_task(task)
123
-
124
- # call the callback url
125
- if task.callback_url:
126
- self.notify_callback(task, response)
127
-
128
- return task
129
-
130
- def notify_callback(self, task: Task, response: dict):
131
- response_data = {
132
- 'task_id': task.id,
133
- 'company_task_id': task.company_task_id,
134
- 'status': task.status.name,
135
- 'answer': response.get('answer', ''),
136
- 'additional_data': response.get('additional_data', {}),
137
- 'client_data': task.client_data,
138
- }
139
- try:
140
- response, status_code = self.call_service.post(task.callback_url, response_data)
141
- except Exception as e:
142
- raise IAToolkitException(
143
- IAToolkitException.ErrorType.REQUEST_ERROR,
144
- f"Error al notificar callback {task.callback_url}: {str(e)}"
145
- )
146
-
147
- def get_task_files(self, uploaded_files):
148
- files_info = []
149
-
150
- for file in uploaded_files:
151
- filename = secure_filename(file.filename)
152
-
153
- try:
154
- # the file is already in base64
155
- file_content = file.read().decode('utf-8')
156
- except Exception as e:
157
- raise IAToolkitException(
158
- IAToolkitException.ErrorType.FILE_IO_ERROR,
159
- f"Error al extraer el contenido del archivo {filename}: {str(e)}"
160
- )
161
-
162
- files_info.append({
163
- 'filename': filename,
164
- 'content': file_content, # file in base64
165
- 'type': file.content_type
166
- })
167
-
168
- return files_info
169
-
170
- def trigger_pending_tasks(self, company_short_name: str):
171
- n_tasks = 0
172
- try:
173
- company = self.profile_repo.get_company_by_short_name(company_short_name)
174
- pending_tasks = self.task_repo.get_pending_tasks(company.id)
175
- for task in pending_tasks:
176
- self.execute_task(task)
177
- n_tasks += 1
178
- except Exception as e:
179
- raise IAToolkitException(
180
- IAToolkitException.ErrorType.TASK_EXECUTION_ERROR,
181
- f"Error ejecutando tareas pendientes: {str(e)}"
182
- )
183
-
184
- return {'message': f'{n_tasks} tareas ejecutadas.'}
185
-
186
-
187
-
188
-
@@ -1,13 +0,0 @@
1
- <!-- templates/about.html -->
2
- <!DOCTYPE html>
3
- <html lang="en">
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>About</title>
8
- </head>
9
- <body>
10
- <h1>AI Toolkit</h1>
11
- <p>This is a static page in Flask.</p>
12
- </body>
13
- </html>
@@ -1,145 +0,0 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}IAToolkit - Framework de IA{% endblock %}
4
-
5
- {% block styles %}
6
- {# Enlazamos la hoja de estilos del website y los iconos de Bootstrap #}
7
- <link rel="stylesheet" href="{{ url_for('static', filename='styles/landing_page.css') }}">
8
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
9
- {% endblock %}
10
-
11
-
12
- {% block content %}
13
- <div class="container mt-4">
14
-
15
- <!-- 1. Encabezado con una clase 100% propia y única -->
16
- <header class="website-header container">
17
- <span class="website-brand">IAToolkit</span>
18
- </header>
19
-
20
- <!-- 2. Sección Principal (Hero) -->
21
- <section class="hero-section">
22
- <div class="container">
23
- <div class="row align-items-center g-5 py-5">
24
- <div class="col-lg-7">
25
- <h1 class="hero-title gradient-text">Framework de IA Open Source</h1>
26
- <ul class="hero-bullets mt-4">
27
- <li><i class="bi bi-hdd-stack"></i>Integra tus bases de datos SQL y documentos para dar contexto real a tus asistentes.</li>
28
- <li><i class="bi bi-code-slash"></i>Crea un repositorio de prompts validados por tu equipo para estandarizar y acelerar las tareas de IA.</li>
29
- <li><i class="bi bi-shield-lock"></i> Monta la plataforma en tu propia infraestructura con control total sobre el LLM, garantizando la privacidad de los datos.</li> </ul>
30
- </div>
31
- <div class="col-lg-5">
32
- <div class="border rounded-3 p-4 p-md-5 shadow-sm bg-light">
33
- <h3 class="fw-bold text-center mb-3">Prueba la Plataforma</h3>
34
- <p class="text-muted mb-4">
35
- Descubre nuestra demo interactiva, configurada con datos de una empresa de muestra. Explora las funcionalidades de la plataforma en un entorno práctico.<br>
36
- </p>
37
- <div class="d-grid">
38
- {# Este botón usa la clase .btn-primary, que es estilizada por .hero-section .btn-primary en el CSS #}
39
- <a href="{{ url_for('home', company_short_name='sample_company') }}"
40
- target="_blank"
41
- rel="noopener noreferrer"
42
- class="btn btn-primary btn-lg fw-bold">
43
- Acceder
44
- </a>
45
- </div>
46
- </div>
47
- </div>
48
- </div>
49
- </div>
50
- </section>
51
-
52
- <!-- 3. Sección de Características -->
53
- <section class="features-section">
54
- <div class="container">
55
- <div class="row g-4">
56
- <div class="col-lg-4 d-flex align-items-stretch">
57
- <div class="opensource-box">
58
- <div>
59
- <div class="opensource-icon"><i class="bi bi-github"></i></div>
60
- <h3>100% Open Source</h3>
61
- <p>Construido en Python, IAToolkit te da control total. Audita el código, adáptalo y contribuye a una comunidad en crecimiento.</p>
62
- </div>
63
- <a href="https://github.com/flibedinsky/iatoolkit" target="_blank" class="btn btn-light mt-auto">
64
- <i class="bi bi-github me-2"></i>Ir a GitHub
65
- {% if iatoolkit_version %}
66
- <span class="badge bg-dark ms-2">{{ iatoolkit_version }}</span>
67
- {% endif %}
68
- </a>
69
- </div>
70
- </div>
71
- <div class="col-lg-4 d-flex align-items-stretch">
72
- <div class="feature-item">
73
- <div class="feature-icon"><i class="bi bi-hdd-stack"></i></div>
74
- <h3>Conecta tus Datos</h3>
75
- <p>Integra tus bases de datos SQL, documentos (PDFs, TXT) y otros sistemas para que el asistente tenga un contexto real de tu negocio.</p>
76
- </div>
77
- </div>
78
- <div class="col-lg-4 d-flex align-items-stretch">
79
- <div class="feature-item">
80
- <div class="feature-icon"><i class="bi bi-gem"></i></div>
81
- <h3>Multi-LLM</h3>
82
- <p>No te ates a un solo proveedor. IAToolkit está diseñado para funcionar con diferentes modelos, incluyendo Gemini y OpenAI (GPT).</p>
83
- </div>
84
- </div>
85
- </div>
86
- <div class="row g-4 mt-4">
87
- <div class="col-lg-4 d-flex align-items-stretch">
88
- <div class="feature-item">
89
- <div class="feature-icon"><i class="bi bi-magic"></i></div>
90
- <h3>Prompt Manager</h3>
91
- <p>Crea, gestiona y comparte una librería de prompts personalizados para tu empresa, optimizando las tareas repetitivas.</p>
92
- </div>
93
- </div>
94
- <div class="col-lg-4 d-flex align-items-stretch">
95
- <div class="feature-item">
96
- <div class="feature-icon"><i class="bi bi-palette"></i></div>
97
- <h3>100% Personalizable</h3>
98
- <p>Adapta cada aspecto, desde la apariencia visual hasta las capacidades y herramientas del asistente, para que se alinee con la identidad de tu marca.</p>
99
- </div>
100
- </div>
101
- <div class="col-lg-4 d-flex align-items-stretch">
102
- <div class="feature-item">
103
- <div class="feature-icon"><i class="bi bi-shield-lock"></i></div>
104
- <h3>Privacidad Primero</h3>
105
- <p>Despliega IAToolkit en tus propios servidores. Tus datos y consultas nunca son compartidos con terceros, garantizando la máxima confidencialidad.</p>
106
- </div>
107
- </div>
108
- </div>
109
- </div>
110
- </section>
111
-
112
- <!-- 3.5 Sobre el Autor -->
113
- <section class="author-section py-5">
114
- <div class="container">
115
- <div class="author-card p-4">
116
- <div class="row align-items-center g-4">
117
- <div class="col-md-2 text-center">
118
- <img src="{{ url_for('static', filename='images/fernando.jpeg') }}" alt="Foto de Fernando Libedinsky" class="img-fluid rounded-circle" style="max-width: 120px;">
119
- </div>
120
- <div class="col-md-10">
121
- <div class="d-flex flex-wrap align-items-center mb-2">
122
- <h5 class="mb-0 me-3">Sobre el autor</h5>
123
- <a href="https://www.linkedin.com/in/fernandolibedinsky" target="_blank" rel="noopener" class="author-linkedin ms-auto">
124
- <i class="bi bi-linkedin me-1"></i> LinkedIn
125
- </a>
126
- </div>
127
- <p class="author-bio mb-0">
128
- Soy <strong>Fernando Libedinsky</strong>, ingeniero de software y creador de <strong>IAToolkit</strong>.
129
- <br>Tras una extensa trayectoria en el desarrollo de software, sigo movido por la misma curiosidad que me llevó a programar por primera vez: aprender, explorar y construir cosas nuevas.
130
- <br>IAToolkit es la continuación de ese impulso, una plataforma creada para conectar rapidamente empresas con la IA.
131
- </p>
132
- </div>
133
- </div>
134
- </div>
135
- </div>
136
- </section>
137
-
138
- <!-- 4. Footer -->
139
- <footer class="landing-footer">
140
- <div class="container">
141
- &copy; 2024 IAToolkit - Proyecto Open Source
142
- </div>
143
- </footer>
144
- </div>
145
- {% endblock %}