ivoryos 1.2.0b1__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ivoryos might be problematic. Click here for more details.
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/PKG-INFO +69 -35
- ivoryos-1.2.0b1/ivoryos.egg-info/PKG-INFO → ivoryos-1.2.2/README.md +51 -41
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/__init__.py +22 -1
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/config.py +1 -0
- ivoryos-1.2.2/ivoryos/optimizer/ax_optimizer.py +164 -0
- ivoryos-1.2.2/ivoryos/optimizer/base_optimizer.py +65 -0
- ivoryos-1.2.2/ivoryos/optimizer/baybe_optimizer.py +183 -0
- ivoryos-1.2.2/ivoryos/optimizer/registry.py +9 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/auth/auth.py +3 -1
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/data/data.py +2 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/design/design.py +4 -4
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/library/library.py +4 -4
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/script_runner.py +1 -1
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/serilize.py +4 -6
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/utils.py +2 -1
- ivoryos-1.2.2/ivoryos/version.py +1 -0
- ivoryos-1.2.0b1/README.md → ivoryos-1.2.2/ivoryos.egg-info/PKG-INFO +75 -30
- ivoryos-1.2.2/ivoryos.egg-info/SOURCES.txt +50 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos.egg-info/requires.txt +5 -1
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos.egg-info/top_level.txt +0 -1
- ivoryos-1.2.2/pyproject.toml +38 -0
- ivoryos-1.2.0b1/MANIFEST.in +0 -8
- ivoryos-1.2.0b1/ivoryos/routes/auth/templates/login.html +0 -25
- ivoryos-1.2.0b1/ivoryos/routes/auth/templates/signup.html +0 -32
- ivoryos-1.2.0b1/ivoryos/routes/control/templates/controllers.html +0 -166
- ivoryos-1.2.0b1/ivoryos/routes/control/templates/controllers_new.html +0 -112
- ivoryos-1.2.0b1/ivoryos/routes/data/templates/components/step_card.html +0 -13
- ivoryos-1.2.0b1/ivoryos/routes/data/templates/workflow_database.html +0 -109
- ivoryos-1.2.0b1/ivoryos/routes/data/templates/workflow_view.html +0 -130
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/action_form.html +0 -53
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/actions_panel.html +0 -25
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/autofill_toggle.html +0 -10
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/canvas.html +0 -5
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/canvas_footer.html +0 -9
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/canvas_header.html +0 -75
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/canvas_main.html +0 -34
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/deck_selector.html +0 -10
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/edit_action_form.html +0 -38
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/instruments_panel.html +0 -66
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals/drop_modal.html +0 -17
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals/json_modal.html +0 -22
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals/new_script_modal.html +0 -17
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals/rename_modal.html +0 -23
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals/saveas_modal.html +0 -27
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/modals.html +0 -6
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/python_code_overlay.html +0 -39
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/sidebar.html +0 -15
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/components/text_to_code_panel.html +0 -20
- ivoryos-1.2.0b1/ivoryos/routes/design/templates/experiment_builder.html +0 -41
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/error_modal.html +0 -20
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/logging_panel.html +0 -31
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/progress_panel.html +0 -27
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/run_panel.html +0 -9
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/run_tabs.html +0 -17
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/tab_bayesian.html +0 -399
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/tab_configuration.html +0 -98
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/components/tab_repeat.html +0 -14
- ivoryos-1.2.0b1/ivoryos/routes/execute/templates/experiment_run.html +0 -294
- ivoryos-1.2.0b1/ivoryos/routes/library/templates/library.html +0 -91
- ivoryos-1.2.0b1/ivoryos/routes/main/templates/help.html +0 -141
- ivoryos-1.2.0b1/ivoryos/routes/main/templates/home.html +0 -103
- ivoryos-1.2.0b1/ivoryos/static/favicon.ico +0 -0
- ivoryos-1.2.0b1/ivoryos/static/gui_annotation/Slide1.png +0 -0
- ivoryos-1.2.0b1/ivoryos/static/gui_annotation/Slide2.PNG +0 -0
- ivoryos-1.2.0b1/ivoryos/static/js/action_handlers.js +0 -213
- ivoryos-1.2.0b1/ivoryos/static/js/db_delete.js +0 -23
- ivoryos-1.2.0b1/ivoryos/static/js/overlay.js +0 -12
- ivoryos-1.2.0b1/ivoryos/static/js/script_metadata.js +0 -39
- ivoryos-1.2.0b1/ivoryos/static/js/socket_handler.js +0 -125
- ivoryos-1.2.0b1/ivoryos/static/js/sortable_card.js +0 -24
- ivoryos-1.2.0b1/ivoryos/static/js/sortable_design.js +0 -138
- ivoryos-1.2.0b1/ivoryos/static/js/ui_state.js +0 -113
- ivoryos-1.2.0b1/ivoryos/static/logo.webp +0 -0
- ivoryos-1.2.0b1/ivoryos/static/style.css +0 -211
- ivoryos-1.2.0b1/ivoryos/templates/base.html +0 -157
- ivoryos-1.2.0b1/ivoryos/version.py +0 -1
- ivoryos-1.2.0b1/ivoryos.egg-info/SOURCES.txt +0 -109
- ivoryos-1.2.0b1/setup.py +0 -38
- ivoryos-1.2.0b1/tests/__init__.py +0 -0
- ivoryos-1.2.0b1/tests/conftest.py +0 -133
- ivoryos-1.2.0b1/tests/integration/__init__.py +0 -0
- ivoryos-1.2.0b1/tests/integration/test_route_auth.py +0 -80
- ivoryos-1.2.0b1/tests/integration/test_route_control.py +0 -94
- ivoryos-1.2.0b1/tests/integration/test_route_database.py +0 -61
- ivoryos-1.2.0b1/tests/integration/test_route_design.py +0 -36
- ivoryos-1.2.0b1/tests/integration/test_route_main.py +0 -35
- ivoryos-1.2.0b1/tests/integration/test_sockets.py +0 -26
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/LICENSE +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/api/api.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/auth/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/control/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/control/control.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/control/control_file.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/control/control_new_device.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/control/utils.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/data/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/design/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/design/design_file.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/design/design_step.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/execute/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/execute/execute.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/execute/execute_file.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/library/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/main/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/routes/main/main.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/socket_handlers.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/__init__.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/bo_campaign.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/client_proxy.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/db_models.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/form.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/global_config.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/llm_agent.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/py_to_json.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos/utils/task_runner.py +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/ivoryos.egg-info/dependency_links.txt +0 -0
- {ivoryos-1.2.0b1 → ivoryos-1.2.2}/setup.cfg +0 -0
|
@@ -1,13 +1,26 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ivoryos
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
|
|
5
|
-
|
|
6
|
-
Author: Ivory Zhang
|
|
7
|
-
Author-email: ivoryzhang@chem.ubc.ca
|
|
5
|
+
Author-email: Ivory Zhang <ivoryzhang@chem.ubc.ca>
|
|
8
6
|
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/heingroup/ivoryos
|
|
8
|
+
Requires-Python: >=3.7
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
|
+
Requires-Dist: bcrypt
|
|
12
|
+
Requires-Dist: Flask-Login
|
|
13
|
+
Requires-Dist: Flask-Session
|
|
14
|
+
Requires-Dist: Flask-SocketIO
|
|
15
|
+
Requires-Dist: Flask-SQLAlchemy
|
|
16
|
+
Requires-Dist: Flask-WTF
|
|
17
|
+
Requires-Dist: SQLAlchemy-Utils
|
|
18
|
+
Requires-Dist: python-dotenv
|
|
19
|
+
Requires-Dist: astor; python_version < "3.9"
|
|
20
|
+
Provides-Extra: optimizer
|
|
21
|
+
Requires-Dist: ax-platform; extra == "optimizer"
|
|
22
|
+
Requires-Dist: baybe; extra == "optimizer"
|
|
23
|
+
Dynamic: license-file
|
|
11
24
|
|
|
12
25
|
[](https://ivoryos.readthedocs.io/en/latest/?badge=latest)
|
|
13
26
|
[](https://pypi.org/project/ivoryos/)
|
|
@@ -39,7 +52,7 @@ With the least modification of the current workflow, user can design, manage and
|
|
|
39
52
|
This software is developed and tested using Windows. This software and its dependencies are compatible across major platforms: Linux, macOS, and Windows. Some dependencies (Flask-SQLAlchemy) may require additional setup.
|
|
40
53
|
|
|
41
54
|
### Python Version
|
|
42
|
-
Python >=3.10 for best compatibility. Python >=3.7 without Ax.
|
|
55
|
+
Python >=3.10 for the best compatibility. Python >=3.7 without Ax.
|
|
43
56
|
### Python dependencies
|
|
44
57
|
This software is compatible with the latest versions of all dependencies.
|
|
45
58
|
- bcrypt~=4.0
|
|
@@ -50,7 +63,9 @@ This software is compatible with the latest versions of all dependencies.
|
|
|
50
63
|
- SQLAlchemy-Utils~=0.41
|
|
51
64
|
- Flask-WTF~=1.2
|
|
52
65
|
- python-dotenv==1.0.1
|
|
53
|
-
- ax-platform (optional
|
|
66
|
+
- ax-platform (optional 1.0 for Python>=3.10)
|
|
67
|
+
- baybe (optional)
|
|
68
|
+
|
|
54
69
|
|
|
55
70
|
## Installation
|
|
56
71
|
```bash
|
|
@@ -74,43 +89,60 @@ import ivoryos
|
|
|
74
89
|
ivoryos.run(__name__)
|
|
75
90
|
```
|
|
76
91
|
### Login
|
|
77
|
-
Create an account and login (local database)
|
|
92
|
+
Create an account and login (local database with bcrypt password)
|
|
78
93
|
### Features
|
|
79
|
-
- **Direct control**: direct function calling
|
|
80
|
-
- **
|
|
81
|
-
- **Design**: add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution page
|
|
82
|
-
- **Execution**: configure iteration methods and parameters in _Compile/Run_ tab.
|
|
83
|
-
- **
|
|
84
|
-
- **
|
|
94
|
+
- **Direct control**: direct function calling _Devices_ tab
|
|
95
|
+
- **Workflows**:
|
|
96
|
+
- **Design Editor**: drag/add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution configuration page
|
|
97
|
+
- **Execution Config**: configure iteration methods and parameters in _Compile/Run_ tab.
|
|
98
|
+
- **Design Library**: manage workflow scripts in _Library_ tab.
|
|
99
|
+
- **Workflow Data**: Execution records are in _Data_ tab.
|
|
85
100
|
|
|
86
101
|
[//]: # ()
|
|
87
102
|
|
|
88
103
|
[//]: # ()
|
|
89
104
|
|
|
90
105
|
|
|
91
|
-
### Additional settings
|
|
92
|
-
#### AI assistant
|
|
93
|
-
To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
|
|
106
|
+
### Additional settings
|
|
107
|
+
[//]: # (#### AI assistant)
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
1. Create a `.env` file for `OPENAI_API_KEY`
|
|
97
|
-
```
|
|
98
|
-
OPENAI_API_KEY="Your API Key"
|
|
99
|
-
```
|
|
100
|
-
2. In your SDL script, define model, you can use any GPT models.
|
|
109
|
+
[//]: # (To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.)
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```
|
|
111
|
+
[//]: # ()
|
|
112
|
+
[//]: # (#### Enable LLMs with [OpenAI API](https://github.com/openai/openai-python))
|
|
105
113
|
|
|
106
|
-
|
|
107
|
-
1. Download Ollama.
|
|
108
|
-
2. pull models from Ollama
|
|
109
|
-
3. In your SDL script, define LLM server and model, you can use any models available on Ollama.
|
|
114
|
+
[//]: # (1. Create a `.env` file for `OPENAI_API_KEY`)
|
|
110
115
|
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
[//]: # (```)
|
|
117
|
+
|
|
118
|
+
[//]: # (OPENAI_API_KEY="Your API Key")
|
|
119
|
+
|
|
120
|
+
[//]: # (```)
|
|
121
|
+
|
|
122
|
+
[//]: # (2. In your SDL script, define model, you can use any GPT models.)
|
|
123
|
+
|
|
124
|
+
[//]: # ()
|
|
125
|
+
[//]: # (```python)
|
|
126
|
+
|
|
127
|
+
[//]: # (ivoryos.run(__name__, model="gpt-3.5-turbo"))
|
|
128
|
+
|
|
129
|
+
[//]: # (```)
|
|
130
|
+
|
|
131
|
+
[//]: # ()
|
|
132
|
+
[//]: # (#### Enable local LLMs with [Ollama](https://ollama.com/))
|
|
133
|
+
|
|
134
|
+
[//]: # (1. Download Ollama.)
|
|
135
|
+
|
|
136
|
+
[//]: # (2. pull models from Ollama)
|
|
137
|
+
|
|
138
|
+
[//]: # (3. In your SDL script, define LLM server and model, you can use any models available on Ollama.)
|
|
139
|
+
|
|
140
|
+
[//]: # ()
|
|
141
|
+
[//]: # (```python)
|
|
142
|
+
|
|
143
|
+
[//]: # (ivoryos.run(__name__, llm_server="localhost", model="llama3.1"))
|
|
144
|
+
|
|
145
|
+
[//]: # (```)
|
|
114
146
|
|
|
115
147
|
#### Add additional logger(s)
|
|
116
148
|
```python
|
|
@@ -135,7 +167,7 @@ ivoryos.run(__name__)
|
|
|
135
167
|
|
|
136
168
|
* Running on all addresses (0.0.0.0)
|
|
137
169
|
* Running on http://127.0.0.1:8000
|
|
138
|
-
* Running on http://
|
|
170
|
+
* Running on http://0.0.0.0:8000
|
|
139
171
|
|
|
140
172
|
### Deck function and web form
|
|
141
173
|

|
|
@@ -163,6 +195,8 @@ When you run the application for the first time, it will automatically create th
|
|
|
163
195
|
- [x] dropdown input ✅
|
|
164
196
|
- [x] show line number option ✅
|
|
165
197
|
- [ ] snapshot version control
|
|
198
|
+
- [ ] optimizer-agnostic
|
|
199
|
+
- [ ] check batch-config file compatibility
|
|
166
200
|
|
|
167
201
|
## Citing
|
|
168
202
|
|
|
@@ -203,4 +237,4 @@ For an additional perspective related to the development of the tool, please see
|
|
|
203
237
|
## Authors and Acknowledgement
|
|
204
238
|
Ivory Zhang, Lucy Hao
|
|
205
239
|
|
|
206
|
-
Authors acknowledge
|
|
240
|
+
Authors acknowledge Telescope Innovations, Hein Lab members for their valuable suggestions and contributions.
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: ivoryos
|
|
3
|
-
Version: 1.2.0b1
|
|
4
|
-
Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
|
|
5
|
-
Home-page: https://gitlab.com/heingroup/ivoryos
|
|
6
|
-
Author: Ivory Zhang
|
|
7
|
-
Author-email: ivoryzhang@chem.ubc.ca
|
|
8
|
-
License: MIT
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
|
|
12
1
|
[](https://ivoryos.readthedocs.io/en/latest/?badge=latest)
|
|
13
2
|
[](https://pypi.org/project/ivoryos/)
|
|
14
3
|

|
|
@@ -39,7 +28,7 @@ With the least modification of the current workflow, user can design, manage and
|
|
|
39
28
|
This software is developed and tested using Windows. This software and its dependencies are compatible across major platforms: Linux, macOS, and Windows. Some dependencies (Flask-SQLAlchemy) may require additional setup.
|
|
40
29
|
|
|
41
30
|
### Python Version
|
|
42
|
-
Python >=3.10 for best compatibility. Python >=3.7 without Ax.
|
|
31
|
+
Python >=3.10 for the best compatibility. Python >=3.7 without Ax.
|
|
43
32
|
### Python dependencies
|
|
44
33
|
This software is compatible with the latest versions of all dependencies.
|
|
45
34
|
- bcrypt~=4.0
|
|
@@ -50,7 +39,9 @@ This software is compatible with the latest versions of all dependencies.
|
|
|
50
39
|
- SQLAlchemy-Utils~=0.41
|
|
51
40
|
- Flask-WTF~=1.2
|
|
52
41
|
- python-dotenv==1.0.1
|
|
53
|
-
- ax-platform (optional
|
|
42
|
+
- ax-platform (optional 1.0 for Python>=3.10)
|
|
43
|
+
- baybe (optional)
|
|
44
|
+
|
|
54
45
|
|
|
55
46
|
## Installation
|
|
56
47
|
```bash
|
|
@@ -74,43 +65,60 @@ import ivoryos
|
|
|
74
65
|
ivoryos.run(__name__)
|
|
75
66
|
```
|
|
76
67
|
### Login
|
|
77
|
-
Create an account and login (local database)
|
|
68
|
+
Create an account and login (local database with bcrypt password)
|
|
78
69
|
### Features
|
|
79
|
-
- **Direct control**: direct function calling
|
|
80
|
-
- **
|
|
81
|
-
- **Design**: add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution page
|
|
82
|
-
- **Execution**: configure iteration methods and parameters in _Compile/Run_ tab.
|
|
83
|
-
- **
|
|
84
|
-
- **
|
|
70
|
+
- **Direct control**: direct function calling _Devices_ tab
|
|
71
|
+
- **Workflows**:
|
|
72
|
+
- **Design Editor**: drag/add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution configuration page
|
|
73
|
+
- **Execution Config**: configure iteration methods and parameters in _Compile/Run_ tab.
|
|
74
|
+
- **Design Library**: manage workflow scripts in _Library_ tab.
|
|
75
|
+
- **Workflow Data**: Execution records are in _Data_ tab.
|
|
85
76
|
|
|
86
77
|
[//]: # ()
|
|
87
78
|
|
|
88
79
|
[//]: # ()
|
|
89
80
|
|
|
90
81
|
|
|
91
|
-
### Additional settings
|
|
92
|
-
#### AI assistant
|
|
93
|
-
To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
|
|
82
|
+
### Additional settings
|
|
83
|
+
[//]: # (#### AI assistant)
|
|
94
84
|
|
|
95
|
-
|
|
96
|
-
1. Create a `.env` file for `OPENAI_API_KEY`
|
|
97
|
-
```
|
|
98
|
-
OPENAI_API_KEY="Your API Key"
|
|
99
|
-
```
|
|
100
|
-
2. In your SDL script, define model, you can use any GPT models.
|
|
85
|
+
[//]: # (To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.)
|
|
101
86
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```
|
|
87
|
+
[//]: # ()
|
|
88
|
+
[//]: # (#### Enable LLMs with [OpenAI API](https://github.com/openai/openai-python))
|
|
105
89
|
|
|
106
|
-
|
|
107
|
-
1. Download Ollama.
|
|
108
|
-
2. pull models from Ollama
|
|
109
|
-
3. In your SDL script, define LLM server and model, you can use any models available on Ollama.
|
|
90
|
+
[//]: # (1. Create a `.env` file for `OPENAI_API_KEY`)
|
|
110
91
|
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
|
|
92
|
+
[//]: # (```)
|
|
93
|
+
|
|
94
|
+
[//]: # (OPENAI_API_KEY="Your API Key")
|
|
95
|
+
|
|
96
|
+
[//]: # (```)
|
|
97
|
+
|
|
98
|
+
[//]: # (2. In your SDL script, define model, you can use any GPT models.)
|
|
99
|
+
|
|
100
|
+
[//]: # ()
|
|
101
|
+
[//]: # (```python)
|
|
102
|
+
|
|
103
|
+
[//]: # (ivoryos.run(__name__, model="gpt-3.5-turbo"))
|
|
104
|
+
|
|
105
|
+
[//]: # (```)
|
|
106
|
+
|
|
107
|
+
[//]: # ()
|
|
108
|
+
[//]: # (#### Enable local LLMs with [Ollama](https://ollama.com/))
|
|
109
|
+
|
|
110
|
+
[//]: # (1. Download Ollama.)
|
|
111
|
+
|
|
112
|
+
[//]: # (2. pull models from Ollama)
|
|
113
|
+
|
|
114
|
+
[//]: # (3. In your SDL script, define LLM server and model, you can use any models available on Ollama.)
|
|
115
|
+
|
|
116
|
+
[//]: # ()
|
|
117
|
+
[//]: # (```python)
|
|
118
|
+
|
|
119
|
+
[//]: # (ivoryos.run(__name__, llm_server="localhost", model="llama3.1"))
|
|
120
|
+
|
|
121
|
+
[//]: # (```)
|
|
114
122
|
|
|
115
123
|
#### Add additional logger(s)
|
|
116
124
|
```python
|
|
@@ -135,7 +143,7 @@ ivoryos.run(__name__)
|
|
|
135
143
|
|
|
136
144
|
* Running on all addresses (0.0.0.0)
|
|
137
145
|
* Running on http://127.0.0.1:8000
|
|
138
|
-
* Running on http://
|
|
146
|
+
* Running on http://0.0.0.0:8000
|
|
139
147
|
|
|
140
148
|
### Deck function and web form
|
|
141
149
|

|
|
@@ -163,6 +171,8 @@ When you run the application for the first time, it will automatically create th
|
|
|
163
171
|
- [x] dropdown input ✅
|
|
164
172
|
- [x] show line number option ✅
|
|
165
173
|
- [ ] snapshot version control
|
|
174
|
+
- [ ] optimizer-agnostic
|
|
175
|
+
- [ ] check batch-config file compatibility
|
|
166
176
|
|
|
167
177
|
## Citing
|
|
168
178
|
|
|
@@ -203,4 +213,4 @@ For an additional perspective related to the development of the tool, please see
|
|
|
203
213
|
## Authors and Acknowledgement
|
|
204
214
|
Ivory Zhang, Lucy Hao
|
|
205
215
|
|
|
206
|
-
Authors acknowledge
|
|
216
|
+
Authors acknowledge Telescope Innovations, Hein Lab members for their valuable suggestions and contributions.
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
+
import uuid
|
|
3
4
|
from typing import Union
|
|
4
5
|
|
|
5
|
-
from flask import Flask, redirect, url_for, g, Blueprint
|
|
6
|
+
from flask import Flask, redirect, url_for, g, Blueprint, session
|
|
7
|
+
from flask_login import AnonymousUserMixin
|
|
8
|
+
|
|
6
9
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
7
10
|
|
|
8
11
|
from ivoryos.config import Config, get_config
|
|
@@ -90,6 +93,23 @@ def create_app(config_class=None):
|
|
|
90
93
|
"""
|
|
91
94
|
g.logger = logger
|
|
92
95
|
g.socketio = socketio
|
|
96
|
+
session.permanent = False
|
|
97
|
+
# DEMO_MODE: Simulate logged-in user per session
|
|
98
|
+
if app.config.get("DEMO_MODE", False):
|
|
99
|
+
if "demo_user_id" not in session:
|
|
100
|
+
session["demo_user_id"] = f"demo_{str(uuid.uuid4())[:8]}"
|
|
101
|
+
|
|
102
|
+
class SessionDemoUser(AnonymousUserMixin):
|
|
103
|
+
@property
|
|
104
|
+
def is_authenticated(self):
|
|
105
|
+
return True
|
|
106
|
+
|
|
107
|
+
def get_id(self):
|
|
108
|
+
return session.get("demo_user_id")
|
|
109
|
+
|
|
110
|
+
login_manager.anonymous_user = SessionDemoUser
|
|
111
|
+
|
|
112
|
+
|
|
93
113
|
|
|
94
114
|
@app.route('/')
|
|
95
115
|
def redirect_to_prefix():
|
|
@@ -101,6 +121,7 @@ def create_app(config_class=None):
|
|
|
101
121
|
text = ' '.join(word for word in name.split('_'))
|
|
102
122
|
return text.capitalize()
|
|
103
123
|
|
|
124
|
+
# app.config.setdefault("DEMO_MODE", False)
|
|
104
125
|
return app
|
|
105
126
|
|
|
106
127
|
|
|
@@ -43,6 +43,7 @@ class TestingConfig(Config):
|
|
|
43
43
|
|
|
44
44
|
class DemoConfig(Config):
|
|
45
45
|
DEBUG = False
|
|
46
|
+
DEMO_MODE = True
|
|
46
47
|
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
|
|
47
48
|
OUTPUT_FOLDER = os.path.join(os.path.abspath(os.curdir), '/tmp/ivoryos_data')
|
|
48
49
|
CSV_FOLDER = os.path.join(OUTPUT_FOLDER, 'config_csv/')
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# optimizers/ax_optimizer.py
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from ivoryos.optimizer.base_optimizer import OptimizerBase
|
|
7
|
+
from ivoryos.utils.utils import install_and_import
|
|
8
|
+
|
|
9
|
+
class AxOptimizer(OptimizerBase):
|
|
10
|
+
def __init__(self, experiment_name, parameter_space, objective_config, optimizer_config=None):
|
|
11
|
+
try:
|
|
12
|
+
from ax.api.client import Client
|
|
13
|
+
except ImportError as e:
|
|
14
|
+
install_and_import("ax", "ax-platform")
|
|
15
|
+
raise ImportError("Please install Ax with pip install ax-platform to use AxOptimizer. Attempting to install Ax...")
|
|
16
|
+
super().__init__(experiment_name, parameter_space, objective_config, optimizer_config)
|
|
17
|
+
|
|
18
|
+
self.client = Client()
|
|
19
|
+
# 2. Configure where Ax will search.
|
|
20
|
+
self.client.configure_experiment(
|
|
21
|
+
name=experiment_name,
|
|
22
|
+
parameters=self._convert_parameter_to_ax_format(parameter_space)
|
|
23
|
+
)
|
|
24
|
+
# 3. Configure the objective function.
|
|
25
|
+
self.client.configure_optimization(objective=self._convert_objective_to_ax_format(objective_config))
|
|
26
|
+
if optimizer_config:
|
|
27
|
+
self.client.set_generation_strategy(self._convert_generator_to_ax_format(optimizer_config))
|
|
28
|
+
self.generators = self._create_generator_mapping()
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _create_generator_mapping():
|
|
32
|
+
"""Create a mapping from string values to Generator enum members."""
|
|
33
|
+
from ax.modelbridge import Generators
|
|
34
|
+
return {member.value: member for member in Generators}
|
|
35
|
+
|
|
36
|
+
def _convert_parameter_to_ax_format(self, parameter_space):
|
|
37
|
+
"""
|
|
38
|
+
Converts the parameter space configuration to Baybe format.
|
|
39
|
+
:param parameter_space: The parameter space configuration.
|
|
40
|
+
[
|
|
41
|
+
{"name": "param_1", "type": "range", "bounds": [1.0, 2.0], "value_type": "float"},
|
|
42
|
+
{"name": "param_2", "type": "choice", "bounds": ["a", "b", "c"], "value_type": "str"},
|
|
43
|
+
{"name": "param_3", "type": "range", "bounds": [0 10], "value_type": "int"},
|
|
44
|
+
]
|
|
45
|
+
:return: A list of Baybe parameters.
|
|
46
|
+
"""
|
|
47
|
+
from ax import RangeParameterConfig, ChoiceParameterConfig
|
|
48
|
+
ax_params = []
|
|
49
|
+
for p in parameter_space:
|
|
50
|
+
if p["type"] == "range":
|
|
51
|
+
ax_params.append(
|
|
52
|
+
RangeParameterConfig(
|
|
53
|
+
name=p["name"],
|
|
54
|
+
bounds=tuple(p["bounds"]),
|
|
55
|
+
parameter_type=p["value_type"]
|
|
56
|
+
))
|
|
57
|
+
elif p["type"] == "choice":
|
|
58
|
+
ax_params.append(
|
|
59
|
+
ChoiceParameterConfig(
|
|
60
|
+
name=p["name"],
|
|
61
|
+
values=p["bounds"],
|
|
62
|
+
parameter_type=p["value_type"],
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
return ax_params
|
|
66
|
+
|
|
67
|
+
def _convert_objective_to_ax_format(self, objective_config: list):
|
|
68
|
+
"""
|
|
69
|
+
Converts the objective configuration to Baybe format.
|
|
70
|
+
:param parameter_space: The parameter space configuration.
|
|
71
|
+
[
|
|
72
|
+
{"name": "obj_1", "minimize": True, "weight": 1},
|
|
73
|
+
{"name": "obj_2", "minimize": False, "weight": 2}
|
|
74
|
+
]
|
|
75
|
+
:return: Ax objective configuration. "-cost, utility"
|
|
76
|
+
"""
|
|
77
|
+
objectives = []
|
|
78
|
+
for obj in objective_config:
|
|
79
|
+
obj_name = obj.get("name")
|
|
80
|
+
minimize = obj.get("minimize", True)
|
|
81
|
+
weight = obj.get("weight", 1)
|
|
82
|
+
sign = "-" if minimize else ""
|
|
83
|
+
objectives.append(f"{sign}{weight} * {obj_name}")
|
|
84
|
+
return ", ".join(objectives)
|
|
85
|
+
|
|
86
|
+
def _convert_generator_to_ax_format(self, optimizer_config):
|
|
87
|
+
"""
|
|
88
|
+
Converts the optimizer configuration to Ax format.
|
|
89
|
+
:param optimizer_config: The optimizer configuration.
|
|
90
|
+
:return: Ax generator configuration.
|
|
91
|
+
"""
|
|
92
|
+
from ax.generation_strategy.generation_node import GenerationStep
|
|
93
|
+
from ax.generation_strategy.generation_strategy import GenerationStrategy
|
|
94
|
+
generators = self._create_generator_mapping()
|
|
95
|
+
step_1 = optimizer_config.get("step_1", {})
|
|
96
|
+
step_2 = optimizer_config.get("step_2", {})
|
|
97
|
+
step_1_generator = step_1.get("model", "Sobol")
|
|
98
|
+
step_2_generator = step_2.get("model", "BOTorch")
|
|
99
|
+
generator_1 = GenerationStep(model=generators.get(step_1_generator), num_trials=step_1.get("num_samples", 5))
|
|
100
|
+
generator_2 = GenerationStep(model=generators.get(step_2_generator), num_trials=step_2.get("num_samples", -1))
|
|
101
|
+
return GenerationStrategy(steps=[generator_1, generator_2])
|
|
102
|
+
|
|
103
|
+
def suggest(self, n=1):
|
|
104
|
+
trial_index, params = self.client.get_next_trials(1).popitem()
|
|
105
|
+
self.trial_index = trial_index
|
|
106
|
+
return params
|
|
107
|
+
|
|
108
|
+
def observe(self, results):
|
|
109
|
+
self.client.complete_trial(
|
|
110
|
+
trial_index=self.trial_index,
|
|
111
|
+
raw_data=results
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def get_schema():
|
|
116
|
+
return {
|
|
117
|
+
"parameter_types": ["range", "choice"],
|
|
118
|
+
"multiple_objectives": True,
|
|
119
|
+
# "objective_weights": True,
|
|
120
|
+
"optimizer_config": {
|
|
121
|
+
"step_1": {"model": ["Sobol", "Uniform", "Factorial", "Thompson"], "num_samples": 5},
|
|
122
|
+
"step_2": {"model": ["BoTorch", "SAASBO", "SAAS_MTGP", "Legacy_GPEI", "EB", "EB_Ashr", "ST_MTGP", "BO_MIXED", "Contextual_SACBO"]}
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
def append_existing_data(self, existing_data):
|
|
127
|
+
"""
|
|
128
|
+
Append existing data to the Ax experiment.
|
|
129
|
+
:param existing_data: A dictionary containing existing data.
|
|
130
|
+
"""
|
|
131
|
+
from pandas import DataFrame
|
|
132
|
+
if not existing_data:
|
|
133
|
+
return
|
|
134
|
+
if isinstance(existing_data, DataFrame):
|
|
135
|
+
existing_data = existing_data.to_dict(orient="records")
|
|
136
|
+
parameter_names = [i.get("name") for i in self.parameter_space]
|
|
137
|
+
objective_names = [i.get("name") for i in self.objective_config]
|
|
138
|
+
for name, value in existing_data.items():
|
|
139
|
+
# First attach the trial and note the trial index
|
|
140
|
+
parameters = {name: value for name in existing_data if name in parameter_names}
|
|
141
|
+
trial_index = self.client.attach_trial(parameters=parameters)
|
|
142
|
+
raw_data = {name: value for name in existing_data if name in objective_names}
|
|
143
|
+
# Then complete the trial with the existing data
|
|
144
|
+
self.client.complete_trial(trial_index=trial_index, raw_data=raw_data)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
# Example usage
|
|
149
|
+
optimizer = AxOptimizer(
|
|
150
|
+
experiment_name="example_experiment",
|
|
151
|
+
parameter_space=[
|
|
152
|
+
{"name": "param_1", "type": "range", "bounds": [0.0, 1.0], "value_type": "float"},
|
|
153
|
+
{"name": "param_2", "type": "choice", "bounds": ["a", "b", "c"], "value_type": "str"}
|
|
154
|
+
],
|
|
155
|
+
objective_config=[
|
|
156
|
+
{"name": "objective_1", "minimize": True},
|
|
157
|
+
{"name": "objective_2", "minimize": False}
|
|
158
|
+
],
|
|
159
|
+
optimizer_config={
|
|
160
|
+
"step_1": {"model": "Sobol", "num_samples": 5},
|
|
161
|
+
"step_2": {"model": "BoTorch"}
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
print(optimizer._create_generator_mapping())
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
### ivoryos/optimizers/base.py
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OptimizerBase(ABC):
|
|
8
|
+
def __init__(self, experiment_name:str, parameter_space: list, objective_config: dict, optimizer_config: dict):
|
|
9
|
+
"""
|
|
10
|
+
:param experiment_name: arbitrary name
|
|
11
|
+
:param parameter_space: list of parameter names
|
|
12
|
+
[
|
|
13
|
+
{"name": "param_1", "type": "range", "bounds": [1.0, 2.0], "value_type": "float"},
|
|
14
|
+
{"name": "param_2", "type": "choice", "bounds": ["a", "b", "c"], "value_type": "str"},
|
|
15
|
+
{"name": "param_3", "type": "range", "bounds": [0 10], "value_type": "int"},
|
|
16
|
+
]
|
|
17
|
+
:param objective_config: objective configuration
|
|
18
|
+
[
|
|
19
|
+
{"name": "obj_1", "minimize": True, "weight": 1},
|
|
20
|
+
{"name": "obj_2", "minimize": False, "weight": 1}
|
|
21
|
+
]
|
|
22
|
+
:param optimizer_config: optimizer configuration
|
|
23
|
+
optimizer_config={
|
|
24
|
+
"step_1": {"model": "Random", "num_samples": 10},
|
|
25
|
+
"step_2": {"model": "BOTorch"}
|
|
26
|
+
}
|
|
27
|
+
"""
|
|
28
|
+
self.experiment_name = experiment_name
|
|
29
|
+
self.parameter_space = parameter_space
|
|
30
|
+
self.objective_config = objective_config
|
|
31
|
+
self.optimizer_config = optimizer_config
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def suggest(self, n=1):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def observe(self, results: dict):
|
|
39
|
+
"""
|
|
40
|
+
observe
|
|
41
|
+
:param results: {"objective_name": "value"}
|
|
42
|
+
"""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def append_existing_data(self, existing_data):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def get_schema():
|
|
51
|
+
"""
|
|
52
|
+
Returns a template for the optimizer configuration.
|
|
53
|
+
"""
|
|
54
|
+
return {
|
|
55
|
+
"parameter_types": ["range", "choice"],
|
|
56
|
+
"multiple_objectives": True,
|
|
57
|
+
# "objective_weights": True,
|
|
58
|
+
"optimizer_config": {
|
|
59
|
+
"step_1": {"model": [], "num_samples": 10},
|
|
60
|
+
"step_2": {"model": []}
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|