Maharshi Gor commited on
Commit
1758388
·
1 Parent(s): d0ae1a9

Restructure output panel rendering. This change fixes logprob issue and

Browse files
src/app_configs.py CHANGED
@@ -38,20 +38,33 @@ AVAILABLE_MODELS = {
38
  },
39
  }
40
 
 
 
 
 
 
 
 
 
 
 
 
41
  DEFAULT_SELECTIONS = {
42
  "tossup": {
43
  "simple_workflow": False,
44
  "model": "OpenAI/gpt-4o-mini",
45
- "temperature": 0.2,
46
  "confidence_threshold": 0.85,
47
  "early_stop": True,
 
48
  },
49
  "bonus": {
50
  "simple_workflow": False,
51
  "model": "OpenAI/gpt-4o-mini",
52
- "temperature": 0.2,
53
  "confidence_threshold": 0.85,
54
  "early_stop": True,
 
55
  },
56
  }
57
 
 
38
  },
39
  }
40
 
41
+ CONFIGS = {
42
+ "tossup": {
43
+ "required_input_vars": ["question_text"],
44
+ "required_output_vars": ["answer", "confidence"],
45
+ },
46
+ "bonus": {
47
+ "required_input_vars": ["leadin", "part"],
48
+ "required_output_vars": ["answer", "confidence", "explanation"],
49
+ },
50
+ }
51
+
52
  DEFAULT_SELECTIONS = {
53
  "tossup": {
54
  "simple_workflow": False,
55
  "model": "OpenAI/gpt-4o-mini",
56
+ "temperature": 0.7,
57
  "confidence_threshold": 0.85,
58
  "early_stop": True,
59
+ "max_temperature": 5.0,
60
  },
61
  "bonus": {
62
  "simple_workflow": False,
63
  "model": "OpenAI/gpt-4o-mini",
64
+ "temperature": 0.7,
65
  "confidence_threshold": 0.85,
66
  "early_stop": True,
67
+ "max_temperature": 5.0,
68
  },
69
  }
70
 
src/components/model_pipeline/model_pipeline.py CHANGED
@@ -18,6 +18,10 @@ from components.utils import make_state
18
  from workflows.structs import ModelStep, TossupWorkflow, Workflow
19
  from workflows.validators import WorkflowValidator
20
 
 
 
 
 
21
 
22
  class PipelineInterface:
23
  """UI for the pipeline."""
@@ -28,17 +32,20 @@ class PipelineInterface:
28
  workflow: Workflow,
29
  ui_state: PipelineUIState | None = None,
30
  model_options: list[str] = None,
31
- simple: bool = False,
32
  ):
33
  self.app = app
34
  self.model_options = model_options
35
- self.simple = simple
 
36
  ui_state = ui_state or PipelineUIState.from_workflow(workflow)
37
 
38
  # Gradio States
39
  self.workflow_state = make_state(workflow.model_dump())
40
  self.variables_state = make_state(workflow.get_available_variables())
41
- self.model_selection_state = make_state(workflow.get_model_selections())
 
 
42
  self.pipeline_change = gr.State(False)
43
 
44
  if isinstance(workflow, TossupWorkflow):
@@ -51,24 +58,19 @@ class PipelineInterface:
51
 
52
  def get_aux_states(pipeline_state_dict: td.PipelineStateDict):
53
  """Get the auxiliary states for the pipeline."""
 
54
  pipeline_state = self.sm.make_pipeline_state(pipeline_state_dict)
55
  return (
56
  pipeline_state.workflow.model_dump(),
57
  pipeline_state.workflow.get_available_variables(),
58
- pipeline_state.workflow.get_model_selections(),
59
  )
60
 
61
  # Triggers for pipeline state changes
62
  self.pipeline_state.change(
63
  get_aux_states,
64
  inputs=[self.pipeline_state],
65
- outputs=[self.workflow_state, self.variables_state, self.model_selection_state],
66
- )
67
-
68
- self.workflow_state.change(
69
- lambda x: logger.debug(f"Workflow state changed: {x}"),
70
- inputs=[self.workflow_state],
71
- outputs=[],
72
  )
73
 
74
  # IO Variables
@@ -98,6 +100,7 @@ class PipelineInterface:
98
  model_options=self.model_options,
99
  input_variables=available_variables,
100
  pipeline_state_manager=self.sm,
 
101
  )
102
 
