psaiops 0.3.0__py3-none-any.whl → 0.3.2__py3-none-any.whl

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.
File without changes
@@ -0,0 +1,133 @@
1
+ import functools
2
+
3
+ import gradio
4
+ import torch
5
+ import torch.cuda
6
+
7
+ import psaiops.score.router.lib
8
+
9
+ # META #########################################################################
10
+
11
+ STYLE = '''.white-text span { color: white; }'''
12
+ TITLE = '''Attention Scoring'''
13
+ INTRO = '''Plot the logits of the router for a given prompt.\nUnder construction, only "openai/gpt-oss-20b" is available for now.'''
14
+
15
+ MODEL = 'openai/gpt-oss-20b'
16
+
17
+ # COLORS #######################################################################
18
+
19
+ def create_color_map() -> dict:
20
+ return {
21
+ '-1': '#004444',
22
+ **{str(__i): '#{:02x}0000'.format(int(2.55 * __i)) for __i in range(101)}}
23
+
24
+ # INTRO ########################################################################
25
+
26
+ def create_intro_block(intro: str) -> dict:
27
+ __intro = gradio.Markdown(intro, line_breaks=True)
28
+ return {'intro_block': __intro}
29
+
30
+ # MODEL ########################################################################
31
+
32
+ def create_model_block() -> dict:
33
+ __model = gradio.Dropdown(label='Model', value='openai/gpt-oss-20b', choices=['openai/gpt-oss-20b'], scale=1, allow_custom_value=False, multiselect=False, interactive=True) # 'openai/gpt-oss-120b'
34
+ return {'model_block': __model,}
35
+
36
+ # SAMPLING #####################################################################
37
+
38
+ def create_sampling_block() -> dict:
39
+ __tokens = gradio.Slider(label='Tokens', value=16, minimum=1, maximum=128, step=1, scale=1, interactive=True)
40
+ __topk = gradio.Slider(label='Top K', value=4, minimum=1, maximum=8, step=1, scale=1, interactive=True)
41
+ __topp = gradio.Slider(label='Top P', value=0.9, minimum=0.0, maximum=1.0, step=0.1, scale=1, interactive=True)
42
+ return {
43
+ 'tokens_block': __tokens,
44
+ 'topk_block': __topk,
45
+ 'topp_block': __topp,}
46
+
47
+ # INPUTS #######################################################################
48
+
49
+ def create_inputs_block() -> dict:
50
+ __input = gradio.Textbox(label='Prompt', value='', placeholder='A string of tokens to score.', lines=4, scale=1, show_copy_button=True, interactive=True)
51
+ return {'input_block': __input}
52
+
53
+ # OUTPUTS ######################################################################
54
+
55
+ def create_outputs_block() -> dict:
56
+ __output = gradio.Plot(label='Logits', scale=1)
57
+ return {'output_block': __output,}
58
+
59
+ # SELECT #######################################################################
60
+
61
+ def create_selection_block() -> dict:
62
+ __position = gradio.Slider(label='Token Position', value=-1, minimum=-1, maximum=15, step=1, scale=1, interactive=True) # info='-1 to average on all tokens'
63
+ return {'position_block': __position,}
64
+
65
+ # ACTIONS ######################################################################
66
+
67
+ def create_actions_block() -> dict:
68
+ __process = gradio.Button('Process', variant='primary', size='lg', scale=1, interactive=True)
69
+ return {'process_block': __process,}
70
+
71
+ # STATE ########################################################################
72
+
73
+ def create_state() -> dict:
74
+ return {}
75
+
76
+ # LAYOUT #######################################################################
77
+
78
+ def create_layout(intro: str=INTRO) -> dict:
79
+ __fields = {}
80
+ __fields.update(create_intro_block(intro=intro))
81
+ with gradio.Tabs():
82
+ with gradio.Tab('Score Tokens') as __main_tab:
83
+ __fields.update({'main_tab': __main_tab})
84
+ with gradio.Row(equal_height=True):
85
+ __fields.update(create_inputs_block())
86
+ with gradio.Row(equal_height=True):
87
+ __fields.update(create_outputs_block())
88
+ with gradio.Row(equal_height=True):
89
+ __fields.update(create_selection_block())
90
+ with gradio.Row(equal_height=True):
91
+ __fields.update(create_actions_block())
92
+ with gradio.Tab('Settings') as __settings_tab:
93
+ __fields.update({'settings_tab': __settings_tab})
94
+ with gradio.Column(scale=1):
95
+ with gradio.Row(equal_height=True):
96
+ __fields.update(create_model_block())
97
+ with gradio.Row(equal_height=True):
98
+ __fields.update(create_sampling_block())
99
+ return __fields
100
+
101
+ # EVENTS #######################################################################
102
+
103
+ def update_position_range(value: float, tokens: float) -> dict:
104
+ return gradio.update(maximum=int(tokens) - 1, value=min(int(tokens) - 1, int(value)))
105
+
106
+ # APP ##########################################################################
107
+
108
+ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, model: str=MODEL) -> gradio.Blocks:
109
+ __fields = {}
110
+ with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
111
+ # load the model
112
+ __device = 'cuda' if torch.cuda.is_available() else 'cpu'
113
+ # __model = psaiops.score.router.lib.get_model(name=model, device=__device)
114
+ __tokenizer = psaiops.score.router.lib.get_tokenizer(name=model, device=__device)
115
+ # create the UI
116
+ __fields.update(create_layout(intro=intro))
117
+ # init the state
118
+ __fields.update(create_state())
119
+ # wire the input fields
120
+ __fields['tokens_block'].change(
121
+ fn=update_position_range,
122
+ inputs=[__fields[__k] for __k in ['position_block', 'tokens_block']],
123
+ outputs=__fields['position_block'],
124
+ queue=False,
125
+ show_progress='hidden')
126
+ # gradio application
127
+ return __app
128
+
129
+ # MAIN #########################################################################
130
+
131
+ if __name__ == '__main__':
132
+ __app = create_app()
133
+ __app.launch(share=True, debug=True)
@@ -0,0 +1,66 @@
1
+ import functools
2
+
3
+ import torch
4
+ import transformers
5
+
6
+ import deformers.models.openai.gptoss
7
+
8
+ # LOAD #########################################################################
9
+
10
+ @functools.lru_cache(maxsize=4)
11
+ def get_tokenizer(name: str, device: str='cpu'):
12
+ return transformers.AutoTokenizer.from_pretrained(
13
+ name,
14
+ use_fast=True,
15
+ dtype='auto',
16
+ device_map=device)
17
+
18
+ @functools.lru_cache(maxsize=2)
19
+ def get_model(name: str, device: str='cpu'):
20
+ __model = deformers.models.openai.gptoss.GptOssForCausalInference.from_pretrained(
21
+ name,
22
+ dtype='auto',
23
+ device_map=device)
24
+ # toggle the inference mode (not training)
25
+ __model.eval()
26
+ # transformers model
27
+ return __model
28
+
29
+ # PREPROCESS #####################################################################
30
+
31
+ @functools.lru_cache(maxsize=4)
32
+ def preprocess_token_ids(
33
+ tokenizer_obj: object,
34
+ prompt_str: str,
35
+ device_str: str='cpu'
36
+ ) -> dict:
37
+ # tokenize
38
+ __inputs = tokenizer_obj(prompt_str, return_tensors='pt')
39
+ # move to the main device
40
+ return {__k: __v.to(device_str) for __k, __v in __inputs.items()}
41
+
42
+ # GENERATE #######################################################################
43
+
44
+ def generate_token_ids(
45
+ model_obj: object,
46
+ input_args: dict,
47
+ token_num: int,
48
+ topk_num: int = 4,
49
+ topp_num: float = 0.9,
50
+ ) -> torch.Tensor:
51
+ # generate completion
52
+ with torch.no_grad():
53
+ __outputs = model_obj.generate(
54
+ **input_args,
55
+ max_new_tokens=token_num,
56
+ do_sample=(0.0 < topp_num < 1.0) or (topk_num > 0),
57
+ top_k=topk_num if (topk_num > 0) else None,
58
+ top_p=topp_num if (0.0 < topp_num < 1.0) else None,
59
+ return_dict_in_generate=True,
60
+ output_hidden_states=False,
61
+ output_attentions=False,
62
+ output_scores=False,
63
+ # early_stopping=True,
64
+ use_cache=True)
65
+ # full sequence
66
+ return __outputs.sequences # (1, T)
File without changes
@@ -0,0 +1,157 @@
1
+ import functools
2
+
3
+ import gradio
4
+ import torch
5
+ import torch.cuda
6
+
7
+ import psaiops.score.shapley.lib
8
+
9
+ # META #########################################################################
10
+
11
+ STYLE = '''.white-text span { color: white; }'''
12
+ TITLE = '''Attention Scoring'''
13
+ INTRO = '''Score each token according to their [Shapley value](https://en.wikipedia.org/wiki/Shapley_value).\nUnder construction, only "openai/gpt-oss-20b" is available for now.'''
14
+
15
+ MODEL = 'openai/gpt-oss-20b'
16
+
17
+ # COLORS #######################################################################
18
+
19
+ def create_color_map() -> dict:
20
+ return {
21
+ '-1': '#004444',
22
+ **{str(__i): '#{:02x}0000'.format(int(2.55 * __i)) for __i in range(101)}}
23
+
24
+ # INTRO ########################################################################
25
+
26
+ def create_intro_block(intro: str) -> dict:
27
+ __intro = gradio.Markdown(intro, line_breaks=True)
28
+ return {'intro_block': __intro}
29
+
30
+ # MODEL ########################################################################
31
+
32
+ def create_model_block() -> dict:
33
+ __model = gradio.Dropdown(label='Model', value='openai/gpt-oss-20b', choices=['openai/gpt-oss-20b'], scale=1, allow_custom_value=False, multiselect=False, interactive=True) # 'openai/gpt-oss-120b'
34
+ return {'model_block': __model,}
35
+
36
+ # SAMPLING #####################################################################
37
+
38
+ def create_sampling_block() -> dict:
39
+ __tokens = gradio.Slider(label='Tokens', value=16, minimum=1, maximum=128, step=1, scale=1, interactive=True)
40
+ __topk = gradio.Slider(label='Top K', value=4, minimum=1, maximum=8, step=1, scale=1, interactive=True)
41
+ __topp = gradio.Slider(label='Top P', value=0.9, minimum=0.0, maximum=1.0, step=0.1, scale=1, interactive=True)
42
+ return {
43
+ 'tokens_block': __tokens,
44
+ 'topk_block': __topk,
45
+ 'topp_block': __topp,}
46
+
47
+ # SAMPLING #####################################################################
48
+
49
+ def create_computation_block() -> dict:
50
+ __count = gradio.Slider(label='Sample count', value=4, minimum=1, maximum=16, step=1, scale=1, interactive=True)
51
+ __min = gradio.Slider(label='Min size', value=50, minimum=0, maximum=100, step=1, scale=1, interactive=True)
52
+ __max = gradio.Slider(label='Max size', value=100, minimum=0, maximum=100, step=1, scale=1, interactive=True)
53
+ return {
54
+ 'count_block': __count,
55
+ 'min_block': __min,
56
+ 'max_block': __max,}
57
+
58
+ # INPUTS #######################################################################
59
+
60
+ def create_inputs_block() -> dict:
61
+ __input = gradio.Textbox(label='Prompt', value='', placeholder='A string of tokens to score.', lines=4, scale=1, show_copy_button=True, interactive=True)
62
+ return {'input_block': __input}
63
+
64
+ # OUTPUTS ######################################################################
65
+
66
+ def create_outputs_block() -> dict:
67
+ __output = gradio.HighlightedText(label='Scores', value='', scale=1, interactive=False, show_legend=False, show_inline_category=False, combine_adjacent=False, color_map=create_color_map(), elem_classes='white-text')
68
+ return {'output_block': __output,}
69
+
70
+ # SELECT #######################################################################
71
+
72
+ def create_selection_block() -> dict:
73
+ __position = gradio.Slider(label='Token Position', value=-1, minimum=-1, maximum=15, step=1, scale=1, interactive=True) # info='-1 to average on all tokens'
74
+ __layer = gradio.Slider(label='Layer Depth', value=12, minimum=-1, maximum=23, step=1, scale=1, interactive=True) # info='-1 to average on all layers'
75
+ return {
76
+ 'position_block': __position,
77
+ 'layer_block': __layer,}
78
+
79
+ # ACTIONS ######################################################################
80
+
81
+ def create_actions_block() -> dict:
82
+ __process = gradio.Button('Process', variant='primary', size='lg', scale=1, interactive=True)
83
+ return {'process_block': __process,}
84
+
85
+ # STATE ########################################################################
86
+
87
+ def create_state() -> dict:
88
+ return {}
89
+
90
+ # LAYOUT #######################################################################
91
+
92
+ def create_layout(intro: str=INTRO) -> dict:
93
+ __fields = {}
94
+ __fields.update(create_intro_block(intro=intro))
95
+ with gradio.Tabs():
96
+ with gradio.Tab('Score Tokens') as __main_tab:
97
+ __fields.update({'main_tab': __main_tab})
98
+ with gradio.Row(equal_height=True):
99
+ __fields.update(create_inputs_block())
100
+ __fields.update(create_outputs_block())
101
+ with gradio.Row(equal_height=True):
102
+ __fields.update(create_selection_block())
103
+ with gradio.Row(equal_height=True):
104
+ __fields.update(create_actions_block())
105
+ with gradio.Tab('Settings') as __settings_tab:
106
+ __fields.update({'settings_tab': __settings_tab})
107
+ with gradio.Column(scale=1):
108
+ with gradio.Row(equal_height=True):
109
+ __fields.update(create_model_block())
110
+ with gradio.Row(equal_height=True):
111
+ __fields.update(create_sampling_block())
112
+ with gradio.Row(equal_height=True):
113
+ __fields.update(create_computation_block())
114
+ return __fields
115
+
116
+ # EVENTS #######################################################################
117
+
118
+ def update_layer_range(value: float, model: str) -> dict:
119
+ return gradio.update(maximum=35, value=min(35, int(value))) if '120b' in model else gradio.update(maximum=23, value=min(23, int(value)))
120
+
121
+ def update_position_range(value: float, tokens: float) -> dict:
122
+ return gradio.update(maximum=int(tokens) - 1, value=min(int(tokens) - 1, int(value)))
123
+
124
+ # APP ##########################################################################
125
+
126
+ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, model: str=MODEL) -> gradio.Blocks:
127
+ __fields = {}
128
+ with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
129
+ # load the model
130
+ __device = 'cuda' if torch.cuda.is_available() else 'cpu'
131
+ # __model = psaiops.score.shapley.lib.get_model(name=model, device=__device)
132
+ __tokenizer = psaiops.score.shapley.lib.get_tokenizer(name=model, device=__device)
133
+ # create the UI
134
+ __fields.update(create_layout(intro=intro))
135
+ # init the state
136
+ __fields.update(create_state())
137
+ # wire the input fields
138
+ __fields['tokens_block'].change(
139
+ fn=update_position_range,
140
+ inputs=[__fields[__k] for __k in ['position_block', 'tokens_block']],
141
+ outputs=__fields['position_block'],
142
+ queue=False,
143
+ show_progress='hidden')
144
+ __fields['model_block'].change(
145
+ fn=update_layer_range,
146
+ inputs=[__fields[__k] for __k in ['layer_block', 'model_block']],
147
+ outputs=__fields['layer_block'],
148
+ queue=False,
149
+ show_progress='hidden')
150
+ # gradio application
151
+ return __app
152
+
153
+ # MAIN #########################################################################
154
+
155
+ if __name__ == '__main__':
156
+ __app = create_app()
157
+ __app.launch(share=True, debug=True)
@@ -0,0 +1,66 @@
1
+ import functools
2
+
3
+ import torch
4
+ import transformers
5
+
6
+ import deformers.models.openai.gptoss
7
+
8
+ # LOAD #########################################################################
9
+
10
+ @functools.lru_cache(maxsize=4)
11
+ def get_tokenizer(name: str, device: str='cpu'):
12
+ return transformers.AutoTokenizer.from_pretrained(
13
+ name,
14
+ use_fast=True,
15
+ dtype='auto',
16
+ device_map=device)
17
+
18
+ @functools.lru_cache(maxsize=2)
19
+ def get_model(name: str, device: str='cpu'):
20
+ __model = deformers.models.openai.gptoss.GptOssForCausalInference.from_pretrained(
21
+ name,
22
+ dtype='auto',
23
+ device_map=device)
24
+ # toggle the inference mode (not training)
25
+ __model.eval()
26
+ # transformers model
27
+ return __model
28
+
29
+ # PREPROCESS #####################################################################
30
+
31
+ @functools.lru_cache(maxsize=4)
32
+ def preprocess_token_ids(
33
+ tokenizer_obj: object,
34
+ prompt_str: str,
35
+ device_str: str='cpu'
36
+ ) -> dict:
37
+ # tokenize
38
+ __inputs = tokenizer_obj(prompt_str, return_tensors='pt')
39
+ # move to the main device
40
+ return {__k: __v.to(device_str) for __k, __v in __inputs.items()}
41
+
42
+ # GENERATE #######################################################################
43
+
44
+ def generate_token_ids(
45
+ model_obj: object,
46
+ input_args: dict,
47
+ token_num: int,
48
+ topk_num: int = 4,
49
+ topp_num: float = 0.9,
50
+ ) -> torch.Tensor:
51
+ # generate completion
52
+ with torch.no_grad():
53
+ __outputs = model_obj.generate(
54
+ **input_args,
55
+ max_new_tokens=token_num,
56
+ do_sample=(0.0 < topp_num < 1.0) or (topk_num > 0),
57
+ top_k=topk_num if (topk_num > 0) else None,
58
+ top_p=topp_num if (0.0 < topp_num < 1.0) else None,
59
+ return_dict_in_generate=True,
60
+ output_hidden_states=False,
61
+ output_attentions=False,
62
+ output_scores=False,
63
+ # early_stopping=True,
64
+ use_cache=True)
65
+ # full sequence
66
+ return __outputs.sequences # (1, T)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: psaiops
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Web apps to inspect & engineer NN activations.
5
5
  License: .github/LICENSE.md
