From c3350a39cd1dcd1f09679e4440d5b94a578b6e6d Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:16:01 -0700 Subject: [PATCH 01/17] switch openai model to gemini --- logllm/log_llm.py | 172 ++++++++++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 58 deletions(-) diff --git a/logllm/log_llm.py b/logllm/log_llm.py index ac78d62..f4ee018 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -1,76 +1,94 @@ -from openai import OpenAI +import google.generativeai as genai import wandb -from .extractor import extract_notebook_code +from extractor import extract_notebook_code import json +import os +genai.configure(api_key=os.environ['API_KEY']) def init_wandb(project_name): wandb.init(project=project_name, settings=wandb.Settings(_disable_stats=True)) -def extract_experimental_conditions(code): - client = OpenAI() +def extract_experimental_conditions(code): system_prompt = """ - # You are advanced machine learning experiment designer. - # Extract all experimental conditions and results for logging via wandb api. - # Add your original params in your JSON responce if you want to log other params. - # Extract all informaiton you can find the given script as int, bool or float value. - # If you can not describe conditions with int, bool or float value, use list of natural language. - # Give advice to improve the acc. - # If you use natural language, answer should be very short. - # Do not include information already provided in param_name_1 for `condition_as_natural_langauge`. - # Output JSON schema example: - This is just a example, make it change as you want. Use nested dictionally if nessasary. - {{ - "method":"str", - "dataset":"str", - "task":"str", - "accuracy":"", - "other_param_here":{ - "other_param_here":"", - "other_param_here":"", - }, - "other_param_here":"", - ... - "condition_as_natural_langauge":["Small dataset."], - "advice_to_improve_acc":["Use bigger dataset.","Use more simple model."] - }} - """.replace(" ","") - - user_prompt = f""" - # Here is a user's Jupyter Notebook script:{code} - """ - - response = client.chat.completions.create( - model="gpt-4o-mini-2024-07-18", - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": user_prompt}, - ], - response_format={"type": "json_object"}, - ) + You are an advanced machine learning experiment designer. + Extract all experimental conditions and results for logging via wandb API. + Add your original parameters in your JSON response if you want to log other parameters. + Extract all information you can find in the given script as int, bool, or float values. + If you cannot describe conditions with int, bool, or float values, use a list of natural language. + Give advice to improve the accuracy. + If you use natural language, the answers should be very short. + Do not include information already provided in param_name_1 for `condition_as_natural_language`. + Output JSON schema example: + {{ + "method": "str", + "dataset": "str", + "task": "str", + "accuracy": float, + "other_param_here": {{ + "param1": int, + "param2": int + }}, + "condition_as_natural_language": ["Small dataset."], + "advice_to_improve_acc": ["Use a bigger dataset.", "Use a simpler model."] + Here is a user's Jupyter Notebook script:{code} + + Your answers should return a dictionary like this: + "method": "SVC", + "dataset": "Iris", + "task": "classification", + "accuracy": 1.0, + "C": 1.0, + "degree": 3, + "tol": 0.001, + "cache_size": 200, + "max_iter": -1, + "test_size": 0.2, + "random_state": 42, + "kernel": "linear", + "condition_as_natural_langauge": [ + "Using linear kernel on SVC model.", + "Excluding class 2 from Iris dataset.", + "Splitting data into 80% training and 20% testing." + ], + "advice_to_improve_acc": [ + "Consider using cross-validation for better performance evaluation.", + "Experiment with different kernels to optimize results.", + "Increase the dataset size to improve generalization." + ] +} + Remeber this is just an example how the data shuold be returned. - # Parse the JSON string from `response.choices[0].message.content` into a dictionary - parsed_json = json.loads(response.choices[0].message.content) + """ - # Format the dictionary to make it more readable (4-space indentation, non-ASCII characters displayed as is) - formatted_json = json.dumps(parsed_json, indent=4, ensure_ascii=False) + model = genai.GenerativeModel("gemini-1.5-pro", + generation_config={"response_mime_type": "application/json"}, + system_instruction="You are an advanced machine learning expert that is responsible for making realistic prdedictions and recommendations on machine learning patterns") + response = model.generate_content(system_prompt) - # Print the formatted JSON data - print(formatted_json) - return response.choices[0].message.content + # Print for debugging + print(f"Response content: {response}") + # Return the extracted JSON content + return response def log_to_wandb(response_text): - wandb.log(json.loads(response_text)) - -def log_llm(notebook_path, project_name = None, is_logging = False): - - + try: + # Parse the response text into a dictionary + response_dict = json.loads(response_text) + # Log the dictionary to W&B + wandb.log(response_dict) + except json.JSONDecodeError as e: + print(f"Error parsing JSON: {e}") + except Exception as e: + print(f"Error logging to W&B: {e}") + +def log_llm(notebook_path, project_name=None, is_logging=False): if project_name is None: - project_name = notebook_path.replace(".ipynb","") - + project_name = notebook_path.replace(".ipynb", "") + # Initialize W&B if is_logging: init_wandb(project_name) @@ -78,11 +96,49 @@ def log_llm(notebook_path, project_name = None, is_logging = False): # Extract code from Jupyter Notebook code_string = extract_notebook_code(notebook_path) - # Send code to OpenAI + # Send code to Generative AI response_text = extract_experimental_conditions(code_string) # Log response to W&B if is_logging: log_to_wandb(response_text) - print("Response from OpenAI logged to W&B.") + print("Response from Google Generative AI processed and logged to W&B.") + + + + +def log_to_wandb(parsed_json): + if parsed_json: + try: + # Log the parsed JSON to W&B + wandb.log(parsed_json) + except Exception as e: + print(f"Error logging to W&B: {e}") + else: + print("No data to log. Parsed JSON is empty or None.") + + +def log_llm(notebook_path, project_name=None, is_logging=False): + if project_name is None: + project_name = os.path.basename(notebook_path).replace(".ipynb", "") + + # Initialize W&B + if is_logging: + init_wandb(project_name) + + # Extract code from Jupyter Notebook + code_string = extract_notebook_code(notebook_path) + + # Send code to Google Generative AI for processing + parsed_json = extract_experimental_conditions(code_string) + + # Log the response to W&B + if is_logging and parsed_json: + log_to_wandb(parsed_json) + + print("Response from Google Generative AI processed and logged to W&B.") + + print("Dictionary: ", parsed_json) # Inspect the response to ensure it's valid JSON + + From 2e999d6ebc2f34d69f8e18258f3fef3f8e3a51b1 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:25:19 -0700 Subject: [PATCH 02/17] new test_logger for gemini --- tests/test_logger.py | 97 +++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/tests/test_logger.py b/tests/test_logger.py index ef1de6a..6cc1f42 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -1,10 +1,20 @@ import pytest -import json # jsonモジュールをインポート - +import json +from logllm.log_llm import log_llm from logllm.extractor import extract_notebook_code -from logllm.log_llm import extract_experimental_conditions, logllm +import google.generativeai as genai +from google.generativeai import GenerativeModel +import os + + +genai.configure(api_key=os.environ['API_KEY']) + -# サンプルのJupyter Notebookの内容を含むJSONを定義 +# Define a sample notebook path and project name for testing +notebook_path = "sample_notebook.ipynb" +project_name = "test_project" + +# Mock notebook content for testing sample_notebook_content = { "cells": [ { @@ -22,60 +32,55 @@ ] } -def test_extract_notebook_code(tmp_path): - # テスト用の一時ファイルを作成して、サンプルNotebook JSONを書き込む - notebook_file = tmp_path / "sample_notebook.ipynb" +# Function to create a sample notebook file for testing +def create_sample_notebook(notebook_file): with open(notebook_file, 'w', encoding='utf-8') as f: json.dump(sample_notebook_content, f) - # コード抽出関数をテスト - extracted_code = extract_notebook_code(notebook_file) - expected_code = "print('Hello, World!')\n\na = 10\nb = 20\nc = a + b\nprint(c)\n" - assert extracted_code == expected_code - -def test_extract_experimental_conditions(monkeypatch): - # モックを使用してOpenAIのAPIレスポンスをシミュレート - def mock_chat_completion_create(*args, **kwargs): - return { - 'choices': [ - {'message': {'content': 'Extracted conditions from the code.'}} - ] - } +def test_log_llm(monkeypatch, tmp_path): + # Create a temporary notebook file + notebook_file = tmp_path / notebook_path + create_sample_notebook(notebook_file) - monkeypatch.setattr("openai.ChatCompletion.create", mock_chat_completion_create) - - # APIキーとコードを仮定してテスト - api_key = "fake-api-key" - code = "print('Hello, World!')\n" - response = extract_experimental_conditions(api_key, code) - assert response == 'Extracted conditions from the code.' - -def test_logllm(monkeypatch, tmp_path): - # モックのW&Bの初期化とログ関数 + # Mock the W&B init and log functions def mock_init(*args, **kwargs): pass def mock_log(data): - assert "openai_response" in data - assert data["openai_response"] == 'Extracted conditions from the code.' + assert "method" in data + assert data["method"] == "example_method" monkeypatch.setattr("wandb.init", mock_init) monkeypatch.setattr("wandb.log", mock_log) - # モックのOpenAIレスポンス - def mock_chat_completion_create(*args, **kwargs): - return { - 'choices': [ - {'message': {'content': 'Extracted conditions from the code.'}} - ] - } + # Mock the Google Generative AI response + def mock_generate_content(*args, **kwargs): + class MockResponse: + choices = [type('obj', (object,), { + "message": type('msg', (object,), { + "content": json.dumps({ + "method": "example_method", + "dataset": "example_dataset", + "task": "example_task", + "accuracy": 0.95, + "other_param_here": { + "param1": 10, + "param2": 20 + }, + "condition_as_natural_language": ["Small dataset."], + "advice_to_improve_acc": ["Use a bigger dataset.", "Use a simpler model."] + }) + }) + })] - monkeypatch.setattr("openai.ChatCompletion.create", mock_chat_completion_create) + return MockResponse() - # テスト用の一時ファイルを作成して、サンプルNotebook JSONを書き込む - notebook_file = tmp_path / "sample_notebook.ipynb" - with open(notebook_file, 'w', encoding='utf-8') as f: - json.dump(sample_notebook_content, f) + monkeypatch.setattr("google.generativeai.GenerativeModel.start_chat", mock_generate_content) + + # Call the log_llm function to test + log_llm(str(notebook_file), project_name, is_logging=True) + + print("Test completed successfully.") - # logllm関数をテスト - logllm(str(notebook_file), "fake-api-key", "test-project") \ No newline at end of file +if __name__ == "__main__": + pytest.main([__file__]) From d694282a2cdcc728f55d188f8e2ecf5390009497 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:43:24 -0700 Subject: [PATCH 03/17] query gemini integration --- logllm/query.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/logllm/query.py b/logllm/query.py index 1f3f7c8..c9e0bdb 100644 --- a/logllm/query.py +++ b/logllm/query.py @@ -1,7 +1,11 @@ -from openai import OpenAI +import google.generativeai as genai +import os + +genai.configure(api_key=os.environ['API_KEY']) def query(user_input: str): - client = OpenAI() + model = genai.GenerativeModel("gemini-1.5-flash") + system_prompt = """ # Convert the following query to a W&B API query: @@ -11,9 +15,8 @@ def query(user_input: str): # Here is a user's :{user_input} """ - response = client.chat.completions.create( - model="gpt-4o-mini-2024-07-18", - messages=[ + response = model.start_chat( + history=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] From 2b314741b6bd2399f9be29657a207cbb289a6569 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:47:04 -0700 Subject: [PATCH 04/17] changed setup --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index bac5640..0ff8392 100644 --- a/setup.py +++ b/setup.py @@ -5,11 +5,11 @@ version='0.1', packages=find_packages(), install_requires=[ - 'openai', + 'Gemini', 'wandb', ], description='Automatically extract experimental conditions from your Python scripts with GPT4, and logs results with WandB.', - author='Yusuke', - author_email='yusuke.mikami.contact@gmail.com', - url='https://github.com/shure-dev/logllm', # Replace with your GitHub URL + author='Archilles', + author_email='jakingsarchly@gmail.com', + url='https://github.com/Archly2022/logllm.git', # Replace with your GitHub URL ) \ No newline at end of file From fe503ed1746674f45ff9d310c08770f2339554d9 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:05:10 -0700 Subject: [PATCH 05/17] response in json format --- logllm/log_llm.py | 126 ++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 76 deletions(-) diff --git a/logllm/log_llm.py b/logllm/log_llm.py index f4ee018..3dd4f39 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -1,17 +1,36 @@ import google.generativeai as genai import wandb -from extractor import extract_notebook_code +from logllm import extract_notebook_code import json import os +from dotenv import load_dotenv +import markdown as md -genai.configure(api_key=os.environ['API_KEY']) +load_dotenv() + +genai.configure(api_key=os.getenv('API_KEY')) + +generation_config = { + "temperature": 0, + "top_p": 0.95, + "top_k": 64, + "max_output_tokens": 8192, + "response_mime_type": "application/json", + +} + +model = genai.GenerativeModel( + model_name="gemini-1.5-flash", + generation_config=generation_config, + +) def init_wandb(project_name): wandb.init(project=project_name, settings=wandb.Settings(_disable_stats=True)) def extract_experimental_conditions(code): - system_prompt = """ + user_input = f""" You are an advanced machine learning experiment designer. Extract all experimental conditions and results for logging via wandb API. Add your original parameters in your JSON response if you want to log other parameters. @@ -31,48 +50,34 @@ def extract_experimental_conditions(code): "param2": int }}, "condition_as_natural_language": ["Small dataset."], - "advice_to_improve_acc": ["Use a bigger dataset.", "Use a simpler model."] - Here is a user's Jupyter Notebook script:{code} - - Your answers should return a dictionary like this: - "method": "SVC", - "dataset": "Iris", - "task": "classification", - "accuracy": 1.0, - "C": 1.0, - "degree": 3, - "tol": 0.001, - "cache_size": 200, - "max_iter": -1, - "test_size": 0.2, - "random_state": 42, - "kernel": "linear", - "condition_as_natural_langauge": [ - "Using linear kernel on SVC model.", - "Excluding class 2 from Iris dataset.", - "Splitting data into 80% training and 20% testing." - ], - "advice_to_improve_acc": [ - "Consider using cross-validation for better performance evaluation.", - "Experiment with different kernels to optimize results.", - "Increase the dataset size to improve generalization." - ] -} - Remeber this is just an example how the data shuold be returned. + "advice_to_improve_acc": ["Use a bigger dataset.", "Use a simpler model."]. + f""Here is a user's Jupyter Notebook script: {code}"". """ - model = genai.GenerativeModel("gemini-1.5-pro", - generation_config={"response_mime_type": "application/json"}, - system_instruction="You are an advanced machine learning expert that is responsible for making realistic prdedictions and recommendations on machine learning patterns") - response = model.generate_content(system_prompt) + chat_session = model.start_chat( + history=[ + { + "role": "user", + "parts": [ + "Hello! help me analyse data in json format only", + ], + }, + { + "role": "model", + "parts": [ + "Sure I can do that provide me with data", + ], + }, + ] + ) + response = chat_session.send_message(user_input) + result = response.candidates[0].content.parts[0].text + model_response = md.markdown(result) + print("result: ", result) + return model_response - # Print for debugging - print(f"Response content: {response}") - - # Return the extracted JSON content - return response def log_to_wandb(response_text): try: @@ -85,39 +90,6 @@ def log_to_wandb(response_text): except Exception as e: print(f"Error logging to W&B: {e}") -def log_llm(notebook_path, project_name=None, is_logging=False): - if project_name is None: - project_name = notebook_path.replace(".ipynb", "") - - # Initialize W&B - if is_logging: - init_wandb(project_name) - - # Extract code from Jupyter Notebook - code_string = extract_notebook_code(notebook_path) - - # Send code to Generative AI - response_text = extract_experimental_conditions(code_string) - - # Log response to W&B - if is_logging: - log_to_wandb(response_text) - - print("Response from Google Generative AI processed and logged to W&B.") - - - - -def log_to_wandb(parsed_json): - if parsed_json: - try: - # Log the parsed JSON to W&B - wandb.log(parsed_json) - except Exception as e: - print(f"Error logging to W&B: {e}") - else: - print("No data to log. Parsed JSON is empty or None.") - def log_llm(notebook_path, project_name=None, is_logging=False): if project_name is None: @@ -132,13 +104,15 @@ def log_llm(notebook_path, project_name=None, is_logging=False): # Send code to Google Generative AI for processing parsed_json = extract_experimental_conditions(code_string) + + # parsed_json = json.dumps(parsed_json) + # print(parsed_json) # Log the response to W&B if is_logging and parsed_json: log_to_wandb(parsed_json) print("Response from Google Generative AI processed and logged to W&B.") + print("response: ", parsed_json) - print("Dictionary: ", parsed_json) # Inspect the response to ensure it's valid JSON - - + # print("Dictionary: ", parsed_json) # Inspect the response to ensure it's valid JSON \ No newline at end of file From 1f930ff3806b8c1fe9334b99453743536fecf610 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:05:53 -0700 Subject: [PATCH 06/17] modified --- tests/test_logger.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/test_logger.py b/tests/test_logger.py index 6cc1f42..f4baaa6 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -2,12 +2,8 @@ import json from logllm.log_llm import log_llm from logllm.extractor import extract_notebook_code -import google.generativeai as genai -from google.generativeai import GenerativeModel -import os -genai.configure(api_key=os.environ['API_KEY']) # Define a sample notebook path and project name for testing @@ -83,4 +79,4 @@ class MockResponse: print("Test completed successfully.") if __name__ == "__main__": - pytest.main([__file__]) + pytest.main([__file__]) \ No newline at end of file From c868afb2249eb1720a99dd698b06bd4eb9584af1 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:06:49 -0700 Subject: [PATCH 07/17] commits --- extractor.py | 1 + 1 file changed, 1 insertion(+) create mode 120000 extractor.py diff --git a/extractor.py b/extractor.py new file mode 120000 index 0000000..531c796 --- /dev/null +++ b/extractor.py @@ -0,0 +1 @@ +../logllm/extractor.py \ No newline at end of file From 338506dc005d5e0643016847168e1c6cf48d6da9 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Thu, 29 Aug 2024 07:39:05 -0700 Subject: [PATCH 08/17] provider for llms --- logllm/log_llm.py | 126 ++++++++++++++++++++++++---------------------- logllm/query.py | 74 ++++++++++++++++++++++----- 2 files changed, 126 insertions(+), 74 deletions(-) diff --git a/logllm/log_llm.py b/logllm/log_llm.py index 3dd4f39..d3cfbe6 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -5,31 +5,31 @@ import os from dotenv import load_dotenv import markdown as md +from openai import OpenAI +# Load environment variables load_dotenv() +# Configure Google Generative AI genai.configure(api_key=os.getenv('API_KEY')) generation_config = { - "temperature": 0, - "top_p": 0.95, - "top_k": 64, - "max_output_tokens": 8192, - "response_mime_type": "application/json", - + "temperature": 0, + "top_p": 0.95, + "top_k": 64, + "max_output_tokens": 8192, + "response_mime_type": "application/json", } model = genai.GenerativeModel( - model_name="gemini-1.5-flash", - generation_config=generation_config, - + model_name="gemini-1.5-flash", + generation_config=generation_config, ) def init_wandb(project_name): wandb.init(project=project_name, settings=wandb.Settings(_disable_stats=True)) - -def extract_experimental_conditions(code): +def extract_experimental_conditions_gemini(code): user_input = f""" You are an advanced machine learning experiment designer. Extract all experimental conditions and results for logging via wandb API. @@ -37,82 +37,86 @@ def extract_experimental_conditions(code): Extract all information you can find in the given script as int, bool, or float values. If you cannot describe conditions with int, bool, or float values, use a list of natural language. Give advice to improve the accuracy. - If you use natural language, the answers should be very short. + If you use natural language, the answers should be short. Do not include information already provided in param_name_1 for `condition_as_natural_language`. - Output JSON schema example: - {{ - "method": "str", - "dataset": "str", - "task": "str", - "accuracy": float, - "other_param_here": {{ - "param1": int, - "param2": int - }}, - "condition_as_natural_language": ["Small dataset."], - "advice_to_improve_acc": ["Use a bigger dataset.", "Use a simpler model."]. - - f""Here is a user's Jupyter Notebook script: {code}"". - """ + + Here is a user's Jupyter Notebook script: {code} + """.replace(" ","") chat_session = model.start_chat( - history=[ - { - "role": "user", - "parts": [ - "Hello! help me analyse data in json format only", - ], - }, - { - "role": "model", - "parts": [ - "Sure I can do that provide me with data", - ], - }, - ] + history=[ + {"role": "user", "parts": ["Hello! help me analyse data in json format only"]}, + {"role": "model", "parts": ["Sure I can do that, provide me with data"]}, + ] ) response = chat_session.send_message(user_input) - result = response.candidates[0].content.parts[0].text - model_response = md.markdown(result) - print("result: ", result) - return model_response + result = response.candidates[0].content.parts[0].text + parsed_json = json.loads(result) + formatted_json = json.dumps(parsed_json, indent=4, ensure_ascii=False) + print("response: ", formatted_json) + return formatted_json + +def extract_experimental_conditions_openai(code): + client = OpenAI() + + system_prompt = """ + You are an advanced machine learning experiment designer. + Extract all experimental conditions and results for logging via wandb API. + Add your original parameters in your JSON response if you want to log other parameters. + Extract all information you can find in the given script as int, bool, or float values. + If you cannot describe conditions with int, bool, or float values, use a list of natural language. + Give advice to improve the accuracy. + If you use natural language, the answers should be very short. + Do not include information already provided in param_name_1 for `condition_as_natural_language`. + """.replace(" ", "") + + user_prompt = f""" + Here is a user's Jupyter Notebook script:{code} + """ + + response = client.chat.completions.create( + model="gpt-4o-mini-2024-07-18", + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt}, + ], + response_format={"type": "json_object"}, + ) + + parsed_json = json.loads(response.choices[0].message.content) + formatted_json = json.dumps(parsed_json, indent=4, ensure_ascii=False) + print(formatted_json) + + return response.choices[0].message.content def log_to_wandb(response_text): try: - # Parse the response text into a dictionary response_dict = json.loads(response_text) - # Log the dictionary to W&B wandb.log(response_dict) except json.JSONDecodeError as e: print(f"Error parsing JSON: {e}") except Exception as e: print(f"Error logging to W&B: {e}") - -def log_llm(notebook_path, project_name=None, is_logging=False): +def log_llm(notebook_path, project_name=None, is_logging=False, provider=None): if project_name is None: project_name = os.path.basename(notebook_path).replace(".ipynb", "") - # Initialize W&B if is_logging: init_wandb(project_name) - # Extract code from Jupyter Notebook code_string = extract_notebook_code(notebook_path) - # Send code to Google Generative AI for processing - parsed_json = extract_experimental_conditions(code_string) + if provider == "gemini": + parsed_json = extract_experimental_conditions_gemini(code_string) + elif provider == "openai": + parsed_json = extract_experimental_conditions_openai(code_string) + else: + raise ValueError("Invalid provider specified. Use 'gemini' or 'openai'.") - # parsed_json = json.dumps(parsed_json) - # print(parsed_json) - - # Log the response to W&B if is_logging and parsed_json: log_to_wandb(parsed_json) - print("Response from Google Generative AI processed and logged to W&B.") - print("response: ", parsed_json) - - # print("Dictionary: ", parsed_json) # Inspect the response to ensure it's valid JSON \ No newline at end of file + print("Response from the provider processed and logged to W&B.") diff --git a/logllm/query.py b/logllm/query.py index c9e0bdb..3612885 100644 --- a/logllm/query.py +++ b/logllm/query.py @@ -1,27 +1,75 @@ import google.generativeai as genai -import os +import os +from dotenv import load_dotenv +import openai +from logllm.log_llm import log_llm -genai.configure(api_key=os.environ['API_KEY']) +# Load environment variables +load_dotenv() -def query(user_input: str): - model = genai.GenerativeModel("gemini-1.5-flash") +# Configure Google Generative AI API Key +genai.configure(api_key=os.getenv('API_KEY')) +# Function to query OpenAI +def query_openai(user_input: str): system_prompt = """ - # Convert the following query to a W&B API query: - """.replace(" ","") + Convert the following query to a W&B API query: + """.strip() user_prompt = f""" - # Here is a user's :{user_input} - """ + Here is a user's query: {user_input} + """.strip() - response = model.start_chat( - history=[ + response = openai.ChatCompletion.create( + model="gpt-4o-mini-2024-07-18", + messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ] ) - print(response) - - \ No newline at end of file + return response['choices'][0]['message']['content'] + +# Function to query Google Gemini +def query_gemini(user_input: str): + model = genai.GenerativeModel("gemini-1.5-flash") + + system_prompt = """ + Convert the following query to a W&B API query: + """.strip() + + user_prompt = f""" + Here is a user's query: {user_input} + """.strip() + + chat_session = model.start_chat( + history=[ + {"role": "system", "parts": [system_prompt]}, + {"role": "user", "parts": [user_prompt]}, + ] + ) + + response = chat_session.send_message(user_prompt) + return response.candidates[0].content.parts[0].text + +# General query function that calls the appropriate provider +def query(user_input: str, provider: str): + if provider == 'openai': + return query_openai(user_input) + elif provider == 'gemini': + return query_gemini(user_input) + else: + raise ValueError("Invalid provider specified. Use 'openai' or 'gemini'.") + +# Usage Example: +notebook_path = "demos/svc-sample.ipynb" + +# Extract experimental conditions and results using log_llm +parsed_json = log_llm(notebook_path, project_name="Machine learning", is_logging=False, provider="gemini") + +# Use the parsed_json as user_input for the query +response = query("what is the best model? :{parsed_json}", provider="gemini") + +# Print the response from the query +print(response) From 9efbc318862de25fa56c2de56ae2cdf303396a20 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:54:10 -0700 Subject: [PATCH 09/17] added query for gemini provider --- demos/svc-sample.ipynb | 629 ++++++++++++++++++++++++++++++++++++----- logllm/log_llm.py | 1 + logllm/query.py | 28 +- 3 files changed, 575 insertions(+), 83 deletions(-) diff --git a/demos/svc-sample.ipynb b/demos/svc-sample.ipynb index 2710f7e..968f8b4 100644 --- a/demos/svc-sample.ipynb +++ b/demos/svc-sample.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -136,83 +136,185 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 27, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "Finishing last run (ID:0k33o6dd) before initializing another..." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "97a074080cae47398d640efce9fbd7c8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Label(value='0.001 MB of 0.001 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View run still-water-35 at: https://wandb.ai/jakingsarchly-aj-technologies/svc-sample/runs/0k33o6dd
View project at: https://wandb.ai/jakingsarchly-aj-technologies/svc-sample
Synced 5 W&B file(s), 0 media file(s), 0 artifact file(s) and 0 other file(s)" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Find logs at: ./wandb/run-20240828_173350-0k33o6dd/logs" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Successfully finished last run (ID:0k33o6dd). Initializing new run:
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "309bc972e41a413198f404fa324e9660", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.0114827127111817, max=1.0))…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "wandb version 0.17.8 is available! To upgrade, please run:\n", + " $ pip install wandb --upgrade" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Tracking run with wandb version 0.17.7" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240828_173436-tzy0aus4" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Syncing run hearty-frost-36 to Weights & Biases (docs)
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View project at https://wandb.ai/jakingsarchly-aj-technologies/svc-sample" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View run at https://wandb.ai/jakingsarchly-aj-technologies/svc-sample/runs/tzy0aus4" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "name": "stdout", "output_type": "stream", "text": [ - "{\n", - " \"method\": \"SVC\",\n", - " \"dataset\": \"Iris\",\n", - " \"task\": \"classification\",\n", - " \"accuracy\": 1.0,\n", - " \"C\": 1.0,\n", - " \"degree\": 3,\n", - " \"tol\": 0.001,\n", - " \"cache_size\": 200,\n", - " \"max_iter\": -1,\n", - " \"test_size\": 0.2,\n", - " \"random_state\": 42,\n", - " \"kernel\": \"linear\",\n", - " \"condition_as_natural_langauge\": [\n", - " \"Using linear kernel on SVC model.\",\n", - " \"Excluding class 2 from Iris dataset.\",\n", - " \"Splitting data into 80% training and 20% testing.\",\n", - " \"Shrinking enabled for SVC.\"\n", - " ],\n", - " \"advice_to_improve_acc\": [\n", - " \"Consider using cross-validation for better performance evaluation.\",\n", - " \"Experiment with different kernels to optimize results.\",\n", - " \"Increase the dataset size to improve generalization.\"\n", - " ]\n", - "}\n", - "Response from OpenAI logged to W&B.\n" + "Response from Google Generative AI processed and logged to W&B.\n", + "Dictionary: \n" ] } ], "source": [ - "from logllm import log_llm\n", + "from logllm.log_llm import log_llm\n", "\n", "notebook_path = \"svc-sample.ipynb\" # Here is target file to log\n", "\n", - "log_llm(notebook_path,is_logging=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Expected condition with GPT4 from the script\n", - "\n", - "```Python\n", - "{\n", - " \"method\": \"SVC\",\n", - " \"dataset\": \"Iris\",\n", - " \"task\": \"classification\",\n", - " \"accuracy\": 1.0,\n", - " \"C\": 1.0,\n", - " \"degree\": 3,\n", - " \"tol\": 0.001,\n", - " \"cache_size\": 200,\n", - " \"max_iter\": -1,\n", - " \"test_size\": 0.2,\n", - " \"random_state\": 42,\n", - " \"kernel\": \"linear\",\n", - " \"condition_as_natural_langauge\": [\n", - " \"Using linear kernel on SVC model.\",\n", - " \"Excluding class 2 from Iris dataset.\",\n", - " \"Splitting data into 80% training and 20% testing.\"\n", - " ],\n", - " \"advice_to_improve_acc\": [\n", - " \"Consider using cross-validation for better performance evaluation.\",\n", - " \"Experiment with different kernels to optimize results.\",\n", - " \"Increase the dataset size to improve generalization.\"\n", - " ]\n", - "}\n", - "\n", - "```" + "log_llm(notebook_path,is_logging=True)" ] }, { @@ -220,20 +322,409 @@ "execution_count": 3, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "Finishing last run (ID:cgiewcph) before initializing another..." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1948cf8b7b924ea18bcac164243eea12", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Label(value='0.001 MB of 0.001 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + "

