szili2011 commited on
Commit
6686e9d
1 Parent(s): 32f06b9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -0
app.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer
4
+ from scratch3 import Project
5
+
6
+ # Load the LLaMa model and tokenizer
7
+ model_name = "TheBloke/LLaMa-7B-GGML"
8
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
9
+ model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
10
+
11
+ # Define extended Scratch blocks
12
+ scratch_blocks = {
13
+ "motion": [
14
+ {"name": "move", "parameters": {"steps": "number"}},
15
+ {"name": "turn", "parameters": {"angle": "number"}},
16
+ {"name": "go to", "parameters": {"x": "number", "y": "number"}},
17
+ {"name": "point in direction", "parameters": {"direction": "number"}}
18
+ ],
19
+ "sound": [
20
+ {"name": "play sound", "parameters": {"sound": "string"}},
21
+ {"name": "stop all sounds", "parameters": {}}
22
+ ],
23
+ "event": [
24
+ {"name": "when green flag clicked", "parameters": {}},
25
+ {"name": "when this sprite clicked", "parameters": {}}
26
+ ],
27
+ "control": [
28
+ {"name": "wait", "parameters": {"seconds": "number"}},
29
+ {"name": "repeat", "parameters": {"times": "number"}},
30
+ {"name": "if then", "parameters": {"condition": "string"}},
31
+ ],
32
+ "variables": [
33
+ {"name": "set variable", "parameters": {"variable": "string", "value": "number"}},
34
+ {"name": "change variable", "parameters": {"variable": "string", "value": "number"}},
35
+ ],
36
+ "looks": [
37
+ {"name": "say", "parameters": {"message": "string"}},
38
+ {"name": "think", "parameters": {"message": "string"}},
39
+ {"name": "show", "parameters": {}},
40
+ {"name": "hide", "parameters": {}}
41
+ ],
42
+ "drawing": [
43
+ {"name": "draw line", "parameters": {"x1": "number", "y1": "number", "x2": "number", "y2": "number"}},
44
+ {"name": "draw circle", "parameters": {"x": "number", "y": "number", "radius": "number"}},
45
+ {"name": "draw rectangle", "parameters": {"x": "number", "y": "number", "width": "number", "height": "number"}},
46
+ ]
47
+ }
48
+
49
+ def generate_script(prompt):
50
+ """
51
+ Generate a Scratch script based on the provided prompt using the AI model.
52
+ """
53
+ inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
54
+ with torch.no_grad():
55
+ outputs = model.generate(inputs["input_ids"], max_length=300, num_return_sequences=1)
56
+
57
+ generated_script = tokenizer.decode(outputs[0], skip_special_tokens=True)
58
+ return generated_script
59
+
60
+ def parse_generated_script(generated_script):
61
+ """
62
+ Parse the generated script into instructions.
63
+ """
64
+ instructions = []
65
+ for line in generated_script.split('.'):
66
+ line = line.strip()
67
+ if line:
68
+ instructions.append(line)
69
+ return instructions
70
+
71
+ def create_scratch_project(title, sprites, sounds, custom_prompt):
72
+ """
73
+ Create a Scratch project based on user input and generated script.
74
+ """
75
+ # Combine title and custom prompt for better context
76
+ prompt = f"Create a Scratch project titled '{title}' featuring sprites {sprites} with sounds {sounds}. " \
77
+ f"Additional details: {custom_prompt}"
78
+ generated_script = generate_script(prompt)
79
+
80
+ # Parse the generated script into instructions
81
+ instructions = parse_generated_script(generated_script)
82
+
83
+ # Create a new Scratch project
84
+ project = Project()
85
+
86
+ # Add sprites
87
+ sprite_list = [sprite.strip() for sprite in sprites.split(',')]
88
+ for sprite in sprite_list:
89
+ sprite_block = {
90
+ "objName": sprite,
91
+ "skin": 1,
92
+ "x": 0,
93
+ "y": 0,
94
+ "direction": 90,
95
+ "visible": True,
96
+ "size": 100
97
+ }
98
+ project.sprites.append(sprite_block)
99
+
100
+ # Add sounds if provided
101
+ for sound in sounds.split(','):
102
+ sound = sound.strip()
103
+ if sound:
104
+ sound_block = {
105
+ "name": sound,
106
+ "path": f"sounds/{sound}.wav"
107
+ }
108
+ project.sounds.append(sound_block)
109
+
110
+ # Map parsed instructions to Scratch blocks
111
+ for instruction in instructions:
112
+ if "move" in instruction:
113
+ steps = extract_number(instruction)
114
+ project.add_motion_block({"name": "move", "parameters": {"steps": steps}})
115
+ elif "turn" in instruction:
116
+ angle = extract_number(instruction)
117
+ project.add_motion_block({"name": "turn", "parameters": {"angle": angle}})
118
+ elif "play sound" in instruction:
119
+ project.add_sound_block({"name": "play sound", "parameters": {"sound": sounds.split(',')[0].strip()}})
120
+ elif "when green flag clicked" in instruction:
121
+ project.add_event_block({"name": "when green flag clicked"})
122
+ elif "repeat" in instruction:
123
+ times = extract_number(instruction)
124
+ project.add_control_block({"name": "repeat", "parameters": {"times": times}})
125
+ elif "say" in instruction:
126
+ message = extract_message(instruction)
127
+ project.add_looks_block({"name": "say", "parameters": {"message": message}})
128
+ elif "draw line" in instruction:
129
+ x1, y1, x2, y2 = extract_drawing_parameters(instruction)
130
+ project.add_drawing_block({"name": "draw line", "parameters": {"x1": x1, "y1": y1, "x2": x2, "y2": y2}})
131
+ elif "draw circle" in instruction:
132
+ x, y, radius = extract_circle_parameters(instruction)
133
+ project.add_drawing_block({"name": "draw circle", "parameters": {"x": x, "y": y, "radius": radius}})
134
+ elif "draw rectangle" in instruction:
135
+ x, y, width, height = extract_rectangle_parameters(instruction)
136
+ project.add_drawing_block({"name": "draw rectangle", "parameters": {"x": x, "y": y, "width": width, "height": height}})
137
+ elif "remove sprite" in instruction:
138
+ sprite_name = extract_sprite_name(instruction)
139
+ project.remove_sprite(sprite_name)
140
+ elif "rename sprite" in instruction:
141
+ old_name, new_name = extract_rename_sprite_parameters(instruction)
142
+ project.rename_sprite(old_name, new_name)
143
+
144
+ # Save the project as an .sb3 file
145
+ sb3_file_path = f"{title}.sb3"
146
+ with open(sb3_file_path, "wb") as f:
147
+ f.write(project.export())
148
+
149
+ return sb3_file_path
150
+
151
+ def extract_number(instruction):
152
+ """
153
+ Extract a number from the instruction string.
154
+ """
155
+ import re
156
+ match = re.search(r'\d+', instruction)
157
+ return int(match.group(0)) if match else 0
158
+
159
+ def extract_message(instruction):
160
+ """
161
+ Extract a message from the instruction string.
162
+ """
163
+ return instruction.split("say")[-1].strip().strip('"')
164
+
165
+ def extract_drawing_parameters(instruction):
166
+ """
167
+ Extract parameters for drawing a line from the instruction string.
168
+ """
169
+ numbers = list(map(int, re.findall(r'\d+', instruction)))
170
+ return numbers
171
+
172
+ def extract_circle_parameters(instruction):
173
+ """
174
+ Extract parameters for drawing a circle from the instruction string.
175
+ """
176
+ numbers = list(map(int, re.findall(r'\d+', instruction)))
177
+ return numbers
178
+
179
+ def extract_rectangle_parameters(instruction):
180
+ """
181
+ Extract parameters for drawing a rectangle from the instruction string.
182
+ """
183
+ numbers = list(map(int, re.findall(r'\d+', instruction)))
184
+ return numbers
185
+
186
+ def extract_sprite_name(instruction):
187
+ """
188
+ Extract the sprite name from the instruction string for removal.
189
+ """
190
+ return instruction.split("remove sprite")[-1].strip()
191
+
192
+ def extract_rename_sprite_parameters(instruction):
193
+ """
194
+ Extract old and new names for renaming a sprite from the instruction string.
195
+ """
196
+ parts = instruction.split("rename sprite")[-1].strip().split("to")
197
+ old_name = parts[0].strip()
198
+ new_name = parts[1].strip() if len(parts) > 1 else None
199
+ return old_name, new_name
200
+
201
+ # Create Gradio interface
202
+ iface = gr.Interface(
203
+ fn=create_scratch_project,
204
+ inputs=[
205
+ gr.Textbox(label="Project Title"),
206
+ gr.Textbox(label="Sprite Names (comma separated)"),
207
+ gr.Textbox(label="Sound Names (comma separated)"),
208
+ gr.Textbox(label="Custom Prompt (optional)"),
209
+ ],
210
+ outputs=gr.File(label="Download Your Scratch Project (.sb3)"),
211
+ title="Scratch Project Generator",
212
+ description="Create a Scratch project using AI. Provide a title, sprites, sounds, and a custom prompt."
213
+ )
214
+
215
+ # Launch the Gradio app
216
+ iface.launch()