From b0a401960721eaeba1303a20df18c3fa6df2b897 Mon Sep 17 00:00:00 2001 From: DoraDong-2023 Date: Fri, 1 Dec 2023 17:30:02 +0800 Subject: [PATCH] v1.1.7 update --- Git2APP.md | 42 +- README.md | 38 +- demo/MIOSTONE_IBD200.html | 2642 +++++++++++++++++++++++++ demo/MIOSTONE_IBD200.json | 2178 ++++++++++++++++++++ demo/tutorial_links.txt | 2 + src/deploy/inference_dialog_server.py | 34 +- src/inference/execution_UI.py | 47 +- 7 files changed, 4947 insertions(+), 36 deletions(-) create mode 100644 demo/MIOSTONE_IBD200.html create mode 100644 demo/MIOSTONE_IBD200.json diff --git a/Git2APP.md b/Git2APP.md index 8eebf87..d749a4b 100644 --- a/Git2APP.md +++ b/Git2APP.md @@ -157,26 +157,23 @@ from typing import Union import pandas as pd from your_module import TreeNode -def compute_gini_gain(dataset: Union[pd.DataFrame, list], node: TreeNode) -> float: - """ - Calculate the Gini gain of a given dataset and node using a decision tree classifier. - - :param dataset: The dataset for which Gini gain needs to be calculated. - :param node: The specific node in the decision tree being evaluated. - :return: Returns the calculated Gini gain for the given node in the dataset. +def add(a:int, b:int) -> int: + """ + Compute the sum of two integers. + + Parameters: + ----------- + a : int + The first integer. + b : int + The second integer. + + Returns: + -------- + int + The sum of `a` and `b`. """ - dt = DecisionTreeClassifier(criterion='gini', max_depth=1) - node_values = node_value(dataset, node) - dt.fit(node_values.values.reshape(-1, 1), dataset.y) - impurity_before_split = dt.tree_.impurity[0] - impurity_left_child = dt.tree_.impurity[1] - impurity_right_child = dt.tree_.impurity[2] - n_node_samples = dt.tree_.n_node_samples - - gini_before = impurity_before_split - gini_after = (n_node_samples[1]/n_node_samples[0])*impurity_left_child + (n_node_samples[2]/n_node_samples[0])*impurity_right_child - gini_gain = gini_before - gini_after - return gini_gain + return a + b ``` You can refer to the prompts available in [BioMANIA](https://www.biorxiv.org/content/10.1101/2023.10.29.564479v1) to add the function body, or either using the [prompt](./src/Git2APP/get_API_docstring_from_sourcecode.py) that modified based on that. @@ -244,4 +241,11 @@ Follow the steps in [`Run with script/Inference`](README.md#inference) section i Remember to update the app's accordingly to your repository improvements. +**Tips: Currently, we do not support real-time communication. Therefore, if there is content that requires a long time to run, such as training a model, it is best to train only one epoch per inquiry. We might plan to support real-time display of results in the near future.** + +### 2.4 Share your APP! + +Follow the steps in [`Share your APP`](README.md#share-your-app) section in `README` to introduce your tool to others! + + I hope this tutorial helps you create your BioMANIA app with your GitHub-hosted package. If you have any further questions or need assistance with specific steps, feel free to ask! \ No newline at end of file diff --git a/README.md b/README.md index 91a73ff..8cdd2ab 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Tips: - We have implemented switching different libraries inside one dialog. You can - Notice that the inference speed depends on OpenAI key and back-end device. A paid OpenAI key and running back-end on GPU will speed up the inference quite a lot! - All uploaded files are saved under `./tmp` folder. Please enter `./tmp/`+your_file_name when the API requires filename parameters. -- It will be quite slow if the file for transmission is too large. +- It will be quite slow if the file for transmission is large. If the file transfer is too large, you may encounter the following issue: "JavaScript heap memory exhaustion caused by excessive memory usage or memory leaks in the program.". **You can copy the file under `src/tmp/` folder directly.** > **This has only one backend, which may lead to request confusion when multiple users request simultaneously. The stability of the operation is affected by the device's network. When it runs on the CPU, switching between different libraries takes about half a minute to load models and data. We recommend prioritizing running it locally with GPU, which takes only about 3 seconds to switch between different libraries!** @@ -306,6 +306,7 @@ python inference/retriever_bm25_inference.py --LIB ${LIB} --top_k 3 7. Fine-tune the retriever. You can finetune the retriever based on the [bert-base-uncased](https://huggingface.co/bert-base-uncased) model ```bash +export LIB=scanpy CUDA_VISIBLE_DEVICES=0 mkdir ./hugging_models/retriever_model_finetuned/${LIB} python models/train_retriever.py \ @@ -346,7 +347,7 @@ test the inference performance using: ```bash export LIB=scanpy export HUGGINGPATH=./hugging_models -CUDA_VISIBLE_DEVICES=1 +CUDA_VISIBLE_DEVICES=0 python inference/retriever_finetune_inference.py \ --retrieval_model_path ./hugging_models/retriever_model_finetuned/${LIB}/assigned \ --corpus_tsv_path ./data/standard_process/${LIB}/retriever_train_data/corpus.tsv \ @@ -472,6 +473,32 @@ python report/Py2report.py scanpy The output files are located in the ./report folder. + +## Share your APP! + +If you want to share your APP to others, there are two ways. + +### Share docker + +You can build docker and push to dockerhub, and share your docker image url in [our issue](https://github.com/batmen-lab/BioMANIA/issues/2). +```bash +# cd BioMANIA +docker build -t [docker_image_name] -f Dockerfile ./ +# run on cpu +docker run -e OPENAI_API_KEY=[your_OPENAI_API_KEY] -d -p 3000:3000 [docker_image_name] +# (optional)run on cuda +docker run -e OPENAI_API_KEY=[your_OPENAI_API_KEY] --gpus all -d -p 3000:3000 [docker_image_name] +# (optional)push to docker +docker push [your_docker_repo]/[docker_image_name]:[tag] +``` + +Notice if you want to include some data inside the docker, please modify the `Dockerfile` carefully to copy the folders to `/app`. Also add your PyPI or Git pip install url to the `requirements.txt` before your packaging for docker. + +### Share data/models + +You can just share your `data` and `hugging_models` folder and `logo` image by drive link to [our issue](https://github.com/batmen-lab/BioMANIA/issues/2). + + ## Reference and Acknowledgments We extend our gratitude to the following references: @@ -494,6 +521,13 @@ report/Py2report.py ``` ## Version History +- v1.1.8 (comming soon) +- v1.1.7 (2023-11-30) + - Added [SONATA tutorial](./demo/sonata_SNARE_seq.html) and [MIOSTONE tutorial](./demo/MIOSTONE_IBD200.html) to showcase tool usage. Upload data and pretrained models onto [drive](https://drive.google.com/drive/folders/1vWef2csBMe-PSPqA9pY2IVCY_JT5ac7p?usp=drive_link). + - Fixed bug in class-type APIs that caused errors when using methods. Methods can now be called and used correctly. + - Resolved program exit issue without error throw. Errors are now handled properly with relevant error messages displayed. + - Addressed retriever loading issue for specific tools. Indivdual retrievers can now be loaded and utilized correctly for each tool. + - Enhance Robustness for basic type parameters. When entering `result_*` for basic type parameters, it will show `result_*` instead of `"result_*"` even it is of `str` type. - v1.1.6 (2023-11-27) - Support sharing your APP and install others' APP through [our issue](https://github.com/batmen-lab/BioMANIA/issues/2)! - Enhance code robustness: diff --git a/demo/MIOSTONE_IBD200.html b/demo/MIOSTONE_IBD200.html new file mode 100644 index 0000000..9df3203 --- /dev/null +++ b/demo/MIOSTONE_IBD200.html @@ -0,0 +1,2642 @@ + + +BioMANIA UI
Top K: 1 | Lib: MIOSTONE |

Welcome to BioMANIA! How can I help?

Change the device for computation to cuda.
Can you confirm which of the following 2 candidates

Candidate [1]: MIOSTONE.utils.set_device
+Set the device for PyTorch based on the specified device string.
+Candidate [2]: MIOSTONE.experiment.set_device
+Set the device for PyTorch based on the specified device string.

1
Predicted API: MIOSTONE.utils.set_device

The task is to set the device for PyTorch based on a specified device string, such as 'cuda', 'mps', or 'cpu'. We solved this by using the MIOSTONE.utils.set_device function, which takes the device string as a parameter and sets the device accordingly. The function returns a variable of type 'device'.

python
from MIOSTONE.utils import set_device
+result_1 = set_device('cuda')
Executed results [Success]

We obtain a new variable: cuda

Set the seed as 3
Can you confirm which of the following 5 candidates

Candidate [1]: MIOSTONE.visualize_results.set_seed
+Set random seeds for reproducibility.
+Candidate [2]: MIOSTONE.utils.set_seed
+Set random seeds for reproducibility.
+Candidate [3]: MIOSTONE.visualize_dimred.set_seed
+Set random seeds for reproducibility.
+Candidate [4]: MIOSTONE.visualize_attr.set_seed
+Set random seeds for reproducibility.
+Candidate [5]: MIOSTONE.experiment.set_seed
+Set random seeds for reproducibility.

2
Predicted API: MIOSTONE.utils.set_seed

The user query is about setting random seeds for reproducibility in programming. The selected API function is MIOSTONE.utils.set_seed which allows users to specify a seed value for random number generators. This helps in ensuring that the same random numbers are generated every time the code is run, making the results reproducible.

python
from MIOSTONE.utils import set_seed
+result_2 = set_seed(3)
Executed results [Success]

We obtain a new variable: None

Can you load the config for mode `IBD200` dataset?
Can you confirm which of the following 5 candidates

Candidate [1]: MIOSTONE.visualize_attr.load_config

+

Candidate [2]: MIOSTONE.experiment.load_config

+

Candidate [3]: MIOSTONE.visualize_results.load_config

+

Candidate [4]: MIOSTONE.utils.load_config

+

Candidate [5]: MIOSTONE.visualize_dimred.load_config

4
Predicted API: MIOSTONE.utils.load_config

The user query is asking for a summary of the task and its solution in simple terms. The selected API function is MIOSTONE.utils.load_config, which is used to load a configuration file. The function takes a parameter called mode which is a string and is required. The function returns a list.

python
from MIOSTONE.utils import load_config
+result_3 = load_config('IBD200')
Executed results [Success]

We obtain a new variable: namespace(seed=3, device=device(type='cuda'), dataset='IBD200', target='Type', prob_label=False, rebalance='reweight', preprocess='clr', phylogeny='WoL2', taxonomy=True, prune_by_dataset=True, tree_dataset='none', tree_target='none', prune_by_num_leaves=-1, model='tree', mlp_type='pyramid', node_min_dim=1, node_dim_func='linear', node_dim_func_param=0.95, node_gate_type='concrete', node_gate_param=0.1, output_depth=0, output_truncation=True, transfer_learning='none', pretrained_model_path='', ft_epochs=30, k_fold=3, batch_size=386, epochs=1, loss='ce', mixup_num_samples=0, metrics=['accuracy', 'auroc', 'ap'], save_model=True, plot_loss=False, combine_folds=True, seeds_agg='median', metric='ap', metric_avg='macro', metric_axis='y', plot_type='bar', other_axis='model', hyperparam=[], model_selection='none', top_k=5, algorithm='pca', depth=-1, embedding_reduction='none', leaf_attr='deeplift', layer_deeplift=True, num_samples=None, top_k_nodes=None, min_depth=0, max_depth=5, visualize_depth=5, save_attributions=False)

Can you help me with loading and preprocessing the data?
Predicted API: MIOSTONE.experiment.load_and_preprocess_data

The task is to load and preprocess data, and we solved it by using the MIOSTONE.experiment.load_and_preprocess_data API function. This function allows us to specify the dataset we want to load and the path to save the data. It returns a tuple containing the custom tree, dataset, pretrained seed, and hyperparameters.

Enter Parameters: basic type

The predicted API takes loading which dataset('mode': str), and path to save data('pre_data_path': str), as input. However, there are still some parameters undefined in the query.

Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'mode'?

IBD200
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'pre_data_path'?

./tmp/data
python
from MIOSTONE.experiment import load_and_preprocess_data
+result_4 = load_and_preprocess_data('IBD200', './tmp/data')
Executed results [Success]

We obtain a new variable: (Tree node 'root' (0x7f9874dc142), <MIOSTONE.data.CustomDataset object at 0x7f981ccb3c10>, None, None)

python
result_5, result_6, result_7, result_8 = result_4
Executed results [Success]

Create a directory to store the results, losses, and models for the given dataset and target.
Predicted API: MIOSTONE.experiment.set_results_dir

The task is to create a directory where we can store the results, losses, and models for a specific dataset and target. We solved this by using the MIOSTONE API function called set_results_dir, which sets up the necessary directories for storing the data. The function takes the dataset name and target directory as parameters and returns a tuple containing the paths to the results, losses, and models directories.

Enter Parameters: basic type

The predicted API takes The name of the dataset.('dataset': str), and The target directory for storing results.('target': str), as input. However, there are still some parameters undefined in the query.

Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'dataset'?

IBD200
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'target'?

Type
python
from MIOSTONE.experiment import set_results_dir
+result_9 = set_results_dir('IBD200', 'Type')
Executed results [Success]

We obtain a new variable: ('../results/IBD200/Type', '../results/IBD200/Type/losses', '../results/IBD200/Type/models')

python
result_10, result_11, result_12 = result_9
Executed results [Success]

Please set the file name under mode 'IBD200'
Predicted API: MIOSTONE.experiment.set_file_name

The task is to set a file name under the mode 'IBD200'. We solved it by using the MIOSTONE.experiment.set_file_name API function, which generates a file name based on the provided arguments. The function takes the mode as a parameter and returns the generated file name as a string.

python
from MIOSTONE.experiment import set_file_name
+result_13 = set_file_name('IBD200')
Executed results [Success]

We obtain a new variable: 3_tree_clr_reweight_386_1_ce_1_linear_0.95_concrete_0.1_0_tx_pd_ot_saved

Train a model on the dataset
Predicted API: MIOSTONE.experiment.train_model

The task is to train a machine learning model on a given dataset. We solved it by using the MIOSTONE.experiment.train_model API function, which allows us to train the model with specified hyperparameters and settings. The function takes in the dataset, device (CPU or GPU), and other optional parameters for saving results and models.

Enter Parameters: basic type

The predicted API takes Loading which dataset('mode': str), and The device (CPU or GPU) on which the model will be trained.('device': str), and An instance of the Dataset class containing the data.('dataset': CustomDataset), and The name to use for saving results, losses, and models.('file_name': str), and The directory path to save the results.('results_dir': str), and The directory path to save the loss curves.('losses_dir': str), and The directory path to save the trained models.('models_dir': str), as input. However, there are still some parameters undefined in the query.

Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'mode'?

IBD200
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'device'?

cuda
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'dataset'?

result_6
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'file_name'?

result_13
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'results_dir'?

result_10
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'losses_dir'?

result_11
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'models_dir'?

result_12
python
from MIOSTONE.experiment import train_model
+result_14 = train_model('IBD200', 'cuda', result_6, result_5, result_13, result_10, result_11, result_12)
Executed results [Success]

We obtain a new variable: None

Can you set the model selection parameter for `IBD200` data?
Predicted API: MIOSTONE.visualize_results.set_model_selection_param

The task is to set the model selection parameter for the IBD200 data. We solved it by using the MIOSTONE.visualize_results.set_model_selection_param API function, which allows us to specify the model selection parameter and hue based on the command-line arguments. The function returns a tuple containing the model selection parameter and hue.

python
from MIOSTONE.visualize_results import set_model_selection_param
+result_17 = set_model_selection_param('IBD200')
Executed results [Success]

We obtain a new variable: (None, 'model')

python
result_18, result_19 = result_17
Executed results [Success]

Can you Preprocess the results of the dataset and target?
Predicted API: MIOSTONE.visualize_results.preprocess_results

The task is to preprocess the results of a dataset and target using the MIOSTONE API. This can be done by calling the MIOSTONE.visualize_results.preprocess_results function with the appropriate parameters. The function will return a Pandas DataFrame containing the preprocessed results.

Enter Parameters: basic type

The predicted API takes ('dataset': str), and ('target': str), and ('metric': str), and ('metric_avg': str), and ('combine_folds': bool), and ('seeds_agg': str), and ('hyperparam': List[str]), and ('model_selection': str), and ('model_selection_param': int), as input. However, there are still some parameters undefined in the query.

Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'dataset'?

IBD200
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'target'?

Type
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'metric'?

ap
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'metric_avg'?

macro
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'combine_folds'?

True
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'seeds_agg'?

median
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'hyperparam'?

[]
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'model_selection'?

none
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'model_selection_param'?

result_18
python
from MIOSTONE.visualize_results import preprocess_results
+result_21 = preprocess_results('IBD200', 'Type', 'ap', 'macro', True, 'median', [], 'none', result_18)
Executed results [Success]

We obtain a new variable: model_name ... mixup_alpha
+0 tree_taxo_pruned_ce_1_linear_0.95_concrete_0.1_0 ... 0.0

+

[1 rows x 29 columns]

Executed results [Success]

We visualize the first 5 rows of the table data

model_namemetric_valuenode_gate_paramnode_dim_funcoutput_truncationepochspretrained_seedbatch_sizepreprocessnode_min_dimfocal_gammaoutput_depthtree_datasetprob_labeltaxonomynode_dim_func_paramtransfer_learningseeddataset:targetmixup_num_samplesprune_by_datasetrebalancefoldnode_gate_typemodellosstree_targetft_epochsmixup_alpha
0tree_taxo_pruned_ce_1_linear_0.95_concrete_0.1_00.5884869098663330.1linearTrue30386clr10.00FalseTrue0.95none3IBD200:Type0Truereweightcombinedconcretetreece00.0
Please plot the model metrics based on the result_21 using metric `ap`
Predicted API: MIOSTONE.visualize_results.plot_model_metrics

The task is to plot the model metrics based on the result_21 using the metric "ap". We solved it by using the MIOSTONE.visualize_results.plot_model_metrics API function, which takes the results dataframe, metric, aggregation method, hue, plot type, metric axis, and other axis as parameters. The function returns None.

Enter Parameters: basic type

The predicted API takes ('seeds_agg': str), and ('hue': str), and ('plot_type': str), and ('metric_axis': str), and ('other_axis': str), as input. However, there are still some parameters undefined in the query.

Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'seeds_agg'?

median
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'hue'?

result_19
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'plot_type'?

bar
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'metric_axis'?

y
Enter Parameters: basic type

Which value do you think is appropriate for the parameters 'other_axis'?

model
python
from MIOSTONE.visualize_results import plot_model_metrics
+result_23 = plot_model_metrics(result_21, 'ap', 'median', result_19, 'bar', 'y', 'model')
Executed results [Success]

We visualize the obtained figure

Progress Image
BioMANIA UI is an interface based off of ChatBot UI. We appreciate the authors for their work.
\ No newline at end of file diff --git a/demo/MIOSTONE_IBD200.json b/demo/MIOSTONE_IBD200.json new file mode 100644 index 0000000..7a2d424 --- /dev/null +++ b/demo/MIOSTONE_IBD200.json @@ -0,0 +1,2178 @@ +{ + "version": 4, + "history": [ + { + "id": "7eefb725-7109-40bb-b3d7-39ca52ced7a2", + "name": "New Conversation", + "method": { + "id": "No specified", + "name": "DFS without filter", + "method": "No specified", + "maxLength": 8000 + }, + "messages": [ + { + "role": "assistant", + "content": "Welcome to BioMANIA! How can I help?", + "tools": [], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Change the device for computation to cuda.", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": true + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-1", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-1", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Candidate [1]: MIOSTONE.utils.set_device\nSet the device for PyTorch based on the specified device string.\nCandidate [2]: MIOSTONE.experiment.set_device\nSet the device for PyTorch based on the specified device string.", + "task_title": "Can you confirm which of the following 2 candidates", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "1", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-2", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-2", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_tool_start", + "block_id": "tool-2", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-2", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to set the device for PyTorch based on a specified device string, such as 'cuda', 'mps', or 'cpu'. We solved this by using the `MIOSTONE.utils.set_device` function, which takes the device string as a parameter and sets the device accordingly. The function returns a variable of type 'device'.", + "task_title": "Predicted API: MIOSTONE.utils.set_device", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-3", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-3", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-2", + "task": "from MIOSTONE.utils import set_device\nresult_1 = set_device('cuda')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We obtain a new variable: cuda", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Set the seed as 3", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-5", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-5", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Candidate [1]: MIOSTONE.visualize_results.set_seed\nSet random seeds for reproducibility.\nCandidate [2]: MIOSTONE.utils.set_seed\nSet random seeds for reproducibility.\nCandidate [3]: MIOSTONE.visualize_dimred.set_seed\nSet random seeds for reproducibility.\nCandidate [4]: MIOSTONE.visualize_attr.set_seed\nSet random seeds for reproducibility.\nCandidate [5]: MIOSTONE.experiment.set_seed\nSet random seeds for reproducibility.", + "task_title": "Can you confirm which of the following 5 candidates", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "2", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-6", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-6", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_tool_start", + "block_id": "tool-6", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-6", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The user query is about setting random seeds for reproducibility in programming. The selected API function is `MIOSTONE.utils.set_seed` which allows users to specify a seed value for random number generators. This helps in ensuring that the same random numbers are generated every time the code is run, making the results reproducible.", + "task_title": "Predicted API: MIOSTONE.utils.set_seed", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-7", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-7", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-2", + "task": "from MIOSTONE.utils import set_seed\nresult_2 = set_seed(3)", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We obtain a new variable: None", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Can you load the config for mode `IBD200` dataset?", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-9", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-9", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Candidate [1]: MIOSTONE.visualize_attr.load_config\n\nCandidate [2]: MIOSTONE.experiment.load_config\n\nCandidate [3]: MIOSTONE.visualize_results.load_config\n\nCandidate [4]: MIOSTONE.utils.load_config\n\nCandidate [5]: MIOSTONE.visualize_dimred.load_config\n", + "task_title": "Can you confirm which of the following 5 candidates", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "4", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-10", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-10", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_tool_start", + "block_id": "tool-10", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-10", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The user query is asking for a summary of the task and its solution in simple terms. The selected API function is `MIOSTONE.utils.load_config`, which is used to load a configuration file. The function takes a parameter called `mode` which is a string and is required. The function returns a list.", + "task_title": "Predicted API: MIOSTONE.utils.load_config", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-11", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-11", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-2", + "task": "from MIOSTONE.utils import load_config\nresult_3 = load_config('IBD200')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We obtain a new variable: namespace(seed=3, device=device(type='cuda'), dataset='IBD200', target='Type', prob_label=False, rebalance='reweight', preprocess='clr', phylogeny='WoL2', taxonomy=True, prune_by_dataset=True, tree_dataset='none', tree_target='none', prune_by_num_leaves=-1, model='tree', mlp_type='pyramid', node_min_dim=1, node_dim_func='linear', node_dim_func_param=0.95, node_gate_type='concrete', node_gate_param=0.1, output_depth=0, output_truncation=True, transfer_learning='none', pretrained_model_path='', ft_epochs=30, k_fold=3, batch_size=386, epochs=1, loss='ce', mixup_num_samples=0, metrics=['accuracy', 'auroc', 'ap'], save_model=True, plot_loss=False, combine_folds=True, seeds_agg='median', metric='ap', metric_avg='macro', metric_axis='y', plot_type='bar', other_axis='model', hyperparam=[], model_selection='none', top_k=5, algorithm='pca', depth=-1, embedding_reduction='none', leaf_attr='deeplift', layer_deeplift=True, num_samples=None, top_k_nodes=None, min_depth=0, max_depth=5, visualize_depth=5, save_attributions=False)", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Can you help me with loading and preprocessing the data?", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-13", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-13", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to load and preprocess data, and we solved it by using the MIOSTONE.experiment.load_and_preprocess_data API function. This function allows us to specify the dataset we want to load and the path to save the data. It returns a tuple containing the custom tree, dataset, pretrained seed, and hyperparameters.", + "task_title": "Predicted API: MIOSTONE.experiment.load_and_preprocess_data", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "The predicted API takes loading which dataset('mode': str), and path to save data('pre_data_path': str), as input. However, there are still some parameters undefined in the query.", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-15", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-15", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "Which value do you think is appropriate for the parameters 'mode'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "IBD200", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-16", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-16", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'pre_data_path'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "./tmp/data", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-17", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-17", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-1", + "task": "from MIOSTONE.experiment import load_and_preprocess_data\nresult_4 = load_and_preprocess_data('IBD200', './tmp/data')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "We obtain a new variable: (Tree node 'root' (0x7f9874dc142), , None, None)", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "code-3", + "task": "result_5, result_6, result_7, result_8 = result_4", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-4", + "task": "", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Create a directory to store the results, losses, and models for the given dataset and target.", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-21", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-21", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to create a directory where we can store the results, losses, and models for a specific dataset and target. We solved this by using the MIOSTONE API function called `set_results_dir`, which sets up the necessary directories for storing the data. The function takes the dataset name and target directory as parameters and returns a tuple containing the paths to the results, losses, and models directories.", + "task_title": "Predicted API: MIOSTONE.experiment.set_results_dir", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "The predicted API takes The name of the dataset.('dataset': str), and The target directory for storing results.('target': str), as input. However, there are still some parameters undefined in the query.", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-23", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-23", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "Which value do you think is appropriate for the parameters 'dataset'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "IBD200", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-24", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-24", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'target'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Type", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-25", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-25", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-1", + "task": "from MIOSTONE.experiment import set_results_dir\nresult_9 = set_results_dir('IBD200', 'Type')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "We obtain a new variable: ('../results/IBD200/Type', '../results/IBD200/Type/losses', '../results/IBD200/Type/models')", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "code-3", + "task": "result_10, result_11, result_12 = result_9", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-4", + "task": "", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Please set the file name under mode 'IBD200'", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-29", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-29", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to set a file name under the mode 'IBD200'. We solved it by using the MIOSTONE.experiment.set_file_name API function, which generates a file name based on the provided arguments. The function takes the mode as a parameter and returns the generated file name as a string.", + "task_title": "Predicted API: MIOSTONE.experiment.set_file_name", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-30", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-30", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-2", + "task": "from MIOSTONE.experiment import set_file_name\nresult_13 = set_file_name('IBD200')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We obtain a new variable: 3_tree_clr_reweight_386_1_ce_1_linear_0.95_concrete_0.1_0_tx_pd_ot_saved", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Train a model on the dataset", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-32", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-32", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to train a machine learning model on a given dataset. We solved it by using the MIOSTONE.experiment.train_model API function, which allows us to train the model with specified hyperparameters and settings. The function takes in the dataset, device (CPU or GPU), and other optional parameters for saving results and models.", + "task_title": "Predicted API: MIOSTONE.experiment.train_model", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "The predicted API takes Loading which dataset('mode': str), and The device (CPU or GPU) on which the model will be trained.('device': str), and An instance of the Dataset class containing the data.('dataset': CustomDataset), and The name to use for saving results, losses, and models.('file_name': str), and The directory path to save the results.('results_dir': str), and The directory path to save the loss curves.('losses_dir': str), and The directory path to save the trained models.('models_dir': str), as input. However, there are still some parameters undefined in the query.", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-34", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-34", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "Which value do you think is appropriate for the parameters 'mode'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "IBD200", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-35", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-35", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'device'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "cuda", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-36", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-36", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'dataset'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_6", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-37", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-37", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'file_name'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_13", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-38", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-38", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'results_dir'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_10", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-39", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-39", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'losses_dir'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_11", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-40", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-40", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'models_dir'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_12", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-41", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-41", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-1", + "task": "from MIOSTONE.experiment import train_model\nresult_14 = train_model('IBD200', 'cuda', result_6, result_5, result_13, result_10, result_11, result_12)", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "We obtain a new variable: None", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Can you set the model selection parameter for `IBD200` data?", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-49", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-49", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to set the model selection parameter for the `IBD200` data. We solved it by using the `MIOSTONE.visualize_results.set_model_selection_param` API function, which allows us to specify the model selection parameter and hue based on the command-line arguments. The function returns a tuple containing the model selection parameter and hue.", + "task_title": "Predicted API: MIOSTONE.visualize_results.set_model_selection_param", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-50", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-50", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-2", + "task": "from MIOSTONE.visualize_results import set_model_selection_param\nresult_17 = set_model_selection_param('IBD200')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We obtain a new variable: (None, 'model')", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "code-4", + "task": "result_18, result_19 = result_17", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-5", + "task": "", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Can you Preprocess the results of the dataset and target?", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-65", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-65", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to preprocess the results of a dataset and target using the MIOSTONE API. This can be done by calling the `MIOSTONE.visualize_results.preprocess_results` function with the appropriate parameters. The function will return a Pandas DataFrame containing the preprocessed results.", + "task_title": "Predicted API: MIOSTONE.visualize_results.preprocess_results", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "The predicted API takes ('dataset': str), and ('target': str), and ('metric': str), and ('metric_avg': str), and ('combine_folds': bool), and ('seeds_agg': str), and ('hyperparam': List[str]), and ('model_selection': str), and ('model_selection_param': int), as input. However, there are still some parameters undefined in the query.", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-67", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-67", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "Which value do you think is appropriate for the parameters 'dataset'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "IBD200", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-68", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-68", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'target'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Type", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-69", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-69", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'metric'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "ap", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-70", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-70", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'metric_avg'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "macro", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-71", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-71", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'combine_folds'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "True", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-72", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-72", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'seeds_agg'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "median", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-73", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-73", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'hyperparam'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "[]", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-74", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-74", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'model_selection'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "none", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-75", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-75", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'model_selection_param'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_18", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-76", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-76", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-1", + "task": "from MIOSTONE.visualize_results import preprocess_results\nresult_21 = preprocess_results('IBD200', 'Type', 'ap', 'macro', True, 'median', [], 'none', result_18)", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "We obtain a new variable: model_name ... mixup_alpha\n0 tree_taxo_pruned_ce_1_linear_0.95_concrete_0.1_0 ... 0.0\n\n[1 rows x 29 columns]", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "We visualize the first 5 rows of the table data", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "", + "tableData": ",model_name,metric_value,node_gate_param,node_dim_func,output_truncation,epochs,pretrained_seed,batch_size,preprocess,node_min_dim,focal_gamma,output_depth,tree_dataset,prob_label,taxonomy,node_dim_func_param,transfer_learning,seed,dataset:target,mixup_num_samples,prune_by_dataset,rebalance,fold,node_gate_type,model,loss,tree_target,ft_epochs,mixup_alpha\n0,tree_taxo_pruned_ce_1_linear_0.95_concrete_0.1_0,0.588486909866333,0.1,linear,True,3,0,386,clr,1,0.0,0,,False,True,0.95,none,3,IBD200:Type,0,True,reweight,combined,concrete,tree,ce,,0,0.0", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "Please plot the model metrics based on the result_21 using metric `ap`", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-88", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-88", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "The task is to plot the model metrics based on the result_21 using the metric \"ap\". We solved it by using the MIOSTONE.visualize_results.plot_model_metrics API function, which takes the results dataframe, metric, aggregation method, hue, plot type, metric axis, and other axis as parameters. The function returns None.", + "task_title": "Predicted API: MIOSTONE.visualize_results.plot_model_metrics", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "The predicted API takes ('seeds_agg': str), and ('hue': str), and ('plot_type': str), and ('metric_axis': str), and ('other_axis': str), as input. However, there are still some parameters undefined in the query.", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + }, + { + "method_name": "on_tool_start", + "block_id": "tool-90", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-90", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-3", + "task": "Which value do you think is appropriate for the parameters 'seeds_agg'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "median", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-91", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-91", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'hue'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "result_19", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-92", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-92", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'plot_type'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "bar", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-93", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-93", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'metric_axis'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "y", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-94", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-94", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "log-1", + "task": "Which value do you think is appropriate for the parameters 'other_axis'?", + "task_title": "Enter Parameters: basic type", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "red" + } + ], + "recommendations": [], + "files": [] + }, + { + "role": "user", + "content": "model", + "tools": [], + "recommendations": [], + "files": [], + "conversation_started": false + }, + { + "role": "assistant", + "content": "", + "tools": [ + { + "method_name": "on_tool_start", + "block_id": "tool-95", + "api_name": "", + "api_description": "", + "api_calling": "", + "depth": 0 + }, + { + "method_name": "on_tool_end", + "block_id": "tool-95", + "task": "", + "status": "0", + "depth": 0 + }, + { + "method_name": "on_agent_action", + "block_id": "code-1", + "task": "from MIOSTONE.visualize_results import plot_model_metrics\nresult_23 = plot_model_metrics(result_21, 'ap', 'median', result_19, 'bar', 'y', 'model')", + "task_title": "Executed code", + "composite_code": "", + "imageData": "", + "tableData": "", + "depth": 0, + "color": "black" + }, + { + "method_name": "on_agent_action", + "block_id": "log-2", + "task": "We visualize the obtained figure", + "task_title": "Executed results [Success]", + "composite_code": "", + "imageData": "iVBORw0KGgoAAAANSUhEUgAABdwAAAXcCAYAAAA4NUxkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC9/ElEQVR4nOzdZ5iV1fk+7GvT+wiiogKKvSuKiGJBsWAvwYYKWGKMvSZRE0uifxNbxG6iBoma2DtGjCUW7D32hgVsgAwo0vf7wXfm54QiOA8M5TyPYx9xntXuPUzmw7XXrFUql8vlAAAAAAAAtVKvrgsAAAAAAICFgcAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAoQIO6LmBRNW3atIwYMSItW7ZMqVSq63IAAAAAABZ55XI548aNyzLLLJN69eZ8v7rAvY6MGDEiHTp0qOsyAAAAAAD4H5988knat28/x+ME7nWkZcuWSb7/h2vVqlUdVwMAAAAAwNixY9OhQ4fq/HZOCdzrSNUxMq1atRK4AwAAAADMR37qMeAuTQUAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAoQIO6LoA5N2XKlEyZMqWuywAoVL169dKwYcOUSqW6LgUAAADgJxG4L0DGjx+fkSNH5ttvv63rUgDmioYNG6Zly5Zp27Zt6tevX9flAAAAAMwRgfsCYtKkSfnkk0/SsGHDLL300mncuLFdoMBCo1wuZ+rUqfnmm28yZsyYfPfdd+nQoYPQHQAAAFigCNwXEF9++WXq16+f5ZZbTgAFLLRatGiRioqKfPzxxxk5cmSWWmqpui4JAAAAYLa5NHUBUC6XM378+FRUVAjbgYVe06ZN06pVq4wbNy7lcrmuywEAAACYbQL3BcDkyZMzderUNG3atK5LAZgnWrZsmcmTJ2fy5Ml1XQoAAADAbBO4LwCmTZuWJHa3A4uMqt93Vb//AAAAABYEAvcFiEtSgUWF33cAAADAgkjgDgAAAAAABRC4AwAAAABAARrUdQEUp/sl3eu6hDny5FFPFjrf8ssvn48++qjGs0aNGmWJJZbIBhtskJ///OfZaaedCl1zbnj00Uez5ZZbZosttsijjz5a1+X8JD169Mh//vOfWfY55phjctFFF82bggAAAABgHhC4s9Dp3r17VlpppSRJZWVlXnrppdx99925++67c9xxx+XCCy+s4woXHeuuu27WW2+9GbZ17dp13hYzlwwbNiydOnXKcsstl2HDhtV1OQAAAADUIYE7C51DDjkk/fv3r/56ypQpOe6443LppZfmz3/+c/bdd99suOGGdVfgImS33XbLGWecUddlAAAAAMA84Qx3FnoNGjTIeeedl1atWiVJ7rnnnjquCAAAAABYGAncWSQ0adIkK6+8cpLkiy++mK793//+d4466qist956adu2bRo3bpz27dtn7733znPPPTfDOc8444yUSqWcccYZ+eqrr3LEEUekQ4cOadSoUTp06JCjjjoqY8aMmWlNgwYNyoYbbphmzZqlTZs26dWrVx5//PEffS/PPvts9tprryyzzDJp1KhRllxyyey888558MEHZ9i/f//+KZVKGThwYN5+++3svffeWXLJJdO8efNsuOGGueuuu6r7PvPMM9lll12yxBJLpGnTptl4443z0EMP/WhNRRg9enROOeWUrLnmmmnWrFlatmyZDTbYIOeee26+++676fo/+uijKZVK6dGjR8aPH5/TTjstq6++epo1a5bll1++Rt8XXngh++23Xzp27JjGjRunTZs22W677TJ48OAZ1vLZZ5/lmGOOySqrrJImTZqkWbNm6dChQ3r27Jnzzz+/ul///v3TqVOnJMlHH32UUqlU4wUAAADAosWRMiwyxo4dmyRZaqmlpms77LDD8sknn2TNNddM9+7d06BBg7z11lu5+eabc/vtt+ef//xnfvazn81w3k8++STrr79+Jk+enO7du2fChAl58sknc+mll+aZZ57Jk08+mYYNG9YYc8wxx+Tiiy9OvXr1summm2aZZZbJq6++mh49euSoo46a6Xv461//msMOOyzTpk1L586d06NHj3z00Ue59957c++99+aMM87I6aefPsOxL774Yo488si0b98+PXv2zEcffZSnnnoqu+++e26++eY0aNAge+21V9Zaa6307Nkzb731Vp5++un06tUrjzzySDbddNPZ/VbPsQ8++CBbbbVVPvrooyyxxBLZYYcdMnny5DzyyCP59a9/nZtuuin//ve/07p16+nGTpgwIT169Mgbb7yRzTffPOuuu25GjRpV3T5gwIAcf/zxmTZtWtZbb71stNFG+fzzz/Poo49myJAhOfPMM3PaaadV9//888/TpUuXjBgxIh07dkyvXr3SpEmTjBgxIi+//HJeeOGFnHjiiUmSTTfdNN98801uu+22NG/ePL17955r3yMAAAAA5n8CdxYJb775Zj744IMkyS677DJd+/nnn58ttthiukD3zjvvzJ577plf/OIX2WGHHdK0adPpxl577bXp379/rrzyyjRu3DjJ9yH8xhtvnOeeey633npr9t133+r+9913Xy6++OI0b948999/fzbbbLPqtnPOOSennHLKDN/Da6+9lsMPPzzlcjmDBg3KAQccUN12//33V5+Xvskmm2SbbbaZbvwll1ySs846K6ecckr17utLLrkkRx99dI477rh8++23ueaaa2rMe9xxx+Wiiy7KmWeeOdMd9EXo06dPPvroo+yyyy658cYb07x58yTJV199lV69elV/WHDDDTdMN/aZZ57JOuusk/feey/t2rWr0fbAAw/kuOOOy+KLL57bbrstm2++eXXba6+9lh122CGnn356tthii2yxxRZJkr/85S8ZMWJEDj300Fx55ZU1dqpPnjw5jz32WPXXhxxySLbeeuvcdtttadu2bQYOHFjktwUAAACABYwjZVioVVZWZsiQIdljjz0yderU/Pa3v02XLl2m67fbbrvNcPf0brvtlj333DOjRo3KI488MsM12rdvn8suu6w6bE9SfaRM8v1xNT900UUXJUmOPPLIGmF7kpx88slZb731ZrjOgAEDMmXKlOy+++41QvEk2X777XPooYcmSc4777wZju/atWuNsD1JfvnLX6ZNmzb59NNPs/XWW083729/+9skyWOPPZbJkyfPcN5ZOfPMM6c7ZqVUKtU48uWJJ57IM888k2bNmuUvf/lLddieJEsssUT+8pe/JEn++c9/5tNPP53hOpdeeul0YXuSnH766SmXy7nyyitrhO1Jsvbaa+fCCy9M8v0HD1Wqjhzq1avXdMfCNGzYMD179pyD7wAAAAAAixI73FnoHHjggTnwwANrPKtfv36uv/767LfffjMdN2LEiNx333156623UllZmSlTpiRJXn/99STJ22+/nR122GG6cT179kyzZs2me7766qsnSYYPH179bMqUKXniiSeSJPvvv/8M6+jbt29efvnl6Z4/+uijSb4/N3xGDj744Fx66aV5/PHHM3Xq1NSvX79G+/bbbz9dgNygQYN06tQpo0ePnuF7W3zxxdOmTZuMHj06o0aNmmGoPSvrrrvuDD9AaNu27XTvq1evXjM87meDDTbIuuuum1deeSX/+c9/pvs3XHLJJaf74CJJRo4cmWeffTZNmzbNzjvvPMP6evTokSQZOnRo9bOuXbvm8ssvz29+85uUy+Vsu+22adGixY+9VQAAAAAQuLPw6d69e1ZaaaUk3x9J8vjjj2fcuHH55S9/mZVXXjldu3adbsyZZ56Zs88+e5a7uKvOgP9fHTt2nOHzVq1aJfn+jPEqo0aNqv666rLN/zWz51XB/czaV1xxxer1Ro0alSWXXHK26qwKk2fW3rJly4wePbrG+5hdVcfczMqPva/k+/f2yiuv1Pjwosr/XpBa5cMPP0y5XM53331X468PZuSrr76q/u8DDjggDz74YG644Yb87Gc/S/369bPGGmtk0003Te/evbPVVlvNci4AAAAAFl0CdxY6hxxySI1d4JWVldl9993zyCOPZK+99sobb7xRY0f67bffnjPOOCMtWrTIpZdemq222irLLLNMmjZtmlKplFNOOSXnnHNOyuXyDNerV2/BOJnpx+pcUN7H/5rRufpJMm3atCTff6AwswtvZ6RevXq5/vrrc8opp+S+++7Lk08+mSeffDJXXHFFrrjiiuy888654447pvsLAgAAAAAQuLPQq6ioyE033ZTVVlstH330US688MLqs8mT5Oabb06SnH322dXnoP/Qu+++W1gtiy++eBo3bpyJEydm2LBhWXPNNafrM2zYsBmOXXbZZfP+++/ngw8+yFprrTVde9WlsE2aNEmbNm0Kq3luW3bZZZP8X/0zUtVW1Xd2dOjQIUlSKpVy7bXXzvEHCmussUbWWGONnHTSSSmXy3n44YfTp0+f3HPPPRk0aNB0xxYBAAAAwIK5pRXm0BJLLFEdsp9//vkZM2ZMddvo0aOTJMstt9x047788ss8+OCDhdXRoEGDdO/ePUlyww03zLDP3//+9xk+rzpvfODAgTNsv/baa5Mkm222WRo0WHA+S6t6X//617+qLyz9oZdeeikvv/xy6tWrN93Fp7OyzDLLZJ111sm4cePyr3/9q1Y1lkql9OzZM3369EmSGmfsN2rUKEmqz/wHAAAAYNElcGeRcfjhh6djx46prKzMBRdcUP286nLTv/zlL5k0aVL188rKyvTr1y+VlZWF1nHssccmSS655JIal3UmybnnnpsXX3xxhuOOOeaYNGjQIHfeeWeuv/76Gm1DhgzJVVddlSQ58cQTC613btt0002z0UYb5bvvvssvfvGLjB8/vrpt5MiR+cUvfpEk2Weffap3rc+us846K8n3F+nec88907WXy+U888wzGTJkSPWzQYMG5YUXXpiu77hx46oveP3hhzNLLLFEGjVqlM8//7z6wxsAAAAAFk0CdxYZjRs3rr7Ac8CAAdXh6LHHHpvFFlssgwcPzgorrJDevXtn1113zXLLLZdXXnklBx10UKF17LzzzjniiCPyzTffZLPNNsuWW26ZPn36ZK211srJJ5+cY445Zobj1l577Vx22WUplUo54IADssEGG2S//fbLpptuml69emXixIk544wzsu222xZa77xw4403Zrnllstdd92VTp06Zc8998xuu+2WFVdcMc8991zWX3/9XHrppXM8784771z9b73LLrtk5ZVXzk477ZT99tsv2267bdq1a5du3brl4Ycfrh5z++23p0uXLll22WWz4447Zv/998+OO+6YDh065OWXX85aa62Vn//859X9GzZsmF122SVTp07Neuutlz59+uSQQw7JIYccUsj3BgAAAIAFh8CdRUrfvn2zxhprZNy4cTnvvPOSJJ06dcpLL72U/fbbL/Xr18+9996bV155Jfvuu29eeumlOd5VPTsuvfTSXHvttencuXOefvrpDB48OEsvvXQeeuih7LbbbjMdd+ihh2bo0KHp3bt3RowYkZtvvjlvvfVWdthhhwwZMiSnn3564bXOCyussEJefPHFnHzyyVl88cVz77335sEHH8yKK66YP/7xj3niiSfSunXrnzT30UcfnZdeeimHHnpoSqVSHnroodx55515//3307lz51x88cU5+uijq/ufcMIJOfbYY9O+ffu8+OKLueWWW/Liiy9mjTXWyCWXXJKnn346LVu2rLHGVVddlV/84hcplUq59dZbc8011+Saa66p1fcEAAAAgAVPqVwul+u6iEXR2LFjU1FRkcrKyrRq1WqWfSdMmJAPP/wwnTp1SpMmTeZRhQB1x+89AAAAoC7MSW47I3a4AwAAAABAAQTuAAAAAABQAIE7AAAAAAAUQOAOAAAAAAAFELgDAAAAAEABBO4AAAAAAFAAgTsAAAAAABRA4A4AAAAAAAVY6AL3t99+O5dcckn69++ftddeOw0aNEipVMpZZ51Vq3n//e9/Z4cddkjbtm3TtGnTrLbaajn11FPzzTffFFQ5AAAAAAALsgZ1XUDRrrjiigwYMKDQOf/85z/n+OOPT6lUymabbZallloqjz/+eP7f//t/ue222/LEE0+kbdu2ha4JAAAAAMCCZaHb4b7WWmvlxBNPzA033JA333wzBxxwQK3me+mll3LCCSekfv36ue+++/Kf//wnN998c95///307Nkzb7/9dg477LCCqgcAAAAAYEG10O1wP+SQQ2p8Xa9e7T5TOOecc1Iul3PggQdm++23r37erFmzXHPNNVlhhRVy22235a233spqq61Wq7UAAAAAAFhwLXQ73Is0adKk3HfffUmSPn36TNe+3HLLpXv37kmSO+64Y57WBgAAAADA/EXgPgvvvPNOxo8fnyTp0qXLDPtUPX/ppZfmWV0AAAAAAMx/BO6z8OGHHyZJFltssbRs2XKGfTp06FCjL3Vn+eWXT6lUSqlUyjHHHDPLvuedd1513wYNijtZqX///imVShk4cGBhYwcOHJhSqZT+/fsXUuOCpOq9//BVr169VFRUpGvXrjn77LPzzTff1HWZAAAAAJBkITzDvUjjxo1LkjRv3nymfVq0aJEkGTt27CznmjhxYiZOnFj99Y/1/yk+/v3ahc85N3U87bW5NvcNN9yQ8847L40aNZph+7XXXjvX1p6RgQMH5sADD0y/fv1+Uhi/qGvevHl69+6dJJk6dWo++OCDPP3003nuuecyaNCgPPbYY1lqqaXquMq65WcMAAAAoO7Z4T6PnHPOOamoqKh+Ve2Mp3hdunTJqFGjctddd82wfejQoXnrrbey4YYbzuPKZu2cc87Jm2++md13372uS5nvtG3bNgMHDszAgQPz97//PU8++WSeeuqptGjRIu+8805OOumkui4RAAAAAATus1J1jMy333470z5Vx1m0atVqlnOdfPLJqaysrH598sknxRVKDQcddFCSme9iv+aaa2r0m18svfTSWW211VJRUVHXpSwQunbtmhNOOCFJcvvtt2fKlCl1XBEAAAAAizqB+ywsv/zySZIxY8ZUHy/zv6qC86q+M9O4ceO0atWqxou5Y+21106XLl0yZMiQDB8+vEbbN998k5tvvjnt27fPtttuO9M5qs4Ln5kePXqkVCrl0Ucf/dF6ll9++Rx44IFJkuuuu67GeeQ9evSo7vdTzn+//fbbc8ghh2SttdZK69at06RJk3Tq1CkHHXRQ3n777en6b7HFFimVSvnHP/4x0znPPffclEql7LXXXtO1vfDCC9lvv/3SsWPHNG7cOG3atMl2222XwYMHz/S9l0qlDBs2LHfddVe22mqrtGnTZra/dz9mgw02SPL9h2IjR46sfj5lypRcffXV6dGjR9q0aZPGjRunU6dO+eUvfznDD7seffTR6n+P8ePH57TTTsvqq6+eZs2aTff/7RdeeCH9+vVLp06d0qRJk7Rp0ybrrrtuTjrppHz00UfTzT1ixIgcf/zx1fO1bNkyG264YS699NIZfkjww5+DV155JXvssUeWWGKJNG3aNOuss04GDBiQqVOn1hgzuz9jP/y5ffzxx7PzzjtniSWWSL169Wr83H366ac56qijsvLKK6dJkyapqKhI9+7dc9VVV023dlLznoFvv/02J598clZaaaU0btw47dq1S79+/ab7/yIAAADAwkjgPgurrrpqmjVrliR5/vnnZ9in6vn6668/z+rixx100EGZNm3adOH1zTffnG+++Sb9+vVLvXrz5se/d+/e6d69e5JkxRVXTL9+/apfvXr1qtXce+21V/7xj3+kadOm2WqrrbLddtulXr16+dvf/pYNNtggQ4cOrdG/6jLZSy+9dIbzTZs2LVdccUWS5Mgjj6zRNmDAgHTt2jU33nhjFl988eyyyy5Zc8018+ijj2bHHXfM73//+5nWecEFF2S33XbLuHHj0qtXr2yxxRapX79+bd56kpp3ITRu3DjJ93cvbLPNNvn5z3+eF154Ieuss0522WWXNG7cOFdeeWU6d+6cl156aYbzTZgwIT169MiFF16YTp06ZZdddsnKK69c3X7eeeela9euGTRoUBo1apRdd901m266aSZPnpzzzz8/jzzySI35Hnvssay11lr585//nAkTJmSbbbZJ9+7d8/777+eoo47KjjvumMmTJ8+wlmeffTbdunXLSy+9lJ49e2bzzTfP22+/nWOPPTb77LNPyuVydd85/Rm75ZZb0qNHj3zwwQfZeuuts80221R//5577rmsu+66ufTSSzNp0qTstttu2WSTTfLiiy/msMMOy4477phJkybNsObKyspssskmufLKK7PGGmtk++23T7lczqBBg9K9e/dUVlbOcBwAAADAwsKlqbPQqFGj7Ljjjrnlllty4403Zsstt6zR/tFHH1UHms7dnr/06dMnJ5xwQgYOHJhTTz21+vm1116bUqk0T4+TOf/88zNw4MA8+eST2XTTTQu90PKGG27ITjvtVONi33K5nCuuuCJHHHFEDj300Lz22mvVu/V33XXXLLfcchk6dGheeumldO7cucZ8gwcPzrBhw7LOOutk8803r37+wAMP5Ljjjsviiy+e2267rUbba6+9lh122CGnn356tthii2yxxRbT1XnFFVfkrrvuyi677FLYe0+SO++8M0nSsWPHtG7dOkly2GGH5dFHH81OO+2Ua665JksuuWR1/4suuijHHXdc9t5777z55pvThf7PPPNM1llnnbz33ntp165djba77747v/rVr9KkSZNcd9110/0FwBtvvFHjryI+//zz7LHHHhkzZkwuv/zy/OIXv6j+kGfUqFHZa6+9MmTIkJxzzjk57bTTpntvV1xxRQ4//PAMGDAgDRp8/6v69ddfz5Zbbplbb701f/nLX/KLX/wiyZz/jF1++eW57LLLcvjhh9d4PnHixOy5554ZPXp0DjvssFx88cVp2LBhkuSDDz5Iz54988ADD+TMM8/M2WefPd28d955Z7bbbrs8/vjj1X/F8/XXX2errbbKyy+/nMsvvzwnn3zyLGsDAAAAWJDZ4Z7vd/uuttpq6du373Rtv/nNb1IqlfK3v/0t//rXv6qfjx8/PgcffHCmTp2an/3sZ1lttdXmZcn8iIqKiuyxxx5577338p///CdJ8vbbb+fJJ5/MFltskRVWWKGOKyzG3nvvXSNsT74/Dufwww/PxhtvnNdffz1vvvlmdVv9+vVzxBFHJEkuu+yy6ear2vle1afK6aefnnK5nCuvvLJG2J58f4TPhRdemCS55JJLZlhnv379Cgvbp06dmvfeey/HHntsbr311iTJsccemyR58803849//CPLLLNMbrzxxhphe1W/HXbYIe+++27uv//+Gc5/6aWXThe2J99/D5Lk7LPPnuFxO2ussUZWX3316q8vuuiijBo1KkcccUR++ctf1viLisUXXzyDBg1Kw4YNc+mll9bYrV5l6aWXzgUXXFAdtifJmmuuWR3OX3DBBTOsf3ZstdVW04Xtyfc73z/66KMss8wyueiii6rD9iRZYYUVcv755yf5/t95woQJ041v3rx5/va3v9U4Mqt169b5zW9+kyT597///ZNrBgAAAFgQLHSB+4svvphu3bpVv+67774kyVVXXVXj+WeffVY9ZuTIkXn77bfz8ccfTzff+uuvnwsuuCBTp07NDjvskC233DJ77713VlpppTz00ENZddVVc+WVV86z98fs+9/LU6v+d367LLW23nvvvVx66aU59thjc/DBB6d///7p379/vvjiiySZ7iz3Qw45JM2aNcuNN96Yr7/+usY8Q4YMyWKLLZb999+/+vnIkSPz7LPPpmnTptl5551nWEPVOeH/e4RNld69e9fmLeajjz6qPpO8QYMGWXnllTNgwIDUq1cvxx9/fHXgPnjw4JTL5Wy//fbVlx7PSa1LLrlkNttss+mef/7553n55ZdTr169HHzwwbNVc9Xvnr333nuG7csuu2xWXnnlfPXVV3n33Xena99rr73SpEmT6Z7369cvSfLuu+9mxIgRs1XL/5rZv0fVufr77LNP9REzP7THHnukdevWGTduXF544YXp2rt06ZKll156uudVH0Q4xx0AAABY2C10R8qMHTs2zzzzzHTPP/3003z66afVX0+cOHG25zzuuOOy9tpr54ILLsizzz6bb7/9Nh07dszJJ5+ck08+eabBHnVryy23TKdOnXLrrbfmoosuyqBBg9KqVatah7/zi6lTp+bII4/MVVddNcMd0lV+eM558v2O4wMOOCBXXXVVrrnmmpx44olJvj9mpFwu58ADD6y+uyBJPvzww5TL5Xz33XczDGF/6Kuvvprh8x+7VPjHNG/evPrfrVQqpUWLFllllVWy0047pVOnTtX9PvjggyTJNddck2uuuWaOa51ZnVUfxi299NKpqKiYrZqraplRgD+jWlZZZZUaz374vn6oZcuWWXzxxTNq1Kh8+umnWWaZZWarnh+a2fusCsRntnapVEqnTp3y9ddfzzA879ix4wzHVe14n9GueAAAAICFyUIXuPfo0WOW4eOMnHHGGTnjjDNm2WfrrbfO1ltvXYvKmNdKpVL69++f008/Pf369cvnn3+eQw89NE2bNq313NOmTSugwtoZMGBArrzyyrRr1y4XXnhhNtlkkyy11FLVu6L79OmTf/zjHzP8/8PRRx+dq666KldccUWOP/74TJgwIX/7299SKpWmO06m6r22aNEiP/vZz35SrbX9nrdt23a2zr6vqnW99dbLuuuuO8u+G2200XTPivjZ+N9aevfuPd2xP/9r8cUX/0lrzOnvuipFvs8fmlcXEQMAAADMrxa6wB1+qH///jnzzDNzzz33JJn942QaNmyYyZMnZ9y4cTP8C4aPPvqo0Dp/iptvvjnJ98clzeh89BkdU1JljTXWyNZbb51///vfuf/++zNixIiMGTMm22+/fVZcccUafTt06JDk+w8wrr322vk6VK2qtXv37tXn0Rehauf2Z599lsrKytna5d6hQ4e8++67+fWvf50uXbrM8ZoffvjhDJ+PGzcuo0aNSpK0b99+juedlWWXXTbJ/+3On1VdVX0BAAAA+D/zb3IGBejYsWN23XXXLL744unWrdsMdzXPSFWY+MMLR6u8+uqr+eSTT+aojkaNGiVJpkyZMkfjZmX06NFJkuWWW266ttdffz0vv/zyLMcfc8wxSb6/JLTqAtUjjzxyun7LLLNM1llnnYwbN67GxcHzo+233z5Jcvfddxd6fEm7du2y7rrrZtq0adV3AcxuLVUfjMypW265ZYZHX/39739Pkqy00ko1Qu8ifsaqzre/6aabZvj9u+OOO/L111+nZcuW2WCDDX7yOgAAAAALK4E7C73bb789I0eOzFNPPTXbY6qODzrzzDNrhJ7Dhg1Lv3795vgoj6qdyG+88cYcjZuVqosoL7vsshpH3Hz22Wfp27fvjwavO+ywQ1ZaaaX861//yiuvvJIVV1yxOiT+X2eddVaS5MADD6z+a4EfKpfLeeaZZzJkyJCf+nYK0blz5/zsZz/LJ598kj322CPDhg2brs+3336bG264ofpS2dl1+umnJ0lOPfXU3HbbbdO1v/HGGzU+oDnppJOy2GKL5cILL8wFF1yQSZMmTTfmww8/zPXXXz/D9UaMGJETTzwxU6dOrX725ptv5ve//32S7++W+KEifsb23HPPdOzYMSNGjMjxxx9f42foww8/zAknnJAkOeqoo2Z4oSsAAADAok7gDjNwyimnZLHFFsvgwYOzyiqrpHfv3tliiy2yxhprpG3bttlkk03maL5u3bplmWWWyUsvvZT1118//fr1yyGHHJLzzjuvVjU2atQof/3rX7Pqqqtm7733rj4SZuLEidl9991nOb5evXo1drQffvjhKZVKM+y78847Z8CAARk9enR22WWXrLzyytlpp52y3377Zdttt027du3SrVu3PPzwwz/5/RTlb3/7W3r27Jn7778/q666arp27Zq99947e+21V7p27Zo2bdpk//33z9dffz1H8+6+++45++yzM2HChPTu3Turr7569tlnn+y6665Zc801s+aaa9a4sLl9+/a566670rp165x44onp0KFDevbsmf333z8777xzVlpppaywwgozPfrmsMMOy9VXX52VV145++67b3r16pX11lsvX3zxRXbffff88pe/rNG/iJ+xxo0b59Zbb02bNm1yxRVXZKWVVso+++yTHXfcMWussUY+/PDDbLfddtUfPgAAAABQk8AdZqBTp04ZOnRo9thjj4wbNy733ntvvvjii5x66qkZPHhwGjZsOEfzNWrUKA888EB22WWXfPrpp7n++utzzTXX5L777vvJNW600UZ5/vnns8suu+Tbb7/N3Xffnffffz9HHXVUnnrqqbRq1epH59huu+2SJM2aNfvR8+2PPvrovPTSSzn00ENTKpXy0EMP5c4778z777+fzp075+KLL87RRx/9k99PUVq2bJkhQ4bkxhtvzNZbb52PP/44d9xxRx5++OF899132W+//XLHHXdMd1b97DjllFMydOjQ7Lvvvhk3blxuv/32PPHEE2nYsGF+9atfZauttqrRf/PNN8/rr7+e3/3ud2nfvn2ee+653HLLLXn55Zez1FJL5fTTT89f//rXGa610UYbZejQoVlrrbXy4IMP5tFHH83KK6+cCy+8MDfffPN0H44U9TO24YYb5uWXX84RRxyR+vXr54477sjjjz+ezp0754orrsi9995bfXwNAAAAADWVynN6NgaFGDt2bCoqKlJZWfmjweiECRPy4YcfplOnTo5xoFC//e1vc/bZZ+fQQw/NVVddVdflkO8v+r3uuuvyt7/9Lf3796/rcuqM33sAAABAXZiT3HZG7HCHRdRnn32Wyy67LPXq1cuxxx5b1+UAAAAAwAKvQV0XAMxbv/nNbzJ8+PD8+9//zpgxY3LYYYdVX8AKAAAAAPx0AndYxPzzn//Mxx9/nHbt2uXYY4/NH//4x7ouCQAAAAAWCgJ3WMQMGzasrktgFgYOHJiBAwfWdRkAAAAA/ATOcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncWGssvv3xKpVJKpVKOOeaYWfY977zzqvs2aNCgRluPHj1SKpVyxhlnzHT8qFGj8vvf/z7dunVL27Zt07hx4yy99NLp1atX/vKXv2Ty5MmzXP+zzz7Lb37zm6y33npp2bJlGjVqlGWWWSadO3fOz3/+8wwcODBTp06tUc+cvv5XuVzOTTfdlD322CMdOnRIkyZN0rp166y33nr51a9+lY8//nim9Q4cOLB63nXWWSfTpk2bYb8nnngipVIpyy+//HRtP/z3mdVr4MCBs/zeAQAAAMD8qsGPd2FBscFJg+q6hDnywnl959rcN9xwQ84777w0atRohu3XXnvtT5779ttvz4EHHpixY8emRYsW6d69e9q0aZNPPvkkDz30UB544IGcf/75ueuuu7L66qtPN37o0KHZcccdM2bMmLRo0SJdu3bNUkstlW+++SavvfZarr766lx99dXp3bt3WrRokV69es0wwL7uuuuSJNttt13atWs3y5pHjBiR3XffPc8++2xKpVI22GCDdO/ePePHj89TTz2V8847LxdffHEuuOCCHHHEEbOc67XXXsv111+fvn1/2r9f9+7ds9JKK820fVZtAAAAADA/E7iz0OnSpUuef/753HXXXdlzzz2nax86dGjeeuutbLjhhnnuuefmaO477rgje+65Z6ZNm5Zjjz02Z599dpo1a1bdPnz48Bx88MF54IEHsummm+aFF16oEZZPnDgxe+21V8aMGZM+ffrkiiuuSKtWrWqs8dZbb+Xaa69N/fr1kyS/+c1vZlhLVeD+m9/8Jj169JhpzV9//XU222yzfPDBB+ncuXP+/ve/Z80116xunzJlSgYMGJBf//rXOfLIIzN16tQcffTRM5yrWbNmGT9+fE477bTsvffeady48Sy/XzNyyCGHpH///nM8DgAAAADmd46UYaFz0EEHJZn5LvZrrrmmRr/ZNXLkyBx44IGZNm1ajjvuuPz5z3+uEbYnybLLLpu77747m2yySUaPHp0DDjigRvsTTzyR4cOHp0GDBvnLX/4yXdieJKuttlrOPffcNG3adI7qm5kjjzwyH3zwQTp16pSHH364RtieJA0aNMgJJ5yQAQMGJElOPPHEvPnmmzOca+ONN07Xrl3z0Ucf5fLLLy+kPgAAAABYWAjcWeisvfba6dKlS4YMGZLhw4fXaPvmm29y8803p3379tl2223naN7LLrsslZWVWWKJJfL//t//m2m/Ro0a5dJLL03yfcD+n//8p7rtiy++SJK0aNEizZs3n6P1f4oPPvgg//znP5Mk559/fhZbbLGZ9j388MOz7rrrZvLkyTn33HNn2u9Pf/pTkuTss8/O2LFjC60XAAAAABZkAncWSgcddFCmTZs23QWcN998c7755pv069cv9erN2Y//nXfemSTZa6+90qRJk1n27dy5c9Zaa60kyd133139vGPHjkmSMWPGzJPLQe+5555MmzYtiy22WHbZZZdZ9i2VStU78u+5556Uy+UZ9uvRo0e23377jBo1qjp8BwAAAAAE7iyk+vTpk6ZNm04Xal977bUplUpzfJzM5MmT8+qrryZJunbtOltjNtxwwyTJ888/X/1sk002SefOnZMkBx54YLp27Zrf/va3ufPOO/Ppp5/OUU2z44UXXkjy/QcADRr8+JUNVTWPGjUqw4YNm2m/c845J/Xq1ctFF12Uzz77rJBaAQAAAGBBJ3BnoVRRUZE99tgj7733XvWRLm+//XaefPLJbLHFFllhhRXmaL7Ro0dn2rRpSZKlllpqtsZU9fvqq6+qn9WrVy/33Xdftt9++yTJc889l7PPPju77757OnTokFVXXTV/+tOf8t13381RfTNTtfac1vy/df+vddddN3369Mn48eNz5plnzlFNBx54YEql0kxfY8aMmaP5AAAAAGB+8eNbXmEBddBBB+WGG27Itddemy222KL6EtU53d3+U83sSJall146gwcPzuuvv5677747Tz31VF588cUMHz4877zzTn7zm9/kH//4Rx599NFZnrk+L2uekT/84Q+5+eabc8011+T444/PKqusMlvjunfvnpVWWmmm7Y0aNZrtGgAAAABgfiJwZ6G15ZZbplOnTrn11ltz0UUXZdCgQWnVqlV69+49x3O1adMm9erVy7Rp06ovPv0xX375ZZJkiSWWmGH7mmuumTXXXLP66zfffDOXX355Lrvssrzyyis59dRTc9lll81xrT/Utm3bJJnjmpOZ111l+eWXz+GHH56LLroop5xySm699dbZWuOQQw5J//79Z6svAAAAACxIHCnDQqtUKqV///4ZP358+vXrl88//zz77LNPmjZtOsdzNWzYMGuvvXaS5JlnnpmtMc8++2ySZIMNNpit/quvvnouueSSHHXUUUn+75LW2qha+8UXX8yUKVN+tH9VzYsvvniWX375H+1/6qmnplWrVrntttuqxwIAAADAokrgzkKtf//+qVevXu65554ktTtOZtddd02S3HLLLZkwYcIs+7744ot5/fXXkyS77LLLHK2z7bbbJklGjhz5E6qsaeedd069evVSWVmZu+66a5Z9y+Vy/v73vydJdtppp5RKpR+dv23btjnppJOSJL/5zW9qXS8AAAAALMgE7izUOnbsmF133TWLL754unXrlo022ugnz3XkkUemVatW+eqrr3LyySfPtN+kSZOqd6lvvPHG6dGjR3Xb7JyR/vHHHydJ2rdv/5NrrbLiiitmr732SpKcdNJJs7yQ9PLLL8+rr76aBg0aVIfos+O4445Lu3bt8sgjj+T++++vbckAAAAAsMASuLPQu/322zNy5Mg89dRTtZpniSWWyDXXXJNSqZSLLrooxx9/fMaPH1+jz/Dhw7PLLrtk6NChWWyxxap3jFe55557sttuu+XBBx/M1KlTp1vj0UcfzRlnnJEk2WeffWpVb5XLLrssyy+/fD788MNstdVW1Tvvq0yZMiUXXnhhjjnmmCTJn/70pxpny/+Y5s2b57TTTkuSXHTRRYXUDAAAAAALIpemwhzo3bt3brrpphx88MH585//nKuvvjrdu3dP69atM3z48AwdOjRTpkzJiiuumDvvvDMrrrhijfHTpk3LXXfdlbvuuisVFRVZf/31065du3z77bd555138tZbbyVJtt5665x66qmF1NymTZs88cQT2W233fL8889n7bXXTpcuXbLiiitm/Pjxeeqpp/LVV1+lUaNGueCCC6qD9znx85//PH/+85/z7rvv/mjfq6++Oo8++uhM27fddtv06dNnjmsAAAAAgLomcIc5tOeee2bLLbfMZZddlsGDB+fZZ5/NuHHj0rp162y55ZbZY489ctBBB6VRo0bTje3Vq1ceeOCBPPTQQ3nyySfzwQcfVO+8X3LJJbPbbrtl3333zZ577jlbZ6jPrmWXXTbPPPNMbr755vzzn//Mc889l1deeSVNmjTJcsstl759++bII4+crYtSZ6RBgwY5++yzq4+vmZUnn3wyTz755EzbF1tsMYE7AAAAAAukUnl2DpWmcGPHjk1FRUUqKyvTqlWrWfadMGFCPvzww3Tq1ClNmjSZRxUC1B2/9wAAAIC6MCe57Yw4wx0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMB9AVIul+u6BIB5wu87AAAAYEEkcF8A1K9fP0kyefLkOq4EYN6YOHFikqRBgwZ1XAkAAADA7BO4LwAaNmyYxo0bp7Ky0q5PYKE3derUjB49Os2bNxe4AwAAAAsUScYCom3bthk+fHg+/fTTVFRUpGHDhimVSnVdFkAhyuVypk6dmu+++y6VlZWZNm1all566bouCwAAAGCOCNwXEK1atUqSjBw5MsOHD6/jagDmjvr166dZs2ZZcskl06hRo7ouBwAAAGCOCNwXIK1atUqrVq0yefLkTJ06ta7LAShUvXr1/PUOAAAAsEATuC+AGjZsmIYNG9Z1GQAAAAAA/IBLUwEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAowEIbuN9yyy3p0aNHWrdunebNm2fdddfNueeem8mTJ8/xXOPHj88555yT9dZbL82bN0/Lli2z4YYb5pJLLsnUqVPnQvUAAAAAACxoSuVyuVzXRRTt2GOPzYABA9KgQYNstdVWadGiRR5++OGMGTMmm266aYYMGZKmTZvO1lyjR4/OVlttlVdeeSUtW7ZMt27dUr9+/Tz99NMZM2ZMttlmm9x7771p1KjRHNU4duzYVFRUpLKyMq1atfopbxMAAAAAgALVNrdd6Ha433nnnRkwYEBatGiRZ555Jg888EBuu+22vPvuu1l77bXzxBNP5He/+91sz3fYYYfllVdeyVprrZXXX389Q4YMyf3335+33norXbt2zYMPPpgzzzxzLr4jAAAAAAAWBAvdDveuXbvmueeey1lnnZVTTz21RtsTTzyRzTbbLI0bN84XX3yRioqKWc41YsSItG/fPuVyOY888kh69OhRo/3VV1/Nuuuum6ZNm+aLL75Iy5YtZ7tOO9wBAAAAAOYvdrj/wPDhw/Pcc88lSfr06TNd+6abbpoOHTpk4sSJGTx48I/O9/zzz6dcLqdRo0bZfPPNp2tfZ511ssQSS+S7776brfkAAAAAAFh4LVSB+0svvZQkadOmTTp16jTDPl26dKnRd1a++eabJMliiy2WevVm/K1q27ZtkuSFF16Y43oBAAAAAFh4LFSB+4cffpgk6dix40z7dOjQoUbfWVlyySWTJF9++WV1+P5D06ZNy0cffTTb8wEAAAAAsPBaqAL3cePGJUmaN28+0z4tWrRI8v1ZPD9mo402SrNmzZIkV1999XTtgwYNyvjx42drvokTJ2bs2LE1XgAAAAAALDwWqsC9aC1btswJJ5yQJDn55JNz8cUX57PPPsuXX36Zq6++OkcddVQaNmyYJDM9cqbKOeeck4qKiupX1U57AAAAAAAWDgtV4N6yZcskybfffjvTPlVHw8zuDbOnn356DjvssEyYMCHHHHNMlllmmSy11FL5+c9/nvXXXz8HHXRQku/PjZ+Vk08+OZWVldWvTz75ZLbWBwAAAABgwdCgrgso0vLLL58kswyzq9qq+v6Y+vXr54orrsjhhx+eu+++Ox9//HFatGiRHj16ZMcdd8z++++fJFl77bVnOU/jxo3TuHHj2VoTAAAAAIAFz0IVuHfu3DlJMmrUqHz44Yfp1KnTdH2ef/75JMn6668/R3Ovvfba04Xq5XI5Tz75ZJJkm222+SklAwAAAACwkFiojpRp3759NtxwwyTJjTfeOF37E088kU8++SSNGzfODjvsUOv1br755nz88cfZeOONs8EGG9R6PgAAAAAAFlwLVeCeJKecckqS5I9//GNefPHF6uejRo3K4YcfniQ58sgjU1FRUd12xx13ZLXVVkvPnj2nm2/EiBEzPKLm3nvvzaGHHprGjRvnyiuvLPptAAAAAACwgFmojpRJkt122y1HH310Lr744nTr1i09e/ZM8+bN89BDD2XMmDHp3r17/vCHP9QYU1lZmbfffjsTJkyYbr5nn302e+yxR9Zdd9106tQpDRs2zKuvvpq33norLVq0yJ133pl11llnXr09AAAAAADmUwvdDvckGTBgQG666aZsvPHGGTp0aAYPHpz27dvnj3/8Yx5++OE0bdp0tudaa6210rdv34wfPz4PPvhg7rnnnpTL5Rx33HF566230qtXr7n4TgAAAAAAWFCUyuVyua6LWBSNHTs2FRUVqaysTKtWreq6HAAAAACARV5tc9uFcoc7AAAAAADMawJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAAogcAcAAAAAgAII3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACiBwBwAAAACAAgjcAQAAAACgAAJ3AAAAAAAogMAdAAAAAAAKIHAHAAAAAIACCNwBAAAAAKAAAncAAAAAACiAwB0AAAAAAArQYG4vMHny5DzzzDN54403Mnr06EyaNCmnnXba3F4WAAAAAADmqVK5XC7PjYknTZqUs846K5deemkqKytrtE2dOrXG1yeddFLuuuuudOjQIQ899NDcKGe+M3bs2FRUVKSysjKtWrWq63IAAAAAABZ5tc1t58qRMqNGjUq3bt1y9tlnZ8yYMSmXy9WvGdltt93y3nvv5dFHH83zzz8/N0oCAAAAAIC5aq4E7j/72c/y8ssvp1wup3v37rnqqqtmeYxM9+7d0759+yTJ/fffPzdKAgAAAACAuarwwP3222/PY489llKplBNPPDGPP/54fv7zn6dz586zHLf11lunXC5n6NChRZcEAAAAAABzXeGB+4033pgkWWeddXLuuefO9rh11lknSfL2228XXRIAAAAAAMx1hQfuzz77bEqlUvbdd985GrfUUkslSb766quiSwIAAAAAgLmu8MC9KjBfYYUV5mhcw4YNkySTJk0quiQAAAAAAJjrCg/cmzRpkmTOg/OqoL5169ZFlwQAAAAAAHNd4YH70ksvnSR5880352jc008/nSTp1KlT0SUBAAAAAMBcV3jgvtlmm6VcLueWW25JuVyerTEjR47MbbfdllKplC222KLokgAAAAAAYK4rPHDff//9kyTvvvtuzj777B/tP2nSpOy///4ZP358SqVS+vfvX3RJAAAAAAAw182VHe477rhjyuVyTj/99PziF7/Ie++9N12/8ePH54477shGG22UBx98MKVSKfvvv39WW221oksCAAAAAIC5rlSe3XNf5kBlZWU22WSTvPnmmymVSkm+v0z1u+++S6lUSps2bTJmzJhMmzYtSVIul7PeeuvliSeeSLNmzYouZ740duzYVFRUpLKyMq1atarrcgAAAAAAFnm1zW0L3+GeJBUVFXn66aez9957p1wup1wuV4ftSTJq1KhMnTq1um3PPffMY489tsiE7QAAAAAALHzmyg73H3rttddy3XXX5bHHHsuwYcMyZsyYtGjRIu3bt88WW2yRvn37ZsMNN5ybJcyX7HAHAAAAAJi/1Da3neuBOzMmcAcAAAAAmL/Ml0fKAAAAAADAoqbwwP3222/P5MmTi54WAAAAAADma4UH7r17987SSy+dI444Ik8//XTR0wMAAAAAwHxprhwp8/XXX+fKK69M9+7ds+qqq+bss8/ORx99NDeWAgAAAACA+ULhgfsRRxyRxRdfPOVyOeVyOe+9915OO+20rLjiiunRo0cGDhyYb775puhlAQAAAACgTpXK5XK56EmnTJmS+++/P3//+99zzz33ZOLEid8vViolSZo2bZpdd901ffv2zbbbblv9fFFS29tuAQAAAAAoVm1z27kSuP9QZWVlbrrpplx//fV58sknU7VcVcjerl277LfffjnggAOy9tprz81S5isCdwAAAACA+ct8H7j/0LBhwzJo0KDccMMNeffdd/+viP8/fF9nnXXSr1+/HHvssfOqpDojcAcAAAAAmL8sUIH7Dz399NMZNGhQbr755owePfr/CiqVMnXq1LooaZ4SuAMAAAAAzF9qm9sWfmnq7OrWrVsuv/zyfPbZZ7ngggvSqFGjuioFAAAAAABqrUFdLTxu3LjccsstGTRoUJ544onU0UZ7AAAAAAAoxDwN3KdNm5YHHngggwYNyt13350JEyYkSXXY3qxZs+yxxx7zsiQAAAAAACjEPAncX3755QwaNCj/+Mc/8uWXXyb5v5C9VCqlR48e6devX3r37p3mzZvPi5IAAAAAAKBQcy1w/+yzz3L99dfn73//e15//fUkqXFszCqrrJK+ffvmgAMOSIcOHeZWGQAAAAAAME8UHrhff/31GTRoUB555JFMmzYtyf8F7a1bt84+++yTvn37ZqONNip6aQAAAAAAqDOFB+59+/ZNqVSqDtkbNmyY7bffPn379s3OO++chg0bFr0kAAAAAADUublypEy5XM4GG2yQvn37Zt99903btm3nxjIAAAAAADDfKDxw/9WvfpW+fftmjTXWKHpqAAAAAACYb9UresIddtghI0eOzMsvv1z01AAAAAAAMN8qPHDv0aNHttxyy1x//fVFTw0AAAAAAPOtwgP3pk2bJkk6d+5c9NQAAAAAADDfKjxwb9euXdFTAgAAAADAfK/wwH2TTTZJkrz66qtFTw0AAAAAAPOtwgP3gw8+OOVyOdddd10qKyuLnh4AAAAAAOZLc+XS1COPPDJffvlldtppp3z++edFLwEAAAAAAPOdBkVP+Nhjj6V37955//33c//992eVVVbJHnvskc022yzt27evvlR1VjbffPOiywIAAAAAgLmqVC6Xy0VOWK9evZRKpeqvy+Vyja9/tKBSKVOmTCmypPnS2LFjU1FRkcrKyrRq1aquywEAAAAAWOTVNrctfId78n3IPquvAQAAAABgYVN44H766acXPSUAAAAAAMz3Cj9ShtnjSBkAAAAAgPlLbXPbenOhJgAAAAAAWOQI3AEAAAAAoAACdwAAAAAAKIDAHQAAAAAACtCg6Anr169f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AAAAAN9zaSoAAAAAABRA4A4AAAAAAAUQuAMAAAAAQAEE7gAAAAAAUICffGnq7Prss8/y9NNP59NPP83YsWMzderUHx1z2mmnze2yAAAAAACgUKVyuVyeGxO//PLL+dWvfpWHHnpojsfOTii/oBs7dmwqKipSWVmZVq1a1XU5AAAAAACLvNrmtnNlh/vgwYPTu3fvTJw4MT+W55dKpRp9SqXS3CgJAAAAAADmqsID91GjRqVPnz6ZMGFCmjVrluOPPz6bbrppevXqlVKplD/84Q9Zb7318uGHH+b+++/P/fffn1KplH79+qVfv35FlwMAAAAAAPNE4YH7lVdembFjx6ZUKuWuu+5Kz549a7SvtdZa2WGHHZIkRxxxRJ566qn07t071113XdZYY42ceOKJRZcEAAAAAABzXb2iJxwyZEhKpVJ69eo1Xdg+IxtvvHHuv//+NGjQIKecckpefvnloksCAAAAAIC5rvDA/a233kqSbL311jNsnzJlynTP1llnney9996ZMmVK/vrXvxZdEgAAAAAAzHWFB+5jxoxJkrRv377G84YNGyZJxo8fP8NxPXr0SJI8/PDDRZcEAAAAAABzXeGBe6NGjWb4vGXLlkmSESNGzLC9WbNms2wHAAAAAID5WeGB+9JLL50kGT16dI3nK6ywQpLkpZdemuG49957L8mMj5wBAAAAAID5XeGB+1prrZXk/85yr9K1a9eUy+Xcd999+eqrr2q0TZw4MVdffXWSZLnlliu6JAAAAAAAmOsKD9w322yzlMvlPP744zWe77vvvkmSb7/9Nttss03uv//+vPPOOxk8eHA233zzfPzxxymVStlpp52KLgkAAAAAAOa6UrlcLhc54bvvvptVV1019erVyzvvvFN9lEyS7Lbbbrn77rtTKpWmG1cul7PEEkvk1VdfzVJLLVVkSfOlsWPHpqKiIpWVlWnVqlVdlwMAAAAAsMirbW7boOiCVl555Vx33XUZP358Jk6cWKPthhtuyF577ZX7779/unEdO3bM7bffvkiE7QAAAAAALHwK3+E+O4YOHZohQ4bk888/T/PmzbPhhhtmjz32SKNGjeZ1KXXGDncAAAAAgPnLfLfDfXZssskm2WSTTepiaQAAAAAAmCsKvzQVAAAAAAAWRQJ3AAAAAAAoQOFHyowfPz6/+93vUi6X07t379k6Ombo0KG59dZbU79+/Zx99tmL1FnuAAAAAAAsHAq/NHXQoEHp379/GjVqlE8++SRLLLHEj44ZOXJkOnTokEmTJuWGG27IPvvsU2RJ8yWXpgIAAAAAzF9qm9sWfqTM/fffnyTp2bPnbIXtSdK2bdtsvfXWKZfLue+++4ouCQAAAAAA5rrCA/cXX3wxpVIpm2666RyNq+r/wgsvFF0SAAAAAADMdYUH7sOHD0+SLL/88nM0rmPHjkmSTz/9tOiSAAAAAABgris8cJ8yZUqSpH79+nNWSL3vS5k4cWLRJQEAAAAAwFxXeOC++OKLJ0k+/vjjORr3ySefJEkWW2yxoksCAAAAAIC5rvDAfdVVV/1Jl59W9V955ZWLLgkAAAAAAOa6wgP3bbbZJkny2GOPZfDgwbM15t57781//vOflEqlbLvttkWXBAAAAAAAc13hgfshhxySZs2aJUn23Xff3H777bPsf9ttt2W//fZLkjRp0iSHHnpo0SUBAAAAAMBc16DoCZdYYomcffbZOe644/LNN99kzz33zPrrr59dd901a6yxRlq0aJFvvvkmb7zxRu666668+OKLKZfLKZVK+f3vf5927doVXRIAAAAAAMx1pXK5XJ4bE5944om58MILv1+kVJppv6rlTzzxxJx77rmFrX/LLbfksssuyyuvvJJJkyZlpZVWyn777ZfjjjsuDRs2nKO5vv3221x88cW57bbb8s477+S7777L4osvni5duuTQQw/NLrvsMsf1jR07NhUVFamsrEyrVq3meDwAAAAAAMWqbW471wL3JLn99ttz2mmn5Y033phpnzXXXDNnnXVWdt1118LWPfbYYzNgwIA0aNAgW221VVq0aJGHH344Y8aMyaabbpohQ4akadOmszXXqFGjsvnmm+eNN95IixYtsskmm2SxxRbLe++9lxdffDFJcvTRR2fAgAFzVKPAHQAAAABg/jJfB+5VXnjhhTz++OP59NNPM3bs2LRq1Srt27fP5ptvnvXXX7/Qte68887svvvuadGiRf7zn/9Uzz9y5MhstdVWee2113LCCSfk/PPPn635jjnmmFx88cXZYIMNMmTIkLRp06a6bfDgwdl1110zZcqUPPXUU+nWrdts1ylwBwAAAACYvywQgfu81LVr1zz33HM566yzcuqpp9Zoe+KJJ7LZZpulcePG+eKLL1JRUfGj86299tr573//m5tvvjl77rnndO3bbrttHnzwwVx44YU57rjjZrtOgTsAAAAAwPyltrltvblQU50ZPnx4nnvuuSRJnz59pmvfdNNN06FDh0ycODGDBw+erTmbNGkyW/3atm07+4UCAAAAALDQmWeB+6RJk/L555/n448/nmtrvPTSS0mSNm3apFOnTjPs06VLlxp9f8z222+fJPnTn/6U0aNH12gbPHhwHnnkkbRr1+4nXZwKAAAAAMDCo8HcnPydd97JgAED8sADD+TDDz9MkpRKpUyZMqVGv3/+85/54IMP0q5duxx00EE/eb2qNTp27DjTPh06dKjR98f8+te/zrPPPpsHHnggyy23XLp37159aeoLL7yQ7t2755prrpmt42kAAAAAAFh4zbXA/U9/+lN+97vfZerUqfmxY+K//fbb/Pa3v02DBg2y0047Zckll/xJa44bNy5J0rx585n2adGiRZLvz+KZHc2bN88999yTU045JRdccEEeeOCB6rbFF188W2+9dZZddtkfnWfixImZOHFi9dezuz4AAAAAAAuGuXKkzB//+MeccsopmTJlSurVq5eNN944m2666Uz777vvvmnSpEmmTp2au+++e26U9JN99tln6d69ey655JKcddZZ+eCDD/LNN9/k2WefzQYbbJAzzzwzm266aXXYPzPnnHNOKioqql9VO+0BAAAAAFg4FB64v/vuu/nd736XJFlrrbXy3//+N08++WROOOGEmY5p1qxZttpqqyTJo48++pPXbtmyZZLvd8zPzDfffJMks33DbL9+/fLcc8/lD3/4Q0455ZR06tQpzZs3z4Ybbph77703a6+9dl555ZWcf/75s5zn5JNPTmVlZfXrk08+mc13BQAAAADAgqDwwP3SSy/N1KlTU1FRkQceeCCrrrrqbI3r0qVLyuVyXnvttZ+89vLLL58kswyzq9qq+s7K8OHD8+CDDyb5fhf+/2rYsGF69+6dJPn3v/89y7kaN26cVq1a1XgBAAAAALDwKDxwf/jhh1MqldK3b98svfTSsz2uU6dOSWYdlv+Yzp07J0lGjRo100tRn3/++STJ+uuv/6Pzffzxx9X/PbOAvOqy1NGjR89RrQAAAAAALFwKD9yrAvMuXbrM0biq42Cqjnz5Kdq3b58NN9wwSXLjjTdO1/7EE0/kk08+SePGjbPDDjv86Hw/vAz1mWeemWGfp59+Osn/fWAAAAAAAMCiqfDAfeLEiUmSJk2azNG4qqC9efPmtVr/lFNOSfL9xa0vvvhi9fNRo0bl8MMPT5IceeSR1TvTk+SOO+7Iaqutlp49e9aYq2PHjtUB/jHHHJNhw4bVaL/++utz0003JUn69OlTq7oBAAAAAFiwNSh6wiWWWCLDhw/P8OHD52jcG2+8kSRZaqmlarX+brvtlqOPPjoXX3xxunXrlp49e6Z58+Z56KGHMmbMmHTv3j1/+MMfaoyprKzM22+/nQkTJkw337XXXpstt9wyb775ZlZfffV069Ytbdu2zZtvvpnXX389SbL//vtnv/32q1XdAAAAAAAs2Arf4b7uuuumXC7/6CWiP1Qul3PHHXekVCplo402qnUNAwYMyE033ZSNN944Q4cOzeDBg9O+ffv88Y9/zMMPP5ymTZvO9lxrrbVW/vvf/+bXv/51VllllTz33HO588478+WXX2a77bbLTTfdlL///e8plUq1rhsAAAAAgAVXqVwul4uc8C9/+UsOO+yw1K9fP0OHDq0+kuWuu+7K7rvvnlKplKlTp9YYc/HFF+fYY49NqVTKLbfckj322KPIkuZLY8eOTUVFRSorK2d6ISsAAAAAAPNObXPbwne49+vXL8sss0ymTZuWXXbZJUOHDp1p38mTJ+dPf/pTTjjhhJRKpay66qqLRNgOAAAAAMDCp/Az3Bs3bpwbbrgh2267bb788ststtlm2XjjjdO6devqPieddFI++eSTPPLIIxk5cmTK5XKaNGmS66+/vuhyAAAAAABgnij8SJkq999/fw444ICMHj16puebVy292GKL5eabb87WW289N0qZLzlSBgAAAABg/jLfHSlTZfvtt89///vfHHvssWnTpk3K5fJ0r4qKihx++OH573//u0iF7QAAAAAALHzm2g73//XGG29k2LBhGTNmTFq0aJH27dtnvfXWS716cy3zn6/Z4Q4AAAAAMH+pbW5b+BnuM7PGGmtkjTXW+NF+zz//fLp06TIPKgIAAAAAgOLMN9vLX3755ey8887ZaKON6roUAAAAAACYY3UeuP/3v//Nz372s2ywwQa577776rocAAAAAAD4SQo7UmbChAl57LHH8s477+S7775Lx44d061btyy33HIz7P/uu+/mt7/9bW677bbqS1STOM8cAAAAAIAFUiGB+xVXXJHf/e53+frrr2s8r1+/fvbbb79cccUVadKkSZLvg/mTTz45l19+eaZMmVIdtLdp0ybHHHNMjj766CJKAgAAAACAearWgfuf/vSnnHLKKUlSHZ5XmTJlSgYNGpQRI0bkgQceyPDhw9OrV6+88cYb1X2XWmqpHH/88Tn88MPTvHnz2pYDAAAAAAB1olT+35R8DgwbNiyrrbZaJk+enHK5nHbt2qVbt25p0qRJXn/99bz22mvfL1Iq5aabbsrvf//7vP766ymXy1l66aVz8skn55BDDqne/b4oGTt2bCoqKlJZWekYHQAAAACA+UBtc9ta7XAfOHBgJk2alFKplKOPPjrnnXdeGjZsWN1+5513Zt99982kSZNy8MEHZ9y4calXr15OPvnk/Pa3v10kg3YAAAAAABZO9Woz+LHHHkuSrLPOOrnoootqhO1Jsttuu+XEE09MuVzOuHHjUiqVcsstt+Sss84StgMAAAAAsFCpVeD+1ltvpVQqZa+99pppnz59+iT5/liZbbfdNrvvvnttlgQAAAAAgPlSrQL3MWPGJElWXHHFmfb5YVuvXr1qsxwAAAAAAMy3ahW4T5gwIUlmeTxMo0aNqv+7ffv2tVkOAAAAAADmW7UK3OfU/57xDgAAAAAAC4t5GrgDAAAAAMDCqkERk3z55Zf5+OOPC+vXsWPHIsoCAAAAAIB5plQul8s/dXC9evVSKpWKrCelUilTpkwpdM750dixY1NRUZHKysq0atWqrssBAAAAAFjk1Ta3LWSH+49l9lWhfC2yfQAAAAAAmK/VKnDv2LFj4TvcAQAAAABgQVSrwH3YsGEFlQEAAAAAAAu2enVdAAAAAAAALAwE7gAAAAAAUACBOwAAAAAAFGCeBu4vvfRSDjrooBx88MHzclkAAAAAAJjr5mng/vHHH2fgwIEZOHDgvFwWAAAAAADmOkfKAAAAAABAAQTuAAAAAABQAIE7AAAAAAAUQOAOAAAAAAAFELgDAAAAAEABBO4AAAAAAFCABvNysfXXXz9/+9vf5uWSAAAAAAAwT5TK5XK5rotYFI0dOzYVFRWprKxMq1at6rocAAAAAIBFXm1zW0fKAAAAAABAAQTuAAAAAABQgLl6hvuUKVPy3HPP5b///W++/vrrTJgwYbbGnXbaaXOzLAAAAAAAKNxcOcN92rRpOffcc/PnP/85I0eOnOPxU6dOLbqk+Y4z3AEAAAAA5i+1zW0L3+FeLpez55575s4776z+ek6USqWiSwIAAAAAgLmu8MB90KBBueOOO5Ik9evXT+/evbPNNtukffv2ady4cdHLAQAAAADAfKHwwP26665LkjRp0iT/+te/svnmmxe9BAAAAAAAzHfqFT3hq6++mlKplEMOOUTYDgAAAADAIqPwwP3bb79NkmyyySZFTw0AAAAAAPOtwgP3ZZZZJkkybdq0oqcGAAAAAID5VuGBe9UxMq+++mrRUwMAAAAAwHyr8MD9qKOOSr169TJw4MCMGzeu6OkBAAAAAGC+VHjgvv766+ess87Kl19+md122y1ff/110UsAAAAAAMB8p0HREz722GPZeOON06dPn9x4441ZZZVV0rdv32y88cZp27Zt6tX78Yy/6lgaAAAAAABYUJTK5XK5yAnr1auXUqlU/XW5XK7x9Y8WVCplypQpRZY0Xxo7dmwqKipSWVmZVq1a1XU5AAAAAACLvNrmtoXvcE++D9ln9TUAAAAAACxsCg/cTz/99KKnBAAAAACA+V7hR8owexwpAwAAAAAwf6ltbvvjN5gCAAAAAAA/SuAOAAAAAAAFmCuXps7MmDFjMm7cuLRs2TKLLbbYvFwaAAD+P/buPcyrst7//2sBCsg4I4iGBuYpLdMUU/KAhGgWWGYHd2ol2GHXdldm7i7tYO7OWu5vkYcObs/l1izLLBU8hAaWYqKpZGiI4VkxZhDlMLB+f/hjdmwEgbk/zgCPx3XNdTGftda93uN1dRFPFvcCAABoqIY+4T5//vyceeaZOfDAA9PU1JTNN9882267bTbffPM0NTXlwAMPzNlnn5358+c3cgwAAAAAAGi4hr009frrr8/YsWPz5JNPJkle6jZVVSVJBg0alIsuuigHH3xwI0bplrw0FQAAAACge+mWL0299tpr8453vCNPPvlk6rpOXdfp169fdt999+y///7Zfffd09TU1HHs8ccfz6GHHprrrruuEeMAAAAAAEDDFQ/ura2t+dCHPpTFixenruu8/e1vzy233JK2trZMmzYtv//97zNt2rS0trbm5ptvzujRo5Mkixcvzgc/+MG0tbWVHgkAAAAAABqueHD/wQ9+kGeffTZVVeXUU0/NNddck+HDh3dsH7NMVVU54IAD8tvf/jZf+cpXkiT/+Mc/8oMf/KD0SAAA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SZIdd9xxja7bfvvtl7seAAAAAADWJcWD+8KFC5MkvXv3XqPrNt544yTJ888/X3okAAAAAABouOLBvX///kmSxx57bI2ue/zxx5MkLS0tpUcCAAAAAICGKx7cd9hhhyTJ9ddfv0bXLTt/2223LT0SAAAAAAA0XPHgPmrUqNR1nWuvvTZTp05drWtuu+22XHPNNamqKgcddFDpkQAAAAAAoOGKB/ePfvSj2WijjVLXdd71rne9bHS//fbb8+53vzt1Xadnz5756Ec/WnokAAAAAABouF6lF3zNa16Tz372szn99NPz5JNPZv/998+73vWuvOtd78ouu+ySpqamPPfcc5k+fXquuuqqXHXVVWlvb09VVTn++OOz4447lh4JAAAAAAAarqrrui696NKlS3PkkUfm5z//+Ys3qaqVnrvs9kcccUQuu+yyVZ67Pmlra0tLS0taW1vT3Nzc1eMAAAAAAGzwOttti28pkyQ9evTIz372s5xxxhnZfPPNU9f1Sr8GDhyY7373u7n88ss3mNgOAAAAAMD6pyFPuP+z559/Ptdee21+//vf55FHHklbW1uam5szePDgjBgxIqNHj07fvn0bOUK35Al3AAAAAIDupbPdtuHBnZcmuAMAAAAAdC/dcksZAAAAAADY0AjuAAAAAABQQK9GLj537tyce+65mTBhQqZPn55nn3027e3taW9vX+68m266KU888UQGDhyYQw45pJEjAQAAAABAQzQsuF9++eX5+Mc/nnnz5iVJlm0VX1XVCufefffdOfHEE9O3b988/vjj9jQHAAAAAGCd05AtZS6++OIcffTRaWtrS13XGTRoUHbaaaeVnj9u3Lj06tUrCxYsyNVXX92IkQAAAAAAoKGKB/fHHnssn/jEJ1LXdbbeeutMnDgxjz76aE4//fSVXtO/f/+MGDEiyYvbywAAAAAAwLqmeHA/66yzsmDBgvTt2zc33nhjDj744NW6btiwYanrOnfffXfpkQAAAAAAoOGKB/eJEyemqqocffTR2XnnnVf7uh133DFJMmvWrNIjAQAAAABAwxUP7g899FCSZPjw4Wt0XUtLS5J0vGQVAAAAAADWJcWD+/z585MkTU1Na3TdCy+8kCTp06dP6ZEAAAAAAKDhigf3zTffPEny5JNPrtF1DzzwQJJkiy22KD0SAAAAAAA0XPHgvssuuyRJbrnl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102YMCGjR49Ojx490t7eXnKkbqmzb7sFAAAAAKCsznbbbrelTOH+DwAAAAAAr4huE9yXhfaqqrp4EgAAAAAAWHPdJrg//fTTSZKmpqYungQAAAAAANZctwjuCxcu7HjZ6nbbbdfF0wAAAAAAwJrr1ZmLL7roolx00UUveexLX/pSvve9763y+rquM3/+/Nx///2ZP39+qqrKwQcf3JmRAAAAAACgS3QquM+aNSuTJk1aYd/1uq5z3333rfY6y/ZvHzRoUE488cTOjAQAAAAAAF2iU8F9mWXB/OU++7+qqkpTU1O22267HHzwwTnxxBMzaNCgEiMBAAAAAMArqqpXp4yvgR49eqSqqvzyl7/MYYcdVnLp9UpbW1taWlrS2tqa5ubmrh4HAAAAAGCD19lu25CXphZu+AAAAAAA0O0V2VLmny1durT0kgAAAAAA0O015Al3AAAAAADY0AjuAAAAAABQgOAOAAAAAAAFCO4AAAAAAFCA4A4AAAAAAAUI7gAAAAAAUIDgDgAAAAAABQjuAAAAAABQgOAOAAAAAAAF9Cq94C233JIkaW5uzh577FF6eQAAAAAA6JaKP+E+cuTIHHjggfnJT35SemkAAAAAAOi2igf3vn37JkmGDh1aemkAAAAAAOi2igf3QYMGlV4SAAAAAAC6veLBfb/99kuS/PnPfy69NAAAAAAAdFvFg/tHPvKR1HWdiy66KK2traWXBwAAAACAbqkhL0395Cc/maeeeirveMc78sQTT5S+BQAAAAAAdDu9Si94yy235H3ve1/+9re/5dprr81OO+2U97znPTnggAMyePDgjpeqrsqIESM6PccVV1yRs88+O3fffXcWLVqUHXfcMR/4wAdywgknZKONNlrtdbbddts8/PDDL3veV77ylXz5y1/uzMgAAAAAAKzDqrqu65IL9ujRI1VVdXxf1/Vy37/sQFWV9vb2Ts3wmc98JuPHj0+vXr0yatSoNDU15aabbsrcuXMzfPjwTJw4cbXCf5L8x3/8R5555pmXPPbss8/m6quvTvLiXzQccMABqz1jW1tbWlpa0tramubm5tW+DgAAAACAxuhst21IcO+MqqqyZMmStb7+V7/6Vd797nenqakpN998c/bcc88kyTPPPJNRo0blnnvuyYknnpgzzjijU3Mmybe//e2cdNJJ2WmnnfLXv/51ja4V3AEAAAAAupfOdtviW8qceuqppZdcI9/85jeTJCeffHJHbE+SgQMH5pxzzskBBxyQs846K6ecckpaWlo6da/zzz8/SfLhD3+4U+sAAAAAALDuK/6Ee1d69NFHM3jw4CTJzJkzs912261wzjbbbJPZs2fn0ksvzVFHHbXW95oyZUqGDx+eXr16Zfbs2Rk0aNAaXe8JdwAAAACA7qWz3bZz+790M9OmTUuSDBgw4CVje5Lstddey527tpY93T5mzJg1ju0AAAAAAKx/1qvg/tBDDyV58Sn2lRkyZMhy566N+fPn52c/+1mS5CMf+charwMAAAAAwPqj+B7uK7No0aI8++yzWbRo0SqDeGfMmzcvSdKvX7+VntPU1JTkxX8asLZ+9rOf5bnnnsugQYMyZsyY1bpm4cKFWbhwYcf3nbk/AAAAAADdT0OD+4wZMzJ+/PhMmDCh44nyqqrS3t6+3HmXXXZZZs6cmUGDBq0TLyA977zzkiTHHHNMevVavf+E3/rWt/KVr3ylkWMBAAAAANCFGralzOmnn55dd901P/zhDzNz5szUdd3x9X/Nnz8/X/rSl/KJT3wiTz311Frfc9NNN+1Yb2Wee+65JFnrF5XOmDEjU6ZMSZI1+suBz3/+82ltbe34mj179lrdHwAAAACA7qkhwf20007LF77whbS3t6dHjx7Zd999M3z48JWef9RRR6VPnz5ZsmRJfv3rX6/1fbfddtskWWXMXnZs2blratnLUocPH56dd955ta/r3bt3mpubl/sCAAAAAGD9UTy4P/DAAznllFOSJLvuumvuvffeTJkyJSeeeOJKr9lkk00yatSoJMmkSZPW+t5Dhw5NksyZM2elL0W94447kiR77rnnGq+/ZMmSXHzxxUm8LBUAAAAAgOUVD+5nnXVWlixZkpaWlkyYMGG1nwLfa6+9Utd17rnnnrW+9+DBg7P33nsnSS699NIVjk+ePDmzZ89O7969V/tlp//smmuuyeOPP55NN900RxxxxFrPCQAAAADA+qd4cL/ppptSVVWOOeaYbLXVVqt93XbbbZdk1dvBrI4vfOELSV7c1ubOO+/s+HzOnDk57rjjkiSf/OQn09LS0nHsl7/8ZV73utfloIMOWuXay7aTOfLII9OvX79OzQkAAAAAwPqlV+kFlwXzvfbaa42uW/bC02UvNV1bhx9+eD796U/n+9//fvbZZ58cdNBB6devX2688cbMnTs3+++/f772ta8td01ra2v++te/ZsGCBStd96mnnspvf/vbJLaTAQAAAABgRcWfcF+4cGGSpE+fPmt03bLQXuLJ8fHjx+fyyy/Pvvvum1tvvTXXXHNNBg8enNNOOy033XRT+vbtu8ZrXnLJJVm8eHHe8IY35M1vfnOnZwQAAAAAYP1S/An3LbbYIo8++mgeffTRNbpu+vTpSZJXvepVReb4l3/5l/zLv/zLap07bty4jBs3bpXnnHjiiat88SsAAAAAABu24k+477777qnrOjfccMNqX1PXdX75y1+mqipPjwMAAAAAsE4qHtzf+c53Jkmuu+66TJ06dbWuOfPMM/PAAw8kSd71rneVHgkAAAAAABqueHAfO3Zstt566yxdujSHHXZYbr311pWeu3jx4px++uk58cQTU1VVdt5557znPe8pPRIAAAAAADRc8T3ce/funZ/+9Kc55JBD8tRTT+WAAw7Ivvvum/79+3ec87nPfS6zZ8/O7373uzzzzDOp6zp9+vTJT37yk9LjAAAAAADAK6Kq67puxMLXXnttPvShD+XZZ59NVVUvec6yW2+22Wb52c9+loMPPrgRo3RLbW1taWlpSWtra5qbm7t6HAAAAACADV5nu23xLWWWGT16dO6999585jOfyYABA1LX9QpfLS0tOe6443LvvfduULEdAAAAAID1T8OecP+/pk+fnlmzZmXu3LlpamrK4MGDs8cee6RHj4Y1/27NE+4AAAAAAN1LZ7tt8T3cV2aXXXbJLrvs8krdDgAAAAAAXlEb5uPlAAAAAABQmOAOAAAAAAAFrPWWMrfcckvJOZYzYsSIhq0NAAAAAACNsNbBfeTIkamqquQsSZKqqtLe3l58XQAAAAAAaKROvTS1rutScwAAAAAAwDptrYP7qaeeusrjd9xxR377298mSTbbbLMMHz48O+64Y/r165f58+fnwQcfzOTJkzN37txUVZVDDz00b3rTm9Z2HAAAAAAA6FJV3YDH1P/nf/4nxx57bDbaaKOcfvrp+ehHP5qNN954hfMWLVqU8847LyeffHIWLVqUCy+8MO9///tLj9MttbW1paWlJa2trWlubu7qcQAAAAAANnid7bbFg/v999+fPffcM+3t7Zk0aVL222+/l73m1ltvzciRI7PxxhvnjjvuyOte97qSI3VLgjsAAAAAQPfS2W7bo/RAZ555ZhYsWJAPfOADqxXbk2S//fbL0Ucfneeffz5nnXVW6ZEAAAAAAKDhigf366+/PlVVZeTIkWt03YEHHthxPQAAAAAArGuKB/dHH300SdK7d+81um7Z+cuuBwAAAACAdUnx4N6nT58kyV133bVG1y07f01DPQAAAAAAdAfFg/sb3vCG1HWd8847L0899dRqXfPUU0/lvPPOS1VVecMb3lB6JAAAAAAAaLjiwf0DH/hAkuTZZ5/NqFGjct99963y/OnTp+eggw7KnDlzkiQf/OAHS48EAAAAAAANV9V1XZdccOnSpdlnn31yxx13pKqq9OzZMwcffHAOOuig7Ljjjtlkk03y/PPP58EHH8xNN92U66+/PkuWLEld1xk2bFj+8Ic/pKqqkiN1S21tbWlpaUlra2uam5u7ehwAAAAAgA1eZ7tt8eCevPh0+9ve9rb86U9/evEmqwjoy27/pje9Kdddd10233zz0uN0S4I7AAAAAED30tluW3xLmSQZMGBA/vCHP+Qb3/hGXvWqV6Wu65V+vepVr8o3v/nN/OEPf9hgYjsAAAAAAOufhjzh/s/a29szZcqU3H777Xnsscfy3HPPpampKa9+9aszbNiw7LfffunVq1cjR+iWPOEOAAAAANC9dMstZXh5gjsAAAAAQPfSLbeUAQAAAACADY3gDgAAAAAABbwim6cvWrQoc+fOzYIFC1br/G222abBEwEAAAAAQFkNC+4PPfRQxo8fn2uvvTZ/+9vfsrpbxVdVlfb29kaNBQAAAAAADdGQ4H755ZfnIx/5SF544YUkWe3YDgAAAAAA66riwf2ee+7Jhz70oSxZsiR1XadPnz7Za6+9Mnjw4PTu3bv07QAAAAAAoFsoHty/853vpL29PVVV5aMf/Wi+853vpKWlpfRtAAAAAACgWyke3G+++eZUVZWRI0fmxz/+cenlAQAAAACgW+pResGnnnoqSfL+97+/9NIAAAAAANBtFQ/uy7aPGTBgQOmlAQAAAACg2yoe3HfZZZckyezZs0svDQAAAAAA3Vbx4H7MMcekrutceeWVpZcGAAAAAIBuq3hwHzt2bEaMGJFbb701Z555ZunlAQAAAACgWyoe3KuqypVXXpkRI0bkM5/5TD784Q/nnnvuKX0bAAAAAADoVqq6ruuSC26//fZJkvb29jzyyCOpqipJ0q9fvwwYMCA9eqy68VdVlb/97W8lR+qW2tra0tLSktbW1jQ3N3f1OAAAAAAAG7zOdttepQeaNWtWR2SvqirLev5zzz2X55577mWvX3YtAAAAAACsS4oH92222UY0BwAAAABgg9OQJ9wBAAAAAGBDU/ylqQAAAAAAsCES3AEAAAAAoADBHQAAAAAAChDcAQAAAACggE69NHXUqFFrfE3Pnj2z2WabZdCgQXnzm9+ct7/97Rk4cGBnxgAAAAAAgC5X1XVdr+3FPXr0SFVVnRqgT58++djHPpbTTjstffr06dRa65K2tra0tLSktbU1zc3NXT0OAAAAAMAGr7PdttNbytR13amvF154IWeeeWb233//zJs3r7PjAAAAAABAl+jUljK/+93v1viaxYsXZ968eXnwwQdz8803Z+LEiWlvb89dd92VD3/4w7niiis6MxIAAAAAAHSJTm0pU8L999+fI444Ivfdd1+qqsrUqVOz5557duVIrwhbygAAAAAAdC9dvqVMZ73uda/Lb3/724792y+55JIunggAAAAAANZclwf3JNlmm23yvve9L3VdZ8qUKV09DgAAAAAArLFuEdyTZL/99kuSPPzww108CQAAAAAArLluE9wHDhyYJJk7d27XDgIAAAAAAGuh2wT3BQsWJEnHXu4AAAAAALAu6TbB/YEHHkiSbL755l08CQAAAAAArLluE9x/9atfpaqqDB06tKtHAQAAAACANdYtgvv3vve93HPPPUmSQw45pIunAQAAAACANderK29+55135vvf/34uueSSJMmAAQNyzDHHdOVIAAAAAACwVjoV3EeNGrXG17S3t2fevHmZOXNmnnvuuSRJXdepqio//vGP07dv386MBAAAAAAAXaJTwX3SpEmpqmqtrq3ruuPXffv2zQ9+8IO8+93v7sw4AAAAAADQZTq9pcw/h/M19ZrXvCaHH354TjjhhGyzzTadHQUAAAAAALpMp4L77373uzW+pmfPnmlpacmrXvWqbLnllp25PQAAAAAAdBudCu5vectbSs0BAAAAAADrtB5dPQAAAAAAAKwPBHcAAAAAAChAcAcAAAAAgAIEdwAAAAAAKEBwBwAAAACAAgR3AAAAAAAoQHAHAAAAAIACBHcAAAAAAChAcAcAAAAAgAIEdwAAAAAAKEBwBwAAAACAAgR3AAAA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jTbK97///Wy99daZMmVKbrzxxobOAaya4A4AAAAAL+HRRx/N1KlTkyRHH330CseHDx+eIUOGZOHChbnmmmsaNkdbW1tmzJiRJDn44INXON63b9/sv//+SZKf//znDZsDeHm2lAEAAACAlzBt2rQkyYABA7Lddtu95Dl77bVXZs+enWnTpuWoo45a7bUffPDBfOlLX8pTTz2Vpqam7LrrrjnssMMycODAFc597rnnOn69+eabv+R6y67705/+tNozAOUJ7gAAAADwEh566KEkWeWLSIcMGbLcuatrypQpmTJlynKf9enTJ//5n/+Zk046abnPBwwYkJ49e2bJkiWZOXNmXv/616+w3syZM9dqDqAsW8oAAAAAwEuYN29ekqRfv34rPaepqSnJi9u+rI5Bgwbli1/8Ym677bY8/fTTaWtry9SpU3PMMcdk4cKFOfnkkzv2jV+mT58+2W+//ZIk55577gprPvDAA7npppvWaA6gMQR3AAAAAHiFvP3tb8/Xv/71DBs2LAMHDsymm26avfbaKxdddFHOOOOMJMlXv/rVPPnkk8td9+UvfzlVVeWqq67KJz7xiTzwwANpa2vL9ddfn9GjR3ec16OH3Addyf8CAQAAAOAlbLrppkmS+fPnr/ScZfurNzc3d/p+xx9/fAYOHJiFCxdm4sSJyx07+OCDc+6556ZPnz750Y9+lJ122iktLS055JBDsmjRonzta19L8uL2M0DXsYc7AAAAALyEbbfdNkkye/bslZ6z7NiyczujZ8+eee1rX5tnnnkmjzzyyArHP/KRj+TQQw/Nz3/+8/zlL39JVVUZOnRo3v/+9+fSSy9Nkuy2226dngNYe4I7AAAAALyEoUOHJknmzJmThx56KNttt90K59xxxx1Jkj333LPIPefMmZPkf5+u/78GDRqUT37ykyt8/vvf/z5J8ta3vrXIHMDasaUMAAAAALyEwYMHZ++9906SjifI/9nkyZMze/bs9O7dO2PGjOn0/e68887MmDEjSTJs2LDVvm7WrFn5xS9+kaampowbN67TcwBrT3AHAAAAgJX4whe+kCQ57bTTcuedd3Z8PmfOnBx33HFJkk9+8pNpaWnpOPbLX/4yr3vd63LQQQctt9bzzz+fs88+O/PmzVvhPrfcckve+973JkmGDx++QnBftGhRpk2btsJ1999/fw499NC88MIL+a//+q9svvnma/mTAiVUdV3XXT3EhqitrS0tLS1pbW0t8lINAAAAABrj+OOPz/e///1stNFGOeigg9KvX7/ceOONmTt3bvbff/9cf/316du3b8f5F154YY499ti85jWvyaxZszo+nzt3bvr375/evXtn6NCh2WabbdLe3p4ZM2bk3nvvTfLiHuwTJkzIVltttdwMy67dfvvts/POO2ezzTbLrFmzcvvtt2fp0qX5yle+klNOOeUV+e8B67POdlt7uAMAAADAKowfPz77779/zj777Nx6661ZvHhxdthhh5x88sk54YQTsvHGG6/WOptssklOOeWU3HHHHbn//vtz33335YUXXkj//v1z8MEH54gjjsi4ceNecr1NNtkkxx9/fH7/+9/nj3/8Y+bPn58tt9wyRx55ZD796U+v0RY0QON4wr2LeMIdAAAAAKB76Wy3tYc7AAAAAAAUILgDAAAAAEABgjsAAAAAABQguAMAAAAAQAGCOwAAAAAAFCC4AwAAAABAAYI7AAAAAAAU0KurBwAAAAD4v970uYu7egQAOulP3zmmq0d4xXnCHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAAoADBHQAAAAAAChDcAQAAAACgAMEdAAAAAAAKENwBAAAAAKAAwR0AAAAAAAoQ3AEAAAAA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", + "tableData": "", + "depth": 0, + "color": "black" + } + ], + "recommendations": [], + "files": [] + } + ], + "top_k": 1, + "folderId": null, + "Lib": "MIOSTONE", + "files": [], + "new_lib_github_url": "", + "new_lib_doc_url": "", + "api_html": "", + "lib_alias": "", + "conversation_started": true + } + ], + "folders": [], + "prompts": [] +} \ No newline at end of file diff --git a/demo/tutorial_links.txt b/demo/tutorial_links.txt index 288e500..1611fea 100644 --- a/demo/tutorial_links.txt +++ b/demo/tutorial_links.txt @@ -1,2 +1,4 @@ scanpy: https://scanpy-tutorials.readthedocs.io/en/latest/pbmc3k.html squidpy: https://squidpy.readthedocs.io/en/stable/notebooks/tutorials/tutorial_imc.html +sonata: https://github.com/batmen-lab/SONATA/blob/main/examples/SNARE-seq.ipynb +MIOSTONE: https://github.com/batmen-lab/MIOSTONE/blob/main/example/IBD200.ipynb \ No newline at end of file diff --git a/src/deploy/inference_dialog_server.py b/src/deploy/inference_dialog_server.py index 6b34524..ee98eff 100644 --- a/src/deploy/inference_dialog_server.py +++ b/src/deploy/inference_dialog_server.py @@ -221,7 +221,8 @@ def reset_lib(self, lib_name): if len(parts)>=3: # only work for path containing LIB, otherwise, please reenter the path in script if not parts[-1]: parts = parts[:-1] - new_path = '/'.join(parts) + parts[-2]= lib_name + new_path = '/'.join(parts) retrieval_model_path = new_path print('load retrieval_model_path in: ', retrieval_model_path) self.retriever = ToolRetriever(LIB=lib_name,corpus_tsv_path=f"./data/standard_process/{lib_name}/retriever_train_data/corpus.tsv", model_path=retrieval_model_path) @@ -230,8 +231,8 @@ def reset_lib(self, lib_name): self.executor.execute_api_call(f"import {lib_name}", "import") # pyteomics tutorial needs these import libs self.executor.execute_api_call(f"import os, gzip, numpy as np, matplotlib.pyplot as plt", "import") - self.executor.execute_api_call(f"from urllib.request import urlretrieve", "import") - self.executor.execute_api_call(f"from pyteomics import fasta, parser, mass, achrom, electrochem, auxiliary", "import") + #self.executor.execute_api_call(f"from urllib.request import urlretrieve", "import") + #self.executor.execute_api_call(f"from pyteomics import fasta, parser, mass, achrom, electrochem, auxiliary", "import") self.executor.execute_api_call(f"import numpy as np", "import") self.executor.execute_api_call(f"np.seterr(under='ignore')", "import") self.executor.execute_api_call(f"import warnings", "import") @@ -875,20 +876,21 @@ def run_pipeline_after_entering_params(self, user_input): sys.stderr = self.buf # execute and obtain figures for code in execution_code_list: - error_list.append(self.executor.execute_api_call(code, "code")) + #print(f'start executing code: {code}') + ans = self.executor.execute_api_call(code, "code") + if ans: + error_list.append(ans) if plt.get_fignums()!=self.plt_status: error_list.append(self.executor.execute_api_call("from inference.utils import save_plot_with_timestamp", "import")) error_list.append(self.executor.execute_api_call("save_plot_with_timestamp()", "code")) self.plt_status = plt.get_fignums() else: pass - # split tuple variable into individual variables - self.executor.split_tuple_variable() # This function verifies whether the new variable is a tuple. + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + content = self.buf.getvalue() # print the new variable if self.executor.execute_code[-1]['success']=='True': - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - content = self.buf.getvalue() # if execute, visualize value code = self.executor.execute_code[-1]['code'] vari = [i.strip() for i in code.split('(')[0].split('=')] @@ -899,7 +901,7 @@ def run_pipeline_after_entering_params(self, user_input): #if self.executor.variables[vari[0]]['value'] is not None: if True: #print('if vari value is not None, return it') - [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task="Execute success. We obtain a new " + str(self.executor.variables[vari[0]]['value']),task_title="Executed results [Success]",) for callback in self.callbacks] + [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task="We obtain a new variable: " + str(self.executor.variables[vari[0]]['value']),task_title="Executed results [Success]",) for callback in self.callbacks] self.indexxxx+=1 if self.executor.variables[vari[0]]['type']=='AnnData': print('if the new variable is of type AnnData, ') @@ -944,11 +946,19 @@ def run_pipeline_after_entering_params(self, user_input): self.indexxxx += 1 tips_for_execution_success = False self.image_file_list = new_img_list - if tips_for_execution_success: + if tips_for_execution_success: # if no output, no new variable, present the log [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task=str(content),task_title="Executed results [Success]",) for callback in self.callbacks] self.indexxxx+=1 else: - [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task="Execution failed! "+"".join(error_list),task_title="Executed results [Fail]",) for callback in self.callbacks] + print(f'Execution Error: {content}') + [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task=""+"".join(error_list),task_title="Executed results [Fail]",) for callback in self.callbacks] # Execution failed! + self.indexxxx+=1 + # split tuple variable into individual variables + ans, new_code = self.executor.split_tuple_variable() # This function verifies whether the new variable is a tuple. + if ans: + [callback.on_agent_action(block_id="code-"+str(self.indexxxx),task=new_code,task_title="Executed code",) for callback in self.callbacks] + self.indexxxx+=1 + [callback.on_agent_action(block_id="log-"+str(self.indexxxx),task="",task_title="Executed results [Success]",) for callback in self.callbacks] self.indexxxx+=1 print("Show current variables in namespace:" + str(self.executor.variables)) new_str = [] diff --git a/src/inference/execution_UI.py b/src/inference/execution_UI.py index 53bb203..89306cb 100644 --- a/src/inference/execution_UI.py +++ b/src/inference/execution_UI.py @@ -157,6 +157,11 @@ def get_import_code(self, api_name): print(f"==?# Error: Could not generate import code for {api_name}") return "", "" def format_value(self, value, value_type): + try: + if str(value).strip().startswith('result_'): + return str(value) + except: + pass if "str" in value_type: value = str(value).strip() if value.startswith("("): # if user input tuple parameters, return directly @@ -251,6 +256,7 @@ def generate_execution_code_for_one_api(self, api_name, selected_params, return_ self.generate_code.append(f"{api_call}") return import_code+'\n'+f"{api_call}" def split_tuple_variable(self, ): + print('==>start split_tuple_variable') # generate splitting code if the results is a tuple # split result_n into result_n+1, reuslt_n+2, result_n+3 = result_n if self.execute_code[-1]['success']: @@ -267,10 +273,45 @@ def split_tuple_variable(self, ): new_variables = [f"result_{self.counter + i + 1}" for i in range(length)] new_code = ', '.join(new_variables) + f" = {result_name_tuple}" # execute new api call - self.execute_api_call(last_code['code']+'\n'+new_code, last_code['code_type']) + print('==>for split_tuple_variable, execute code: ', last_code['code']+'\n'+new_code) + self.execute_api_call(new_code, last_code['code_type']) # Update the count self.counter += length - #print(f'==>generate new code: {new_code}') + return True, new_code + else: + pass + return False, "" + def get_max_result_from_variable_list(self, result_name_list): + max_value = float('-inf') + max_variable = None + for variable in result_name_list: + if variable.startswith('result_'): + variable_number = int(variable.split('_')[1]) + if variable_number > max_value: + max_value = variable_number + max_variable = variable + else: + pass + return max_variable + + def split_tuple_variable_from_variables(self, ): + # generate splitting code if the results is a tuple + # split result_n into result_n+1, reuslt_n+2, result_n+3 = result_n + current_max_result_variable_name = self.get_max_result_from_variable_list(list(self.variables.keys())) + if current_max_result_variable_name: # if exist result_* variable in namespace + # Extract the variable name that starts with 'result' + current_max_result_variable = self.variables[current_max_result_variable_name] + # Check if the variable is a tuple + if 'tuple' in str(type(current_max_result_variable['value'])): + print('==>start split tuple variables!') + length = len(current_max_result_variable['value']) + new_variables = [f"result_{self.counter + i + 1}" for i in range(length)] + new_code = ', '.join(new_variables) + f" = {current_max_result_variable_name}" + # execute new api call + print('==>for split_tuple_variable, execute code: ', new_code) + self.execute_api_call(new_code, 'code') + # Update the count + self.counter += length else: pass @@ -296,7 +337,7 @@ def execute_api_call(self, api_call_code, code_type): if "Error" in captured_output_value: return captured_output_value self.execute_code.append({'code':api_call_code,'code_type':code_type, 'success':'True', 'error':''}) - return "" + return captured_output_value except Exception as e: error = f"{e}" print('==?error in execute api call:', error)