Run history:


param_value_1
param_value_10
param_value_11
param_value_12
param_value_13
param_value_15
param_value_16
param_value_18
param_value_2
param_value_3
param_value_4
param_value_5
param_value_7
param_value_9
result_value_1
result_value_2
result_value_3
result_value_4
result_value_5

Run summary:


adviceTry different kernel...
param_name_1test_size
param_name_10shrinking
param_name_11probability
param_name_12tol
param_name_13cache_size
param_name_14class_weight
param_name_15verbose
param_name_16max_iter
param_name_17decision_function_sh...
param_name_18break_ties
param_name_19random_state
param_name_2random_state
param_name_3shuffle
param_name_4stratify
param_name_5C
param_name_6kernel
param_name_7degree
param_name_8gamma
param_name_9coef0
param_value_10.2
param_value_10True
param_value_11False
param_value_120.001
param_value_13200
param_value_15False
param_value_16-1
param_value_17ovr
param_value_18False
param_value_242
param_value_3True
param_value_4True
param_value_51.0
param_value_6linear
param_value_73
param_value_8auto
param_value_90.0
result_name_1accuracy
result_name_2precision
result_name_3recall
result_name_4f1-score
result_name_5support
result_value_11.0
result_value_21.0
result_value_31.0
result_value_41.0
result_value_510

" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View run feasible-firefly-6 at: https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/cgiewcph
View project at: https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning
Synced 6 W&B file(s), 0 media file(s), 0 artifact file(s) and 0 other file(s)" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Find logs at: ./wandb/run-20240829_234314-cgiewcph/logs" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Successfully finished last run (ID:cgiewcph). Initializing new run:
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "85e6384590334d3cbe7d0a9af4c13821", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.011427467188877927, max=1.0…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "wandb version 0.17.8 is available! To upgrade, please run:\n", + " $ pip install wandb --upgrade" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Tracking run with wandb version 0.17.7" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240829_234514-7yf7z1q5" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Syncing run lyric-sunset-7 to Weights & Biases (docs)
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View project at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " View run at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/7yf7z1q5" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "name": "stdout", "output_type": "stream", "text": [ - "ChatCompletion(id='chatcmpl-9zwYXx1NmoGH6pF3HgxopPsanZpVl', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='To convert the user\\'s query into a W&B (Weights & Biases) API query, you might want to search for the best model based on certain metrics or criteria defined in your W&B workspace. Here\\'s a sample API query to retrieve the best model:\\n\\n```python\\nimport wandb\\n\\n# Initialize a W&B run\\nwandb.login()\\n\\n# Define your project and entity\\nproject = \\'your_project_name\\'\\nentity = \\'your_entity_name\\'\\n\\n# Retrieve the best model based on a specific metric\\nbest_model = wandb.Api().runs(f\"{entity}/{project}\", {\"order\": \"-summary.best_metric_name\"}).get(0)\\n\\n# Display the best model details\\nprint(\"Best Model ID:\", best_model.id)\\nprint(\"Best Model Summary:\", best_model.summary)\\n```\\n\\nReplace `your_project_name`, `your_entity_name`, and `summary.best_metric_name` with the appropriate values for your specific use case.', refusal=None, role='assistant', function_call=None, tool_calls=None))], created=1724550125, model='gpt-4o-mini-2024-07-18', object='chat.completion', service_tier=None, system_fingerprint='fp_48196bc67a', usage=CompletionUsage(completion_tokens=186, prompt_tokens=40, total_tokens=226))\n" + "response: {\n", + " \"param_name_1\": {\n", + " \"condition_as_natural_language\": \"Support Vector Machine model with linear kernel\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": 10,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": 1.0\n", + " },\n", + " \"param_name_2\": {\n", + " \"condition_as_natural_language\": \"Test size is 20%\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": 0.2,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_3\": {\n", + " \"condition_as_natural_language\": \"Random state is 42\",\n", + " \"condition_as_int\": 42,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_4\": {\n", + " \"condition_as_natural_language\": \"Shuffle is True\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": true,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_5\": {\n", + " \"condition_as_natural_language\": \"Stratify is True\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": true,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_6\": {\n", + " \"condition_as_natural_language\": \"C is 1.0\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": 1.0,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_7\": {\n", + " \"condition_as_natural_language\": \"Kernel is linear\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_8\": {\n", + " \"condition_as_natural_language\": \"Degree is 3\",\n", + " \"condition_as_int\": 3,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_9\": {\n", + " \"condition_as_natural_language\": \"Gamma is auto\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_10\": {\n", + " \"condition_as_natural_language\": \"Coef0 is 0.0\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": 0.0,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_11\": {\n", + " \"condition_as_natural_language\": \"Shrinking is True\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": true,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_12\": {\n", + " \"condition_as_natural_language\": \"Probability is False\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": false,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_13\": {\n", + " \"condition_as_natural_language\": \"Tol is 1e-3\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": 0.001,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_14\": {\n", + " \"condition_as_natural_language\": \"Cache size is 200\",\n", + " \"condition_as_int\": 200,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_15\": {\n", + " \"condition_as_natural_language\": \"Class weight is None\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_16\": {\n", + " \"condition_as_natural_language\": \"Verbose is False\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": false,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_17\": {\n", + " \"condition_as_natural_language\": \"Max iter is -1\",\n", + " \"condition_as_int\": -1,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_18\": {\n", + " \"condition_as_natural_language\": \"Decision function shape is ovr\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_19\": {\n", + " \"condition_as_natural_language\": \"Break ties is False\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": false,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_20\": {\n", + " \"condition_as_natural_language\": \"Random state is None\",\n", + " \"condition_as_int\": null,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"param_name_21\": {\n", + " \"condition_as_natural_language\": \"Excluded class is 1\",\n", + " \"condition_as_int\": 1,\n", + " \"condition_as_bool\": null,\n", + " \"condition_as_float\": null,\n", + " \"result_as_int\": null,\n", + " \"result_as_bool\": null,\n", + " \"result_as_float\": null\n", + " },\n", + " \"advice\": \"Try different kernels, like 'rbf' or 'poly', and adjust the hyperparameters (C, gamma) to see if you can improve the accuracy.\"\n", + "}\n", + "Response from the provider processed and logged to W&B.\n", + "It seems like you're trying to find the best model based on a set of parameters and their corresponding results. However, the provided data is not in a format that can be directly used for a W&B API query. \n", + "\n", + "To help you create a W&B API query, I need more information:\n", + "\n", + "1. **What is the metric you are using to evaluate the \"best\" model?** Is it accuracy, precision, recall, F1-score, or something else?\n", + "2. **What is the name of the experiment or project in Weights & Biases where you have logged these results?**\n", + "3. **What is the specific W&B API endpoint you want to use?** For example, are you looking to retrieve the best model based on a specific metric, or are you trying to filter runs based on certain parameter values?\n", + "\n", + "Once you provide this information, I can help you construct a W&B API query to find the best model based on your criteria. \n", + "\n" ] } ], "source": [ - "from logllm import query\n", + "from logllm.log_llm import log_llm\n", + "from logllm.query import query\n", "\n", - "notebook_path = \"svc-sample.ipynb\" # Here is target file to log\n", + "notebook_path = \"svc-sample.ipynb\" \n", + "# code_string = extract_notebook_code(notebook_path)\n", + "\n", + "# Extract experimental conditions and results using log_llm\n", + "code_string = log_llm(notebook_path, project_name=\"Machine learning\", is_logging=True, provider=\"gemini\")\n", + "\n", + "# Use the parsed_json as user_input for the query\n", + "response = query(f\"\"\"Whats the best model?. {code_string}\"\"\", provider=\"gemini\")\n", "\n", - "query(\"what is the best model?\")" + "# Print the response from the query\n", + "print(response)" ] } ], diff --git a/logllm/log_llm.py b/logllm/log_llm.py index d3cfbe6..296f7a4 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -120,3 +120,4 @@ def log_llm(notebook_path, project_name=None, is_logging=False, provider=None): log_to_wandb(parsed_json) print("Response from the provider processed and logged to W&B.") + return parsed_json diff --git a/logllm/query.py b/logllm/query.py index 3612885..20ff520 100644 --- a/logllm/query.py +++ b/logllm/query.py @@ -2,13 +2,20 @@ import os from dotenv import load_dotenv import openai -from logllm.log_llm import log_llm +from logllm.extractor import extract_notebook_code # Load environment variables load_dotenv() # Configure Google Generative AI API Key genai.configure(api_key=os.getenv('API_KEY')) +generation_config = { + "temperature": 0, + "top_p": 0.95, + "top_k": 64, + "max_output_tokens": 8192, + "response_mime_type": "text/plain", +} # Function to query OpenAI def query_openai(user_input: str): @@ -33,20 +40,20 @@ def query_openai(user_input: str): # Function to query Google Gemini def query_gemini(user_input: str): - model = genai.GenerativeModel("gemini-1.5-flash") + model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config) system_prompt = """ - Convert the following query to a W&B API query: + Please provide the data you want me to convert to a W&B API query: """.strip() user_prompt = f""" Here is a user's query: {user_input} - """.strip() + """ chat_session = model.start_chat( history=[ - {"role": "system", "parts": [system_prompt]}, {"role": "user", "parts": [user_prompt]}, + {"role": "model", "parts": [system_prompt]}, ] ) @@ -54,6 +61,7 @@ def query_gemini(user_input: str): return response.candidates[0].content.parts[0].text # General query function that calls the appropriate provider + def query(user_input: str, provider: str): if provider == 'openai': return query_openai(user_input) @@ -61,15 +69,7 @@ def query(user_input: str, provider: str): return query_gemini(user_input) else: raise ValueError("Invalid provider specified. Use 'openai' or 'gemini'.") + # Usage Example: -notebook_path = "demos/svc-sample.ipynb" - -# Extract experimental conditions and results using log_llm -parsed_json = log_llm(notebook_path, project_name="Machine learning", is_logging=False, provider="gemini") - -# Use the parsed_json as user_input for the query -response = query("what is the best model? :{parsed_json}", provider="gemini") -# Print the response from the query -print(response) From b35664bf1e8f62bdfa0b1b4f647174a146328dd2 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Fri, 30 Aug 2024 00:27:13 -0700 Subject: [PATCH 10/17] commit --- extractor.py | 1 - 1 file changed, 1 deletion(-) delete mode 120000 extractor.py diff --git a/extractor.py b/extractor.py deleted file mode 120000 index 531c796..0000000 --- a/extractor.py +++ /dev/null @@ -1 +0,0 @@ -../logllm/extractor.py \ No newline at end of file From 1bfa4115e96e0ac6cd43e66b81036a89adaa836d Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Sat, 31 Aug 2024 05:27:02 -0700 Subject: [PATCH 11/17] modified logllm response --- logllm/log_llm.py | 185 +++++++++++++++++++++++----------------------- 1 file changed, 94 insertions(+), 91 deletions(-) diff --git a/logllm/log_llm.py b/logllm/log_llm.py index 296f7a4..724757d 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -4,120 +4,123 @@ import json import os from dotenv import load_dotenv -import markdown as md from openai import OpenAI -# Load environment variables +def init_wandb(project_name): + wandb.init(project=project_name, settings=wandb.Settings(_disable_stats=True)) + +# Load environment variables from a .env file load_dotenv() -# Configure Google Generative AI -genai.configure(api_key=os.getenv('API_KEY')) +# Function to configure Google Generative AI only when needed +def configure_google_genai(): + # Set up Google Generative AI with API key and model configuration + genai.configure(api_key=os.getenv('API_KEY')) + + # Define generation settings for the model + generation_config = { + "temperature": 0, # Controls the randomness of the output + "top_p": 0.95, # Nucleus sampling parameter + "top_k": 64, # Limits the pool of candidates to the top-k + "max_output_tokens": 8192, # Maximum number of tokens in the output + "response_mime_type": "application/json", # Expected response format + } + + # Initialize and return the GenerativeModel instance + return genai.GenerativeModel( + model_name="gemini-1.5-flash", + generation_config=generation_config, + ) -generation_config = { - "temperature": 0, - "top_p": 0.95, - "top_k": 64, - "max_output_tokens": 8192, - "response_mime_type": "application/json", -} +# System prompt for guiding the AI model to extract experiment details +system_prompt = """ + You are an advanced machine learning experiment designer. + Extract all experimental conditions and results for logging via wandb API. + Add your original parameters in your JSON response if you want to log other parameters. + Extract all information you can find in the given script as int, bool, or float values. + If you cannot describe conditions with int, bool, or float values, use a list of natural language. + Give advice to improve the accuracy. + If you use natural language, the answers should be very short. + Do not include information already provided in param_name_1 for `condition_as_natural_language`. + Output JSON schema example: + This is just an example, make changes as necessary. Use nested dictionaries if necessary. + {{ + "method":"str", + "dataset":"str", + "task":"str", + "accuracy":"", + "other_param_here":{ + "other_param_here":"", + "other_param_here":"", + }, + "other_param_here":"", + ... + "condition_as_natural_language":["Small dataset."], + "advice_to_improve_acc":["Use a bigger dataset.","Use a simpler model."] + }} +""".replace(" ", "") + +# Function to extract experimental conditions using the specified provider (Google or OpenAI) +def extract_experimental_conditions(provider, code): + # Combine system prompt with user's code input + user_input = f"{system_prompt}\n\nHere is a user's Jupyter Notebook script: {code}" -model = genai.GenerativeModel( - model_name="gemini-1.5-flash", - generation_config=generation_config, -) + if provider == "gemini": + # Configure and use Google Generative AI if specified + model = configure_google_genai() + chat_session = model.start_chat( + history=[{"role": "user", "parts": ["Hello! help me analyze data in JSON format only and return only json object nothing else"]}] + ) + response = chat_session.send_message(user_input) + result = response.candidates[0].content.parts[0].text -def init_wandb(project_name): - wandb.init(project=project_name, settings=wandb.Settings(_disable_stats=True)) + elif provider == "openai": + # Use OpenAI's API to get the response + client = OpenAI() + response = client.chat.completions.create( + model="gpt-4o-mini-2024-07-18", + messages=[ + {"role": "system", "content": user_input}, + ], + response_format={"type": "json_object"}, + ) + result = response.choices[0].message.content -def extract_experimental_conditions_gemini(code): - user_input = f""" - You are an advanced machine learning experiment designer. - Extract all experimental conditions and results for logging via wandb API. - Add your original parameters in your JSON response if you want to log other parameters. - Extract all information you can find in the given script as int, bool, or float values. - If you cannot describe conditions with int, bool, or float values, use a list of natural language. - Give advice to improve the accuracy. - If you use natural language, the answers should be short. - Do not include information already provided in param_name_1 for `condition_as_natural_language`. - - Here is a user's Jupyter Notebook script: {code} - """.replace(" ","") - - chat_session = model.start_chat( - history=[ - {"role": "user", "parts": ["Hello! help me analyse data in json format only"]}, - {"role": "model", "parts": ["Sure I can do that, provide me with data"]}, - ] - ) + else: + # Raise an error if an invalid provider is specified + raise ValueError("Invalid provider specified. Use 'gemini' or 'openai'.") - response = chat_session.send_message(user_input) - result = response.candidates[0].content.parts[0].text - + # Parse the result from JSON string to Python dictionary parsed_json = json.loads(result) - formatted_json = json.dumps(parsed_json, indent=4, ensure_ascii=False) - print("response: ", formatted_json) - return formatted_json - -def extract_experimental_conditions_openai(code): - client = OpenAI() - - system_prompt = """ - You are an advanced machine learning experiment designer. - Extract all experimental conditions and results for logging via wandb API. - Add your original parameters in your JSON response if you want to log other parameters. - Extract all information you can find in the given script as int, bool, or float values. - If you cannot describe conditions with int, bool, or float values, use a list of natural language. - Give advice to improve the accuracy. - If you use natural language, the answers should be very short. - Do not include information already provided in param_name_1 for `condition_as_natural_language`. - """.replace(" ", "") - - user_prompt = f""" - Here is a user's Jupyter Notebook script:{code} - """ - - response = client.chat.completions.create( - model="gpt-4o-mini-2024-07-18", - messages=[ - {"role": "system", "content": system_prompt}, - {"role": "user", "content": user_prompt}, - ], - response_format={"type": "json_object"}, - ) - - parsed_json = json.loads(response.choices[0].message.content) - formatted_json = json.dumps(parsed_json, indent=4, ensure_ascii=False) - print(formatted_json) - - return response.choices[0].message.content + # Format the JSON output for better readability + return json.dumps(parsed_json, indent=4, ensure_ascii=False) +# Function to log the extracted information to Weights & Biases (W&B) def log_to_wandb(response_text): try: + # Parse the JSON response and log it to W&B response_dict = json.loads(response_text) wandb.log(response_dict) - except json.JSONDecodeError as e: - print(f"Error parsing JSON: {e}") - except Exception as e: + except (json.JSONDecodeError, Exception) as e: + # Handle errors in JSON parsing or W&B logging print(f"Error logging to W&B: {e}") +# Main function to extract and log experimental conditions from a Jupyter Notebook def log_llm(notebook_path, project_name=None, is_logging=False, provider=None): - if project_name is None: - project_name = os.path.basename(notebook_path).replace(".ipynb", "") - + # Use the notebook file name as the project name if not specified + project_name = project_name or os.path.basename(notebook_path).replace(".ipynb", "") if is_logging: + # Initialize a new W&B run if logging is enabled init_wandb(project_name) + # Extract the code from the notebook code_string = extract_notebook_code(notebook_path) - - if provider == "gemini": - parsed_json = extract_experimental_conditions_gemini(code_string) - elif provider == "openai": - parsed_json = extract_experimental_conditions_openai(code_string) - else: - raise ValueError("Invalid provider specified. Use 'gemini' or 'openai'.") + # Extract the experimental conditions using the specified AI provider + parsed_json = extract_experimental_conditions(provider, code_string) if is_logging and parsed_json: + # Log the extracted information to W&B log_to_wandb(parsed_json) - print("Response from the provider processed and logged to W&B.") - return parsed_json + # Inform the user that the process is complete + print("Response from the provider processed and logged to W&B.") \ No newline at end of file From d5dd6cef36415b3bc66122fc3793614c33c3fb7c Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Sat, 31 Aug 2024 05:34:19 -0700 Subject: [PATCH 12/17] data visualization --- logllm/plot.py | 35 ++++++ logllm/svc-sample.ipynb | 242 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 logllm/plot.py create mode 100644 logllm/svc-sample.ipynb diff --git a/logllm/plot.py b/logllm/plot.py new file mode 100644 index 0000000..5b449ef --- /dev/null +++ b/logllm/plot.py @@ -0,0 +1,35 @@ +import json +import matplotlib.pyplot as plt + +def plot_ml_metrics(response_data): + # Parse the JSON string into a Python dictionary if needed + if isinstance(response_data, str): + response_data = json.loads(response_data) + + try: + # Extract all keys that start with "result_name_" and their corresponding "result_value_" + metrics = [] + values = [] + for key, value in response_data.items(): + if key.startswith("result_name_"): + metric_name = value + metric_index = key.split("_")[-1] # Extract the index (e.g., "1" from "result_name_1") + metric_value = response_data.get(f"result_value_{metric_index}", None) + + if metric_value is not None: + metrics.append(metric_name) + values.append(metric_value) + + # Plotting + plt.figure(figsize=(10, 6)) # Adjusted figure size for better visualization + plt.bar(metrics, values, color='skyblue') + plt.title('Model Performance Metrics', fontsize=16) + plt.xlabel('Metric', fontsize=14) + plt.ylabel('Value', fontsize=14) + plt.ylim(0, max(values) * 1.1) # Dynamically set the y-limit based on the maximum value + plt.grid(True, axis='y', linestyle='--', alpha=0.7) + plt.tight_layout() + plt.show() + + except TypeError as e: + print(f"Error processing the response data: {e}") diff --git a/logllm/svc-sample.ipynb b/logllm/svc-sample.ipynb new file mode 100644 index 0000000..d3b4ff4 --- /dev/null +++ b/logllm/svc-sample.ipynb @@ -0,0 +1,242 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sample code how to use `logllm` package" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your (messy) machine learning code is here" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Filtered Confusion Matrix (excluding Class 1):\n", + "[[10]]\n", + "\n", + "Detailed Classification Report (excluding certain classes):\n", + " precision recall f1-score support\n", + "\n", + " Class 0 1.0000 1.0000 1.0000 10\n", + "\n", + " accuracy 1.0000 10\n", + " macro avg 1.0000 1.0000 1.0000 10\n", + "weighted avg 1.0000 1.0000 1.0000 10\n", + "\n", + "\n", + "Note: Class 1 was intentionally excluded from the evaluation.\n" + ] + } + ], + "source": [ + "from sklearn import datasets as ds\n", + "from sklearn.model_selection import train_test_split as tts\n", + "from sklearn.svm import SVC as SupportVectorClassifier\n", + "from sklearn.metrics import confusion_matrix as cm, classification_report as cr\n", + "import numpy as np\n", + "\n", + "# Load the dataset\n", + "iris_dataset = ds.load_iris()\n", + "\n", + "# Binarize the class labels (exclude Class 2)\n", + "features = iris_dataset.data[iris_dataset.target != 2] \n", + "labels = iris_dataset.target[iris_dataset.target != 2] \n", + "\n", + "# Split the data into training and test sets\n", + "train_data, test_data, train_labels, test_labels = tts(\n", + " features, \n", + " labels, \n", + " test_size=0.2, \n", + " random_state=42, \n", + " shuffle=True, \n", + " stratify=labels \n", + ")\n", + "\n", + "# Initialize and configure the Support Vector Machine model\n", + "svc_model = SupportVectorClassifier(\n", + " C=1.0, \n", + " kernel='linear', \n", + " degree=3, \n", + " gamma='auto', \n", + " coef0=0.0, \n", + " shrinking=True,\n", + " probability=False, \n", + " tol=1e-3, \n", + " cache_size=200, \n", + " class_weight=None,\n", + " verbose=False, \n", + " max_iter=-1, \n", + " decision_function_shape='ovr',\n", + " break_ties=False, \n", + " random_state=None\n", + ")\n", + "\n", + "# Train the model\n", + "svc_model.fit(train_data, train_labels)\n", + "\n", + "# Obtain the predicted results for the test data\n", + "predicted_labels = svc_model.predict(test_data)\n", + "\n", + "# Create the confusion matrix\n", + "conf_matrix = cm(test_labels, predicted_labels)\n", + "\n", + "# Define evaluation labels (intentionally exclude Class 1)\n", + "excluded_class = 1\n", + "classes_to_evaluate = [cls for cls in np.unique(test_labels) if cls != excluded_class]\n", + "\n", + "# Calculate confusion matrix with the excluded class removed\n", + "conf_matrix_filtered = np.array([\n", + " [conf_matrix[i, j] for j in range(len(conf_matrix)) if j != excluded_class]\n", + " for i in range(len(conf_matrix)) if i != excluded_class\n", + "])\n", + "\n", + "# Filter true labels and predicted labels (only keep the evaluated classes)\n", + "filtered_test_labels = [label for label in test_labels if label in classes_to_evaluate]\n", + "filtered_predicted_labels = [pred for pred in predicted_labels if pred in classes_to_evaluate]\n", + "\n", + "# Output a detailed classification report (excluding the specified class)\n", + "classification_report_filtered = cr(\n", + " filtered_test_labels, \n", + " filtered_predicted_labels, \n", + " labels=classes_to_evaluate,\n", + " target_names=[f\"Class {cls}\" for cls in classes_to_evaluate],\n", + " digits=4,\n", + " output_dict=False,\n", + " zero_division=0\n", + ")\n", + "\n", + "# Display the complex evaluation results\n", + "print(f\"Filtered Confusion Matrix (excluding Class {excluded_class}):\\n{conf_matrix_filtered}\")\n", + "print(\"\\nDetailed Classification Report (excluding certain classes):\")\n", + "print(classification_report_filtered)\n", + "\n", + "# Provide a note regarding the intentionally excluded class\n", + "if excluded_class in np.unique(test_labels):\n", + " print(f\"\\nNote: Class {excluded_class} was intentionally excluded from the evaluation.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Start logging with `logllm`" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Response from Google Generative AI processed and logged to W&B.\n", + "Dictionary: \n" + ] + } + ], + "source": [ + "from logllm.log_llm import log_llm\n", + "\n", + "notebook_path = \"svc-sample.ipynb\" # Here is target file to log\n", + "\n", + "log_llm(notebook_path,is_logging=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Expected condition with GPT4 from the script\n", + "\n", + "```Python\n", + "{\n", + " \"method\": \"SVC\",\n", + " \"dataset\": \"Iris\",\n", + " \"task\": \"classification\",\n", + " \"accuracy\": 1.0,\n", + " \"C\": 1.0,\n", + " \"degree\": 3,\n", + " \"tol\": 0.001,\n", + " \"cache_size\": 200,\n", + " \"max_iter\": -1,\n", + " \"test_size\": 0.2,\n", + " \"random_state\": 42,\n", + " \"kernel\": \"linear\",\n", + " \"condition_as_natural_langauge\": [\n", + " \"Using linear kernel on SVC model.\",\n", + " \"Excluding class 2 from Iris dataset.\",\n", + " \"Splitting data into 80% training and 20% testing.\"\n", + " ],\n", + " \"advice_to_improve_acc\": [\n", + " \"Consider using cross-validation for better performance evaluation.\",\n", + " \"Experiment with different kernels to optimize results.\",\n", + " \"Increase the dataset size to improve generalization.\"\n", + " ]\n", + "}\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "GenerativeModel.start_chat() got an unexpected keyword argument 'model'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[13], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlogllm\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mquery\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m query\n\u001b[1;32m 3\u001b[0m notebook_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msvc-sample.ipynb\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;66;03m# Here is target file to log\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m query(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwhat is the best model?\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/vscode/logllm/logllm/query.py:18\u001b[0m, in \u001b[0;36mquery\u001b[0;34m(user_input)\u001b[0m\n\u001b[1;32m 10\u001b[0m model \u001b[38;5;241m=\u001b[39m genai\u001b[38;5;241m.\u001b[39mGenerativeModel(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgemini-1.5-flash\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 13\u001b[0m system_prompt \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;124m # Convert the following query to a W&B API query:\u001b[39m\n\u001b[1;32m 15\u001b[0m \u001b[38;5;124m\u001b[39m\u001b[38;5;124m\"\"\"\u001b[39m\u001b[38;5;241m.\u001b[39mreplace(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m,\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 17\u001b[0m user_prompt \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[0;32m---> 18\u001b[0m \u001b[38;5;124m# Here is a user\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms :\u001b[39m\u001b[38;5;132;01m{\u001b[39;00muser_input\u001b[38;5;132;01m}\u001b[39;00m\n\u001b[1;32m 19\u001b[0m \u001b[38;5;124m\u001b[39m\u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[1;32m 21\u001b[0m response \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mstart_chat(\n\u001b[1;32m 22\u001b[0m model\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgemini-1.5-flash\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 23\u001b[0m history\u001b[38;5;241m=\u001b[39m[\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 26\u001b[0m ]\n\u001b[1;32m 27\u001b[0m )\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28mprint\u001b[39m(response)\n", + "\u001b[0;31mTypeError\u001b[0m: GenerativeModel.start_chat() got an unexpected keyword argument 'model'" + ] + } + ], + "source": [ + "from logllm.query import query\n", + "\n", + "notebook_path = \"svc-sample.ipynb\" # Here is target file to log\n", + "\n", + "query(\"what is the best model?\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 0669102ffc39d1009bbb42bb771c8b9ca193b06d Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Sat, 31 Aug 2024 05:35:12 -0700 Subject: [PATCH 13/17] commit --- requirements.txt | 129 +++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 65 deletions(-) diff --git a/requirements.txt b/requirements.txt index 94406a3..307ebe4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,65 +1,64 @@ -annotated-types==0.7.0 -anyio==4.4.0 -appnope==0.1.4 -asttokens==2.4.1 -certifi==2024.7.4 -charset-normalizer==3.3.2 -click==8.1.7 -comm==0.2.2 -debugpy==1.8.5 -decorator==5.1.1 -distro==1.9.0 -docker-pycreds==0.4.0 -executing==2.0.1 -gitdb==4.0.11 -GitPython==3.1.43 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -idna==3.7 -ipykernel==6.29.5 -ipynbname==2024.1.0.0 -ipython==8.26.0 -jedi==0.19.1 -jiter==0.5.0 -joblib==1.4.2 -jupyter_client==8.6.2 -jupyter_core==5.7.2 --e git+https://github.com/shure-dev/logllm.git@6e726bcbbc9ec449eb3b2b455d68f88065c73380#egg=logllm -matplotlib-inline==0.1.7 -nest-asyncio==1.6.0 -numpy==2.1.0 -openai==1.42.0 -packaging==24.1 -parso==0.8.4 -pexpect==4.9.0 -platformdirs==4.2.2 -prompt_toolkit==3.0.47 -protobuf==5.27.3 -psutil==6.0.0 -ptyprocess==0.7.0 -pure_eval==0.2.3 -pydantic==2.8.2 -pydantic_core==2.20.1 -Pygments==2.18.0 -python-dateutil==2.9.0.post0 -PyYAML==6.0.2 -pyzmq==26.1.1 -requests==2.32.3 -scikit-learn==1.5.1 -scipy==1.14.1 -sentry-sdk==2.13.0 -setproctitle==1.3.3 -setuptools==73.0.1 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.1 -stack-data==0.6.3 -threadpoolctl==3.5.0 -tornado==6.4.1 -tqdm==4.66.5 -traitlets==5.14.3 -typing_extensions==4.12.2 -urllib3==2.2.2 -wandb==0.17.7 -wcwidth==0.2.13 +annotated-types +anyio +appnope +asttokens +certifi +charset-normalizer +click +comm +debugpy +decorator +distro +docker-pycreds +executing +gitdb +GitPython +idna +ipykernel +ipynbname +ipython +jedi +jiter +joblib +jupyter_client +jupyter_core +matplotlib-inline +nest-asyncio +numpy +parso +pexpect +platformdirs +prompt_toolkit +protobuf +psutil +ptyprocess +pure_eval +pydantic +pydantic_core +Pygments +python-dateutil +PyYAML +pyzmq +requests +scikit-learn +scipy +sentry-sdk +setproctitle +setuptools +six +smmap +sniffio +stack-data +threadpoolctl +tornado +tqdm +traitlets +typing_extensions +urllib3 +wandb +wcwidth +google.generativeai +scikit-learn +pandas +seaborn + From 2b8a6205504e15e97a50f764349b81b3ca142916 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Fri, 6 Sep 2024 00:27:19 -0700 Subject: [PATCH 14/17] modified plot_metrics throw exception None metricsor value --- logllm/log_llm.py | 4 ++-- logllm/plot.py | 29 +++++++++++++++++------------ logllm/query.py | 7 ++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/logllm/log_llm.py b/logllm/log_llm.py index 724757d..7c5ca77 100644 --- a/logllm/log_llm.py +++ b/logllm/log_llm.py @@ -91,9 +91,9 @@ def extract_experimental_conditions(provider, code): raise ValueError("Invalid provider specified. Use 'gemini' or 'openai'.") # Parse the result from JSON string to Python dictionary - parsed_json = json.loads(result) + result = json.loads(result) # Format the JSON output for better readability - return json.dumps(parsed_json, indent=4, ensure_ascii=False) + return json.dumps(result, indent=4, ensure_ascii=False) # Function to log the extracted information to Weights & Biases (W&B) def log_to_wandb(response_text): diff --git a/logllm/plot.py b/logllm/plot.py index 5b449ef..dcbbc4e 100644 --- a/logllm/plot.py +++ b/logllm/plot.py @@ -7,29 +7,34 @@ def plot_ml_metrics(response_data): response_data = json.loads(response_data) try: - # Extract all keys that start with "result_name_" and their corresponding "result_value_" + # Define keys to exclude from the plot + exclude_keys = {'cache_size', 'random_state_tts', 'random_state',} + + # Extract all keys and numeric values from the response, excluding specific keys metrics = [] values = [] for key, value in response_data.items(): - if key.startswith("result_name_"): - metric_name = value - metric_index = key.split("_")[-1] # Extract the index (e.g., "1" from "result_name_1") - metric_value = response_data.get(f"result_value_{metric_index}", None) - - if metric_value is not None: - metrics.append(metric_name) - values.append(metric_value) + # Check if the key is not in the exclude list and if the value is numeric + if key not in exclude_keys and isinstance(value, (int, float)): + metrics.append(key) + values.append(value) + + # Check if any numeric values were found + if not values: + print("No numeric values found to plot.") + return # Plotting plt.figure(figsize=(10, 6)) # Adjusted figure size for better visualization - plt.bar(metrics, values, color='skyblue') + plt.bar(metrics, values, color='pink') plt.title('Model Performance Metrics', fontsize=16) - plt.xlabel('Metric', fontsize=14) + plt.xlabel('Parameter', fontsize=14) plt.ylabel('Value', fontsize=14) plt.ylim(0, max(values) * 1.1) # Dynamically set the y-limit based on the maximum value + plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability plt.grid(True, axis='y', linestyle='--', alpha=0.7) plt.tight_layout() plt.show() - except TypeError as e: + except Exception as e: print(f"Error processing the response data: {e}") diff --git a/logllm/query.py b/logllm/query.py index 20ff520..254ac74 100644 --- a/logllm/query.py +++ b/logllm/query.py @@ -2,7 +2,7 @@ import os from dotenv import load_dotenv import openai -from logllm.extractor import extract_notebook_code +from logllm.log_llm import log_llm # Load environment variables load_dotenv() @@ -39,8 +39,9 @@ def query_openai(user_input: str): return response['choices'][0]['message']['content'] # Function to query Google Gemini -def query_gemini(user_input: str): +def query_gemini(user_input: str, code): model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config) + user_input = f"{code}" system_prompt = """ Please provide the data you want me to convert to a W&B API query: @@ -52,8 +53,8 @@ def query_gemini(user_input: str): chat_session = model.start_chat( history=[ - {"role": "user", "parts": [user_prompt]}, {"role": "model", "parts": [system_prompt]}, + {"role": "user", "parts": [user_prompt]}, ] ) From 2cc21474013b1d1d86da9719f5020aa137c82509 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Sat, 14 Sep 2024 06:14:04 -0700 Subject: [PATCH 15/17] commit changes --- demos/svc-sample.ipynb | 550 +++++------------------------------------ 1 file changed, 55 insertions(+), 495 deletions(-) diff --git a/demos/svc-sample.ipynb b/demos/svc-sample.ipynb index 968f8b4..0f40a15 100644 --- a/demos/svc-sample.ipynb +++ b/demos/svc-sample.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -127,251 +127,28 @@ " print(f\"\\nNote: Class {excluded_class} was intentionally excluded from the evaluation.\")" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Start logging with `logllm`" - ] - }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 4, "metadata": {}, "outputs": [ { - "data": { - "text/html": [ - "Finishing last run (ID:0k33o6dd) before initializing another..." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "97a074080cae47398d640efce9fbd7c8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Label(value='0.001 MB of 0.001 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View run still-water-35 at: https://wandb.ai/jakingsarchly-aj-technologies/svc-sample/runs/0k33o6dd
View project at: https://wandb.ai/jakingsarchly-aj-technologies/svc-sample
Synced 5 W&B file(s), 0 media file(s), 0 artifact file(s) and 0 other file(s)" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Find logs at: ./wandb/run-20240828_173350-0k33o6dd/logs" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Successfully finished last run (ID:0k33o6dd). Initializing new run:
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "309bc972e41a413198f404fa324e9660", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.0114827127111817, max=1.0))…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "wandb version 0.17.8 is available! To upgrade, please run:\n", - " $ pip install wandb --upgrade" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Tracking run with wandb version 0.17.7" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240828_173436-tzy0aus4" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Syncing run hearty-frost-36 to Weights & Biases (docs)
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View project at https://wandb.ai/jakingsarchly-aj-technologies/svc-sample" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View run at https://wandb.ai/jakingsarchly-aj-technologies/svc-sample/runs/tzy0aus4" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "Response from Google Generative AI processed and logged to W&B.\n", - "Dictionary: \n" + "Failed to detect the name of this notebook, you can set it manually with the WANDB_NOTEBOOK_NAME environment variable to enable code saving.\n", + "\u001b[34m\u001b[1mwandb\u001b[0m: Currently logged in as: \u001b[33mjakingsarchly\u001b[0m (\u001b[33mjakingsarchly-aj-technologies\u001b[0m). Use \u001b[1m`wandb login --relogin`\u001b[0m to force relogin\n" ] - } - ], - "source": [ - "from logllm.log_llm import log_llm\n", - "\n", - "notebook_path = \"svc-sample.ipynb\" # Here is target file to log\n", - "\n", - "log_llm(notebook_path,is_logging=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "Finishing last run (ID:cgiewcph) before initializing another..." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1948cf8b7b924ea18bcac164243eea12", + "model_id": "5645fa146bad499586e5d77c04729e08", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "VBox(children=(Label(value='0.001 MB of 0.001 MB uploaded\\r'), FloatProgress(value=1.0, max=1.0)))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - "

