baptiste.bernard commited on
Commit
d79eb5f
·
1 Parent(s): b374d39

add RAG and update README

Browse files
Files changed (2) hide show
  1. README.md +22 -18
  2. app.py +77 -106
README.md CHANGED
@@ -23,9 +23,6 @@ Gaia Chat est un exemple de chatbot utilisant [Gradio](https://gradio.app), [`hu
23
  ## Prérequis
24
 
25
  - Python 3.6 ou supérieur
26
- - Gradio
27
- - Chardet
28
-
29
 
30
  ## Installation
31
 
@@ -33,10 +30,6 @@ Gaia Chat est un exemple de chatbot utilisant [Gradio](https://gradio.app), [`hu
33
 
34
  Assurez-vous que Python est installé.
35
 
36
- ```sh
37
- python --version
38
- ```
39
-
40
  1. Rendez-vous sur le site officiel de Python : [https://www.python.org/downloads/](https://www.python.org/downloads/)
41
  2. Vérifiez l’installation avec la commande :
42
  ```sh
@@ -56,11 +49,20 @@ source .venv/bin/activate
56
 
57
  pip install -r requirements.txt
58
  ```
59
- ### 5. Gener un Access token sur Hugging Face
60
 
61
  Rendez-vous sur votre profil Hugging Face pour genenez votre Access Token : [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
62
 
63
- ### 4. Lancer l'application
 
 
 
 
 
 
 
 
 
64
 
65
  Exécutez la commande suivante pour démarrer Gaia Chat :
66
 
@@ -84,11 +86,9 @@ Une fois l'application lancée, ouvrez votre navigateur et accédez à l'URL ind
84
  Gaia Chat is an example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and l '[Hugging Face Inference API](https://huggingface.co/docs/api-inference/index). This project shows how to create an interactive chatbot using these tools.
85
 
86
 
87
- ## prerequisites
88
 
89
  - Python 3.6
90
- - Gradio
91
- - Chardet
92
 
93
  ## Facilities
94
 
@@ -96,10 +96,6 @@ Gaia Chat is an example chatbot using [Gradio](https://gradio.app), [`huggingfac
96
 
97
  Make sure Python is installed.
98
 
99
- ```sh
100
- python --version
101
- ```
102
-
103
  1. Go to the official Python website: [https://www.python.org/downloads/](https://www.python.org/downloads/)
104
  2. Verify the installation with the command:
105
  ```sh
@@ -118,11 +114,19 @@ source .venv/bin/activate
118
  pip install -r requirements.txt
119
  ```
120
 
121
- ### 5. Generate Access Token on Hugging Face
122
 
123
  Go to your Hugging Face profile to generate your access token: [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
124
 
125
- ### 4. Launch the application
 
 
 
 
 
 
 
 
126
 
127
  Run the following command to start Gaia Chat:
128
 
 
23
  ## Prérequis
24
 
25
  - Python 3.6 ou supérieur
 
 
 
26
 
27
  ## Installation
28
 
 
30
 
31
  Assurez-vous que Python est installé.
32
 
 
 
 
 
33
  1. Rendez-vous sur le site officiel de Python : [https://www.python.org/downloads/](https://www.python.org/downloads/)
34
  2. Vérifiez l’installation avec la commande :
35
  ```sh
 
49
 
50
  pip install -r requirements.txt
51
  ```
52
+ ### 4. Gener un Access token sur Hugging Face
53
 
54
  Rendez-vous sur votre profil Hugging Face pour genenez votre Access Token : [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
55
 
56
+
57
+ ### 5. Créer et configurer le fichier `.env`
58
+
59
+ 1. Créer le fichier `.env` :
60
+ ```sh
61
+ echo HFTOKEN="votre_token_ici" > .env
62
+ ```
63
+ 2. Ajouter le token que vous avez créé précédemment dans votre fichier `.env`.
64
+
65
+ ### 6. Lancer l'application
66
 
67
  Exécutez la commande suivante pour démarrer Gaia Chat :
68
 
 
86
  Gaia Chat is an example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and l '[Hugging Face Inference API](https://huggingface.co/docs/api-inference/index). This project shows how to create an interactive chatbot using these tools.
87
 
88
 
89
+ ## Prerequisites
90
 
91
  - Python 3.6
 
 
92
 
93
  ## Facilities
94
 
 
96
 
97
  Make sure Python is installed.
98
 
 
 
 
 
99
  1. Go to the official Python website: [https://www.python.org/downloads/](https://www.python.org/downloads/)
100
  2. Verify the installation with the command:
101
  ```sh
 
114
  pip install -r requirements.txt
115
  ```
116
 
117
+ ### 4. Generate Access Token on Hugging Face
118
 
119
  Go to your Hugging Face profile to generate your access token: [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
120
 
121
+ ### 5. Create and configure the `.env` File
122
+
123
+ 1. Create the `.env` file:
124
+ ```sh
125
+ echo HFTOKEN="your_token_here" > .env
126
+ ```
127
+ 2. Add the token you created earlier to your `.env` file.
128
+
129
+ ### 6. Launch the application
130
 
131
  Run the following command to start Gaia Chat:
132
 
app.py CHANGED
@@ -1,8 +1,7 @@
1
  import os
2
- import sys
3
  from dotenv import load_dotenv
4
  import gradio as gr
5
- from huggingface_hub import InferenceClient
6
  from langchain_huggingface import HuggingFaceEmbeddings
7
  from langchain.text_splitter import RecursiveCharacterTextSplitter
8
  from langchain_community.vectorstores import FAISS
@@ -10,159 +9,131 @@ from langchain_community.document_loaders import PyPDFLoader
10
  from langchain.schema import Document
11
 
12
  load_dotenv()
13
- hftoken = os.environ.get("HFTOKEN")
14
 
15
-
16
- from huggingface_hub import login
17
  login(token=hftoken)
18
 
19
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=hftoken)
20
- vector_store = None
21
- # model_kwargs = {'device': 'cpu'}
22
- # encode_kwargs = {'normalize_embeddings': False}
23
- model_name="sentence-transformers/all-MiniLM-L6-v2"
24
-
25
- embeddings = HuggingFaceEmbeddings(
26
- model_name=model_name
27
- # model_kwargs=model_kwargs,
28
- # encode_kwargs=encode_kwargs
29
- )
30
 
 
31
 
32
  def extract_text_from_file(file_path):
33
  """Extrait le texte d'un fichier PDF ou TXT."""
34
  try:
35
- file_extension = os.path.splitext(file_path)[1].lower()
36
-
37
- if file_extension == ".pdf":
38
  loader = PyPDFLoader(file_path)
39
  pages = loader.load()
40
- docs = [Document(page_content=page.page_content) for page in pages]
41
- elif file_extension == ".txt":
42
  with open(file_path, "r", encoding="utf-8") as file:
43
- text = file.read()
44
- docs = [Document(page_content=text)]
45
  else:
46
- return None, "Format non pris en charge. Téléchargez un PDF ou TXT."
47
-
48
- return docs, None
49
  except Exception as e:
50
- return None, f"Erreur lors de la lecture du fichier : {e}"
 
51
 
52
  def embed_documents(file):
53
- """Convertit un document en vecteurs FAISS et génère un résumé."""
54
  global vector_store
55
-
56
- docs, error = extract_text_from_file(file.name)
57
- if error:
58
- return error
59
-
60
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
61
  documents = text_splitter.split_documents(docs)
62
 
63
  if documents:
64
  vector_store = FAISS.from_documents(documents, embeddings)
65
-
66
- full_text = "\n".join([doc.page_content for doc in documents])
67
- summary = summarize_text(full_text)
68
- return f"✅ Document indexé avec succès !\n\n📌 **Résumé du fichier** :\n{summary}"
69
  else:
70
- return "❌ Aucun texte trouvable dans le fichier."
71
-
72
- def summarize_text(text):
73
- """Utilise le modèle HF pour générer un résumé du document."""
74
- messages = [{"role": "system", "content": "Résume ce texte en quelques phrases :"}, {"role": "user", "content": text}]
75
-
76
- response = client.chat_completion(messages, max_tokens=200, temperature=0.5)
77
- return response.choices[0].message["content"]
78
 
79
  def query_faiss(query):
80
- """Recherche les documents pertinents dans FAISS et retourne une réponse reformulée."""
 
81
  if vector_store is None:
82
- return "❌ Aucun document indexé. Téléchargez un fichier."
83
-
84
  retriever = vector_store.as_retriever(search_kwargs={"k": 3})
85
  results = retriever.get_relevant_documents(query)
86
 
87
- if not results:
88
- return "Je n'ai pas trouvé d'informations pertinentes dans les documents."
89
-
90
- context = "\n".join([doc.page_content for doc in results])
91
-
92
-
93
-
94
- messages = [
95
- {"role": "system", "content": "Réponds à la question en utilisant les informations suivantes sans les copier mot pour mot."},
96
- {"role": "user", "content": f"Contexte : {context}\nQuestion : {query}"}
97
- ]
98
 
99
- response = client.chat_completion(messages, max_tokens=200, temperature=0.5)
100
- return response.choices[0].message["content"]
101
-
102
-
103
-
104
- def respond(message, history, system_message, max_tokens, temperature, top_p, file=None):
105
- """Gère la réponse du chatbot avec FAISS et Hugging Face."""
106
  global vector_store
107
-
108
- messages = [{"role": "system", "content": system_message}]
 
 
 
 
 
 
 
109
 
110
  for val in history:
111
- if val[0]:
112
- messages.append({"role": "user", "content": val[0]})
113
- if val[1]:
114
- messages.append({"role": "assistant", "content": val[1]})
115
 
116
-
117
- if file:
118
- response = embed_documents(file)
119
- yield response
120
- return
121
-
122
- context = query_faiss(message)
123
- if "❌" not in context:
124
  messages.append({"role": "user", "content": f"Contexte : {context}\nQuestion : {message}"})
125
  else:
126
-
127
-
128
  messages.append({"role": "user", "content": message})
129
 
130
-
131
-
132
-
133
  response = ""
134
- for msg in client.chat_completion(
135
- messages,
136
- max_tokens=max_tokens,
137
- stream=True,
138
- temperature=temperature,
139
- top_p=top_p,
140
- ):
141
- token = msg.choices[0].delta.content
142
- response += token
143
- yield response
 
 
 
 
 
 
 
 
 
 
144
 
145
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
146
- gr.Markdown("# 📚 Chatbot avec intégration de documents")
147
- gr.Image(value="logo-gaia.png", label="Logo")
148
 
 
 
 
149
  with gr.Row():
150
  with gr.Column():
151
  gr.Markdown("## ⚙️ Paramètres")
152
- with gr.Accordion("Réglages avancés", open=False):
153
- system_message = gr.Textbox(value="You are a friendly Chatbot.", label="System message")
154
- max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
155
- temperature = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
156
- top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
157
-
158
- file_upload = gr.File(label="📂 Télécharger un fichier PDF ou TXT", file_types=[".pdf", ".txt"], type="filepath")
159
- file_output = gr.Textbox()
160
- file_upload.change(embed_documents, inputs=file_upload, outputs=file_output)
 
161
 
162
  with gr.Column():
163
  gr.Markdown("## 💬 Chat")
164
  chatbot = gr.ChatInterface(
165
- respond,
166
  additional_inputs=[system_message, max_tokens, temperature, top_p, file_upload],
167
  )
168
 
 
1
  import os
 
2
  from dotenv import load_dotenv
3
  import gradio as gr
4
+ from huggingface_hub import InferenceClient, login
5
  from langchain_huggingface import HuggingFaceEmbeddings
6
  from langchain.text_splitter import RecursiveCharacterTextSplitter
7
  from langchain_community.vectorstores import FAISS
 
9
  from langchain.schema import Document
10
 
11
  load_dotenv()
12
+ hftoken = os.getenv("HFTOKEN")
13
 
 
 
14
  login(token=hftoken)
15
 
16
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=hftoken)
17
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
 
 
 
 
 
 
 
 
 
18
 
19
+ vector_store = None
20
 
21
  def extract_text_from_file(file_path):
22
  """Extrait le texte d'un fichier PDF ou TXT."""
23
  try:
24
+ ext = os.path.splitext(file_path)[1].lower()
25
+ if ext == ".pdf":
 
26
  loader = PyPDFLoader(file_path)
27
  pages = loader.load()
28
+ return [Document(page_content=page.page_content) for page in pages]
29
+ elif ext == ".txt":
30
  with open(file_path, "r", encoding="utf-8") as file:
31
+ return [Document(page_content=file.read())]
 
32
  else:
33
+ return None
 
 
34
  except Exception as e:
35
+ print(f"Erreur extraction : {e}")
36
+ return None
37
 
38
  def embed_documents(file):
39
+ """Charge un document dans FAISS pour la recherche vectorielle."""
40
  global vector_store
41
+ docs = extract_text_from_file(file.name)
42
+ if not docs:
43
+ return "❌ Erreur lors du chargement du fichier."
44
+
 
45
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
46
  documents = text_splitter.split_documents(docs)
47
 
48
  if documents:
49
  vector_store = FAISS.from_documents(documents, embeddings)
50
+ return "📁 Document chargé et indexé ! Posez-moi une question."
 
 
 
51
  else:
52
+ return "❌ Aucun texte valide extrait du fichier."
 
 
 
 
 
 
 
53
 
54
  def query_faiss(query):
55
+ """Effectue une recherche dans FAISS et génère une réponse."""
56
+ global vector_store
57
  if vector_store is None:
58
+ return None
59
+
60
  retriever = vector_store.as_retriever(search_kwargs={"k": 3})
61
  results = retriever.get_relevant_documents(query)
62
 
63
+ if results:
64
+ context = "\n".join([doc.page_content for doc in results])
65
+ return context
66
+ return None
 
 
 
 
 
 
 
67
 
68
+ def chatbot_response(message, history, system_message, max_tokens, temperature, top_p, file=None):
69
+ """Gère les réponses du chatbot avec ou sans document."""
 
 
 
 
 
70
  global vector_store
71
+ if file:
72
+ status = embed_documents(file)
73
+ if "❌" in status:
74
+ yield status
75
+ return
76
+ yield status
77
+
78
+ context = query_faiss(message) if vector_store else None
79
+ messages = [{"role": "system", "content": system_message + " Réponds uniquement en français."}]
80
 
81
  for val in history:
82
+ if val[0]: messages.append({"role": "user", "content": val[0]})
83
+ if val[1]: messages.append({"role": "assistant", "content": val[1]})
 
 
84
 
85
+ if context:
 
 
 
 
 
 
 
86
  messages.append({"role": "user", "content": f"Contexte : {context}\nQuestion : {message}"})
87
  else:
 
 
88
  messages.append({"role": "user", "content": message})
89
 
 
 
 
90
  response = ""
91
+ try:
92
+ response_stream = client.chat_completion(
93
+ messages,
94
+ max_tokens=max_tokens,
95
+ stream=True,
96
+ temperature=temperature,
97
+ top_p=top_p,
98
+ )
99
+
100
+ for msg in response_stream:
101
+ if msg.choices and msg.choices[0].delta and msg.choices[0].delta.content:
102
+ token = msg.choices[0].delta.content
103
+ response += token
104
+ yield response
105
+
106
+ if not response.strip():
107
+ yield "Je ne sais pas. Peux-tu reformuler ?"
108
+ except Exception as e:
109
+ print(f"Erreur réponse : {e}")
110
+ yield "❌ Une erreur est survenue lors de la génération de la réponse."
111
 
112
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
113
+ with gr.Row():
114
+ gr.Image("logo-gaia.png", width=300, height=300, show_label=False, show_download_button=False)
115
 
116
+ with gr.Row():
117
+ gr.Markdown("<h1 style='text-align: center;'>📚 Chatbot GAIA</h1>")
118
+
119
  with gr.Row():
120
  with gr.Column():
121
  gr.Markdown("## ⚙️ Paramètres")
122
+ with gr.Accordion(" Paramètres avancés", open=False):
123
+ system_message = gr.Textbox(value="Réponds de façon simple et claire.", label="Message système")
124
+ max_tokens = gr.Slider(1, 2048, value=800, step=1, label="Max tokens")
125
+ temperature = gr.Slider(0.1, 4.0, value=0.3, step=0.1, label="Température")
126
+ top_p = gr.Slider(0.1, 1.0, value=0.95, step=0.05, label="Top-p")
127
+
128
+
129
+ gr.Markdown("## 📂 Télécharger un fichier")
130
+ file_upload = gr.File(label="Téléchargez un PDF ou TXT", file_types=[".pdf", ".txt"], type="filepath")
131
+ file_upload.change(embed_documents, inputs=file_upload, outputs=[])
132
 
133
  with gr.Column():
134
  gr.Markdown("## 💬 Chat")
135
  chatbot = gr.ChatInterface(
136
+ chatbot_response,
137
  additional_inputs=[system_message, max_tokens, temperature, top_p, file_upload],
138
  )
139