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
@@ -1,45 +0,0 @@
1
- {% extends "base.html" %}
2
-
3
- {% block title %}Login Test - {{ branding.name }}{% endblock %}
4
- {% block styles %}
5
- <style>
6
- {{ branding.css_variables | safe }}
7
- </style>
8
- <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_public.css') }}">
9
- {% endblock %}
10
-
11
- {% block content %}
12
- <div class="container mt-4">
13
-
14
- {% include '_company_header.html' %}
15
-
16
- <div class="container-fluid">
17
- <div class="row flex-fill mt-5 justify-content-center">
18
- <div class="col-12 col-lg-6">
19
- <div class="branded-form-container">
20
- <h4 class="branded-form-title">
21
- Login Externo para {{ company_short_name }}
22
- </h4>
23
- <div class="text-center mb-4">
24
- <p class="text-muted widget-intro-text">
25
- Este formulario simula el inicio de una sesión externa. Al enviar, serás redirigido a la URL de login final.
26
- </p>
27
- </div>
28
-
29
- <!-- Formulario HTML estándar que hace un POST a la misma URL -->
30
- <form method="POST" action="">
31
- <div class="mb-3">
32
- <label for="external_user_id" class="form-label d-block">External user ID</label>
33
- <input type="text" id="external_user_id" name="external_user_id" class="form-control" required>
34
- </div>
35
- <button type="submit" class="btn btn-branded-primary">
36
- Redirigir a External Login
37
- </button>
38
- </form>
39
- </div>
40
- </div>
41
- </div>
42
- </div>
43
- </div>
44
- {% endblock %}
45
-
@@ -1,73 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- import os
7
- import logging
8
- from flask import request, jsonify, url_for
9
- from iatoolkit.views.base_login_view import BaseLoginView
10
-
11
-
12
- class ExternalLoginView(BaseLoginView):
13
- """
14
- Handles login for external users via API.
15
- Authenticates and then delegates the path decision (fast/slow) to the base class.
16
- """
17
- def post(self, company_short_name: str):
18
- # Authenticate the API call.
19
- auth_result = self.auth_service.verify()
20
- if not auth_result.get("success"):
21
- return jsonify(auth_result), auth_result.get("status_code")
22
-
23
- company = self.profile_service.get_company_by_short_name(company_short_name)
24
- if not company:
25
- return jsonify({"error": "Empresa no encontrada"}), 404
26
-
27
- user_identifier = auth_result.get('user_identifier')
28
-
29
- # 2. Create the external user session.
30
- self.profile_service.create_external_user_profile_context(company, user_identifier)
31
-
32
- # 3. create a redeem_token for create session at the end of the process
33
- redeem_token = self.jwt_service.generate_chat_jwt(
34
- company_short_name=company_short_name,
35
- user_identifier=user_identifier,
36
- expires_delta_seconds=300
37
- )
38
-
39
- if not redeem_token:
40
- return jsonify({"error": "Error al generar el redeem_token para login externo."}), 403
41
-
42
- # 4. define URL to call when slow path is finished
43
- target_url = url_for('finalize_with_token',
44
- company_short_name=company_short_name,
45
- token=redeem_token,
46
- _external=True)
47
-
48
- # 5. Delegate the path decision to the centralized logic.
49
- try:
50
- return self._handle_login_path(company_short_name, user_identifier, target_url, redeem_token)
51
- except Exception as e:
52
- logging.exception(f"Error processing external login path for {company_short_name}/{user_identifier}: {e}")
53
- return jsonify({"error": f"Internal server error while starting chat. {str(e)}"}), 500
54
-
55
-
56
- class RedeemTokenApiView(BaseLoginView):
57
- # this endpoint is only used ONLY by chat_main.js to redeem a chat token
58
- def post(self, company_short_name: str):
59
- data = request.get_json()
60
- if not data or 'token' not in data:
61
- return jsonify({"error": "Falta token de validación"}), 400
62
-
63
- # get the token and validate with auth service
64
- token = data.get('token')
65
- redeem_result = self.auth_service.redeem_token_for_session(
66
- company_short_name=company_short_name,
67
- token=token
68
- )
69
-
70
- if not redeem_result['success']:
71
- return {"error": redeem_result['error']}, 401
72
-
73
- return {"status": "ok"}, 200
@@ -1,14 +0,0 @@
1
- # iatoolkit/views/index_view.py
2
-
3
- from flask import render_template, session
4
- from flask.views import MethodView
5
-
6
-
7
- class IndexView(MethodView):
8
- """
9
- Handles the rendering of the generic landing page, which no longer depends
10
- on a specific company.
11
- """
12
-
13
- def get(self):
14
- return render_template('index.html')
@@ -1,93 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- import requests
7
- import json
8
- import os
9
- from flask.views import MethodView
10
- from flask import render_template, request, Response
11
- from injector import inject
12
- from iatoolkit.services.profile_service import ProfileService
13
- from iatoolkit.services.branding_service import BrandingService
14
-
15
-
16
- class LoginSimulationView(MethodView):
17
- @inject
18
- def __init__(self,
19
- profile_service: ProfileService,
20
- branding_service: BrandingService):
21
- self.profile_service = profile_service
22
- self.branding_service = branding_service
23
-
24
-
25
- def get(self, company_short_name: str = None):
26
- company = self.profile_service.get_company_by_short_name(company_short_name)
27
- if not company:
28
- return render_template('error.html',
29
- company_short_name=company_short_name,
30
- message="Empresa no encontrada"), 404
31
-
32
- branding_data = self.branding_service.get_company_branding(company_short_name)
33
-
34
- return render_template('login_simulation.html',
35
- branding=branding_data,
36
- company_short_name=company_short_name
37
- )
38
-
39
- def post(self, company_short_name: str):
40
- """
41
- Recibe el POST del formulario y actúa como un proxy servidor-a-servidor.
42
- Llama al endpoint 'external_login' y devuelve su respuesta (HTML y headers).
43
- """
44
- api_key = os.getenv("IATOOLKIT_API_KEY")
45
- # Obtenemos la URL base de la petición actual para construir la URL interna
46
- base_url = request.host_url.rstrip('/')
47
-
48
- # 1. Obtener el user_identifier del formulario
49
- user_identifier = request.form.get('external_user_id')
50
-
51
- if not user_identifier:
52
- return Response("Error: El campo 'external_user_id' es requerido.", status=400)
53
-
54
- # 2. Preparar la llamada a la API real de external_login
55
- target_url = f"{base_url}/{company_short_name}/external_login"
56
- headers = {
57
- 'Content-Type': 'application/json',
58
- 'Authorization': f'Bearer {api_key}'
59
- }
60
- # El payload debe ser un diccionario que se convertirá a JSON
61
- payload = {'user_identifier': user_identifier}
62
-
63
- try:
64
- # 3. Llamada POST segura desde este servidor al endpoint de IAToolkit
65
- internal_response = requests.post(
66
- target_url,
67
- headers=headers,
68
- data=json.dumps(payload),
69
- timeout=120,
70
- stream=True # Usamos stream para manejar la respuesta eficientemente
71
- )
72
- internal_response.raise_for_status()
73
-
74
- # 4. Creamos una nueva Response de Flask para el navegador del usuario.
75
- user_response = Response(
76
- internal_response.iter_content(chunk_size=1024),
77
- status=internal_response.status_code
78
- )
79
-
80
- # 5. Copiamos TODAS las cabeceras de la respuesta interna a la respuesta final.
81
- # Esto es CRUCIAL para que las cookies ('Set-Cookie') lleguen al navegador.
82
- for key, value in internal_response.headers.items():
83
- # Excluimos cabeceras que no debemos pasar (controladas por el servidor WSGI)
84
- if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding', 'connection']:
85
- user_response.headers[key] = value
86
-
87
- return user_response
88
-
89
- except requests.exceptions.HTTPError as e:
90
- error_text = f"Error en la llamada interna a la API: {e.response.status_code}. Respuesta: {e.response.text}"
91
- return Response(error_text, status=e.response.status_code, mimetype='text/plain')
92
- except requests.exceptions.RequestException as e:
93
- return Response(f'Error de conexión con el servicio de IA: {str(e)}', status=502, mimetype='text/plain')
@@ -1,72 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from flask.views import MethodView
7
- from flask import request, jsonify
8
- from iatoolkit.services.tasks_service import TaskService
9
- from iatoolkit.repositories.profile_repo import ProfileRepo
10
- from iatoolkit.services.auth_service import AuthService
11
- from injector import inject
12
- from datetime import datetime
13
- import logging
14
- from typing import Optional
15
-
16
-
17
- class TaskApiView(MethodView):
18
- @inject
19
- def __init__(self,
20
- auth_service: AuthService,
21
- task_service: TaskService,
22
- profile_repo: ProfileRepo):
23
- self.auth_service = auth_service
24
- self.task_service = task_service
25
- self.profile_repo = profile_repo
26
-
27
- def post(self):
28
- try:
29
- auth_result = self.auth_service.verify(anonymous=True)
30
- if not auth_result.get("success"):
31
- return jsonify(auth_result), auth_result.get("status_code")
32
-
33
- req_data = request.get_json()
34
- files = request.files.getlist('files')
35
-
36
- required_fields = ['company', 'task_type', 'client_data']
37
- for field in required_fields:
38
- if field not in req_data:
39
- return jsonify({"error": f"El campo {field} es requerido"}), 400
40
-
41
- company_short_name = req_data.get('company', '')
42
- task_type = req_data.get('task_type', '')
43
- client_data = req_data.get('client_data', {})
44
- company_task_id = req_data.get('company_task_id', 0)
45
- execute_at = req_data.get('execute_at', None)
46
-
47
- # validate date format is parameter is present
48
- if execute_at:
49
- try:
50
- # date in iso format
51
- execute_at = datetime.fromisoformat(execute_at)
52
- except ValueError:
53
- return jsonify({
54
- "error": "El formato de execute_at debe ser YYYY-MM-DD HH:MM:SS"
55
- }), 400
56
-
57
- new_task = self.task_service.create_task(
58
- company_short_name=company_short_name,
59
- task_type_name=task_type,
60
- client_data=client_data,
61
- company_task_id=company_task_id,
62
- execute_at=execute_at,
63
- files=files)
64
-
65
- return jsonify({
66
- "task_id": new_task.id,
67
- "status": new_task.status.name
68
- }), 201
69
-
70
- except Exception as e:
71
- logging.exception("Error al crear la tarea: %s", str(e))
72
- return jsonify({"error": str(e)}), 500
@@ -1,55 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from flask.views import MethodView
7
- from flask import request, jsonify
8
- from iatoolkit.services.tasks_service import TaskService
9
- from iatoolkit.repositories.profile_repo import ProfileRepo
10
- from iatoolkit.services.auth_service import AuthService
11
- from injector import inject
12
- import logging
13
- from typing import Optional
14
-
15
-
16
- class TaskReviewApiView(MethodView):
17
- @inject
18
- def __init__(self,
19
- auth_service: AuthService,
20
- task_service: TaskService,
21
- profile_repo: ProfileRepo):
22
- self.auth_service = auth_service
23
- self.task_service = task_service
24
- self.profile_repo = profile_repo
25
-
26
- def post(self, task_id: int):
27
- auth_result = self.auth_service.verify(anonymous=True)
28
- if not auth_result.get("success"):
29
- return jsonify(auth_result), auth_result.get("status_code")
30
-
31
- try:
32
- req_data = request.get_json()
33
- required_fields = ['review_user', 'approved']
34
- for field in required_fields:
35
- if field not in req_data:
36
- return jsonify({"error": f"El campo {field} es requerido"}), 400
37
-
38
- review_user = req_data.get('review_user', '')
39
- approved = req_data.get('approved', False)
40
- comment = req_data.get('comment', '')
41
-
42
- new_task = self.task_service.review_task(
43
- task_id=task_id,
44
- review_user=review_user,
45
- approved=approved,
46
- comment=comment)
47
-
48
- return jsonify({
49
- "task_id": new_task.id,
50
- "status": new_task.status.name
51
- }), 200
52
-
53
- except Exception as e:
54
- logging.exception("Error al revisar la tarea: %s", str(e))
55
- return jsonify({"error": str(e)}), 500
@@ -1,276 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: iatoolkit
3
- Version: 0.71.4
4
- Summary: IAToolkit
5
- Author: Fernando Libedinsky
6
- License-Expression: MIT
7
- Requires-Python: >=3.12
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: aiohappyeyeballs==2.4.4
11
- Requires-Dist: aiohttp==3.11.9
12
- Requires-Dist: aiosignal==1.3.1
13
- Requires-Dist: annotated-types==0.7.0
14
- Requires-Dist: anyio==4.6.2.post1
15
- Requires-Dist: asgiref==3.8.1
16
- Requires-Dist: async-timeout==4.0.3
17
- Requires-Dist: attrs==24.3.0
18
- Requires-Dist: backoff==2.2.1
19
- Requires-Dist: bcrypt==4.2.1
20
- Requires-Dist: beautifulsoup4==4.12.3
21
- Requires-Dist: blinker==1.9.0
22
- Requires-Dist: boto3==1.36.22
23
- Requires-Dist: botocore==1.36.22
24
- Requires-Dist: build==1.2.2.post1
25
- Requires-Dist: cachelib==0.13.0
26
- Requires-Dist: cachetools==5.5.0
27
- Requires-Dist: certifi==2024.12.14
28
- Requires-Dist: cffi==1.17.1
29
- Requires-Dist: charset-normalizer==3.4.0
30
- Requires-Dist: click==8.1.8
31
- Requires-Dist: coloredlogs==15.0.1
32
- Requires-Dist: contourpy==1.3.3
33
- Requires-Dist: coverage==7.6.10
34
- Requires-Dist: cryptography==44.0.3
35
- Requires-Dist: cycler==0.12.1
36
- Requires-Dist: dataclasses-json==0.6.7
37
- Requires-Dist: Deprecated==1.2.15
38
- Requires-Dist: distro==1.9.0
39
- Requires-Dist: durationpy==0.9
40
- Requires-Dist: ecs-logging==2.2.0
41
- Requires-Dist: elastic-apm==6.23.0
42
- Requires-Dist: et_xmlfile==2.0.0
43
- Requires-Dist: exceptiongroup==1.2.2
44
- Requires-Dist: fastapi==0.115.6
45
- Requires-Dist: filelock==3.16.1
46
- Requires-Dist: Flask==3.1.0
47
- Requires-Dist: Flask-Bcrypt==1.0.1
48
- Requires-Dist: flask-cors==6.0.0
49
- Requires-Dist: Flask-Injector==0.15.0
50
- Requires-Dist: Flask-Session==0.8.0
51
- Requires-Dist: flatbuffers==24.3.25
52
- Requires-Dist: fonttools==4.59.2
53
- Requires-Dist: frozenlist==1.5.0
54
- Requires-Dist: fsspec==2024.10.0
55
- Requires-Dist: google-ai-generativelanguage==0.6.15
56
- Requires-Dist: google-api-core==2.24.1
57
- Requires-Dist: google-api-python-client==2.161.0
58
- Requires-Dist: google-auth==2.37.0
59
- Requires-Dist: google-auth-httplib2==0.2.0
60
- Requires-Dist: google-auth-oauthlib==1.2.1
61
- Requires-Dist: google-cloud-core==2.4.1
62
- Requires-Dist: google-cloud-storage==3.0.0
63
- Requires-Dist: google-crc32c==1.6.0
64
- Requires-Dist: google-generativeai==0.8.5
65
- Requires-Dist: google-resumable-media==2.7.2
66
- Requires-Dist: googleapis-common-protos==1.66.0
67
- Requires-Dist: grpcio==1.74.0
68
- Requires-Dist: grpcio-status==1.71.2
69
- Requires-Dist: gunicorn==23.0.0
70
- Requires-Dist: h11==0.14.0
71
- Requires-Dist: httpcore==1.0.7
72
- Requires-Dist: httplib2==0.22.0
73
- Requires-Dist: httptools==0.6.4
74
- Requires-Dist: httpx==0.28.0
75
- Requires-Dist: httpx-sse==0.4.0
76
- Requires-Dist: huggingface-hub==0.31.4
77
- Requires-Dist: humanfriendly==10.0
78
- Requires-Dist: idna==3.10
79
- Requires-Dist: importlib_metadata==8.5.0
80
- Requires-Dist: importlib_resources==6.4.5
81
- Requires-Dist: iniconfig==2.0.0
82
- Requires-Dist: injector==0.22.0
83
- Requires-Dist: itsdangerous==2.2.0
84
- Requires-Dist: Jinja2==3.1.5
85
- Requires-Dist: jiter==0.8.0
86
- Requires-Dist: jmespath==1.0.1
87
- Requires-Dist: joblib==1.4.2
88
- Requires-Dist: jsonpatch==1.33
89
- Requires-Dist: jsonpointer==3.0.0
90
- Requires-Dist: kiwisolver==1.4.9
91
- Requires-Dist: kubernetes==31.0.0
92
- Requires-Dist: langchain==0.3.19
93
- Requires-Dist: langchain-core==0.3.35
94
- Requires-Dist: langchain-text-splitters==0.3.6
95
- Requires-Dist: langsmith==0.3.8
96
- Requires-Dist: lxml==5.3.0
97
- Requires-Dist: markdown-it-py==3.0.0
98
- Requires-Dist: markdown2==2.5.3
99
- Requires-Dist: MarkupSafe==3.0.2
100
- Requires-Dist: marshmallow==3.23.1
101
- Requires-Dist: matplotlib==3.10.6
102
- Requires-Dist: mdurl==0.1.2
103
- Requires-Dist: mmh3==5.0.1
104
- Requires-Dist: monotonic==1.6
105
- Requires-Dist: mpmath==1.3.0
106
- Requires-Dist: msgspec==0.19.0
107
- Requires-Dist: multidict==6.1.0
108
- Requires-Dist: mypy-extensions==1.0.0
109
- Requires-Dist: narwhals==2.3.0
110
- Requires-Dist: networkx==3.4.2
111
- Requires-Dist: numpy==2.2.3
112
- Requires-Dist: oauth2client==4.1.3
113
- Requires-Dist: oauthlib==3.2.2
114
- Requires-Dist: onnxruntime==1.19.2
115
- Requires-Dist: openai==1.79.0
116
- Requires-Dist: openpyxl==3.1.5
117
- Requires-Dist: opentelemetry-api==1.28.2
118
- Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.28.2
119
- Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.28.2
120
- Requires-Dist: opentelemetry-instrumentation==0.49b2
121
- Requires-Dist: opentelemetry-instrumentation-asgi==0.49b2
122
- Requires-Dist: opentelemetry-instrumentation-fastapi==0.49b2
123
- Requires-Dist: opentelemetry-proto==1.28.2
124
- Requires-Dist: opentelemetry-sdk==1.28.2
125
- Requires-Dist: opentelemetry-semantic-conventions==0.49b2
126
- Requires-Dist: opentelemetry-util-http==0.49b2
127
- Requires-Dist: orjson==3.10.12
128
- Requires-Dist: overrides==7.7.0
129
- Requires-Dist: packaging==24.2
130
- Requires-Dist: pandas==2.3.1
131
- Requires-Dist: pgvector==0.3.6
132
- Requires-Dist: pillow==11.0.0
133
- Requires-Dist: plotly==6.3.0
134
- Requires-Dist: pluggy==1.5.0
135
- Requires-Dist: posthog==3.7.4
136
- Requires-Dist: propcache==0.2.1
137
- Requires-Dist: proto-plus==1.26.0
138
- Requires-Dist: protobuf==5.29.1
139
- Requires-Dist: psutil==7.0.0
140
- Requires-Dist: psycopg2-binary==2.9.10
141
- Requires-Dist: pyarrow==21.0.0
142
- Requires-Dist: pyasn1==0.6.1
143
- Requires-Dist: pyasn1_modules==0.4.1
144
- Requires-Dist: pycparser==2.22
145
- Requires-Dist: pydantic==2.10.2
146
- Requires-Dist: pydantic-settings==2.6.1
147
- Requires-Dist: pydantic_core==2.27.1
148
- Requires-Dist: PyDrive==1.3.1
149
- Requires-Dist: Pygments==2.18.0
150
- Requires-Dist: PyJWT==2.10.1
151
- Requires-Dist: PyMuPDF==1.25.0
152
- Requires-Dist: pyparsing==3.2.1
153
- Requires-Dist: pypdf==5.1.0
154
- Requires-Dist: PyPika==0.48.9
155
- Requires-Dist: pyproject_hooks==1.2.0
156
- Requires-Dist: pytesseract==0.3.13
157
- Requires-Dist: pytest==8.3.4
158
- Requires-Dist: pytest-cov==5.0.0
159
- Requires-Dist: pytest-mock==3.14.0
160
- Requires-Dist: python-dateutil==2.9.0.post0
161
- Requires-Dist: python-docx==1.1.2
162
- Requires-Dist: python-dotenv==1.0.1
163
- Requires-Dist: pytz==2025.2
164
- Requires-Dist: PyYAML==6.0.2
165
- Requires-Dist: redis==5.2.1
166
- Requires-Dist: regex==2024.11.6
167
- Requires-Dist: requests==2.32.3
168
- Requires-Dist: requests-oauthlib==2.0.0
169
- Requires-Dist: requests-toolbelt==1.0.0
170
- Requires-Dist: rich==13.9.4
171
- Requires-Dist: rsa==4.9
172
- Requires-Dist: s3transfer==0.11.2
173
- Requires-Dist: safetensors==0.5.2
174
- Requires-Dist: scikit-learn==1.7.1
175
- Requires-Dist: scipy==1.15.1
176
- Requires-Dist: seaborn==0.13.2
177
- Requires-Dist: setuptools==75.8.0
178
- Requires-Dist: shellingham==1.5.4
179
- Requires-Dist: sib-api-v3-sdk==7.6.0
180
- Requires-Dist: six==1.17.0
181
- Requires-Dist: sniffio==1.3.1
182
- Requires-Dist: soupsieve==2.6
183
- Requires-Dist: SQLAlchemy==2.0.36
184
- Requires-Dist: starlette==0.41.3
185
- Requires-Dist: sympy==1.13.1
186
- Requires-Dist: tenacity==9.0.0
187
- Requires-Dist: threadpoolctl==3.5.0
188
- Requires-Dist: tiktoken==0.8.0
189
- Requires-Dist: tokenizers==0.21.0
190
- Requires-Dist: tomli==2.2.1
191
- Requires-Dist: tqdm==4.67.1
192
- Requires-Dist: typer==0.15.1
193
- Requires-Dist: typing-inspect==0.9.0
194
- Requires-Dist: typing_extensions==4.12.2
195
- Requires-Dist: tzdata==2025.2
196
- Requires-Dist: uritemplate==4.1.1
197
- Requires-Dist: urllib3==2.3.0
198
- Requires-Dist: uvicorn==0.32.1
199
- Requires-Dist: uvloop==0.21.0
200
- Requires-Dist: watchfiles==1.0.0
201
- Requires-Dist: websocket-client==1.8.0
202
- Requires-Dist: websockets==14.1
203
- Requires-Dist: Werkzeug==3.1.3
204
- Requires-Dist: whitenoise==6.8.2
205
- Requires-Dist: wikipedia==1.4.0
206
- Requires-Dist: wrapt==1.17.0
207
- Requires-Dist: yarl==1.18.3
208
- Requires-Dist: zipp==3.21.0
209
- Requires-Dist: zstandard==0.23.0
210
- Dynamic: license-file
211
-
212
-
213
- <div align="center">
214
- <h1>
215
- IAToolkit
216
- </h1>
217
-
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>
224
- </div>
225
-
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
-
231
- With IAToolkit, you can build production-ready, context-aware chatbots and agents that
232
- can query relational databases, perform semantic searches on documents,
233
- and connect to your internal APIs in minutes.
234
-
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.
237
-
238
-
239
- ## 🚀 Key Features
240
-
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.
244
-
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.
248
-
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.
252
-
253
- * **🧠 LLM Agnostic**
254
- * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration.
255
- * No code refactoring needed.
256
-
257
- * **🛠️ Developer-First Experience**
258
- * Built with a clean **Dependency Injection** architecture.
259
- * High-quality code base with **90%+ test coverage**.
260
-
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
265
-
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.
268
-
269
- ## 🤝 Contributing
270
-
271
- We welcome contributions! Whether it's adding a new feature, improving documentation, or fixing a bug,
272
- please feel free to open a pull request.
273
-
274
- ## 📄 License
275
-
276
- IAToolkit is open-source and licensed under the [MIT License](LICENSE).