iatoolkit 0.3.2__py3-none-any.whl → 0.3.4__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.

Potentially problematic release.


This version of iatoolkit might be problematic. Click here for more details.

iatoolkit/__init__.py CHANGED
@@ -22,7 +22,11 @@ from services.dispatcher_service import Dispatcher
22
22
  from services.document_service import DocumentService
23
23
  from services.search_service import SearchService
24
24
  from repositories.profile_repo import ProfileRepo
25
+ from repositories.llm_query_repo import LLMQueryRepo
25
26
  from repositories.database_manager import DatabaseManager
27
+ from infra.call_service import CallServiceClient
28
+ from common.util import Utility
29
+ from repositories.models import Base, Company, Function, TaskType
26
30
 
27
31
 
28
32
  __all__ = [
@@ -37,5 +41,12 @@ __all__ = [
37
41
  'DocumentService',
38
42
  'SearchService',
39
43
  'ProfileRepo',
44
+ 'LLMQueryRepo',
40
45
  'DatabaseManager',
46
+ 'CallServiceClient',
47
+ 'Utility',
48
+ 'Company',
49
+ 'Function',
50
+ 'TaskType',
51
+ 'Base',
41
52
  ]
@@ -8,10 +8,8 @@ import logging
8
8
 
9
9
  class CompanyRegistry:
10
10
  """
11
- Registro centralizado de empresas para iatoolkit.
12
-
13
- Permite a los clientes registrar sus clases de empresa de forma explícita
14
- en lugar de usar autodiscovery.
11
+ Company registry with dependency injection support.
12
+ Allow the client to register companies and instantiate them with dependency injection.
15
13
  """
16
14
 
17
15
  def __init__(self):
@@ -19,22 +17,6 @@ class CompanyRegistry:
19
17
  self._company_instances: Dict[str, BaseCompany] = {}
20
18
  self._injector = None
21
19
 
22
- def register_company(self, name: str, company_class: Type[BaseCompany]) -> None:
23
- """
24
- Registra una clase de empresa.
25
-
26
- Args:
27
- name: Nombre de la empresa (ej: 'maxxa')
28
- company_class: Clase que hereda de BaseCompany
29
- """
30
- if not issubclass(company_class, BaseCompany):
31
- raise ValueError(f"La clase {company_class.__name__} debe heredar de BaseCompany")
32
-
33
- company_key = name.lower()
34
- self._company_classes[company_key] = company_class
35
-
36
- logging.info(f"Empresa registrada: {company_key} -> {company_class.__name__}")
37
-
38
20
  def set_injector(self, injector) -> None:
39
21
  """Establece el injector para crear instancias con dependencias"""
40
22
  self._injector = injector
@@ -65,34 +47,33 @@ class CompanyRegistry:
65
47
  return self._company_instances.copy()
66
48
 
67
49
  def get_registered_companies(self) -> Dict[str, Type[BaseCompany]]:
68
- """Retorna las clases registradas"""
69
50
  return self._company_classes.copy()
70
51
 
71
- def get_company_instances(self) -> Dict[str, BaseCompany]:
72
- """Retorna las instancias de empresas"""
73
- return self._company_instances.copy()
74
-
75
52
  def clear(self) -> None:
76
53
  """Limpia el registro (útil para tests)"""
77
54
  self._company_classes.clear()
78
55
  self._company_instances.clear()
79
56
 
80
57
 
81
- # Instancia global del registry
58
+ # global instance of the company registry
82
59
  _company_registry = CompanyRegistry()
83
60
 
84
61
 
85
62
  def register_company(name: str, company_class: Type[BaseCompany]) -> None:
86
63
  """
87
- Función pública para registrar empresas.
64
+ Public function to register a company.
88
65
 
89
66
  Args:
90
- name: Nombre de la empresa
91
- company_class: Clase que hereda de BaseCompany
67
+ name: Name of the company
68
+ company_class: Class that inherits from BaseCompany
92
69
  """
93
- _company_registry.register_company(name, company_class)
70
+ if not issubclass(company_class, BaseCompany):
71
+ raise ValueError(f"La clase {company_class.__name__} debe heredar de BaseCompany")
72
+
73
+ company_key = name.lower()
74
+ _company_registry._company_classes[company_key] = company_class
94
75
 
95
76
 
96
77
  def get_company_registry() -> CompanyRegistry:
97
- """Obtiene el registry global"""
78
+ """get the global company registry instance"""
98
79
  return _company_registry
iatoolkit/iatoolkit.py CHANGED
@@ -19,7 +19,6 @@ import click
19
19
  from typing import Optional, Dict, Any
20
20
  from repositories.database_manager import DatabaseManager
21
21
  from injector import Binder, singleton, Injector
22
- from .toolkit_config import IAToolkitConfig
23
22
 
24
23
  VERSION = "2.0.0"
25
24
 
@@ -51,9 +50,9 @@ class IAToolkit:
51
50
  return
52
51
 
53
52
  self.config = config or {}
54
- self.app: Optional[Flask] = None
55
- self.db_manager: Optional[DatabaseManager] = None
56
- self._injector: Optional[Injector] = None
53
+ self.app = None
54
+ self.db_manager = None
55
+ self._injector = None
57
56
 
58
57
  @classmethod
59
58
  def get_instance(cls) -> 'IAToolkit':
@@ -68,7 +67,7 @@ class IAToolkit:
68
67
  def create_iatoolkit(self):
69
68
  """
70
69
  Creates, configures, and returns the Flask application instance.
71
- his is the main entry point for the application factory.
70
+ this is the main entry point for the application factory.
72
71
  """
73
72
  self._setup_logging()
74
73
 
@@ -78,12 +77,8 @@ class IAToolkit:
78
77
  # Step 2: Set up the core components that DI depends on
79
78
  self._setup_database()
80
79
 
81
- # Step 3: Create the Injector with CORE dependencies (NO VIEWS)
82
- toolkit_config_module = IAToolkitConfig(app=self.app, db_manager=self.db_manager)
83
- self._injector = Injector([
84
- toolkit_config_module,
85
- self._configure_core_dependencies # This method binds services, repos, etc.
86
- ])
80
+ # Step 3: Create the Injector and configure all dependencies in one place
81
+ self._injector = Injector(self._configure_core_dependencies)
87
82
 
88
83
  # Step 4: Register routes using the fully configured injector
89
84
  self._register_routes()
@@ -102,7 +97,6 @@ class IAToolkit:
102
97
  logging.info(f"🎉 IAToolkit v{VERSION} inicializado correctamente")
103
98
  return self.app
104
99
 
105
-
106
100
  def _get_config_value(self, key: str, default=None):
107
101
  """Obtiene un valor de configuración, primero del dict config, luego de env vars"""
108
102
  return self.config.get(key, os.getenv(key, default))
@@ -228,7 +222,8 @@ class IAToolkit:
228
222
  """⚙️ Configures all system dependencies."""
229
223
  try:
230
224
  # Core dependencies
231
- binder.bind(Injector, to=self._injector, scope=singleton)
225
+ binder.bind(Flask, to=self.app, scope=singleton)
226
+ binder.bind(DatabaseManager, to=self.db_manager, scope=singleton)
232
227
 
233
228
  # Bind all application components by calling the specific methods
234
229
  self._bind_repositories(binder)
@@ -317,16 +312,17 @@ class IAToolkit:
317
312
 
318
313
  def _setup_cli_commands(self):
319
314
  """⌨️ Configura comandos CLI básicos"""
315
+ from services.dispatcher_service import Dispatcher
316
+ from services.profile_service import ProfileService
320
317
 
321
318
  @self.app.cli.command("init-db")
322
319
  def init_db():
323
320
  """🗄️ Inicializa la base de datos del sistema"""
324
321
  try:
325
- from services.dispatcher_service import Dispatcher
326
- dispatcher = self._get_injector().get(Dispatcher)
322
+ dispatcher = self.get_injector().get(Dispatcher)
327
323
 
328
324
  click.echo("🚀 Inicializando base de datos...")
329
- dispatcher.init_db()
325
+ dispatcher.setup_all_companies()
330
326
  click.echo("✅ Base de datos inicializada correctamente")
331
327
 
332
328
  except Exception as e:
@@ -334,6 +330,34 @@ class IAToolkit:
334
330
  click.echo(f"❌ Error: {e}")
335
331
 
336
332
 
333
+ @self.app.cli.command("setup-company")
334
+ @click.argument("company_short_name")
335
+ def setup_company(company_short_name: str):
336
+ """⚙️ Ejecuta el proceso de configuración para una nueva empresa."""
337
+ try:
338
+ # step 1: init the database
339
+ dispatcher = self.get_injector().get(Dispatcher)
340
+ click.echo("🚀 step 1 of 2: init companies in the database...")
341
+ dispatcher.setup_all_companies()
342
+ click.echo("✅ database is ready.")
343
+
344
+ # step 2: generate the api key
345
+ profile_service = self.get_injector().get(ProfileService)
346
+ click.echo(f"🔑 step 2 of 2: generating api-key for use in '{company_short_name}'...")
347
+ result = profile_service.new_api_key(company_short_name)
348
+
349
+ if 'error' in result:
350
+ click.echo(f"❌ Error in step 2: {result['error']}")
351
+ click.echo("👉 Make sure company name is correct and it's initialized in your app.")
352
+ else:
353
+ click.echo("Configuration es ready, add this variable to your environment")
354
+ click.echo(f"IATOOLKIT_API_KEY={result['api-key']}")
355
+
356
+ except Exception as e:
357
+ logging.exception(e)
358
+ click.echo(f"❌ Ocurrió un error inesperado durante la configuración: {e}")
359
+
360
+
337
361
  def _setup_context_processors(self):
338
362
  # Configura context processors para templates
339
363
  @self.app.context_processor
@@ -362,7 +386,7 @@ class IAToolkit:
362
386
  except:
363
387
  return 'templates'
364
388
 
365
- def _get_injector(self) -> Injector:
389
+ def get_injector(self) -> Injector:
366
390
  """Obtiene el injector actual"""
367
391
  if not self._injector:
368
392
  raise IAToolkitException(
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
7
- Requires-Python: >=3.10
7
+ Requires-Python: >=3.11
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: aiohappyeyeballs==2.4.4
10
10
  Requires-Dist: aiohttp==3.11.9
@@ -206,3 +206,47 @@ Requires-Dist: wrapt==1.17.0
206
206
  Requires-Dist: yarl==1.18.3
207
207
  Requires-Dist: zipp==3.21.0
208
208
  Requires-Dist: zstandard==0.23.0
209
+
210
+ # iatoolkit
211
+
212
+ IAToolkit is a comprehensive, open-source framework designed for building enterprise-grade
213
+ AI chatbots and conversational applications.
214
+ Built on Flask with dependency injection, it provides a robust foundation for scalable AI solutions.
215
+
216
+ ## 🚀 Key Features
217
+ - **Universal LLM Integration**: OpenAI GPT, Google Gemini
218
+ - **Template System**: Jinja2-powered prompt templates with variables
219
+ - **Context Management**: Maintain conversation context across sessions
220
+
221
+ ### 🔒 **Enterprise Security**
222
+ - **JWT Authentication**: Secure token-based authentication
223
+ - **Session Management**: Redis-backed secure sessions
224
+ - **CORS Configuration**: Flexible cross-origin resource sharing
225
+
226
+ ### 🛠 **Function Calling & Tools**
227
+ - **Native Function Calls**: Direct integration with LLM function calling
228
+ - **Custom Tools**: Build and register custom tools for your chatbot
229
+ - **SQL Query Generation**: Natural language to SQL conversion
230
+ - **API Integrations**: Connect to external services and APIs
231
+
232
+ ### 🗄 **Database & Storage**
233
+ - **Multi-Database Support**: PostgreSQL, MySQL, SQLite via SQLAlchemy
234
+ - **Vector Store Integration**: Semantic search and retrieval
235
+ - **Document Processing**: PDF, Word, Excel, and text file handling
236
+
237
+ ### 📊 **Analytics & Monitoring**
238
+ - **Query Logging**: Track all LLM interactions
239
+ - **Performance Metrics**: Response times, token usage, costs
240
+ - **Benchmarking**: Compare model performance
241
+ - **Task Management**: Async task processing with status tracking
242
+
243
+ ### 🔧 **Developer Experience**
244
+ - **Dependency Injection**: Clean, testable architecture
245
+ - **CLI Tools**: Command-line interface for common tasks
246
+ - **Hot Reloading**: Development-friendly configuration
247
+ - **Comprehensive Logging**: Debug and monitor easily
248
+
249
+ ## License
250
+ MIT License
251
+
252
+
@@ -1,11 +1,11 @@
1
- iatoolkit/__init__.py,sha256=Yu9XbQmEjs0gA1HBnqiaORL7HUfoKuEElUIs8scg4IQ,1125
1
+ iatoolkit/__init__.py,sha256=JdcXIcvFFTMy2XI9ccEws_pCklilDkPPEb7RaQNf7oY,1444
2
2
  iatoolkit/base_company.py,sha256=VWfpNofFlmgHQQK8BCw2KSOPLd2DM9eA68lGQ3SDE7M,1639
3
- iatoolkit/company_registry.py,sha256=saOf5JxsEtvAs-JqkNp-UfOIQvtVCXyujvv6G5_zi5k,3332
4
- iatoolkit/iatoolkit.py,sha256=YX5Oh-WWBKX0DDrzeOeaNoBrPLm0O7t4ttntYC_rk-8,15186
3
+ iatoolkit/company_registry.py,sha256=cRaez-VBo1icnUNKmkQqo_Xlr8UKWFoYEMZ70XP6Jgk,2702
4
+ iatoolkit/iatoolkit.py,sha256=K7d8fKKTk-Q-sMW6Ip58oleiosRP4e-pdc3E5GSoSMw,16450
5
5
  services/__init__.py,sha256=fSvSfIcPW1dHwTBY1hQ5dBEhaoorzk_GzR4G46gD8tY,173
6
- services/api_service.py,sha256=VTM5OfKF7-eCT-dpl46ZnZ3ptbTxLUDH2IxnbS4T3jA,1113
6
+ services/api_service.py,sha256=InIKTc64BWcp4U4tYKHz28x4ErPxIfvR9x3ZlxJZlXs,2911
7
7
  services/benchmark_service.py,sha256=g9JVrmAqIe_iI0D1DwdQ6DJ2_FJRCTndarESNSVfhbw,5907
8
- services/dispatcher_service.py,sha256=iNu_gUZS_AgbwmCxtLBk0A33-jxsnMGYAKI5ScaJ-yE,13207
8
+ services/dispatcher_service.py,sha256=CBslIE5FsrST46JjpKW1k_XHnIRtN9WehEr6LKadZlU,13360
9
9
  services/document_service.py,sha256=sm5QtbrKs2dF9hpLuSLMB-IMWYNBD7yWHv3rd80aD0o,5960
10
10
  services/excel_service.py,sha256=wE9Udbyb96kGRSnZZ6KM2mbE484rKjTEhta9GKKpy-8,3630
11
11
  services/file_processor_service.py,sha256=82UArWtwpr94CAMkkoRP0_nPtoqItymdKSIABS0Xkxw,2943
@@ -13,15 +13,15 @@ services/history_service.py,sha256=dl-D7qgdnzpY9QhjuxJokBYZZ1AF0y59HbRzwpPet58,1
13
13
  services/jwt_service.py,sha256=dC45Sn6FyzdzRiQJnzgkjN3Hy21V1imRxB0hTyWRvlA,3979
14
14
  services/load_documents_service.py,sha256=_-OTUih8Zk0m4dHqAhkE7kAwU2mbz_QoMrOKnrq7ZWs,8821
15
15
  services/mail_service.py,sha256=ystFit1LuYUC4ekYYebyiy1rqYQmxeL6K8h58MxEkOY,2233
16
- services/profile_service.py,sha256=z1dSX45HDv8VJE4w8-ucpb3kBpE2fkyOdtgnrHc9vuE,17918
17
- services/prompt_manager_service.py,sha256=nnr_iNIFeJzOY_1fbuu5-reyJS04RvGx5JW_d3YFUbk,7966
16
+ services/profile_service.py,sha256=YtnlXofXtvud4AHOFMmPlX9VO7mhs_Fglpc1PTulExc,17861
17
+ services/prompt_manager_service.py,sha256=kKsqZyt2ZUWIHYTA5C6sfBk8sbXhvYF4QAUN9sOYk_s,7915
18
18
  services/query_service.py,sha256=Fx_P1WcuoAp_TyocN5LGlv_hc_03ImzU5QdAIqQg0ek,15591
19
19
  services/search_service.py,sha256=oJD6WRXCJBD7WUVHWWKxexRkhR8nQSrFtcPV3pFO2KQ,1153
20
20
  services/sql_service.py,sha256=H7CIPpXTcxLXLojD2fBFr_mIAD0PW1vEJhKHLfJi4Hk,1418
21
21
  services/tasks_service.py,sha256=hHJDlcsSOPtEleD6_Vv3pocfxWNmthIhmZSdnoWFpEM,6861
22
22
  services/user_feedback_service.py,sha256=YtCndRBekDEWYEbac431Ksn2gMO5iBrI3WqKK0xtShE,2513
23
23
  services/user_session_context_service.py,sha256=5qn7fqpuiU8KgMpU4M5-iRUsETumz1raBw-EeZLuE1A,3868
24
- iatoolkit-0.3.2.dist-info/METADATA,sha256=AE1OLko65VWq_UUTE5isDj_4Qd3IXeYD_-v0oO569uU,7026
25
- iatoolkit-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- iatoolkit-0.3.2.dist-info/top_level.txt,sha256=dqlBbmgo9okD9d_WMR9uYzdup7Rxgj26yFF85jRGeu4,19
27
- iatoolkit-0.3.2.dist-info/RECORD,,
24
+ iatoolkit-0.3.4.dist-info/METADATA,sha256=fiepVsfr8K9meQEu6b5xlOFZX4KJ1npM2m9mMgC6Y9Q,8801
25
+ iatoolkit-0.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ iatoolkit-0.3.4.dist-info/top_level.txt,sha256=dqlBbmgo9okD9d_WMR9uYzdup7Rxgj26yFF85jRGeu4,19
27
+ iatoolkit-0.3.4.dist-info/RECORD,,
services/api_service.py CHANGED
@@ -7,24 +7,69 @@ from infra.call_service import CallServiceClient
7
7
  from injector import inject
8
8
  from common.exceptions import IAToolkitException
9
9
  import json
10
-
10
+ from typing import Optional, Dict, Any, Union
11
11
 
12
12
  class ApiService:
13
13
  @inject
14
14
  def __init__(self, call_service: CallServiceClient):
15
15
  self.call_service = call_service
16
16
 
17
- def call_api(self, endpoint: str, method: str, **kwargs):
18
- if method == 'get':
19
- response, status_code = self.call_service.get(endpoint)
20
- elif method == 'post':
21
- response, status_code = self.call_service.post(endpoint=endpoint, json_dict=kwargs)
17
+ def call_api(
18
+ self,
19
+ endpoint: str,
20
+ method: str,
21
+ headers: Optional[Dict[str, str]] = None,
22
+ params: Optional[Dict[str, Union[str, int, float, bool]]] = None,
23
+ body: Optional[Dict[str, Any]] = None,
24
+ files: Optional[Dict[str, Any]] = None,
25
+ timeout: Union[int, float, tuple] = 10
26
+ ) -> str:
27
+ """
28
+ Ejecuta una llamada HTTP genérica.
29
+
30
+ - endpoint: URL completa
31
+ - method: GET | POST | PUT | DELETE (case-insensitive)
32
+ - headers: dict opcional de cabeceras
33
+ - params: dict opcional de query string
34
+ - body: dict opcional para JSON (POST/PUT/DELETE)
35
+ - files: dict opcional para multipart/form-data (prioriza POST files)
36
+ - timeout: segundos (int/float) o tuple (connect, read)
37
+ """
38
+ m = (method or "").strip().lower()
39
+
40
+ if m == "get":
41
+ response, status_code = self.call_service.get(
42
+ endpoint, params=params, headers=headers, timeout=timeout
43
+ )
44
+ elif m == "post":
45
+ # Si vienen files → multipart; si no → JSON
46
+ if files:
47
+ response, status_code = self.call_service.post_files(
48
+ endpoint, data=files, params=params, headers=headers, timeout=timeout
49
+ )
50
+ else:
51
+ response, status_code = self.call_service.post(
52
+ endpoint=endpoint, json_dict=body, params=params, headers=headers, timeout=timeout
53
+ )
54
+ elif m == "put":
55
+ response, status_code = self.call_service.put(
56
+ endpoint, json_dict=body, params=params, headers=headers, timeout=timeout
57
+ )
58
+ elif m == "delete":
59
+ response, status_code = self.call_service.delete(
60
+ endpoint, json_dict=body, params=params, headers=headers, timeout=timeout
61
+ )
22
62
  else:
23
- raise IAToolkitException(IAToolkitException.ErrorType.INVALID_PARAMETER,
24
- f'API error, {method} not supported')
63
+ raise IAToolkitException(
64
+ IAToolkitException.ErrorType.INVALID_PARAMETER,
65
+ f"API error: método '{method}' no soportado"
66
+ )
25
67
 
26
- if status_code != 200:
27
- raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR,
28
- f'API {endpoint} error: {status_code}')
68
+ if status_code < 200 or status_code >= 300:
69
+ raise IAToolkitException(
70
+ IAToolkitException.ErrorType.CALL_ERROR,
71
+ f"API {endpoint} error: {status_code}"
72
+ )
29
73
 
74
+ # Normalizamos a string JSON (para que el LLM lo consuma consistente)
30
75
  return json.dumps(response)
@@ -6,6 +6,7 @@
6
6
  from iatoolkit import current_iatoolkit
7
7
  from common.exceptions import IAToolkitException
8
8
  from services.prompt_manager_service import PromptService
9
+ from services.api_service import ApiService
9
10
  from repositories.llm_query_repo import LLMQueryRepo
10
11
  from repositories.models import Company, Function
11
12
  from services.excel_service import ExcelService
@@ -23,10 +24,12 @@ class Dispatcher:
23
24
  prompt_service: PromptService,
24
25
  llmquery_repo: LLMQueryRepo,
25
26
  util: Utility,
27
+ api_service: ApiService,
26
28
  excel_service: ExcelService,
27
29
  mail_service: MailService):
