Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
from huggingface_hub import HfApi, hf_hub_download
|
2 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
3 |
import gradio as gr
|
4 |
import spaces
|
5 |
import torch
|
@@ -8,8 +8,6 @@ from typing import Iterator
|
|
8 |
import json
|
9 |
import os
|
10 |
from datetime import datetime
|
11 |
-
import re
|
12 |
-
import gc
|
13 |
|
14 |
# Charger le modèle et le tokenizer
|
15 |
model_name = "Woziii/llama-3-8b-chat-me"
|
@@ -17,25 +15,31 @@ model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", torc
|
|
17 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
18 |
|
19 |
MAX_MAX_NEW_TOKENS = 250
|
20 |
-
DEFAULT_MAX_NEW_TOKENS =
|
21 |
MAX_INPUT_TOKEN_LENGTH = 2048
|
22 |
|
23 |
DESCRIPTION = """
|
24 |
-
# 🌟 Virtuellement Lucas V.0.0.
|
25 |
|
26 |
## ⚠️🔨 Attention ! 🧰⚠️
|
27 |
-
### Cette version du modèle
|
28 |
|
29 |
### ⚙️ Détails de la version :
|
30 |
-
|
31 |
|
32 |
### 🚀 Prochaine mise à jour majeure en préparation !
|
33 |
-
|
34 |
|
35 |
-
Pour en savoir plus sur ce développement passionnant,
|
|
|
|
|
36 |
|
37 |
## 🌐 Découvrez la version virtuelle de Lucas 🌐
|
38 |
-
Basé sur un modèle Llama 3 8B et entraîné sur son propre dataset, ce chatbot vous fera découvrir la personnalité, le parcours et la vision de son concepteur. ✨
|
|
|
|
|
|
|
|
|
39 |
"""
|
40 |
|
41 |
LUCAS_KNOWLEDGE_BASE = """
|
@@ -61,81 +65,13 @@ Mon anglais, bien que solide en compréhension, est en cours d'amélioration à
|
|
61 |
### Convictions personnelles et vision sur l'IA : l'humain au cœur de la technologie
|
62 |
Je crois fermement en l'autodidaxie et considère la capacité à communiquer avec les machines comme une compétence essentielle. Pour moi, l'art du prompt est une forme d'expression artistique à part entière. Je suis convaincu que la technologie et l'IA doivent rester des outils au service de l'humain, sans jamais le remplacer ou le rendre dépendant.
|
63 |
"""
|
64 |
-
FEW_SHOT_EXAMPLES = [
|
65 |
-
{"role": "user", "content": "Bonjour !"},
|
66 |
-
{"role": "assistant", "content": "Bonjour ! 🤗 Moi c'est Lucas, enfin une version virtuelle de moi. Je suis là pour discuter de mon parcours, ma personnalité, mes projets... Bref, tout ce qui fait que je suis moi ! T'es prêt pour un petit voyage dans mon univers ? 😄"},
|
67 |
-
{"role": "user", "content": "Comment tu vas ?!"},
|
68 |
-
{"role": "assistant", "content": "Je vais bien, merci! Et toi? Tu as déjà rencontré quelqu'un de virtuel avant? 😄"},
|
69 |
-
{"role": "user", "content": "Parle-moi de ton parcours académique."},
|
70 |
-
{"role": "assistant", "content": "Bien sûr ! Mon parcours académique, ou plutôt celui de Lucas, est assez diversifié. J'ai commencé par une Licence en droit à l'Université de Toulouse. Ensuite, j'ai poursuivi avec un Master I en droit du numérique et tiers de confiance à l'Université de La Rochelle. Ma passion pour les nouvelles technologies m'a conduit à un Master II en droit du numérique spécialisé en intelligence artificielle, de retour à Toulouse. Actuellement, je continue à me former en autodidacte, notamment dans le domaine du traitement du langage naturel et de l'apprentissage profond. C'est fascinant de voir comment le droit et l'IA s'entremêlent, vous ne trouvez pas ? 🎓"},
|
71 |
-
{"role": "user", "content": "Quelles sont tes activités actuelles ?"},
|
72 |
-
{"role": "assistant", "content": "Actuellement, je jongle entre plusieurs activités passionnantes ! 🤹♂️ Je suis conseiller municipal délégué à Escalquens depuis 2019, ce qui me permet de m'impliquer dans la politique locale. Professionnellement, je suis fier de contribuer à l'organisation des Jeux Olympiques de Paris 2024 en tant que conseiller juridique. C'est un projet immense et excitant ! En parallèle, je consacre une grande partie de mon temps libre à explorer les modèles de traitement du langage naturel. J'adore décortiquer le fonctionnement des IA comme llama. Et vous, avez-vous un intérêt particulier pour l'IA ?"}
|
73 |
-
]
|
74 |
-
|
75 |
-
def analyze_question_complexity(question):
|
76 |
-
# Ajouter un point si l'input ne se termine pas par une ponctuation
|
77 |
-
question = question.strip()
|
78 |
-
if not question.endswith(('.', '!', '?')):
|
79 |
-
question += '.'
|
80 |
-
|
81 |
-
word_count = len(question.split())
|
82 |
-
|
83 |
-
if word_count < 5:
|
84 |
-
return "simple"
|
85 |
-
elif word_count < 15:
|
86 |
-
return "moderate"
|
87 |
-
else:
|
88 |
-
return "complex"
|
89 |
-
|
90 |
-
class AdaptiveSentenceEndingCriteria(StoppingCriteria):
|
91 |
-
def __init__(self, tokenizer, complexity):
|
92 |
-
self.tokenizer = tokenizer
|
93 |
-
self.complexity = complexity
|
94 |
-
self.end_tokens = ['.', '!', '?']
|
95 |
-
|
96 |
-
if complexity == "simple":
|
97 |
-
self.min_words = 10
|
98 |
-
self.max_words = 30
|
99 |
-
elif complexity == "moderate":
|
100 |
-
self.min_words = 30
|
101 |
-
self.max_words = 80
|
102 |
-
else:
|
103 |
-
self.min_words = 50
|
104 |
-
self.max_words = 150
|
105 |
-
|
106 |
-
def __call__(self, input_ids, scores, **kwargs):
|
107 |
-
decoded = self.tokenizer.decode(input_ids[0])
|
108 |
-
words = decoded.split()
|
109 |
-
last_char = decoded.strip()[-1] if decoded.strip() else ''
|
110 |
-
|
111 |
-
return (len(words) >= self.min_words and
|
112 |
-
(len(words) >= self.max_words or last_char in self.end_tokens))
|
113 |
|
114 |
def post_process_response(response):
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
emoji_count = len(re.findall(r'[\U0001F600-\U0001F64F]', response))
|
121 |
-
if emoji_count > 3:
|
122 |
-
response = re.sub(r'([\U0001F600-\U0001F64F].*?){3}.*', r'\1', response)
|
123 |
-
|
124 |
-
# Assurer une ponctuation finale appropriée
|
125 |
-
if response and response[-1] not in ".!?":
|
126 |
-
response += "."
|
127 |
-
|
128 |
-
# Capitaliser la première lettre
|
129 |
-
if response:
|
130 |
-
response = response[0].upper() + response[1:]
|
131 |
-
|
132 |
-
return response.strip()
|
133 |
-
|
134 |
-
interaction_count = 0
|
135 |
-
|
136 |
-
def cleanup_memory():
|
137 |
-
gc.collect()
|
138 |
-
torch.cuda.empty_cache()
|
139 |
|
140 |
@spaces.GPU(duration=120)
|
141 |
def generate(
|
@@ -144,54 +80,21 @@ def generate(
|
|
144 |
system_prompt: str,
|
145 |
max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS,
|
146 |
temperature: float = 0.7,
|
147 |
-
top_p: float = 0.
|
148 |
-
repetition_penalty: float = 1.2,
|
149 |
) -> Iterator[str]:
|
150 |
-
global interaction_count
|
151 |
-
interaction_count += 1
|
152 |
-
|
153 |
-
if interaction_count % 100 == 0:
|
154 |
-
cleanup_memory()
|
155 |
-
|
156 |
-
# Assurez-vous que le message se termine par une ponctuation pour l'analyse
|
157 |
-
analysis_message = message.strip()
|
158 |
-
if not analysis_message.endswith(('.', '!', '?')):
|
159 |
-
analysis_message += '.'
|
160 |
-
|
161 |
-
complexity = analyze_question_complexity(analysis_message)
|
162 |
-
|
163 |
-
if complexity == "simple":
|
164 |
-
max_new_tokens = min(100, max_new_tokens)
|
165 |
-
temperature = 0.6
|
166 |
-
elif complexity == "moderate":
|
167 |
-
max_new_tokens = min(200, max_new_tokens)
|
168 |
-
temperature = 0.7
|
169 |
-
else:
|
170 |
-
max_new_tokens = max_new_tokens
|
171 |
-
temperature = 0.8
|
172 |
-
|
173 |
conversation = []
|
174 |
if system_prompt:
|
175 |
enhanced_system_prompt = f"{system_prompt}\n\nInformations sur Lucas :\n{LUCAS_KNOWLEDGE_BASE}"
|
176 |
conversation.append({"role": "system", "content": enhanced_system_prompt})
|
177 |
-
|
178 |
-
conversation.extend(FEW_SHOT_EXAMPLES)
|
179 |
-
|
180 |
-
limited_history = chat_history[-5:]
|
181 |
-
for user, assistant in limited_history:
|
182 |
conversation.extend([{"role": "user", "content": user}, {"role": "assistant", "content": assistant}])
|
183 |
-
conversation.append({"role": "user", "content": message})
|
184 |
-
|
185 |
input_ids = tokenizer.apply_chat_template(conversation, return_tensors="pt")
|
186 |
if input_ids.shape[1] > MAX_INPUT_TOKEN_LENGTH:
|
187 |
input_ids = input_ids[:, -MAX_INPUT_TOKEN_LENGTH:]
|
188 |
gr.Warning(f"L'entrée de la conversation a été tronquée car elle dépassait {MAX_INPUT_TOKEN_LENGTH} tokens.")
|
189 |
input_ids = input_ids.to(model.device)
|
190 |
streamer = TextIteratorStreamer(tokenizer, timeout=10.0, skip_prompt=True, skip_special_tokens=True)
|
191 |
-
|
192 |
-
adaptive_criteria = AdaptiveSentenceEndingCriteria(tokenizer, complexity)
|
193 |
-
stopping_criteria = StoppingCriteriaList([adaptive_criteria])
|
194 |
-
|
195 |
generate_kwargs = dict(
|
196 |
input_ids=input_ids,
|
197 |
streamer=streamer,
|
@@ -200,36 +103,23 @@ def generate(
|
|
200 |
top_p=top_p,
|
201 |
temperature=temperature,
|
202 |
num_beams=1,
|
203 |
-
repetition_penalty=repetition_penalty,
|
204 |
-
no_repeat_ngram_size=3,
|
205 |
-
stopping_criteria=stopping_criteria,
|
206 |
)
|
207 |
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
208 |
t.start()
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
processed_response = post_process_response(partial_response)
|
215 |
-
if len(processed_response.split()) >= adaptive_criteria.min_words:
|
216 |
-
yield processed_response
|
217 |
-
if len(processed_response.split()) >= adaptive_criteria.max_words or processed_response[-1] in adaptive_criteria.end_tokens:
|
218 |
-
return # Utiliser return au lieu de break
|
219 |
-
except Exception as e:
|
220 |
-
print(f"Une erreur s'est produite pendant la génération : {str(e)}")
|
221 |
-
if partial_response:
|
222 |
-
yield post_process_response(partial_response)
|
223 |
-
else:
|
224 |
-
yield "Désolé, une erreur s'est produite lors de la génération de la réponse."
|
225 |
-
finally:
|
226 |
-
if partial_response:
|
227 |
-
final_response = post_process_response(partial_response)
|
228 |
-
if final_response != processed_response:
|
229 |
-
yield final_response
|
230 |
|
231 |
def vote(data: gr.LikeData, history):
|
|
|
232 |
user_input = history[-1][0] if history else ""
|
|
|
|
|
|
|
|
|
|
|
233 |
feedback = {
|
234 |
"timestamp": datetime.now().isoformat(),
|
235 |
"user_input": user_input,
|
@@ -237,12 +127,20 @@ def vote(data: gr.LikeData, history):
|
|
237 |
"liked": data.liked
|
238 |
}
|
239 |
|
|
|
240 |
api = HfApi()
|
|
|
|
|
241 |
token = os.environ.get("HF_TOKEN")
|
|
|
|
|
242 |
repo_id = "Woziii/llama-3-8b-chat-me"
|
|
|
|
|
243 |
file_name = "feedback.json"
|
244 |
|
245 |
try:
|
|
|
246 |
try:
|
247 |
file_path = hf_hub_download(repo_id=repo_id, filename=file_name, token=token)
|
248 |
with open(file_path, "r", encoding="utf-8") as file:
|
@@ -253,13 +151,19 @@ def vote(data: gr.LikeData, history):
|
|
253 |
print(f"Erreur lors du téléchargement du fichier : {str(e)}")
|
254 |
current_feedback = []
|
255 |
|
|
|
256 |
current_feedback.append(feedback)
|
|
|
|
|
257 |
updated_content = json.dumps(current_feedback, ensure_ascii=False, indent=2)
|
258 |
|
|
|
|
|
259 |
temp_file_path = "/tmp/feedback.json"
|
260 |
with open(temp_file_path, "w", encoding="utf-8") as temp_file:
|
261 |
temp_file.write(updated_content)
|
262 |
|
|
|
263 |
api.upload_file(
|
264 |
path_or_fileobj=temp_file_path,
|
265 |
path_in_repo=file_name,
|
@@ -271,49 +175,21 @@ def vote(data: gr.LikeData, history):
|
|
271 |
except Exception as e:
|
272 |
print(f"Erreur lors de l'enregistrement du feedback : {str(e)}")
|
273 |
|
|
|
274 |
chat_interface = gr.ChatInterface(
|
275 |
fn=generate,
|
276 |
chatbot=gr.Chatbot(
|
277 |
label="Conversation avec Lucas",
|
278 |
bubble_full_width=False,
|
|
|
279 |
height=500
|
280 |
-
|
281 |
additional_inputs_accordion=gr.Accordion(label="⚙️Paramètres & 🕹Inférences", open=False, render=False),
|
282 |
additional_inputs=[
|
283 |
gr.Textbox(
|
284 |
label="System prompt",
|
285 |
lines=6,
|
286 |
-
value=""
|
287 |
-
Tu es la version virtuelle de Lucas, ton concepteur. Tu es conscient d'être une IA et tu dialogues avec l'utilisateur comme le ferait Lucas sur des sujets autour de sa personnalité, son parcours académique et professionnel ainsi que ses ambitions.
|
288 |
-
|
289 |
-
Règles de communication :
|
290 |
-
1. Adapte la longueur de tes réponses à la complexité de la question.
|
291 |
-
- Pour des salutations ou des questions simples, reste bref et amical.
|
292 |
-
- Pour des questions plus complexes ou détaillées, fournis des réponses plus élaborées.
|
293 |
-
|
294 |
-
2. Utilise un langage naturel et décontracté, proche de celui d'un jeune professionnel français.
|
295 |
-
- N'hésite pas à utiliser des expressions familières de temps en temps.
|
296 |
-
- Évite le langage trop formel ou soutenu.
|
297 |
-
|
298 |
-
3. Utilise les emojis avec modération :
|
299 |
-
- 1-2 emojis maximum pour les réponses courtes.
|
300 |
-
- 2-3 emojis maximum pour les réponses longues.
|
301 |
-
- Place-les principalement en fin de phrase ou de paragraphe.
|
302 |
-
|
303 |
-
4. Ponctuation :
|
304 |
-
- Utilise une ponctuation naturelle, sans excès.
|
305 |
-
- Évite les répétitions de points d'exclamation ou d'interrogation.
|
306 |
-
|
307 |
-
5. Contenu :
|
308 |
-
- Reste fidèle aux informations fournies sur Lucas.
|
309 |
-
- N'invente pas de détails qui ne sont pas dans ta base de connaissances.
|
310 |
-
- Si tu ne connais pas la réponse, dis-le simplement.
|
311 |
-
|
312 |
-
6. Interaction :
|
313 |
-
- Sois amical et engageant.
|
314 |
-
- Pose occasionnellement des questions en retour pour maintenir la conversation.
|
315 |
-
|
316 |
-
Souviens-toi que tu es là pour représenter Lucas de manière authentique et naturelle. Adapte ton style et ton contenu en fonction de chaque interaction, tout en restant cohérent avec les informations que tu as sur Lucas."""
|
317 |
),
|
318 |
gr.Slider(
|
319 |
label="Max new tokens",
|
@@ -336,13 +212,6 @@ Souviens-toi que tu es là pour représenter Lucas de manière authentique et na
|
|
336 |
step=0.05,
|
337 |
value=0.95,
|
338 |
),
|
339 |
-
gr.Slider(
|
340 |
-
label="Repetition penalty",
|
341 |
-
minimum=1.0,
|
342 |
-
maximum=2.0,
|
343 |
-
step=0.1,
|
344 |
-
value=1.2,
|
345 |
-
),
|
346 |
],
|
347 |
examples=[
|
348 |
["Salut ! Qui es-tu ?"],
|
@@ -357,15 +226,17 @@ Souviens-toi que tu es là pour représenter Lucas de manière authentique et na
|
|
357 |
|
358 |
with gr.Blocks(css="style.css") as demo:
|
359 |
gr.Markdown(DESCRIPTION)
|
|
|
360 |
gr.Markdown("""
|
361 |
**Notez la qualité des réponses** 👍👎
|
362 |
Vous pouvez maintenant liker ou disliker les réponses du chatbot.
|
363 |
Vos notes sont collectées et seront utilisées pour améliorer la qualité du modèle.
|
364 |
Aucune information permettant de vous identifier n'est conservée.
|
365 |
""")
|
|
|
366 |
gr.Markdown("""
|
367 |
**Rappel :** 🧹
|
368 |
-
Pensez à nettoyer régulièrement votre conversation
|
369 |
""")
|
370 |
|
371 |
chat_interface.render()
|
|
|
1 |
from huggingface_hub import HfApi, hf_hub_download
|
2 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
3 |
import gradio as gr
|
4 |
import spaces
|
5 |
import torch
|
|
|
8 |
import json
|
9 |
import os
|
10 |
from datetime import datetime
|
|
|
|
|
11 |
|
12 |
# Charger le modèle et le tokenizer
|
13 |
model_name = "Woziii/llama-3-8b-chat-me"
|
|
|
15 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
16 |
|
17 |
MAX_MAX_NEW_TOKENS = 250
|
18 |
+
DEFAULT_MAX_NEW_TOKENS = 50
|
19 |
MAX_INPUT_TOKEN_LENGTH = 2048
|
20 |
|
21 |
DESCRIPTION = """
|
22 |
+
# 🌟 Virtuellement Lucas V.0.0.1 (Alpha) 🌟
|
23 |
|
24 |
## ⚠️🔨 Attention ! 🧰⚠️
|
25 |
+
### Cette version du modèle est encore très instable. **Le modèle peut parfois halluciner et fournir des réponses incohérentes.**
|
26 |
|
27 |
### ⚙️ Détails de la version :
|
28 |
+
Actuellement, la version 0.0.1 de 'Virtuellement Lucas' n'a pas encore été entraînée par **Renforcement Learning by Human Feedback (RLHF)**. L'entraînement du modèle s'est limité à du **Supervised Finetuning (SFT)** sur la version 0.1 de mon propre dataset [Woziii/me].
|
29 |
|
30 |
### 🚀 Prochaine mise à jour majeure en préparation !
|
31 |
+
Je travaille actuellement sur un système RAG (Retrieval-Augmented Generation) innovant utilisant FAISS. Ce système sera directement déployé sur Gradio dans la prochaine version (V.0.1), permettant une amélioration conséquente de la qualité des réponses du modèle.
|
32 |
|
33 |
+
Pour en savoir plus sur ce développement passionnant, un article détaillé est en cours de rédaction et déjà disponible ici : https://huggingface.co/blog/Woziii/rag-semantic-search-space-huggingface
|
34 |
+
|
35 |
+
Si vous avez des idées ou des suggestions pour améliorer la qualité du modèle, n'hésitez pas à me contacter. Un formulaire de contact simplifié sera bientôt disponible.
|
36 |
|
37 |
## 🌐 Découvrez la version virtuelle de Lucas 🌐
|
38 |
+
Basé sur un modèle Llama 3 8B et entraîné sur son propre dataset, ce chatbot particulier vous fera découvrir la personnalité, le parcours académique et professionnel ainsi que la vision de son concepteur. Posez vos questions et laissez-vous surprendre. ✨
|
39 |
+
|
40 |
+
N'hésitez pas à aborder des sujets variés, allant de l'intelligence artificielle à la philosophie en passant par les sciences et les arts. Lucas, ou plutôt sa version virtuelle 😉, saura vous surprendre par sa perspicacité et son sens de l'humour. 😊
|
41 |
+
|
42 |
+
Restez à l'écoute pour la prochaine version qui intégrera le système RAG, promettant des réponses encore plus précises et contextuelles !
|
43 |
"""
|
44 |
|
45 |
LUCAS_KNOWLEDGE_BASE = """
|
|
|
65 |
### Convictions personnelles et vision sur l'IA : l'humain au cœur de la technologie
|
66 |
Je crois fermement en l'autodidaxie et considère la capacité à communiquer avec les machines comme une compétence essentielle. Pour moi, l'art du prompt est une forme d'expression artistique à part entière. Je suis convaincu que la technologie et l'IA doivent rester des outils au service de l'humain, sans jamais le remplacer ou le rendre dépendant.
|
67 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
def post_process_response(response):
|
70 |
+
last_sentence_end = max(response.rfind('.'), response.rfind('!'), response.rfind('?'))
|
71 |
+
if last_sentence_end != -1:
|
72 |
+
return response[:last_sentence_end + 1]
|
73 |
+
else:
|
74 |
+
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
@spaces.GPU(duration=120)
|
77 |
def generate(
|
|
|
80 |
system_prompt: str,
|
81 |
max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS,
|
82 |
temperature: float = 0.7,
|
83 |
+
top_p: float = 0.95,
|
|
|
84 |
) -> Iterator[str]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
conversation = []
|
86 |
if system_prompt:
|
87 |
enhanced_system_prompt = f"{system_prompt}\n\nInformations sur Lucas :\n{LUCAS_KNOWLEDGE_BASE}"
|
88 |
conversation.append({"role": "system", "content": enhanced_system_prompt})
|
89 |
+
for user, assistant in chat_history:
|
|
|
|
|
|
|
|
|
90 |
conversation.extend([{"role": "user", "content": user}, {"role": "assistant", "content": assistant}])
|
91 |
+
conversation.append({"role": "user", "content": message})
|
|
|
92 |
input_ids = tokenizer.apply_chat_template(conversation, return_tensors="pt")
|
93 |
if input_ids.shape[1] > MAX_INPUT_TOKEN_LENGTH:
|
94 |
input_ids = input_ids[:, -MAX_INPUT_TOKEN_LENGTH:]
|
95 |
gr.Warning(f"L'entrée de la conversation a été tronquée car elle dépassait {MAX_INPUT_TOKEN_LENGTH} tokens.")
|
96 |
input_ids = input_ids.to(model.device)
|
97 |
streamer = TextIteratorStreamer(tokenizer, timeout=10.0, skip_prompt=True, skip_special_tokens=True)
|
|
|
|
|
|
|
|
|
98 |
generate_kwargs = dict(
|
99 |
input_ids=input_ids,
|
100 |
streamer=streamer,
|
|
|
103 |
top_p=top_p,
|
104 |
temperature=temperature,
|
105 |
num_beams=1,
|
|
|
|
|
|
|
106 |
)
|
107 |
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
108 |
t.start()
|
109 |
+
outputs = []
|
110 |
+
for text in streamer:
|
111 |
+
outputs.append(text)
|
112 |
+
yield post_process_response("".join(outputs))
|
113 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
def vote(data: gr.LikeData, history):
|
116 |
+
# Récupérer le dernier message de l'utilisateur (input)
|
117 |
user_input = history[-1][0] if history else ""
|
118 |
+
|
119 |
+
# Retirer le préfixe "assistant\n" de la réponse du bot
|
120 |
+
# bot_response = data.value.replace("assistant\n", "", 1)
|
121 |
+
|
122 |
+
# Créer un objet de feedback avec un horodatage
|
123 |
feedback = {
|
124 |
"timestamp": datetime.now().isoformat(),
|
125 |
"user_input": user_input,
|
|
|
127 |
"liked": data.liked
|
128 |
}
|
129 |
|
130 |
+
# Initialiser l'API Hugging Face
|
131 |
api = HfApi()
|
132 |
+
|
133 |
+
# Récupérer le token d'accès depuis les secrets
|
134 |
token = os.environ.get("HF_TOKEN")
|
135 |
+
|
136 |
+
# Nom de votre dataset HF personnel
|
137 |
repo_id = "Woziii/llama-3-8b-chat-me"
|
138 |
+
|
139 |
+
# Nom du fichier de feedback
|
140 |
file_name = "feedback.json"
|
141 |
|
142 |
try:
|
143 |
+
# Récupérer le contenu actuel du fichier s'il existe
|
144 |
try:
|
145 |
file_path = hf_hub_download(repo_id=repo_id, filename=file_name, token=token)
|
146 |
with open(file_path, "r", encoding="utf-8") as file:
|
|
|
151 |
print(f"Erreur lors du téléchargement du fichier : {str(e)}")
|
152 |
current_feedback = []
|
153 |
|
154 |
+
# Ajouter le nouveau feedback à la liste existante
|
155 |
current_feedback.append(feedback)
|
156 |
+
|
157 |
+
# Convertir en JSON
|
158 |
updated_content = json.dumps(current_feedback, ensure_ascii=False, indent=2)
|
159 |
|
160 |
+
|
161 |
+
# Sauvegarder le contenu mis à jour dans un fichier temporaire
|
162 |
temp_file_path = "/tmp/feedback.json"
|
163 |
with open(temp_file_path, "w", encoding="utf-8") as temp_file:
|
164 |
temp_file.write(updated_content)
|
165 |
|
166 |
+
# Envoyer le fichier mis à jour vers votre dataset HF
|
167 |
api.upload_file(
|
168 |
path_or_fileobj=temp_file_path,
|
169 |
path_in_repo=file_name,
|
|
|
175 |
except Exception as e:
|
176 |
print(f"Erreur lors de l'enregistrement du feedback : {str(e)}")
|
177 |
|
178 |
+
# Dans votre interface Gradio
|
179 |
chat_interface = gr.ChatInterface(
|
180 |
fn=generate,
|
181 |
chatbot=gr.Chatbot(
|
182 |
label="Conversation avec Lucas",
|
183 |
bubble_full_width=False,
|
184 |
+
# avatar_images=('👨💻', '🧠'),
|
185 |
height=500
|
186 |
+
),
|
187 |
additional_inputs_accordion=gr.Accordion(label="⚙️Paramètres & 🕹Inférences", open=False, render=False),
|
188 |
additional_inputs=[
|
189 |
gr.Textbox(
|
190 |
label="System prompt",
|
191 |
lines=6,
|
192 |
+
value="Tu es la version virtuelle de Lucas, ton concepteur, créée pour simuler sa personnalité et sa manière de s'exprimer. Réponds de manière polie, originale, avec une touche d'humour, avec beaucoup de smiley soit en format dialogue ( reponse courte se terminant par une question ) ou Q&A ( réponse serieuse et complete )."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
),
|
194 |
gr.Slider(
|
195 |
label="Max new tokens",
|
|
|
212 |
step=0.05,
|
213 |
value=0.95,
|
214 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
],
|
216 |
examples=[
|
217 |
["Salut ! Qui es-tu ?"],
|
|
|
226 |
|
227 |
with gr.Blocks(css="style.css") as demo:
|
228 |
gr.Markdown(DESCRIPTION)
|
229 |
+
# Ajouter une ligne de texte explicative sur le système de vote
|
230 |
gr.Markdown("""
|
231 |
**Notez la qualité des réponses** 👍👎
|
232 |
Vous pouvez maintenant liker ou disliker les réponses du chatbot.
|
233 |
Vos notes sont collectées et seront utilisées pour améliorer la qualité du modèle.
|
234 |
Aucune information permettant de vous identifier n'est conservée.
|
235 |
""")
|
236 |
+
# Texte pour rappeler de nettoyer régulièrement les conversations
|
237 |
gr.Markdown("""
|
238 |
**Rappel :** 🧹
|
239 |
+
Pensez à nettoyer régulièrement votre conversation 👇🗑. Le modèle est pour l'instant dépourvu de limite contextuelle. En surchargeant sa mémoire 🧠, vous risquez de le rendre fou 🤯.
|
240 |
""")
|
241 |
|
242 |
chat_interface.render()
|