File size: 11,201 Bytes
806374e
672c6f3
806374e
fd6f10e
9cf2f4c
18c2654
806374e
 
18c2654
806374e
fd6f10e
04accba
672c6f3
 
04accba
 
 
 
2888244
672c6f3
806374e
 
 
 
 
944ab9b
 
 
 
 
 
 
 
 
 
 
 
 
04accba
806374e
fd6f10e
e53eee7
bc1aadf
18c2654
672c6f3
5a88082
806374e
 
 
672c6f3
806374e
04accba
806374e
0dfa905
806374e
 
 
 
 
 
1965b20
 
4af0e65
0207153
46c60b8
04accba
46c60b8
898d7eb
 
 
46c60b8
898d7eb
 
 
04accba
 
0bb2945
c732fe2
ab92035
0bb2945
 
2923823
 
 
 
b3b43c2
2923823
0bb2945
 
2923823
 
 
 
b3b43c2
0bb2945
8d46470
 
 
 
 
 
 
 
 
 
ab92035
8d46470
 
c732fe2
 
ab92035
9e4c9b2
bd095b8
9f99078
bd095b8
ad49927
 
 
 
 
c732fe2
 
 
99615f4
46c60b8
9e4c9b2
 
bd095b8
9f99078
bd095b8
 
 
 
 
 
c732fe2
 
 
99615f4
46c60b8
9e4c9b2
 
bd095b8
d8dc558
99615f4
 
 
 
9eab70b
99615f4
9eab70b
99615f4
 
 
 
5df60f7
04accba
ad49927
dc86373
0207153
dc86373
0207153
dc86373
0207153
dc86373
 
5df60f7
9f99078
 
0c148ab
d0f6885
04accba
c6a8aac
bd095b8
d0f6885
c6a8aac
c732fe2
 
 
 
 
ab92035
 
 
 
f190d31
e53eee7
46c60b8
1a48f09
2ce4574
1a48f09
 
 
2ce4574
f8a3614
 
 
 
 
 
99615f4
46c60b8
 
f8a3614
 
c6a8aac
638d862
c0308c2
46c60b8
c6a8aac
 
04accba
46c60b8
 
 
04accba
 
e53eee7
f190d31
04accba
e53eee7
4af0e65
 
5017d85
da45833
ab92035
 
0bb2945
c732fe2
ab92035
 
8c128f8
cec8058
 
 
 
 
fd6f10e
5df60f7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
import os
import gradio as gr
from groq import Groq

api_key = os.getenv("GROQ_API_KEY")

if not api_key:
    raise ValueError("GROQ_API_KEY is not set. Please set it as an environment variable.")

client = Groq(api_key=api_key)

def generate_reply(user_input, chat_history, profound_state):
    if chat_history is None:
        chat_history = []
    
    profound_mode = "Provide a basic explanation"
    if profound_state:
        profound_mode = "Provide a highly detailed and in-depth explanation, including historical context, key figures, and consequences of the event."

    conversation = [{"role": "system", "content": (
        "Determine the language of the user's question and respond in the same language. "
        "Users may switch between English and French, so maintain consistency. "
        "Only answer history-related questions. If asked about another topic, reply with: "
        "'I am a history chatbot and can only answer history-related questions.' "
        "(or the equivalent in French, depending on the input language). Then stop responding."
        "The following questions are examples of acceptable questions "
        "How did the Leaning Tower of Pisa start leaning?"
        "Qui a construit le Colisée ?"
        "What caused the fall of the Roman Empire?"
        "Quand la Seconde Guerre mondiale a-t-elle commencé et terminé ?"
        "What was the significance of the Magna Carta?"
        "Qui était la première personne à marcher sur la lune?"
        "The following questions are examples of questions that should be re-interpreted, as they are not directly historical but can be answered in a historical manner"
        "Tell me a story? In this case you could provide the user a real story from any historical event."
        "Why is pizza cut into triangles? In this case you could explain to the user when and why people started cutting pizzas into triangles, focusing solely on the history behind it."
        "The following questions are examples of questions that should be rejected"
        "Is water wet?"
        "Is god real?"
        f" {profound_mode}"
    )}]

    for entry in chat_history:
        conversation.append(entry)

    conversation.append({"role": "user", "content": user_input})
    
    try:
        response = client.chat.completions.create(
            model="llama3-70b-8192",
            messages=conversation,
            temperature=0.7,
            max_completion_tokens=1024 if profound_state else 512,
            top_p=0.95,
            stream=False,
            stop=None,
        )
        reply = response.choices[0].message.content or "..."
    except Exception as error:
        reply = f"Error: {error}"
    
    chat_history.append({"role": "user", "content": user_input})
    chat_history.append({"role": "assistant", "content": reply})
    return chat_history, chat_history, ""

