QuentinL52 commited on
Commit
90c84b7
·
verified ·
1 Parent(s): c3a4252

Create core/rag_handler.py

Browse files
Files changed (1) hide show
  1. src/core/rag_handler.py +130 -0
src/core/rag_handler.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ from typing import Optional, List
4
+ from langchain_community.document_loaders import DirectoryLoader, TextLoader
5
+ from langchain_community.vectorstores import FAISS
6
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ _embeddings_model = None
11
+ _rag_handler_instance = None
12
+
13
+ VECTOR_STORE_PATH = "/tmp/vector_store"
14
+
15
+ def get_embeddings_model():
16
+ global _embeddings_model
17
+ if _embeddings_model is None:
18
+ from langchain_huggingface import HuggingFaceEmbeddings
19
+ logger.info("Initialisation du modèle d'embeddings...")
20
+ _embeddings_model = HuggingFaceEmbeddings(
21
+ model_name='sentence-transformers/all-MiniLM-L6-v2',
22
+ model_kwargs={'device': 'cpu'},
23
+ encode_kwargs={'normalize_embeddings': True}
24
+ )
25
+ logger.info("✅ Modèle d'embeddings initialisé avec succès")
26
+ return _embeddings_model
27
+
28
+ class RAGHandler:
29
+ def __init__(self, knowledge_base_path: str = "/app/knowledge_base", lazy_init: bool = True):
30
+ self.knowledge_base_path = knowledge_base_path
31
+ self.embeddings = None
32
+ self.vector_store = None
33
+ self._initialized = False
34
+
35
+ os.makedirs(VECTOR_STORE_PATH, exist_ok=True)
36
+
37
+ if not lazy_init:
38
+ self._initialize()
39
+
40
+ def _initialize(self):
41
+ if self._initialized:
42
+ return
43
+
44
+ logger.info("Initialisation du RAG Handler...")
45
+ self.embeddings = get_embeddings_model()
46
+
47
+ if self.embeddings is None:
48
+ logger.error("Impossible d'initialiser les embeddings")
49
+ return
50
+
51
+ self.vector_store = self._load_or_create_vector_store(self.knowledge_base_path)
52
+ self._initialized = True
53
+ logger.info("✅ RAG Handler initialisé avec succès")
54
+
55
+ def _load_documents(self, path: str) -> List:
56
+ if not os.path.exists(path):
57
+ logger.warning(f"Répertoire {path} non trouvé")
58
+ return []
59
+
60
+ loader = DirectoryLoader(
61
+ path,
62
+ glob="**/*.md",
63
+ loader_cls=TextLoader,
64
+ loader_kwargs={"encoding": "utf-8"}
65
+ )
66
+ logger.info(f"Chargement des documents depuis : {path}")
67
+ documents = loader.load()
68
+ logger.info(f"✅ {len(documents)} documents chargés")
69
+ return documents
70
+
71
+ def _create_vector_store(self, knowledge_base_path: str) -> Optional[FAISS]:
72
+ documents = self._load_documents(knowledge_base_path)
73
+ if not documents:
74
+ logger.warning("Aucun document trouvé - création d'un vector store vide")
75
+ from langchain.schema import Document
76
+ dummy_doc = Document(
77
+ page_content="Document de test pour initialiser le vector store",
78
+ metadata={"source": "dummy"}
79
+ )
80
+ documents = [dummy_doc]
81
+
82
+ logger.info(f"{len(documents)} documents chargés. Création des vecteurs...")
83
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
84
+ texts = text_splitter.split_documents(documents)
85
+
86
+ vector_store = FAISS.from_documents(texts, self.embeddings)
87
+
88
+ vector_store.save_local(VECTOR_STORE_PATH)
89
+ logger.info(f"✅ Vector store créé et sauvegardé dans : {VECTOR_STORE_PATH}")
90
+
91
+ return vector_store
92
+
93
+ def _load_or_create_vector_store(self, knowledge_base_path: str) -> Optional[FAISS]:
94
+ index_path = os.path.join(VECTOR_STORE_PATH, "index.faiss")
95
+ if os.path.exists(index_path):
96
+ logger.info(f"Chargement du vector store existant depuis : {VECTOR_STORE_PATH}")
97
+ return FAISS.load_local(
98
+ VECTOR_STORE_PATH,
99
+ embeddings=self.embeddings,
100
+ allow_dangerous_deserialization=True
101
+ )
102
+ else:
103
+ logger.info("Aucun vector store trouvé. Création d'un nouveau...")
104
+ return self._create_vector_store(knowledge_base_path)
105
+
106
+ def get_relevant_feedback(self, query: str, k: int = 1) -> List[str]:
107
+ if not self._initialized:
108
+ self._initialize()
109
+
110
+ if not self.vector_store:
111
+ logger.warning("Vector store non disponible - retour de conseils génériques")
112
+ return [
113
+ "Préparez vos réponses aux questions comportementales",
114
+ "Montrez votre motivation pour le poste",
115
+ "Donnez des exemples concrets de vos réalisations"
116
+ ]
117
+
118
+ results = self.vector_store.similarity_search(query, k=k)
119
+ feedback = [doc.page_content for doc in results if doc.page_content.strip()]
120
+
121
+ if not feedback:
122
+ return ["Conseil général: Préparez-vous bien pour les entretiens futurs."]
123
+
124
+ return feedback
125
+
126
+ def get_rag_handler() -> Optional[RAGHandler]:
127
+ global _rag_handler_instance
128
+ if _rag_handler_instance is None:
129
+ _rag_handler_instance = RAGHandler(lazy_init=True)
130
+ return _rag_handler_instance