Spaces:
Sleeping
Sleeping
Upload 3 files
Browse filesRAG Mistral AI intégrant la sauvegarde du fichier faiss_inde.bin et chunked_docs.pkl s'il n'existe pas, sinon, si la base a déjà été vectorisée, le programme appel directement l'API du LLM de mistral
- RAG_Mistral.py +55 -39
- chunked_docs.pkl +3 -0
- faiss_index.bin +3 -0
RAG_Mistral.py
CHANGED
@@ -16,6 +16,7 @@ import os
|
|
16 |
import numpy as np
|
17 |
import fitz # PyMuPDF pour extraction PDF
|
18 |
import faiss
|
|
|
19 |
import matplotlib.pyplot as plt
|
20 |
from mistralai import Mistral
|
21 |
from sklearn.manifold import TSNE
|
@@ -29,7 +30,7 @@ MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY_static')
|
|
29 |
# 📌 Initialisation du client Mistral
|
30 |
client = Mistral(api_key=MISTRAL_API_KEY)
|
31 |
model_embedding = "mistral-embed"
|
32 |
-
model_chat = "
|
33 |
temperature = 0.1 # Réduction de la température pour privilégier la RAG
|
34 |
probability = 0.9 # Ajustement de la probabilité pour plus de contrôle
|
35 |
|
@@ -37,37 +38,52 @@ probability = 0.9 # Ajustement de la probabilité pour plus de contrôle
|
|
37 |
chunk_size = 256 # Réduction du chunk size pour un meilleur contrôle du contexte
|
38 |
chunk_overlap = 15
|
39 |
|
40 |
-
# 📌
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
embeddings = []
|
51 |
-
|
52 |
-
|
|
|
53 |
embeddings_batch_response = client.embeddings.create(
|
54 |
model=model_embedding,
|
55 |
inputs=batch,
|
56 |
)
|
57 |
batch_embeddings = [data.embedding for data in embeddings_batch_response.data]
|
58 |
embeddings.extend(batch_embeddings)
|
|
|
59 |
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
71 |
|
72 |
# 📌 Récupération des chunks les plus pertinents
|
73 |
def retrieve_relevant_chunks(question, k=5):
|
@@ -77,7 +93,18 @@ def retrieve_relevant_chunks(question, k=5):
|
|
77 |
inputs=[question],
|
78 |
)
|
79 |
question_embedding = np.array(question_embedding_response.data[0].embedding).astype('float32').reshape(1, -1)
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
distances, indices = index.search(question_embedding, k)
|
|
|
|
|
|
|
|
|
|
|
81 |
return [chunked_docs[i] for i in indices[0]]
|
82 |
|
83 |
# 📌 Génération de réponse avec MistralAI
|
@@ -88,11 +115,11 @@ def generate_response(context, question):
|
|
88 |
{"role": "user", "content": question}
|
89 |
]
|
90 |
|
91 |
-
response = client.chat.complete(model=model_chat, messages=messages, temperature=temperature
|
92 |
return response.choices[0].message.content
|
93 |
|
94 |
# 📌 Exécuter une requête utilisateur
|
95 |
-
user_question = "
|
96 |
relevant_chunks = retrieve_relevant_chunks(user_question)
|
97 |
context = "\n".join(relevant_chunks)
|
98 |
answer = generate_response(context, user_question)
|
@@ -101,20 +128,9 @@ answer = generate_response(context, user_question)
|
|
101 |
print("\n🔹 Réponse Mistral :")
|
102 |
print(answer)
|
103 |
|
104 |
-
# # 📊 Visualisation des embeddings avec t-SNE
|
105 |
-
# tsne = TSNE(n_components=2, perplexity=min(30, max(2, embeddings.shape[0] - 1)), random_state=42)
|
106 |
-
# embeddings_2d = tsne.fit_transform(embeddings)
|
107 |
-
|
108 |
-
# plt.figure(figsize=(10, 8))
|
109 |
-
# plt.scatter(embeddings_2d[:, 0], embeddings_2d[:, 1], alpha=0.5)
|
110 |
-
# plt.title('Visualisation des embeddings avec t-SNE')
|
111 |
-
# plt.xlabel('Dimension 1')
|
112 |
-
# plt.ylabel('Dimension 2')
|
113 |
-
# plt.show()
|
114 |
-
|
115 |
# 💾 Sauvegarde des résultats
|
116 |
-
with open("
|
117 |
f.write(f"Question : {user_question}\n")
|
118 |
f.write(f"Réponse :\n{answer}\n")
|
119 |
|
120 |
-
print("\n✅ Réponse enregistrée dans '
|
|
|
16 |
import numpy as np
|
17 |
import fitz # PyMuPDF pour extraction PDF
|
18 |
import faiss
|
19 |
+
import pickle
|
20 |
import matplotlib.pyplot as plt
|
21 |
from mistralai import Mistral
|
22 |
from sklearn.manifold import TSNE
|
|
|
30 |
# 📌 Initialisation du client Mistral
|
31 |
client = Mistral(api_key=MISTRAL_API_KEY)
|
32 |
model_embedding = "mistral-embed"
|
33 |
+
model_chat = "ministral-8b-latest"
|
34 |
temperature = 0.1 # Réduction de la température pour privilégier la RAG
|
35 |
probability = 0.9 # Ajustement de la probabilité pour plus de contrôle
|
36 |
|
|
|
38 |
chunk_size = 256 # Réduction du chunk size pour un meilleur contrôle du contexte
|
39 |
chunk_overlap = 15
|
40 |
|
41 |
+
# 📌 Définition des chemins de stockage
|
42 |
+
index_path = "faiss_index.bin"
|
43 |
+
chunks_path = "chunked_docs.pkl"
|
44 |
+
|
45 |
+
# 📌 Vérification et chargement des données
|
46 |
+
if os.path.exists(index_path) and os.path.exists(chunks_path):
|
47 |
+
print("🔄 Chargement des données existantes...")
|
48 |
+
index = faiss.read_index(index_path) # Charger l'index FAISS
|
49 |
+
with open(chunks_path, "rb") as f:
|
50 |
+
chunked_docs = pickle.load(f) # Charger les chunks de texte
|
51 |
+
print("✅ Index et chunks chargés avec succès !")
|
52 |
+
else:
|
53 |
+
print("⚡ Création et stockage d'un nouvel index FAISS...")
|
54 |
+
|
55 |
+
# 📌 Extraction et segmentation des PDF
|
56 |
+
pdf_folder = 'C:/Users/MIPO10053340/OneDrive - Groupe Avril/Bureau/Salon_Agriculture_2024/Micka_API_Call/Docs_pdf/'
|
57 |
+
chunked_docs = SimpleDirectoryReader(pdf_folder).load_data()
|
58 |
+
chunked_docs = [doc.text for doc in chunked_docs]
|
59 |
+
|
60 |
+
# 📌 Génération des embeddings
|
61 |
embeddings = []
|
62 |
+
batch_size = 5
|
63 |
+
for i in range(0, len(chunked_docs), batch_size):
|
64 |
+
batch = chunked_docs[i:i + batch_size]
|
65 |
embeddings_batch_response = client.embeddings.create(
|
66 |
model=model_embedding,
|
67 |
inputs=batch,
|
68 |
)
|
69 |
batch_embeddings = [data.embedding for data in embeddings_batch_response.data]
|
70 |
embeddings.extend(batch_embeddings)
|
71 |
+
embeddings = np.array(embeddings).astype('float32')
|
72 |
|
73 |
+
# 📌 Vérification avant d’indexer dans FAISS
|
74 |
+
if embeddings is None or len(embeddings) == 0:
|
75 |
+
raise ValueError("⚠️ ERREUR : Aucun embedding généré ! Vérifie l'étape de génération des embeddings.")
|
76 |
+
|
77 |
+
# 📌 Création et stockage de l'index FAISS
|
78 |
+
dimension = embeddings.shape[1]
|
79 |
+
index = faiss.IndexFlatL2(dimension)
|
80 |
+
index.add(embeddings)
|
81 |
+
faiss.write_index(index, index_path) # Sauvegarde de l'index
|
82 |
+
|
83 |
+
# 📌 Sauvegarde des chunks de texte
|
84 |
+
with open(chunks_path, "wb") as f:
|
85 |
+
pickle.dump(chunked_docs, f)
|
86 |
+
print("✅ Index et chunks sauvegardés !")
|
87 |
|
88 |
# 📌 Récupération des chunks les plus pertinents
|
89 |
def retrieve_relevant_chunks(question, k=5):
|
|
|
93 |
inputs=[question],
|
94 |
)
|
95 |
question_embedding = np.array(question_embedding_response.data[0].embedding).astype('float32').reshape(1, -1)
|
96 |
+
|
97 |
+
# Vérification de la compatibilité des dimensions
|
98 |
+
dimension = index.d
|
99 |
+
if question_embedding.shape[1] != dimension:
|
100 |
+
raise ValueError(f"⚠️ ERREUR : La dimension de l'embedding de la question ({question_embedding.shape[1]}) ne correspond pas aux embeddings indexés ({dimension}).")
|
101 |
+
|
102 |
distances, indices = index.search(question_embedding, k)
|
103 |
+
|
104 |
+
if len(indices[0]) == 0:
|
105 |
+
print("⚠️ Avertissement : Aucun chunk pertinent trouvé, réponse possible moins précise.")
|
106 |
+
return []
|
107 |
+
|
108 |
return [chunked_docs[i] for i in indices[0]]
|
109 |
|
110 |
# 📌 Génération de réponse avec MistralAI
|
|
|
115 |
{"role": "user", "content": question}
|
116 |
]
|
117 |
|
118 |
+
response = client.chat.complete(model=model_chat, messages=messages, temperature=temperature)
|
119 |
return response.choices[0].message.content
|
120 |
|
121 |
# 📌 Exécuter une requête utilisateur
|
122 |
+
user_question = "Bonjour le Chat, je suis éléveur de poulets depuis plus de 20 ans et j'ai un doctorat de nutrition animale.Qu’est-ce qu’une protéine idéale en poule pondeuse ? Peux-tu suggérer une protéine idéale en pondeuse ? Merci d'être exhaustif et d'approfondir tes réponses et de ne pas survoler le sujet"
|
123 |
relevant_chunks = retrieve_relevant_chunks(user_question)
|
124 |
context = "\n".join(relevant_chunks)
|
125 |
answer = generate_response(context, user_question)
|
|
|
128 |
print("\n🔹 Réponse Mistral :")
|
129 |
print(answer)
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
# 💾 Sauvegarde des résultats
|
132 |
+
with open("mistral_response_types.txt", "w", encoding="utf-8") as f:
|
133 |
f.write(f"Question : {user_question}\n")
|
134 |
f.write(f"Réponse :\n{answer}\n")
|
135 |
|
136 |
+
print("\n✅ Réponse enregistrée dans 'mistral_response_types.txt'")
|
chunked_docs.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:002933b799b3b8d0824a2144045cd30f9a0bc3adcbbec594f3b3b0fab6f9b384
|
3 |
+
size 1940652
|
faiss_index.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:2e097afeea3f73b331e09a0a81f4a09d920478ec100bb52c83ba550a6bf29600
|
3 |
+
size 2293805
|