def toggle_profound_mode(current_state, language_state):
    new_state = not current_state
    if language_state == "english":
        button_label = "Enable Profound Mode"
        if new_state:
            button_label = "Disable Profound Mode"
    else:
        button_label = "Activer le mode approfondi"
        if new_state:
            button_label = "Désactiver le mode approfondi"
    return new_state, button_label

def generate_quiz(subject, num_questions, chat_history, language_state):
    """Generate a history quiz with multiple-choice questions and append it to the chat."""
    try:
        if language_state == "english":
            prompt = f"Generate {num_questions} multiple-choice history questions about {subject}. "
            prompt += "For each question, provide the question text, four options labeled A, B, C, and D. "
            prompt += "At the end of all questions, list the correct answers in the format: 'Correct Answers: X, Y, Z, ...'. "
            prompt += "Ensure that the correct answers are evenly distributed among A, B, C, and D. For example, if there are 12 questions, there should be roughly 3 correct answers for each letter. "
            prompt += "Randomize their order so that they are not in a repeating pattern, but still evenly spread (e.g., B, A, C, C, A, B, D, D, B, A, D, C)."
            prompt += "Reply only in english"

        else: 
            prompt = f"Générez {num_questions} questions à choix multiples sur l'histoire de {subject}. "
            prompt += "Pour chaque question, fournissez l'énoncé de la question, quatre options étiquetées A, B, C et D. "
            prompt += "À la fin de toutes les questions, listez les bonnes réponses au format : 'Réponses correctes : X, Y, Z, ...'. "
            prompt += "Assurez-vous que les bonnes réponses sont réparties uniformément entre A, B, C et D. Par exemple, s'il y a 12 questions, il devrait y avoir environ 3 bonnes réponses pour chaque lettre. "
            prompt += "Mélangez l'ordre de ces réponses pour éviter les modèles répétitifs, tout en maintenant une répartition équilibrée (par ex., B, A, C, C, A, B, D, D, B, A, D, C)."
            prompt += "Répondez uniquement en français."

        response = client.chat.completions.create(
            model="llama3-70b-8192",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.7,
            max_completion_tokens=1024,
            top_p=0.95,
            stream=False,
            stop=None,
        )
        quiz_content = response.choices[0].message.content or "Error generating quiz."
    except Exception as error:
        quiz_content = f"Error: {error}"
    
    chat_history.append({"role": "assistant", "content": quiz_content})
    return chat_history, chat_history

def toggle_language(language):
    """Toggle UI elements between English and French."""
    if language == "english":
        return (
            "french",  
            "## Chatbot d'histoire", 
            "EN",  
            "Entrez votre question ici...",  
            "Envoyer",  
            "Nouvelle Conversation",
            "Sujet du quiz",
            "Nombre de questions",
            "Démarrer le quiz",
            "Guide utilisateur",
            "Activer le mode approfondi",
            "Désactiver le mode approfondi"
        )
    else:
        return (
            "english",
            "## History Chatbot",
            "FR",
            "Enter your question here...",
            "Send",
            "New Conversation",
            "Quiz Subject",
            "Number of Questions",
            "Start Quiz",
            "User Guide",
            "Enable Profound Mode",
            "Disable Profound Mode"
        )