Run history:


param_value_1
param_value_10
param_value_11
param_value_12
param_value_13
param_value_15
param_value_16
param_value_18
param_value_2
param_value_3
param_value_4
param_value_5
param_value_7
param_value_9
result_value_1
result_value_2
result_value_3
result_value_4
result_value_5

Run summary:


adviceTry different kernel...
param_name_1test_size
param_name_10shrinking
param_name_11probability
param_name_12tol
param_name_13cache_size
param_name_14class_weight
param_name_15verbose
param_name_16max_iter
param_name_17decision_function_sh...
param_name_18break_ties
param_name_19random_state
param_name_2random_state
param_name_3shuffle
param_name_4stratify
param_name_5C
param_name_6kernel
param_name_7degree
param_name_8gamma
param_name_9coef0
param_value_10.2
param_value_10True
param_value_11False
param_value_120.001
param_value_13200
param_value_15False
param_value_16-1
param_value_17ovr
param_value_18False
param_value_242
param_value_3True
param_value_4True
param_value_51.0
param_value_6linear
param_value_73
param_value_8auto
param_value_90.0
result_name_1accuracy
result_name_2precision
result_name_3recall
result_name_4f1-score
result_name_5support
result_value_11.0
result_value_21.0
result_value_31.0
result_value_41.0
result_value_510

" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View run feasible-firefly-6 at: https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/cgiewcph
View project at: https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning
Synced 6 W&B file(s), 0 media file(s), 0 artifact file(s) and 0 other file(s)" - ], - "text/plain": [ - "" + "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.011181736244341461, max=1.0…" ] }, "metadata": {}, @@ -380,19 +157,8 @@ { "data": { "text/html": [ - "Find logs at: ./wandb/run-20240829_234314-cgiewcph/logs" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "The new W&B backend becomes opt-out in version 0.18.0; try it out with `wandb.require(\"core\")`! See https://wandb.me/wandb-core for more information." + "wandb version 0.18.0 is available! To upgrade, please run:\n", + " $ pip install wandb --upgrade" ], "text/plain": [ "" @@ -404,34 +170,7 @@ { "data": { "text/html": [ - "Successfully finished last run (ID:cgiewcph). Initializing new run:
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "85e6384590334d3cbe7d0a9af4c13821", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.011427467188877927, max=1.0…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "wandb version 0.17.8 is available! To upgrade, please run:\n", - " $ pip install wandb --upgrade" + "Tracking run with wandb version 0.17.7" ], "text/plain": [ "" @@ -443,7 +182,7 @@ { "data": { "text/html": [ - "Tracking run with wandb version 0.17.7" + "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240914_060949-s287yjqk" ], "text/plain": [ "" @@ -455,7 +194,7 @@ { "data": { "text/html": [ - "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240829_234514-7yf7z1q5" + "Syncing run proud-darkness-12 to Weights & Biases (docs)
" ], "text/plain": [ "" @@ -467,7 +206,7 @@ { "data": { "text/html": [ - "Syncing run lyric-sunset-7 to Weights & Biases (docs)
" + " View project at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning" ], "text/plain": [ "" @@ -479,7 +218,7 @@ { "data": { "text/html": [ - " View project at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning" + " View run at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/s287yjqk" ], "text/plain": [ "" @@ -490,241 +229,62 @@ }, { "data": { - "text/html": [ - " View run at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/7yf7z1q5" - ], + "image/png": "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2fS4uDgTFBRkJJnVq1enua/EoTsmJsb4+/sbPz8/ExkZaYy5tv06HA5z//33G2NMqqF7+/btzvHEr2eC8PBwU6JECWNZljl06JBz/HZCd5EiRcyVK1dSnCe19dzu89ytW7eb/r4AQG7COd0AkMO1a9dOcXFx+u677yRJP//8sy5evKgXX3xRrq6uqS63fPlyGWNUv3591axZM9n01q1bKzAwUOHh4Vq3bp1z/JdffpEkvfbaaymu9/XXX09xfN68eZKunXeaUl1FixZVUFCQrly5oi1btqRa9+3q2bOn6tevr/r166tChQqqUKGCtm3bprx582ratGlycXHR4cOHtXXrVvn7++s///lPiutJGE/p/GFJat++fbrqS+/rkMDX11dPPvnkTR+jZs2aKa77vvvukyQ1b95cxYoVSzLN4XCoevXqkpTiudaXL1/W119/rQ4dOqhp06Z6+OGHVb9+fQ0YMECSbnqBui5duiQbCwoKSvGxFi5cKEnq3LmzChYsmOo6EyxZskRRUVFq1qyZAgMDk013cXFRy5YtJaX+Wt6Kq6urXnjhBV28eFGLFy+WdP32fbe6gNr8+fMlSW3atHFeVyAxb29vPfroozLGaM2aNemqr3Xr1sqTJ89tLXO7z3OJEiUkXevnZtd+AIDcIPVPWwCAHOHFF19Uv379NGPGDPXu3dt5IauEqyynZt++fZKkypUrpzjdxcVFFStW1LFjx7Rv3z49/vjjSZarVKlSisulNv73339LkiZMmKBZs2bdtKbjx4/ftPbbsXPnTuf/e3h4qEyZMnr00UfVt29flStXLkltkZGRql+/forriYyMvGltqfV9K+l9HRKUL19eDofjpo+R0OeNChcunKbpV65cSTIeHBysli1b6sSJE6k+5vnz51McL1SoUIq3TfP390/xsXbv3i1JeuCBB1J9rMQSXsuNGzem+lqeOnVK0p1tZ23bttXnn3+uGTNm6JlnntGMGTPkcDj04osvpqm++fPna/369SnOc/jw4TuqLz3b4u0+z506ddLIkSM1bdo0LV26VI8//rgefvhhNW7cWGXLlr3txweA7IzQDQA5XJEiRfToo4/ql19+0erVq7V06VJVrFhRtWvXvulyCeEmIeykJCAgQNK1vZo3LpcQyFJb5kZhYWGSkobg1CTcYisjrFixItUrNSdIqO3SpUsp7k1OLLXabnfPYoL0vg6387je3t4pjidcQf1W002iq3THxcWpTZs2OnHihFq0aKH+/furSpUq8vPzk8Ph0P79+1W+fHnFxMSkuM7U6nVxSfngvIQrefv5+aU4/UYJr+XRo0d19OjRm857J9tZUFCQKlasqCVLlmj16tXavn27Hn/88VS3/xvr279/v/bv329LfenZFm/3eS5WrJg2bNigd999V4sXL9Y333yjb775RtK14P7JJ5+oXr16t10HAGRHHF4OALlAwiGt7dq1U3R0dJruEZw3b15J0unTp1OdJ2GPYOLDYBOWO3PmTIrLpLa+hOUSDqe+2b+EW2zdLQm1PfTQQ7es7dChQ7Y89u2+Dpnlzz//1P79+1WqVCnNmzdPDRo0UMGCBZ17228VdG9XQs8XL15M0/wJz+egQYNu+Vqmdku0tGrbtm2S37fb+b37+uuvb1lfwm2+7obbfZ6la3vUf/zxR128eFErVqzQ0KFDVbFiRW3cuFFNmzbN8N8VAMiqCN0AkAs8/fTTyps3r44cOSLLsvTyyy/fcpl7771XkvTPP/+kOD0+Pl579uxJMm/i/0+YdqOEw1RvlHD4dFr2dN9tCbXt3r1b8fHxd/Wx0/s6ZJaEIFWrVi15eHgkm36zc7nTo0qVKpKuHS6eFndzO2vbtq0sy9KRI0eUN29ePfXUU7dcJr313Xhf94x2u89zYh4eHmrUqJGGDBminTt36qGHHtKVK1ec15kAgJyO0A0AuYC3t7f69OmjJk2aqFu3bipVqtQtl2natKksy9LatWsVHBycbPq8efN07Ngx5cmTRw899FCS5SRp4sSJKa53woQJKY4/88wzkqQvv/zSeX50VlG+fHlVrVpV58+f1/Tp0+/qY6f3dcgsXl5ekq7vfU8sJiZGY8aMydDHSwiyU6ZMSfU88cSeeOIJubu7a8mSJfr3338ztJYblSpVSt26dVOTJk3Ut2/fVA/TT+zpp5+WJM2cOVPnzp1L82MlPO8ZeepFYrf7PKfG4XA4L4p3s3P+ASAnIXQDQC4xdOhQ/fbbb6mG3hvdc889ziDcvn37JFeN3rp1q3r16iVJeuONN5Ic1ty9e3flyZNHmzZt0rvvvuu8cnFMTIz69eunXbt2pfh4Tz/9tB544AHt2bNHrVq1SnY+a1RUlBYvXqzOnTunvekM9NFHH8myLPXo0UOTJk1KdkXmgwcPavjw4c6rsGeU9L4OmeWBBx6Qq6ur1q1bl+QLirCwML388ssphvE78dRTT6l27do6ffq0WrRoob179yaZvn379iTbfLFixfTmm28qJiZGzZo108qVK5PMb4zRn3/+qddeey3Fq7LfrgkTJui3337TkCFD0jR/7dq11aZNG507d06PPfZYsi9a4uLitHLlSr388suKiopyjpcpU0bStSMiUju1407c7vM8aNAgTZ48Odnh6Dt37tT3338vSbr//vszvE4AyJJsvSEZAOCuu/E+3beS2n26jbl2T+Nq1aoZScbhcJgaNWqYypUrO+d/9NFHTURERLLlZs6c6by3dKFChUxQUJApUKCAcXFxMR9++GGK9yc25tq9jGvWrOlc/z333GPq1q1rKleubNzd3Y0kExAQkGSZjL5P982MHTvWOBwOI8nky5fP1KpVy9SuXdsEBAQ41zdhwoQUH+dmbtVDel6HtNy3+VaPO2TIECPJDBkyJMXpCfd9njp1apLxvn37OmsrWbKkqVWrlvHy8jJubm5mwoQJKb7+CffpTmm7SJDac3n48GFToUIF5/R7773X1KpVyxQsWDDF5yAmJsa0bdvWOX+RIkVMnTp1TI0aNUy+fPmc47t37061ltRqS+ne3ylJ7T7dxhhz+fJl89hjjyV5DuvWrWuqVatmvLy8nOM3vuaPPPKIc9usW7euadiwoXn++eed01N7vRK72XZzO8/zk08+aSQZFxcXc88995g6deqYe+65x7ls48aNTUxMTJqeKwDI7tjTDQBIVeHChbVhwwa9//77qlSpkvbt26fDhw8rKChIX3zxhZYsWSJPT89ky7388sv6448/1LhxY0VGRmrPnj2qVq2ali5dqueffz7VxytatKg2bNig8ePHq0GDBjp37pyCg4N1+fJl1alTR8OGDdOKFSvsbPmmevTooW3btqlr164qXLiwdu3apX///VeFChXSiy++qB9++CHd9+O+mfS+Dpnl448/1pgxY1SxYkWdPHlShw8f1qOPPqo1a9Yku6VZRihZsqS2bNmiESNG6P7779eJEye0e/duFShQQB06dND//ve/JPO7urpqxowZWrx4sfOw6eDgYIWGhuree+/VG2+8oZUrV2baOfJ58+bVsmXL9O2336pZs2a6evWqtm7dqrNnz6p69erq37+//vzzz2Sv+axZ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5W65aHP4haQ95cmvaBOvHVevP18Oy1JQngIKi4vRnsjL13tycaiGt5/OxkbpYNT1a334OtxUyctHJ2IidCz6+vNb2M1D5TzyKiQ6XGdirn/ZGujulTt7SrQ9ZYttLyf+PtETPdETPdFTjulp//79Sosse053z549tWDBAq1evVplypS56bwNGjRQzZo19dlnnznH5s+frzZt2ujq1atyc3NLMn9Ke7pLlCihc+fOOY/Fz63f1NATPdETPSUbXxucO/cK58Se6te8XmN22PZy4u8TPdETPdETPeWYni5cuKACBQrc8pzuLBe6jTHq2bOn5s+fr5UrV6p8+fK3XKZ///766aef9M8//zjHXnvtNW3bto0LqQHAneJCajkHF1IDACDDZNsLqfXo0UMzZ87UrFmzlC9fPp08eVInT55McsjBwIED1b59e+fP3bt31+HDh9W7d2/t3r1bU6ZM0eTJk9W3b9/MaAEAAAAAAElZMHRPmDBBYWFhatSokYoWLer8N2fOHOc8oaGhOnLkiPPnMmXKaMmSJVq5cqXuu+8+/e9//9Pnn3+u1q1bZ0YLAAAAAABIyoKHl2cGDi8HgJvg8PKcg8PLAQDIMNn28HIAAAAAAHIKQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2IXQDAAAAAGATQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2IXQDAAAAAGATQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2cb3TFfzzzz/as2ePwsPD1a5du4yoCQAAAACAHCHde7r/+usv3XfffapWrZqee+45dezY0Tlt9erV8vb21qJFizKiRgAAAAAAsqV0he5du3bpkUceUUhIiN566y01b948yfSHH35YhQoV0g8//JAhRQIAAAAAkB2lK3QPGTJEkrRlyxaNGjVKQUFBSaZblqV69erpr7/+uvMKAQAAAADIptIVuletWqXWrVvrnnvuSXWekiVLKjQ0NN2FAQAAAACQ3aUrdF++fFn+/v43nScyMlJxcXHpKgoAAAAAgJwgXaG7RIkS2rlz503n2bJli8qVK5euogAAAAAAyAnSFbpbtmypX3/9VX/88UeK07///ntt3LhRTz311J3UBgAAAABA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HnnkEbm7u0uSBg8erHHjxmnLli2qWrWqevXqpYMHD6pq1apycXFRo0aN9Ndff+nChQtyc3NT4cKFZVmWYmNjed/K5vgUiwxhjFF8fLx8fX21bds251iCkJAQjRs3TiEhIZKuBfJly5Zp7969Kl26dCZUjOwk8Te7hqsG51rGGOeXL3/99Zckaf/+/Spfvry2bNmiLl266MMPP9Rrr72muLg4TZkyRUuXLk22zfChN3dyc3PThAkTFBcXpzFjxqh79+569dVX5eLiorZt2+rKlSv63//+p1mzZmnr1q3q37+/9u3bp6ZNm2Z26chk69atc94p48MPP9SyZcskSbVq1dJLL72kxo0ba8KECerWrZsk6fLly1qwYIF27dqVZD387cldPv30U7377rvOC75eunRJrq6u2rp1q6pWraqoqCgZYxQaGirp2vYRHx+vixcvqnjx4vL393fuqCJwZ3+W4RMs7kB0dLTc3Nycoej3339X8+bN1bdvXw0dOlQuLi66evWqXnjhBTkcDi1cuFAuLi4yxmjz5s3Kly+fKlasmMldAMjqEl8puF+/fho9erSioqI0fvx4563jpk+frhdffFHStQ+9zzzzjB566CENHTo0EytHVhITE6PHH39c58+fV+HChdWuXTu1a9dOkrR48WJ9//33+v77751fBs+aNYtTWXK5AwcOqHXr1rrnnntUtGhRTZgwQdu2bVPVqlUVHBys3r176/jx4/rrr7+UL18+nT17Vh06dNDFixe1du1agnYul7CHeseOHapevbpzPCYmRm5ubmrSpImaNGmid955R/Hx8WrZsqXq1aund999NxOrhh0I3Ui3MWPGaNOmTTp27Jg6dOigZs2aqUSJEpoxY4a6dOmi2rVrOw8DvXLlirZs2SI3N7ckH54B4Hbs3btXn3/+udq0aaOGDRsqJCREAwYM0Lp167RgwQJVr15dJ06c0GuvvaazZ89qw4YN7CFAElFRUbpw4YK6du2qq1evqlOnTs7gLV27HaEk5cuXTwULFsykKpHZNmzYoHr16ik2Nlbz5s3TG2+8ofDwcP3xxx+qW7eu8wiaH3/8UWPGjNGuXbt0zz33SLp2Wt26devk5ubGIeW5VMLrHh8fr19//VUtWrTQlClT9Pzzz8vLy8s537PPPquCBQvqyy+/VIsWLbRr1y7t37+f26HmQIRupMvAgQM1adIk9evXT4cPH9aGDRtUvXp1DR06VKVLl9bu3bs1e/ZsXb16VUWLFlWvXr3k6urKOSkA0u2HH35Qv379lC9fPi1btkzFixeXJK1cuVITJkzQvHnzVLp0aeXJk0d58uTRypUr+dCLVB08eFC9evVSZGSk2rdvr/bt22vgwIG6ePGiJkyYkNnlIRN9/PHHWrRokVauXClXV1f9/vvv6tixo3x8fFStWjVNmjRJefPmlXTttJczZ85owYIFioiIUJEiRfTss8/K4XDwmSeXSmnn0muvvaaZM2dq3LhxatOmjTw9PZ3jFy5cUFxcnLZv365du3Y5L/bJtpOzELpx27777ju99957mj17tmrVqqXff/9dzZo1U4UKFVS9enUNHz5cZcuWTfZBlw++AG5HwgcXY4wsy9KcOXM0efJkrVu3Tn/99ZcqV67snDc8PFwbNmzQqVOnFBAQoMaNG/OhF7cUEhKiPn366N9//5WXl5f27t2rX3/9VXXr1s3s0pCJjh07pqJFi8rhcCgkJERlypTRsWPHtGrVKn322WcqWbKkvvnmG+XJkyfVdfCZJ3dKHLjnz58vd3d3PfHEE5KkXr166euvv9aXX36p1q1bK0+ePBo9erT69eunGjVq6M8//yRw52Ac44vbEhUVpfz58+vFF19UrVq1tHDhQrVp00bjxo1T9+7dtWTJEr333nvat29fsjcb3nwA3I6EDy7r16+XJD3//PN66623VK1aNb388svat2+fpGt7mry9vfXoo4/q5Zdf1qOPPiqHw8FVynFLZcqU0RdffKG33npLLVu21J9//knghgIDA+VwOLR48WKVK1dOP/30kwIDA/XMM8+oe/fuOnr0qDp37qyIiAhJ1/ZWLlmyRNL1i33ymSf3SXyxz/79++vtt9/W0aNHdeLECUnS559/rs6dO6tbt26aN2+eJKlJkybq3Lmz/vrrLwJ3DseebqTZ//3f/ykwMFBPPfWUYmJi5OLiopYtW+qZZ55Rv379FBERoRo1aigqKkodOnTQ+++/n9klA8iGEu8p2LZtm+6//3599tln6tmzpyTpp59+0tixYxUeHq6pU6eqfPny7FUCkOH+/fdfffTRR1qwYIGmTp2qVq1aKTIyUrNmzdLEiRMVHh6uYsWK6Z9//tHhw4cJS5AkffTRR/rkk080f/585y0IE+vRo4emTZumUaNG6bXXXnOOE7hzNl5ZpMkPP/ygUaNGacWKFfL19ZVlWdq1a5eOHz+uOnXqSJKOHz+uWrVq6fHHH09yURoASKvEewrGjx+vPXv2yNPTU2+++aZiYmLUu3dvtWrVSsYYjR8/Xl26dNHEiROTHGoOABmhfPnyGjRokBwOh9q1a6cZM2aoVatWevnll1WiRAktXbpU0dHRWrp0qVxdXfnyL5czxigsLEy//vqr3n//fT344IM6fPiwdu3apW+//VZ+fn4aN26cxo0bp4sXL2rOnDnq3r278w5ABO6cjT3duKUff/xRoaGhMsaoV69ezr1Q//zzjzp06KAGDRqoVatWGjlypDw8PDR37lxZlsVVygGk2+DBg/XVV1/ps88+09WrV7Vy5UotWLBAgwYN0oABAyRJP//8s4YOHaratWtr4sSJmVwxgJzq4MGD+uijjzRnzhxn8E641kQC9lJCunak1pNPPilPT0+1adNGM2bM0MWLF1WoUCGtW7dOjRo10pw5c5zzJr5uCXI2/jrgpi5cuKBXXnlFYWFheuuttyRdP8+ycuXKatmypebNm6c5c+aoTJky+uOPP2RZVpK9VQBwO06dOqVffvlFI0eOdN53u1mzZipbtqzef/99557vli1bys/PL8XD9wAgo5QtW1b9+/eXZVnq1KmTJk6cqGeffTbJPARuSNc+Izdr1kyLFi1Shw4d1Lt3bzVv3lwPPfSQ3nvvPR08eNB5RETCbXX5vJw7sKcbqYqMjJSnp6f+/fdftWnTRvHx8VqwYIHKlCmT5Fu5Q4cOKTw8XJUqVZKLiwvf9gK4I2fPnlWlSpU0YMAA9enTxzl+5MgRPf/889q0aZNGjx7t/CJQSvkWLQCQkUJCQjRgwABdvHhRv/zyS2aXgywm8WfjCxcu6NKlSypVqpRz+iOPPKIqVaroiy++yKwSkYkI3UjRJ598osjISL366qsqVKiQ/v33XzVt2lSlS5fW7NmzFRAQkOLhMJzPBOB2pBSW4+Pj1aVLF125ckUffPCBypcv75zWo0cP7du3T3v37tVHH33k3BMOALcj8WeYmJgYubm5pWm5EydOqEiRIhwWjBTduE2Eh4fr77//1pAhQxQaGqqtW7eyYyqXYrcAUnT8+HF98MEH+vbbb3Xu3DmVL19ev/76qw4ePKiXXnpJp0+fTvGNhsANIK0SB+69e/dq48aNOnfunFxcXPTCCy9o+/btmjRpkvPWYJcvX1ZoaKjatGmjevXqafHixYqKihLfHQO4XQmfYT799FMtXbpUktL0t6RYsWLOv1sE7twnLi7uptNv3Cb++OMPjR07Vh4eHtqyZYvzgnvIfdjTjVQNHTpUn332md577z21b99eBQsW1L///qvHH39cefLk0apVq5Q/f/7MLhNANpPwtpPw4WTQoEGaP3++Lly4oMDAQAUFBenTTz/Vt99+qzFjxsjd3V2BgYE6duyYYmNjtW3bNvXr10+rV6/W+vXr+bIPQLpVqlRJL730kt59992b7rlOPG3t2rUqXLiwKlSocDdLRSaLiIiQl5eXpGtfFJcrV+6We62NMdq+fbuqV6/OKZi5HHu64bR7925FRkY6fx46dKh69uypIUOG6JtvvnHu8f75559Vvnx5+fj4ZGK1ALKrxB9qR48erUmTJmns2LEKDQ1VxYoVNWfOHAUHB6tz58764osv1LZtW3l4eKhp06batGmTJOn06dOqXLkyewwApFl8fHyyscqVK+vMmTOSUt9znThwjxs3Tm3atFFERIR9hSLL+f3335331O7Zs6fatm2b5DNzShK2m/vuu895dARfEudefNUCGWO0ePFi/ec//9GsWbP09NNPy8PDQ5L0/vvvKzo6WoMHD5abm5vatGmjSpUqae7cuZI4hxtA2g0ePFgBAQHq2bOnLMvS1atXtWrVKg0dOlSPPPKIli5dqoULF2rUqFF64IEHFBMTo3r16qlhw4Z68803JUnHjh3T+PHjtWjRIq1du1bu7u6Z2xSAbCMh+AQHB8vf31/FixfXQw89pCVLlig6Olru7u7O014SPt8kPg3myy+/1ODBg/Xll1/qvvvuy8ROcDcZYxQcHKw9e/bo/vvv1+HDh7Vp0yblzZs3zetYvHix7r333iTXKEHuwp5uyLIstWzZUm3btlX37t21YMECRUVFOae/8cYbcnd313//+1+tWrUqybIEbgBpcfHiRa1bt04//vijpk6dKkny9vbW2bNnVb9+ff36669q06aNRo4cqVdffVXR0dGaPn26Nm7c6Dwc/cqVKxoxYoR++uknrVixQlWqVMnMlgBkQzNnztTjjz+uChUqKCgoSBMmTNChQ4e0ePFibdy4UVevXpV07b7bkpIE7rfffluTJk1SmzZtMq1+3F0Je6v7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", "text/plain": [ - "" + "
" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "response: {\n", - " \"param_name_1\": {\n", - " \"condition_as_natural_language\": \"Support Vector Machine model with linear kernel\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": 10,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": 1.0\n", - " },\n", - " \"param_name_2\": {\n", - " \"condition_as_natural_language\": \"Test size is 20%\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": 0.2,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_3\": {\n", - " \"condition_as_natural_language\": \"Random state is 42\",\n", - " \"condition_as_int\": 42,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_4\": {\n", - " \"condition_as_natural_language\": \"Shuffle is True\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": true,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_5\": {\n", - " \"condition_as_natural_language\": \"Stratify is True\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": true,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_6\": {\n", - " \"condition_as_natural_language\": \"C is 1.0\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": 1.0,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_7\": {\n", - " \"condition_as_natural_language\": \"Kernel is linear\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_8\": {\n", - " \"condition_as_natural_language\": \"Degree is 3\",\n", - " \"condition_as_int\": 3,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_9\": {\n", - " \"condition_as_natural_language\": \"Gamma is auto\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_10\": {\n", - " \"condition_as_natural_language\": \"Coef0 is 0.0\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": 0.0,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_11\": {\n", - " \"condition_as_natural_language\": \"Shrinking is True\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": true,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_12\": {\n", - " \"condition_as_natural_language\": \"Probability is False\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": false,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_13\": {\n", - " \"condition_as_natural_language\": \"Tol is 1e-3\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": 0.001,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_14\": {\n", - " \"condition_as_natural_language\": \"Cache size is 200\",\n", - " \"condition_as_int\": 200,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_15\": {\n", - " \"condition_as_natural_language\": \"Class weight is None\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_16\": {\n", - " \"condition_as_natural_language\": \"Verbose is False\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": false,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_17\": {\n", - " \"condition_as_natural_language\": \"Max iter is -1\",\n", - " \"condition_as_int\": -1,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_18\": {\n", - " \"condition_as_natural_language\": \"Decision function shape is ovr\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_19\": {\n", - " \"condition_as_natural_language\": \"Break ties is False\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": false,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_20\": {\n", - " \"condition_as_natural_language\": \"Random state is None\",\n", - " \"condition_as_int\": null,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"param_name_21\": {\n", - " \"condition_as_natural_language\": \"Excluded class is 1\",\n", - " \"condition_as_int\": 1,\n", - " \"condition_as_bool\": null,\n", - " \"condition_as_float\": null,\n", - " \"result_as_int\": null,\n", - " \"result_as_bool\": null,\n", - " \"result_as_float\": null\n", - " },\n", - " \"advice\": \"Try different kernels, like 'rbf' or 'poly', and adjust the hyperparameters (C, gamma) to see if you can improve the accuracy.\"\n", - "}\n", - "Response from the provider processed and logged to W&B.\n", - "It seems like you're trying to find the best model based on a set of parameters and their corresponding results. However, the provided data is not in a format that can be directly used for a W&B API query. \n", - "\n", - "To help you create a W&B API query, I need more information:\n", - "\n", - "1. **What is the metric you are using to evaluate the \"best\" model?** Is it accuracy, precision, recall, F1-score, or something else?\n", - "2. **What is the name of the experiment or project in Weights & Biases where you have logged these results?**\n", - "3. **What is the specific W&B API endpoint you want to use?** For example, are you looking to retrieve the best model based on a specific metric, or are you trying to filter runs based on certain parameter values?\n", - "\n", - "Once you provide this information, I can help you construct a W&B API query to find the best model based on your criteria. \n", - "\n" - ] } ], "source": [ "from logllm.log_llm import log_llm\n", - "from logllm.query import query\n", - "\n", - "notebook_path = \"svc-sample.ipynb\" \n", + "from logllm.plot import plot_ml_metrics\n", "# code_string = extract_notebook_code(notebook_path)\n", + "notebook_path = \"svc-sample.ipynb\" \n", "\n", "# Extract experimental conditions and results using log_llm\n", "code_string = log_llm(notebook_path, project_name=\"Machine learning\", is_logging=True, provider=\"gemini\")\n", "\n", - "# Use the parsed_json as user_input for the query\n", - "response = query(f\"\"\"Whats the best model?. {code_string}\"\"\", provider=\"gemini\")\n", + "# Plot the response from the query\n", + "plot_ml_metrics(code_string)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Expected condition with GPT4 from the script\n", + "\n", + "```Python\n", + "{\n", + " \"method\": \"SVC\",\n", + " \"dataset\": \"Iris\",\n", + " \"task\": \"classification\",\n", + " \"accuracy\": 1.0,\n", + " \"C\": 1.0,\n", + " \"degree\": 3,\n", + " \"tol\": 0.001,\n", + " \"cache_size\": 200,\n", + " \"max_iter\": -1,\n", + " \"test_size\": 0.2,\n", + " \"random_state\": 42,\n", + " \"kernel\": \"linear\",\n", + " \"condition_as_natural_langauge\": [\n", + " \"Using linear kernel on SVC model.\",\n", + " \"Excluding class 2 from Iris dataset.\",\n", + " \"Splitting data into 80% training and 20% testing.\"\n", + " ],\n", + " \"advice_to_improve_acc\": [\n", + " \"Consider using cross-validation for better performance evaluation.\",\n", + " \"Experiment with different kernels to optimize results.\",\n", + " \"Increase the dataset size to improve generalization.\"\n", + " ]\n", + "}\n", "\n", - "# Print the response from the query\n", - "print(response)" + "```" ] } ], From 679c9cae4a6dcfdf7ed781e87ebcb979fe8b9b98 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:10:51 -0700 Subject: [PATCH 16/17] plot multiple metrics --- logllm/plotter.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 logllm/plotter.py diff --git a/logllm/plotter.py b/logllm/plotter.py new file mode 100644 index 0000000..799d24e --- /dev/null +++ b/logllm/plotter.py @@ -0,0 +1,85 @@ +import json +import numpy as np +import matplotlib.pyplot as plt + +def plot_metrics(*models_results): + # Process each model to ensure it's in dictionary format + processed_models = [] + for model in models_results: + # Convert to dictionary if the input is a JSON string + if isinstance(model, str): + model = json.loads(model) # Convert string to dictionary + processed_models.append(model) + + # Define keys to exclude from the plot + exclude_keys = {'cache_size', 'random_state_tts', 'random_state', 'random_state_1', 'n_estimators'} + + # Initialize containers for metrics, values, and model names + metrics = [] + model_names = [] + model_values = {} + + for model in processed_models: + model_name = model.get("model_name", "Test Model") + model_names.append(model_name) + + for key, value in model.items(): + if key.startswith("result_name_"): + metric_name = value + metric_index = key.split("_")[-1] # Extract the index (e.g., "1" from "result_name_1") + metric_value = model.get(f"result_value_{metric_index}", None) + + if metric_value is not None: + if metric_name not in metrics: + metrics.append(metric_name) + if metric_name not in model_values: + model_values[metric_name] = [] + + # Add the metric value to the list + model_values[metric_name].append(metric_value) + + # Handle additional numeric values in the model (not using the result_name format) + for key, value in model.items(): + # Exclude specific keys and ensure the value is numeric + if key not in exclude_keys and isinstance(value, (int, float)): + if key not in metrics: + metrics.append(key) + if key not in model_values: + model_values[key] = [] + model_values[key].append(value) + + # Handle cases where no valid metrics were provided + if not metrics or not model_names: + print("No valid metrics or model names found.") + return + + # Ensure all models have values for all metrics, filling in with 0 if not available + for metric in metrics: + for i in range(len(model_names)): + if len(model_values[metric]) <= i: + model_values[metric].append(0) # Default value if missing + + # Plotting side-by-side bar chart + x = np.arange(len(metrics)) # Label locations + bar_width = 0.15 # Width of the bars + fig, ax = plt.subplots(figsize=(10, 6)) + + # Create a bar for each model's performance metrics + for i, model_name in enumerate(model_names): + values = [model_values[metric][i] for metric in metrics] + ax.bar(x + i * bar_width, values, width=bar_width, label=model_name) + + # Customization of the plot + ax.set_xlabel('Metric', fontsize=14) + ax.set_ylabel('Value', fontsize=14) + ax.set_title('Comparison of Model Performance Metrics', fontsize=16) + ax.set_xticks(x + bar_width * (len(model_names) - 1) / 2) + ax.set_xticklabels(metrics, fontsize=12) + ax.legend(title='Models') + ax.grid(True, axis='y', linestyle='--', alpha=0.7) + + plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability + plt.tight_layout() + plt.show() + + From 20e57b0e257bcbd3dc158511dac6f523be332da2 Mon Sep 17 00:00:00 2001 From: Archly2022 <97497497+Archly2022@users.noreply.github.com> Date: Wed, 25 Sep 2024 06:11:01 -0700 Subject: [PATCH 17/17] updated plotter to plot metrics --- demos/svc-sample.ipynb | 111 +++++++--------------------------------- logllm/plot.py | 113 ++++++++++++++++++++++++++++------------- logllm/plotter.py | 85 ------------------------------- logllm/query.py | 6 +-- 4 files changed, 99 insertions(+), 216 deletions(-) delete mode 100644 logllm/plotter.py diff --git a/demos/svc-sample.ipynb b/demos/svc-sample.ipynb index 0f40a15..16dd421 100644 --- a/demos/svc-sample.ipynb +++ b/demos/svc-sample.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -74,7 +74,7 @@ " shrinking=True,\n", " probability=False, \n", " tol=1e-3, \n", - " cache_size=200, \n", + " cache_size=100, \n", " class_weight=None,\n", " verbose=False, \n", " max_iter=-1, \n", @@ -129,99 +129,14 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Failed to detect the name of this notebook, you can set it manually with the WANDB_NOTEBOOK_NAME environment variable to enable code saving.\n", - "\u001b[34m\u001b[1mwandb\u001b[0m: Currently logged in as: \u001b[33mjakingsarchly\u001b[0m (\u001b[33mjakingsarchly-aj-technologies\u001b[0m). Use \u001b[1m`wandb login --relogin`\u001b[0m to force relogin\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5645fa146bad499586e5d77c04729e08", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Label(value='Waiting for wandb.init()...\\r'), FloatProgress(value=0.011181736244341461, max=1.0…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "wandb version 0.18.0 is available! To upgrade, please run:\n", - " $ pip install wandb --upgrade" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Tracking run with wandb version 0.17.7" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { - "text/html": [ - "Run data is saved locally in /Users/jake/vscode/logllm/demos/wandb/run-20240914_060949-s287yjqk" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAADeYklEQVR4nOzdd3RVdfb38c/JTQIJpNBCSwIEhNBbEJGqgIggVRQHEEQZR1QEbDgqRUV0bDj6gI5IEVFRFB3FBo6ADQWlV+kgKE1CCSQkdz9/8LvHXJJQIpcU3q+1WCTf0/Y+LWef6piZCQAAAAAAnHdBeR0AAAAAAACFFUU3AAAAAAABQtENAAAAAECAUHQDAAAAABAgFN0AAAAAAAQIRTcAAAAAAAFC0Q0AAAAAQIBQdAMAAAAAECAU3QAAAAAABAhFNwAUUlu3bpXjOKpcuXJeh5IvLF++XJ07d1bJkiUVFBQkx3E0f/78vA7rLzvfy3nq1KlyHEcDBgw4L+PLK/v379egQYNUsWJFeTweOY6j0aNH53VYuMjMnz9fjuOoTZs2eR0KgDxE0Q0g3/j222/197//XYmJiYqKilKRIkVUsWJFde7cWZMmTdLRo0fzOkQUUHv27NEVV1yhOXPmKDw8XM2aNVPz5s0VFRV1xmErV64sx3HkOI7uueee0/b7wgsvuP06jnO+wi8QMuft+1esWDElJibqrrvu0vbt2y9oPF27dnX3G0lJSWrevLni4+MvaAzIvczr0YsvvnjafocNG+b2e75OPm3dulWjR4/W1KlTz8v4AFzcgvM6AABISUnRzTffrHfeeUeSVLRoUVWtWlVhYWH69ddfNWfOHM2ZM0cjR47U559/rrp16+ZxxAVDSEiIatSooYoVK+Z1KHnu7bff1h9//KGuXbvq/fffV1BQ7s45v/nmm/rXv/4lj8eTbfc33njjr4RZKNSpU8c9mbFnzx5t3LhR69ev1/Tp0zV37lw1adIk4DGsWLFC3377rSpWrKjVq1ef1ckV5F/Tp0/XXXfdlW23jIwMvf322+d9mlu3btWYMWPUunXrv3TXR3h4uGrUqMEJH+Aix5VuAHnqxIkTuuqqq/TOO++oXLlymjZtmg4cOKBVq1Zp8eLF2rVrl1avXq3bbrtNe/fu1aZNm/I65AKjYsWKWrdunb788su8DiXPrVu3TpLUoUOHXBfcNWrU0G+//aZ58+Zl2339+vVasmSJatSokes4C4MXX3xR33zzjb755htt2LBB69evV4MGDZScnKz+/fvL6/UGPAbf8j7buxmQf9WoUUOLFy/W+vXrs+0+d+5c/fbbb/l2u7v00ku1bt06vf7663kdCoA8RNENIE+NGTNG3377rcqWLavvv/9eN910k8LCwvz6qVWrll5++WV99dVXiomJyaNIUZAdO3ZMkrKsW+eib9++knK+mj19+nRJUr9+/XI9jcKoatWqmjx5siRp7dq1Wr58ecCneT6WN/KHM213vna2OwD5GUU3gDyTnJysf//735Kk8ePHn/FZvBYtWujyyy/P0j5nzhxdffXVKl26tIoUKaIqVapo8ODB2rFjR7bj8T2ju3XrVi1YsEDt2rVTdHS0SpYsqe7du+uXX35x+/3vf/+rli1bKjIyUiVKlNCNN96oXbt2ZRln5pflnDhxQmPGjFH16tVVtGhRVaxYUXfccYcOHDiQbTyLFi3S/fffr6SkJMXExKhIkSKKi4tTv379tHr16myHGT16tPtiqL179+rOO+9U5cqVFRIS4t4KeboXbG3btk233XabEhISVKRIEUVERCghIUHdu3fP8VbN7777Tj169FDZsmUVGhqq2NhY3XTTTVq7dm22/bdp08Z9Wdm6devUq1cvlS5dWmFhYWrcuLH7OMG5MjO98cYbat26taKjoxUWFqbExEQ98MADWeaxbz75nsu8+eab3Wc/z/XFRq1bt1ZcXJxmz56d5f0CZqYZM2YoLCxMPXr0OO14jh49qscff1z16tVTsWLFFBkZqaZNm+r//b//p/T09ByH862rkZGRioqK0hVXXKG5c+eeMe6UlBQ99dRTSkpKUmRkpMLDw9WgQQM9/fTTSk1NPbvk/6KGDRsqIiJCkvy2L0n68ccf1bt3b1WsWFGhoaEqW7asevXqpaVLl2Y7rszPy7/33ntq1aqVoqOj3eWc+SVw06ZNy/EZ+3NdDpm38fT0dP3rX/9S3bp1FR4e7m5jmad/7NgxPfjgg0pISFBYWJhq1Kjh92zy/v37dffdd6tSpUoqWrSoateunePzw7/99ptefPFFdejQQZUrV1bRokVVokQJtW7d2j3Zc6pTt/833nhDSUlJCg8PV8mSJdWrVy9t3rw522Glk+vNM888o8suu0zR0dEKDw/XJZdcon79+mnBggVZ+jczvf3222rfvr1KlSqlIkWKKCEhQUOGDNFvv/2W43TOpGfPngoLC9Mbb7whM/PrdvToUX3wwQeKj49Xq1atTjue9PR0vfzyy2rRooWio6NVtGhRJSYm6uGHH9ahQ4f8+m3Tpo2uuOIKSSe3u8zrUOb96YABA9z1bsuWLRowYIAqVqyo4OBg96V9Z3qR2rnM5/379+vee+9VYmKiihYtqmLFiqly5cq6+uqrNWHChLOYmwDyjAFAHpkxY4ZJsjJlytiJEydyNY4RI0aYJJNksbGx1rhxYwsPDzdJVqJECVu8eHGWYSpVqmSS7LnnnjOPx2MxMTHWqFEjK1asmEmy8uXL2+7du+25555zx1u/fn0rUqSISbIaNWrYsWPH/Mb51VdfmSRr1aqVderUySTZJZdcYg0aNLDg4GCTZNWqVbPff/89SzxVq1Y1SVaqVCmrU6eO1a9f36KiokyShYWF2VdffZVlmFGjRpkkGzx4sMXHx5vH47F69epZvXr1bODAgWZmtmXLFpNklSpV8ht2y5YtVrp0aZNk4eHhVrduXWvQoIGVLFnSJFn9+vWzTG/ChAnmOI5JspiYGEtKSrLo6GiTZEWLFrWPP/44yzCtW7c2SfbMM89Y8eLFLSIiwho3bmxlypRxl9n06dNPs3Sz8nq99re//c0dPiEhwRo1amShoaFurps2bXL7f+2116x58+YWExPjLpPmzZtb8+bN7c477zyrafrWl6+//tpd306Ne+HChSbJbrzxRtuxY4cb36n27NljdevWNUkWFBRk9erVs5o1a7r9t2/fPsu6ZWb21ltvWVBQkLueJCUlWcmSJS0oKMiefPLJbJezmdnOnTutVq1aJsmCg4OtWrVqVrNmTXedbNGihaWkpPgNM2XKFJNk/fv3P6v54+PLIbv11cysePHiJslmzpzptj333HPuelWyZElr2LChlSpVyiRZSEiIvffeezlOx5d32bJlrUmTJlamTBn7+eefrXnz5nbJJZe466pveTdv3twdR26WQ3bbeNWqVa1x48ZWu3Ztv3l34403WrNmzdztsnLlyu64x4wZY7///rtdcsklFhoaag0bNrQKFSq43SdPnpwl58cee8zdH1StWtWSkpIsPj7eHeYf//hHlmEyb/++9bZSpUp++7Ly5cvb3r17swy7bds2v/lxySWXWKNGjdx9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iUVHR7vfCv/444+zDOP7Tvep3232yc23s71er/3tb39zY61WrZo1atTI/T53fHx8tt9BP5/f6T6TnL7TbXbym8Z169Y1SebxeKx+/fpWq1Ytt/927drZsWPHsgz3xhtvuPO/dOnS1qRJEytZsqQFBQXZk08+me1yNjv5LeOGDRv6za+mTZtarVq13HlWtmxZv2HO93e6T+ell14yj8djkiwiIsIaN25sSUlJVrZsWXd8EydOzHY6p3OmHHKzHM7mu81nmu6Zttuc1tN7773XjS0+Pt4aN25sYWFhFhISYhMnTsx2+ee0/WeW07zctm2bux/y7csaN25spUqVynYenDhxwvr27ev2X65cObv00kutfv36FhER4bavXbs2x1hyii27b39nJ6fvdJud/BvTvn17v3nYtGlTq1u3roWFhbntpy7zK6+80l03mzZtaq1bt7YbbrjB7X42+5XTrTfnMp+7du1qkiwoKMiqVatml156qVWrVs0d9oorrrATJ06c1bwCcOFxpRtAnitevLhmzZqlhQsX6pZbblFcXJy2bt2q5cuXy8zUqVMnvfbaa9qwYYPq1KnjN+y4ceP00UcfqX379jpy5IhWrFih0qVL6x//+IeWL1/u3nZ3oTiOo9mzZ2v06NHyer1as2aNypQpo9tvv10//PCDypUr59d/ZGSkvvnmG910002KjIzU+vXrlZaWpuHDh+v7778PyJW2559/Xnfffbfq1aunffv2admyZZJO3pL93//+N9vbfW+//XZ9/fXX6tatm7xer5YtW6bw8HD17dtXP//8szp16nTe48yO4zh644039Prrr6tly5bas2ePVq9erUqVKum+++7Tzz//nK8/n1OmTBl9//33evTRR1WzZk1t2LBB27ZtU5MmTfTiiy/qk08+yfbuhj59+uh///ufrrjiCh0/flzr1q1T3bp19emnn+qGG27IcXrly5fX999/rwkTJqhVq1bav3+/li5dqsOHD+vSSy/VmDFj9NVXXwUy5dO64447tGzZMt16660qU6aMVq9erV9++UWlS5fWjTfeqHfffTfX3+M+ndwuh7zyr3/9S+PHj1diYqJ+++03bdu2Te3atdPXX3+d5ZNm50N8fLx++uknjRs3To0aNdKuXbu0du1alSxZUv3799djjz3m139wcLCmT5+uOXPmuLdNL126VLt371b16tV15513av78+Xn2jHzx4sX12WefacaMGerQoYNSUlL0888/a9++fapXr54eeOAB/fjjj1mW+ZtvvqkBAwYoMjJSP/30kxYsWJCrZ7Bzci7z+eGHH9aIESPUpEkTHTlyRMuWLdOxY8fUunVrvf766/riiy8UHMxHiYD8yjE7y2+1AAByNH/+fF1xxRVq3bp1ltsrAQAAcPHiSjcAAAAAAAFC0Q0AAAAAQIBQdAMAAAAAECAU3QAAAAAABAgvUgMAAAAAIEC40g0AAAAAQIBc9B/083q92rVrlyIiIuQ4Tl6HAwAAAAAoAMxMhw8fVoUKFRQUlPP17Iu+6N61a5fi4uLyOgwAAAAAQAG0Y8cOxcbG5tj9oi+6IyIiJJ2cUZGRkXkcDQAAAACgIDh06JDi4uLcmjInF33R7bulPDIykqIbAAAAAHBOzvSYMi9SAwAAAAAgQCi6AQAAAAAIEIpuAAAAAAAC5KJ/pvtseL1epaWl5XUYCJCQkBB5PJ68DgMAAABAIUTRfQZpaWnasmWLvF5vXoeCAIqOjla5cuX4VjsAAACA84qi+zTMTLt375bH41FcXNxpP3iOgsnMlJKSoj179kiSypcvn8cRAQAAAChMKLpPIz09XSkpKapQoYLCw8PzOhwESFhYmCRpz549iomJ4VZzAAAAAOcNl25PIyMjQ5IUGhqax5Eg0HwnVU6cOJHHkQAAAAAoTCi6zwLP+RZ+LGMAAAAAgUDRDQAAAABAgFB0I1vz58+X4zg6ePDgWQ9TuXJljR8/PmAxAQAAAEBBU6CL7tGjR8txHL9/5cqVy+uwLogBAwbIcRz94x//yNJt8ODBchxHAwYMuPCBAQAAAABcBbrolqTatWtr9+7d7r+VK1fmdUgXTFxcnN5++20dO3bMbTt+/LjeeustxcfH52FkAAAAAACpEBTdwcHBKleunPuvTJkyeR3SBdOoUSPFx8fr/fffd9vef/99xcXFqWHDhm5bamqqhgwZopiYGBUtWlQtWrTQ4sWL/cb1ySefqHr16goLC9MVV1yhrVu3Zpned999p1atWiksLExxcXEaMmSIjh49mmN8o0ePVnx8vIoUKaIKFSpoyJAhfz1pAAAAAChACnzR/csvv6hChQqqUqWKevfurc2bN+d1SBfUzTffrClTpri/T548WQMHDvTr5/7779d7772nadOm6eeff1a1atXUoUMHHThwQJK0Y8cO9ejRQ9dcc42WLVumW2+9VSNGjPAbx8qVK9WhQwf16NFDK1as0MyZM/XNN9/ozjvvzDauWbNm6fnnn9crr7yiX375RR988IHq1q17nrMHAAAAgPwtOK8D+CuaNm2q119/XdWrV9fvv/+uxx9/XJdffrlWr16tUqVKZTtMamqqUlNT3d8PHTokSUpPT1d6erokKSgoSEFBQfJ6vTIz95908tNSvp8zO9f2c3G6cfTt21cPPvigtmzZIsdx9O233+rtt9/W/PnzJUlHjhzRxIkTNWXKFHXs2FFmpv/85z+aO3euJk2apPvuu08TJ05UQkKCnnvuOTmOo+rVq2vFihX617/+5eb+9NNP68Ybb9Tdd98tx3FUrVo1vfDCC2rTpo0mTJigokWLSpLb/7Zt21SuXDm1bdtWISEhiouLU5MmTc77fDyfy8PM/NYDj8cj6c/vtfvk1B4cHCwz82t3HEcej0der1der/eM7ZnXvezaMzIy/OLPqd3j8chxHDeXM8VOTuRETuRETuRETuRETuRETueW06lx5qRAF90dO3Z0f65bt66aNWumqlWratq0aRo+fHi2w4wbN05jxozJ0r506VIVK1ZMklSmTBlVrVpVO3fuVFpamlJSUpSRkaHQ0FCFhobq+PHjfguwSJEiCgkJ0bFjx/wWSNGiRRUcHKyUlBS/lSksLExBQUFZbs0uVqyYvF6v3zPajuOoWLFiysjI0PHjx9123wKOjo5Whw4dNGnSJJmZrr76apUuXVper1cnTpzQqlWrdOLECSUlJUk6edIhPT1djRo10sqVK3XixAmtXbtWSUlJSklJccd/6aWXSpKOHTumkJAQLV68WJs3b9abb77p9mNm8nq9Wr16tXs7e1pamo4ePapOnTpp/Pjxqlq1qjp06KArr7xS11xzjYKDg3PMKSgoSOHh4UpPT/c7MeLxeBQWFqYTJ04oLS3NbQ8ODlbRokXdnHxys5x8sa9atcptr1evnkJDQ7VkyRK/5ZSUlKS0tDStWLHCL8YmTZooOTlZ69at81vW9evX1759+/zuwoiKilLNmjW1a9cu7dy50233rXtbtmzR3r173fbY2FjFxsZqw4YNSk5OdtsTEhIUExOjVatW+a03iYmJio6O1tKlS/3mATmREzmREzmREzmREzmR01/JqeO0zWpc2qtGpf6sb9YnO1r4W5BalfOqRpSpbc2YApVTbpfTrl27dDYc+6uXYfOZ9u3bq1q1apo4cWK23bO70h0XF6f9+/crMjJS0p9nL1JSUrR161ZVqVLFLczyy5Xum2++WQcPHtTs2bM1Z84c3XXXXZKkl156SZ06dVK3bt0UHR2toUOHqmHDhtq6dasqVarkjqd79+4qWbKkXnvtNXXv3l0lSpTQ5MmT3fF/+OGH6t69uw4cOKDo6GjVqlVL7dq105AhQ7LEEx8fr9DQUFWpUkV33323hg4dKulkwT537lzNmzdPs2bNUpUqVTR//nyFhITkuyvdqamp2rx5s+Lj491lnV/PqBXGs4TkRE7kRE7kRE7kRE7kVDByqvrQZwpyTB7nz3F4TcowRx7HFORIax+9ukDllNvllJycrFKlSik5OdmtJbNToK90nyo1NVVr165Vy5Ytc+ynSJEiKlKkSJb24OBgBQf7z46goCC/z5H5ZP45s3NtPxenG3fHjh3dK8BXX321X/dLLrlEoaGh+vbbb1WpUiU5jqMTJ05oyZIlGjp0qBzHUa1atfTBBx/4TeOHH35wx+84jho1aqQ1a9bokksuOWOcvvGEh4era9eu6tq1q+68804lJiZq1apVatSo0Rlzyqv27NaDU38/XbtvHKfybZx/td23Yznb9nOJPad2ciIniZxyivFc28mJnCRyyinGc20nJ3KSyCmnGM+1/Vxz8pojbzbXFTPMUYZlnUZByCk3yymneLLEd1Z95VP33nuvrr32WsXHx2vPnj16/PHHdejQIfXv3z+vQ7ugPB6P1q5d6/6cWbFixXT77bfrvvvuU8mSJRUfH69//etfSklJ0S233CJJ+sc//qFnn31Ww4cP12233aaffvpJU6dO9RvPAw88oMsuu0x33HGHBg0apGLFimnt2rWaO3euXnzxxSwxTZ06VRkZGWratKnCw8M1ffp0hYWFqVKlSoGZCQAAAACQDxXot5fv3LlTN954o2rUqKEePXooNDRUixYtuigLu8jIyBxvaXjyySfVs2dP9evXT40aNdLGjRv1+eefq0SJEpJO3h7+3nvv6aOPPlL9+vX18ssv64knnvAbR7169bRgwQL98ssvatmypRo2bKhHHnlE5cuXz3aa0dHRevXVV9W8eXPVq1dPX375pT766KMcX3AHAAAAAIVRoXum+1wd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MtdFdyCZme666y7Nnj1b8+fPP+eCGwAAAACAQDqronv0GT4RllfuuOMOvfnmm/rwww8VERGh3377TdLJ+/LDwsLyODoAAAAAwMUuKK8D+CsmTpyo5ORktWnTRuXLl3f/zZw5M69DAwAAAACgYL+9/CweRwcAAAAAIM/kuug+fPiwXnrpJc2bN0+7du3yeyO4j+M42rRp018KEAAAAACAgipXRffevXt1+eWXa9OmTYqMjHTf2paWluZ+Z61ChQoKCQk5r8ECAAAAAFCQ5OqZ7tGjR2vTpk16/fXX9ccff0iShg0bpqNHj+qHH37QpZdeqsqVK2v16tXnNVgAAAAAAAqSXBXdn3zyidq2bau+fftm+ZRYkyZN9Omnn2rr1q359q3nAAAAAABcCLkqunfv3q2GDRu6v3s8Hve2ckkqUaKEOnbsqHffffevRwgAAAAAQAGVq6I7KipKJ06ccH8vUaKEdu7c6ddPZGSkfv/9978WHQAAAAAABViuiu6EhARt3brV/b1hw4aaO3euDhw4IEk6duyYPvroI8XHx5+XIAEAAAAAKIjOuuhOT093f77qqqv05ZdfKiUlRZJ02223ac+ePapfv7569eqlOnXqaNOmTRowYMB5DxgAAAAAgILirIvuChUq6N5779WaNWv0j3/8Q6+++qpbdPfo0UNPP/20jhw5ovfee0+//fabhg8frvvuuy9ggQMAAAAAkN+dddGdnJys5557TnXr1lXPnj11+PBhFS1a1O1+zz33aN++fdq9e7eOHDmip59+Wh6PJyBBAwAAAABQEJx10b179249//zzqlu3rhYtWqTbbrtN5cuX1y233KJvvvlG0sm3mJctWzbLZ8QAAAAAALgYnXXRXbJkSd19991atmyZlixZottvv12hoaGaMmWKWrdurcTERD399NO8sRwAAAAAgP+Tq7eXN2rUSC+99JJ2796tN998U23bttXGjRs1YsQIxcXFqXv37vr444/l9XrPd7wAAAAAABQYuSq6fUJDQ9W7d2998cUX2rp1q0aPHq24uDh9+OGH6tq1q+Li4s5XnAAAAAAAFDh/qejOLDY2Vo888og++eQTNW/eXGam33777XyNHgAAAACAAif4fIzk6NGjeueddzR58mR99913MjOFh4fruuuuOx+jBwAAAACgQPpLRffXX3+tyZMna9asWUpJSZGZ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j6LNvezWOd/dU4888oiNHDnSqlWrZtWqVbOXX37ZZs6caY7j2KOPPpoH0f41L7/8ssXHx1uNGjVs4cKF9tZbb9mDDz7o7mv2799v9957r5UuXdr69OnjDldQa5NAoejO50aNGmXXX3+9BQUFWeXKle3GG2+0JUuW2O7du61ly5bWsWPHAl2EJicnW5s2bcxxHJswYYLbfuqV023btlnXrl1t6NChBeKPTk4ee+wxK1WqlGVkZNh7771njuPYE088YWYnd+DvvvuuJSUlFZgzoZn/6PTs2dPi4uLs+uuvt8GDB1uFChUsIiLC7rzzTrefL7/80q666irzeDw2a9asvAg5V053QPf2229bcHCwXXXVVX63dBaUg0CfU+PNyMiwzp07W1JSktvWsWNHi4uLc9fPuXPnWu/evS01NfWCxpobGRkZNmDAAGvatKl7ELt792778ccfrWrVqlanTh2/u4p882Pv3r1Wrlw5GzNmTJ7EfT516dLFEhMT3d8z/+145ZVXzHEcCw4Otscee8zMCsY67MshIyPDHnzwQXMcx8qXL29dunSx+fPn2++//25mZtdee61fUVOQZF4Ovp+ffvppK1WqlJmdPHldokQJu+GGG9z3Snz++efWpUsX++677y58wOdRjx49LDEx0Q4fPmwffPCBNWjQwMqUKePe7VemTBl3Ged3KSkp1qVLF/t//+//uW2+45m2bdvalVdeaWZmGzZsyLI8J0+ebH/729/yfa7Hjx+3AQMGWKtWrczsZM7//Oc/rX///la9enWLjo62OnXq2LRp02zTpk22Z88e83g89sILL+Rx5Ocm8za5Zs0a++2338zs5JXtwYMHW0hIiDVs2NBuvfVWt/DctWuXVa9e3W/553eZ85w2bZpVqlTJqlWrZtWrV3cfu/Idr2cuvG+66aZsx3Gxo+jOh1JSUmzWrFl+t1L9+OOPNmLECKtataqVKlXK6tWrZzVq1LD69eu7V6EK6oq9YsUKi4iIsIoVK9rLL7+cpfvevXtt0KBBFhsba7/88kseRHjucjq79/rrr1twcLB1797dgoOD7V//+pfbbfXq1daqVSsbMGBAgVuWTz/9tJUvX97mz5/v3ur4yy+/WNeuXa148eJ+V+/nzp1rXbt2dV8EmN9lXhbbt2+3X375xX788Ue/fqZNm2Yej8c6duzo162gLMfMce7Zs8f9IzpixAiLj4+39evXW+fOnS02Nta9InHo0CEbO3asXXXVVQXmWeBOnTpZy5YtzcysQ4cOdsstt1hycrJNnz7dYmJirG7durZ27Vq/k35btmyxxMREmzx5cl6Ffc5y2v/MmDHDHMexu+66K0u3F154wYYNG2ajR4+2kJAQW7FiRaDDzLX9+/e7V3jNzA4ePGhPP/20rVu3znbv3m3Dhg2zJk2amMfjsWbNmtnkyZNt4sSJ5jiOffDBB3kY+bnLvC5mvkK4fPly83g81q9fPytdurRfgbZ3714bMGCAXXnllfm+SDuVb93NyMiw9PR0mzBhgkVFRVloaKhVqVLF2rdvb3v27DGv12szZsywokWL5ut11Sc9Pd32799vZcuWtTp16tiUKVP8uo8bN84iIyPtlVdesVKlSlmvXr0sOTnZzMx+/fVX69evn11//fVuW3527bXXWo0aNWzDhg0WFxdnQ4YMsaNHj1p6erpNnDjRevbsaUWKFLGYmBi79dZb7ZJLLrHExMQCc4dN5r+Xb731ltWoUcOGDRvmbp9HjhyxTZs2+f1dPHbsmL3++usWFxdX4F7qmPnk7JtvvmnVq1e3kJAQe+mll8zsz23V7OS++f7777eIiAjr2rVrXoSbr1F05zOHDh2y5s2bW926dW3SpEnm9XrdDdx3u9WLL75oAwYMMMdxzHGcQnEF5vPPP7eIiAgLDg62QYMG2eLFi23z5s02adIk69Wrl5UoUaLA3H7k20GlpaXZ1q1bbenSpX5/TK6//npzHMc6dOjgnh1duHChNW3a1JKSkvyu3ORXp96J0LNnT2vfvr0bsy+HzZs3W2JiojVp0sTvJUan3t6aX2X+4/rGG29YgwYNLCoqyooVK2atW7e2Tz75xL29avr06RYcHGydO3e2H374Ia9CPmen5li7dm23oHn33XfNcRwrV66cxcXFuc8Cp6am2pQpU6xcuXIFohj1er2WkpJi9913n0VERFhiYqKVL1/evWJ/7NgxmzZtmlWuXNni4+PthRdesDVr1tjSpUtt0KBBVqFChQJzYsG37aWmptqyZcts/fr1bjG2bds269GjhxUrVsy9A+Xw4cO2Zs0au+yyy+yf//ynff/991a0aFF766238iyH00lPT7eZM2da1apV7b///a+lpqZahQoV7LLLLrM//vjD7e/o0aP29ttv2/XXX2+hoaFWtmxZcxzHrrnmGjt06FCBOCGWeT9777332o033ugWmIcOHbJ//OMf7luufVdM165da/3797dSpUoVmDcnZ14Whw8fttTUVHdZHj582D788EP797//7XfCJD093R5//HFr0qSJ7dix40KHfE6Sk5OtYcOGtnLlSlu7dq3Vrl3bEhMT/Qrvr776yipVqmRBQUF+7wj59ddf7eabb7aKFSv6nWjKz+bPn28REREWHR1tTZs2tV27dmXZ3ubPn29PPvmkValSxYoVK2ahoaHu88L5+dgns6lTp1pYWJiNGTPG/ve//+XY39q1a23ixIkWHh5eYB4f3LRpk99Jvvfee88++eQTMzt58ahcuXIWGRnpLjOzP/dX+/bts8GDB9t//vOfCxt0AUDRnY8cOXLEatWqZW3btrXvvvsuy4szTt0Rff/993bNNddYo0aNCuQLjU61dOlSu/TSS91PnziOY7GxsXb11Vfb6tWr8zq8s5L5s2Dt2rWzSy65xBzHsSpVqtjw4cPN7OTtV71797aQkBCrWrWqVa9e3WrVqmVt2rRxD5yye6FcXsvIyMiyTs6fP98OHjxoTZs2tSuuuMLvD6vv4H/KlCnmOI6tWrWqwPwxPdWbb75pISEh9uCDD9rkyZPt3XfftRo1alhMTIy9//77bl5vvPGGOY5jLVq0KBBXmDIvr1dffdXd7jLf6vfoo4+a4zjWsWNH++abb+z777+3xx57zIoVK+Y+GnHquPKrw4cPW0xMjIWGhlrv3r39uqWmptp3331n11xzjQUHB5vjOJaQkGCVK1cuMCf8fOvhoUOHrG3btla+fHkrU6aMdejQwX2xz6pVq6xnz54WFBRk1apVs/r161tcXJzVr1/fzE6eAIyJicnyluj8ZPHixda+fXu3mO7QoYP7ortT18O0tDTbsWOHjRgxwq688kqLjIz0+7xNfpV5X9mzZ0+rXr26PfLII34nf5YvX279+vUzx3Hs8ssvt5YtW1rz5s2tcuXKBfIRpVmzZlmnTp2sWrVqVqtWLXvuueeyfVns77//blOnTrXIyEj3alt+dfToUatTp461atXKfRnl+vXr3cI780nL1157zWJiYiw+Pt4ee+wxu/fee61Tp05WpkyZfL08V61a5Xdh4ddff7WSJUuax+Oxdu3a2a5du9xupx4DHDhwwN58802rW7eutW/f/oLF/FctXLjQypUrZ88995zfSws3btxoO3fudE8affnll3bttddaQkKCPfPMM25/+flYaNeuXda3b18bMGCAmf15bJD5JbjTp0+3SpUqWfXq1f2u3PuO+3x3PJoVjGODC4WiOx/55z//afXr1/crMLPbMDOvwL4XMyxZsuSCxBho+/fvt+XLl9uMGTNsxowZtnHjxgL3WaIjR45YzZo1rVWrVvbaa6/Z+++/b4MHDzbHcezvf/+729+MGTPsqaeeskcffdQ++ugjt9DOr8/ov/POOzZgwAD39rYrr7zSGjRoYMeOHbO///3vVqxYMVu+fLmZ+a+3zzzzjMXExBTIZynNTt5S3rBhQ3v44Yf9bu1r06aNJSYm2rp16/z6f+211+zf//73hQ7znGXej0yaNMmCgoLs2WeftSpVqrjP9Po89dRTVq5cOStevLhFRUVZ06ZN/Q528/MBhI/X67WpU6da0aJFrXXr1hYZGWlDhgzJtt/58+fbzJkz7bPPPiswX4jwLc/jx49b48aNrWXLljZp0iS75557rEqVKlaxYkX3UaRt27bZzJkzrWfPntarVy8bOXKku//p0aNHlufb84PNmzf7LYuvvvrKHMcxj8fj9z4Qn1NfiHfixAlbv369lS9f3j0BWhAMHjzYqlSpYt999517cJ/5TqHDhw/bRx99ZDfddJPdfPPN9vLLLxeYuzIymzZtmoWGhtott9xid9xxh3s337XXXut3+/gXX3xht99+u5UtWzZfn/TzxfPCCy9YlSpV3JOw06dPt/T0dFuzZo3VqlXLatasaZMmTXKHmz17tt18881WqVIlu/TSS+3OO+/M149i7du3z0qUKOH30tT//Oc/1qVLFxs3bpwVL17cOnfu7Lftnrptmpk98MADVrFixQJxQszMbPz48Va7dm33ZN/hw4dt0KBBVrNmTStfvrzdfPPNduDAAVuyZImNHz/ePvvsM3fY/P738vDhw/b000+7FxA8Ho/9+9//9vukptnJK/2VK1e2atWq+V3pz2/bYn5C0Z2PtG/fPstbOs2y30H5/PDDD1a2bFm/Nycjb40cOdLq169va9ascZflSy+9ZI7j+D3DnZ38eIXb7GRc77//vhUvXtyaNWtmV111lVWuXNn9vvHy5cutUqVKVq9ePb+35f7+++92ww03WKtWrQrEs2jZWbt2rUVFRfnd2njqC8V++OEHO3ToUJZh8+sfn1MLbsdx7Nlnn3W/mPDggw+amf8JoF9++cV+/vlnW7ly5WmvXOQnp87/9PR0O3DggO3YscO6detmkZGRfs83Zz47X5BkLiwPHTpk1113nd+txe+//75Vr17dYmJicvwk2MqVK+1vf/ubRUdHuyfP8ott27ZZcHCwzZ49212mkyZNss6dO1urVq0sJCTkrL6IkJqaak2bNi0wnyjavHmz1axZ0+8k3pYtW+zmm2+2Dh062KBBgwrMXWCns2zZMqtSpYo99dRTfn8nKlWqZJdddplbiB07dsyGDh1qPXv2tNdff93tLz/vg/7zn/+Y4zj25ZdfWs+ePa1q1apuPqtXr8628DYz9wRLfj0m8Dlx4oR7J9Dx48fdW5LT09Pt4MGDNnHiRCtWrJh16tTJ7+/GqT744AOLjIwsMBeQhg8fbpGRkfbZZ5/Zyy+/bHXq1LHY2FgbNWqU9erVyxzHcW/HLqhXfbt3726O41jTpk39PpmZ+bhg2rRpVq1aNYuPj/c7sYDsUXTnE2lpaVajRg3r2bOn23bqc06vvvqq323kJ06csEGDBll4eHih+IZsQXXqH/xOnTpZ9+7d3d99nwXzPcvzxx9/FMiTJCdOnLA33njDPB6PhYWF+e1gjx07ZpMmTbIKFSpY+fLlbdiwYfbAAw9Yp06dLDIyskC86Mbn1E9gffnll+Y4jvvJvlML7q1bt1rr1q1txowZeRPwOfjqq6/8rpL5ntl+8cUX3bybN29uf/vb38ws+7cmZ5afDyAyH6ympKS4V5p8MW/dutW6du2apfDOr3eanOrUN8YfP37c6tWrZw0bNrS2bdtmeW/Chx9+aDVq1LCyZcvali1bzOzPXH/44QcbOHCgNWzYMN9uq3PmzDGzk38rDx8+bCdOnLDU1FT7/vvv7aqrrrKQkJAsz6H/8ccf7h02Xq/Xjh49aldddZV169bNUlNT8/X6a2a2ZMkScxzHpk+fbuvXr7dXXnnFIiIirG7dutaiRQtzHMeGDRtmx44dKzCf7stu+5o9e7ZVrFjR7+sPHTt2tPj4eLeg8xWqR44cyfcn/Q4ePGgdOnSwPXv22KpVq+zSSy+10NBQi4mJsa1bt5rX63WXV+bC+7XXXnPH4ZtP+X15+qSnp1vz5s2tadOmfreaHzhwwCZMmGDFixfPsfBOSUmx7t27W9WqVfPdHTY+vvXMtzy2bdtm1atXN8dxrGrVqtazZ0/3xPvWrVutRIkS9t///jfP4v2r9u7da127drVOnTpZSEiI9e/f330HkZn/39epU6daVFSUTZs2LS9CLVAouvMB38p7yy23WHR0tHtwkdm3335r9evX9yvWfv/9d3vggQfc7+XiwvMtuz/++MM2bNhgqamp1qpVK+vWrZuZnXyzZebvcJ84ccJeeOEFGzBgQIG83fqZZ56xsmXLWmRkpDVt2tRvJ5ySkmJffvmlde7c2UqXLm0JCQnWuXPnAvEynxUrVvi9/GzKlCk2ZMgQy8jIsC1btlhcXJz17dvX2rdvb3Fxce42l5qaahMmTLD69evb/Pnz8yr8s/LEE09YhQoV/E7QLV++3KZPn+534NquXTu75ppr/Ib9/PPP7ZtvvilQB4A+999/vzVr1szKlCljbdq0sbfeesvd9rZt2+Ze8R46dGhehXvOvvnmG7vuuuv8Xhz2yy+/WNu2ba1UqVLuG9rNzO8Tix9++KHVqlXLHMfJcnC7ZMkSv+05P8j88kXfi0QbNmxogwYN8rtd9bvvvnML71mzZllGRob9+uuv1rhxY79HJV544QX3/RL5TU4nuFq1amUej8fi4+MtJibGHnroIfdq8OWXX16g3hB811132dSpU7PsR0aPHm0RERHu76ee2Pzpp5+sXbt2tnLlSr/h8uP+yPdunswvD61Tp46FhYVZWFiYff7552Z2ch/lK6x9hXfdunX9btPO73xXcH3LYdq0aVayZEnr0qWL3yMOf/zxh02YMMEiIiKsS5cuWV58t3//fmvTpk2Wr4LktczrV1pamnm9Xr+r1gcPHrT//ve/fu/8SElJsRdffNGqV69eYN4Fkh2v12t79uyx33//3Z5++mkLCQmxm266ye+kSXp6uvueAt9LVnF6FN35yOeff25FihSxyy67zC2uU1NTbfny5da8eXNr165dlluNCsL3cQu7o0ePWsmSJa1fv3529OhR69u3r8XFxdkTTzxhQUFB9sQTT7g77xUrVliLFi3sgQceyOOoc+f333+3NWvW2KRJk6xUqVLum0lPtXbtWjt8+LDfQXN+dejQIRs4cKDVq1fPFixYYFOnTjXHcfwOfm677TZzHMdKlizpvmBq7969NnnyZIuIiHC/V5nf+a4kbdq0yT1wP/UMfv/+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", "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Syncing run proud-darkness-12 to Weights & Biases (docs)
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View project at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - " View run at https://wandb.ai/jakingsarchly-aj-technologies/Machine%20learning/runs/s287yjqk" - ], - "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -229,7 +144,7 @@ }, { "data": { - "image/png": "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2fS4uDgTFBRkJJnVq1enua/EoTsmJsb4+/sbPz8/ExkZaYy5tv06HA5z//33G2NMqqF7+/btzvHEr2eC8PBwU6JECWNZljl06JBz/HZCd5EiRcyVK1dSnCe19dzu89ytW7eb/r4AQG7COd0AkMO1a9dOcXFx+u677yRJP//8sy5evKgXX3xRrq6uqS63fPlyGWNUv3591axZM9n01q1bKzAwUOHh4Vq3bp1z/JdffpEkvfbaaymu9/XXX09xfN68eZKunXeaUl1FixZVUFCQrly5oi1btqRa9+3q2bOn6tevr/r166tChQqqUKGCtm3bprx582ratGlycXHR4cOHtXXrVvn7++s///lPiutJGE/p/GFJat++fbrqS+/rkMDX11dPPvnkTR+jZs2aKa77vvvukyQ1b95cxYoVSzLN4XCoevXqkpTiudaXL1/W119/rQ4dOqhp06Z6+OGHVb9+fQ0YMECSbnqBui5duiQbCwoKSvGxFi5cKEnq3LmzChYsmOo6EyxZskRRUVFq1qyZAgMDk013cXFRy5YtJaX+Wt6Kq6urXnjhBV28eFGLFy+WdP32fbe6gNr8+fMlSW3atHFeVyAxb29vPfroozLGaM2aNemqr3Xr1sqTJ89tLXO7z3OJEiUkXevnZtd+AIDcIPVPWwCAHOHFF19Uv379NGPGDPXu3dt5IauEqyynZt++fZKkypUrpzjdxcVFFStW1LFjx7Rv3z49/vjjSZarVKlSisulNv73339LkiZMmKBZs2bdtKbjx4/ftPbbsXPnTuf/e3h4qEyZMnr00UfVt29flStXLkltkZGRql+/forriYyMvGltqfV9K+l9HRKUL19eDofjpo+R0OeNChcunKbpV65cSTIeHBysli1b6sSJE6k+5vnz51McL1SoUIq3TfP390/xsXbv3i1JeuCBB1J9rMQSXsuNGzem+lqeOnVK0p1tZ23bttXnn3+uGTNm6JlnntGMGTPkcDj04osvpqm++fPna/369SnOc/jw4TuqLz3b4u0+z506ddLIkSM1bdo0LV26VI8//rgefvhhNW7cWGXLlr3txweA7IzQDQA5XJEiRfToo4/ql19+0erVq7V06VJVrFhRtWvXvulyCeEmIeykJCAgQNK1vZo3LpcQyFJb5kZhYWGSkobg1CTcYisjrFixItUrNSdIqO3SpUsp7k1OLLXabnfPYoL0vg6387je3t4pjidcQf1W002iq3THxcWpTZs2OnHihFq0aKH+/furSpUq8vPzk8Ph0P79+1W+fHnFxMSkuM7U6nVxSfngvIQrefv5+aU4/UYJr+XRo0d19OjRm857J9tZUFCQKlasqCVLlmj16tXavn27Hn/88VS3/xvr279/v/bv329LfenZFm/3eS5WrJg2bNigd999V4sXL9Y333yjb775RtK14P7JJ5+oXr16t10HAGRHHF4OALlAwiGt7dq1U3R0dJruEZw3b15J0unTp1OdJ2GPYOLDYBOWO3PmTIrLpLa+hOUSDqe+2b+EW2zdLQm1PfTQQ7es7dChQ7Y89u2+Dpnlzz//1P79+1WqVCnNmzdPDRo0UMGCBZ17228VdG9XQs8XL15M0/wJz+egQYNu+Vqmdku0tGrbtm2S37fb+b37+uuvb1lfwm2+7obbfZ6la3vUf/zxR128eFErVqzQ0KFDVbFiRW3cuFFNmzbN8N8VAMiqCN0AkAs8/fTTyps3r44cOSLLsvTyyy/fcpl7771XkvTPP/+kOD0+Pl579uxJMm/i/0+YdqOEw1RvlHD4dFr2dN9tCbXt3r1b8fHxd/Wx0/s6ZJaEIFWrVi15eHgkm36zc7nTo0qVKpKuHS6eFndzO2vbtq0sy9KRI0eUN29ePfXUU7dcJr313Xhf94x2u89zYh4eHmrUqJGGDBminTt36qGHHtKVK1ec15kAgJyO0A0AuYC3t7f69OmjJk2aqFu3bipVqtQtl2natKksy9LatWsVHBycbPq8efN07Ngx5cmTRw899FCS5SRp4sSJKa53woQJKY4/88wzkqQvv/zSeX50VlG+fHlVrVpV58+f1/Tp0+/qY6f3dcgsXl5ekq7vfU8sJiZGY8aMydDHSwiyU6ZMSfU88cSeeOIJubu7a8mSJfr3338ztJYblSpVSt26dVOTJk3Ut2/fVA/TT+zpp5+WJM2cOVPnzp1L82MlPO8ZeepFYrf7PKfG4XA4L4p3s3P+ASAnIXQDQC4xdOhQ/fbbb6mG3hvdc889ziDcvn37JFeN3rp1q3r16iVJeuONN5Ic1ty9e3flyZNHmzZt0rvvvuu8cnFMTIz69eunXbt2pfh4Tz/9tB544AHt2bNHrVq1SnY+a1RUlBYvXqzOnTunvekM9NFHH8myLPXo0UOTJk1KdkXmgwcPavjw4c6rsGeU9L4OmeWBBx6Qq6ur1q1bl+QLirCwML388ssphvE78dRTT6l27do6ffq0WrRoob179yaZvn379iTbfLFixfTmm28qJiZGzZo108qVK5PMb4zRn3/+qddeey3Fq7LfrgkTJui3337TkCFD0jR/7dq11aZNG507d06PPfZYsi9a4uLitHLlSr388suKiopyjpcpU0bStSMiUju1407c7vM8aNAgTZ48Odnh6Dt37tT3338vSbr//vszvE4AyJJsvSEZAOCuu/E+3beS2n26jbl2T+Nq1aoZScbhcJgaNWqYypUrO+d/9NFHTURERLLlZs6c6by3dKFChUxQUJApUKCAcXFxMR9++GGK9yc25tq9jGvWrOlc/z333GPq1q1rKleubNzd3Y0kExAQkGSZjL5P982MHTvWOBwOI8nky5fP1KpVy9SuXdsEBAQ41zdhwoQUH+dmbtVDel6HtNy3+VaPO2TIECPJDBkyJMXpCfd9njp1apLxvn37OmsrWbKkqVWrlvHy8jJubm5mwoQJKb7+CffpTmm7SJDac3n48GFToUIF5/R7773X1KpVyxQsWDDF5yAmJsa0bdvWOX+RIkVMnTp1TI0aNUy+fPmc47t37061ltRqS+ne3ylJ7T7dxhhz+fJl89hjjyV5DuvWrWuqVatmvLy8nOM3vuaPPPKIc9usW7euadiwoXn++eed01N7vRK72XZzO8/zk08+aSQZFxcXc88995g6deqYe+65x7ls48aNTUxMTJqeKwDI7tjTDQBIVeHChbVhwwa9//77qlSpkvbt26fDhw8rKChIX3zxhZYsWSJPT89ky7388sv6448/1LhxY0VGRmrPnj2qVq2ali5dqueffz7VxytatKg2bNig8ePHq0GDBjp37pyCg4N1+fJl1alTR8OGDdOKFSvsbPmmevTooW3btqlr164qXLiwdu3apX///VeFChXSiy++qB9++CHd9+O+mfS+Dpnl448/1pgxY1SxYkWdPHlShw8f1qOPPqo1a9Yku6VZRihZsqS2bNmiESNG6P7779eJEye0e/duFShQQB06dND//ve/JPO7urpqxowZWrx4sfOw6eDgYIWGhuree+/VG2+8oZUrV2baOfJ58+bVsmXL9O2336pZs2a6evWqtm7dqrNnz6p69erq37+//vzzz2Sv+axZ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5W65aHP4haQ95cmvaBOvHVevP18Oy1JQngIKi4vRnsjL13tycaiGt5/OxkbpYNT1a334OtxUyctHJ2IidCz6+vNb2M1D5TzyKiQ6XGdirn/ZGujulTt7SrQ9ZYttLyf+PtETPdETPdFTjulp//79Sosse053z549tWDBAq1evVplypS56bwNGjRQzZo19dlnnznH5s+frzZt2ujq1atyc3NLMn9Ke7pLlCihc+fOOY/Fz63f1NATPdETPSUbXxucO/cK58Se6te8XmN22PZy4u8TPdETPdETPeWYni5cuKACBQrc8pzuLBe6jTHq2bOn5s+fr5UrV6p8+fK3XKZ///766aef9M8//zjHXnvtNW3bto0LqQHAneJCajkHF1IDACDDZNsLqfXo0UMzZ87UrFmzlC9fPp08eVInT55McsjBwIED1b59e+fP3bt31+HDh9W7d2/t3r1bU6ZM0eTJk9W3b9/MaAEAAAAAAElZMHRPmDBBYWFhatSokYoWLer8N2fOHOc8oaGhOnLkiPPnMmXKaMmSJVq5cqXuu+8+/e9//9Pnn3+u1q1bZ0YLAAAAAABIyoKHl2cGDi8HgJvg8PKcg8PLAQDIMNn28HIAAAAAAHIKQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2IXQDAAAAAGATQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2IXQDAAAAAGATQjcAAAAAADYhdAMAAAAAYBNCNwAAAAAANiF0AwAAAABgE0I3AAAAAAA2cb3TFfzzzz/as2ePwsPD1a5du4yoCQAAAACAHCHde7r/+usv3XfffapWrZqee+45dezY0Tlt9erV8vb21qJFizKiRgAAAAAAsqV0he5du3bpkUceUUhIiN566y01b948yfSHH35YhQoV0g8//JAhRQIAAAAAkB2lK3QPGTJEkrRlyxaNGjVKQUFBSaZblqV69erpr7/+uvMKAQAAAADIptIVuletWqXWrVvrnnvuSXWekiVLKjQ0NN2FAQAAAACQ3aUrdF++fFn+/v43nScyMlJxcXHpKgoAAAAAgJwgXaG7RIkS2rlz503n2bJli8qVK5euogAAAAAAyAnSFbpbtmypX3/9VX/88UeK07///ntt3LhRTz311J3UBgAAAABA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HnnkEbm7u0uSBg8erHHjxmnLli2qWrWqevXqpYMHD6pq1apycXFRo0aN9Ndff+nChQtyc3NT4cKFZVmWYmNjed/K5vgUiwxhjFF8fLx8fX21bds251iCkJAQjRs3TiEhIZKuBfJly5Zp7969Kl26dCZUjOwk8Te7hqsG51rGGOeXL3/99Zckaf/+/Spfvry2bNmiLl266MMPP9Rrr72muLg4TZkyRUuXLk22zfChN3dyc3PThAkTFBcXpzFjxqh79+569dVX5eLiorZt2+rKlSv63//+p1mzZmnr1q3q37+/9u3bp6ZNm2Z26chk69atc94p48MPP9SyZcskSbVq1dJLL72kxo0ba8KECerWrZsk6fLly1qwYIF27dqVZD387cldPv30U7377rvOC75eunRJrq6u2rp1q6pWraqoqCgZYxQaGirp2vYRHx+vixcvqnjx4vL393fuqCJwZ3+W4RMs7kB0dLTc3Nycoej3339X8+bN1bdvXw0dOlQuLi66evWqXnjhBTkcDi1cuFAuLi4yxmjz5s3Kly+fKlasmMldAMjqEl8puF+/fho9erSioqI0fvx4563jpk+frhdffFHStQ+9zzzzjB566CENHTo0EytHVhITE6PHH39c58+fV+HChdWuXTu1a9dOkrR48WJ9//33+v77751fBs+aNYtTWXK5AwcOqHXr1rrnnntUtGhRTZgwQdu2bVPVqlUVHBys3r176/jx4/rrr7+UL18+nT17Vh06dNDFixe1du1agnYul7CHeseOHapevbpzPCYmRm5ubmrSpImaNGmid955R/Hx8WrZsqXq1aund999NxOrhh0I3Ui3MWPGaNOmTTp27Jg6dOigZs2aqUSJEpoxY4a6dOmi2rVrOw8DvXLlirZs2SI3N7ckH54B4Hbs3btXn3/+udq0aaOGDRsqJCREAwYM0Lp167RgwQJVr15dJ06c0GuvvaazZ89qw4YN7CFAElFRUbpw4YK6du2qq1evqlOnTs7gLV27HaEk5cuXTwULFsykKpHZNmzYoHr16ik2Nlbz5s3TG2+8ofDwcP3xxx+qW7eu8wiaH3/8UWPGjNGuXbt0zz33SLp2Wt26devk5ubGIeW5VMLrHh8fr19//VUtWrTQlClT9Pzzz8vLy8s537PPPquCBQvqyy+/VIsWLbRr1y7t37+f26HmQIRupMvAgQM1adIk9evXT4cPH9aGDRtUvXp1DR06VKVLl9bu3bs1e/ZsXb16VUWLFlWvXr3k6urKOSkA0u2HH35Qv379lC9fPi1btkzFixeXJK1cuVITJkzQvHnzVLp0aeXJk0d58uTRypUr+dCLVB08eFC9evVSZGSk2rdvr/bt22vgwIG6ePGiJkyYkNnlIRN9/PHHWrRokVauXClXV1f9/vvv6tixo3x8fFStWjVNmjRJefPmlXTttJczZ85owYIFioiIUJEiRfTss8/K4XDwmSeXSmnn0muvvaaZM2dq3LhxatOmjTw9PZ3jFy5cUFxcnLZv365du3Y5L/bJtpOzELpx27777ju99957mj17tmrVqqXff/9dzZo1U4UKFVS9enUNHz5cZcuWTfZBlw++AG5HwgcXY4wsy9KcOXM0efJkrVu3Tn/99ZcqV67snDc8PFwbNmzQqVOnFBAQoMaNG/OhF7cUEhKiPn366N9//5WXl5f27t2rX3/9VXXr1s3s0pCJjh07pqJFi8rhcCgkJERlypTRsWPHtGrVKn322WcqWbKkvvnmG+XJkyfVdfCZJ3dKHLjnz58vd3d3PfHEE5KkXr166euvv9aXX36p1q1bK0+ePBo9erT69eunGjVq6M8//yRw52Ac44vbEhUVpfz58+vFF19UrVq1tHDhQrVp00bjxo1T9+7dtWTJEr333nvat29fsjcb3nwA3I6EDy7r16+XJD3//PN66623VK1aNb388svat2+fpGt7mry9vfXoo4/q5Zdf1qOPPiqHw8FVynFLZcqU0RdffKG33npLLVu21J9//knghgIDA+VwOLR48WKVK1dOP/30kwIDA/XMM8+oe/fuOnr0qDp37qyIiAhJ1/ZWLlmyRNL1i33ymSf3SXyxz/79++vtt9/W0aNHdeLECUnS559/rs6dO6tbt26aN2+eJKlJkybq3Lmz/vrrLwJ3DseebqTZ//3f/ykwMFBPPfWUYmJi5OLiopYtW+qZZ55Rv379FBERoRo1aigqKkodOnTQ+++/n9klA8iGEu8p2LZtm+6//3599tln6tmzpyTpp59+0tixYxUeHq6pU6eqfPny7FUCkOH+/fdfffTRR1qwYIGmTp2qVq1aKTIyUrNmzdLEiRMVHh6uYsWK6Z9//tHhw4cJS5AkffTRR/rkk080f/585y0IE+vRo4emTZumUaNG6bXXXnOOE7hzNl5ZpMkPP/ygUaNGacWKFfL19ZVlWdq1a5eOHz+uOnXqSJKOHz+uWrVq6fHHH09yURoASKvEewrGjx+vPXv2yNPTU2+++aZiYmLUu3dvtWrVSsYYjR8/Xl26dNHEiROTHGoOABmhfPnyGjRokBwOh9q1a6cZM2aoVatWevnll1WiRAktXbpU0dHRWrp0qVxdXfnyL5czxigsLEy//vqr3n//fT344IM6fPiwdu3apW+//VZ+fn4aN26cxo0bp4sXL2rOnDnq3r278w5ABO6cjT3duKUff/xRoaGhMsaoV69ezr1Q//zzjzp06KAGDRqoVatWGjlypDw8PDR37lxZlsVVygGk2+DBg/XVV1/ps88+09WrV7Vy5UotWLBAgwYN0oABAyRJP//8s4YOHaratWtr4sSJmVwxgJzq4MGD+uijjzRnzhxn8E641kQC9lJCunak1pNPPilPT0+1adNGM2bM0MWLF1WoUCGtW7dOjRo10pw5c5zzJr5uCXI2/jrgpi5cuKBXXnlFYWFheuuttyRdP8+ycuXKatmypebNm6c5c+aoTJky+uOPP2RZVpK9VQBwO06dOqVffvlFI0eOdN53u1mzZipbtqzef/99557vli1bys/PL8XD9wAgo5QtW1b9+/eXZVnq1KmTJk6cqGeffTbJPARuSNc+Izdr1kyLFi1Shw4d1Lt3bzVv3lwPPfSQ3nvvPR08eNB5RETCbXX5vJw7sKcbqYqMjJSnp6f+/fdftWnTRvHx8VqwYIHKlCmT5Fu5Q4cOKTw8XJUqVZKLiwvf9gK4I2fPnlWlSpU0YMAA9enTxzl+5MgRPf/889q0aZNGjx7t/CJQSvkWLQCQkUJCQjRgwABdvHhRv/zyS2aXgywm8WfjCxcu6NKlSypVqpRz+iOPPKIqVaroiy++yKwSkYkI3UjRJ598osjISL366qsqVKiQ/v33XzVt2lSlS5fW7NmzFRAQkOLhMJzPBOB2pBSW4+Pj1aVLF125ckUffPCBypcv75zWo0cP7du3T3v37tVHH33k3BMOALcj8WeYmJgYubm5pWm5EydOqEiRIhwWjBTduE2Eh4fr77//1pAhQxQaGqqtW7eyYyqXYrcAUnT8+HF98MEH+vbbb3Xu3DmVL19ev/76qw4ePKiXXnpJp0+fTvGNhsANIK0SB+69e/dq48aNOnfunFxcXPTCCy9o+/btmjRpkvPWYJcvX1ZoaKjatGmjevXqafHixYqKihLfHQO4XQmfYT799FMtXbpUktL0t6RYsWLOv1sE7twnLi7uptNv3Cb++OMPjR07Vh4eHtqyZYvzgnvIfdjTjVQNHTpUn332md577z21b99eBQsW1L///qvHH39cefLk0apVq5Q/f/7MLhNANpPwtpPw4WTQoEGaP3++Lly4oMDAQAUFBenTTz/Vt99+qzFjxsjd3V2BgYE6duyYYmNjtW3bNvXr10+rV6/W+vXr+bIPQLpVqlRJL730kt59992b7rlOPG3t2rUqXLiwKlSocDdLRSaLiIiQl5eXpGtfFJcrV+6We62NMdq+fbuqV6/OKZi5HHu64bR7925FRkY6fx46dKh69uypIUOG6JtvvnHu8f75559Vvnx5+fj4ZGK1ALKrxB9qR48erUmTJmns2LEKDQ1VxYoVNWfOHAUHB6tz58764osv1LZtW3l4eKhp06batGmTJOn06dOqXLkyewwApFl8fHyyscqVK+vMmTOSUt9znThwjxs3Tm3atFFERIR9hSLL+f3335331O7Zs6fatm2b5DNzShK2m/vuu895dARfEudefNUCGWO0ePFi/ec//9GsWbP09NNPy8PDQ5L0/vvvKzo6WoMHD5abm5vatGmjSpUqae7cuZI4hxtA2g0ePFgBAQHq2bOnLMvS1atXtWrVKg0dOlSPPPKIli5dqoULF2rUqFF64IEHFBMTo3r16qlhw4Z68803JUnHjh3T+PHjtWjRIq1du1bu7u6Z2xSAbCMh+AQHB8vf31/FixfXQw89pCVLlig6Olru7u7O014SPt8kPg3myy+/1ODBg/Xll1/qvvvuy8ROcDcZYxQcHKw9e/bo/vvv1+HDh7Vp0yblzZs3zetYvHix7r333iTXKEHuwp5uyLIstWzZUm3btlX37t21YMECRUVFOae/8cYbcnd313//+1+tWrUqybIEbgBpcfHiRa1bt04//vijpk6dKkny9vbW2bNnVb9+ff36669q06aNRo4cqVdffVXR0dGaPn26Nm7c6Dwc/cqVKxoxYoR++uknrVixQlWqVMnMlgBkQzNnztTjjz+uChUqKCgoSBMmTNChQ4e0ePFibdy4UVevXpV07b7bkpIE7rfffluTJk1SmzZtMq1+3F0Je6v7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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABy60lEQVR4nO3de3zO9f/H8ed1XTtjm9M2szkv57NRKORUIXIKhfCVIiVnUegbQuFbSkoOkVBUcozIMYUtIsccolnOs83s+Pn94bePrW2MfOzgcb/dumXvz+n9uq7rs13Pz+H9sRmGYQgAAAAAANx19qzuAAAAAAAAuRWhGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAJAlTpw4IZvNphIlStyV9c2dO1c2m03PPffcXVlfVrlw4YJ69+6tokWLyuFwyGazacyYMVndLdxnfvzxR9lsNjVs2DCruwIAOR6hGwByqRIlSshms8lms2nQoEE3nfd///ufOa/NZrtHPcweUtad/F+ePHlUrlw59e/fX3/++ec97U/r1q01a9YsRUdHq1atWqpXr56KFSt2T/uAO5fyc/T+++/fdN5XX33VnPduHXw6ceKExowZo7lz596V9QEA/j1CNwDcBxYuXKjExMQMpy9YsOAe9iZ7qlSpkurVq6d69eqpaNGiOnr0qKZPn64qVapo586d96QPe/fu1bZt21S0aFGdPHlSP//8s7Zu3aqePXvek+3j7po/f36G0xITE7Vo0aK7vs0TJ05o7Nix/zp0e3h4qGzZshzwAYC7gNANALlc2bJlFR4ervXr16c7/dChQ9q1a5fKli17j3uWvbz//vvaunWrtm7dqsOHD+vQoUOqVq2aIiIi1L17dyUlJVneh4MHD0qS6tWrJy8vL8u3B+uULVtWO3fu1KFDh9Kdvm7dOoWHh2fb/a527do6ePCgPvvss6zuCgDkeIRuAMjlnn32WUkZn81OPhvXtWvXe9annKB06dKaPXu2JOnAgQPas2eP5duMiYmRJLm7u1u+LVjrVvtdcjv7HQDkfoRuAMjlGjRooMDAQH399deKjo5ONc0wDH3++edyd3dX27Ztb7qe6OhovfXWW6pSpYry5MkjT09P1alTRx988IESEhIyXG7T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AAAAACxC6AYAAAAAwCKEbgAAAAAALELoBgAAAADAIoRuAAAAAAAsQugGAAAAAMAihG4AAAAAACySq0P3hx9+qJIlS8rNzU01a9bUli1bsrpLAAAAAID7iFNWd8Aqixcv1oABA/Thhx+qXr16mjlzph5//HH9/vvvKlasWFZ37+7ZtCurewDcvga1sroHAAAAwD2Ra890T5kyRb169dJ//vMflS9fXtOmTVNgYKBmzJiR1V0DAAAAANwncuWZ7ri4OO3evVvDhw9P1d6sWTNt37493WViY2MVGxtr/hwRESFJunjxohISEiRJdrtddrtdSUlJSkpKMudNbk9MTJRhGLdsdzgcstls5npTtktSYmJiptqdnJxkREUqUTfWbZNNDptNSYahpEy022WT/SbtiYYhIxPtDtmu12TceF2S2yWl6uPN2p1sdhmGQU25vaaLF7Pn/mQYqdptNpscDoeSoiLvz/eJmnJ2TSn2s2y1P/1jn7fZbHJER92/7xM15dyaLl683p7d9qd02u12u+zbf70/3ydqytk1PVTteh+z2/70/99hL1++LEmp9v305MrQff78eSUmJsrX1zdVu6+vr8LDw9NdZsKECRo7dmya9pIlS1rSRwAAAABAzhcZGSkvL68Mp+fK0J3MZrOl+tkwjDRtyUaMGKGBAweaPyclJenixYsqWLBghssg97py5YoCAwN16tQpeXp6ZnV3gFyJ/QywFvsYYD32s/ubYRiKjIyUv7//TefLlaG7UKFCcjgcac5qnz17Ns3Z72Surq5ydXVN1ebt7W1VF5FDeHp68gsUsBj7GWAt9jHAeuxn96+bneFOlisHUnNxcVHNmjW1bt26VO3r1q1T3bp1s6hXAAAAAID7Ta480y1JAwcOVNeuXVWrVi099NBD+vjjj/Xnn3/qhRdeyOquAQAAAADuE7k2dD/99NO6cOGC3nzzTZ05c0aVKlXSqlWrVLx48azuGnIAV1dXjR49Os0tBwDuHvYzwFrsY4D12M+QGTbjVuObAwAAAACAO5Ir7+kGAAAAACA7IHQDAAAAAGARQjcAAAAAABYhdAMAAAAAYBFCNwAAAAAAFiF0477FwP0AAAAArEboxn3pvffe0y+//CJJSkpKyuLeALkD+xIAAEBaPKcb96XatWvLx8dHK1asyOquALlCUlKS7Pbrx3FXrlyp/Pnzq27d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ZElz4KYxY8YoKSlJo0ePlmEY6t69u4KCgrRixQqNGjVKnp6eWdxjIOcpVKiQ+vfvr1q1amnnzp3q27ev3nrrLb300kt69dVXNX/+fEVFRentt99WUFCQuRyBG8hY8hf5gIAAPfnkkzp79qyee+45ubi4qF27dvryyy/10EMPadWqVYqMjJSvr682bNigixcvavfu3ebj95L3s+S/gwCu++GHHzR//nzNnTtX/fv3144dO7Rx40blzZs3w2WSLzWvVq2a2cbfMtxrhG5kG4ZhaOXKlXryySe1cOFCPfXUU+ajit58803FxcVp1KhRcnZ2VseOHVW+fHktXbpUEmffgJtJb1RWNzc3Pfjgg8qXL5+++eYbPfTQQ3r++eclSd7e3uagaqVLl86KLgM5UvKZs5EjR2rz5s3y9PSUm5ubunXrpujoaHXr1k3bt2/XyJEjtX//fv3555+qWbOmJk6cKCcnpzRn3xhADbjBMAyFhobq4MGDqlGjhk6ePKmff/75poH7n1auXKkHHngg1cFk4F7g8nJkO926ddPy5cs1c+ZMtWnTxgzep0+fVqVKlXTlyhUtWrRIHTt2zOKeAtlfysFkFixYoKioKHl4eKhbt27mPP3799eRI0c0e/Zs+fv7q127durUqZPat2/Ps+6B27Rw4UI9//zzWrt2rapVq6YDBw7o448/1qJFi/Thhx/q2WeflWEYSkxMlN1uN/ctDh4DGUv5t+zJJ5/UihUr9NRTT2nhwoVydXXN8O9UyuU++ugjjRo1St98843q169/T/sPcKYb2cJHH32khIQEvfTSS/rss8/0n//8xxz1NTl4X716VX379lXRokXVtm3bLO4xkDMkf9kYOXKkpk+frlKlSunPP//UihUrtGTJEklSpUqVtGrVKnXo0EGRkZGKj4/XU089JZvNJsMwCNzAbThy5Ihq166tevXqSZJq1aolb29vXb58Wc8//7w8PT315JNPprmflMANpC9loE5ISNBDDz2kihUratu2berbt6/efvttFS5cOM2VIimXmzlzpoYPH65Zs2YRuJElCN3IckOGDNHixYvVrVs3/fnnnypWrJhmzZolwzD04osv6vDhw6pcubI+/fRTeXh4aPz48ZLEIBjATSR/2TAMQ9HR0dq/f782bdqkwMBAhYSEmIOmrVixQn369JHdbtepU6cUHx+v//73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mjVTQECA3N3dJUnTpk1TbGxsussl38N9t9bn6emZps3Jyemm0+Lj482fL168KEnatm2btm3bllG5io6OznBaSsnr++CDD246X3R0dKrQndHrAgDAvUDoBgAgG0lISNB///tf+fv769dff011ebdhGJo0aVKGy6YcjO1urO/fSg7mgwYN0jvvvHPX1vfbb7+pUqVKmV4uvdcFAIB7hXu6AQDIRs6fP6+IiAg9+OCDqQKyJO3atUsxMTFZur7bERwcLJvNpp9++inTyzgcDklKdfl7sjp16kjSba0PAICsRugGACAb8fHxkbu7u0JCQnT16lWz/dKlS+azvLNyfbfDz89PHTt21Pbt2zV58mQZhpFmnp9//jlVvwoUKCBJOn36dJp5e/TooXz58mnkyJHav39/mulXr1417/sGACC74PJyAACyEbvdrr59++rdd99V1apV1apVK125ckWrV69W8eLF5e/vn6Xru10ffvihDh06pKFDh2r+/Pl66KGH5OXlpVOnTmn37t06cuSIzpw5Iw8PD0nSo48+qq+++kodOnTQE088ITc3N1WuXFktWrRQ4cKF9cUXX6hDhw6qWrWqHnvsMZUrV07Xrl3TyZMntWnTJtWtW/em98sDAHCvEboBAMhmJkyYoAIFCmju3Ln68MMP5evrq06dOmns2LG3dS+zVeu7HQUKFND27ds1ffp0LV68WJ9//rmSkpLk5+enqlWr6vXXX0816Fnv3r114sQJLVq0SOPGjVNCQoK6d++uFi1aSJJatGih0NBQTZ48WevXr9e6deuUJ08eBQQEqEePHnr22WctrQcAgNtlM9K71gsAAAAAAPxr3NMNAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBF/g/JfG8XJHz0qAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -240,15 +155,23 @@ ], "source": [ "from logllm.log_llm import log_llm\n", - "from logllm.plot import plot_ml_metrics\n", + "from logllm.plot import plot_metrics\n", + "from logllm.plot_v1 import plot_ml_metrics\n", + "\n", "# code_string = extract_notebook_code(notebook_path)\n", "notebook_path = \"svc-sample.ipynb\" \n", + "notebook_pat = \"train.ipynb\"\n", + "notebook_pa = \"cal.ipynb\"\n", "\n", "# Extract experimental conditions and results using log_llm\n", - "code_string = log_llm(notebook_path, project_name=\"Machine learning\", is_logging=True, provider=\"gemini\")\n", + "code_string = log_llm(notebook_path, provider=\"gemini\")\n", + "code_strin = log_llm(notebook_pat, provider=\"gemini\")\n", + "code_str = log_llm(notebook_pa, provider=\"gemini\")\n", + "\n", "\n", "# Plot the response from the query\n", - "plot_ml_metrics(code_string)\n", + "plot_metrics(code_string, code_strin, code_str)\n", + "plot_ml_metrics(code_str)\n", "\n" ] }, diff --git a/logllm/plot.py b/logllm/plot.py index dcbbc4e..799d24e 100644 --- a/logllm/plot.py +++ b/logllm/plot.py @@ -1,40 +1,85 @@ import json +import numpy as np import matplotlib.pyplot as plt -def plot_ml_metrics(response_data): - # Parse the JSON string into a Python dictionary if needed - if isinstance(response_data, str): - response_data = json.loads(response_data) +def plot_metrics(*models_results): + # Process each model to ensure it's in dictionary format + processed_models = [] + for model in models_results: + # Convert to dictionary if the input is a JSON string + if isinstance(model, str): + model = json.loads(model) # Convert string to dictionary + processed_models.append(model) - try: - # Define keys to exclude from the plot - exclude_keys = {'cache_size', 'random_state_tts', 'random_state',} + # Define keys to exclude from the plot + exclude_keys = {'cache_size', 'random_state_tts', 'random_state', 'random_state_1', 'n_estimators'} - # Extract all keys and numeric values from the response, excluding specific keys - metrics = [] - values = [] - for key, value in response_data.items(): - # Check if the key is not in the exclude list and if the value is numeric + # Initialize containers for metrics, values, and model names + metrics = [] + model_names = [] + model_values = {} + + for model in processed_models: + model_name = model.get("model_name", "Test Model") + model_names.append(model_name) + + for key, value in model.items(): + if key.startswith("result_name_"): + metric_name = value + metric_index = key.split("_")[-1] # Extract the index (e.g., "1" from "result_name_1") + metric_value = model.get(f"result_value_{metric_index}", None) + + if metric_value is not None: + if metric_name not in metrics: + metrics.append(metric_name) + if metric_name not in model_values: + model_values[metric_name] = [] + + # Add the metric value to the list + model_values[metric_name].append(metric_value) + + # Handle additional numeric values in the model (not using the result_name format) + for key, value in model.items(): + # Exclude specific keys and ensure the value is numeric if key not in exclude_keys and isinstance(value, (int, float)): - metrics.append(key) - values.append(value) - - # Check if any numeric values were found - if not values: - print("No numeric values found to plot.") - return - - # Plotting - plt.figure(figsize=(10, 6)) # Adjusted figure size for better visualization - plt.bar(metrics, values, color='pink') - plt.title('Model Performance Metrics', fontsize=16) - plt.xlabel('Parameter', fontsize=14) - plt.ylabel('Value', fontsize=14) - plt.ylim(0, max(values) * 1.1) # Dynamically set the y-limit based on the maximum value - plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability - plt.grid(True, axis='y', linestyle='--', alpha=0.7) - plt.tight_layout() - plt.show() - - except Exception as e: - print(f"Error processing the response data: {e}") + if key not in metrics: + metrics.append(key) + if key not in model_values: + model_values[key] = [] + model_values[key].append(value) + + # Handle cases where no valid metrics were provided + if not metrics or not model_names: + print("No valid metrics or model names found.") + return + + # Ensure all models have values for all metrics, filling in with 0 if not available + for metric in metrics: + for i in range(len(model_names)): + if len(model_values[metric]) <= i: + model_values[metric].append(0) # Default value if missing + + # Plotting side-by-side bar chart + x = np.arange(len(metrics)) # Label locations + bar_width = 0.15 # Width of the bars + fig, ax = plt.subplots(figsize=(10, 6)) + + # Create a bar for each model's performance metrics + for i, model_name in enumerate(model_names): + values = [model_values[metric][i] for metric in metrics] + ax.bar(x + i * bar_width, values, width=bar_width, label=model_name) + + # Customization of the plot + ax.set_xlabel('Metric', fontsize=14) + ax.set_ylabel('Value', fontsize=14) + ax.set_title('Comparison of Model Performance Metrics', fontsize=16) + ax.set_xticks(x + bar_width * (len(model_names) - 1) / 2) + ax.set_xticklabels(metrics, fontsize=12) + ax.legend(title='Models') + ax.grid(True, axis='y', linestyle='--', alpha=0.7) + + plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability + plt.tight_layout() + plt.show() + + diff --git a/logllm/plotter.py b/logllm/plotter.py deleted file mode 100644 index 799d24e..0000000 --- a/logllm/plotter.py +++ /dev/null @@ -1,85 +0,0 @@ -import json -import numpy as np -import matplotlib.pyplot as plt - -def plot_metrics(*models_results): - # Process each model to ensure it's in dictionary format - processed_models = [] - for model in models_results: - # Convert to dictionary if the input is a JSON string - if isinstance(model, str): - model = json.loads(model) # Convert string to dictionary - processed_models.append(model) - - # Define keys to exclude from the plot - exclude_keys = {'cache_size', 'random_state_tts', 'random_state', 'random_state_1', 'n_estimators'} - - # Initialize containers for metrics, values, and model names - metrics = [] - model_names = [] - model_values = {} - - for model in processed_models: - model_name = model.get("model_name", "Test Model") - model_names.append(model_name) - - for key, value in model.items(): - if key.startswith("result_name_"): - metric_name = value - metric_index = key.split("_")[-1] # Extract the index (e.g., "1" from "result_name_1") - metric_value = model.get(f"result_value_{metric_index}", None) - - if metric_value is not None: - if metric_name not in metrics: - metrics.append(metric_name) - if metric_name not in model_values: - model_values[metric_name] = [] - - # Add the metric value to the list - model_values[metric_name].append(metric_value) - - # Handle additional numeric values in the model (not using the result_name format) - for key, value in model.items(): - # Exclude specific keys and ensure the value is numeric - if key not in exclude_keys and isinstance(value, (int, float)): - if key not in metrics: - metrics.append(key) - if key not in model_values: - model_values[key] = [] - model_values[key].append(value) - - # Handle cases where no valid metrics were provided - if not metrics or not model_names: - print("No valid metrics or model names found.") - return - - # Ensure all models have values for all metrics, filling in with 0 if not available - for metric in metrics: - for i in range(len(model_names)): - if len(model_values[metric]) <= i: - model_values[metric].append(0) # Default value if missing - - # Plotting side-by-side bar chart - x = np.arange(len(metrics)) # Label locations - bar_width = 0.15 # Width of the bars - fig, ax = plt.subplots(figsize=(10, 6)) - - # Create a bar for each model's performance metrics - for i, model_name in enumerate(model_names): - values = [model_values[metric][i] for metric in metrics] - ax.bar(x + i * bar_width, values, width=bar_width, label=model_name) - - # Customization of the plot - ax.set_xlabel('Metric', fontsize=14) - ax.set_ylabel('Value', fontsize=14) - ax.set_title('Comparison of Model Performance Metrics', fontsize=16) - ax.set_xticks(x + bar_width * (len(model_names) - 1) / 2) - ax.set_xticklabels(metrics, fontsize=12) - ax.legend(title='Models') - ax.grid(True, axis='y', linestyle='--', alpha=0.7) - - plt.xticks(rotation=45, ha='right') # Rotate x-axis labels for better readability - plt.tight_layout() - plt.show() - - diff --git a/logllm/query.py b/logllm/query.py index 254ac74..22f634b 100644 --- a/logllm/query.py +++ b/logllm/query.py @@ -63,11 +63,11 @@ def query_gemini(user_input: str, code): # General query function that calls the appropriate provider -def query(user_input: str, provider: str): +def query(provider): if provider == 'openai': - return query_openai(user_input) + return query_openai() elif provider == 'gemini': - return query_gemini(user_input) + return query_gemini() else: raise ValueError("Invalid provider specified. Use 'openai' or 'gemini'.")