File size: 21,230 Bytes
3d6ba31
 
 
 
dc83bf2
 
3d6ba31
15c54ca
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c747d4b
 
3d6ba31
 
 
 
 
 
 
dc83bf2
3d6ba31
 
 
dc83bf2
3d6ba31
 
 
 
dc83bf2
3d6ba31
 
 
dc83bf2
3d6ba31
 
 
dc83bf2
3d6ba31
 
dc83bf2
3d6ba31
dc83bf2
 
 
 
 
 
 
3d6ba31
 
 
 
 
 
 
 
 
 
 
e7c72ea
3d6ba31
 
 
e7c72ea
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc83bf2
 
 
 
 
 
 
 
 
 
15c54ca
dc83bf2
 
 
cc637aa
 
dc83bf2
 
 
 
 
 
 
 
 
 
 
 
cc637aa
dc83bf2
 
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dfd8fd1
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1d16db
 
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
dc83bf2
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc83bf2
3d6ba31
 
 
 
 
 
 
 
 
fa23888
3d6ba31
 
 
114995f
3d6ba31
 
 
dc83bf2
 
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ef56b5d
3d6ba31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc83bf2
 
3d6ba31
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
import gradio as gr
import os
import numpy as np
import ujson as json
import time
from threading import Thread

from loading import load_data, save_git, load_git
from tools import compute_ordered_matrix
from plotting import plot_sim_matrix_fig, plot_umap_fig, plot_tree, update_sim_matrix_fig, update_umap_fig, update_tree_fig
from llm_run import download_llm_to_cache, load_model, llm_run

def reload_figures():
    global MODEL_SEARCHED_X, MODEL_SEARCHED_Y, ALPHA_EDGES, ALPHA_NAMES, ALPHA_MARKERS, FIGS, ORDERED_MODEL_NAMES
    fig1 = update_sim_matrix_fig(FIGS['fig1'], ORDERED_MODEL_NAMES, model_search_x=MODEL_SEARCHED_X, model_search_y=MODEL_SEARCHED_Y)
    fig2 = update_umap_fig(FIGS['fig2'], DIST_MATRIX, MODEL_NAMES, FAMILIES, COLORS, model_search_x=MODEL_SEARCHED_X, alpha_edges=ALPHA_EDGES['fig2'], alpha_names=ALPHA_NAMES['fig2'], alpha_markers=ALPHA_MARKERS['fig2'])
    fig4 = update_tree_fig(FIGS['fig4'], MODEL_NAMES, model_search=MODEL_SEARCHED_X, alpha_edges=ALPHA_EDGES['fig4'], alpha_names=ALPHA_NAMES['fig4'], alpha_markers=ALPHA_MARKERS['fig4'])
    return [fig1,fig2,fig4]

def search_bar_changeX(value):
    global MODEL_SEARCHED_X
    MODEL_SEARCHED_X = value
    return reload_figures()

def search_bar_changeY(value):
    global MODEL_SEARCHED_Y
    MODEL_SEARCHED_Y = value
    return reload_figures()

def slider_changeAlphaMarkers(value,key):
    global ALPHA_MARKERS
    ALPHA_MARKERS[key] = value
    return reload_figures()

def slider_changeAlphaNames(value,key):
    global ALPHA_NAMES
    ALPHA_NAMES[key] = value
    return reload_figures()

def slider_changeAlphaEdges(value,key):
    global ALPHA_EDGES
    ALPHA_EDGES[key] = value
    return reload_figures()