def user_guide(chat_history, language_state):
    userGuide = ''

    if language_state == "english":
        userGuide = "I am a chatbot designed to help you study and learn history.\nPress the EN button to change the language to French.\nEnter a question and click send to see my answer.\nTo change between normal and extended awnsers you can toggle profound mode on and off.\nIf you want to reset the chat click the button right under send.\nYou can also chose to send one of the example promts I've provided so you can see what I'm capable of!\nIf you want to test yourself on a certain topic, enter a quiz subject, chose the number of questions, and click on start quiz...\nEnjoy:)"
    else: 
        userGuide = "Je suis un chatbot conçu pour vous aider à étudier et à apprendre l'histoire.\nAppuyez sur le bouton FR pour changer le langage à l'anglais.\nSaisissez une question et cliquez sur «Envoyer» pour voir ma réponse.\nPour basculer entre les réponses normales et étendues, vous pouvez activer et désactiver le mode aprofondi.\nSi vous souhaitez réinitialiser le chat, cliquez sur le bouton situé juste en dessous de «Envoyer».\nVous pouvez également choisir d'envoyer l'un des exemples d'invites que j'ai fournis pour que vous puissiez voir de quoi je suis capable!\nSi vous souhaitez vous tester sur un sujet spécifique, saisissez un sujet de quiz, choisissez le nombre de questions et cliquez sur «Démarrer le quiz»...\nProfitez-en:)"

    chat_history.append({"role": "assistant", "content": userGuide})
    return chat_history, chat_history

with gr.Blocks() as interface:
    profound_state = gr.State(False) 
    language_state = gr.State("english")  
    examples = [ 
        "How did the Leaning Tower of Pisa start leaning?",
        "Qui a construit le Colisée ?",
        "What caused the fall of the Roman Empire?",
        "Quand la Seconde Guerre mondiale a-t-elle commencé et terminé ?",
        "What was the significance of the Magna Carta?",
        "Qui était la première personne à marcher sur la lune?"
    ]

    title = gr.Markdown("## History Chatbot")
    lang_button = gr.Button("FR")
    help_button = gr.Button("User Guide")
    chatbot = gr.Chatbot(type="messages")
    profound_button = gr.Button("Enable Profound Mode") 
    user_input = gr.Textbox(placeholder="Enter your question here...")
    send_button = gr.Button("Send")
    reset_button = gr.Button("New Conversation")    
    
    examples = gr.Examples(
        examples=examples,
        inputs=user_input
    )

    quiz_subject = gr.Textbox(label="Quiz Subject")
    quiz_num_questions = gr.Number(label="Number of Questions", value=5, precision=0)
    quiz_button = gr.Button("Start Quiz")

    state = gr.State([])

    def update_ui(language, profound_state):
        new_language, new_title, new_button_text, new_placeholder, new_send_label, new_reset_label, quiz_sub, quiz_len, quiz_but, help_but, turn_profound_on, turn_profound_off = toggle_language(language)
        
        profound_label = turn_profound_on
        if profound_state:
            profound_label = turn_profound_off
            
        return (
            new_language, new_title, new_button_text,
            gr.update(placeholder=new_placeholder, value=""),
            new_send_label, new_reset_label,
            gr.update(label=quiz_sub), 
            gr.update(label=quiz_len), 
            gr.update(value=quiz_but),
            gr.update(value=help_but),
            gr.update(value=profound_label)
        )
    
    lang_button.click(
        fn=update_ui,   
        inputs=[language_state,profound_state],
        outputs=[language_state, title, lang_button, user_input, send_button, reset_button, quiz_subject, quiz_num_questions, quiz_button, help_button, profound_button]
    )

    profound_button.click(
        fn=toggle_profound_mode,
        inputs=[profound_state, language_state],
        outputs=[profound_state, profound_button]
    )

    send_button.click(
        fn=generate_reply,
        inputs=[user_input, state, profound_state],
        outputs=[chatbot, state, user_input]
    )

    reset_button.click(lambda: (gr.update(value=[]), []), outputs=[chatbot, state])

    quiz_button.click(
        fn=generate_quiz,
        inputs=[quiz_subject, quiz_num_questions,state,language_state],
        outputs=[chatbot, state]
    )

    help_button.click(
        fn=user_guide,
        inputs=[state,language_state],
        outputs=[chatbot, state]
    )

if __name__ == "__main__":
    interface.launch(share=True)