lgaleana commited on
Commit
0905f7c
1 Parent(s): 754049c

Introduce state and update adding/removing

Browse files
Files changed (3) hide show
  1. actions.py +16 -35
  2. app.py +10 -33
  3. components.py +35 -26
actions.py CHANGED
@@ -3,29 +3,7 @@ from typing import List
3
 
4
  import gradio as gr
5
 
6
- from components import all_tasks, Input, MAX_INPUTS, MAX_TASKS, Task
7
-
8
-
9
- def add_input(*visibility):
10
- for i, visible in enumerate(visibility, 1):
11
- if not bool(visible):
12
- return (
13
- [gr.Textbox.update(visible=True)] * i
14
- + [gr.Textbox.update(visible=False, value="")] * (MAX_INPUTS - i)
15
- + [1] * i
16
- + [0] * (MAX_INPUTS - i)
17
- )
18
-
19
-
20
- def remove_input(*visibility):
21
- for i, visible in reversed(list(enumerate(visibility, 1))):
22
- if bool(visible):
23
- return (
24
- [gr.Textbox.update(visible=True)] * (i - 1)
25
- + [gr.Textbox.update(visible=False, value="")] * (MAX_INPUTS - i + 1)
26
- + [1] * (i - 1)
27
- + [0] * (MAX_INPUTS - i + 1)
28
- )
29
 
30
 
31
  def _is_task_row_fully_invisible(row: List[int]) -> bool:
@@ -37,9 +15,9 @@ def _is_task_row_fully_invisible(row: List[int]) -> bool:
37
 
38
  def add_task(index, *visibility):
39
  visibility = list(visibility)
40
- n_avail_tasks = len(Task.AVAILABLE_TASKS)
41
 
42
- for i in range(MAX_TASKS):
43
  start_row = i * n_avail_tasks
44
  is_row_invisible = _is_task_row_fully_invisible(
45
  visibility[start_row : start_row + n_avail_tasks]
@@ -54,13 +32,14 @@ def add_task(index, *visibility):
54
  + [1]
55
  + [gr.Number.update()] * (len(visibility) - unchanged_up_to - 1)
56
  )
 
57
 
58
 
59
  def remove_task(*visibility):
60
  visibility = list(visibility)
61
- n_avail_tasks = len(Task.AVAILABLE_TASKS)
62
 
63
- for i in range(MAX_TASKS):
64
  start_row = i * n_avail_tasks
65
  is_row_invisible = _is_task_row_fully_invisible(
66
  visibility[start_row : start_row + n_avail_tasks]
@@ -73,6 +52,12 @@ def remove_task(*visibility):
73
  + [gr.Number.update()] * unchanged_up_to
74
  + [0] * (len(visibility) - unchanged_up_to)
75
  )
 
 
 
 
 
 
76
 
77
 
78
  def execute_task(id_: int, prev_error_value, n_task_inputs, *vars_in_scope):