103
  step_interface.on_model_step_change(
@@ -259,14 +262,14 @@ class PipelineInterface:
259
  self._render_add_step_button(-1)
260
 
261
  @gr.render(
262
- triggers=[self.workflow_state.change, self.app.load],
263
  inputs=[self.pipeline_state],
264
  concurrency_limit=1,
265
  concurrency_id="render_output_fields",
266
  )
267
  def render_output_fields(pipeline_state_dict: td.PipelineStateDict):
268
  pipeline_state = self.sm.make_pipeline_state(pipeline_state_dict)
269
- logger.info(f"Rerendering output panel: {pipeline_state.workflow}")
270
  self._render_output_panel(pipeline_state)
271
 
272
  export_btn = gr.Button("Export Pipeline", elem_classes="export-button")
 
18
  from workflows.structs import ModelStep, TossupWorkflow, Workflow
19
  from workflows.validators import WorkflowValidator
20
 
21
+ from .state_manager import get_output_panel_state
22
+
23
+ DEFAULT_MAX_TEMPERATURE = 5.0
24
+
25
 
26
  class PipelineInterface:
27
  """UI for the pipeline."""
 
32
  workflow: Workflow,
33
  ui_state: PipelineUIState | None = None,
34
  model_options: list[str] = None,
35
+ config: dict = {},
36
  ):
37
  self.app = app
38
  self.model_options = model_options
39
+ self.config = config
40
+ self.simple = self.config.get("simple", False)
41
  ui_state = ui_state or PipelineUIState.from_workflow(workflow)
42
 
43
  # Gradio States
44
  self.workflow_state = make_state(workflow.model_dump())
45
  self.variables_state = make_state(workflow.get_available_variables())
46
+ self.output_panel_state = make_state(get_output_panel_state(workflow))
47
+
48
+ # Maintains the toggle state change for pipeline changes through user input.
49
  self.pipeline_change = gr.State(False)
50
 
51
  if isinstance(workflow, TossupWorkflow):
 
58
 
59
  def get_aux_states(pipeline_state_dict: td.PipelineStateDict):
60
  """Get the auxiliary states for the pipeline."""
61
+ logger.debug("Pipeline changed! Getting aux states for pipeline state.")
62
  pipeline_state = self.sm.make_pipeline_state(pipeline_state_dict)
63
  return (
64
  pipeline_state.workflow.model_dump(),
65
  pipeline_state.workflow.get_available_variables(),
66
+ get_output_panel_state(pipeline_state.workflow),
67
  )
68
 
69
  # Triggers for pipeline state changes
70
  self.pipeline_state.change(
71
  get_aux_states,
72
  inputs=[self.pipeline_state],
73
+ outputs=[self.workflow_state, self.variables_state, self.output_panel_state],
 
 
 
 
 
 
74
  )
75
 
76
  # IO Variables
 
100
  model_options=self.model_options,
101
  input_variables=available_variables,
102
  pipeline_state_manager=self.sm,
103
+ max_temperature=self.config.get("max_temperature", DEFAULT_MAX_TEMPERATURE),
104
  )
105
 
