Spaces:
Sleeping
Sleeping
renaming main file frontend to app.py
Browse files- app.py +4 -258
- frontend.py +0 -46
app.py
CHANGED
|
@@ -1,262 +1,7 @@
|
|
| 1 |
-
# import gradio as gr
|
| 2 |
-
# from youtube_transcript_api import YouTubeTranscriptApi
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
from openai import OpenAI
|
| 6 |
-
import os
|
| 7 |
-
from dotenv import load_dotenv
|
| 8 |
-
from youtube_transcript_api import YouTubeTranscriptApi
|
| 9 |
import gradio as gr
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
# Load environment variables from .env file
|
| 12 |
-
load_dotenv()
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
OpenAI.api_key = os.getenv('OPENAI_API_KEY')
|
| 16 |
-
client = OpenAI()
|
| 17 |
-
|
| 18 |
-
def extraire_qr_de_chatgpt(reponse_chat_gpt):
|
| 19 |
-
"""
|
| 20 |
-
Extrait les paires de questions et réponses du texte de réponse ChatGPT.
|
| 21 |
-
|
| 22 |
-
:param reponse_chat_gpt: Le texte de réponse de ChatGPT contenant des Q/R.
|
| 23 |
-
:return: Liste de tuples contenant les paires (question, réponse).
|
| 24 |
-
"""
|
| 25 |
-
# Séparer le texte en lignes
|
| 26 |
-
lignes = reponse_chat_gpt.split('\n\n') # Deux sauts de ligne séparent chaque Q/R
|
| 27 |
-
paires_qr = []
|
| 28 |
-
|
| 29 |
-
for ligne in lignes:
|
| 30 |
-
if ligne.startswith("Q:") and "\nR:" in ligne:
|
| 31 |
-
question, reponse = ligne.split("\nR:")
|
| 32 |
-
paires_qr.append((question[3:], reponse)) # Supprime 'Q: ' de la question
|
| 33 |
-
|
| 34 |
-
return paires_qr
|
| 35 |
-
|
| 36 |
-
def obtenir_transcription(id_youtube):
|
| 37 |
-
"""
|
| 38 |
-
Obtient la transcription d'une vidéo YouTube à partir de son ID.
|
| 39 |
-
"""
|
| 40 |
-
try:
|
| 41 |
-
result = YouTubeTranscriptApi.get_transcript(id_youtube, languages=["fr"])
|
| 42 |
-
texte_continu = ' '.join([segment['text'] for segment in result])
|
| 43 |
-
# qr = extraire_qr_de_chatgpt(texte_continu)
|
| 44 |
-
return texte_continu
|
| 45 |
-
except Exception as e:
|
| 46 |
-
return str(e)
|
| 47 |
-
def decouper_texte_en_segments(texte, longueur_max=2000):
|
| 48 |
-
"""
|
| 49 |
-
Découpe un texte en segments de taille spécifiée sans couper les mots en deux.
|
| 50 |
-
|
| 51 |
-
:param texte: Le texte à découper.
|
| 52 |
-
:param longueur_max: La longueur maximale de chaque segment.
|
| 53 |
-
:return: Une liste de segments de texte.
|
| 54 |
-
"""
|
| 55 |
-
# Vérifie si le texte est plus court que la longueur maximale
|
| 56 |
-
if len(texte) <= longueur_max:
|
| 57 |
-
return [texte]
|
| 58 |
-
|
| 59 |
-
segments = []
|
| 60 |
-
mots = texte.split()
|
| 61 |
-
segment_actuel = []
|
| 62 |
-
|
| 63 |
-
for mot in mots:
|
| 64 |
-
# Vérifie si l'ajout du mot courant dépasse la longueur maximale
|
| 65 |
-
if len(' '.join(segment_actuel + [mot])) > longueur_max:
|
| 66 |
-
# Si oui, ajoute le segment actuel à la liste des segments et commence un nouveau segment
|
| 67 |
-
segments.append(' '.join(segment_actuel))
|
| 68 |
-
segment_actuel = [mot]
|
| 69 |
-
else:
|
| 70 |
-
# Si non, ajoute le mot au segment actuel
|
| 71 |
-
segment_actuel.append(mot)
|
| 72 |
-
|
| 73 |
-
# Ajoute le dernier segment s'il y a des mots restants
|
| 74 |
-
if segment_actuel:
|
| 75 |
-
segments.append(' '.join(segment_actuel))
|
| 76 |
-
|
| 77 |
-
return segments
|
| 78 |
-
|
| 79 |
-
def generer_questions_reponses(texte):
|
| 80 |
-
"""
|
| 81 |
-
Génère des questions et réponses à partir d'un texte donné en utilisant l'API d'OpenAI.
|
| 82 |
-
|
| 83 |
-
:param texte: Le texte à partir duquel générer les Q/R.
|
| 84 |
-
:return: Texte contenant les questions et réponses.
|
| 85 |
-
"""
|
| 86 |
-
client = OpenAI()
|
| 87 |
-
response = client.chat.completions.create(
|
| 88 |
-
model="gpt-4",
|
| 89 |
-
messages=[
|
| 90 |
-
{
|
| 91 |
-
"role": "system",
|
| 92 |
-
"content":
|
| 93 |
-
"""
|
| 94 |
-
Vous êtes un assistant perspicace capable de générer du contenu éducatif sous forme de question/réponse adapté
|
| 95 |
-
à un système de cartes de Leitner. Pour un text donné, tu es capable de générer des questions et des réponses.
|
| 96 |
-
Tu es attentif au nombre de question demandée par l'utilisateur
|
| 97 |
-
Utilisez un style formel en évitant les textes inutiles.
|
| 98 |
-
Les questions commencent par Q: et les réponses sur la ligne suivante par R:
|
| 99 |
-
Veuillez garder les réponses sous 10 mots maximum.
|
| 100 |
-
"""
|
| 101 |
-
},
|
| 102 |
-
{
|
| 103 |
-
"role": "user",
|
| 104 |
-
"content": f"""Pour un texte donné ci-après, extrait une information éducative pertinente et
|
| 105 |
-
résume là sous forme d'une question et d'une réponse très courte pour alimenter
|
| 106 |
-
une boîte de Leitner; La réponse ne doit pas dépasser 10 mots; Format de la réponse
|
| 107 |
-
: Première ligne Q: ... et deuxième ligne R: ...; Texte à traiter : '{texte}';"""
|
| 108 |
-
|
| 109 |
-
}
|
| 110 |
-
],
|
| 111 |
-
temperature=0.5 # Ajustez ce paramètre selon vos besoins
|
| 112 |
-
)
|
| 113 |
-
# print(response.choices[0].message.content)
|
| 114 |
-
# paires_qr = extraire_qr_de_chatgpt(response.choices[0].message.content)
|
| 115 |
-
# print(paires_qr)
|
| 116 |
-
return response.choices[0].message.content
|
| 117 |
-
|
| 118 |
-
def ajouter_cartes_leitner(texte_qr):
|
| 119 |
-
"""
|
| 120 |
-
Extrait les paires de questions-réponses du texte et les ajoute à la boîte de Leitner.
|
| 121 |
-
|
| 122 |
-
:param texte_qr: Le texte contenant les questions et réponses générées.
|
| 123 |
-
:return: Un message confirmant l'ajout des cartes.
|
| 124 |
-
"""
|
| 125 |
-
if leitner_system is None:
|
| 126 |
-
return "Veuillez d'abord créer une boîte de Leitner."
|
| 127 |
-
|
| 128 |
-
paires_qr = extraire_qr_de_chatgpt(texte_qr)
|
| 129 |
-
if not paires_qr:
|
| 130 |
-
return "Aucune paire Q/R n'a été trouvée dans le texte."
|
| 131 |
-
|
| 132 |
-
for question, reponse in paires_qr:
|
| 133 |
-
leitner_system.add_card(question, reponse)
|
| 134 |
-
|
| 135 |
-
return f"{len(paires_qr)} cartes ajoutées à la boîte de Leitner."
|
| 136 |
-
def processus_complet(id_youtube):
|
| 137 |
-
"""
|
| 138 |
-
Combine l'obtention de la transcription YouTube et la génération de Q/R dans un seul processus.
|
| 139 |
-
"""
|
| 140 |
-
transcription = obtenir_transcription(id_youtube)
|
| 141 |
-
segments = decouper_texte_en_segments(transcription, longueur_max=1000)
|
| 142 |
-
qr = generer_questions_reponses(segments[8])
|
| 143 |
-
print(segments[8])
|
| 144 |
-
# paires_qr = extraire_qr_de_chatgpt(qr)
|
| 145 |
-
# leitner_system_test = LeitnerSystem()
|
| 146 |
-
# result = YouTubeTranscriptApi.get_transcript('d2lJUOv0hLA&t=65s', languages = ["fr"])
|
| 147 |
-
# texte_continu = ' '.join([segment['text'] for segment in result]) # Concaténation de tous les segments de texte en une seule chaîne
|
| 148 |
-
# segments = decouper_texte_en_segments(texte_continu, longueur_max=1000)
|
| 149 |
-
# paires_qr = extraire_qr_de_chatgpt(generer_questions_reponses(segments[8]))
|
| 150 |
-
# for question, reponse in paires_qr:
|
| 151 |
-
# leitner_system_test.add_card(question, reponse)
|
| 152 |
-
return qr
|
| 153 |
-
|
| 154 |
-
client = OpenAI()
|
| 155 |
-
|
| 156 |
-
class LeitnerSystem:
|
| 157 |
-
def __init__(self):
|
| 158 |
-
self.compartments = [[], [], [], []] # Quatre compartiments pour cet exemple
|
| 159 |
-
|
| 160 |
-
def add_card(self, question, answer):
|
| 161 |
-
self.compartments[0].append({'question': question, 'answer': answer})
|
| 162 |
-
def compare_semantic_similarity(self, correct_answer, user_answer):
|
| 163 |
-
"""Utilise l'API d'OpenAI pour comparer la similarité sémantique des réponses."""
|
| 164 |
-
client = OpenAI()
|
| 165 |
-
try:
|
| 166 |
-
|
| 167 |
-
response = client.chat.completions.create(
|
| 168 |
-
model="gpt-4", # Utilisez "gpt-4" si vous avez accès à GPT-4
|
| 169 |
-
messages=[
|
| 170 |
-
{"role": "system", "content": "Vous êtes un assistant hautement intelligent capable d'évaluer la similarité sémantique entre deux phrases en fournissant une valeur de 0 à 10. X est un entier."},
|
| 171 |
-
{"role": "user", "content": f"""
|
| 172 |
-
Évaluez la similarité sémantique entre ces deux phrases en fournissant une note sur 10.
|
| 173 |
-
Exemple : 7. Cette avaleur est un entier
|
| 174 |
-
Phrase 1: '{correct_answer}'. Phrase 2: '{user_answer}'."
|
| 175 |
-
"""}
|
| 176 |
-
],
|
| 177 |
-
temperature=0.5,
|
| 178 |
-
max_tokens=600,
|
| 179 |
-
# seed=10
|
| 180 |
-
)
|
| 181 |
-
|
| 182 |
-
score = response.choices[0].message.content
|
| 183 |
-
# print(score)
|
| 184 |
-
# Utilisation d'une expression régulière pour extraire le score numérique
|
| 185 |
-
# score, analysis = self.extract_score_and_explanation(full_response)
|
| 186 |
-
|
| 187 |
-
return score
|
| 188 |
-
except Exception as e:
|
| 189 |
-
print("Erreur lors de l'évaluation de la similarité :", e)
|
| 190 |
-
return "0", str(e)
|
| 191 |
-
|
| 192 |
-
def compare_semantic_similarity_explanation(self, correct_answer, user_answer):
|
| 193 |
-
"""Utilise l'API d'OpenAI pour comparer la similarité sémantique des réponses."""
|
| 194 |
-
client = OpenAI()
|
| 195 |
-
try:
|
| 196 |
-
response = client.chat.completions.create(
|
| 197 |
-
model="gpt-4", # Utilisez "gpt-4" si vous avez accès à GPT-4
|
| 198 |
-
messages=[
|
| 199 |
-
{"role": "system", "content": "Vous êtes un assistant hautement intelligent capable d'évaluer la similarité sémantique entre deux phrases"},
|
| 200 |
-
{"role": "user", "content": f"Évaluez la similarité sémantique entre ces deux phrases en fournissant un explication en français. Les aspects positifs de la réponse, et les aspects négatifs. Phrase 1: '{correct_answer}'. Phrase 2: '{user_answer}'."}
|
| 201 |
-
],
|
| 202 |
-
temperature=0.5,
|
| 203 |
-
max_tokens=600,
|
| 204 |
-
# seed=10
|
| 205 |
-
)
|
| 206 |
-
|
| 207 |
-
explanation = response.choices[0].message.content
|
| 208 |
-
# print(explanation)
|
| 209 |
-
# Utilisation d'une expression régulière pour extraire le score numérique
|
| 210 |
-
# score, analysis = self.extract_score_and_explanation(full_response)
|
| 211 |
-
|
| 212 |
-
return explanation
|
| 213 |
-
except Exception as e:
|
| 214 |
-
print("Erreur lors de l'évaluation de la similarité :", e)
|
| 215 |
-
return "0", str(e)
|
| 216 |
-
|
| 217 |
-
def creer_boite_leitner():
|
| 218 |
-
global leitner_system
|
| 219 |
-
leitner_system = LeitnerSystem()
|
| 220 |
-
return "Boîte de Leitner créée avec succès!"
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
import random
|
| 225 |
-
|
| 226 |
-
# Ajout d'un attribut pour stocker la dernière question posée
|
| 227 |
-
LeitnerSystem.derniere_question = None
|
| 228 |
-
|
| 229 |
-
def poser_question():
|
| 230 |
-
global leitner_system
|
| 231 |
-
if leitner_system is None or not leitner_system.compartments[0]:
|
| 232 |
-
return "Aucune carte disponible pour le quiz.", ""
|
| 233 |
-
|
| 234 |
-
carte = random.choice(leitner_system.compartments[0])
|
| 235 |
-
leitner_system.derniere_question = carte
|
| 236 |
-
return carte['question'], ""
|
| 237 |
-
|
| 238 |
-
def valider_reponse(user_answer):
|
| 239 |
-
global leitner_system
|
| 240 |
-
|
| 241 |
-
if leitner_system.derniere_question is None:
|
| 242 |
-
return "Veuillez d'abord poser une question.", ""
|
| 243 |
-
|
| 244 |
-
correct_answer = leitner_system.derniere_question['answer']
|
| 245 |
-
|
| 246 |
-
# Utilise l'API d'OpenAI pour évaluer la similarité sémantique des réponses
|
| 247 |
-
score = leitner_system.compare_semantic_similarity(correct_answer, user_answer)
|
| 248 |
-
explanation = leitner_system.compare_semantic_similarity_explanation(correct_answer, user_answer)
|
| 249 |
-
|
| 250 |
-
# Logique pour déplacer la carte en fonction de la réponse
|
| 251 |
-
if float(score) > 5.0:
|
| 252 |
-
result = f"Correct! Votre score de similarité : {score}\n{explanation}"
|
| 253 |
-
# Déplacer la carte au prochain compartiment ou marquer comme maîtrisée
|
| 254 |
-
# Cette partie dépend de la manière dont vous souhaitez gérer la progression dans les compartiments
|
| 255 |
-
else:
|
| 256 |
-
result = f"Incorrect. Votre score de similarité : {score}\n{explanation}"
|
| 257 |
-
# Optionnellement, remettre la carte dans le premier compartiment ou gérer la répétition
|
| 258 |
-
|
| 259 |
-
return result, ""
|
| 260 |
|
| 261 |
with gr.Blocks() as demo:
|
| 262 |
with gr.Row():
|
|
@@ -296,5 +41,6 @@ with gr.Blocks() as demo:
|
|
| 296 |
|
| 297 |
# createLeitnerBox_btn.click(createLeitnerBox_btn)
|
| 298 |
|
|
|
|
| 299 |
if __name__ == "__main__":
|
| 300 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
from fonctions import obtenir_transcription, processus_complet, creer_boite_leitner, ajouter_cartes_leitner, poser_question, valider_reponse
|
| 3 |
+
from classes import LeitnerSystem
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
with gr.Blocks() as demo:
|
| 7 |
with gr.Row():
|
|
|
|
| 41 |
|
| 42 |
# createLeitnerBox_btn.click(createLeitnerBox_btn)
|
| 43 |
|
| 44 |
+
|
| 45 |
if __name__ == "__main__":
|
| 46 |
+
demo.launch()
|
frontend.py
DELETED
|
@@ -1,46 +0,0 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
-
from fonctions import obtenir_transcription, processus_complet, creer_boite_leitner, ajouter_cartes_leitner, poser_question, valider_reponse
|
| 3 |
-
from classes import LeitnerSystem
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
with gr.Blocks() as demo:
|
| 7 |
-
with gr.Row():
|
| 8 |
-
id_youtube_input = gr.Textbox(label="ID YouTube", value="a6Sfpbjz68k&t=365s")
|
| 9 |
-
with gr.Row():
|
| 10 |
-
transcript_btn = gr.Button("Générer transcription")
|
| 11 |
-
generer_btn = gr.Button("Générer Q/R")
|
| 12 |
-
with gr.Row():
|
| 13 |
-
txtB_transcript = gr.Textbox(label= "transcription", lines = 4)
|
| 14 |
-
sortie = gr.Textbox(label="Questions/Réponses", lines=4)
|
| 15 |
-
with gr.Row():
|
| 16 |
-
createLeitnerBox_btn = gr.Button("Créer une boite de Leitner")
|
| 17 |
-
ajouter_cartes_btn = gr.Button("Ajouter les cartes")
|
| 18 |
-
with gr.Row():
|
| 19 |
-
leitner_box_status = gr.Textbox(label="Statut de la boîte de Leitner")
|
| 20 |
-
ajout_cartes_status = gr.Textbox(label="Statut d'ajout des cartes")
|
| 21 |
-
with gr.Row():
|
| 22 |
-
# Ajout_des_cartes_btn = gr.Button("Ajout des cartes")
|
| 23 |
-
poser_question_btn = gr.Button("Poser une Question")
|
| 24 |
-
question_affichee = gr.Textbox(label="Question")
|
| 25 |
-
with gr.Row():
|
| 26 |
-
valider_reponse_btn = gr.Button("Valider la Réponse")
|
| 27 |
-
reponse_utilisateur = gr.Textbox(label="Votre Réponse")
|
| 28 |
-
with gr.Row():
|
| 29 |
-
resultat_quiz = gr.Textbox(label="Résultat")
|
| 30 |
-
|
| 31 |
-
# charger contenu
|
| 32 |
-
transcript_btn.click(obtenir_transcription,inputs = id_youtube_input, outputs = txtB_transcript)
|
| 33 |
-
generer_btn.click(processus_complet, inputs=id_youtube_input, outputs=sortie)
|
| 34 |
-
# charger box
|
| 35 |
-
createLeitnerBox_btn.click(creer_boite_leitner, inputs=None, outputs=leitner_box_status)
|
| 36 |
-
# charger carte dans box
|
| 37 |
-
ajouter_cartes_btn.click(ajouter_cartes_leitner, inputs=sortie, outputs=ajout_cartes_status)
|
| 38 |
-
# Quizz et evaluation + mise à jour de la box
|
| 39 |
-
poser_question_btn.click(poser_question, inputs=None, outputs=[question_affichee, reponse_utilisateur])
|
| 40 |
-
valider_reponse_btn.click(valider_reponse, inputs=reponse_utilisateur, outputs=resultat_quiz)
|
| 41 |
-
|
| 42 |
-
# createLeitnerBox_btn.click(createLeitnerBox_btn)
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
if __name__ == "__main__":
|
| 46 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|