@@ -85,16 +70,12 @@ def execute_task(id_: int, prev_error_value, n_task_inputs, *vars_in_scope):
85
  """
86
  n_task_inputs = int(n_task_inputs)
87
  task_inputs = vars_in_scope[:n_task_inputs]
88
- input_vars = vars_in_scope[n_task_inputs:MAX_INPUTS]
89
- task_outputs = vars_in_scope[n_task_inputs + MAX_INPUTS :]
90
  non_empty_task_inputs = [ti for ti in task_inputs if ti]
91
 
92
  # Put all defined variables into a dict, with names (except task inputs)
93
- vars = {
94
- f"{Input.VNAME}{i}": input_ for i, input_ in enumerate(input_vars) if input_
95
- }
96
  vars.update(
97
- {f"{Task.VNAME}{i}": task_output for i, task_output in enumerate(task_outputs)}
98
  )
99
  # Get all variables referenced within the task inputs
100
  prompt_vars = {v for ti in non_empty_task_inputs for v in re.findall("{(.*?)}", ti)}
@@ -118,9 +99,9 @@ def execute_task(id_: int, prev_error_value, n_task_inputs, *vars_in_scope):
118
  if non_empty_task_inputs:
119
  # Execute the task logic
120
  return (
121
- all_tasks[id_].execute(*non_empty_task_inputs, vars),
122
  error_update,
123
  )
124
  else:
125
- # There is no actionf or this task.
126
  return None, error_update
 
3
 
4
  import gradio as gr
5
 
6
+ from components import Input, State as s, Task
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
 
9
  def _is_task_row_fully_invisible(row: List[int]) -> bool:
 
15
 
16
  def add_task(index, *visibility):
17
  visibility = list(visibility)
18
+ n_avail_tasks = len(Task.available_tasks)
19
 
20
+ for i in range(s.MAX_TASKS):
21
  start_row = i * n_avail_tasks
22
  is_row_invisible = _is_task_row_fully_invisible(
23
  visibility[start_row : start_row + n_avail_tasks]
 
32
  + [1]
33
  + [gr.Number.update()] * (len(visibility) - unchanged_up_to - 1)
34
  )
35
+ return [gr.Box.update()] * len(visibility) + [gr.Number.update()] * len(visibility)
36
 
37
 
38
  def remove_task(*visibility):
39
  visibility = list(visibility)
40
+ n_avail_tasks = len(Task.available_tasks)
41
 
42
+ for i in range(s.MAX_TASKS):
43
  start_row = i * n_avail_tasks
44
  is_row_invisible = _is_task_row_fully_invisible(
45
  visibility[start_row : start_row + n_avail_tasks]
 
52
  + [gr.Number.update()] * unchanged_up_to
53
  + [0] * (len(visibility) - unchanged_up_to)
54
  )
55
+ return (
56
+ [gr.Box.update()] * (len(visibility) - n_avail_tasks)
57
+ + [gr.Box.update(visible=False)] * n_avail_tasks
58
+ + [gr.Number.update()] * (len(visibility) - n_avail_tasks)
59
+ + [0] * (len(visibility) - n_avail_tasks)
60
+ )
61
 
62
 
63
  def execute_task(id_: int, prev_error_value, n_task_inputs, *vars_in_scope):
 
70
  """
71
  n_task_inputs = int(n_task_inputs)
72
  task_inputs = vars_in_scope[:n_task_inputs]
73
+ task_outputs = vars_in_scope[n_task_inputs:]
 
74
  non_empty_task_inputs = [ti for ti in task_inputs if ti]
75
 
76
  # Put all defined variables into a dict, with names (except task inputs)
 
 
 
77
  vars.update(
78
+ {f"{Task.vname}{i}": task_output for i, task_output in enumerate(task_outputs)}
79
  )
80
  # Get all variables referenced within the task inputs
81
  prompt_vars = {v for ti in non_empty_task_inputs for v in re.findall("{(.*?)}", ti)}
 
99
  if non_empty_task_inputs:
100
  # Execute the task logic
101
  return (
102
+ s.all_tasks[id_].execute(*non_empty_task_inputs, vars),
103
  error_update,
104
  )
105
  else:
106
+ # There is no actionf for this task.
107
  return None, error_update
app.py CHANGED
@@ -1,13 +1,11 @@
1
  import gradio as gr
2
 
3
  import actions as a
4
- from components import AITask, all_inputs, all_tasks, VisitURL
5
 
6
 
7
  def _get_all_vars_up_to(to: int):
8
- return [in_.output for in_ in all_inputs.values()] + [
9
- t.output for i, t in all_tasks.items() if i < to
10
- ]
11
 
12
 
13
  with gr.Blocks() as demo:
@@ -25,16 +23,11 @@ with gr.Blocks() as demo:
25
  <br>Example prompt: "Translate the following text into spanish and add {v0} more sentences: {t0}".
