psaiops 0.0.15__tar.gz → 0.0.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of psaiops might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: psaiops
3
- Version: 0.0.15
3
+ Version: 0.0.17
4
4
  Summary: Web apps to inspect & engineer NN activations.
5
5
  License: .github/LICENSE.md
6
6
  Author: apehex
@@ -9,7 +9,7 @@ import psaiops.score.attention.lib
9
9
  # META #########################################################################
10
10
 
11
11
  TITLE = '''Attention Scoring'''
12
- INTRO = '''Score each token according to the weights of the attention layers.\nThe model is fixed to "openai/gpt-oss-20b" for now.'''
12
+ INTRO = '''Score each token according to the weights of the attention layers. The model is fixed to "openai/gpt-oss-20b" for now.'''
13
13
  STYLE = '''.white-text span { color: white; }'''
14
14
 
15
15
  MODEL = 'openai/gpt-oss-20b'
@@ -78,7 +78,7 @@ def create_outputs_block() -> dict:
78
78
 
79
79
  def create_actions_block() -> dict:
80
80
  __process = gradio.Button('Process', variant='primary', size='lg', scale=1, interactive=True)
81
- __position = gradio.Slider(label='Position', value=-1, minimum=-1, maximum=128, step=1, scale=1, interactive=True) # info='-1 to average on all tokens'
81
+ __position = gradio.Slider(label='Position', value=-1, minimum=-1, maximum=15, step=1, scale=1, interactive=True) # info='-1 to average on all tokens'
82
82
  return {
83
83
  'process_block': __process,
84
84
  'position_block': __position}
@@ -121,8 +121,8 @@ def create_layout(intro: str=INTRO) -> dict:
121
121
  def update_layer_range(value: float, model: str) -> dict:
122
122
  return gradio.update(maximum=35, value=min(35, int(value))) if '120b' in model else gradio.update(maximum=23, value=min(23, int(value)))
123
123
 
124
- def update_position_range(value: float, tokens: list) -> dict:
125
- return gradio.update(maximum=len(tokens) - 1, value=min(len(tokens) - 1, int(value)))
124
+ def update_position_range(value: float, tokens: float) -> dict:
125
+ return gradio.update(maximum=int(tokens) - 1, value=min(int(tokens) - 1, int(value)))
126
126
 