106
  step_interface.on_model_step_change(
 
262
  self._render_add_step_button(-1)
263
 
264
  @gr.render(
265
+ triggers=[self.output_panel_state.change, self.app.load],
266
  inputs=[self.pipeline_state],
267
  concurrency_limit=1,
268
  concurrency_id="render_output_fields",
269
  )
270
  def render_output_fields(pipeline_state_dict: td.PipelineStateDict):
271
  pipeline_state = self.sm.make_pipeline_state(pipeline_state_dict)
272
+ logger.debug(f"Rerendering output panel: {get_output_panel_state(pipeline_state.workflow)}")
273
  self._render_output_panel(pipeline_state)
274
 
275
  export_btn = gr.Button("Export Pipeline", elem_classes="export-button")
src/components/model_pipeline/state_manager.py CHANGED
@@ -8,7 +8,18 @@ from components import typed_dicts as td
8
  from components import utils
9
  from components.structs import ModelStepUIState, PipelineState, PipelineUIState, TossupPipelineState
10
  from workflows.factory import create_new_llm_step
11
- from workflows.structs import Buzzer, ModelStep, TossupWorkflow, Workflow
 
 
 
 
 
 
 
 
 
 
 
12
 
13
 
14
  class PipelineStateManager:
@@ -134,6 +145,26 @@ class TossupPipelineStateManager(PipelineStateManager):
134
  workflow = self.parse_yaml_workflow(yaml_str)
135
  return TossupPipelineState.from_workflow(workflow).model_dump(), not change_state
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  def update_buzzer(
138
  self,
139
  state_dict: td.TossupPipelineStateDict,
@@ -144,6 +175,8 @@ class TossupPipelineStateManager(PipelineStateManager):
144
  """Update the buzzer."""
145
  state = self.make_pipeline_state(state_dict)
146
  prob_threshold = float(tokens_prob) if tokens_prob and tokens_prob > 0 else None
 
 
147
  state.workflow.buzzer = Buzzer(
148
  method=method, confidence_threshold=confidence_threshold, prob_threshold=prob_threshold
149
  )
 
8
  from components import utils
9
  from components.structs import ModelStepUIState, PipelineState, PipelineUIState, TossupPipelineState
10
  from workflows.factory import create_new_llm_step
11
+ from workflows.structs import Buzzer, BuzzerMethod, ModelStep, TossupWorkflow, Workflow
12
+
13
+
14
+ def get_output_panel_state(workflow: Workflow) -> dict:
15
+ state = {
16
+ "variables": workflow.get_available_variables(),
17
+ "models": workflow.get_step_model_selections(),
18
+ "output_models": workflow.get_output_model_selections(),
19
+ }
20
+ if isinstance(workflow, TossupWorkflow):
21
+ state["buzzer"] = workflow.buzzer.model_dump(exclude_defaults=False)
22
+ return state
23
 
24
 
25
  class PipelineStateManager:
 
145
  workflow = self.parse_yaml_workflow(yaml_str)
146
  return TossupPipelineState.from_workflow(workflow).model_dump(), not change_state
147
 
148
+ def update_model_step_state(
149
+ self, state_dict: td.TossupPipelineStateDict, model_step: ModelStep, ui_state: ModelStepUIState
150
+ ) -> td.TossupPipelineStateDict:
151
+ """Update a particular model step in the pipeline."""
152
+ state = self.make_pipeline_state(state_dict)
153
+ state = state.update_step(model_step, ui_state)
154
+ state.workflow = state.workflow.refresh_buzzer()
155
+ return state.model_dump()
156
+
157
+ def update_output_variables(
158
+ self, state_dict: td.TossupPipelineStateDict, target: str, produced_variable: str
159
+ ) -> td.TossupPipelineStateDict:
160
+ if produced_variable == UNSELECTED_VAR_NAME:
161
+ produced_variable = None
162
+ """Update the output variables for a step."""
163
+ state = self.make_pipeline_state(state_dict)
164
+ state.workflow.outputs[target] = produced_variable
165
+ state.workflow = state.workflow.refresh_buzzer()
166
+ return state.model_dump()
167
+
168
  def update_buzzer(
169
  self,
170
  state_dict: td.TossupPipelineStateDict,
 
175
  """Update the buzzer."""
176
  state = self.make_pipeline_state(state_dict)
177
  prob_threshold = float(tokens_prob) if tokens_prob and tokens_prob > 0 else None
178
+ if method == BuzzerMethod.OR and prob_threshold is None:
179
+ prob_threshold = 0.0
180
  state.workflow.buzzer = Buzzer(
181
  method=method, confidence_threshold=confidence_threshold, prob_threshold=prob_threshold
182
  )
src/components/model_pipeline/tossup_pipeline.py CHANGED
@@ -10,23 +10,6 @@ from display.formatting import tiny_styled_warning
10
  from workflows.structs import Buzzer, TossupWorkflow
11
 
12
  from .model_pipeline import PipelineInterface, PipelineState, PipelineUIState
13
- from .state_manager import PipelineStateManager, TossupPipelineStateManager
14
-
15
-
16
- def get_probs_model_name(workflow: TossupWorkflow, answer_var: str | None = None) -> str | None:
17
- if answer_var is None:
18
- answer_var = workflow.outputs["answer"]
19
- if answer_var is None or answer_var == UNSELECTED_VAR_NAME:
20
- return None
21
- step_id = answer_var.split(".")[0]
22
- return workflow.steps[step_id].get_full_model_name()
23
-
24
-
25
- def is_logprobs_supported(workflow: TossupWorkflow, answer_var: str | None = None) -> bool:
26
- model_name = get_probs_model_name(workflow, answer_var)
27
- if model_name is None:
28
- return True
29
- return AVAILABLE_MODELS[model_name].get("logprobs", False)
30
 
31
 
32
  def toggleable_slider(
@@ -56,17 +39,16 @@ class TossupPipelineInterface(PipelineInterface):
56
  workflow: TossupWorkflow,
57
  ui_state: PipelineUIState | None = None,
58
  model_options: list[str] = None,
59
- simple: bool = False,
60
- defaults: dict = {},
61
  ):
62
- super().__init__(app, workflow, ui_state, model_options, simple)
63
- self.defaults = defaults
 
64
 
65
  self.pipeline_state.change(
66
- lambda x: logger.debug(
67
- f"Pipeline state changed. Type: {type(x)}. Has buzzer info: {x['workflow']['buzzer'] if isinstance(x, dict) else 'N/A'}"
68
- ),
69
  inputs=[self.pipeline_state],
 
70
  )
71
 
72
  def update_prob_slider(
@@ -81,7 +63,7 @@ class TossupPipelineInterface(PipelineInterface):
81
  gr.update(value="AND", interactive=True),
82
  gr.update(visible=False),
83
  )
84
- logprobs_supported = is_logprobs_supported(state.workflow, answer_var)
85
  buzzer = state.workflow.buzzer
86
  tokens_prob_threshold = tokens_prob if logprobs_supported else None
87
  method = buzzer.method if logprobs_supported else "AND"
@@ -90,10 +72,10 @@ class TossupPipelineInterface(PipelineInterface):
90
  confidence_threshold=buzzer.confidence_threshold,
91
  prob_threshold=tokens_prob_threshold,
92
  )
93
- model_name = get_probs_model_name(state.workflow, answer_var)
94
  return (
95
  state.model_dump(),
96
- gr.update(interactive=logprobs_supported),
97
  gr.update(value=method, interactive=logprobs_supported),
98
  gr.update(
99
  value=tiny_styled_warning(
@@ -172,20 +154,21 @@ class TossupPipelineInterface(PipelineInterface):
172
  header="Buzzer settings:",
173
  subheader="Set your thresholds for confidence and output tokens probability (computed using <code>logprobs</code>).",
174
  )
175
- logprobs_supported = is_logprobs_supported(pipeline_state.workflow)
176
- selected_model_name = get_probs_model_name(pipeline_state.workflow)
177
  self._render_buzzer_panel(pipeline_state.workflow.buzzer, logprobs_supported, selected_model_name)
178
 
179
- # def update_choices(available_variables: list[str]):
180
- # """Update the choices for the dropdowns"""
181
- # return [gr.update(choices=available_variables, value=None, selected=None) for _ in dropdowns.values()]
182
 
183
- # self.variables_state.change(
184
- # update_choices,
185
- # inputs=[self.variables_state],
186
- # outputs=list(dropdowns.values()),
187
- # )
188
 
 
189
  gr.on(
190
  triggers=[
191
  self.confidence_slider.release,
@@ -197,17 +180,17 @@ class TossupPipelineInterface(PipelineInterface):
197
  outputs=[self.pipeline_state],
198
  )
199
 
200
- # TODO: Do Add model step change triggers as well. (Model name change triggers)
201
- answer_dropdown = dropdowns["answer"]
202
- if answer_dropdown is not None:
203
- gr.on(
204
- triggers=[answer_dropdown.input, self.model_selection_state.change],
205
- fn=self.update_prob_slider,
206
- inputs=[self.pipeline_state, answer_dropdown, self.prob_slider],
207
- outputs=[
208
- self.pipeline_state,
209
- self.prob_slider,
210
- self.buzzer_method_dropdown,
211
- self.buzzer_warning_display,
212
- ],
213
- )
 
10
  from workflows.structs import Buzzer, TossupWorkflow
11
 
12
  from .model_pipeline import PipelineInterface, PipelineState, PipelineUIState
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
 
15
  def toggleable_slider(
 
39
  workflow: TossupWorkflow,
40
  ui_state: PipelineUIState | None = None,
41
  model_options: list[str] = None,
42
+ config: dict = {},
 
43
  ):
44
+ super().__init__(app, workflow, ui_state, model_options, config)
45
+
46
+ self.buzzer_state = gr.State(workflow.buzzer.model_dump())
47
 
48
  self.pipeline_state.change(
49
+ lambda x: TossupPipelineState(**x).workflow.buzzer.model_dump(),
 
 
50
  inputs=[self.pipeline_state],
51
+ outputs=[self.buzzer_state],
52
  )
53
 
54
  def update_prob_slider(
 
63
  gr.update(value="AND", interactive=True),
64
  gr.update(visible=False),
65
  )
66
+ logprobs_supported = state.workflow.is_token_probs_supported(answer_var)
67
  buzzer = state.workflow.buzzer
68
  tokens_prob_threshold = tokens_prob if logprobs_supported else None
69
  method = buzzer.method if logprobs_supported else "AND"
 
72
  confidence_threshold=buzzer.confidence_threshold,
73
  prob_threshold=tokens_prob_threshold,
74
  )
75
+ model_name = state.workflow.get_answer_model(answer_var)
76
  return (
77
  state.model_dump(),
78
+ gr.update(interactive=logprobs_supported, value=tokens_prob if logprobs_supported else 0.0),
79
  gr.update(value=method, interactive=logprobs_supported),
80
  gr.update(
81
  value=tiny_styled_warning(
 
154
  header="Buzzer settings:",
155
  subheader="Set your thresholds for confidence and output tokens probability (computed using <code>logprobs</code>).",
156
  )
157
+ logprobs_supported = pipeline_state.workflow.is_token_probs_supported()
158
+ selected_model_name = pipeline_state.workflow.get_answer_model()
159
  self._render_buzzer_panel(pipeline_state.workflow.buzzer, logprobs_supported, selected_model_name)
160
 
161
+ def update_choices(available_variables: list[str]):
162
+ """Update the choices for the dropdowns"""
163
+ return [gr.update(choices=available_variables, value=None, selected=None) for _ in dropdowns.values()]
164
 
165
+ self.variables_state.change(
166
+ update_choices,
167
+ inputs=[self.variables_state],
168
+ outputs=list(dropdowns.values()),
169
+ )
170
 
171
+ # Updating the pipeline buzzer on user input changes in Buzzer panel.
172
  gr.on(
173
  triggers=[
174
  self.confidence_slider.release,
 
180
  outputs=[self.pipeline_state],
181
  )
182
 
183
+ # THIS WASN't NEEDED SINCE WE RERENDER THE OUTPUT PANEL ENTIRELY ON CHANGES
184
+ # answer_dropdown = dropdowns["answer"]
185
+ # if answer_dropdown is not None:
186
+ # gr.on(
187
+ # triggers=[self.buzzer_state.change],
188
+ # fn=self.update_prob_slider,
189
+ # inputs=[self.buzzer_state, answer_dropdown, self.prob_slider],
190
+ # outputs=[
191
+ # self.pipeline_state,
192
+ # self.prob_slider,
193
+ # self.buzzer_method_dropdown,
194
+ # self.buzzer_warning_display,
195
+ # ],
196
+ # )
src/components/model_step/model_step.py CHANGED
@@ -44,6 +44,7 @@ class ModelStepComponent(FormComponent):
44
  input_variables: list[str] | None = None,
45
  max_input_fields=5,
46
  max_output_fields=5,
 
47
  pipeline_state_manager: PipelineStateManager | None = None,
48
  **kwargs,
49
  ):
@@ -51,6 +52,7 @@ class ModelStepComponent(FormComponent):
51
  "input": max_input_fields,
52
  "output": max_output_fields,
53
  }
 
54
  self.model_options = model_options
55
  self.input_variables = [UNSELECTED_VAR_NAME] + input_variables
56
  self.sm = ModelStepStateManager(max_input_fields, max_output_fields)
@@ -238,7 +240,7 @@ class ModelStepComponent(FormComponent):
238
  self.temperature_slider = gr.Slider(
239
  value=self.model_step.temperature,
240
  minimum=0.0,
241
- maximum=5,
242
  step=0.05,
243
  info="Temperature",
244
  show_label=False,
 
44
  input_variables: list[str] | None = None,
45
  max_input_fields=5,
46
  max_output_fields=5,
47
+ max_temperature=5.0,
48
  pipeline_state_manager: PipelineStateManager | None = None,
49
  **kwargs,
50
  ):
 
52
  "input": max_input_fields,
53
  "output": max_output_fields,
54
  }
55
+ self.max_temperature = max_temperature
56
  self.model_options = model_options
57
  self.input_variables = [UNSELECTED_VAR_NAME] + input_variables
58
  self.sm = ModelStepStateManager(max_input_fields, max_output_fields)
 
240
  self.temperature_slider = gr.Slider(
241
  value=self.model_step.temperature,
242
  minimum=0.0,
243
+ maximum=self.max_temperature,
244
  step=0.05,
245
  info="Temperature",
246
  show_label=False,
src/workflows/structs.py CHANGED
@@ -257,7 +257,7 @@ class Workflow(BaseModel):
257
  variables.update(self.get_step_variables(step.id))
258
  return list(variables)
259
 
260
- def get_model_selections(self) -> dict[str, str]:
261
  """Get all model selections for all steps."""
262
  return {step_id: step.get_full_model_name() for step_id, step in self.steps.items()}
263
 
 
257
  variables.update(self.get_step_variables(step.id))
258
  return list(variables)
259
 
260
+ def get_step_model_selections(self) -> dict[str, str]:
261
  """Get all model selections for all steps."""
262
  return {step_id: step.get_full_model_name() for step_id, step in self.steps.items()}
263