26
  """
27
  )
28
- for i in all_inputs.values():
29
- i.render()
30
- with gr.Row():
31
- add_input_btn = gr.Button("Add input variable")
32
- remove_input_btn = gr.Button("Remove input variable")
33
- for t in all_tasks.values():
34
  t.render()
35
  task_picker = gr.Dropdown(
36
- [AITask.NAME, VisitURL.NAME],
37
- value=AITask.NAME,
38
  label="Pick a new Task",
39
  type="index",
40
  )
@@ -45,38 +38,22 @@ with gr.Blocks() as demo:
45
  execute_btn = gr.Button("Execute")
46
 
47
  # Edit layout
48
- add_input_btn.click(
49
- a.add_input,
50
- inputs=[i.visible for i in all_inputs.values()],
51
- outputs=[i.gr_component for i in all_inputs.values()] # type: ignore
52
- + [i.visible for i in all_inputs.values()],
53
- )
54
- remove_input_btn.click(
55
- a.remove_input,
56
- inputs=[i.visible for i in all_inputs.values()],
57
- outputs=[i.gr_component for i in all_inputs.values()] # type: ignore
58
- + [i.visible for i in all_inputs.values()],
59
- )
60
  add_task_btn.click(
61
  a.add_task,
62
- inputs=[task_picker] + [v for t in all_tasks.values() for v in t.visibilities], # type: ignore
63
- outputs=[c for t in all_tasks.values() for c in t.gr_components] # type: ignore
64
- + [v for t in all_tasks.values() for v in t.visibilities],
65
  )
66
  remove_task_btn.click(
67
- a.remove_task,
68
- inputs=[v for t in all_tasks.values() for v in t.visibilities], # type: ignore
69
- outputs=[c for t in all_tasks.values() for c in t.gr_components] # type: ignore
70
- + [v for t in all_tasks.values() for v in t.visibilities],
71
  )
72
 
73
  # Sequential execution
74
  execution_event = execute_btn.click(
75
- lambda _: gr.HighlightedText.update(value=None, visible=False),
76
  inputs=[],
77
  outputs=[error_message],
78
  )
79
- for i, task in all_tasks.items():
80
  execution_event = execution_event.then(
81
  a.execute_task,
82
  inputs=[task.component_id, error_message, task.n_inputs]
 
1
  import gradio as gr
2
 
3
  import actions as a
4
+ from components import AITask, State as s, VisitURL
5
 
6
 
7
  def _get_all_vars_up_to(to: int):
8
+ return [t.output for i, t in s.all_tasks.items() if i < to]
 
 
9
 
10
 
11
  with gr.Blocks() as demo:
 
23
  <br>Example prompt: "Translate the following text into spanish and add {v0} more sentences: {t0}".
24
  """
25
  )
26
+ for t in s.all_tasks.values():
 
 
 
 
 
27
  t.render()
28
  task_picker = gr.Dropdown(
29
+ [AITask.name, VisitURL.name],
30
+ value=AITask.name,
31
  label="Pick a new Task",
32
  type="index",
33
  )
 
38
  execute_btn = gr.Button("Execute")
39
 
40
  # Edit layout
 
 
 
 
 
 
 
 
 
 
 
 
41
  add_task_btn.click(
42
  a.add_task,
43
+ inputs=[task_picker] + s.task_visibilities(), # type: ignore
44
+ outputs=s.task_rows(),
 
45
  )
46
  remove_task_btn.click(
47
+ a.remove_task, inputs=s.task_visibilities(), outputs=s.task_rows()
 
 
 
48
  )
49
 
50
  # Sequential execution
51
  execution_event = execute_btn.click(
52
+ lambda: gr.HighlightedText.update(value=None, visible=False),
53
  inputs=[],
54
  outputs=[error_message],
55
  )
