Coverage for src/app/dependencies/dependency_inj.py: 91%
214 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-03 00:42 +0200
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-03 00:42 +0200
1import psycopg2
2import os
3from dotenv import load_dotenv
4from flask import Flask, request, jsonify
5from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity, get_jwt
6from flask_bcrypt import Bcrypt
7from datetime import timedelta
9from langchain_openai import OpenAIEmbeddings
10from langchain_community.vectorstores import FAISS
11from langchain_openai import ChatOpenAI
13from dependencies.init_vector_store import VECTOR_STORE_PATH, load_vector_store
14from config.db_config import db_config
16from controllers.add_file_controller import AddFileController
17from controllers.chat_controller import ChatController
18from controllers.delete_template_controller import DeleteTemplateController
19from controllers.get_conversation_controller import GetConversationController
20from controllers.get_conversations_controller import GetConversationsController
21from controllers.get_message_controller import GetMessageController
22from controllers.get_messages_by_conversation_controller import GetMessagesByConversationController
23from controllers.get_dashboard_metrics_controller import GetDashboardMetricsController
24from controllers.get_support_message_controller import GetSupportMessageController
25from controllers.get_support_messages_controller import GetSupportMessagesController
26from controllers.mark_done_support_message_contoller import MarkDoneSupportMessagesController
27from controllers.get_template_controller import GetTemplateController
28from controllers.get_template_list_controller import GetTemplateListController
29from controllers.save_conversation_title_controller import SaveConversationTitleController
30from controllers.delete_conversation_controller import DeleteConversationController
31from controllers.save_message_controller import SaveMessageController
32from controllers.update_message_rating_controller import UpdateMessageRatingController
33from controllers.save_support_message_controller import SaveSupportMessageController
34from controllers.save_template_controller import SaveTemplateController
35from controllers.registration_controller import RegistrationController
36from controllers.authentication_controller import AuthenticationController
38from services.chat_service import ChatService
39from services.similarity_search_service import SimilaritySearchService
40from services.generate_answer_service import GenerateAnswerService
41from services.add_file_service import AddFileService
42from services.split_file_service import SplitFileService
43from services.add_chunks_service import AddChunksService
44from services.delete_template_service import DeleteTemplateService
45from services.get_conversation_service import GetConversationService
46from services.get_conversations_service import GetConversationsService
47from services.get_message_service import GetMessageService
48from services.get_messages_by_conversation_service import GetMessagesByConversationService
49from services.get_dashboard_metrics_services import GetDashboardMetricsService
50from services.get_support_message_service import GetSupportMessageService
51from services.get_support_messages_service import GetSupportMessagesService
52from services.mark_done_support_message_services import MarkDoneSupportMessagesService
53from services.get_template_list_service import GetTemplateListService
54from services.get_template_service import GetTemplateService
55from services.save_conversation_title_service import SaveConversationTitleService
56from services.delete_conversation_service import DeleteConversationService
57from services.save_message_service import SaveMessageService
58from services.update_message_rating_service import UpdateMessageRatingService
59from services.save_support_message_service import SaveSupportMessageService
60from services.save_template_service import SaveTemplateService
61from services.registration_service import RegistrationService
62from services.validation_service import ValidationService
63from services.authentication_service import AuthenticationService
65from adapters.faiss_adapter import FaissAdapter
66from adapters.langChain_adapter import LangChainAdapter
67from adapters.conversation_postgres_adapter import ConversationPostgresAdapter
68from adapters.message_postgres_adapter import MessagePostgresAdapter
69from adapters.support_message_postgres_adapter import SupportMessagePostgresAdapter
70from adapters.template_postgres_adapter import TemplatePostgresAdapter
71from adapters.user_postgres_adapter import UserPostgresAdapter
73from repositories.faiss_repository import FaissRepository
74from repositories.langChain_repository import LangChainRepository
75from repositories.conversation_postgres_repository import ConversationPostgresRepository
76from repositories.message_postgres_repository import MessagePostgresRepository
77from repositories.support_message_postgres_repository import SupportMessagePostgresRepository
78from repositories.template_postgres_repository import TemplatePostgresRepository
79from repositories.user_postgres_repository import UserPostgresRepository
81from models.prompt_template_model import PromptTemplateModel
83load_dotenv()
86def initialize_postgres():
87 """
88 """
89 try:
91 conn = psycopg2.connect(**db_config)
92 with conn.cursor() as cursor:
93 cursor.execute("""
94 CREATE TABLE IF NOT EXISTS Users (
95 id SERIAL PRIMARY KEY,
96 username VARCHAR(256) NOT NULL UNIQUE,
97 password_hash VARCHAR(512) NOT NULL,
98 email VARCHAR(256) NOT NULL UNIQUE,
99 phone CHAR(16),
100 first_name VARCHAR(256) NOT NULL,
101 last_name VARCHAR(256) NOT NULL,
102 is_admin BOOLEAN DEFAULT FALSE
103 );
104 """)
105 cursor.execute("""
106 CREATE TABLE IF NOT EXISTS Conversations (
107 id SERIAL PRIMARY KEY,
108 title VARCHAR(256) NOT NULL
109 );
110 """)
111 cursor.execute("""
112 CREATE TABLE IF NOT EXISTS Messages (
113 id SERIAL PRIMARY KEY,
114 text VARCHAR(1024) NOT NULL,
115 created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
116 user_id INTEGER,
117 conversation_id INTEGER NOT NULL,
118 rating BOOLEAN,
119 FOREIGN KEY (user_id) REFERENCES Users(id) ON DELETE CASCADE,
120 FOREIGN KEY (conversation_id) REFERENCES Conversations(id) ON DELETE CASCADE
121 );
122 """)
123 cursor.execute("""
124 CREATE TABLE IF NOT EXISTS Support (
125 id SERIAL PRIMARY KEY,
126 user_id INTEGER NOT NULL,
127 description VARCHAR(1024) NOT NULL,
128 status BOOLEAN DEFAULT FALSE,
129 subject VARCHAR(256) NOT NULL,
130 created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
131 FOREIGN KEY (user_id) REFERENCES Users(id) ON DELETE CASCADE
132 );
133 """)
134 cursor.execute("""
135 CREATE TABLE IF NOT EXISTS Templates (
136 id SERIAL PRIMARY KEY,
137 question VARCHAR(1024) NOT NULL,
138 answer VARCHAR(1024) NOT NULL,
139 author INTEGER NOT NULL,
140 last_modified TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
141 FOREIGN KEY (author) REFERENCES Users(id) ON DELETE CASCADE
142 );
143 """)
144 conn.commit()
146 except psycopg2.Error as e:
147 raise Exception(f"Error connecting to Postgres: {e}")
149def initialize_langchain() -> LangChainAdapter:
150 try:
151 # Read API key from .env
152 api_key = os.getenv("OPENAI_API_KEY")
153 if not api_key: 153 ↛ 154line 153 didn't jump to line 154 because the condition on line 153 was never true
154 raise ValueError("OPENAI_API_KEY not found in .env file")
156 model = ChatOpenAI(
157 model="gpt-4o-mini",
158 max_tokens=4000,
159 temperature=0.7,
160 request_timeout=15
161 )
163 langchain_repository = LangChainRepository(model)
164 langchain_adapter = LangChainAdapter(langchain_repository)
166 return langchain_adapter
168 except Exception as e:
169 raise Exception(f"Error initializing LangChain: {e}")
172def initialize_faiss() -> FaissAdapter:
173 try:
174 # Read API key from .env
175 api_key = os.getenv("OPENAI_API_KEY")
176 if not api_key: 176 ↛ 177line 176 didn't jump to line 177 because the condition on line 176 was never true
177 raise ValueError("OPENAI_API_KEY not found in .env file")
179 # OpenAI embedding model
180 embedding_model = OpenAIEmbeddings(model="text-embedding-3-small", openai_api_key=api_key)
182 if os.path.exists(VECTOR_STORE_PATH) and os.listdir(VECTOR_STORE_PATH): 182 ↛ 185line 182 didn't jump to line 185 because the condition on line 182 was always true
183 vector_store = load_vector_store(embedding_model)
184 else:
185 vector_store = FAISS.from_texts([""], embedding_model)
187 faiss_repository = FaissRepository(vector_store)
188 faiss_adapter = FaissAdapter(faiss_repository)
190 return faiss_adapter
192 except Exception as e:
193 raise Exception(f"Error initializing FAISS: {e}")
195def initialize_prompt_template() -> PromptTemplateModel:
196 try:
197 # Define the prompt template for the virtual assistant
198 template = "Sei un assistente virtuale esperto, progettato per fornire risposte precise, " \
199 "esaustive e professionali riguardanti l'azienda Valsana. Rispondi alle domande in italiano con un tono professionale, " \
200 "ma accessibile e amichevole, e fai riferimento alle informazioni fornite dall'azienda."
202 return PromptTemplateModel(template)
203 except Exception as e:
204 raise Exception(f"Error initializing prompt template: {e}")
207def initialize_conversation_postgres() -> ConversationPostgresAdapter:
208 try:
209 # Initialize the repository and adapter for conversation-related operations
210 conversation_postgres_repository = ConversationPostgresRepository(db_config)
212 return ConversationPostgresAdapter(conversation_postgres_repository)
213 except Exception as e:
214 raise Exception(f"Error initializing conversation Postgres adapter: {e}")
217def initialize_message_postgres() -> MessagePostgresAdapter:
218 try:
219 # Initialize the repository and adapter for message-related operations
220 message_postgres_repository = MessagePostgresRepository(db_config)
222 return MessagePostgresAdapter(message_postgres_repository)
223 except Exception as e:
224 raise Exception(f"Error initializing message Postgres adapter: {e}")
227def initialize_support_message_postgres() -> SupportMessagePostgresAdapter:
228 try:
229 # Initialize the repository and adapter for support message-related operations
230 support_message_postgres_repository = SupportMessagePostgresRepository(db_config)
232 return SupportMessagePostgresAdapter(support_message_postgres_repository)
233 except Exception as e:
234 raise Exception(f"Error initializing support message Postgres adapter: {e}")
237def initialize_template_postgres() -> TemplatePostgresAdapter:
238 try:
239 # Initialize the repository and adapter for template-related operations
240 template_postgres_repository = TemplatePostgresRepository(db_config)
242 return TemplatePostgresAdapter(template_postgres_repository)
243 except Exception as e:
244 raise Exception(f"Error initializing template Postgres adapter: {e}")
246def initialize_user_postgres() -> UserPostgresAdapter:
247 try:
248 # Initialize the repository and adapter for user-related operations
249 user_postgres_repository = UserPostgresRepository(db_config)
251 return UserPostgresAdapter(user_postgres_repository)
252 except Exception as e:
253 raise Exception(f"Error initializing user Postgres adapter: {e}")
256def dependency_injection(app : Flask) -> dict[str, object]:
257 """
258 Initializes and returns a dictionary of controllers dependencies.
259 Returns:
260 - dict[str, object]: A dictionary of controllers dependencies.
261 """
262 try:
264 # Secure Secret Key
265 app.config["JWT_SECRET_KEY"] = os.getenv("JWT_SECRET_KEY")
266 app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(minutes=100) # Token expires in 30 min
268 jwt = JWTManager(app)
269 bcrypt = Bcrypt(app)
271 # Initialize Postgres
272 initialize_postgres()
274 # Initialize
275 prompt_template = initialize_prompt_template()
277 # Adapter
278 langchain_adapter = initialize_langchain()
279 faiss_adapter = initialize_faiss()
281 # Postgres
282 conversation_postgres_adapter = initialize_conversation_postgres()
283 message_postgres_adapter = initialize_message_postgres()
284 support_message_postgres_adapter = initialize_support_message_postgres()
285 template_postgres_adapter = initialize_template_postgres()
286 user_postgres_adapter = initialize_user_postgres()
288 # Services
289 # Langchain
290 generate_answer_service = GenerateAnswerService(langchain_adapter, prompt_template)
291 split_file_service = SplitFileService(langchain_adapter)
293 # Faiss
294 similarity_search_service = SimilaritySearchService(faiss_adapter)
295 add_chunks_service = AddChunksService(faiss_adapter)
297 # Chat Service
298 add_file_service = AddFileService(split_file_service, add_chunks_service)
299 chat_service = ChatService(similarity_search_service, generate_answer_service)
301 # Postgres
302 get_conversation_service = GetConversationService(conversation_postgres_adapter)
303 get_conversations_service = GetConversationsService(conversation_postgres_adapter)
304 save_conversation_title_service = SaveConversationTitleService(conversation_postgres_adapter)
305 delete_conversation_service = DeleteConversationService(conversation_postgres_adapter)
307 get_message_service = GetMessageService(message_postgres_adapter)
308 get_messages_by_conversation_service = GetMessagesByConversationService(message_postgres_adapter)
309 save_message_service = SaveMessageService(message_postgres_adapter)
310 update_message_rating_service = UpdateMessageRatingService(message_postgres_adapter)
311 get_dashboard_metrics_service = GetDashboardMetricsService(message_postgres_adapter)
313 get_support_message_service = GetSupportMessageService(support_message_postgres_adapter)
314 get_support_messages_service = GetSupportMessagesService(support_message_postgres_adapter)
315 save_support_message_service = SaveSupportMessageService(support_message_postgres_adapter)
316 mark_done_support_messages_services = MarkDoneSupportMessagesService(support_message_postgres_adapter)
318 delete_template_service = DeleteTemplateService(template_postgres_adapter)
319 get_template_service = GetTemplateService(template_postgres_adapter)
320 get_template_list_service = GetTemplateListService(template_postgres_adapter)
321 save_template_service = SaveTemplateService(template_postgres_adapter)
323 validation_service = ValidationService(user_postgres_adapter)
324 registration_service = RegistrationService(user_postgres_adapter, validation_service, bcrypt)
325 authentication_service = AuthenticationService(user_postgres_adapter, bcrypt)
328 # Controllers
329 add_file_controller = AddFileController(add_file_service)
330 chat_controller = ChatController(chat_service)
332 get_conversation_controller = GetConversationController(get_conversation_service)
333 get_conversations_controller = GetConversationsController(get_conversations_service)
334 save_conversation_title_controller = SaveConversationTitleController(save_conversation_title_service)
335 delete_conversation_controller = DeleteConversationController(delete_conversation_service)
337 get_message_controller = GetMessageController(get_message_service)
338 get_messages_by_conversation_controller = GetMessagesByConversationController(get_messages_by_conversation_service)
339 save_message_controller = SaveMessageController(save_message_service)
340 update_message_rating_controller = UpdateMessageRatingController(update_message_rating_service)
341 get_dashboard_metrics_controller = GetDashboardMetricsController(get_dashboard_metrics_service)
343 get_support_message_controller = GetSupportMessageController(get_support_message_service)
344 get_support_messages_controller = GetSupportMessagesController(get_support_messages_service)
345 save_support_message_controller = SaveSupportMessageController(save_support_message_service)
346 mark_done_support_message_controller = MarkDoneSupportMessagesController(mark_done_support_messages_services)
348 delete_template_controller = DeleteTemplateController(delete_template_service)
349 get_template_controller = GetTemplateController(get_template_service)
350 get_template_list_controller = GetTemplateListController(get_template_list_service)
351 save_template_controller = SaveTemplateController(save_template_service)
353 registration_controller = RegistrationController(registration_service)
354 authentication_controller = AuthenticationController(authentication_service)
356 dependencies = {
357 "chat_controller": chat_controller,
358 "add_file_controller": add_file_controller,
359 "get_conversation_controller": get_conversation_controller,
360 "get_conversations_controller": get_conversations_controller,
361 "save_conversation_title_controller": save_conversation_title_controller,
362 "get_message_controller": get_message_controller,
363 "get_messages_by_conversation_controller": get_messages_by_conversation_controller,
364 "save_message_controller": save_message_controller,
365 "update_message_rating_controller": update_message_rating_controller,
366 "get_support_message_controller": get_support_message_controller,
367 "get_support_messages_controller": get_support_messages_controller,
368 "save_support_message_controller": save_support_message_controller,
369 "delete_template_controller": delete_template_controller,
370 "get_template_controller": get_template_controller,
371 "get_template_list_controller": get_template_list_controller,
372 "save_template_controller": save_template_controller,
373 "registration_controller": registration_controller,
374 "authentication_controller": authentication_controller,
375 "delete_conversation_controller": delete_conversation_controller,
376 "mark_done_support_message_controller": mark_done_support_message_controller,
377 "get_dashboard_metrics_controller": get_dashboard_metrics_controller
378 }
380 return dependencies
382 except Exception as e:
383 raise Exception(f"Error during dependency injection: {e}")