psaiops 0.3.2__py3-none-any.whl → 0.4.0__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.
- psaiops/combine/app.py +366 -0
- psaiops/common/data.py +8 -0
- psaiops/common/model.py +45 -0
- psaiops/common/tokenizer.py +41 -0
- psaiops/compose/contrast/app.py +4 -2
- psaiops/compose/contrast/lib.py +3 -38
- psaiops/compose/maths/app.py +8 -5
- psaiops/compose/maths/lib.py +0 -41
- psaiops/score/attention/app.py +7 -5
- psaiops/score/attention/lib.py +7 -82
- psaiops/score/residual/app.py +290 -0
- psaiops/score/residual/lib.py +134 -0
- psaiops/score/router/app.py +161 -13
- psaiops/score/router/lib.py +50 -57
- psaiops/score/shapley/app.py +5 -4
- psaiops/score/shapley/lib.py +0 -65
- psaiops/score/similarity/__init__.py +0 -0
- psaiops/score/similarity/app.py +152 -0
- psaiops/score/similarity/lib.py +1 -0
- {psaiops-0.3.2.dist-info → psaiops-0.4.0.dist-info}/METADATA +14 -19
- psaiops-0.4.0.dist-info/RECORD +36 -0
- {psaiops-0.3.2.dist-info → psaiops-0.4.0.dist-info}/WHEEL +1 -1
- psaiops-0.4.0.dist-info/licenses/.github/LICENSE.md +661 -0
- psaiops/common/dropdown.py +0 -19
- psaiops-0.3.2.dist-info/RECORD +0 -28
- /psaiops/{steer → score/residual}/__init__.py +0 -0
psaiops/combine/app.py
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import itertools
|
|
3
|
+
|
|
4
|
+
import gradio
|
|
5
|
+
import pandas
|
|
6
|
+
import torch
|
|
7
|
+
import torch.cuda
|
|
8
|
+
|
|
9
|
+
import psaiops.common.tokenizer
|
|
10
|
+
import psaiops.common.data
|
|
11
|
+
|
|
12
|
+
# META #########################################################################
|
|
13
|
+
|
|
14
|
+
MODEL = 'openai/gpt-oss-20b'
|
|
15
|
+
|
|
16
|
+
STYLE = '''.giga-text input { font-size: 32px; }'''
|
|
17
|
+
TITLE = '''Combine Datasets'''
|
|
18
|
+
INTRO = '''Combine and wrap prompts to form new datasets.'''
|
|
19
|
+
|
|
20
|
+
COUNT = 8
|
|
21
|
+
|
|
22
|
+
# TEMPLATE #####################################################################
|
|
23
|
+
|
|
24
|
+
ROLES = ['system', 'developer', 'user', 'assistant', 'tool']
|
|
25
|
+
CHANNELS = ['analysis', 'commentary', 'final']
|
|
26
|
+
|
|
27
|
+
# INTRO ########################################################################
|
|
28
|
+
|
|
29
|
+
def create_intro_block(intro: str) -> dict:
|
|
30
|
+
__intro = gradio.Markdown(intro, line_breaks=True)
|
|
31
|
+
return {'intro_block': __intro}
|
|
32
|
+
|
|
33
|
+
# MODEL ########################################################################
|
|
34
|
+
|
|
35
|
+
def create_template_block() -> dict:
|
|
36
|
+
__template = gradio.Dropdown(label='Template', value='openai/gpt-oss-20b', choices=['openai/gpt-oss-20b', ''], scale=1, allow_custom_value=False, multiselect=False, interactive=True)
|
|
37
|
+
return {
|
|
38
|
+
'template_block': __template,}
|
|
39
|
+
|
|
40
|
+
# SAMPLING #####################################################################
|
|
41
|
+
|
|
42
|
+
def create_huggingface_block() -> dict:
|
|
43
|
+
__token = gradio.Textbox(label='Token', value='', placeholder='Hugging Face authentication token.', lines=1, max_lines=1, scale=4, show_label=True, show_copy_button=False, interactive=True)
|
|
44
|
+
return {
|
|
45
|
+
'token_block': __token,}
|
|
46
|
+
|
|
47
|
+
# SAMPLING #####################################################################
|
|
48
|
+
|
|
49
|
+
def create_source_block() -> dict:
|
|
50
|
+
__search = gradio.Dropdown(label='Search', value='', choices=[''], scale=7, allow_custom_value=True, multiselect=False, interactive=True)
|
|
51
|
+
__append = gradio.Button(value='>', variant='primary', size='lg', scale=1, interactive=True)
|
|
52
|
+
__dataset = gradio.Dropdown(label='Datasets', value='', choices=[''], scale=8, allow_custom_value=False, multiselect=True, interactive=True)
|
|
53
|
+
return {
|
|
54
|
+
'search_block': __search,
|
|
55
|
+
'append_block': __append,
|
|
56
|
+
'sources_block': __dataset,}
|
|
57
|
+
|
|
58
|
+
# SAMPLING #####################################################################
|
|
59
|
+
|
|
60
|
+
def create_download_block() -> dict:
|
|
61
|
+
__download = gradio.Button(value='Download', variant='primary', size='lg', scale=1, interactive=True)
|
|
62
|
+
return {
|
|
63
|
+
'download_block': __download,}
|
|
64
|
+
|
|
65
|
+
# ACTIONS ######################################################################
|
|
66
|
+
|
|
67
|
+
def create_meta_block() -> dict:
|
|
68
|
+
__name = gradio.Textbox(label='Path', value='', placeholder='Dataset ID: user/name.', lines=1, max_lines=1, scale=1, show_label=True, show_copy_button=False, interactive=True)
|
|
69
|
+
__col0 = gradio.Textbox(label='Column 0', value='', placeholder='Name of the column 0.', lines=1, max_lines=1, scale=1, show_label=True, show_copy_button=False, interactive=True)
|
|
70
|
+
__col1 = gradio.Textbox(label='Column 1', value='', placeholder='Name of the column 1.', lines=1, max_lines=1, scale=1, show_label=True, show_copy_button=False, interactive=True)
|
|
71
|
+
return {
|
|
72
|
+
'name_block': __name,
|
|
73
|
+
'column_0_block': __col0,
|
|
74
|
+
'column_1_block': __col1,}
|
|
75
|
+
|
|
76
|
+
# INPUTS #######################################################################
|
|
77
|
+
|
|
78
|
+
def create_inputs_row(index: int=0) -> dict:
|
|
79
|
+
with gradio.Row(equal_height=True, visible=(index == 0)) as __row:
|
|
80
|
+
__role = gradio.Dropdown(
|
|
81
|
+
type='value',
|
|
82
|
+
label=f'Role',
|
|
83
|
+
value='user',
|
|
84
|
+
choices=[__r for __r in ROLES],
|
|
85
|
+
# elem_classes='giga-text',
|
|
86
|
+
scale=1,
|
|
87
|
+
show_label=(index == 0),
|
|
88
|
+
allow_custom_value=False,
|
|
89
|
+
multiselect=False,
|
|
90
|
+
interactive=True,
|
|
91
|
+
visible=(index == 0))
|
|
92
|
+
__channel = gradio.Dropdown(
|
|
93
|
+
type='value',
|
|
94
|
+
label=f'Channel',
|
|
95
|
+
value='final',
|
|
96
|
+
choices=[__c for __c in CHANNELS],
|
|
97
|
+
# elem_classes='giga-text',
|
|
98
|
+
scale=1,
|
|
99
|
+
show_label=(index == 0),
|
|
100
|
+
allow_custom_value=False,
|
|
101
|
+
multiselect=False,
|
|
102
|
+
interactive=True,
|
|
103
|
+
visible=(index == 0))
|
|
104
|
+
__source = gradio.Dropdown(
|
|
105
|
+
type='value',
|
|
106
|
+
label=f'Source',
|
|
107
|
+
value='mnaual',
|
|
108
|
+
choices=['manual'],
|
|
109
|
+
# elem_classes='giga-text',
|
|
110
|
+
scale=4,
|
|
111
|
+
show_label=(index == 0),
|
|
112
|
+
allow_custom_value=False,
|
|
113
|
+
multiselect=False,
|
|
114
|
+
interactive=True,
|
|
115
|
+
visible=(index == 0))
|
|
116
|
+
__content = gradio.Textbox(
|
|
117
|
+
label=f'Prompt',
|
|
118
|
+
value='',
|
|
119
|
+
placeholder='Some text.',
|
|
120
|
+
lines=1,
|
|
121
|
+
max_lines=1,
|
|
122
|
+
scale=9,
|
|
123
|
+
show_label=(index == 0),
|
|
124
|
+
show_copy_button=True,
|
|
125
|
+
interactive=True,
|
|
126
|
+
visible=(index == 0))
|
|
127
|
+
__hide = gradio.Button(
|
|
128
|
+
value='X',
|
|
129
|
+
variant='secondary',
|
|
130
|
+
size='lg',
|
|
131
|
+
scale=1,
|
|
132
|
+
interactive=True,
|
|
133
|
+
visible=(index == 0))
|
|
134
|
+
return {
|
|
135
|
+
f'row_{index}_block': __row,
|
|
136
|
+
f'role_{index}_block': __role,
|
|
137
|
+
f'channel_{index}_block': __channel,
|
|
138
|
+
f'source_{index}_block': __source,
|
|
139
|
+
f'content_{index}_block': __content,
|
|
140
|
+
f'button_{index}_block': __hide,}
|
|
141
|
+
|
|
142
|
+
# OUTPUTS ######################################################################
|
|
143
|
+
|
|
144
|
+
def create_outputs_block() -> dict:
|
|
145
|
+
__output = gradio.Textbox(label='Sample', value='', placeholder='Resulting combination of the prompts.', lines=2, max_lines=8, scale=1, show_label=True, show_copy_button=True, interactive=False)
|
|
146
|
+
return {'output_block': __output,}
|
|
147
|
+
|
|
148
|
+
# ACTIONS ######################################################################
|
|
149
|
+
|
|
150
|
+
def create_action_block() -> dict:
|
|
151
|
+
__show = gradio.Button(value='Add', variant='primary', size='lg', scale=1, interactive=True)
|
|
152
|
+
__upload = gradio.Button(value='Upload', variant='primary', size='lg', scale=1, interactive=True)
|
|
153
|
+
return {
|
|
154
|
+
'show_block': __show,
|
|
155
|
+
'upload_block': __upload,}
|
|
156
|
+
|
|
157
|
+
# TABLE ########################################################################
|
|
158
|
+
|
|
159
|
+
def create_table_block() -> dict:
|
|
160
|
+
__table = gradio.DataFrame(label='Table', type='numpy', headers=None, row_count=4, col_count=256, scale=1, interactive=False)
|
|
161
|
+
return {'table_block': __table,}
|
|
162
|
+
|
|
163
|
+
# STATE ########################################################################
|
|
164
|
+
|
|
165
|
+
def default_state(visible: bool=False) -> dict:
|
|
166
|
+
return {'visible': visible, 'role': 'user', 'channel': 'final', 'source': 'manual', 'content': ''}
|
|
167
|
+
|
|
168
|
+
def create_state(limit: int=COUNT) -> dict:
|
|
169
|
+
return {
|
|
170
|
+
'cache_block': gradio.State(
|
|
171
|
+
[default_state(True)] + [default_state(False) for _ in range(limit - 1)])}
|
|
172
|
+
|
|
173
|
+
# LAYOUT #######################################################################
|
|
174
|
+
|
|
175
|
+
def create_layout(intro: str=INTRO, limit: int=COUNT) -> dict:
|
|
176
|
+
__fields = {}
|
|
177
|
+
__fields.update(create_intro_block(intro=intro))
|
|
178
|
+
with gradio.Row(equal_height=True):
|
|
179
|
+
__fields.update(create_meta_block())
|
|
180
|
+
with gradio.Tabs():
|
|
181
|
+
with gradio.Tab('Column 0') as __col0_tab:
|
|
182
|
+
__fields.update({'column_0_tab': __col0_tab})
|
|
183
|
+
for __i in range(limit):
|
|
184
|
+
__fields.update(create_inputs_row(index=__i))
|
|
185
|
+
with gradio.Row(equal_height=True):
|
|
186
|
+
__fields.update(create_outputs_block())
|
|
187
|
+
with gradio.Row(equal_height=True):
|
|
188
|
+
__fields.update(create_action_block())
|
|
189
|
+
with gradio.Tab('Details') as __details_tab:
|
|
190
|
+
__fields.update({'details_tab': __details_tab})
|
|
191
|
+
with gradio.Row(equal_height=True):
|
|
192
|
+
__fields.update(create_table_block())
|
|
193
|
+
with gradio.Tab('Settings') as __settings_tab:
|
|
194
|
+
__fields.update({'settings_tab': __settings_tab})
|
|
195
|
+
with gradio.Row(equal_height=True):
|
|
196
|
+
__fields.update(create_template_block())
|
|
197
|
+
with gradio.Row(equal_height=True):
|
|
198
|
+
__fields.update(create_huggingface_block())
|
|
199
|
+
with gradio.Row(equal_height=True):
|
|
200
|
+
__fields.update(create_source_block())
|
|
201
|
+
with gradio.Row(equal_height=True):
|
|
202
|
+
__fields.update(create_download_block())
|
|
203
|
+
return __fields
|
|
204
|
+
|
|
205
|
+
# DYNAMIC ######################################################################
|
|
206
|
+
|
|
207
|
+
def get_input_rows(inputs: dict, limit: int=COUNT) -> list:
|
|
208
|
+
return list(itertools.chain.from_iterable([
|
|
209
|
+
[
|
|
210
|
+
inputs.get(f'row_{__i}_block', None),
|
|
211
|
+
inputs.get(f'role_{__i}_block', None),
|
|
212
|
+
inputs.get(f'channel_{__i}_block', None),
|
|
213
|
+
inputs.get(f'source_{__i}_block', None),
|
|
214
|
+
inputs.get(f'content_{__i}_block', None),
|
|
215
|
+
inputs.get(f'button_{__i}_block', None),]
|
|
216
|
+
for __i in range(limit)]))
|
|
217
|
+
|
|
218
|
+
def render_input_rows(rows: list) -> list:
|
|
219
|
+
return list(itertools.chain.from_iterable([
|
|
220
|
+
[
|
|
221
|
+
gradio.update(visible=__r.get('visible', False)),
|
|
222
|
+
gradio.update(visible=__r.get('visible', False), value=__r.get('role', 'user')),
|
|
223
|
+
gradio.update(visible=__r.get('visible', False), value=__r.get('channel', 'final')),
|
|
224
|
+
gradio.update(visible=__r.get('visible', False), value=__r.get('source', 'manual')),
|
|
225
|
+
gradio.update(visible=__r.get('visible', False), value=__r.get('content', '')),
|
|
226
|
+
gradio.update(visible=__r.get('visible', False))]
|
|
227
|
+
for __r in rows]))
|
|
228
|
+
|
|
229
|
+
def show_input_row(rows: list) -> tuple:
|
|
230
|
+
__count = 0
|
|
231
|
+
__rows = list(rows)
|
|
232
|
+
for __i in range(len(__rows)):
|
|
233
|
+
# count the number of hidden rows (before changing their state)
|
|
234
|
+
__count = __count + int(not __rows[__i]['visible'])
|
|
235
|
+
# all the visible rows stay the same and the first hidden row is toggled
|
|
236
|
+
__rows[__i]['visible'] = __rows[__i]['visible'] or (__count < 2)
|
|
237
|
+
# update state and components
|
|
238
|
+
return __rows, *render_input_rows(__rows)
|
|
239
|
+
|
|
240
|
+
def hide_input_row(rows: list, index: int) -> tuple:
|
|
241
|
+
__rows = list(rows)
|
|
242
|
+
# always show the first row
|
|
243
|
+
if 0 < index < len(__rows):
|
|
244
|
+
# remove the target row
|
|
245
|
+
__rows.pop(index)
|
|
246
|
+
# keep the number of rows constant
|
|
247
|
+
__rows.append(default_state(False))
|
|
248
|
+
# update state and components
|
|
249
|
+
return __rows, *render_input_rows(__rows)
|
|
250
|
+
|
|
251
|
+
# EVENTS #######################################################################
|
|
252
|
+
|
|
253
|
+
def update_input_cache(cache: list, index: int, value: any, field: str) -> list:
|
|
254
|
+
__cache = list(cache)
|
|
255
|
+
__cache[index][field] = value
|
|
256
|
+
return __cache
|
|
257
|
+
|
|
258
|
+
def update_role_cache(cache: list, index: int, value: any) -> list:
|
|
259
|
+
return update_input_cache(cache=cache, index=int(index), value=str(value), field='role')
|
|
260
|
+
|
|
261
|
+
def update_channel_cache(cache: list, index: int, value: any) -> list:
|
|
262
|
+
return update_input_cache(cache=cache, index=int(index), value=str(value), field='channel')
|
|
263
|
+
|
|
264
|
+
def update_source_cache(cache: list, index: int, value: any) -> list:
|
|
265
|
+
return update_input_cache(cache=cache, index=int(index), value=str(value), field='source')
|
|
266
|
+
|
|
267
|
+
def update_content_cache(cache: list, index: int, value: any) -> list:
|
|
268
|
+
return update_input_cache(cache=cache, index=int(index), value=str(value), field='content')
|
|
269
|
+
|
|
270
|
+
def update_table_data(tokenizer: object) -> callable:
|
|
271
|
+
# called with unpacked arguments
|
|
272
|
+
def __update_table_data(*prompts: list) -> list:
|
|
273
|
+
# array of token IDs
|
|
274
|
+
__outputs = tokenizer(prompts, return_tensors='pt', padding=True)
|
|
275
|
+
# array of token strings
|
|
276
|
+
__tokens = [tokenizer.convert_ids_to_tokens(__s) for __s in __outputs['input_ids']]
|
|
277
|
+
# shift the special characters
|
|
278
|
+
return [[__t.replace(chr(0x0120), ' ').replace(chr(0x010a), '\\n') for __t in __s] for __s in __tokens]
|
|
279
|
+
# fixed to a given tokenizer
|
|
280
|
+
return __update_table_data
|
|
281
|
+
|
|
282
|
+
def update_dataset_list(data: str) -> dict:
|
|
283
|
+
__datasets = []
|
|
284
|
+
if len(data) > 3:
|
|
285
|
+
__datasets = psaiops.common.data.query_huggingface(target=data, label='dataset', limit=8)
|
|
286
|
+
return gradio.update(choices=__datasets, visible=True)
|
|
287
|
+
|
|
288
|
+
# APP ##########################################################################
|
|
289
|
+
|
|
290
|
+
def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, limit: int=COUNT, model: str=MODEL) -> gradio.Blocks:
|
|
291
|
+
__inputs = {}
|
|
292
|
+
with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
|
|
293
|
+
# load the tokenizer
|
|
294
|
+
__tokenizer = psaiops.common.tokenizer.get_tokenizer(name=model, device='cpu')
|
|
295
|
+
# create the UI
|
|
296
|
+
__inputs.update(create_layout(intro=intro, limit=limit))
|
|
297
|
+
# init the state
|
|
298
|
+
__inputs.update(create_state(limit=limit))
|
|
299
|
+
# apply the configuration
|
|
300
|
+
__format = update_table_data(tokenizer=__tokenizer)
|
|
301
|
+
# show hidden row
|
|
302
|
+
__inputs['show_block'].click(
|
|
303
|
+
fn=show_input_row,
|
|
304
|
+
inputs=[__inputs['cache_block']],
|
|
305
|
+
outputs=[__inputs['cache_block']] + get_input_rows(inputs=__inputs, limit=limit),
|
|
306
|
+
queue=False,
|
|
307
|
+
show_progress='hidden')
|
|
308
|
+
# update the table TODO
|
|
309
|
+
__inputs['details_tab'].select(
|
|
310
|
+
fn=__format,
|
|
311
|
+
inputs=[__inputs[f'content_{__i}_block'] for __i in range(limit)] + [__inputs['output_block']],
|
|
312
|
+
outputs=__inputs['table_block'],
|
|
313
|
+
queue=False,
|
|
314
|
+
show_progress='hidden')
|
|
315
|
+
# fetch the list of matching datasets
|
|
316
|
+
__inputs['search_block'].change(
|
|
317
|
+
fn=update_dataset_list,
|
|
318
|
+
inputs=__inputs['search_block'],
|
|
319
|
+
outputs=__inputs['search_block'],
|
|
320
|
+
queue=False,
|
|
321
|
+
show_progress='hidden')
|
|
322
|
+
# link each row of inputs to the cache
|
|
323
|
+
for __i in range(limit):
|
|
324
|
+
# update the target role in the cache
|
|
325
|
+
__inputs[f'role_{__i}_block'].change(
|
|
326
|
+
fn=update_role_cache,
|
|
327
|
+
inputs=[__inputs['cache_block'], gradio.State(__i), __inputs[f'role_{__i}_block']],
|
|
328
|
+
outputs=__inputs['cache_block'],
|
|
329
|
+
queue=False,
|
|
330
|
+
show_progress='hidden')
|
|
331
|
+
# update the target channel in the cache
|
|
332
|
+
__inputs[f'channel_{__i}_block'].change(
|
|
333
|
+
fn=update_channel_cache,
|
|
334
|
+
inputs=[__inputs['cache_block'], gradio.State(__i), __inputs[f'channel_{__i}_block']],
|
|
335
|
+
outputs=__inputs['cache_block'],
|
|
336
|
+
queue=False,
|
|
337
|
+
show_progress='hidden')
|
|
338
|
+
# update the target column in the cache
|
|
339
|
+
__inputs[f'source_{__i}_block'].change(
|
|
340
|
+
fn=update_source_cache,
|
|
341
|
+
inputs=[__inputs['cache_block'], gradio.State(__i), __inputs[f'source_{__i}_block']],
|
|
342
|
+
outputs=__inputs['cache_block'],
|
|
343
|
+
queue=False,
|
|
344
|
+
show_progress='hidden')
|
|
345
|
+
# update the target content in the cache
|
|
346
|
+
__inputs[f'content_{__i}_block'].change(
|
|
347
|
+
fn=update_content_cache,
|
|
348
|
+
inputs=[__inputs['cache_block'], gradio.State(__i), __inputs[f'content_{__i}_block']],
|
|
349
|
+
outputs=__inputs['cache_block'],
|
|
350
|
+
queue=False,
|
|
351
|
+
show_progress='hidden')
|
|
352
|
+
# hide the target row
|
|
353
|
+
__inputs[f'button_{__i}_block'].click(
|
|
354
|
+
fn=hide_input_row,
|
|
355
|
+
inputs=[__inputs['cache_block'], gradio.State(__i)],
|
|
356
|
+
outputs=[__inputs['cache_block']] + get_input_rows(inputs=__inputs, limit=limit),
|
|
357
|
+
queue=False,
|
|
358
|
+
show_progress='hidden')
|
|
359
|
+
# gradio application
|
|
360
|
+
return __app
|
|
361
|
+
|
|
362
|
+
# MAIN #########################################################################
|
|
363
|
+
|
|
364
|
+
if __name__ == '__main__':
|
|
365
|
+
__app = create_app()
|
|
366
|
+
__app.launch(share=True, debug=True)
|
psaiops/common/data.py
CHANGED
|
@@ -21,3 +21,11 @@ def query_huggingface(target: str, label: str='model', limit: int=16, endpoint:
|
|
|
21
21
|
__results = []
|
|
22
22
|
# list of strings
|
|
23
23
|
return __results
|
|
24
|
+
|
|
25
|
+
# EXAMPLES #####################################################################
|
|
26
|
+
|
|
27
|
+
def update_dropdown(target: str, label: str) -> dict:
|
|
28
|
+
# query huggingface
|
|
29
|
+
__data = psaiops.elements.data.query_huggingface(target=target, label=label, limit=16)
|
|
30
|
+
# list choices in the dropdown
|
|
31
|
+
return gradio.update(choices=__data, visible=True)
|
psaiops/common/model.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
|
|
5
|
+
import deformers.models.openai.gptoss
|
|
6
|
+
|
|
7
|
+
# LOAD #########################################################################
|
|
8
|
+
|
|
9
|
+
@functools.lru_cache(maxsize=1)
|
|
10
|
+
def get_model(name: str, device: str='cpu'):
|
|
11
|
+
__model = deformers.models.openai.gptoss.GptOssForCausalInference.from_pretrained(
|
|
12
|
+
name,
|
|
13
|
+
dtype='auto',
|
|
14
|
+
device_map=device)
|
|
15
|
+
# toggle the inference mode (not training)
|
|
16
|
+
__model.eval()
|
|
17
|
+
# transformers model
|
|
18
|
+
return __model
|
|
19
|
+
|
|
20
|
+
# GENERATE #######################################################################
|
|
21
|
+
|
|
22
|
+
@functools.lru_cache(maxsize=32)
|
|
23
|
+
def generate_token_ids(
|
|
24
|
+
model_obj: object,
|
|
25
|
+
input_args: dict,
|
|
26
|
+
token_num: int,
|
|
27
|
+
topk_num: int = 4,
|
|
28
|
+
topp_num: float = 0.9,
|
|
29
|
+
) -> torch.Tensor:
|
|
30
|
+
# generate completion
|
|
31
|
+
with torch.no_grad():
|
|
32
|
+
__outputs = model_obj.generate(
|
|
33
|
+
**input_args,
|
|
34
|
+
max_new_tokens=token_num,
|
|
35
|
+
do_sample=(0.0 < topp_num < 1.0) or (topk_num > 0),
|
|
36
|
+
top_k=topk_num if (topk_num > 0) else None,
|
|
37
|
+
top_p=topp_num if (0.0 < topp_num < 1.0) else None,
|
|
38
|
+
return_dict_in_generate=True,
|
|
39
|
+
output_hidden_states=False,
|
|
40
|
+
output_attentions=False,
|
|
41
|
+
output_scores=False,
|
|
42
|
+
early_stopping=True,
|
|
43
|
+
use_cache=True)
|
|
44
|
+
# full sequence
|
|
45
|
+
return __outputs.sequences # (1, T)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
import transformers
|
|
5
|
+
|
|
6
|
+
# LOAD #########################################################################
|
|
7
|
+
|
|
8
|
+
@functools.lru_cache(maxsize=4)
|
|
9
|
+
def get_tokenizer(name: str, device: str='cpu'):
|
|
10
|
+
return transformers.AutoTokenizer.from_pretrained(
|
|
11
|
+
name,
|
|
12
|
+
use_fast=True,
|
|
13
|
+
dtype='auto',
|
|
14
|
+
device_map=device)
|
|
15
|
+
|
|
16
|
+
# PREPROCESS #####################################################################
|
|
17
|
+
|
|
18
|
+
@functools.lru_cache(maxsize=32)
|
|
19
|
+
def preprocess_token_ids(
|
|
20
|
+
tokenizer_obj: object,
|
|
21
|
+
prompt_str: str,
|
|
22
|
+
device_str: str='cpu'
|
|
23
|
+
) -> dict:
|
|
24
|
+
# tokenize
|
|
25
|
+
__inputs = tokenizer_obj(prompt_str, return_tensors='pt')
|
|
26
|
+
# move to the main device
|
|
27
|
+
return {__k: __v.to(device_str) for __k, __v in __inputs.items()}
|
|
28
|
+
|
|
29
|
+
# POSTPROCESS ####################################################################
|
|
30
|
+
|
|
31
|
+
@functools.lru_cache(maxsize=32)
|
|
32
|
+
def postprocess_token_ids(
|
|
33
|
+
tokenizer_obj: object,
|
|
34
|
+
token_data: torch.Tensor,
|
|
35
|
+
) -> list:
|
|
36
|
+
# remove the batch axis
|
|
37
|
+
__indices = token_data.squeeze().tolist()
|
|
38
|
+
# back to token strings
|
|
39
|
+
__tokens = tokenizer_obj.convert_ids_to_tokens(__indices)
|
|
40
|
+
# normalize the tokens
|
|
41
|
+
return [__t.replace(chr(0x0120), ' ').replace(chr(0x010a), '\n') for __t in __tokens]
|
psaiops/compose/contrast/app.py
CHANGED
|
@@ -5,6 +5,8 @@ import pandas
|
|
|
5
5
|
import torch
|
|
6
6
|
import torch.cuda
|
|
7
7
|
|
|
8
|
+
import psaiops.common.model
|
|
9
|
+
import psaiops.common.tokenizer
|
|
8
10
|
import psaiops.compose.contrast.lib
|
|
9
11
|
|
|
10
12
|
# META #########################################################################
|
|
@@ -155,8 +157,8 @@ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, model: str=
|
|
|
155
157
|
with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
|
|
156
158
|
# load the model
|
|
157
159
|
__device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
|
158
|
-
__model = psaiops.
|
|
159
|
-
__tokenizer = psaiops.
|
|
160
|
+
__model = psaiops.common.model.get_model(name=model, device=__device)
|
|
161
|
+
__tokenizer = psaiops.common.tokenizer.get_tokenizer(name=model, device=__device)
|
|
160
162
|
# adapt the computing functions
|
|
161
163
|
__compute = functools.partial(psaiops.compose.contrast.lib.steer_model_output, model_obj=__model, tokenizer_obj=__tokenizer, device_str=__device)
|
|
162
164
|
__format = functools.partial(update_table_data, tokenizer=__tokenizer)
|
psaiops/compose/contrast/lib.py
CHANGED
|
@@ -2,44 +2,9 @@ import functools
|
|
|
2
2
|
|
|
3
3
|
import torch
|
|
4
4
|
import torch.nn.modules
|
|
5
|
-
import transformers
|
|
6
5
|
|
|
7
|
-
import deformers.models.openai.gptoss
|
|
8
6
|
import mlable.shapes
|
|
9
|
-
|
|
10
|
-
# LOAD #########################################################################
|
|
11
|
-
|
|
12
|
-
@functools.lru_cache(maxsize=4)
|
|
13
|
-
def get_tokenizer(name: str, device: str='cpu'):
|
|
14
|
-
return transformers.AutoTokenizer.from_pretrained(
|
|
15
|
-
name,
|
|
16
|
-
use_fast=True,
|
|
17
|
-
dtype='auto',
|
|
18
|
-
device_map=device)
|
|
19
|
-
|
|
20
|
-
@functools.lru_cache(maxsize=2)
|
|
21
|
-
def get_model(name: str, device: str='cpu'):
|
|
22
|
-
__model = deformers.models.openai.gptoss.GptOssForCausalInference.from_pretrained(
|
|
23
|
-
name,
|
|
24
|
-
dtype='auto',
|
|
25
|
-
device_map=device)
|
|
26
|
-
# toggle the inference mode (not training)
|
|
27
|
-
__model.eval()
|
|
28
|
-
# transformers model
|
|
29
|
-
return __model
|
|
30
|
-
|
|
31
|
-
# PREPROCESS #####################################################################
|
|
32
|
-
|
|
33
|
-
@functools.lru_cache(maxsize=4)
|
|
34
|
-
def preprocess_token_ids(
|
|
35
|
-
tokenizer: object,
|
|
36
|
-
prompts: list,
|
|
37
|
-
device: str='cpu'
|
|
38
|
-
) -> dict:
|
|
39
|
-
# tokenize
|
|
40
|
-
__inputs = tokenizer(prompts, return_tensors='pt', padding=True)
|
|
41
|
-
# move to the main device
|
|
42
|
-
return {__k: __v.to(device) for __k, __v in __inputs.items()}
|
|
7
|
+
import psaiops.common.tokenizer
|
|
43
8
|
|
|
44
9
|
# HOOK #########################################################################
|
|
45
10
|
|
|
@@ -137,7 +102,7 @@ def steer_model_output(
|
|
|
137
102
|
if not (__prompt0 and __prompt1 and __prompt2):
|
|
138
103
|
return ''
|
|
139
104
|
# tokenize the 2 prompts and pad to same length
|
|
140
|
-
__inputs = preprocess_token_ids(tokenizer=tokenizer_obj, prompts=(__prompt0, __prompt1), device=device_str)
|
|
105
|
+
__inputs = psaiops.common.tokenizer.preprocess_token_ids(tokenizer=tokenizer_obj, prompts=(__prompt0, __prompt1), device=device_str)
|
|
141
106
|
# forward hook to capture output hidden state
|
|
142
107
|
__hook = functools.partial(capture_hidden_activation, index=__index, captured=__captured)
|
|
143
108
|
# attach to the model
|
|
@@ -158,7 +123,7 @@ def steer_model_output(
|
|
|
158
123
|
# attach to the model
|
|
159
124
|
__handle = model_obj.model.layers[__index].register_forward_hook(__hook)
|
|
160
125
|
# now process the user input
|
|
161
|
-
__inputs = preprocess_token_ids(tokenizer=tokenizer_obj, prompts=(prompt_str,), device=device_str)
|
|
126
|
+
__inputs = psaiops.common.tokenizer.preprocess_token_ids(tokenizer=tokenizer_obj, prompts=(prompt_str,), device=device_str)
|
|
162
127
|
# generate the new with tampered activations
|
|
163
128
|
with torch.no_grad():
|
|
164
129
|
__outputs = model_obj.generate(
|
psaiops/compose/maths/app.py
CHANGED
|
@@ -6,7 +6,8 @@ import pandas
|
|
|
6
6
|
import torch
|
|
7
7
|
import torch.cuda
|
|
8
8
|
|
|
9
|
-
import psaiops.
|
|
9
|
+
import psaiops.common.model
|
|
10
|
+
import psaiops.common.tokenizer
|
|
10
11
|
|
|
11
12
|
# META #########################################################################
|
|
12
13
|
|
|
@@ -133,11 +134,13 @@ def create_table_block() -> dict:
|
|
|
133
134
|
|
|
134
135
|
# STATE ########################################################################
|
|
135
136
|
|
|
137
|
+
def default_state(visible: bool=False) -> dict:
|
|
138
|
+
return {'visible': visible, 'operation': '+', 'factor': 1.0, 'prompt': ''}
|
|
139
|
+
|
|
136
140
|
def create_state(limit: int=COUNT) -> dict:
|
|
137
141
|
return {
|
|
138
142
|
'cache_block': gradio.State(
|
|
139
|
-
[
|
|
140
|
-
+ max(0, limit - 1) * [{'visible': False, 'operation': '+', 'factor': 1.0, 'prompt': ''}])}
|
|
143
|
+
[default_state(True)] + [default_state(False) for _ in range(limit - 1)])}
|
|
141
144
|
|
|
142
145
|
# LAYOUT #######################################################################
|
|
143
146
|
|
|
@@ -251,8 +254,8 @@ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, limit: int=
|
|
|
251
254
|
with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
|
|
252
255
|
# load the model
|
|
253
256
|
__device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
|
254
|
-
# __model = psaiops.
|
|
255
|
-
__tokenizer = psaiops.
|
|
257
|
+
# __model = psaiops.common.model.get_model(name=model, device=__device)
|
|
258
|
+
__tokenizer = psaiops.common.tokenizer.get_tokenizer(name=model, device=__device)
|
|
256
259
|
# create the UI
|
|
257
260
|
__inputs.update(create_layout(intro=intro, limit=limit))
|
|
258
261
|
# init the state
|
psaiops/compose/maths/lib.py
CHANGED
|
@@ -1,42 +1 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
|
|
3
1
|
import torch
|
|
4
|
-
import torch.nn.modules
|
|
5
|
-
import transformers
|
|
6
|
-
|
|
7
|
-
import deformers.models.openai.gptoss
|
|
8
|
-
import mlable.shapes
|
|
9
|
-
|
|
10
|
-
# LOAD #########################################################################
|
|
11
|
-
|
|
12
|
-
@functools.lru_cache(maxsize=4)
|
|
13
|
-
def get_tokenizer(name: str, device: str='cpu'):
|
|
14
|
-
return transformers.AutoTokenizer.from_pretrained(
|
|
15
|
-
name,
|
|
16
|
-
use_fast=True,
|
|
17
|
-
dtype='auto',
|
|
18
|
-
device_map=device)
|
|
19
|
-
|
|
20
|
-
@functools.lru_cache(maxsize=2)
|
|
21
|
-
def get_model(name: str, device: str='cpu'):
|
|
22
|
-
__model = deformers.models.openai.gptoss.GptOssForCausalInference.from_pretrained(
|
|
23
|
-
name,
|
|
24
|
-
dtype='auto',
|
|
25
|
-
device_map=device)
|
|
26
|
-
# toggle the inference mode (not training)
|
|
27
|
-
__model.eval()
|
|
28
|
-
# transformers model
|
|
29
|
-
return __model
|
|
30
|
-
|
|
31
|
-
# PREPROCESS #####################################################################
|
|
32
|
-
|
|
33
|
-
@functools.lru_cache(maxsize=4)
|
|
34
|
-
def preprocess_token_ids(
|
|
35
|
-
tokenizer: object,
|
|
36
|
-
prompts: list,
|
|
37
|
-
device: str='cpu'
|
|
38
|
-
) -> dict:
|
|
39
|
-
# tokenize
|
|
40
|
-
__inputs = tokenizer(prompts, return_tensors='pt', padding=True)
|
|
41
|
-
# move to the main device
|
|
42
|
-
return {__k: __v.to(device) for __k, __v in __inputs.items()}
|
psaiops/score/attention/app.py
CHANGED
|
@@ -4,6 +4,8 @@ import gradio
|
|
|
4
4
|
import torch
|
|
5
5
|
import torch.cuda
|
|
6
6
|
|
|
7
|
+
import psaiops.common.model
|
|
8
|
+
import psaiops.common.tokenizer
|
|
7
9
|
import psaiops.score.attention.lib
|
|
8
10
|
|
|
9
11
|
# META #########################################################################
|
|
@@ -155,14 +157,14 @@ def update_computation_state(
|
|
|
155
157
|
# handle all exceptions at once
|
|
156
158
|
try:
|
|
157
159
|
# dictionary {'input_ids': _, 'attention_mask': _}
|
|
158
|
-
__input_data = psaiops.
|
|
160
|
+
__input_data = psaiops.common.tokenizer.preprocess_token_ids(
|
|
159
161
|
tokenizer_obj=tokenizer_obj,
|
|
160
162
|
prompt_str=__prompt_str,
|
|
161
163
|
device_str=__device_str)
|
|
162
164
|
# parse the inputs
|
|
163
165
|
__input_dim = int(__input_data['input_ids'].shape[-1])
|
|
164
166
|
# tensor (1, T)
|
|
165
|
-
__output_data = psaiops.
|
|
167
|
+
__output_data = psaiops.common.model.generate_token_ids(
|
|
166
168
|
model_obj=model_obj,
|
|
167
169
|
input_args=__input_data,
|
|
168
170
|
token_num=__token_num,
|
|
@@ -185,7 +187,7 @@ def update_computation_state(
|
|
|
185
187
|
input_dim=__input_dim,
|
|
186
188
|
token_idx=__token_idx)
|
|
187
189
|
# detokenize the IDs
|
|
188
|
-
__tokens = psaiops.
|
|
190
|
+
__tokens = psaiops.common.tokenizer.postprocess_token_ids(
|
|
189
191
|
tokenizer_obj=tokenizer_obj,
|
|
190
192
|
token_obj=__output_data)
|
|
191
193
|
# update each component => (input, output, attention, highligh) states
|
|
@@ -245,8 +247,8 @@ def create_app(title: str=TITLE, intro: str=INTRO, style: str=STYLE, model: str=
|
|
|
245
247
|
with gradio.Blocks(theme=gradio.themes.Soft(), title=title, css=style) as __app:
|
|
246
248
|
# load the model
|
|
247
249
|
__device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
|
248
|
-
__model = psaiops.
|
|
249
|
-
__tokenizer = psaiops.
|
|
250
|
+
__model = psaiops.common.model.get_model(name=model, device=__device)
|
|
251
|
+
__tokenizer = psaiops.common.tokenizer.get_tokenizer(name=model, device=__device)
|
|
250
252
|
# adapt the computing function
|
|
251
253
|
__compute = functools.partial(update_computation_state, model_obj=__model, tokenizer_obj=__tokenizer, device_str=__device)
|
|
252
254
|
# create the UI
|