56
+ for i, task in s.all_tasks.items():
57
  execution_event = execution_event.then(
58
  a.execute_task,
59
  inputs=[task.component_id, error_message, task.n_inputs]
components.py CHANGED
@@ -1,5 +1,5 @@
1
  from abc import ABC, abstractmethod
2
- from typing import Dict, List, Optional
3
 
4
  import gradio as gr
5
  import requests
@@ -8,7 +8,7 @@ import ai
8
 
9
 
10
  class Component(ABC):
11
- VNAME = None
12
 
13
  def __init__(self, id_: int, visible: bool = False):
14
  # Internal state
@@ -33,11 +33,11 @@ class Component(ABC):
33
 
34
 
35
  class Input(Component):
36
- VNAME = "v"
37
 
38
  def _render(self, id_: int, visible: bool) -> gr.Textbox:
39
  self.output = gr.Textbox(
40
- label=f"Input: {{{self.VNAME}{id_}}}",
41
  interactive=True,
42
  placeholder="Variable value",
43
  visible=visible,
@@ -46,7 +46,7 @@ class Input(Component):
46
 
47
 
48
  class TaskComponent(Component, ABC):
49
- VNAME = "t"
50
 
51
  @abstractmethod
52
  def inputs(self) -> List:
@@ -66,13 +66,13 @@ class TaskComponent(Component, ABC):
66
 
67
 
68
  class AITask(TaskComponent):
69
- NAME = "AI Task"
70
 
71
  def _render(self, id_: int, visible: bool) -> gr.Box:
72
  with gr.Box(visible=visible) as gr_component:
73
  gr.Markdown(
74
  f"""
75
- {self.NAME}
76
  <br> Use this Task to give instructions to ChatGPT.
77
  """
78
  )
@@ -84,7 +84,7 @@ class AITask(TaskComponent):
84
  placeholder="Example - summarize this text: {v1}",
85
  )
86
  self.output = gr.Textbox(
87
- label=f"Output: {{{self.VNAME}{id_}}}",
88
  lines=10,
89
  interactive=False,
90
  )
@@ -93,7 +93,7 @@ class AITask(TaskComponent):
93
  def execute(self, prompt: str, vars_in_scope: Dict[str, str]) -> Optional[str]:
94
  if prompt:
95
  formatted_prompt = prompt.format(**vars_in_scope)
96
- print(f"Executing {self.NAME} with prompt :: {formatted_prompt}")
97
  return ai.llm.next([{"role": "user", "content": formatted_prompt}])
98
 
99
  def inputs(self) -> List[gr.Textbox]:
@@ -101,13 +101,13 @@ class AITask(TaskComponent):
101
 
102
 
103
  class VisitURL(TaskComponent):
104
- NAME = "Visit URL"
105
 
106
  def _render(self, id_: int, visible: bool) -> gr.Box:
107
  with gr.Box(visible=visible) as gr_component:
108
  gr.Markdown(
109
  f"""
110
- {self.NAME}
111
  <br> Use this Task to visit an URL and get its content.
112
  """
113
  )
@@ -118,7 +118,7 @@ class VisitURL(TaskComponent):
118
  show_label=False,
119
  )
120
  self.output = gr.Textbox(
121
- label=f"Output: {{{self.VNAME}{id_}}}",
122
  lines=10,
123
  interactive=False,
124
  )
@@ -127,7 +127,7 @@ class VisitURL(TaskComponent):
127
  def execute(self, url: str, vars_in_scope: Dict[str, str]) -> Optional[str]:
128
  if url:
129
  formatted_url = url.format(**vars_in_scope)
130
- print(f"Executing {self.NAME} with url :: {formatted_url}")
131
  return requests.get(formatted_url).text
132
 
133
  def inputs(self) -> List[gr.Textbox]:
@@ -135,13 +135,13 @@ class VisitURL(TaskComponent):
135
 
136
 
137
  class Task:
138
- AVAILABLE_TASKS = [AITask, VisitURL]
139
- VNAME = "t"
140
 
141
  def __init__(self, id_: int):
142
  self._id = id_
143
- self._active_index = 0 # Default
144
- self._inner_tasks = [t(self._id, False) for t in self.AVAILABLE_TASKS]
145
 
146
  def render(self) -> None:
147
  self.active_index = gr.Number(self._active_index, visible=False)
@@ -153,12 +153,12 @@ class Task:
153
  return self._inner_tasks[self._active_index].component_id
154
 
155
  @property
156
- def visibilities(self) -> List[gr.Number]:
157
- return [t.visible for t in self._inner_tasks]
158
 
159
  @property
160
- def gr_components(self) -> List[gr.Box]:
161
- return [t.gr_component for t in self._inner_tasks]
162
 
163
  @property
164
  def output(self) -> gr.Textbox:
@@ -178,11 +178,20 @@ class Task:
178
  return inner_task.execute(*args)
179
 
180
 
181
- MAX_INPUTS = 5
182
- MAX_TASKS = 10
183
 
 
184
 
185
- all_inputs = {i: Input(i) for i in range(MAX_INPUTS)}
186
- all_tasks = {i: Task(i) for i in range(MAX_TASKS)}
 
187
 
188
- all_inputs[0]._initial_visibility = True
 
 
 
 
 
 
 
 
1
  from abc import ABC, abstractmethod
2
+ from typing import Dict, List, Optional, Tuple
3
 
4
  import gradio as gr
5
  import requests
 
8
 
9
 
10
  class Component(ABC):
11
+ vname = None
12
 