28
30
  self.prompt_service = prompt_service
29
31
  self.llmquery_repo = llmquery_repo
32
+ self.api_service = api_service
30
33
  self.util = util
31
34
  self.excel_service = excel_service
32
35
  self.mail_service = mail_service
@@ -36,41 +39,42 @@ class Dispatcher:
36
39
  # Use the global registry
37
40
  self.company_registry = get_company_registry()
38
41
 
39
- # The dispatcher starts "empty" and will be initialized later.
42
+ # load into the dispatcher the configured companies
40
43
  self.company_classes = {}
41
44
  self.initialize_companies()
42
45
 
46
+ # run the statrtup logic for all companies
47
+ self.start_execution()
48
+
43
49
  self.tool_handlers = {
44
50
  "iat_generate_excel": self.excel_service.excel_generator,
45
51
  "iat_send_email": self.mail_service.send_mail,
52
+ "iat_api_call": self.api_service.call_api
46
53
  }
47
54
 
48
55
  def initialize_companies(self):
49
56
  """
50
57
  Initializes and instantiates all registered company classes.
51
- This method should be called *after* the main injector is fully configured.
58
+ This method should be called *after* the main injector is fully configured
59
+ and the company registry is populated.
52
60
  """
53
61
  if self.company_classes: # Prevent re-initialization