6
6
  Author: apehex
@@ -16,7 +16,13 @@ psaiops/score/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  psaiops/score/attention/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  psaiops/score/attention/app.py,sha256=UK6-11xUP9S7_8ryZiqFaGfJvG_scS-NzU6QJLEVbEs,13479
18
18
  psaiops/score/attention/lib.py,sha256=j9p7ZXhkh5Y9VDeIe6TPUUrHRkwp1Y6P22iciaaKdL4,6932
19
+ psaiops/score/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ psaiops/score/router/app.py,sha256=v2z4Qjho4naVmPandsX2nWwaCElwaWHnSVM0g5UDG1c,5640
21
+ psaiops/score/router/lib.py,sha256=Cra3jksyqCunCRLsQ88ts0RITU7kC8LgudjIdWfhmyE,1996
22
+ psaiops/score/shapley/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ psaiops/score/shapley/app.py,sha256=eZX-Hw_tj9x7lXyazxVMwBlRPaOHS6jxWcnOdnLzAz4,7151
24
+ psaiops/score/shapley/lib.py,sha256=Cra3jksyqCunCRLsQ88ts0RITU7kC8LgudjIdWfhmyE,1996
19
25
  psaiops/steer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- psaiops-0.3.0.dist-info/METADATA,sha256=lKbJIDRYFfShvGp8gSFuYtqKKhZW_e6tbcMXdgaodSs,1318
21
- psaiops-0.3.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
22
- psaiops-0.3.0.dist-info/RECORD,,
26
+ psaiops-0.3.2.dist-info/METADATA,sha256=jM6uT4ydy8THc_LZftgwj23aruOxmh0QrJqXsWclNtM,1318
27
+ psaiops-0.3.2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
28
+ psaiops-0.3.2.dist-info/RECORD,,