13
  def __init__(self, id_: int, visible: bool = False):
14
  # Internal state
 
33
 
34
 
35
  class Input(Component):
36
+ vname = "v"
37
 
38
  def _render(self, id_: int, visible: bool) -> gr.Textbox:
39
  self.output = gr.Textbox(
40
+ label=f"Input: {{{self.vname}{id_}}}",
41
  interactive=True,
42
  placeholder="Variable value",
43
  visible=visible,
 
46
 
47
 
48
  class TaskComponent(Component, ABC):
49
+ vname = "t"
50
 
51
  @abstractmethod
52
  def inputs(self) -> List:
 
66
 
67
 
68
  class AITask(TaskComponent):
69
+ name = "AI Task"
70
 
71
  def _render(self, id_: int, visible: bool) -> gr.Box:
72
  with gr.Box(visible=visible) as gr_component:
73
  gr.Markdown(
74
  f"""
75
+ {self.name}
76
  <br> Use this Task to give instructions to ChatGPT.
77
  """
78
  )
 
84
  placeholder="Example - summarize this text: {v1}",
85
  )
86
  self.output = gr.Textbox(
87
+ label=f"Output: {{{self.vname}{id_}}}",
88
  lines=10,
89
  interactive=False,
90
  )
 
93
  def execute(self, prompt: str, vars_in_scope: Dict[str, str]) -> Optional[str]:
94
  if prompt:
95
  formatted_prompt = prompt.format(**vars_in_scope)
96
+ print(f"Executing {self.name} with prompt :: {formatted_prompt}")
97
  return ai.llm.next([{"role": "user", "content": formatted_prompt}])
98
 
99
  def inputs(self) -> List[gr.Textbox]:
 
101
 
102
 
103
  class VisitURL(TaskComponent):
104
+ name = "Visit URL"
105
 
106
  def _render(self, id_: int, visible: bool) -> gr.Box:
107
  with gr.Box(visible=visible) as gr_component:
108
  gr.Markdown(
109
  f"""
110
+ {self.name}
111
  <br> Use this Task to visit an URL and get its content.
112
  """
113
  )
 
118
  show_label=False,
119
  )
120
  self.output = gr.Textbox(
121
+ label=f"Output: {{{self.vname}{id_}}}",
122
  lines=10,
123
  interactive=False,
124
  )
 
127
  def execute(self, url: str, vars_in_scope: Dict[str, str]) -> Optional[str]:
128
  if url:
129
  formatted_url = url.format(**vars_in_scope)
130
+ print(f"Executing {self.name} with url :: {formatted_url}")
131
  return requests.get(formatted_url).text
132
 
133
  def inputs(self) -> List[gr.Textbox]:
 
135
 
136
 
137
  class Task:
138
+ available_tasks = [AITask, VisitURL]
139
+ vname = "t"
140
 
141
  def __init__(self, id_: int):
142
  self._id = id_
143
+ self._active_index = -1 # Nothing
144
+ self._inner_tasks = [t(self._id, False) for t in self.available_tasks]
145
 
146
  def render(self) -> None:
147
  self.active_index = gr.Number(self._active_index, visible=False)
 
153
  return self._inner_tasks[self._active_index].component_id
154
 
155
  @property
156
+ def gr_component(self) -> gr.Box:
157
+ return self._inner_tasks[self._active_index].gr_component
158
 
159
  @property
160
+ def visible(self) -> gr.Number:
161
+ return self._inner_tasks[self._active_index].visible
162
 
163
  @property
164
  def output(self) -> gr.Textbox:
 
178
  return inner_task.execute(*args)
179
 
180
 
181
+ class State:
182
+ MAX_TASKS = 10
183
 
184
+ all_tasks = {i: Task(i) for i in range(MAX_TASKS)}
185
 
186
+ @classmethod
187
+ def task_visibilities(cls) -> List:
188
+ return [it.visible for t in cls.all_tasks.values() for it in t._inner_tasks]
189
 
190
+ @classmethod
191
+ def task_rows(cls) -> List:
192
+ return [
193
+ it.gr_component for t in cls.all_tasks.values() for it in t._inner_tasks
194
+ ] + [it.visible for t in cls.all_tasks.values() for it in t._inner_tasks]
195
+
196
+
197
+ tasks = State()