iatoolkit 0.8.1__py3-none-any.whl → 0.63.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 +8 -34
- iatoolkit/base_company.py +14 -3
- iatoolkit/common/routes.py +83 -52
- iatoolkit/common/session_manager.py +0 -1
- iatoolkit/common/util.py +0 -27
- iatoolkit/iatoolkit.py +61 -46
- iatoolkit/infra/llm_client.py +7 -8
- iatoolkit/infra/openai_adapter.py +1 -1
- iatoolkit/infra/redis_session_manager.py +48 -2
- iatoolkit/repositories/database_manager.py +17 -2
- iatoolkit/repositories/models.py +31 -6
- iatoolkit/repositories/profile_repo.py +7 -2
- iatoolkit/services/auth_service.py +188 -0
- iatoolkit/services/branding_service.py +147 -0
- iatoolkit/services/dispatcher_service.py +10 -40
- iatoolkit/services/excel_service.py +15 -15
- iatoolkit/services/history_service.py +3 -12
- iatoolkit/services/jwt_service.py +15 -24
- iatoolkit/services/onboarding_service.py +43 -0
- iatoolkit/services/profile_service.py +97 -44
- iatoolkit/services/query_service.py +124 -81
- iatoolkit/services/tasks_service.py +1 -1
- iatoolkit/services/user_feedback_service.py +67 -31
- iatoolkit/services/user_session_context_service.py +112 -54
- iatoolkit/static/images/fernando.jpeg +0 -0
- iatoolkit/static/js/{chat_feedback.js → chat_feedback_button.js} +6 -11
- iatoolkit/static/js/chat_history_button.js +126 -0
- iatoolkit/static/js/chat_logout_button.js +36 -0
- iatoolkit/static/js/chat_main.js +130 -220
- iatoolkit/static/js/chat_onboarding_button.js +97 -0
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/js/chat_reload_button.js +52 -0
- iatoolkit/static/styles/chat_iatoolkit.css +329 -507
- iatoolkit/static/styles/chat_modal.css +95 -56
- iatoolkit/static/styles/landing_page.css +182 -0
- iatoolkit/static/styles/onboarding.css +169 -0
- iatoolkit/system_prompts/query_main.prompt +3 -12
- iatoolkit/templates/_company_header.html +20 -0
- iatoolkit/templates/_login_widget.html +40 -0
- iatoolkit/templates/base.html +8 -3
- iatoolkit/templates/change_password.html +54 -37
- iatoolkit/templates/chat.html +149 -66
- iatoolkit/templates/chat_modals.html +47 -18
- iatoolkit/templates/error.html +41 -8
- iatoolkit/templates/forgot_password.html +37 -24
- iatoolkit/templates/index.html +140 -0
- iatoolkit/templates/login_simulation.html +34 -0
- iatoolkit/templates/onboarding_shell.html +105 -0
- iatoolkit/templates/signup.html +64 -66
- iatoolkit/views/base_login_view.py +81 -0
- iatoolkit/views/change_password_view.py +23 -12
- iatoolkit/views/external_login_view.py +61 -28
- iatoolkit/views/{file_store_view.py → file_store_api_view.py} +9 -2
- iatoolkit/views/forgot_password_view.py +23 -13
- iatoolkit/views/history_api_view.py +52 -0
- iatoolkit/views/home_view.py +58 -25
- iatoolkit/views/index_view.py +14 -0
- iatoolkit/views/init_context_api_view.py +68 -0
- iatoolkit/views/llmquery_api_view.py +45 -0
- iatoolkit/views/login_simulation_view.py +81 -0
- iatoolkit/views/login_view.py +118 -34
- iatoolkit/views/logout_api_view.py +45 -0
- iatoolkit/views/{prompt_view.py → prompt_api_view.py} +7 -7
- iatoolkit/views/signup_view.py +38 -29
- iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
- iatoolkit/views/tasks_review_api_view.py +55 -0
- iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -31
- iatoolkit/views/verify_user_view.py +13 -8
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/METADATA +2 -2
- iatoolkit-0.63.4.dist-info/RECORD +113 -0
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/top_level.txt +0 -1
- iatoolkit/common/auth.py +0 -200
- iatoolkit/static/images/arrow_up.png +0 -0
- iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- iatoolkit/static/images/logo_clinica.png +0 -0
- iatoolkit/static/images/logo_iatoolkit.png +0 -0
- iatoolkit/static/images/logo_maxxa.png +0 -0
- iatoolkit/static/images/logo_notaria.png +0 -0
- iatoolkit/static/images/logo_tarjeta.png +0 -0
- iatoolkit/static/images/logo_umayor.png +0 -0
- iatoolkit/static/images/upload.png +0 -0
- iatoolkit/static/js/chat_history.js +0 -117
- iatoolkit/templates/home.html +0 -201
- iatoolkit/templates/login.html +0 -43
- iatoolkit/views/chat_token_request_view.py +0 -98
- iatoolkit/views/chat_view.py +0 -51
- iatoolkit/views/download_file_view.py +0 -58
- iatoolkit/views/external_chat_login_view.py +0 -88
- iatoolkit/views/history_view.py +0 -57
- iatoolkit/views/llmquery_view.py +0 -65
- iatoolkit/views/tasks_review_view.py +0 -83
- iatoolkit-0.8.1.dist-info/RECORD +0 -175
- tests/__init__.py +0 -5
- tests/common/__init__.py +0 -0
- tests/common/test_auth.py +0 -279
- tests/common/test_routes.py +0 -42
- tests/common/test_session_manager.py +0 -59
- tests/common/test_util.py +0 -444
- tests/companies/__init__.py +0 -5
- tests/conftest.py +0 -36
- tests/infra/__init__.py +0 -5
- tests/infra/connectors/__init__.py +0 -5
- tests/infra/connectors/test_google_drive_connector.py +0 -107
- tests/infra/connectors/test_local_file_connector.py +0 -85
- tests/infra/connectors/test_s3_connector.py +0 -95
- tests/infra/test_call_service.py +0 -92
- tests/infra/test_database_manager.py +0 -59
- tests/infra/test_gemini_adapter.py +0 -137
- tests/infra/test_google_chat_app.py +0 -68
- tests/infra/test_llm_client.py +0 -165
- tests/infra/test_llm_proxy.py +0 -122
- tests/infra/test_mail_app.py +0 -94
- tests/infra/test_openai_adapter.py +0 -105
- tests/infra/test_redis_session_manager_service.py +0 -117
- tests/repositories/__init__.py +0 -5
- tests/repositories/test_database_manager.py +0 -87
- tests/repositories/test_document_repo.py +0 -76
- tests/repositories/test_llm_query_repo.py +0 -340
- tests/repositories/test_models.py +0 -38
- tests/repositories/test_profile_repo.py +0 -142
- tests/repositories/test_tasks_repo.py +0 -76
- tests/repositories/test_vs_repo.py +0 -107
- tests/services/__init__.py +0 -5
- tests/services/test_dispatcher_service.py +0 -274
- tests/services/test_document_service.py +0 -181
- tests/services/test_excel_service.py +0 -208
- tests/services/test_file_processor_service.py +0 -121
- tests/services/test_history_service.py +0 -164
- tests/services/test_jwt_service.py +0 -255
- tests/services/test_load_documents_service.py +0 -112
- tests/services/test_mail_service.py +0 -70
- tests/services/test_profile_service.py +0 -379
- tests/services/test_prompt_manager_service.py +0 -190
- tests/services/test_query_service.py +0 -243
- tests/services/test_search_service.py +0 -39
- tests/services/test_sql_service.py +0 -160
- tests/services/test_tasks_service.py +0 -252
- tests/services/test_user_feedback_service.py +0 -389
- tests/services/test_user_session_context_service.py +0 -132
- tests/views/__init__.py +0 -5
- tests/views/test_change_password_view.py +0 -191
- tests/views/test_chat_token_request_view.py +0 -188
- tests/views/test_chat_view.py +0 -98
- tests/views/test_download_file_view.py +0 -149
- tests/views/test_external_chat_login_view.py +0 -120
- tests/views/test_external_login_view.py +0 -102
- tests/views/test_file_store_view.py +0 -128
- tests/views/test_forgot_password_view.py +0 -142
- tests/views/test_history_view.py +0 -336
- tests/views/test_home_view.py +0 -61
- tests/views/test_llm_query_view.py +0 -154
- tests/views/test_login_view.py +0 -114
- tests/views/test_prompt_view.py +0 -111
- tests/views/test_signup_view.py +0 -140
- tests/views/test_tasks_review_view.py +0 -104
- tests/views/test_tasks_view.py +0 -130
- tests/views/test_user_feedback_view.py +0 -214
- tests/views/test_verify_user_view.py +0 -110
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/WHEEL +0 -0
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from unittest.mock import patch, MagicMock
|
|
7
|
-
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
8
|
-
import pytest
|
|
9
|
-
|
|
10
|
-
class TestDatabaseManager:
|
|
11
|
-
def setup_method(self):
|
|
12
|
-
self.mock_engine = MagicMock()
|
|
13
|
-
self.mock_sessionmaker = MagicMock()
|
|
14
|
-
self.mock_scoped_session = MagicMock()
|
|
15
|
-
self.mock_base_metadata = MagicMock()
|
|
16
|
-
self.mock_inspect = MagicMock()
|
|
17
|
-
|
|
18
|
-
self.database_url = "sqlite:///:memory:"
|
|
19
|
-
|
|
20
|
-
# Lista para almacenar todos los patches
|
|
21
|
-
self.patchers = []
|
|
22
|
-
|
|
23
|
-
# Crear y agregar patches a la lista
|
|
24
|
-
patcher_engine = patch('iatoolkit.repositories.database_manager.create_engine', return_value=self.mock_engine)
|
|
25
|
-
patcher_sessionmaker = patch('iatoolkit.repositories.database_manager.sessionmaker', return_value=self.mock_sessionmaker)
|
|
26
|
-
patcher_scoped_session = patch('iatoolkit.repositories.database_manager.scoped_session',
|
|
27
|
-
return_value=self.mock_scoped_session)
|
|
28
|
-
patcher_metadata = patch('iatoolkit.repositories.database_manager.Base.metadata', self.mock_base_metadata)
|
|
29
|
-
patcher_inspect = patch('iatoolkit.repositories.database_manager.inspect', self.mock_inspect)
|
|
30
|
-
|
|
31
|
-
self.patchers.extend(
|
|
32
|
-
[patcher_engine, patcher_sessionmaker, patcher_scoped_session, patcher_metadata, patcher_inspect])
|
|
33
|
-
|
|
34
|
-
# Inicia todos los patches y almacena los mocks retornados si es necesario
|
|
35
|
-
self.mock_create_engine = patcher_engine.start()
|
|
36
|
-
self.mock_sessionmaker_function = patcher_sessionmaker.start()
|
|
37
|
-
self.mock_scoped_session_function = patcher_scoped_session.start()
|
|
38
|
-
self.mock_inspect = patcher_inspect.start()
|
|
39
|
-
patcher_metadata.start()
|
|
40
|
-
|
|
41
|
-
self.db_manager = DatabaseManager(self.database_url)
|
|
42
|
-
|
|
43
|
-
def teardown_method(self):
|
|
44
|
-
for patcher in self.patchers:
|
|
45
|
-
patcher.stop()
|
|
46
|
-
|
|
47
|
-
def test_init_initializes_engine_and_session_factory(self):
|
|
48
|
-
self.mock_create_engine.assert_called_once_with(self.database_url, echo=False)
|
|
49
|
-
self.mock_sessionmaker_function.assert_called_once_with(bind=self.mock_engine)
|
|
50
|
-
|
|
51
|
-
def test_get_session_returns_scoped_session(self):
|
|
52
|
-
session = self.db_manager.get_session()
|
|
53
|
-
assert session == self.mock_scoped_session()
|
|
54
|
-
|
|
55
|
-
def test_create_all_calls_metadata_create_all(self):
|
|
56
|
-
self.db_manager.create_all()
|
|
57
|
-
assert self.mock_base_metadata.create_all.call_count == 1
|
|
58
|
-
|
|
59
|
-
def test_drop_all_calls_metadata_drop_all(self):
|
|
60
|
-
self.db_manager.drop_all()
|
|
61
|
-
self.mock_base_metadata.drop_all.assert_called_once_with(self.mock_engine)
|
|
62
|
-
|
|
63
|
-
def test_remove_session_calls_scoped_session_remove(self):
|
|
64
|
-
self.db_manager.remove_session()
|
|
65
|
-
self.mock_scoped_session.remove.assert_called_once()
|
|
66
|
-
|
|
67
|
-
def test_get_table_schema_table_exists(self):
|
|
68
|
-
"""Prueba get_table_schema cuando la tabla existe"""
|
|
69
|
-
self.mock_inspect.return_value.get_table_names.return_value = ['test_table']
|
|
70
|
-
self.mock_inspect.return_value.get_columns.return_value = [
|
|
71
|
-
{"name": "id", "type": "INTEGER"},
|
|
72
|
-
{"name": "name", "type": "VARCHAR"}
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
result = self.db_manager.get_table_schema('test_table')
|
|
76
|
-
|
|
77
|
-
# Verificar que el resultado contiene la información esperada
|
|
78
|
-
assert "{'table': 'test_table', 'description': 'Definición de la tabla test_table.', 'fields': [{'name': 'id', 'type': 'INTEGER'}, {'name': 'name', 'type': 'VARCHAR'}]}" == result.strip()
|
|
79
|
-
|
|
80
|
-
def test_get_table_schema_table_not_exists(self):
|
|
81
|
-
"""Prueba get_table_schema cuando la tabla no existe"""
|
|
82
|
-
self.mock_inspect.return_value.get_table_names.return_value = []
|
|
83
|
-
|
|
84
|
-
with pytest.raises(RuntimeError) as exc_info:
|
|
85
|
-
self.db_manager.get_table_schema('non_existent_table')
|
|
86
|
-
|
|
87
|
-
assert "La tabla 'non_existent_table' no existe en la BD" in str(exc_info.value)
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from unittest.mock import MagicMock
|
|
8
|
-
from iatoolkit.repositories.models import Document, Company
|
|
9
|
-
from iatoolkit.repositories.document_repo import DocumentRepo
|
|
10
|
-
from iatoolkit.common.exceptions import IAToolkitException
|
|
11
|
-
import base64
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TestDocumentRepo:
|
|
15
|
-
def setup_method(self):
|
|
16
|
-
# Mock the DatabaseManager
|
|
17
|
-
self.mock_db_manager = MagicMock()
|
|
18
|
-
self.session = self.mock_db_manager.get_session()
|
|
19
|
-
|
|
20
|
-
# Initialize DocumentRepo with the mocked DatabaseManager
|
|
21
|
-
self.repo = DocumentRepo(self.mock_db_manager)
|
|
22
|
-
self.mock_document = Document(company_id=1,
|
|
23
|
-
filename='test.txt',
|
|
24
|
-
content='123',
|
|
25
|
-
content_b64=base64.b64encode('123'.encode('utf-8')).decode('utf-8'),
|
|
26
|
-
meta={'repertorio_id': 10})
|
|
27
|
-
self.mock_company = Company(name='company')
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def test_insert_when_ok(self):
|
|
31
|
-
self.repo.insert(self.mock_document)
|
|
32
|
-
|
|
33
|
-
# Assert
|
|
34
|
-
self.session.add.assert_called()
|
|
35
|
-
self.session.commit.assert_called()
|
|
36
|
-
|
|
37
|
-
def test_get_missing_company(self):
|
|
38
|
-
# Act & Assert
|
|
39
|
-
with pytest.raises(IAToolkitException) as exc_info:
|
|
40
|
-
self.repo.get(None, filename="test_file.txt")
|
|
41
|
-
|
|
42
|
-
assert exc_info.value.error_type == IAToolkitException.ErrorType.PARAM_NOT_FILLED
|
|
43
|
-
|
|
44
|
-
def test_get_document_by_filename(self):
|
|
45
|
-
self.session.query.return_value.filter_by.return_value.first.return_value = self.mock_document
|
|
46
|
-
|
|
47
|
-
# Act
|
|
48
|
-
result = self.repo.get(self.mock_company, filename="test_file.txt")
|
|
49
|
-
|
|
50
|
-
# Assert
|
|
51
|
-
assert result == self.mock_document
|
|
52
|
-
self.session.query.assert_called()
|
|
53
|
-
|
|
54
|
-
def test_get_by_id_when_id_is_none(self):
|
|
55
|
-
result = self.repo.get_by_id(0)
|
|
56
|
-
|
|
57
|
-
assert result is None
|
|
58
|
-
self.session.query.assert_not_called()
|
|
59
|
-
|
|
60
|
-
def test_get_by_id_when_document_not_found(self):
|
|
61
|
-
self.session.query.return_value.filter_by.return_value.first.return_value = None
|
|
62
|
-
|
|
63
|
-
result = self.repo.get_by_id(999)
|
|
64
|
-
|
|
65
|
-
assert result is None
|
|
66
|
-
self.session.query.assert_called()
|
|
67
|
-
|
|
68
|
-
def test_get_by_id_when_document_exists(self):
|
|
69
|
-
self.session.query.return_value.filter_by.return_value.first.return_value = self.mock_document
|
|
70
|
-
|
|
71
|
-
result = self.repo.get_by_id(1)
|
|
72
|
-
|
|
73
|
-
assert result == self.mock_document
|
|
74
|
-
self.session.query.assert_called()
|
|
75
|
-
|
|
76
|
-
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
7
|
-
from iatoolkit.repositories.models import LLMQuery, Function, Company, Prompt, PromptCategory
|
|
8
|
-
from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
|
|
9
|
-
from datetime import datetime, timedelta
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TestLLMQueryRepo:
|
|
13
|
-
def setup_method(self):
|
|
14
|
-
self.db_manager = DatabaseManager('sqlite:///:memory:')
|
|
15
|
-
self.db_manager.create_all()
|
|
16
|
-
self.session = self.db_manager.get_session()
|
|
17
|
-
self.repo = LLMQueryRepo(self.db_manager)
|
|
18
|
-
self.query = LLMQuery(id=1, company_id=2,
|
|
19
|
-
user_identifier='user_1',
|
|
20
|
-
query="test query",
|
|
21
|
-
output='an output',
|
|
22
|
-
response={'answer': 'an answer'},
|
|
23
|
-
answer_time=3)
|
|
24
|
-
self.function = Function(name="function1",
|
|
25
|
-
company_id=1,
|
|
26
|
-
description="A description",
|
|
27
|
-
parameters={'name': 'value'})
|
|
28
|
-
self.company = Company(name='test_company',
|
|
29
|
-
short_name='test')
|
|
30
|
-
self.session.add(self.company)
|
|
31
|
-
self.session.commit()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def test_add_query_when_success(self):
|
|
35
|
-
new_query = self.repo.add_query(self.query)
|
|
36
|
-
assert new_query.id == 1
|
|
37
|
-
|
|
38
|
-
def test_get_company_functions_when_ok(self):
|
|
39
|
-
self.function.company_id = self.company.id
|
|
40
|
-
|
|
41
|
-
self.session.add(self.function)
|
|
42
|
-
self.session.commit()
|
|
43
|
-
assert len(self.repo.get_company_functions(self.company)) == 1
|
|
44
|
-
|
|
45
|
-
def test_create_or_update_function_when_new_function(self):
|
|
46
|
-
new_function = Function(name="function1",
|
|
47
|
-
company_id=1,
|
|
48
|
-
description="A description",
|
|
49
|
-
parameters={'name': 'value'})
|
|
50
|
-
result = self.repo.create_or_update_function(new_function=new_function)
|
|
51
|
-
assert result.id is not None
|
|
52
|
-
assert result.name == "function1"
|
|
53
|
-
assert result.description == "A description"
|
|
54
|
-
|
|
55
|
-
def test_create_or_update_function_when_updating_function(self):
|
|
56
|
-
# Add an initial function
|
|
57
|
-
function = Function(name="function1",
|
|
58
|
-
company_id=self.company.id,
|
|
59
|
-
description="A description",
|
|
60
|
-
parameters={'name': 'value'})
|
|
61
|
-
self.session.add(function)
|
|
62
|
-
self.session.commit()
|
|
63
|
-
|
|
64
|
-
# Update the description
|
|
65
|
-
upd_function = Function(name="function1",
|
|
66
|
-
company_id=self.company.id,
|
|
67
|
-
description="New description",
|
|
68
|
-
parameters={'name': 'value 2'})
|
|
69
|
-
result = self.repo.create_or_update_function(new_function=upd_function)
|
|
70
|
-
assert result.id == function.id
|
|
71
|
-
assert result.description == "New description"
|
|
72
|
-
assert result.parameters['name'] == 'value 2'
|
|
73
|
-
|
|
74
|
-
def test_create_or_update_prompt_when_new_prompt(self):
|
|
75
|
-
new_prompt = Prompt(name="prompt1",
|
|
76
|
-
company_id=self.company.id,
|
|
77
|
-
description="an intelligent prompt",
|
|
78
|
-
filename='')
|
|
79
|
-
result = self.repo.create_or_update_prompt(new_prompt=new_prompt)
|
|
80
|
-
assert result.id is not None
|
|
81
|
-
assert result.name == "prompt1"
|
|
82
|
-
assert result.description == "an intelligent prompt"
|
|
83
|
-
assert result.active is True
|
|
84
|
-
|
|
85
|
-
def test_create_or_update_prompt_when_updating_prompt(self):
|
|
86
|
-
|
|
87
|
-
category = self.repo.create_or_update_prompt_category(PromptCategory(name='Cobranzas', order=6,
|
|
88
|
-
company_id=self.company.id))
|
|
89
|
-
prompt = Prompt(name="prompt1",
|
|
90
|
-
company_id=self.company.id,
|
|
91
|
-
category_id=category.id,
|
|
92
|
-
active=True,
|
|
93
|
-
order=1,
|
|
94
|
-
description="an intelligent prompt",
|
|
95
|
-
filename='')
|
|
96
|
-
self.session.add(prompt)
|
|
97
|
-
self.session.commit()
|
|
98
|
-
|
|
99
|
-
# Update the description
|
|
100
|
-
upd_prompt = Prompt(name="prompt1",
|
|
101
|
-
company_id=self.company.id,
|
|
102
|
-
category_id=category.id,
|
|
103
|
-
active=True,
|
|
104
|
-
order=3,
|
|
105
|
-
description="a super intelligent prompt",
|
|
106
|
-
filename='')
|
|
107
|
-
result = self.repo.create_or_update_prompt(new_prompt=upd_prompt)
|
|
108
|
-
assert result.description == "a super intelligent prompt"
|
|
109
|
-
assert result.id == prompt.id
|
|
110
|
-
|
|
111
|
-
def test_get_history_empty_result(self):
|
|
112
|
-
"""Test get_history when no queries exist for the user"""
|
|
113
|
-
# Get history for non-existent user
|
|
114
|
-
history = self.repo.get_history(self.company, 'nonexistent_user')
|
|
115
|
-
|
|
116
|
-
# Should return empty list
|
|
117
|
-
assert len(history) == 0
|
|
118
|
-
assert history == []
|
|
119
|
-
|
|
120
|
-
def test_get_history_different_company(self):
|
|
121
|
-
"""Test get_history filters by company_id correctly"""
|
|
122
|
-
# Add two companies
|
|
123
|
-
company1 = Company(name='company1', short_name='comp1')
|
|
124
|
-
company2 = Company(name='company2', short_name='comp2')
|
|
125
|
-
self.session.add(company1)
|
|
126
|
-
self.session.add(company2)
|
|
127
|
-
self.session.commit()
|
|
128
|
-
|
|
129
|
-
# Create queries for different companies
|
|
130
|
-
query1 = LLMQuery(
|
|
131
|
-
company_id=company1.id,
|
|
132
|
-
user_identifier='user123',
|
|
133
|
-
query="Company 1 query",
|
|
134
|
-
output='Company 1 output',
|
|
135
|
-
response={'answer': 'Company 1 answer'},
|
|
136
|
-
answer_time=3
|
|
137
|
-
)
|
|
138
|
-
query2 = LLMQuery(
|
|
139
|
-
company_id=company2.id,
|
|
140
|
-
user_identifier='user123',
|
|
141
|
-
query="Company 2 query",
|
|
142
|
-
output='Company 2 output',
|
|
143
|
-
response={'answer': 'Company 2 answer'},
|
|
144
|
-
answer_time=3
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
# Add queries to database
|
|
148
|
-
self.session.add(query1)
|
|
149
|
-
self.session.add(query2)
|
|
150
|
-
self.session.commit()
|
|
151
|
-
|
|
152
|
-
# Get history for company1
|
|
153
|
-
history1 = self.repo.get_history(company1, 'user123')
|
|
154
|
-
assert len(history1) == 1
|
|
155
|
-
assert history1[0].query == "Company 1 query"
|
|
156
|
-
|
|
157
|
-
# Get history for company2
|
|
158
|
-
history2 = self.repo.get_history(company2, 'user123')
|
|
159
|
-
assert len(history2) == 1
|
|
160
|
-
assert history2[0].query == "Company 2 query"
|
|
161
|
-
|
|
162
|
-
def test_get_history_limit_100(self):
|
|
163
|
-
"""Test get_history respects the limit of 100 queries"""
|
|
164
|
-
# Create 110 queries
|
|
165
|
-
queries = []
|
|
166
|
-
base_time = datetime(2024, 1, 15, 10, 30, 0)
|
|
167
|
-
for i in range(110):
|
|
168
|
-
# Use timedelta to create unique timestamps
|
|
169
|
-
query = LLMQuery(
|
|
170
|
-
company_id=self.company.id,
|
|
171
|
-
user_identifier='user123',
|
|
172
|
-
query=f"Query {i}",
|
|
173
|
-
output=f'Output {i}',
|
|
174
|
-
response={'answer': f'Answer {i}'},
|
|
175
|
-
answer_time=3,
|
|
176
|
-
created_at=base_time + timedelta(seconds=i) # Different timestamps
|
|
177
|
-
)
|
|
178
|
-
queries.append(query)
|
|
179
|
-
|
|
180
|
-
# Add all queries to database
|
|
181
|
-
for query in queries:
|
|
182
|
-
self.session.add(query)
|
|
183
|
-
self.session.commit()
|
|
184
|
-
|
|
185
|
-
# Get history
|
|
186
|
-
history = self.repo.get_history(self.company, 'user123')
|
|
187
|
-
|
|
188
|
-
# Should return only 100 queries (limit)
|
|
189
|
-
assert len(history) == 100
|
|
190
|
-
# Should be ordered by created_at desc (newest first)
|
|
191
|
-
assert history[0].query == "Query 109" # Newest
|
|
192
|
-
assert history[99].query == "Query 10" # 100th newest
|
|
193
|
-
|
|
194
|
-
def test_get_history_mixed_user_types(self):
|
|
195
|
-
"""Test get_history correctly filters by user type"""
|
|
196
|
-
# Create queries for different user types
|
|
197
|
-
external_query = LLMQuery(
|
|
198
|
-
company_id=self.company.id,
|
|
199
|
-
user_identifier='external_user',
|
|
200
|
-
query="External user query",
|
|
201
|
-
output='External output',
|
|
202
|
-
response={'answer': 'External answer'},
|
|
203
|
-
answer_time=3
|
|
204
|
-
)
|
|
205
|
-
local_query = LLMQuery(
|
|
206
|
-
company_id=self.company.id,
|
|
207
|
-
user_identifier='user_456',
|
|
208
|
-
query="Local user query",
|
|
209
|
-
output='Local output',
|
|
210
|
-
response={'answer': 'Local answer'},
|
|
211
|
-
answer_time=3
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
# Add queries to database
|
|
215
|
-
self.session.add(external_query)
|
|
216
|
-
self.session.add(local_query)
|
|
217
|
-
self.session.commit()
|
|
218
|
-
|
|
219
|
-
# Get history for external user
|
|
220
|
-
external_history = self.repo.get_history(self.company, 'external_user')
|
|
221
|
-
assert len(external_history) == 1
|
|
222
|
-
assert external_history[0].query == "External user query"
|
|
223
|
-
|
|
224
|
-
# Get history for local user
|
|
225
|
-
local_history = self.repo.get_history(self.company, 'user_456')
|
|
226
|
-
assert len(local_history) == 1
|
|
227
|
-
assert local_history[0].query == "Local user query"
|
|
228
|
-
|
|
229
|
-
def test_get_history_ordering(self):
|
|
230
|
-
"""Test get_history orders by created_at desc correctly"""
|
|
231
|
-
|
|
232
|
-
# Create queries with different timestamps
|
|
233
|
-
old_query = LLMQuery(
|
|
234
|
-
company_id=self.company.id,
|
|
235
|
-
user_identifier='user123',
|
|
236
|
-
query="Old query",
|
|
237
|
-
output='Old output',
|
|
238
|
-
response={'answer': 'Old answer'},
|
|
239
|
-
answer_time=3,
|
|
240
|
-
created_at=datetime(2024, 1, 15, 10, 30, 0)
|
|
241
|
-
)
|
|
242
|
-
new_query = LLMQuery(
|
|
243
|
-
company_id=self.company.id,
|
|
244
|
-
user_identifier='user123',
|
|
245
|
-
query="New query",
|
|
246
|
-
output='New output',
|
|
247
|
-
response={'answer': 'New answer'},
|
|
248
|
-
answer_time=3,
|
|
249
|
-
created_at=datetime(2024, 1, 15, 11, 30, 0)
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
# Add queries to database
|
|
253
|
-
self.session.add(old_query)
|
|
254
|
-
self.session.add(new_query)
|
|
255
|
-
self.session.commit()
|
|
256
|
-
|
|
257
|
-
# Get history
|
|
258
|
-
history = self.repo.get_history(self.company, 'user123')
|
|
259
|
-
|
|
260
|
-
# Should be ordered by created_at desc (newest first)
|
|
261
|
-
assert len(history) == 2
|
|
262
|
-
assert history[0].query == "New query" # Newest first
|
|
263
|
-
assert history[1].query == "Old query" # Oldest last
|
|
264
|
-
|
|
265
|
-
def test_get_history_no_company_queries(self):
|
|
266
|
-
"""Test get_history when company exists but has no queries"""
|
|
267
|
-
|
|
268
|
-
# Get history for company with no queries
|
|
269
|
-
history = self.repo.get_history(self.company, 'user123')
|
|
270
|
-
|
|
271
|
-
# Should return empty list
|
|
272
|
-
assert len(history) == 0
|
|
273
|
-
assert history == []
|
|
274
|
-
|
|
275
|
-
def test_get_prompts_when_prompts_exist(self):
|
|
276
|
-
"""Test get_prompts returns all prompts for a company."""
|
|
277
|
-
# Create active and inactive prompts for the same company
|
|
278
|
-
prompt1 = Prompt(name="active_prompt",
|
|
279
|
-
company_id=self.company.id,
|
|
280
|
-
description="An active prompt",
|
|
281
|
-
active=True,
|
|
282
|
-
filename='')
|
|
283
|
-
prompt2 = Prompt(name="inactive_prompt",
|
|
284
|
-
company_id=self.company.id,
|
|
285
|
-
description="An inactive prompt",
|
|
286
|
-
active=False,
|
|
287
|
-
filename='')
|
|
288
|
-
|
|
289
|
-
self.session.add_all([prompt1, prompt2])
|
|
290
|
-
self.session.commit()
|
|
291
|
-
|
|
292
|
-
# Get prompts for the company
|
|
293
|
-
prompts = self.repo.get_prompts(self.company)
|
|
294
|
-
|
|
295
|
-
# Should return both prompts
|
|
296
|
-
assert len(prompts) == 2
|
|
297
|
-
prompt_names = {p.name for p in prompts}
|
|
298
|
-
assert "active_prompt" in prompt_names
|
|
299
|
-
assert "inactive_prompt" in prompt_names
|
|
300
|
-
|
|
301
|
-
def test_get_prompts_when_no_prompts_exist(self):
|
|
302
|
-
"""Test get_prompts returns an empty list when a company has no prompts."""
|
|
303
|
-
# Get prompts for a company with no prompts
|
|
304
|
-
prompts = self.repo.get_prompts(self.company)
|
|
305
|
-
|
|
306
|
-
# Should return an empty list
|
|
307
|
-
assert len(prompts) == 0
|
|
308
|
-
assert prompts == []
|
|
309
|
-
|
|
310
|
-
def test_get_prompts_filters_by_company(self):
|
|
311
|
-
"""Test get_prompts only returns prompts for the specified company."""
|
|
312
|
-
# Create another company
|
|
313
|
-
other_company = Company(name='other_company', short_name='other')
|
|
314
|
-
self.session.add(other_company)
|
|
315
|
-
self.session.commit()
|
|
316
|
-
|
|
317
|
-
# Create a prompt for the main company
|
|
318
|
-
prompt1 = Prompt(name="main_company_prompt",
|
|
319
|
-
company_id=self.company.id,
|
|
320
|
-
description="Prompt for the main company",
|
|
321
|
-
filename='')
|
|
322
|
-
|
|
323
|
-
# Create a prompt for the other company
|
|
324
|
-
prompt2 = Prompt(name="other_company_prompt",
|
|
325
|
-
company_id=other_company.id,
|
|
326
|
-
description="Prompt for the other company",
|
|
327
|
-
filename='')
|
|
328
|
-
|
|
329
|
-
self.session.add_all([prompt1, prompt2])
|
|
330
|
-
self.session.commit()
|
|
331
|
-
|
|
332
|
-
# Get prompts for the main company
|
|
333
|
-
prompts = self.repo.get_prompts(self.company)
|
|
334
|
-
|
|
335
|
-
# Should only return the prompt for the main company
|
|
336
|
-
assert len(prompts) == 1
|
|
337
|
-
assert prompts[0].name == "main_company_prompt"
|
|
338
|
-
assert prompts[0].company_id == self.company.id
|
|
339
|
-
|
|
340
|
-
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from unittest.mock import patch, MagicMock
|
|
7
|
-
from iatoolkit.repositories.models import Company, Function, Document, User, LLMQuery, VSDoc
|
|
8
|
-
from sqlalchemy.orm import relationship
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TestModels:
|
|
12
|
-
def setup_method(self):
|
|
13
|
-
self.mock_base = MagicMock()
|
|
14
|
-
|
|
15
|
-
# Aquí almacenamos las referencias de los objetos mock retornados
|
|
16
|
-
self.mock_relationship = patch('sqlalchemy.orm.relationship', MagicMock(return_value=relationship)).start()
|
|
17
|
-
self.mock_column = patch('sqlalchemy.Column', MagicMock()).start()
|
|
18
|
-
self.mock_integer = patch('sqlalchemy.Integer', MagicMock()).start()
|
|
19
|
-
self.mock_string = patch('sqlalchemy.String', MagicMock()).start()
|
|
20
|
-
self.mock_float = patch('sqlalchemy.Float', MagicMock()).start()
|
|
21
|
-
self.mock_date_time = patch('sqlalchemy.DateTime', MagicMock()).start()
|
|
22
|
-
self.mock_json = patch('sqlalchemy.JSON', MagicMock()).start()
|
|
23
|
-
self.mock_foreign_key = patch('sqlalchemy.ForeignKey', MagicMock()).start()
|
|
24
|
-
|
|
25
|
-
self.model_classes = [Company, Function, Document, User, LLMQuery, VSDoc]
|
|
26
|
-
|
|
27
|
-
def teardown_method(self):
|
|
28
|
-
patch.stopall()
|
|
29
|
-
|
|
30
|
-
def test_model_definitions(self):
|
|
31
|
-
for model_class in self.model_classes:
|
|
32
|
-
instance = model_class() # Asegurarse de que se puedan instanciar correctamente
|
|
33
|
-
instance.to_dict()
|
|
34
|
-
assert instance is not None
|
|
35
|
-
|
|
36
|
-
def test_relationship_calls(self):
|
|
37
|
-
# Ahora usamos call_count en el mock generado
|
|
38
|
-
assert self.mock_relationship.call_count == 0
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
7
|
-
from iatoolkit.repositories.models import User, Company, UserFeedback
|
|
8
|
-
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TestProfileRepo:
|
|
12
|
-
def setup_method(self):
|
|
13
|
-
self.db_manager = DatabaseManager('sqlite:///:memory:')
|
|
14
|
-
self.db_manager.create_all()
|
|
15
|
-
self.session = self.db_manager.get_session()
|
|
16
|
-
self.repo = ProfileRepo(self.db_manager)
|
|
17
|
-
|
|
18
|
-
self.user = User(email='fernando@opensoft.cl',
|
|
19
|
-
first_name='Fernando',
|
|
20
|
-
last_name='Libedinsky',
|
|
21
|
-
password='123')
|
|
22
|
-
|
|
23
|
-
self.company = Company(name='opensoft', short_name='open')
|
|
24
|
-
|
|
25
|
-
def test_get_user_by_id_when_not_found(self):
|
|
26
|
-
result = self.repo.get_user_by_id(2)
|
|
27
|
-
assert result is None
|
|
28
|
-
|
|
29
|
-
def test_get_user_by_id_when_success(self):
|
|
30
|
-
self.session.add(self.user)
|
|
31
|
-
result = self.repo.get_user_by_id(1)
|
|
32
|
-
assert result == self.user
|
|
33
|
-
|
|
34
|
-
def test_get_user_by_email_when_not_found(self):
|
|
35
|
-
result = self.repo.get_user_by_email('fl@opensoft')
|
|
36
|
-
assert result is None
|
|
37
|
-
|
|
38
|
-
def test_get_user_by_email_when_success(self):
|
|
39
|
-
self.session.add(self.user)
|
|
40
|
-
result = self.repo.get_user_by_email('fernando@opensoft.cl')
|
|
41
|
-
assert result == self.user
|
|
42
|
-
|
|
43
|
-
def test_create_user_when_ok(self):
|
|
44
|
-
new_user = self.repo.create_user(self.user)
|
|
45
|
-
assert new_user.id == 1
|
|
46
|
-
|
|
47
|
-
def test_save_and_update_user_when_ok(self):
|
|
48
|
-
new_user = self.repo.create_user(self.user)
|
|
49
|
-
new_user.first_name = 'fernando'
|
|
50
|
-
|
|
51
|
-
updated_user = self.repo.save_user(new_user)
|
|
52
|
-
assert updated_user.id == 1
|
|
53
|
-
|
|
54
|
-
def test_update_user_when_not_exist(self):
|
|
55
|
-
user = self.repo.update_user(self.user.email, first_name='Fernando')
|
|
56
|
-
assert user == None
|
|
57
|
-
|
|
58
|
-
def test_verify_user_when_ok(self):
|
|
59
|
-
self.session.add(self.user)
|
|
60
|
-
user = self.repo.verify_user(self.user.email)
|
|
61
|
-
assert user.verified == True
|
|
62
|
-
|
|
63
|
-
def test_set_temp_code_when_ok(self):
|
|
64
|
-
self.session.add(self.user)
|
|
65
|
-
temp_code = 'CCGT'
|
|
66
|
-
user = self.repo.set_temp_code(self.user.email,temp_code)
|
|
67
|
-
|
|
68
|
-
assert user.temp_code == temp_code
|
|
69
|
-
|
|
70
|
-
def test_reset_temp_code_when_ok(self):
|
|
71
|
-
self.session.add(self.user)
|
|
72
|
-
user = self.repo.reset_temp_code(self.user.email)
|
|
73
|
-
|
|
74
|
-
assert user.temp_code == None
|
|
75
|
-
|
|
76
|
-
def test_update_password_when_ok(self):
|
|
77
|
-
self.session.add(self.user)
|
|
78
|
-
hashed_password = 'ggdvXz'
|
|
79
|
-
user = self.repo.update_password(self.user.email, hashed_password)
|
|
80
|
-
|
|
81
|
-
assert user.password == hashed_password
|
|
82
|
-
|
|
83
|
-
def test_get_company_when_no_exist(self):
|
|
84
|
-
assert self.repo.get_company('opensoft') == None
|
|
85
|
-
|
|
86
|
-
def test_get_company_when_ok(self):
|
|
87
|
-
self.session.add(self.company)
|
|
88
|
-
assert self.repo.get_company('opensoft') == self.company
|
|
89
|
-
assert self.repo.get_company_by_short_name('open') == self.company
|
|
90
|
-
|
|
91
|
-
def test_get_company_by_id_when_not_found(self):
|
|
92
|
-
result = self.repo.get_company_by_id(999)
|
|
93
|
-
|
|
94
|
-
assert result is None
|
|
95
|
-
|
|
96
|
-
def test_get_company_by_id_when_success(self):
|
|
97
|
-
self.session.add(self.company)
|
|
98
|
-
|
|
99
|
-
result = self.repo.get_company_by_id(1)
|
|
100
|
-
assert result == self.company
|
|
101
|
-
|
|
102
|
-
def test_get_companies_when_no_companies_exist(self):
|
|
103
|
-
result = self.repo.get_companies()
|
|
104
|
-
assert result == []
|
|
105
|
-
|
|
106
|
-
def test_get_companies_when_companies_exist(self):
|
|
107
|
-
company_opensoft = Company(name='Opensoft', short_name='open')
|
|
108
|
-
company_testlabs = Company(name='TestLabs', short_name='test')
|
|
109
|
-
self.session.add(company_opensoft)
|
|
110
|
-
self.session.add(company_testlabs)
|
|
111
|
-
self.session.commit()
|
|
112
|
-
|
|
113
|
-
result = self.repo.get_companies()
|
|
114
|
-
|
|
115
|
-
assert len(result) == 2
|
|
116
|
-
assert result[0].name == 'Opensoft'
|
|
117
|
-
assert result[1].name == 'TestLabs'
|
|
118
|
-
|
|
119
|
-
def test_create_company_when_company_exists(self):
|
|
120
|
-
self.session.add(self.company)
|
|
121
|
-
|
|
122
|
-
result = self.repo.create_company(Company(name='opensoft'))
|
|
123
|
-
|
|
124
|
-
assert result.id == self.company.id
|
|
125
|
-
assert result.name == self.company.name
|
|
126
|
-
|
|
127
|
-
def test_create_company_when_new_company(self):
|
|
128
|
-
result = self.repo.create_company(Company(name='NewCompany', short_name='new'))
|
|
129
|
-
|
|
130
|
-
assert result.id is not None
|
|
131
|
-
assert result.name == 'NewCompany'
|
|
132
|
-
|
|
133
|
-
def test_save_feedback_when_ok(self):
|
|
134
|
-
company = self.repo.create_company(Company(name='my_company', short_name='my_company'))
|
|
135
|
-
feedback = UserFeedback(company_id=company.id,
|
|
136
|
-
external_user_id='flibe',
|
|
137
|
-
message='feedback message',
|
|
138
|
-
rating=4)
|
|
139
|
-
new_feed = self.repo.save_feedback(feedback)
|
|
140
|
-
assert new_feed.message == 'feedback message'
|
|
141
|
-
assert new_feed.rating == 4
|
|
142
|
-
|