Spaces:
Running
Running
baptiste.bernard
commited on
Commit
·
d79eb5f
1
Parent(s):
b374d39
add RAG and update README
Browse files
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 |
-
###
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
##
|
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 |
-
###
|
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 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
14 |
|
15 |
-
|
16 |
-
from huggingface_hub import login
|
17 |
login(token=hftoken)
|
18 |
|
19 |
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=hftoken)
|
20 |
-
|
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 |
-
|
36 |
-
|
37 |
-
if file_extension == ".pdf":
|
38 |
loader = PyPDFLoader(file_path)
|
39 |
pages = loader.load()
|
40 |
-
|
41 |
-
elif
|
42 |
with open(file_path, "r", encoding="utf-8") as file:
|
43 |
-
|
44 |
-
docs = [Document(page_content=text)]
|
45 |
else:
|
46 |
-
return None
|
47 |
-
|
48 |
-
return docs, None
|
49 |
except Exception as e:
|
50 |
-
|
|
|
51 |
|
52 |
def embed_documents(file):
|
53 |
-
"""
|
54 |
global vector_store
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
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
|
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 |
-
"""
|
|
|
81 |
if vector_store is None:
|
82 |
-
return
|
83 |
-
|
84 |
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
|
85 |
results = retriever.get_relevant_documents(query)
|
86 |
|
87 |
-
if
|
88 |
-
|
89 |
-
|
90 |
-
|
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 |
-
|
100 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
for val in history:
|
111 |
-
if val[0]:
|
112 |
-
|
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 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
|
145 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
146 |
-
gr.
|
147 |
-
|
148 |
|
|
|
|
|
|
|
149 |
with gr.Row():
|
150 |
with gr.Column():
|
151 |
gr.Markdown("## ⚙️ Paramètres")
|
152 |
-
with gr.Accordion("
|
153 |
-
system_message = gr.Textbox(value="
|
154 |
-
max_tokens = gr.Slider(
|
155 |
-
temperature = gr.Slider(
|
156 |
-
top_p = gr.Slider(
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
file_upload.
|
|
|
161 |
|
162 |
with gr.Column():
|
163 |
gr.Markdown("## 💬 Chat")
|
164 |
chatbot = gr.ChatInterface(
|
165 |
-
|
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 |
|