LostPikachu commited on
Commit
ccf4f83
·
verified ·
1 Parent(s): 78bd05e

Upload 3 files

Browse files

RAG Mistral AI (testé sur un corpus de 86 des 200 textes sélectionnés, soucis de graph TNSE à la fin du code #comment) & RAG Open AI (à tester).
Pas de fichier requirements mais toutes les librairies utilisées sont les maj les plus récentes disponibles.
MAJ Test_API_GenAI

Files changed (3) hide show
  1. RAG_Mistral.py +120 -0
  2. RAG_OpenAI.py +95 -0
  3. Tests_API_GenAI.py +58 -49
RAG_Mistral.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Mon Feb 24 15:51:34 2025
4
+
5
+ @author: MIPO10053340
6
+
7
+ C:/Users/MIPO10053340/OneDrive - Groupe Avril/Bureau/Salon_Agriculture_2024/Micka_API_Call/Docs_pdf/Docs_pdf/
8
+
9
+ """
10
+
11
+ # -*- coding: utf-8 -*-
12
+ """
13
+ Optimisation du RAG avec MistralAI - Embeddings en batch
14
+ """
15
+ 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
22
+ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
23
+ from dotenv import load_dotenv
24
+
25
+ # Charger les variables d'environnement
26
+ load_dotenv()
27
+ MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY_static')
28
+
29
+ # 📌 Initialisation du client Mistral
30
+ client = Mistral(api_key=MISTRAL_API_KEY)
31
+ model_embedding = "mistral-embed"
32
+ model_chat = "mistral-large-latest"
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
+
36
+ # 📌 Paramètres de segmentation
37
+ chunk_size = 256 # Réduction du chunk size pour un meilleur contrôle du contexte
38
+ chunk_overlap = 15
39
+
40
+ # 📌 Extraction et segmentation des PDF
41
+ def extract_and_chunk_pdfs(pdf_folder):
42
+ """Extrait et segmente les textes des PDF en chunks optimisés pour Mistral."""
43
+ documents = SimpleDirectoryReader(pdf_folder).load_data()
44
+ chunked_docs = [doc.text for doc in documents]
45
+ return chunked_docs
46
+
47
+ # 📌 Génération des embeddings par batch
48
+ def get_embeddings_in_batches(text_chunks, batch_size=5):
49
+ """Génère les embeddings en batch pour éviter les dépassements de tokens."""
50
+ embeddings = []
51
+ for i in range(0, len(text_chunks), batch_size):
52
+ batch = text_chunks[i:i + batch_size]
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
+ return np.array(embeddings).astype('float32')
61
+
62
+ # 📌 Chargement et embedding des documents
63
+ pdf_folder = 'C:/Users/MIPO10053340/OneDrive - Groupe Avril/Bureau/Salon_Agriculture_2024/Micka_API_Call/Docs_pdf/'
64
+ chunked_docs = extract_and_chunk_pdfs(pdf_folder)
65
+ embeddings = get_embeddings_in_batches(chunked_docs)
66
+
67
+ # 📌 Indexation des embeddings avec FAISS
68
+ dimension = embeddings.shape[1]
69
+ index = faiss.IndexFlatL2(dimension)
70
+ index.add(embeddings)
71
+
72
+ # 📌 Récupération des chunks les plus pertinents
73
+ def retrieve_relevant_chunks(question, k=5):
74
+ """Recherche les chunks les plus pertinents en fonction de la similarité des embeddings."""
75
+ question_embedding_response = client.embeddings.create(
76
+ model=model_embedding,
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
84
+ def generate_response(context, question):
85
+ """Génère une réponse basée sur le contexte extrait du corpus avec une basse température et un contrôle de probabilité."""
86
+ messages = [
87
+ {"role": "system", "content": f"Voici des informations contextuelles à utiliser avec priorité : {context}"},
88
+ {"role": "user", "content": question}
89
+ ]
90
+
91
+ response = client.chat.complete(model=model_chat, messages=messages, temperature=temperature, probability=probability)
92
+ return response.choices[0].message.content
93
+
94
+ # 📌 Exécuter une requête utilisateur
95
+ user_question = "Quelles sont les souches de poulets ou poules présentent dans les publications de notre corpus utilisé pour la RAG"
96
+ relevant_chunks = retrieve_relevant_chunks(user_question)
97
+ context = "\n".join(relevant_chunks)
98
+ answer = generate_response(context, user_question)
99
+
100
+ # 📊 Affichage de la réponse
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("mistral_response.txt", "w", encoding="utf-8") as f:
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 'mistral_response.txt'")
RAG_OpenAI.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import fitz # PyMuPDF pour extraction PDF
4
+ import faiss
5
+ import openai
6
+ from sklearn.manifold import TSNE
7
+ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
8
+ from dotenv import load_dotenv
9
+
10
+ # Charger les variables d'environnement
11
+ load_dotenv()
12
+ OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
13
+
14
+ # 📌 Initialisation du client OpenAI
15
+ openai.api_key = OPENAI_API_KEY
16
+ model_embedding = "text-embedding-ada-002"
17
+ model_chat = "gpt-4-turbo"
18
+
19
+ # 📌 Paramètres de segmentation
20
+ chunk_size = 256
21
+ chunk_overlap = 10
22
+
23
+ # 📌 Extraction et segmentation des PDF
24
+ def extract_and_chunk_pdfs(pdf_folder):
25
+ """Extrait et segmente les textes des PDF en chunks optimisés pour OpenAI."""
26
+ documents = SimpleDirectoryReader(pdf_folder).load_data()
27
+ chunked_docs = [doc.text for doc in documents]
28
+ return chunked_docs
29
+
30
+ # 📌 Génération des embeddings par batch
31
+ def get_embeddings_in_batches(text_chunks, batch_size=5):
32
+ """Génère les embeddings en batch pour éviter les dépassements de tokens."""
33
+ embeddings = []
34
+ for i in range(0, len(text_chunks), batch_size):
35
+ batch = text_chunks[i:i + batch_size]
36
+ response = openai.Embedding.create(
37
+ input=batch,
38
+ model=model_embedding
39
+ )
40
+ batch_embeddings = [data['embedding'] for data in response['data']]
41
+ embeddings.extend(batch_embeddings)
42
+
43
+ return np.array(embeddings).astype('float32')
44
+
45
+ # 📌 Chargement et embedding des documents
46
+ pdf_folder = 'C:/Users/MIPO10053340/OneDrive - Groupe Avril/Bureau/Salon_Agriculture_2024/Micka_API_Call/Docs_pdf/'
47
+ chunked_docs = extract_and_chunk_pdfs(pdf_folder)
48
+ embeddings = get_embeddings_in_batches(chunked_docs)
49
+
50
+ # 📌 Indexation des embeddings avec FAISS
51
+ dimension = embeddings.shape[1]
52
+ index = faiss.IndexFlatL2(dimension)
53
+ index.add(embeddings)
54
+
55
+ # 📌 Récupération des chunks les plus pertinents
56
+ def retrieve_relevant_chunks(question, k=5):
57
+ """Recherche les chunks les plus pertinents en fonction de la similarité des embeddings."""
58
+ response = openai.Embedding.create(
59
+ input=[question],
60
+ model=model_embedding
61
+ )
62
+ question_embedding = np.array(response['data'][0]['embedding']).astype('float32').reshape(1, -1)
63
+ distances, indices = index.search(question_embedding, k)
64
+ return [chunked_docs[i] for i in indices[0]]
65
+
66
+ # 📌 Génération de réponse avec OpenAI
67
+ def generate_response(context, question):
68
+ """Génère une réponse basée sur le contexte extrait du corpus."""
69
+ messages = [
70
+ {"role": "system", "content": f"Voici des informations contextuelles : {context}"},
71
+ {"role": "user", "content": question}
72
+ ]
73
+
74
+ response = openai.ChatCompletion.create(
75
+ model=model_chat,
76
+ messages=messages
77
+ )
78
+ return response["choices"][0]["message"]["content"]
79
+
80
+ # 📌 Exécuter une requête utilisateur
81
+ user_question = "Quelles souches de poulet et poules se trouvent dans ce corpus de texte ?"
82
+ relevant_chunks = retrieve_relevant_chunks(user_question)
83
+ context = "\n".join(relevant_chunks)
84
+ answer = generate_response(context, user_question)
85
+
86
+ # 📊 Affichage de la réponse
87
+ print("\n🔹 Réponse OpenAI :")
88
+ print(answer)
89
+
90
+ # 💾 Sauvegarde des résultats
91
+ with open("openai_response.txt", "w", encoding="utf-8") as f:
92
+ f.write(f"Question : {user_question}\n")
93
+ f.write(f"Réponse :\n{answer}\n")
94
+
95
+ print("\n✅ Réponse enregistrée dans 'openai_response.txt'")
Tests_API_GenAI.py CHANGED
@@ -14,21 +14,18 @@ import pandas as pd
14
  from scipy.stats import entropy
15
 
16
  # API Clients
17
- from mistralai.client import MistralClient
18
- from mistralai.models.chat_completion import ChatMessage
19
 
20
- import openai
21
- from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
22
- import transformers_stream_generator
23
- import einops
24
 
25
- HF_TOKEN = "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"
26
 
27
  # ⚙️ Configurations API (remplace par tes clés API)
28
  MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY_static')
29
  OPENAI_API_KEY = os.getenv('OPENAI_API_KEY_static')
30
- ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY_static')
31
- LLAMA_API_KEY = os.getenv('LLAMA_API_KEY_static')
 
32
 
33
  # 📌 Choix des modèles à utiliser
34
  USE_MODELS = {
@@ -39,6 +36,7 @@ USE_MODELS = {
39
  "deepseek": False
40
  }
41
 
 
42
  # 📊 Fonction pour calculer l'entropie des réponses
43
  def calculate_entropy(text):
44
  tokens = text.split()
@@ -49,53 +47,64 @@ def calculate_entropy(text):
49
  def get_model_responses(question):
50
  responses = {}
51
 
52
- # 🔹 MISTRAL
53
  if USE_MODELS["mistral"]:
54
- mistral_client = MistralClient(api_key=MISTRAL_API_KEY)
55
- messages = [ChatMessage(role="user", content=question)]
56
- response = mistral_client.chat(model="mistral-medium", messages=messages)
57
- text_response = response.choices[0].message.content
58
- responses["mistral"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
 
 
 
 
 
 
 
 
59
 
60
  # 🔹 GPT-4 (OpenAI)
61
  if USE_MODELS["gpt-4"]:
62
- # openai>=1.0.0
63
- client = openai.OpenAI(api_key=OPENAI_API_KEY)
64
 
 
65
  response = client.chat.completions.create(
66
- model="gpt-4",
67
- messages=[{"role": "user", "content": question}]
 
 
68
  )
69
-
70
- text_response = response.choices[0].message.content
71
- responses["gpt-4"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
72
-
73
- # 🔹 LLAMA (Hugging Face)
74
- if USE_MODELS["llama"]:
75
- model_id = "meta-llama/Llama-2-7b-chat-hf"
76
- tokenizer = AutoTokenizer.from_pretrained(model_id)
77
- model = AutoModelForCausalLM.from_pretrained(model_id)
78
- pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
79
- text_response = pipe(question, max_length=300)[0]["generated_text"]
80
- responses["llama"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
81
-
82
- # 🔹 QWEN (Hugging Face)
83
- if USE_MODELS["qwen"]:
84
- model_id = "Qwen/Qwen-7B-Chat"
85
- tokenizer = AutoTokenizer.from_pretrained(model_id, token=HF_TOKEN, trust_remote_code=True)
86
- model = AutoModelForCausalLM.from_pretrained(model_id, token=HF_TOKEN, trust_remote_code=True)
87
- pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
88
- text_response = pipe(question, max_length=300)[0]["generated_text"]
89
- responses["qwen"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
90
-
91
- # 🔹 DEEPSEEK (Hugging Face)
92
- if USE_MODELS["deepseek"]:
93
- model_id = "deepseek-ai/deepseek-7b-chat"
94
- tokenizer = AutoTokenizer.from_pretrained(model_id)
95
- model = AutoModelForCausalLM.from_pretrained(model_id)
96
- pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
97
- text_response = pipe(question, max_length=300)[0]["generated_text"]
98
- responses["deepseek"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
99
 
100
  return responses
101
 
 
14
  from scipy.stats import entropy
15
 
16
  # API Clients
17
+ from mistralai import Mistral
18
+ from openai import OpenAI
19
 
20
+ # from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
 
 
 
21
 
 
22
 
23
  # ⚙️ Configurations API (remplace par tes clés API)
24
  MISTRAL_API_KEY = os.getenv('MISTRAL_API_KEY_static')
25
  OPENAI_API_KEY = os.getenv('OPENAI_API_KEY_static')
26
+ # ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY_static')
27
+ # LLAMA_API_KEY = os.getenv('LLAMA_API_KEY_static')
28
+ # HUGGINGFACE_TOKEN =os.getenv('HUGGINGFACE_TOKEN_static')
29
 
30
  # 📌 Choix des modèles à utiliser
31
  USE_MODELS = {
 
36
  "deepseek": False
37
  }
38
 
39
+
40
  # 📊 Fonction pour calculer l'entropie des réponses
41
  def calculate_entropy(text):
42
  tokens = text.split()
 
47
  def get_model_responses(question):
48
  responses = {}
49
 
50
+ # # 🔹 MISTRAL
51
  if USE_MODELS["mistral"]:
52
+ # Initialisation du client Mistral
53
+ client = Mistral(api_key=MISTRAL_API_KEY)
54
+
55
+ # Créer une complétion de chat
56
+ response = client.chat.complete(
57
+ model="mistral-medium",
58
+ messages=[
59
+ {"role": "user", "content": question}
60
+ ]
61
+ )
62
+ # Extraire et afficher la réponse
63
+ text_response = response.choices[0].message.content
64
+ responses["mistral-medium"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
65
 
66
  # 🔹 GPT-4 (OpenAI)
67
  if USE_MODELS["gpt-4"]:
68
+ # Initialisation du client OpenAI
69
+ client = OpenAI(api_key=OPENAI_API_KEY)
70
 
71
+ # Créer une complétion de chat
72
  response = client.chat.completions.create(
73
+ model="gpt-4-turbo",
74
+ messages=[
75
+ {"role": "user", "content": question}
76
+ ]
77
  )
78
+ # Extraire et afficher la réponse
79
+ text_response = response.choices[0].message.content
80
+ responses["gpt-4-turbo"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
81
+
82
+ # # 🔹 LLAMA (Hugging Face)
83
+ # if USE_MODELS["llama"]:
84
+ # model_id = "meta-llama/Llama-2-7b-chat-hf"
85
+ # tokenizer = AutoTokenizer.from_pretrained(model_id, use_auth_token=HUGGINGFACE_TOKEN)
86
+ # model = AutoModelForCausalLM.from_pretrained(model_id, use_auth_token=HUGGINGFACE_TOKEN)
87
+ # pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
88
+
89
+ # text_response = pipe(question, max_length=300)[0]["generated_text"]
90
+ # responses["llama"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
91
+ # # 🔹 QWEN (Hugging Face)
92
+ # if USE_MODELS["qwen"]:
93
+ # model_id = "Qwen/Qwen-7B-Chat"
94
+ # tokenizer = AutoTokenizer.from_pretrained(model_id, token=HUGGINGFACE_TOKEN, trust_remote_code=True)
95
+ # model = AutoModelForCausalLM.from_pretrained(model_id, token=HUGGINGFACE_TOKEN, trust_remote_code=True)
96
+ # pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
97
+ # text_response = pipe(question, max_length=300)[0]["generated_text"]
98
+ # responses["qwen"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
99
+
100
+ # # 🔹 DEEPSEEK (Hugging Face)
101
+ # if USE_MODELS["deepseek"]:
102
+ # model_id = "deepseek-ai/deepseek-7b-chat"
103
+ # tokenizer = AutoTokenizer.from_pretrained(model_id)
104
+ # model = AutoModelForCausalLM.from_pretrained(model_id)
105
+ # pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
106
+ # text_response = pipe(question, max_length=300)[0]["generated_text"]
107
+ # responses["deepseek"] = {"response": text_response, "entropy": calculate_entropy(text_response)}
108
 
109
  return responses
110