54
62
  return
55
63
 
56
64
  # ✅ NOW it is safe to get the injector and instantiate companies.
57
- injector = current_iatoolkit()._get_injector()
65
+ injector = current_iatoolkit().get_injector()
58
66
  self.company_registry.set_injector(injector)
59
67
  self.company_classes = self.company_registry.instantiate_companies()
60
68
 
61
69
  def start_execution(self):
62
70
  """Runs the startup logic for all registered companies."""
63
- # Ensure companies are initialized before starting them
64
- if not self.company_classes:
65
- self.initialize_companies()
66
-
67
71
  for company_name, company_instance in self.company_classes.items():
68
72
  logging.info(f'Starting execution for company: {company_name}')
69
73
  company_instance.start_execution()
70
74
 
71
75
  return True
72
76
 
73
- def init_db(self):
77
+ def setup_all_companies(self):
74
78
  # create system functions
75
79
  for function in self.system_functions:
76
80
  self.llmquery_repo.create_or_update_function(
@@ -96,10 +100,9 @@ class Dispatcher:
96
100
 
97
101
  # initialize the database for every company class
98
102
  for company in self.company_classes.values():
99
- print(f'inicializando clase: {company.__class__.__name__}')
103
+ print(f'company: {company.__class__.__name__}')
100
104
  company.init_db()
101
105
 
102
-
103
106
  def dispatch(self, company_name: str, action: str, **kwargs) -> str:
104
107
  company_key = company_name.lower()
105
108
 
@@ -266,7 +266,7 @@ class ProfileService:
266
266
 
267
267
  api_key = ApiKey(key=key, company_id=company.id)
268
268
  self.profile_repo.create_api_key(api_key)
269
- return {"message": f"La nueva clave de API para {company_short_name} es: {key}"}
269
+ return {"api-key": key}
270
270
 
271
271
 
272
272
  def send_verification_email(self, new_user: User, company_short_name):
@@ -11,6 +11,7 @@ from collections import defaultdict
11
11
  from repositories.models import Prompt, PromptCategory, Company
12
12
  import os
13
13
  from common.exceptions import IAToolkitException
14
+ from pathlib import Path
14
15
 
15
16
 
16
17
  class PromptService:
@@ -32,7 +33,7 @@ class PromptService:
32
33
 
33
34
  prompt_filename = prompt_name.lower() + '.prompt'
34
35
  if is_system_prompt:
35
- template_dir = 'prompts'
36
+ template_dir = 'src/system_prompts'
36
37
  else:
37
38
  template_dir = f'companies/{company.short_name}/prompts'
38
39
 
@@ -103,16 +104,15 @@ class PromptService:
103
104
  system_prompt_content = []
104
105
 
105
106
  # get the filepaths for all system prompts
106
- current_dir = os.path.dirname(os.path.abspath(__file__))
107
- src_dir = os.path.dirname(current_dir) # ../src
108
- system_prompt_dir = os.path.join(src_dir, "prompts")
107
+ current_dir = Path(__file__).resolve().parent
108
+ project_root = current_dir.parent.parent
109
109
 
110
- # Obtener, ordenar y leer los system prompts
110
+ # read all the system prompts from the database
111
111
  system_prompts = self.llm_query_repo.get_system_prompts()
112
112
 
113
113
  for prompt in system_prompts:
114
- # Construir la ruta absoluta para leer el archivo
115
- absolute_filepath = os.path.join(system_prompt_dir, prompt.filepath)
114
+ # build the absolute filepath for reading it
115
+ absolute_filepath = os.path.join(project_root, prompt.filepath)
116
116
  if not os.path.exists(absolute_filepath):
117
117
  logging.warning(f"El archivo para el prompt de sistema no existe: {absolute_filepath}")
118
118
  continue
@@ -123,7 +123,7 @@ class PromptService:
123
123
  raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
124
124
  f"Error leyendo el archivo de prompt del sistema {absolute_filepath}: {e}")
125
125
 
126
- # Unir todo el contenido en un solo string
126
+ # join the system prompts into a single string
127
127
  return "\n".join(system_prompt_content)
128
128
 
129
129
  except IAToolkitException: