Vipitis commited on
Commit
4e064ff
1 Parent(s): fab61bd

fixed dropdown, imporve function generation

Browse files
Files changed (1) hide show
  1. app.py +25 -15
app.py CHANGED
@@ -142,11 +142,13 @@ If I find an efficient way, the shaders might run in real time and be interactiv
142
 
143
  ## TODO:
144
  - [x] use embedded Shadertoy for reference/attribution (done, but some errors)
145
- - [] working render implementation on CPU only space (use the browser for WebGPU?, maybe via an iFrame too?)
146
- - [~] generate variations of return statements [ShaderEval task1](https://huggingface.co/spaces/Vipitis/ShaderEval) (missing all of the generation parameters)
147
  - [] generation history stating which function and orig/generated returns. (use State ??). do it as comments in the code?
148
- - [x?] generate whole functions (only works once)
 
149
  - [] generate whole shaders (via prompts?)
 
150
  """
151
  passes_dataset = datasets.load_dataset("Vipitis/Shadertoys")
152
  single_passes = passes_dataset.filter(lambda x: not x["has_inputs"] and x["num_passes"] == 1) #could also include shaders with no extra functions.
@@ -184,11 +186,11 @@ def grab_sample(sample_idx):
184
  sample_auhtor = sample_pass["author"]
185
  source_iframe = construct_embed(sample_source)
186
  print(f"{source_iframe=}")
187
- sample_funcs = _parse_functions(sample_code)
188
- funcs = _parse_functions(sample_code)
189
- func_identifiers = [(idx,n.child_by_field_name("declarator").text.decode()) for idx, n in enumerate(funcs)]
190
- print(f"updating drop down to:{func_identifiers}")
191
- return sample_pass, sample_code, source_iframe, funcs, gr.Dropdown.update(choices=func_identifiers) #, sample_title, sample_auhtor
192
 
193
 
194
  def _parse_functions(in_code):
@@ -280,7 +282,7 @@ def alter_body(old_code, func_id, funcs_list, pipeline=PIPE):
280
  str: The altered code.
281
  """
282
  print(f"{func_id=}")
283
- func_id = int(func_id.split(",")[0]) #undo their string casting?
284
  func_node = funcs_list[func_id]
285
  print(f"using for generation: {func_node=}")
286
 
@@ -291,15 +293,22 @@ def alter_body(old_code, func_id, funcs_list, pipeline=PIPE):
291
  pipeline = _make_pipeline("Vipitis/santacoder-finetuned-Shadertoys-fine")
292
 
293
  func_start_idx = _line_chr2char(old_code, func_node.start_point[0], func_node.start_point[1])
 
294
  body_node = func_node.child_by_field_name("body")
295
  body_start_idx = _line_chr2char(old_code, body_node.start_point[0], body_node.start_point[1])
296
  body_end_idx = _line_chr2char(old_code, body_node.end_point[0], body_node.end_point[1])
297
  print(f"{old_code[body_start_idx:body_end_idx]=}")
298
- model_context = old_code[:body_start_idx]
299
- generation = pipeline(model_context, max_new_tokens=(body_end_idx - body_start_idx)*2, return_full_text=False)[0]["generated_text"]
 
 
 
300
  print(f"{generation=}")
301
- first_gened_func = _parse_functions(old_code[func_start_idx:body_start_idx] + generation)[0] # truncate generation to a single function?
 
 
302
  # strip just the body.
 
303
  generated_body = first_gened_func.child_by_field_name("body").text.decode()
304
  print(f"{generated_body=}")
305
  altered_code = old_code[:body_start_idx] + generated_body + old_code[body_end_idx:]
@@ -310,11 +319,11 @@ def add_history(func_id, orig_rtn, gened_rtn, history):
310
  history[func_id] = (orig_rtn, gened_rtn)
311
  return history, history
312
 
313
- def list_dropdown(in_code):
314
  funcs = _parse_functions(in_code)
315
 
316
  # print(f"updating drop down to:{func_identifiers=}")
317
- func_identifiers = [(idx,n.child_by_field_name("declarator").text.decode()) for idx, n in enumerate(funcs)]
318
  # funcs = [n for n in funcs] #wrapped as set to avoid json issues?
319
  print(f"updating drop down to:{func_identifiers}")
320
  return funcs, gr.Dropdown.update(choices=func_identifiers)
@@ -347,12 +356,13 @@ with gr.Blocks() as site:
347
  # history_table = gr.JSON()
348
 
349
  model_cp.submit(fn=_make_pipeline, inputs=[model_cp], outputs=[pipe])
350
- sample_idx.release(fn=grab_sample, inputs=[sample_idx], outputs=[sample_pass, sample_code, source_embed, funcs, func_dropdown])
351
  # sample_idx.release(fn=list_dropdown, inputs=[sample_code], outputs=[funcs, func_dropdown]) #use multiple event handles to call other functions! seems to not work really well. always messes up
352
  gen_return_button.click(fn=alter_return, inputs=[sample_code, time_slider, pipe], outputs=[sample_code])
353
  gen_func_button.click(fn=alter_body, inputs=[sample_code, func_dropdown, funcs, pipe], outputs=[sample_code])
354
  # run_button.click(fn=add_history, inputs=[time_slider, sample_pass, sample_code, hist_state], outputs=[history_table, hist_state])
355
  # sample_idx.release(fn=construct_embed, inputs=[sample_idx], outputs=[source_embed]) #twice to make have different outputs?
 
356
  time_slider.release(fn=lambda code, time: asyncio.run(get_image(code, time)), inputs=[sample_code, time_slider], outputs=rendered_frame)
357
  render_button.click(fn=lambda code: asyncio.run(get_image(code)), inputs=[sample_code], outputs=rendered_frame)
358
  # run_button.click(fn=print, inputs=[model_cp, sample_idx], outputs=output)
 
142
 
143
  ## TODO:
144
  - [x] use embedded Shadertoy for reference/attribution (done, but some errors)
145
+ - [] working render implementation on CPU only space (use the browser for WebGPU?, maybe via an iFrame too?) freespace uses lavapipe which works on really simple stuff.
146
+ - [~] generate variations of return statements [ShaderEval task1](https://huggingface.co/spaces/Vipitis/ShaderEval) (needs to be reworked using the other parts)
147
  - [] generation history stating which function and orig/generated returns. (use State ??). do it as comments in the code?
148
+ - [x] generate whole functions (seems to work quite well)
149
+ - [] display errros/issues to the user
150
  - [] generate whole shaders (via prompts?)
151
+ - [] accordion with generation parameters (as pipeline_kwargs?)
152
  """
153
  passes_dataset = datasets.load_dataset("Vipitis/Shadertoys")
154
  single_passes = passes_dataset.filter(lambda x: not x["has_inputs"] and x["num_passes"] == 1) #could also include shaders with no extra functions.
 
186
  sample_auhtor = sample_pass["author"]
187
  source_iframe = construct_embed(sample_source)
188
  print(f"{source_iframe=}")
189
+ # sample_funcs = _parse_functions(sample_code)
190
+ # funcs = _parse_functions(sample_code)
191
+ # func_identifiers = [f"{idx:2d}: {n.child_by_field_name('declarator').text.decode()}" for idx, n in enumerate(funcs)]
192
+ # print(f"updating drop down to:{func_identifiers}")
193
+ return sample_pass, sample_code, source_iframe, funcs#, gr.Dropdown.update(choices=func_identifiers) #, sample_title, sample_auhtor
194
 
195
 
196
  def _parse_functions(in_code):
 
282
  str: The altered code.
283
  """
284
  print(f"{func_id=}")
285
+ func_id = int(func_id.split(":")[0].strip()) #undo their string casting?
286
  func_node = funcs_list[func_id]
287
  print(f"using for generation: {func_node=}")
288
 
 
293
  pipeline = _make_pipeline("Vipitis/santacoder-finetuned-Shadertoys-fine")
294
 
295
  func_start_idx = _line_chr2char(old_code, func_node.start_point[0], func_node.start_point[1])
296
+ identifier_str = func_node.child_by_field_name("type").text.decode() + " " + func_node.child_by_field_name("declarator").text.decode()
297
  body_node = func_node.child_by_field_name("body")
298
  body_start_idx = _line_chr2char(old_code, body_node.start_point[0], body_node.start_point[1])
299
  body_end_idx = _line_chr2char(old_code, body_node.end_point[0], body_node.end_point[1])
300
  print(f"{old_code[body_start_idx:body_end_idx]=}")
301
+ model_context = identifier_str # just this
302
+ num_new_tokens = (body_end_idx - body_start_idx) + 10 #TODO: approximation, we do have early stopping? maybe also use a number instead?
303
+
304
+ print(f"generating up to {num_new_tokens} after {model_context!r}")
305
+ generation = pipeline(model_context, max_new_tokens=num_new_tokens, return_full_text=False)[0]["generated_text"]
306
  print(f"{generation=}")
307
+ id_with_generation = identifier_str + generation
308
+ print(f"{id_with_generation=}")
309
+ first_gened_func = _parse_functions(id_with_generation)[0] # truncate generation to a single function?
310
  # strip just the body.
311
+ print(f"{first_gened_func=}")
312
  generated_body = first_gened_func.child_by_field_name("body").text.decode()
313
  print(f"{generated_body=}")
314
  altered_code = old_code[:body_start_idx] + generated_body + old_code[body_end_idx:]
 
319
  history[func_id] = (orig_rtn, gened_rtn)
320
  return history, history
321
 
322
+ def list_dropdown(in_code): #only used for auto update, not on sample pick?
323
  funcs = _parse_functions(in_code)
324
 
325
  # print(f"updating drop down to:{func_identifiers=}")
326
+ func_identifiers = [f"{idx:2d}: {n.child_by_field_name('declarator').text.decode()}" for idx, n in enumerate(funcs)]
327
  # funcs = [n for n in funcs] #wrapped as set to avoid json issues?
328
  print(f"updating drop down to:{func_identifiers}")
329
  return funcs, gr.Dropdown.update(choices=func_identifiers)
 
356
  # history_table = gr.JSON()
357
 
358
  model_cp.submit(fn=_make_pipeline, inputs=[model_cp], outputs=[pipe])
359
+ sample_idx.release(fn=grab_sample, inputs=[sample_idx], outputs=[sample_pass, sample_code, source_embed])
360
  # sample_idx.release(fn=list_dropdown, inputs=[sample_code], outputs=[funcs, func_dropdown]) #use multiple event handles to call other functions! seems to not work really well. always messes up
361
  gen_return_button.click(fn=alter_return, inputs=[sample_code, time_slider, pipe], outputs=[sample_code])
362
  gen_func_button.click(fn=alter_body, inputs=[sample_code, func_dropdown, funcs, pipe], outputs=[sample_code])
363
  # run_button.click(fn=add_history, inputs=[time_slider, sample_pass, sample_code, hist_state], outputs=[history_table, hist_state])
364
  # sample_idx.release(fn=construct_embed, inputs=[sample_idx], outputs=[source_embed]) #twice to make have different outputs?
365
+ sample_code.change(fn=list_dropdown, inputs=[sample_code], outputs=[funcs, func_dropdown]) # to update this after generation, so spans aren't messed up
366
  time_slider.release(fn=lambda code, time: asyncio.run(get_image(code, time)), inputs=[sample_code, time_slider], outputs=rendered_frame)
367
  render_button.click(fn=lambda code: asyncio.run(get_image(code)), inputs=[sample_code], outputs=rendered_frame)
368
  # run_button.click(fn=print, inputs=[model_cp, sample_idx], outputs=output)