iatoolkit 0.71.4__py3-none-any.whl → 0.91.1__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.
- iatoolkit/__init__.py +15 -5
- iatoolkit/base_company.py +4 -58
- iatoolkit/cli_commands.py +6 -7
- iatoolkit/common/exceptions.py +1 -0
- iatoolkit/common/routes.py +12 -28
- iatoolkit/common/util.py +7 -1
- iatoolkit/company_registry.py +50 -14
- iatoolkit/{iatoolkit.py → core.py} +54 -55
- iatoolkit/infra/{mail_app.py → brevo_mail_app.py} +15 -37
- iatoolkit/infra/llm_client.py +9 -5
- iatoolkit/locales/en.yaml +10 -2
- iatoolkit/locales/es.yaml +171 -162
- iatoolkit/repositories/database_manager.py +59 -14
- iatoolkit/repositories/llm_query_repo.py +34 -22
- iatoolkit/repositories/models.py +16 -18
- iatoolkit/repositories/profile_repo.py +5 -10
- iatoolkit/repositories/vs_repo.py +9 -4
- iatoolkit/services/auth_service.py +1 -1
- iatoolkit/services/branding_service.py +1 -1
- iatoolkit/services/company_context_service.py +19 -11
- iatoolkit/services/configuration_service.py +219 -46
- iatoolkit/services/dispatcher_service.py +31 -225
- iatoolkit/services/document_service.py +10 -1
- iatoolkit/services/embedding_service.py +9 -6
- iatoolkit/services/excel_service.py +50 -2
- iatoolkit/services/history_manager_service.py +189 -0
- iatoolkit/services/jwt_service.py +1 -1
- iatoolkit/services/language_service.py +8 -2
- iatoolkit/services/license_service.py +82 -0
- iatoolkit/services/mail_service.py +171 -25
- iatoolkit/services/profile_service.py +37 -32
- iatoolkit/services/{prompt_manager_service.py → prompt_service.py} +110 -1
- iatoolkit/services/query_service.py +192 -191
- iatoolkit/services/sql_service.py +63 -12
- iatoolkit/services/tool_service.py +231 -0
- iatoolkit/services/user_feedback_service.py +18 -6
- iatoolkit/services/user_session_context_service.py +18 -0
- iatoolkit/static/images/iatoolkit_core.png +0 -0
- iatoolkit/static/images/iatoolkit_logo.png +0 -0
- iatoolkit/static/js/chat_feedback_button.js +1 -1
- iatoolkit/static/js/chat_help_content.js +4 -4
- iatoolkit/static/js/chat_main.js +17 -5
- iatoolkit/static/js/chat_onboarding_button.js +1 -1
- iatoolkit/static/styles/chat_iatoolkit.css +1 -1
- iatoolkit/static/styles/chat_public.css +28 -0
- iatoolkit/static/styles/documents.css +598 -0
- iatoolkit/static/styles/landing_page.css +223 -7
- iatoolkit/system_prompts/__init__.py +0 -0
- iatoolkit/system_prompts/query_main.prompt +2 -1
- iatoolkit/system_prompts/sql_rules.prompt +47 -12
- iatoolkit/templates/_company_header.html +30 -5
- iatoolkit/templates/_login_widget.html +3 -3
- iatoolkit/templates/chat.html +1 -1
- iatoolkit/templates/forgot_password.html +3 -2
- iatoolkit/templates/onboarding_shell.html +1 -1
- iatoolkit/templates/signup.html +3 -0
- iatoolkit/views/base_login_view.py +1 -1
- iatoolkit/views/change_password_view.py +1 -1
- iatoolkit/views/forgot_password_view.py +9 -4
- iatoolkit/views/history_api_view.py +3 -3
- iatoolkit/views/home_view.py +4 -2
- iatoolkit/views/init_context_api_view.py +1 -1
- iatoolkit/views/llmquery_api_view.py +4 -3
- iatoolkit/views/{file_store_api_view.py → load_document_api_view.py} +1 -1
- iatoolkit/views/login_view.py +17 -5
- iatoolkit/views/logout_api_view.py +10 -2
- iatoolkit/views/prompt_api_view.py +1 -1
- iatoolkit/views/root_redirect_view.py +22 -0
- iatoolkit/views/signup_view.py +12 -4
- iatoolkit/views/static_page_view.py +27 -0
- iatoolkit/views/verify_user_view.py +1 -1
- iatoolkit-0.91.1.dist-info/METADATA +268 -0
- iatoolkit-0.91.1.dist-info/RECORD +125 -0
- iatoolkit-0.91.1.dist-info/licenses/LICENSE_COMMUNITY.md +15 -0
- iatoolkit/services/history_service.py +0 -37
- iatoolkit/templates/about.html +0 -13
- iatoolkit/templates/index.html +0 -145
- iatoolkit/templates/login_simulation.html +0 -45
- iatoolkit/views/external_login_view.py +0 -73
- iatoolkit/views/index_view.py +0 -14
- iatoolkit/views/login_simulation_view.py +0 -93
- iatoolkit-0.71.4.dist-info/METADATA +0 -276
- iatoolkit-0.71.4.dist-info/RECORD +0 -122
- {iatoolkit-0.71.4.dist-info → iatoolkit-0.91.1.dist-info}/WHEEL +0 -0
- {iatoolkit-0.71.4.dist-info → iatoolkit-0.91.1.dist-info}/licenses/LICENSE +0 -0
- {iatoolkit-0.71.4.dist-info → iatoolkit-0.91.1.dist-info}/top_level.txt +0 -0
iatoolkit/templates/about.html
DELETED
|
@@ -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>
|
iatoolkit/templates/index.html
DELETED
|
@@ -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
|
-
© 2024 IAToolkit - Proyecto Open Source
|
|
142
|
-
</div>
|
|
143
|
-
</footer>
|
|
144
|
-
</div>
|
|
145
|
-
{% endblock %}
|
|
@@ -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
|
iatoolkit/views/index_view.py
DELETED
|
@@ -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,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).
|