def search_bar_gr(model_names,slider=True,double_search=False,key=None):
    global MODEL_SEARCHED_X,MODEL_SEARCHED_Y,ALPHA_EDGES,ALPHA_NAMES, ALPHA_MARKERS
    #col1,col2 = gr.Row([0.2,0.8])
    ret = []
    with gr.Column(scale=1) as col1:
        with gr.Group():
            if MODEL_SEARCHED_X is None:
                index = 0
            else:
                index = model_names.index(MODEL_SEARCHED_X)
            ms_x = gr.Dropdown(label='Search'+(' X' if double_search else ''),choices=model_names,value=model_names[index],key='model_search_x_'+key,interactive=True)
            #set MODEL_SEARCH_X
            ret.append(ms_x)
            if double_search:
                if MODEL_SEARCHED_Y is None:
                    index = 0
                else:
                    index = model_names.index(MODEL_SEARCHED_Y)
                ms_y = gr.Dropdown(label='Search Y',choices=model_names,value=model_names[index],key='model_search_y_'+key,interactive=True)
                ret.append(ms_y)
        if slider:
            with gr.Group():
                values = np.arange(0, 1.05,0.05)
                #truncate values to the 100th
                values = np.round(values,2)
                alpha_edges = gr.Slider(label='Alpha Edges',
                                minimum=0,
                                maximum=1,
                                step=0.05,
                                value=ALPHA_EDGES[key],
                                    key='alpha_edges_'+key,
                                    interactive=True)
                
                values = np.arange(0, 1.05,0.05)
                #truncate values to the 100th
                values = np.round(values,2)
                alpha_names = gr.Slider(label='Alpha Names',
                                minimum=0,
                                maximum=1,
                                step=0.05,
                                value=ALPHA_NAMES[key],
                                    key='alpha_names_'+key,
                                    interactive=True)
                
                values = np.arange(0, 1.05,0.05)
                #truncate values to the 100th
                values = np.round(values,2)
                alpha_markers = gr.Slider(label='Alpha Markers',
                                minimum=0,
                                maximum=1,
                                step=0.05,
                                value=ALPHA_MARKERS[key],
                                    key='alpha_markers_'+key,
                                    interactive=True)
                ret.append(alpha_edges)
                ret.append(alpha_names)
                ret.append(alpha_markers)
    col2 = gr.Column(scale=5)
    ret.insert(0,col2)
    return ret

