File size: 6,923 Bytes
d513219
 
9aeb984
4ea6059
df532db
9aeb984
 
 
 
 
 
c784bd4
13c16db
d513219
eefc6b5
 
7847af5
79a8c15
 
 
eefc6b5
d513219
 
 
 
91da114
eefc6b5
4fc8a58
d513219
13c16db
91da114
eefc6b5
8a520bb
eefc6b5
 
8a520bb
 
 
 
eefc6b5
8a520bb
 
 
 
 
eefc6b5
ab5c05f
8a520bb
 
 
eefc6b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2003864
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44d3cff
eefc6b5
44d3cff
 
 
 
 
 
 
 
 
 
 
2003864
ab5c05f
44d3cff
2003864
44d3cff
 
 
eefc6b5
2003864
 
 
 
 
 
 
 
 
 
 
 
eefc6b5
44d3cff
eefc6b5
 
44d3cff
261dc2b
 
44d3cff
261dc2b
 
eefc6b5
 
261dc2b
 
44d3cff
261dc2b
 
eefc6b5
261dc2b
 
44d3cff
26766eb
261dc2b
eefc6b5
 
261dc2b
eefc6b5
261dc2b
8a520bb
eefc6b5
44d3cff
 
 
eefc6b5
 
44d3cff
 
eefc6b5
 
 
 
 
 
ce16d3a
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
import gradio as gr
import openai
import os

# Fetch the API key from Gradio secrets
api_key = os.getenv("OPENAI_API_KEY")

if api_key is None:
    raise ValueError("API key not found. Please set the OPENAI_API_KEY secret.")

openai.api_key = api_key

def generate_exercise_question(topic):
    try:
        messages = [{"role": "system", "content": "You are an AI tutor specialized in teaching Python programming. Your task is to create exercise questions based on the given topic. Provide clear, concise, and informative exercises. Include a specific task for the user to implement, along with example input and expected output."}]
        messages.append({"role": "user", "content": f"Create an exercise question on {topic} with a specific task, example input, and expected output."})

        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            max_tokens=250,
            n=1,
            stop=None,
            temperature=0.7,
        )

        question = response.choices[0].message['content'].strip()
        return question
    except Exception as e:
        return f"Error: {str(e)}"

def check_answer(topic, exercise, user_code):
    try:
        messages = [{"role": "system", "content": "You are an AI tutor specialized in teaching Python programming. Your task is to evaluate the user's code for the given exercise. Provide feedback on correctness and suggest improvements if needed."}]
        messages.append({"role": "user", "content": f"Evaluate this answer for the exercise on {topic}: \nExercise: {exercise}\nUser's code: {user_code}"})

        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            max_tokens=250,
            n=1,
            stop=None,
            temperature=0.7,
        )

        feedback = response.choices[0].message['content'].strip()
        return feedback
    except Exception as e:
        return f"Error: {str(e)}"

def get_solution(topic, exercise):
    try:
        messages = [{"role": "system", "content": "You are an AI tutor specialized in teaching Python programming. Your task is to provide a correct solution for the given exercise."}]
        messages.append({"role": "user", "content": f"Provide the correct solution code for this exercise on {topic}: {exercise}"})

        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            max_tokens=250,
            n=1,
            stop=None,
            temperature=0.7,
        )

        solution = response.choices[0].message['content'].strip()
        return solution
    except Exception as e:
        return f"Error: {str(e)}"

def is_python_topic(topic):
    try:
        messages = [{"role": "system", "content": "You are an AI assistant that determines if a given topic is related to Python programming. Respond with only 'Yes' or 'No'."}]
        messages.append({"role": "user", "content": f"Is '{topic}' a topic related to Python programming?"})

        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            max_tokens=10,
            n=1,
            stop=None,
            temperature=0.3,
        )

        answer = response.choices[0].message['content'].strip().lower()
        return answer == "yes"
    except Exception as e:
        return False

def process_input(user_input, code_input, chat_history, current_topic):
    if not chat_history:
        # First interaction: set topic and generate question
        current_topic = user_input
        question = generate_exercise_question(current_topic)
        chat_history.append((user_input, question))
        return "", chat_history, current_topic, gr.update(visible=True, value="")
    elif code_input.strip():
        # User submitted code
        exercise = chat_history[-1][1]  # Get the last exercise question
        feedback = check_answer(current_topic, exercise, code_input)
        
        if "correct" in feedback.lower():
            response = f"{feedback}\n\nGreat job! Type 'next' for a new question on {current_topic}, or enter a new Python topic to switch subjects."
        else:
            solution = get_solution(current_topic, exercise)
            response = f"{feedback}\n\nHere's the correct solution:\n\n{solution}\n\nType 'next' for a new question on {current_topic}, or enter a new Python topic to switch subjects."
        
        chat_history.append((code_input, response))
        return "", chat_history, current_topic, gr.update(visible=True, value="")
    else:
        # Check if user wants next question or new topic
        if user_input.lower() == "next":
            question = generate_exercise_question(current_topic)
            chat_history.append((user_input, question))
        elif is_python_topic(user_input):
            current_topic = user_input
            question = generate_exercise_question(current_topic)
            chat_history.append((user_input, f"Switching to new topic: {current_topic}\n\n{question}"))
        else:
            chat_history.append((user_input, f"'{user_input}' doesn't seem to be a Python topic. Please enter a valid Python topic or 'next' for a new question on {current_topic}."))
        
        return "", chat_history, current_topic, gr.update(visible=True, value="")

def undo(chat_history, current_topic):
    if chat_history:
        chat_history.pop()
    return chat_history, current_topic, gr.update(visible=bool(chat_history))

def clear():
    return [], "", gr.update(visible=False, value="")

with gr.Blocks() as demo:
    gr.Markdown("# Python Practice Bot")
    gr.Markdown("Learn Python through exercises. Start by entering a topic you want to practice.")

    chatbot = gr.Chatbot(label="Python Tutor")
    current_topic = gr.State("")

    with gr.Row():
        with gr.Column(scale=3):
            user_input = gr.Textbox(
                show_label=False,
                placeholder="Enter a Python topic, type 'next' for a new question, or submit your code...",
                lines=1
            )
            code_input = gr.Code(language="python", label="Your Solution", visible=False)
        with gr.Column(scale=1):
            submit_button = gr.Button("Submit")
            undo_button = gr.Button("Undo")
            clear_button = gr.Button("Clear")

    submit_button.click(
        process_input,
        [user_input, code_input, chatbot, current_topic],
        [user_input, chatbot, current_topic, code_input]
    )

    undo_button.click(undo, [chatbot, current_topic], [chatbot, current_topic, code_input])
    clear_button.click(clear, None, [chatbot, current_topic, code_input])

    gr.Examples(
        examples=[["lists"], ["decorators"], ["dictionaries"], ["file handling"], ["classes and objects"]],
        inputs=[user_input]
    )

demo.launch()