File size: 3,226 Bytes
969d7ed
 
 
 
 
 
fbd6b13
969d7ed
 
5415e57
6c5b6cf
 
 
 
 
 
fbd6b13
969d7ed
5415e57
6c5b6cf
 
 
 
 
 
969d7ed
 
3d7bc32
 
5415e57
969d7ed
 
 
 
 
 
 
 
 
 
 
 
 
 
3d7bc32
969d7ed
3d7bc32
 
969d7ed
 
3d7bc32
 
 
 
 
 
969d7ed
 
 
 
3d7bc32
969d7ed
 
6c5b6cf
5415e57
3d7bc32
 
969d7ed
 
 
 
f48e069
969d7ed
5415e57
969d7ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5415e57
3d7bc32
 
969d7ed
 
 
5415e57
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
import gradio as gr
import sys
import json
from io import StringIO
from urllib import parse

from tutor import Tutor


def submit_chat(tutor_ctx, message):
    try:
        tutor = Tutor(context=tutor_ctx)
        for history in tutor.chat(message):
            yield [tutor.serialize(), history, None]
    except Exception as error:
        raise gr.Error(str(error))
    

def submit_code(tutor_ctx, editor, output):
    try:
        tutor = Tutor(context=tutor_ctx)
        for history in tutor.code(editor, output):
            yield [tutor.serialize(), history, None]
    except Exception as error:
        raise gr.Error(str(error))


def init_tutor(instructions, starter_code, age, name):
    tutor = Tutor(instructions, starter_code, age, name)
    return [tutor.serialize(), tutor._memory_as_history()]


def run_code(code):
    buffer = StringIO()
    sys.stdout = buffer
    try:
        exec(code)
        return buffer.getvalue()
    except Exception as e:
        print(e)
        return buffer.getvalue()
    finally:
        sys.stdout = sys.__stdout__

def _query_param(request: gr.Request, param: str, default: str = None) -> str:
    try:
        return parse.parse_qs(parse.urlparse(request.headers["referer"]).query)[
            param
        ][0]
    except:
        return default

def load_level(request: gr.Request):
    level = _query_param(request, "level", "1")
    age = _query_param(request, "age", "12")
    name = _query_param(request, "name", "")
    with open(f"levels/{level}/metadata.json", "r") as f:
        data = json.load(f)
        instructions = open(f"levels/{level}/{data['instructions']}", "r").read()
        starter_code = open(f"levels/{level}/{data['starter_code']}", "r").read()
        return [instructions, starter_code, age, name]


with gr.Blocks(title="CS Tutor") as demo:
    tutor_ctx = gr.State()
    age = gr.State()
    name = gr.State()
    with gr.Row():
        instruction_panel = gr.Markdown()
    with gr.Row():
        with gr.Column(scale=1):
            chatbot = gr.Chatbot(label="AI Tutor", value=[])
            msg = gr.Textbox(show_label=False, placeholder="Type your message here...")
            msg.submit(submit_chat, [tutor_ctx, msg], [tutor_ctx, chatbot, msg])
        with gr.Column(scale=2):
            editor = gr.Code(
                value="Loading...",
                language="python",
                interactive=True,
                show_label=True,
                label="Code Editor",
                lines=15,
            )
            output = gr.Code(
                value="""Click "Run" to run your code.""",
                language="python",
                interactive=False,
                show_label=True,
                label="Output",
            )
            with gr.Row():
                run = gr.Button("Run")
                run.click(
                    run_code, editor, output, queue=False, scroll_to_output=True
                ).then(submit_code, [tutor_ctx, editor, output], [tutor_ctx, chatbot])
    demo.load(load_level, None, [instruction_panel, editor, age, name], queue=False).then(
        init_tutor, [instruction_panel, editor, age, name], [tutor_ctx, chatbot]
    )

demo.queue()
demo.launch()