127
127
  def update_computation_state(
128
128
  token_num: float,
@@ -140,11 +140,14 @@ def update_computation_state(
140
140
  __token_num = max(1, min(128, int(token_num)))
141
141
  __topk_num = max(1, min(8, int(topk_num)))
142
142
  __topp_num = max(0.0, min(1.0, float(topp_num)))
143
- __token_idx = max(0, min(__token_num, int(token_idx)))
144
- __layer_idx = max(0, int(layer_idx))
145
- __head_idx = max(0, int(head_idx))
143
+ __token_idx = max(-1, min(__token_num, int(token_idx)))
144
+ __layer_idx = max(-1, int(layer_idx))
145
+ __head_idx = max(-1, int(head_idx))
146
146
  __prompt_str = prompt_str.strip()
147
147
  __device_str = device_str if (device_str in ['cpu', 'cuda']) else 'cpu'
148
+ # exit if some values are missing
149
+ if (not __prompt_str) or (model_obj is None) or (tokenizer_obj is None):
150
+ return ([], [], [], torch.empty(0))
148
151
  # handle all exceptions at once
149
152
  try:
150
153
  # dictionary {'input_ids': _, 'attention_mask': _}
@@ -183,14 +186,12 @@ def update_computation_state(
183
186
  token_obj=__output_data)
184
187
  # update each component => (input, output, attention, highligh) states
185
188
  return (
186
- gradio.update(value=__tokens[:__input_dim]),
187
- gradio.update(value=__tokens[__input_dim:]),
188
- gradio.update(value=__attention_data),
189
- gradio.update(value=list(zip(__tokens, __labels))))
189
+ list(zip(__tokens, __labels)),
190
+ __tokens[:__input_dim],
191
+ __tokens[__input_dim:],
192
+ __attention_data,)
190
193
  except:
191
194
  raise Exception('Attention generation aborted with an error.')
192
- finally:
193
- return (gradio.update(), gradio.update(), gradio.update(), gradio.update())
194
195
 
195
196
  def update_text_highlight(
196
197
  token_idx: float,
@@ -199,15 +200,16 @@ def update_text_highlight(
199
200
  input_data: list,
200
201
  output_data: list,
201
202
  attention_data: torch.Tensor,
202
- ) -> dict:
203
+ ) -> list:
203
204
  # sanitize the inputs
204
205
  __input_data = input_data or []
205
206
  __output_data = output_data or []
206
- __attention_data = attention_data or torch.empty(0)
207
+ __attention_data = torch.empty(0) if (attention_data is None) else attention_data
207
208
  __input_dim = len(__input_data)
208
- __token_idx = max(0, min(__input_dim, int(token_idx)))
209
- __layer_idx = max(0, int(layer_idx))
210
- __head_idx = max(0, int(head_idx))
209
+ __output_dim = len(__output_data)
210
+ __token_idx = max(-1, min(__output_dim, int(token_idx)))
211
+ __layer_idx = max(-1, int(layer_idx))
212
+ __head_idx = max(-1, int(head_idx))
211
213
  # exit if the data has not yet been computed
212
214
  if (not __input_data) or (not __output_data) or (attention_data is None) or (len(attention_data) == 0):
213
215
  return gradio.update()
@@ -228,11 +230,9 @@ def update_text_highlight(
228
230
  input_dim=__input_dim,
229
231
  token_idx=__token_idx)
230
232
  # update the component with [(token, label), ...]
231
- return gradio.update(value=list(zip(__tokens, __labels)))
233
+ return list(zip(__tokens, __labels))
232
234
  except:
233
235
  raise Exception('Attention reduction aborted with an error.')
234
- finally:
235
- return gradio.update()
236
236
 
237
237
  # APP ##########################################################################
238
238
 
@@ -249,26 +249,23 @@ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, model: str=
249
249
  __fields.update(create_layout(intro=intro))
250
250
  # init the state
251
251
  __fields.update(create_state())
252
- # fetch the relevant fields
253
- __button_block, __position_block, __output_block = (__fields['process_block'], __fields['position_block'], __fields['output_block'])
254
- __output_state, __attention_state = (__fields['output_state'], __fields['attention_state'])
255
252
  # wire the input fields
256
- __button_block.click(
253
+ __fields['process_block'].click(
257
254
  fn=__compute,
258
255
  inputs=[__fields[__k] for __k in ['tokens_block', 'topk_block', 'topp_block', 'position_block', 'layer_block', 'head_block', 'input_block']],
259
- outputs=[__fields[__k] for __k in ['input_state', 'output_state', 'attention_state', 'output_block']],
256
+ outputs=[__fields[__k] for __k in ['output_block', 'input_state', 'output_state', 'attention_state']],
260
257
  queue=False,
261
258
  show_progress='full')
262
- __output_state.change(
259
+ __fields['tokens_block'].change(
263
260
  fn=update_position_range,
264
- inputs=[__position_block, __output_state],
265
- outputs=__position_block,
261
+ inputs=[__fields[__k] for __k in ['position_block', 'tokens_block']],
262
+ outputs=__fields['position_block'],
266
263
  queue=False,
267
264
  show_progress='hidden')
268
- __position_block.change(
265
+ __fields['position_block'].change(
269
266
  fn=update_text_highlight,
270
267
  inputs=[__fields[__k] for __k in ['position_block', 'layer_block', 'head_block', 'input_state', 'output_state', 'attention_state']],
271
- outputs=__output_block,
268
+ outputs=__fields['output_block'],
272
269
  queue=False,
273
270
  show_progress='hidden')
274
271
  # gradio application
@@ -119,7 +119,7 @@ def postprocess_attention_scores(
119
119
  __output_range = list(range(__output_dim - input_dim)) if (__token_idx < 0) else [__token_idx]
120
120
  __output_mask = torch.BoolTensor([__i in __output_range for __i in range(__output_dim - input_dim)])
121
121
  # normalize the scores
122
- __input_scores = attention_data[__input_slice] / (attention_data[__input_slice].sum() + 1e-5)
122
+ __input_scores = attention_data[__input_slice] / (attention_data[__input_slice].mean() + 1e-5)
123
123
  # round to obtain integer labels from 0 to 100
124
124
  __input_scores = torch.round(100.0 * __input_scores, decimals=0).type(torch.int32)
125
125
  # the generated tokens are not scored
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "psaiops"
3
- version = "0.0.15"
3
+ version = "0.0.17"
4
4
  description = "Web apps to inspect & engineer NN activations."
5
5
  license = ".github/LICENSE.md"
6
6
  readme = ".github/README.md"
File without changes
File without changes