baptiste.bernard commited on
Commit
7dbc57c
·
1 Parent(s): 60c2622

RAG in progress

Browse files
Files changed (2) hide show
  1. app.py +93 -33
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,10 +1,13 @@
1
  import os
2
  import sys
3
- import fitz # PyMuPDF
4
  from dotenv import load_dotenv
5
  import gradio as gr
6
  from huggingface_hub import InferenceClient
7
- import re
 
 
 
 
8
 
9
  load_dotenv()
10
  hftoken = os.environ.get("HF_TOKEN")
@@ -14,7 +17,9 @@ from huggingface_hub import login
14
  login(token=hftoken)
15
 
16
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=hftoken)
17
- file_content = None
 
 
18
 
19
  def extract_text_from_file(file_path):
20
  """Extrait le texte d'un fichier PDF ou TXT."""
@@ -22,81 +27,136 @@ def extract_text_from_file(file_path):
22
  file_extension = os.path.splitext(file_path)[1].lower()
23
 
24
  if file_extension == ".pdf":
25
- # PDF
26
- with fitz.open(file_path) as doc:
27
- text = "\n".join([page.get_text("text") for page in doc])
28
  elif file_extension == ".txt":
29
- # TXT
30
  with open(file_path, "r", encoding="utf-8") as file:
31
  text = file.read()
 
32
  else:
33
- return "Format de fichier non pris en charge. Veuillez télécharger un fichier PDF ou TXT."
34
-
35
- return text.strip() if text.strip() else "Aucun texte extrait du fichier."
36
-
37
  except Exception as e:
38
- return f"Erreur lors de la lecture du fichier : {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  def respond(message, history, system_message, max_tokens, temperature, top_p, file=None):
41
- global file_content
 
42
 
43
  messages = [{"role": "system", "content": system_message}]
 
44
  for val in history:
45
  if val[0]:
46
  messages.append({"role": "user", "content": val[0]})
47
  if val[1]:
48
  messages.append({"role": "assistant", "content": val[1]})
49
-
50
- messages.append({"role": "user", "content": message})
51
- response = ""
52
 
53
 
54
  if file:
55
- file_path = file.name if hasattr(file, 'name') else file
56
- if os.path.exists(file_path):
57
- file_content = extract_text_from_file(file_path)
58
- else:
59
- file_content = "Aucun fichier valide n'a été trouvé."
60
-
61
- if re.search(r"contenu du fichier|afficher le fichier|lire le fichier|voir le fichier|donnée du fichier", message.lower()) and file_content:
62
- response += f"Contenu du fichier :\n{file_content}"
63
  yield response
64
  return
65
 
66
-
67
- for message in client.chat_completion(
 
 
 
 
 
 
 
 
 
 
 
68
  messages,
69
  max_tokens=max_tokens,
70
  stream=True,
71
  temperature=temperature,
72
  top_p=top_p,
73
  ):
74
- token = message.choices[0].delta.content
75
  response += token
76
  yield response
77
 
78
- # interface
79
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
80
- gr.Markdown("# Chatbot Interface")
81
  gr.Image(value="logo-gaia.png", label="Logo")
82
 
83
  with gr.Row():
84
  with gr.Column():
85
- gr.Markdown("## Paramètres")
86
  with gr.Accordion("Réglages avancés", open=False):
87
  system_message = gr.Textbox(value="You are a friendly Chatbot.", label="System message")
88
  max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
89
  temperature = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
90
  top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
91
 
92
- file_upload = gr.File(label="Télécharger un fichier PDF ou TXT", file_types=[".pdf", ".txt"], type="filepath")
 
 
93
 
94
  with gr.Column():
95
- gr.Markdown("## Chat")
96
  chatbot = gr.ChatInterface(
97
  respond,
98
  additional_inputs=[system_message, max_tokens, temperature, top_p, file_upload],
99
  )
100
 
101
  if __name__ == "__main__":
102
- demo.launch()
 
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_community.embeddings import HuggingFaceBgeEmbeddings
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain_community.document_loaders import PyPDFLoader
10
+ from langchain.schema import Document
11
 
12
  load_dotenv()
13
  hftoken = os.environ.get("HF_TOKEN")
 
17
  login(token=hftoken)
18
 
19
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=hftoken)
20
+ vector_store = None
21
+ embeddings = HuggingFaceBgeEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
22
+
23
 
24
  def extract_text_from_file(file_path):
25
  """Extrait le texte d'un fichier PDF ou TXT."""
 
27
  file_extension = os.path.splitext(file_path)[1].lower()
28
 
29
  if file_extension == ".pdf":
30
+ loader = PyPDFLoader(file_path)
31
+ pages = loader.load()
32
+ docs = [Document(page_content=page.page_content) for page in pages]
33
  elif file_extension == ".txt":
 
34
  with open(file_path, "r", encoding="utf-8") as file:
35
  text = file.read()
36
+ docs = [Document(page_content=text)]
37
  else:
38
+ return None, "Format non pris en charge. Téléchargez un PDF ou TXT."
39
+
40
+ return docs, None
 