import spaces
@spaces.GPU(duration=300)
def _run(path,genes,N,progress_bar):
    #Load the model
    progress_bar(0.20, desc="Loading Model...",total=100)
    try:
        model,tokenizer = load_model(path)
    except ValueError as e:
            print(f"Error loading model '{path}': {e}")
            gr.Warning("Model couldn't load. This space currently only works with AutoModelForCausalLM models and for security reasons cannot execute remote code. Please check the model architecture and whether it too recent and requires the execution of custom code.")
            return None
    except OSError as e:
            print(f"Error loading model '{path}': {e}")
            gr.Warning("Model doesn't seem to exist on the HuggingFace Hub or might be gated. Please check the model name and its accessibility.")
            return None
    except RuntimeError as e:
            if 'out of memory' in str(e):
                print(f"Error loading model '{path}': {e}")
                gr.Warning("Loading the model triggered an out of memory error. It may be too big for the GPU (80Go RAM max). Please verify the size of the model.")
                return None
            else:
                print(f"Error loading model '{path}': {e}")
                gr.Warning("Model couldn't be loaded. Check the logs for what happened or report an issue including the model's name.")
                return None
    except Exception as e:
            print(f"Error loading model '{path}': {e}")
            gr.Warning("Model couldn't be loaded. Check the logs for what happened or report an issue including the model's name.")
            return None
    progress_bar(0.25, desc="Generating data...",total=100)
    time0 = time.perf_counter()
    for i,output in enumerate(llm_run(model,tokenizer,genes,N)):
        time_elapsed = time.perf_counter()-time0
        estimated_time_remaining = int(len(genes)*time_elapsed/(i+1))
        minutes = str(estimated_time_remaining//60)
        minutes = "0"*(2-min(2,len(minutes))) + minutes
        seconds = str(estimated_time_remaining%60)
        seconds = "0"*(2-min(2,len(seconds))) + seconds
        progress_bar(0.25 + i*(70/len(genes))/100, desc=f"Generating data... {i+1}/{len(genes)} - estimated remaining time {minutes}:{seconds}",total=100)
    return output

def run(path,progress_bar):
    global DEFAULT_FAMILY_NAME, PHYLOLM_N
    family = DEFAULT_FAMILY_NAME
    N = PHYLOLM_N
    #Loading bar
    progress_bar(0, desc="Downloading model...",total=100)
    try:
        # Download the model to cache
        if download_llm_to_cache(path) is None:
            gr.Warning("Model not found on Hugging Face Hub or might be gated. Please check the model name and try again.")
            return None
    except OSError as e:
        print(f"Error downloading model: {e}")
        gr.Warning("Model not found on Hugging Face Hub or might be gated. Please check the model name and try again.")
        return None
    
    # Load the model
    progress_bar(0.10, desc="Loading contexts...",total=100)

    with open('inputs/math.json', 'r') as f:
        genes = json.load(f)

    # Load the model and run
    progress_bar(0.15, desc="Waiting for GPU...",total=100)

    try:
        output = _run(path,genes,N,progress_bar)
        if output is None:
            return None
    except Exception as e:
        print(f"Error running model: {e}")
        gr.Warning("Something unexpected happened during the run or the loading of the model. Please check the logs or report an issue.")
        return None

    progress_bar(0.95, desc="Saving data ...",total=100)

    alleles = [[compl[j]['generated_text'][len(gene):][:4] for j in range(len(compl))] for gene,compl in zip(genes,output)]
    fsave = False
    for i in range(10): #Trying to push
        try:
            save_git(alleles,genes,path,family)
            fsave = True
            break
        except Exception as e:
            print(f"Error saving data: {e}")
            #Recloning the repo
            try:
                load_git(force_clone=True)
            except Exception as e:
                print(f"Error recloning repo: {e}")
    if not fsave:
        gr.Warning("Something went wrong with GitHub and data couldn't be sent to the server. Please check the logs or report an issue. ")
        """def download_data():
            d = {'family':family,'alleles':alleles}
            model_name = path
            data_path = f'math/{model_name}.json'
            path = os.path.join('Data',data_path)
            #create the file folder path
            if not os.path.exists(os.path.dirname(path)):
                os.makedirs(os.path.dirname(path), exist_ok=True)
            #Open the file
            with open(path,'w') as f:
                json.dump(d,f)
            # Provide the download link
            return gr.File.update(value=path, label="Download data", file_name=f"{model_name}.json")
        gr.Button("Download data",variant="primary").click(fn=download_data, inputs=[], outputs=None)"""
        return None
    

    progress_bar(1, desc="Done!",total=100)

def prepare_run(model_name,progress_bar=gr.Progress()):
    global MODEL_SEARCHED_X,MODEL_NAMES
    if model_name in MODEL_NAMES:
        gr.Warning('Model already exists in the database.')
        MODEL_SEARCHED_X = model_name
        reload_figures()
        return
    run(model_name,progress_bar)

def reload_env():
    global SIM_MAT_SEARCH_X, SIM_MAT_SEARCH_Y, VIZ_SEARCH, TREE_SEARCH
    global MODEL_NAMES, FAMILIES, COLORS, SIM_MATRIX, DIST_MATRIX
    global FIGS, FIGS_OBJECTS
    global ORDERED_MODEL_NAMES
    
    # Load models for the dropdown
    data, model_names, families, sim_matrix, colors = load_data()

    sim_matrix_safe = np.where(sim_matrix == 0, np.finfo(np.float64).eps, sim_matrix)
    dist_matrix = -np.log(sim_matrix_safe)

    #Set globals
    MODEL_NAMES = model_names
    FAMILIES = families
    COLORS = colors
    SIM_MATRIX = sim_matrix
    DIST_MATRIX = dist_matrix

    #Update Figs
    ordered_sim_matrix, ordered_model_names = compute_ordered_matrix(sim_matrix,dist_matrix, model_names)
    ORDERED_MODEL_NAMES = ordered_model_names
    FIGS['fig1'] = plot_sim_matrix_fig(ordered_sim_matrix, ordered_model_names, families, colors)
    FIGS['fig2'] = plot_umap_fig(dist_matrix, sim_matrix, model_names, families, colors,
                                        alpha_edges=ALPHA_EDGES['fig2'],alpha_names=ALPHA_NAMES['fig2'],alpha_markers=ALPHA_MARKERS['fig2'])
    FIGS['fig4'] = plot_tree(sim_matrix, model_names, families, colors,alpha_edges=ALPHA_EDGES['fig4'],alpha_names=ALPHA_NAMES['fig4'],alpha_markers=ALPHA_MARKERS['fig4'])

    #Update search bars
    sim_mat_search_x = gr.Dropdown(label='Search X',choices=model_names,value=model_names[0],key='model_search_x_fig1',interactive=True)
    sim_mat_search_y = gr.Dropdown(label='Search Y',choices=model_names,value=model_names[0],key='model_search_y_fig1',interactive=True)
    viz_search = gr.Dropdown(label='Search',choices=model_names,value=model_names[0],key='model_search_fig2',interactive=True)
    tree_search = gr.Dropdown(label='Search',choices=model_names,value=model_names[0],key='model_search_fig4',interactive=True)

    return FIGS['fig1'], FIGS['fig2'], FIGS['fig4'], sim_mat_search_x, sim_mat_search_y, viz_search, tree_search


USERNAME = os.environ['GITHUB_USERNAME']
TOKEN = os.environ['GITHUB_TOKEN']
MAIL = os.environ['GITHUB_MAIL']

MODEL_SEARCHED_X = None
MODEL_SEARCHED_Y = None
ALPHA_EDGES = {'fig2':0.05, 'fig3':0.05,'fig4':1.0}
ALPHA_NAMES = {'fig2':0.0, 'fig3':0.0,'fig4':0.0}
ALPHA_MARKERS = {'fig2':0.8, 'fig3':0.8,'fig4':1.0}

FIGS = {'fig1':None,'fig2':None,'fig3':None,'fig4':None}
FIGS_OBJECTS = [None,None,None]
MODEL_NAMES = None
FAMILIES = None
COLORS = None
ORDERED_MODEL_NAMES = None
SIM_MATRIX = None
DIST_MATRIX = None

DEFAULT_FAMILY_NAME = '?'
PHYLOLM_N = 32

SIM_MAT_SEARCH_X = None
SIM_MAT_SEARCH_Y = None
VIZ_SEARCH = None
TREE_SEARCH = None

# Build the Gradio interface
with gr.Blocks(title="PhyloLM", theme=gr.themes.Default()) as demo:
    gr.Markdown("# PhyloLM: Phylogenetic Mapping of Language Models")

    gr.Markdown("_This space is under active development. New features and improvements will be added regularly and some things may not work properly. Feel free to open an issue if you encounter any problems._")
    
    gr.Markdown(
        "Welcome to PhyloLM ([paper](https://arxiv.org/abs/2404.04671) - [code](https://github.com/Nicolas-Yax/PhyloLM)) — a tool for comparing language models based on their **behavioral similarity**, inspired by methods from comparative genomics. "
        "Instead of architecture or weights, we use output behavior on diagnostic prompts as a behavioral fingerprint to compute a distance metric, akin to how biologists compare species using genetic data. This makes it possible to draw a unique map of all LLMs (various architectures, gated and non gated, ...)."
        "The goal of this space is to create a collaborative space where everyone can visualize these maps and extend them with models of their choice. "
    )
    
    gr.Markdown("## Explore Maps of Models")
    
    gr.Markdown(
        "This interactive space allows users to explore model similarities through four types of visualizations:\n"
        "- A similarity matrix (values range from 0 = dissimilar to 1 = highly similar). \n"
        "- 2D and 3D scatter plots representing how close or far from each other LLMs are (plotted using UMAP). \n"
        "- A tree to visualize distances between models (distance from leaf A to leaf B in the tree is similar to the distance between the two models)\n\n"
        "Models are colored according to their family (e.g., LLaMA, OPT, Mistral) for the ones that were in the original paper. Models added by users are colored in grey for now. "
    )
    
    # Load models for the dropdown
    data, model_names, families, sim_matrix, colors = load_data()

    sim_matrix_safe = np.where(sim_matrix == 0, np.finfo(np.float64).eps, sim_matrix)
    dist_matrix = -np.log(sim_matrix_safe)

    #Set globals
    MODEL_NAMES = model_names
    FAMILIES = families
    COLORS = colors
    SIM_MATRIX = sim_matrix
    DIST_MATRIX = dist_matrix

    # Create the tabs
    tab_state = gr.State(value="Similarity Matrix")  # Default tab
    tabs = gr.Tabs(["Similarity Matrix", "2D Visualization","Tree Visualization"])
    with tabs:
        with gr.TabItem("Similarity Matrix"):
            # Similarity matrix visualization
            with gr.Row():
                col2,sim_mat_search_x,sim_mat_search_y = search_bar_gr(model_names,slider=False,double_search=True,key='fig1')
                with col2:
                    ordered_sim_matrix, ordered_model_names = compute_ordered_matrix(sim_matrix,dist_matrix, model_names)
                    fig = plot_sim_matrix_fig(ordered_sim_matrix, ordered_model_names, families, colors)
                    sim_matrix_output = gr.Plot(fig,label="Similarity Matrix")
                    FIGS['fig1'] = fig
                    ORDERED_MODEL_NAMES = ordered_model_names
                    FIGS_OBJECTS[0] = sim_matrix_output
        with gr.TabItem("2D Visualization"):
            # 2D visualization
            with gr.Row():
                col2,viz_search,viz_alpha_edge,viz_alpha_name,viz_alpha_marker = search_bar_gr(model_names,slider=True,double_search=False,key='fig2')
                with col2:
                    fig = plot_umap_fig(dist_matrix, sim_matrix, model_names, families, colors,
                                        alpha_edges=ALPHA_EDGES['fig2'],alpha_names=ALPHA_NAMES['fig2'],alpha_markers=ALPHA_MARKERS['fig2'])
                    plot_output = gr.Plot(fig,label="2D Visualization")
                    FIGS['fig2'] = fig
                    FIGS_OBJECTS[1] = plot_output
        with gr.TabItem("Tree Visualization"):
            # Tree visualization
            with gr.Row():
                col2,tree_search,tree_alpha_edge,tree_alpha_name,tree_alpha_marker = search_bar_gr(model_names,slider=True,double_search=False,key='fig4')
                with col2:
                    fig = plot_tree(sim_matrix, model_names, families, colors,alpha_edges=ALPHA_EDGES['fig4'],alpha_names=ALPHA_NAMES['fig4'],alpha_markers=ALPHA_MARKERS['fig4'])
                    tree_output = gr.Plot(fig,label="Tree Visualization")
                    FIGS['fig4'] = fig
                    FIGS_OBJECTS[2] = tree_output
            

    # Submit model section
    gr.Markdown("## Submit a Model")
    
    gr.Markdown(
        "You may contribute new models to this collaborative space using compute resources. "
        "Once processed, the model will be compared to existing ones, and its results added to a shared public database. "
        "Model families (e.g., LLaMA, OPT, Mistral) are extracted from Hugging Face model cards and used only for visualization (e.g., coloring plots); they are **not** involved in the computation of similarity."
    )
    
    gr.Markdown(
        "**To add a new model:**\n"
        "1. Enter the name of a model hosted on Hugging Face (e.g., `'Qwen/Qwen2.5-7B-Instruct'`).\n"
        "2. Click on the **Run PhyloLM** button.\n"
        "- If the model has already been processed, you'll be notified and no new run will start.\n"
        "- If it hasn't been processed, it will be downloaded and be evaluated.\n\n"
        "⚠️ Be careful when submitting large LLMs (typically >15B parameters) as they may exceed the GPU RAM or the time limit, leading to failed runs.\n"
    )
    
    with gr.Group():
        model_input = gr.Textbox(label="Model", interactive=True)
        submit_btn = gr.Button("Run PhyloLM", variant="primary",interactive=True)

    
    # Disclaimer and citation
    gr.Markdown("## Disclaimer")
    gr.Markdown(
        "This is a research prototype and may contain bugs or limitations. "
        "All computed data are public and hosted on [GitHub](https://github.com/PhyloLM/Data). "
        "If you'd like to contribute additional models — especially for gated or large models that cannot be processed via the web interface — "
        "you are welcome to submit a pull request to the repository cited above. "
        "All results are computed on the 'Math' set of genes used in the original paper."
    )
    
    gr.Markdown("## Citation")
    gr.Markdown("If you find this project useful for your research, please consider citing the following paper:")

    #bibtex
    gr.Code('''@inproceedings{
yax2025phylolm,
title={Phylo{LM}: Inferring the Phylogeny of Large Language Models and Predicting their Performances in Benchmarks},
author={Nicolas Yax and Pierre-Yves Oudeyer and Stefano Palminteri},
booktitle={The Thirteenth International Conference on Learning Representations},
year={2025},
url={https://openreview.net/forum?id=rTQNGQxm4K}
}''',language=None)
    gr.Markdown('Socials : [BlueSky](https://bsky.app/profile/nicolasyax.bsky.social) [Twitter](https://x.com/nicolas__yax?s=11)')
    
    # Change actions from search bars
    sim_mat_search_x.change(fn=search_bar_changeX, inputs=sim_mat_search_x, outputs=FIGS_OBJECTS)
    sim_mat_search_y.change(fn=search_bar_changeY, inputs=sim_mat_search_y, outputs=FIGS_OBJECTS)

    viz_search.change(fn=search_bar_changeX, inputs=viz_search, outputs=FIGS_OBJECTS)

    tree_search.change(fn=search_bar_changeX, inputs=tree_search, outputs=FIGS_OBJECTS)

    # Change actions from sliders
    viz_alpha_edge.change(fn=lambda x : slider_changeAlphaEdges(x,'fig2'), inputs=viz_alpha_edge, outputs=FIGS_OBJECTS)
    viz_alpha_name.change(fn=lambda x : slider_changeAlphaNames(x,'fig2'), inputs=viz_alpha_name, outputs=FIGS_OBJECTS)
    viz_alpha_marker.change(fn=lambda x : slider_changeAlphaMarkers(x,'fig2'), inputs=viz_alpha_marker, outputs=FIGS_OBJECTS)

    tree_alpha_edge.change(fn=lambda x : slider_changeAlphaEdges(x,'fig4'), inputs=tree_alpha_edge, outputs=FIGS_OBJECTS)
    tree_alpha_name.change(fn=lambda x : slider_changeAlphaNames(x,'fig4'), inputs=tree_alpha_name, outputs=FIGS_OBJECTS)
    tree_alpha_marker.change(fn=lambda x : slider_changeAlphaMarkers(x,'fig4'), inputs=tree_alpha_marker, outputs=FIGS_OBJECTS)

    # Run PhyloLM button
    run_event = submit_btn.click(fn=prepare_run, inputs=[model_input], outputs=[model_input]).then(fn=reload_env, inputs=[], outputs=FIGS_OBJECTS+ [sim_mat_search_x, sim_mat_search_y, viz_search, tree_search])
    #cancel_btn.click(fn=None,inputs=None,outputs=None,cancels=[run_event])

    #Set more globals
    SIM_MAT_SEARCH_X = sim_mat_search_x
    SIM_MAT_SEARCH_Y = sim_mat_search_y
    VIZ_SEARCH = viz_search
    TREE_SEARCH = tree_search

    
    
if __name__ == "__main__":
    demo.launch()