iatoolkit 1.4.2__py3-none-any.whl → 1.9.0__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 +1 -1
- iatoolkit/common/interfaces/database_provider.py +13 -8
- iatoolkit/common/routes.py +24 -6
- iatoolkit/common/util.py +21 -1
- iatoolkit/infra/connectors/file_connector_factory.py +1 -0
- iatoolkit/infra/connectors/s3_connector.py +4 -2
- iatoolkit/locales/en.yaml +72 -5
- iatoolkit/locales/es.yaml +71 -4
- iatoolkit/repositories/database_manager.py +27 -47
- iatoolkit/repositories/llm_query_repo.py +29 -7
- iatoolkit/repositories/models.py +16 -7
- iatoolkit/services/company_context_service.py +44 -20
- iatoolkit/services/configuration_service.py +227 -71
- iatoolkit/services/dispatcher_service.py +0 -3
- iatoolkit/services/knowledge_base_service.py +14 -1
- iatoolkit/services/load_documents_service.py +10 -3
- iatoolkit/services/prompt_service.py +210 -29
- iatoolkit/services/sql_service.py +17 -0
- iatoolkit/templates/chat.html +2 -1
- iatoolkit/views/categories_api_view.py +71 -0
- iatoolkit/views/configuration_api_view.py +163 -0
- iatoolkit/views/prompt_api_view.py +88 -7
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/METADATA +1 -1
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/RECORD +28 -27
- iatoolkit/views/load_company_configuration_api_view.py +0 -49
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/WHEEL +0 -0
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/licenses/LICENSE +0 -0
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/licenses/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/top_level.txt +0 -0
iatoolkit/__init__.py
CHANGED
|
@@ -9,14 +9,19 @@ class DatabaseProvider(abc.ABC):
|
|
|
9
9
|
|
|
10
10
|
# --- Schema Methods ---
|
|
11
11
|
@abc.abstractmethod
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
def get_database_structure(self) -> dict:
|
|
13
|
+
"""
|
|
14
|
+
Returns the structure of the database (tables, columns, types)
|
|
15
|
+
Format:
|
|
16
|
+
{
|
|
17
|
+
"table_name": {
|
|
18
|
+
"columns": [
|
|
19
|
+
{"name": "col1", "type": "VARCHAR", "nullable": True, "pk": True},
|
|
20
|
+
...
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
"""
|
|
20
25
|
pass
|
|
21
26
|
|
|
22
27
|
# --- Execution Methods ---
|
iatoolkit/common/routes.py
CHANGED
|
@@ -24,7 +24,7 @@ def register_views(app):
|
|
|
24
24
|
from iatoolkit.views.profile_api_view import UserLanguageApiView
|
|
25
25
|
from iatoolkit.views.embedding_api_view import EmbeddingApiView
|
|
26
26
|
from iatoolkit.views.login_view import LoginView, FinalizeContextView
|
|
27
|
-
from iatoolkit.views.
|
|
27
|
+
from iatoolkit.views.configuration_api_view import ConfigurationApiView, ValidateConfigurationApiView
|
|
28
28
|
from iatoolkit.views.logout_api_view import LogoutApiView
|
|
29
29
|
from iatoolkit.views.home_view import HomeView
|
|
30
30
|
from iatoolkit.views.chat_view import ChatView
|
|
@@ -32,6 +32,7 @@ def register_views(app):
|
|
|
32
32
|
from iatoolkit.views.root_redirect_view import RootRedirectView
|
|
33
33
|
from iatoolkit.views.users_api_view import UsersApiView
|
|
34
34
|
from iatoolkit.views.rag_api_view import RagApiView
|
|
35
|
+
from iatoolkit.views.categories_api_view import CategoriesApiView
|
|
35
36
|
|
|
36
37
|
# assign root '/' to our new redirect logic
|
|
37
38
|
app.add_url_rule('/home', view_func=RootRedirectView.as_view('root_redirect'))
|
|
@@ -85,9 +86,21 @@ def register_views(app):
|
|
|
85
86
|
# can be used also for executing iatoolkit prompts
|
|
86
87
|
app.add_url_rule('/<company_short_name>/api/llm_query', view_func=LLMQueryApiView.as_view('llm_query_api'))
|
|
87
88
|
|
|
88
|
-
#
|
|
89
|
-
app.add_url_rule('/<company_short_name>/api/
|
|
90
|
-
|
|
89
|
+
# Categories Endpoint
|
|
90
|
+
app.add_url_rule('/<company_short_name>/api/categories',
|
|
91
|
+
view_func=CategoriesApiView.as_view('categories_api'),
|
|
92
|
+
methods=['GET'])
|
|
93
|
+
|
|
94
|
+
# open the promt directory and specific prompt management
|
|
95
|
+
prompt_view = PromptApiView.as_view('prompt')
|
|
96
|
+
app.add_url_rule('/<company_short_name>/api/prompts',
|
|
97
|
+
view_func=prompt_view,
|
|
98
|
+
methods=['GET', 'POST'],
|
|
99
|
+
defaults={'prompt_name': None})
|
|
100
|
+
|
|
101
|
+
app.add_url_rule('/<company_short_name>/api/prompts/<prompt_name>',
|
|
102
|
+
view_func=prompt_view,
|
|
103
|
+
methods=['GET', 'POST','PUT', 'DELETE'])
|
|
91
104
|
# toolbar buttons
|
|
92
105
|
app.add_url_rule('/<company_short_name>/api/feedback', view_func=UserFeedbackApiView.as_view('feedback'))
|
|
93
106
|
app.add_url_rule('/<company_short_name>/api/history', view_func=HistoryApiView.as_view('history'))
|
|
@@ -128,8 +141,13 @@ def register_views(app):
|
|
|
128
141
|
view_func=EmbeddingApiView.as_view('embedding_api'))
|
|
129
142
|
|
|
130
143
|
# company configuration
|
|
131
|
-
app.add_url_rule('/<company_short_name>/api/
|
|
132
|
-
view_func=
|
|
144
|
+
app.add_url_rule('/<company_short_name>/api/configuration',
|
|
145
|
+
view_func=ConfigurationApiView.as_view('configuration'),
|
|
146
|
+
methods=['GET', 'POST', 'PATCH'],)
|
|
147
|
+
|
|
148
|
+
app.add_url_rule('/<company_short_name>/api/configuration/validate',
|
|
149
|
+
view_func=ValidateConfigurationApiView.as_view('configuration-validate'),
|
|
150
|
+
methods=['GET'])
|
|
133
151
|
|
|
134
152
|
# static pages
|
|
135
153
|
# url: /pages/foundation o /pages/implementation_plan
|
iatoolkit/common/util.py
CHANGED
|
@@ -168,6 +168,20 @@ class Utility:
|
|
|
168
168
|
logging.error(f"Error parsing YAML string: {e}")
|
|
169
169
|
return {}
|
|
170
170
|
|
|
171
|
+
def dump_yaml_to_string(self, config: dict) -> str:
|
|
172
|
+
"""
|
|
173
|
+
Dumps a dictionary into a YAML formatted string.
|
|
174
|
+
It uses default flow style False to ensure block format (readable YAML).
|
|
175
|
+
"""
|
|
176
|
+
try:
|
|
177
|
+
# default_flow_style=False ensures lists and dicts are expanded (not inline like JSON)
|
|
178
|
+
# allow_unicode=True ensures characters like accents are preserved
|
|
179
|
+
return yaml.safe_dump(config, default_flow_style=False, allow_unicode=True, sort_keys=False)
|
|
180
|
+
except yaml.YAMLError as e:
|
|
181
|
+
logging.error(f"Error dumping YAML to string: {e}")
|
|
182
|
+
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
183
|
+
f"Failed to generate YAML: {e}")
|
|
184
|
+
|
|
171
185
|
def generate_context_for_schema(self, entity_name: str, schema_file: str = None, schema: dict = {}) -> str:
|
|
172
186
|
if not schema_file and not schema:
|
|
173
187
|
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
@@ -197,9 +211,13 @@ class Utility:
|
|
|
197
211
|
root_name = list(schema.keys())[0]
|
|
198
212
|
root_details = schema[root_name]
|
|
199
213
|
|
|
214
|
+
# support this format
|
|
215
|
+
if root_details.get('columns'):
|
|
216
|
+
root_details = root_details['columns']
|
|
217
|
+
|
|
200
218
|
if isinstance(root_details, dict):
|
|
201
219
|
# Las claves de metadatos describen el objeto en sí, no sus propiedades hijas.
|
|
202
|
-
METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties']
|
|
220
|
+
METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties', 'pk']
|
|
203
221
|
|
|
204
222
|
# Las propiedades son las claves restantes en el diccionario.
|
|
205
223
|
properties = {
|
|
@@ -242,6 +260,8 @@ class Utility:
|
|
|
242
260
|
description = details.get('description', '')
|
|
243
261
|
data_type = details.get('type', 'any')
|
|
244
262
|
output.append(f"{indent_str}- **`{name.lower()}`** ({data_type}): {description}")
|
|
263
|
+
# if 'pk' in details and details['pk']:
|
|
264
|
+
# output.append(f"{indent_str}- **Primary Key**: {details['pk']}")
|
|
245
265
|
|
|
246
266
|
child_indent_str = ' ' * (indent_level + 1)
|
|
247
267
|
|
|
@@ -9,14 +9,16 @@ from typing import List
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class S3Connector(FileConnector):
|
|
12
|
-
def __init__(self, bucket: str, prefix: str, auth: dict):
|
|
12
|
+
def __init__(self, bucket: str, prefix: str, folder: str, auth: dict):
|
|
13
13
|
self.bucket = bucket
|
|
14
14
|
self.prefix = prefix
|
|
15
|
+
self.folder = folder
|
|
15
16
|
self.s3 = boto3.client('s3', **auth)
|
|
16
17
|
|
|
17
18
|
def list_files(self) -> List[dict]:
|
|
18
19
|
# list all the files as dictionaries, with keys: 'path', 'name' y 'metadata'.
|
|
19
|
-
|
|
20
|
+
prefix = f'{self.prefix}/{self.folder}/'
|
|
21
|
+
response = self.s3.list_objects_v2(Bucket=self.bucket, Prefix=prefix)
|
|
20
22
|
files = response.get('Contents', [])
|
|
21
23
|
|
|
22
24
|
return [
|
iatoolkit/locales/en.yaml
CHANGED
|
@@ -52,8 +52,7 @@ ui:
|
|
|
52
52
|
company_config: "Company Configuration (company.yaml)"
|
|
53
53
|
prompts: "Prompts"
|
|
54
54
|
prompts_description: "System Prompts"
|
|
55
|
-
|
|
56
|
-
knowledge_rag: "RAG (Vector)"
|
|
55
|
+
knowledge_rag: "Knowledge Base (RAG)"
|
|
57
56
|
knowledge_static: "Static Context"
|
|
58
57
|
schemas: "Schemas"
|
|
59
58
|
schemas_description: "Data Definitions (YAML)"
|
|
@@ -78,7 +77,6 @@ ui:
|
|
|
78
77
|
saved_ok: "File saved successfully"
|
|
79
78
|
save_file: "Save"
|
|
80
79
|
credentials: "Email and password required for login."
|
|
81
|
-
saved_ok: "Saved successfully"
|
|
82
80
|
deleted_ok: "Deleted successfully"
|
|
83
81
|
user_manager: "User management"
|
|
84
82
|
admin_page_title: "Admin access"
|
|
@@ -87,6 +85,72 @@ ui:
|
|
|
87
85
|
logout: "Close session"
|
|
88
86
|
error_loading: "Error loading file content"
|
|
89
87
|
loading: "Loading..."
|
|
88
|
+
add: "Add"
|
|
89
|
+
create: "Create"
|
|
90
|
+
delete: "Delete"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
db_explorer:
|
|
94
|
+
data_explorer: "Data Explorer"
|
|
95
|
+
database_connection: "Database Connection"
|
|
96
|
+
tables: "Tables"
|
|
97
|
+
data_explorer_description: "Explore your database tables ."
|
|
98
|
+
select_database: "Please select a database above to view its tables."
|
|
99
|
+
not_table_selected: "No table selected"
|
|
100
|
+
view_yaml: "View YAML"
|
|
101
|
+
save_schema: "Save schema"
|
|
102
|
+
select_table: "Select a table from the left panel"
|
|
103
|
+
table_semantics: "Table Semantics"
|
|
104
|
+
table_description: "Description (AI Context)"
|
|
105
|
+
table_placeholder: "Describe what data this table contains (e.g., 'Active and inactive customer records including billing addresses')..."
|
|
106
|
+
column_metadata: "Column Metadata"
|
|
107
|
+
auto_detect: "Auto-detected from DB"
|
|
108
|
+
meta_column: "Column"
|
|
109
|
+
meta_type: "Type"
|
|
110
|
+
meta_description: "Description"
|
|
111
|
+
meta_synonyms: "Synonyms"
|
|
112
|
+
pii_sesitive: "PII Sensitive"
|
|
113
|
+
|
|
114
|
+
prompts:
|
|
115
|
+
title: "Prompts Manager"
|
|
116
|
+
subtitle: "Manage and test your AI personas and templates"
|
|
117
|
+
library: "Prompt Library"
|
|
118
|
+
new_btn: "New"
|
|
119
|
+
filter_placeholder: "Filter prompts..."
|
|
120
|
+
select_prompt: "Select a prompt"
|
|
121
|
+
toggle_settings: "Toggle Variables & Config"
|
|
122
|
+
settings_btn: "Settings"
|
|
123
|
+
save_btn: "Save"
|
|
124
|
+
tab_editor: "Editor"
|
|
125
|
+
tab_playground: "Playground"
|
|
126
|
+
config_title: "Config"
|
|
127
|
+
desc_label: "Description"
|
|
128
|
+
desc_placeholder: "Describe this prompt..."
|
|
129
|
+
vars_label: "Input Variables"
|
|
130
|
+
no_vars: "No inputs defined"
|
|
131
|
+
playground_inputs: "Variables & Inputs"
|
|
132
|
+
no_vars_detected: "No variables detected in prompt template."
|
|
133
|
+
model_override: "Model Override (Optional)"
|
|
134
|
+
default_model: "Default (from config)"
|
|
135
|
+
run_btn: "Run"
|
|
136
|
+
output_placeholder: "Output will appear here..."
|
|
137
|
+
new_modal_title: "Create New Prompt"
|
|
138
|
+
name_label: "Name (Slug)"
|
|
139
|
+
name_help: "Use lowercase, numbers, and underscores only."
|
|
140
|
+
category_label: "Category"
|
|
141
|
+
delete_confirmation: "Delete Prompt?"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
config:
|
|
145
|
+
editor_description: "IAToolkit configuration file"
|
|
146
|
+
title: "Configuration Editor"
|
|
147
|
+
sections: "Sections"
|
|
148
|
+
refresh: "Refresh"
|
|
149
|
+
validate: "Validate"
|
|
150
|
+
select_section: "Select a section from the left panel"
|
|
151
|
+
no_section_selected: "No section selected"
|
|
152
|
+
view_yaml: "View YAML"
|
|
153
|
+
|
|
90
154
|
|
|
91
155
|
rag:
|
|
92
156
|
ingestion: "Ingestion"
|
|
@@ -115,8 +179,11 @@ ui:
|
|
|
115
179
|
delete_message: "This action cannot be undone. The file will be permanently removed."
|
|
116
180
|
delete_button: "Delete"
|
|
117
181
|
delete_cancel: "Cancel"
|
|
118
|
-
|
|
119
|
-
|
|
182
|
+
target_collection: "Collection"
|
|
183
|
+
select_collection_placeholder: "Select a collection"
|
|
184
|
+
collection_required: "Collection is required"
|
|
185
|
+
collection: "Collection"
|
|
186
|
+
all_collections: "All collections"
|
|
120
187
|
|
|
121
188
|
tooltips:
|
|
122
189
|
history: "History of my queries"
|
iatoolkit/locales/es.yaml
CHANGED
|
@@ -49,8 +49,7 @@ ui:
|
|
|
49
49
|
workspace: "Recursos"
|
|
50
50
|
configuration: "Configuración"
|
|
51
51
|
company_config: "Configuración Empresa (company.yaml)"
|
|
52
|
-
|
|
53
|
-
knowledge_rag: "RAG (Vectorial)"
|
|
52
|
+
knowledge_rag: "Knowledge Base (RAG)"
|
|
54
53
|
knowledge_static: "Contenido Estático"
|
|
55
54
|
prompts: "Prompts"
|
|
56
55
|
prompts_description: "Prompts de sistema"
|
|
@@ -62,7 +61,6 @@ ui:
|
|
|
62
61
|
monitoring: "Monitoreo"
|
|
63
62
|
teams: "Usuarios"
|
|
64
63
|
billing: "Facturación"
|
|
65
|
-
company: "Empresa"
|
|
66
64
|
files: "Archivos"
|
|
67
65
|
select_file: "Seleccione un archivo a editar"
|
|
68
66
|
select_category: "Seleccione una categoría"
|
|
@@ -84,6 +82,70 @@ ui:
|
|
|
84
82
|
load_configuration: "Guardar configuración"
|
|
85
83
|
goto_chat: "Ir al chat"
|
|
86
84
|
logout: "Cerrar sesión"
|
|
85
|
+
add: "Agregar"
|
|
86
|
+
create: "Crear"
|
|
87
|
+
delete: "Borrar"
|
|
88
|
+
|
|
89
|
+
db_explorer:
|
|
90
|
+
data_explorer: "Explorador de datos"
|
|
91
|
+
database_connection: "Bases de datos"
|
|
92
|
+
tables: "Tablas"
|
|
93
|
+
data_explorer_description: "Explora tus tablas de base de datos."
|
|
94
|
+
select_database: "Seleccione una base de datos para ver sus tablas."
|
|
95
|
+
not_table_selected: "No hay tabla seleccionada."
|
|
96
|
+
view_yaml: "Ver YAML"
|
|
97
|
+
save_schema: "Guardar esquema"
|
|
98
|
+
select_table: "Seleccionar una tabla del panel izquierdo"
|
|
99
|
+
table_semantics: "Significado de la tabla"
|
|
100
|
+
table_description: "Descripción de la tabla (Contexto IA)"
|
|
101
|
+
table_placeholder: "Describe el significado de la tabla, ejemplo: tabla de usuarios."
|
|
102
|
+
column_metadata: "Metadatos de columna"
|
|
103
|
+
auto_detect: "Auto-detectar desde la BD"
|
|
104
|
+
meta_column: "Columna"
|
|
105
|
+
meta_type: "Tipo"
|
|
106
|
+
meta_description: "Descripción"
|
|
107
|
+
meta_synonyms: "Sinonimos"
|
|
108
|
+
pii_sesitive: "IP Sensible"
|
|
109
|
+
|
|
110
|
+
prompts:
|
|
111
|
+
title: "Gestor de Prompts"
|
|
112
|
+
subtitle: "Gestiona y prueba tus plantillas y personas de IA"
|
|
113
|
+
library: "Biblioteca de Prompts"
|
|
114
|
+
new_btn: "Nuevo"
|
|
115
|
+
filter_placeholder: "Filtrar prompts..."
|
|
116
|
+
select_prompt: "Selecciona un prompt"
|
|
117
|
+
toggle_settings: "Alternar Variables y Configuración"
|
|
118
|
+
settings_btn: "Ajustes"
|
|
119
|
+
save_btn: "Guardar"
|
|
120
|
+
tab_editor: "Editor"
|
|
121
|
+
tab_playground: "Playground"
|
|
122
|
+
config_title: "Configuración"
|
|
123
|
+
desc_label: "Descripción"
|
|
124
|
+
desc_placeholder: "Describe este prompt..."
|
|
125
|
+
vars_label: "Variables de Entrada"
|
|
126
|
+
no_vars: "Sin variables definidas"
|
|
127
|
+
playground_inputs: "Variables y Entradas"
|
|
128
|
+
no_vars_detected: "No se detectaron variables en la plantilla."
|
|
129
|
+
model_override: "Modelo Específico (Opcional)"
|
|
130
|
+
default_model: "Por defecto (según config)"
|
|
131
|
+
run_btn: "Ejecutar"
|
|
132
|
+
output_placeholder: "El resultado aparecerá aquí..."
|
|
133
|
+
new_modal_title: "Crear Nuevo Prompt"
|
|
134
|
+
name_label: "Nombre (Slug)"
|
|
135
|
+
name_help: "Solo minúsculas, números y guiones bajos."
|
|
136
|
+
category_label: "Categoría"
|
|
137
|
+
delete_confirmation: "Eliminar el prompt?"
|
|
138
|
+
|
|
139
|
+
config:
|
|
140
|
+
editor_description: "Editor de configuración"
|
|
141
|
+
title: "Editor de configuraciones"
|
|
142
|
+
sections: "Secciones"
|
|
143
|
+
refresh: "Refrescar"
|
|
144
|
+
validate: "Validar"
|
|
145
|
+
select_section: "Seleccione una sección del panel izquierdo"
|
|
146
|
+
no_section_selected: "No hay sección seleccionada."
|
|
147
|
+
view_yaml: "Ver YAML"
|
|
148
|
+
|
|
87
149
|
|
|
88
150
|
rag:
|
|
89
151
|
ingestion: "Ingesta"
|
|
@@ -101,7 +163,7 @@ ui:
|
|
|
101
163
|
filename_placeholder: "Contiene..."
|
|
102
164
|
user: "Usuario"
|
|
103
165
|
status: "Estado"
|
|
104
|
-
all_status: "
|
|
166
|
+
all_status: "Estados"
|
|
105
167
|
status_active: "Activo"
|
|
106
168
|
status_pending: "Pendiente"
|
|
107
169
|
status_processing: "Procesando"
|
|
@@ -112,6 +174,11 @@ ui:
|
|
|
112
174
|
delete_message: "Esta acción no se puede deshacer. El archivo se eliminará permanentemente."
|
|
113
175
|
delete_button: "Eliminar"
|
|
114
176
|
delete_cancel: "Cancelar"
|
|
177
|
+
target_collection: "Categoría"
|
|
178
|
+
select_collection_placeholder: "Selecciona una categoría"
|
|
179
|
+
collection_required: "Debe seleccionar una categoría"
|
|
180
|
+
all_collections: "Todas las categorías"
|
|
181
|
+
collection: "Categoría"
|
|
115
182
|
|
|
116
183
|
|
|
117
184
|
tooltips:
|
|
@@ -11,6 +11,7 @@ from iatoolkit.repositories.models import Base
|
|
|
11
11
|
from injector import inject
|
|
12
12
|
from pgvector.psycopg2 import register_vector
|
|
13
13
|
from iatoolkit.common.interfaces.database_provider import DatabaseProvider
|
|
14
|
+
import logging
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class DatabaseManager(DatabaseProvider):
|
|
@@ -135,51 +136,30 @@ class DatabaseManager(DatabaseProvider):
|
|
|
135
136
|
self.get_session().rollback()
|
|
136
137
|
|
|
137
138
|
# -- schema methods ----
|
|
138
|
-
def
|
|
139
|
-
# Returns a list of all table names in the database
|
|
139
|
+
def get_database_structure(self) -> dict:
|
|
140
140
|
inspector = inspect(self._engine)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if schema_object_name:
|
|
168
|
-
json_dict["description"] += (
|
|
169
|
-
f"The meaning of each field in this table is detailed in the **`{schema_object_name}`** object."
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# now add every column to the json dictionary
|
|
173
|
-
for col in columns:
|
|
174
|
-
name = col["name"]
|
|
175
|
-
|
|
176
|
-
# omit the excluded columns.
|
|
177
|
-
if name in exclude_columns:
|
|
178
|
-
continue
|
|
179
|
-
|
|
180
|
-
json_dict["fields"].append({
|
|
181
|
-
"name": name,
|
|
182
|
-
"type": str(col["type"]),
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
return "\n\n" + str(json_dict)
|
|
141
|
+
structure = {}
|
|
142
|
+
for table in inspector.get_table_names(schema=self.schema):
|
|
143
|
+
columns_data = []
|
|
144
|
+
|
|
145
|
+
# get columns
|
|
146
|
+
try:
|
|
147
|
+
columns = inspector.get_columns(table, schema=self.schema)
|
|
148
|
+
# Obtener PKs para marcarlas
|
|
149
|
+
pks = inspector.get_pk_constraint(table, schema=self.schema).get('constrained_columns', [])
|
|
150
|
+
|
|
151
|
+
for col in columns:
|
|
152
|
+
columns_data.append({
|
|
153
|
+
"name": col['name'],
|
|
154
|
+
"type": str(col['type']),
|
|
155
|
+
"nullable": col.get('nullable', True),
|
|
156
|
+
"pk": col['name'] in pks
|
|
157
|
+
})
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logging.warning(f"Could not inspect columns for table {table}: {e}")
|
|
160
|
+
|
|
161
|
+
structure[table] = {
|
|
162
|
+
"columns": columns_data
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return structure
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
#
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
|
-
from iatoolkit.repositories.models import LLMQuery, Tool,
|
|
6
|
+
from iatoolkit.repositories.models import (LLMQuery, Tool,
|
|
7
|
+
Company, Prompt, PromptCategory, PromptType)
|
|
7
8
|
from injector import inject
|
|
8
9
|
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
9
10
|
from sqlalchemy import or_
|
|
11
|
+
from typing import List
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
class LLMQueryRepo:
|
|
12
15
|
@inject
|
|
@@ -54,7 +57,7 @@ class LLMQueryRepo:
|
|
|
54
57
|
self.session.add(new_tool)
|
|
55
58
|
tool = new_tool
|
|
56
59
|
|
|
57
|
-
self.session.
|
|
60
|
+
self.session.commit()
|
|
58
61
|
return tool
|
|
59
62
|
|
|
60
63
|
def delete_tool(self, tool: Tool):
|
|
@@ -67,14 +70,14 @@ class LLMQueryRepo:
|
|
|
67
70
|
prompt.category_id = new_prompt.category_id
|
|
68
71
|
prompt.description = new_prompt.description
|
|
69
72
|
prompt.order = new_prompt.order
|
|
70
|
-
prompt.
|
|
73
|
+
prompt.prompt_type = new_prompt.prompt_type
|
|
71
74
|
prompt.filename = new_prompt.filename
|
|
72
75
|
prompt.custom_fields = new_prompt.custom_fields
|
|
73
76
|
else:
|
|
74
77
|
self.session.add(new_prompt)
|
|
75
78
|
prompt = new_prompt
|
|
76
79
|
|
|
77
|
-
self.session.
|
|
80
|
+
self.session.commit()
|
|
78
81
|
return prompt
|
|
79
82
|
|
|
80
83
|
def create_or_update_prompt_category(self, new_category: PromptCategory):
|
|
@@ -94,12 +97,31 @@ class LLMQueryRepo:
|
|
|
94
97
|
LLMQuery.user_identifier == user_identifier,
|
|
95
98
|
).filter_by(company_id=company.id).order_by(LLMQuery.created_at.desc()).limit(100).all()
|
|
96
99
|
|
|
97
|
-
def get_prompts(self, company: Company) -> list[Prompt]:
|
|
98
|
-
|
|
100
|
+
def get_prompts(self, company: Company, include_all: bool = False) -> list[Prompt]:
|
|
101
|
+
if include_all:
|
|
102
|
+
# Include all prompts: company, system, agent
|
|
103
|
+
return self.session.query(Prompt).filter(
|
|
104
|
+
Prompt.company_id == company.id,
|
|
105
|
+
).all()
|
|
106
|
+
else:
|
|
107
|
+
# Only company prompts, excluding system (default behavior for end users)
|
|
108
|
+
return self.session.query(Prompt).filter(
|
|
109
|
+
Prompt.company_id == company.id,
|
|
110
|
+
Prompt.prompt_type == PromptType.COMPANY.value
|
|
111
|
+
).all()
|
|
99
112
|
|
|
100
113
|
def get_prompt_by_name(self, company: Company, prompt_name: str):
|
|
101
114
|
return self.session.query(Prompt).filter_by(company_id=company.id, name=prompt_name).first()
|
|
102
115
|
|
|
116
|
+
def get_category_by_name(self, company_id: int, name: str) -> PromptCategory:
|
|
117
|
+
return self.session.query(PromptCategory).filter_by(company_id=company_id, name=name).first()
|
|
118
|
+
|
|
119
|
+
def get_all_categories(self, company_id: int) -> List[PromptCategory]:
|
|
120
|
+
return self.session.query(PromptCategory).filter_by(company_id=company_id).order_by(PromptCategory.order).all()
|
|
121
|
+
|
|
103
122
|
def get_system_prompts(self) -> list[Prompt]:
|
|
104
|
-
return self.session.query(Prompt).filter_by(
|
|
123
|
+
return self.session.query(Prompt).filter_by(prompt_type=PromptType.SYSTEM.value, active=True).order_by(Prompt.order).all()
|
|
105
124
|
|
|
125
|
+
def delete_prompt(self, prompt: Prompt):
|
|
126
|
+
self.session.delete(prompt)
|
|
127
|
+
self.session.commit()
|
iatoolkit/repositories/models.py
CHANGED
|
@@ -17,6 +17,19 @@ import enum
|
|
|
17
17
|
class Base(DeclarativeBase):
|
|
18
18
|
pass
|
|
19
19
|
|
|
20
|
+
|
|
21
|
+
class DocumentStatus(str, enum.Enum):
|
|
22
|
+
PENDING = "pending"
|
|
23
|
+
PROCESSING = "processing"
|
|
24
|
+
ACTIVE = "active"
|
|
25
|
+
FAILED = "failed"
|
|
26
|
+
|
|
27
|
+
class PromptType(str, enum.Enum):
|
|
28
|
+
SYSTEM = "system"
|
|
29
|
+
COMPANY = "company"
|
|
30
|
+
AGENT = "agent"
|
|
31
|
+
|
|
32
|
+
|
|
20
33
|
# relation table for many-to-many relationship between companies and users
|
|
21
34
|
user_company = Table('iat_user_company',
|
|
22
35
|
Base.metadata,
|
|
@@ -149,11 +162,6 @@ class Tool(Base):
|
|
|
149
162
|
return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
|
|
150
163
|
|
|
151
164
|
|
|
152
|
-
class DocumentStatus(str, enum.Enum):
|
|
153
|
-
PENDING = "pending"
|
|
154
|
-
PROCESSING = "processing"
|
|
155
|
-
ACTIVE = "active"
|
|
156
|
-
FAILED = "failed"
|
|
157
165
|
|
|
158
166
|
|
|
159
167
|
class CollectionType(Base):
|
|
@@ -290,12 +298,13 @@ class Prompt(Base):
|
|
|
290
298
|
description = Column(String, nullable=False)
|
|
291
299
|
filename = Column(String, nullable=False)
|
|
292
300
|
active = Column(Boolean, default=True)
|
|
293
|
-
|
|
301
|
+
prompt_type = Column(String, default=PromptType.COMPANY.value, nullable=False)
|
|
294
302
|
order = Column(Integer, nullable=True, default=0)
|
|
295
303
|
category_id = Column(Integer, ForeignKey('iat_prompt_categories.id'), nullable=True)
|
|
296
304
|
custom_fields = Column(JSON, nullable=False, default=[])
|
|
297
|
-
|
|
298
305
|
created_at = Column(DateTime, default=datetime.now)
|
|
306
|
+
def to_dict(self):
|
|
307
|
+
return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
|
|
299
308
|
|
|
300
309
|
company = relationship("Company", back_populates="prompts")
|
|
301
310
|
category = relationship("PromptCategory", back_populates="prompts")
|