41
  except Exception as e:
42
+ return None, f"Erreur lors de la lecture du fichier : {e}"
43
+
44
+ def embed_documents(file):
45
+ """Convertit un document en vecteurs FAISS et génère un résumé."""
46
+ global vector_store
47
+
48
+ docs, error = extract_text_from_file(file.name)
49
+ if error:
50
+ return error
51
+
52
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
53
+ documents = text_splitter.split_documents(docs)
54
+
55
+ if documents:
56
+ vector_store = FAISS.from_documents(documents, embeddings)
57
+
58
+ full_text = "\n".join([doc.page_content for doc in documents])
59
+ summary = summarize_text(full_text)
60
+ return f"✅ Document indexé avec succès !\n\n📌 **Résumé du fichier** :\n{summary}"
61
+ else:
62
+ return "❌ Aucun texte trouvable dans le fichier."
63
+
64
+ def summarize_text(text):
65
+ """Utilise le modèle HF pour générer un résumé du document."""
66
+ messages = [{"role": "system", "content": "Résume ce texte en quelques phrases :"}, {"role": "user", "content": text}]
67
+
68
+ response = client.chat_completion(messages, max_tokens=200, temperature=0.5)
69
+ return response.choices[0].message["content"]
70
+
71
+ def query_faiss(query):
72
+ """Recherche les documents pertinents dans FAISS et retourne une réponse reformulée."""
73
+ if vector_store is None:
74
+ return "❌ Aucun document indexé. Téléchargez un fichier."
75
+
76
+ retriever = vector_store.as_retriever(search_kwargs={"k": 3})
77
+ results = retriever.get_relevant_documents(query)
78
+
79
+ if not results:
80
+ return "Je n'ai pas trouvé d'informations pertinentes dans les documents."
81
+
82
+ context = "\n".join([doc.page_content for doc in results])
83
+
84
+
85
+
86
+ messages = [
87
+ {"role": "system", "content": "Réponds à la question en utilisant les informations suivantes sans les copier mot pour mot."},
88
+ {"role": "user", "content": f"Contexte : {context}\nQuestion : {query}"}
89
+ ]
90
+
91
+ response = client.chat_completion(messages, max_tokens=200, temperature=0.5)
92
+ return response.choices[0].message["content"]
93
+
94
+
95
 
96
  def respond(message, history, system_message, max_tokens, temperature, top_p, file=None):
97
+ """Gère la réponse du chatbot avec FAISS et Hugging Face."""
98
+ global vector_store
99
 
100
  messages = [{"role": "system", "content": system_message}]
101
+
102
  for val in history:
103
  if val[0]:
104
  messages.append({"role": "user", "content": val[0]})
105
  if val[1]:
106
  messages.append({"role": "assistant", "content": val[1]})
 
 
 
107
 
108
 
109
  if file:
110
+ response = embed_documents(file)
 
 
 
 
 
 
 
111
  yield response
112
  return
113
 
114
+ context = query_faiss(message)
115
+ if "❌" not in context:
116
+ messages.append({"role": "user", "content": f"Contexte : {context}\nQuestion : {message}"})
117
+ else:
118
+
119
+
120
+ messages.append({"role": "user", "content": message})
121
+
122
+
123
+
124
+
125
+ response = ""
126
+ for msg in client.chat_completion(
127
  messages,
128
  max_tokens=max_tokens,
129
  stream=True,
130
  temperature=temperature,
131
  top_p=top_p,
132
  ):
133
+ token = msg.choices[0].delta.content
134
  response += token
135
  yield response
136
 
 
137
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
138
+ gr.Markdown("# 📚 Chatbot avec intégration de documents")
139
  gr.Image(value="logo-gaia.png", label="Logo")
140
 
141
  with gr.Row():
142
  with gr.Column():
143
+ gr.Markdown("## ⚙️ Paramètres")
144
  with gr.Accordion("Réglages avancés", open=False):
145
  system_message = gr.Textbox(value="You are a friendly Chatbot.", label="System message")
146
  max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
147
  temperature = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
148
  top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
149
 
150
+ file_upload = gr.File(label="📂 Télécharger un fichier PDF ou TXT", file_types=[".pdf", ".txt"], type="filepath")
151
+ file_output = gr.Textbox()
152
+ file_upload.change(embed_documents, inputs=file_upload, outputs=file_output)
153
 
154
  with gr.Column():
155
+ gr.Markdown("## 💬 Chat")
156
  chatbot = gr.ChatInterface(
157
  respond,
158
  additional_inputs=[system_message, max_tokens, temperature, top_p, file_upload],
159
  )
160
 
161
  if __name__ == "__main__":
162
+ demo.launch(share=True)
requirements.txt CHANGED
@@ -3,3 +3,5 @@ huggingface_hub==0.25.2
3
  python-dotenv
4
  PyMuPDF==1.21.0
5
  gradio==3.0.0
 
 
 
3
  python-dotenv
4
  PyMuPDF==1.21.0
5
  gradio==3.0.0
6
+ langchain==0.0.155
7
+ langchain-community==0.0.33