agi-gui 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
agi_gui/AGILAB.py ADDED
@@ -0,0 +1,544 @@
1
+ # BSD 3-Clause License
2
+ #
3
+ # Copyright (c) 2025, Jean-Pierre Morard, THALES SIX GTS France SAS
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+ # 3. Neither the name of Jean-Pierre Morard nor the names of its contributors, or THALES SIX GTS France SAS, may be used to endorse or promote products derived from this software without specific prior written permission.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13
+
14
+ from pathlib import Path
15
+ from datetime import datetime
16
+ import streamlit as st
17
+ import importlib
18
+ import base64
19
+ import sys
20
+ import os
21
+ import argparse
22
+
23
+ # -------------------- Import Statements -------------------- #
24
+ # (Include any other necessary imports from your original code)
25
+ from agi_gui.pagelib import env, get_about_content, render_logo, open_docs, RESOURCE_PATH, get_base64_of_image
26
+
27
+ # -------------------- Import Statements -------------------- #
28
+ import ast
29
+ from datetime import datetime
30
+ import re
31
+ import json
32
+ import glob
33
+ from pathlib import Path, PurePosixPath, PureWindowsPath
34
+ from functools import lru_cache
35
+ import pandas as pd
36
+ import toml
37
+ import os
38
+ import io
39
+ import subprocess
40
+ import streamlit as st
41
+ import random
42
+ import socket
43
+ from PIL import Image
44
+ import base64
45
+ import runpy
46
+ from typing import List, Union, Optional, Dict
47
+ import sys
48
+ import importlib
49
+
50
+ def add_custom_css():
51
+ """
52
+ Loads and injects external CSS into the Streamlit app.
53
+ """
54
+ css_path = RESOURCE_PATH / "first_page.css"
55
+ css_content = load_file_content(css_path)
56
+ if css_content:
57
+ st.markdown(f"<style>{css_content}</style>", unsafe_allow_html=True)
58
+
59
+
60
+ def display_landing_page():
61
+ """
62
+ Loads and displays the landing page Markdown content.
63
+ """
64
+
65
+ img_data = get_base64_of_image(RESOURCE_PATH / "agi_logo.png")
66
+ img_src = f"data:image/png;base64,{img_data}"
67
+ md_content = f"""
68
+ <div style="background-color: #333333; padding: 20px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); max-width: 800px; margin: 20px auto;">
69
+ <div style="display: flex; align-items: center; justify-content: center;">
70
+ <h1 style="margin: 0; padding: 0 10px 0 0;">
71
+ Welcome to AGILAB
72
+ </h1>
73
+ <img src="{img_src}" alt="AGI Logo" style="width:100px;">
74
+ </div>
75
+ <div style="text-align: center;">
76
+ <strong style="color: black;">a step further toward AGI</strong>
77
+ </div>
78
+ </div>
79
+
80
+ <div class="uvp-highlight">
81
+ <strong>Founding Concept:</strong> AGILAB outlines a method for scaling into a project’s execution environment without the need for virtualization or containerization (such as Docker). The approach involves encapsulating an app's logic into two components: a worker (which is scalable and free from dependency constraints) and a manager (which is easily integrable due to minimal dependency requirements). This design enables seamless integration within a single app, contributing to the move toward Artificial General Intelligence (AGI).
82
+ </div>
83
+
84
+ <div class="uvp-highlight">
85
+ <strong>AGILAB</strong>: Revolutionizing Data Science Experimentation with Zero Integration Hassles. As a comprehensive framework built on 50KLOC of pure Python and powered by Gen AI and ML, AGILAB scales effortlessly—from embedded systems to the cloud—empowering seamless collaboration on data insights and predictive modeling.
86
+ </div>
87
+
88
+ <p><strong>Key Features:</strong></p>
89
+ <ul>
90
+ <li><strong>Strong AI Enabler</strong>: Algos Integrations.</li>
91
+ <li><strong>Engineering AI Enabler</strong>: Feature Engineering.</li>
92
+ <li><strong>Availability</strong>: Works online and in standalone mode.</li>
93
+ <li><strong>Enhanced Deployment Productivity</strong>: Automates virtual environment deployment.</li>
94
+ <li><strong>Enhanced Coding Productivity</strong>: Seamless integration with openai-api.</li>
95
+ <li><strong>Enhanced Scalability</strong>: Distributes both data and algorithms on a cluster.</li>
96
+ <li><strong>User-Friendly Interface for Data Science</strong>: Integration of Jupyter-ai and ML Flow.</li>
97
+ <li><strong>Advanced Execution Tools</strong>: Enables Map Reduce and Direct Acyclic Graph Orchestration.</li>
98
+ </ul>
99
+
100
+ <p>
101
+ With AGILAB, there’s no need for additional integration—our all-in-one framework is ready to deploy, enabling you to focus on innovation rather than setup.
102
+ </p>
103
+
104
+ <div class="uvp-highlight">
105
+ <strong>Tips:</strong> To benefit from AGI cluster automation functionality, all you need is <strong>agi-core</strong> and <strong>agi-env</strong>. This means you can remove the lab and view directories. Historically, AGILAB was developed as a playground for agi-core.
106
+ </div>
107
+ """
108
+
109
+ st.markdown(md_content, unsafe_allow_html=True)
110
+
111
+
112
+ # -------------------- Additional Functions (e.g., logo rendering) -------------------- #
113
+ def render_logo_with_columns():
114
+ """
115
+ Renders the agi logo centered on the main page using columns.
116
+ """
117
+ logo_path = (
118
+ RESOURCE_PATH / "agi_logo.png"
119
+ ) # Adjust the path if necessary
120
+ logo = Image.open(logo_path)
121
+
122
+ # Create three columns with ratios: 1:2:1
123
+ left_col, middle_col, right_col = st.columns([1, 2, 1])
124
+
125
+ with middle_col:
126
+ st.write("")
127
+ st.write("")
128
+ st.image(logo, width=200) # Adjust width as needed
129
+
130
+
131
+ def load_file_content(file_path: Path) -> str:
132
+ """
133
+ Reads the content of a file.
134
+ """
135
+ try:
136
+ with open(file_path, "r", encoding="utf-8") as f:
137
+ return f.read()
138
+ except Exception as e:
139
+ st.error(f"Error loading {file_path}: {e}")
140
+ return ""
141
+
142
+
143
+ # -------------------- Custom CSS Styling -------------------- #
144
+ def add_custom_css():
145
+ """
146
+ Add custom CSS styles to the Streamlit app.
147
+
148
+ This function adds custom CSS styles to the Streamlit app to customize the appearance of the page.
149
+
150
+ Args:
151
+ None
152
+
153
+ Returns:
154
+ None
155
+
156
+ Raises:
157
+ None
158
+ """
159
+ custom_css = """
160
+ <style>
161
+ /* Set the background color for the entire page */
162
+ .reportview-container {
163
+ background-color: white; /* Light grey background for a clean look */
164
+ }
165
+ /* Set the background color for the sidebar */
166
+ .sidebar .sidebar-content {
167
+ background-color: white; /* White sidebar for contrast */
168
+ }
169
+ /* Style for header section */
170
+ .header {
171
+ background-color: #1E90FF; /* Primary Blue aligning with :one: emoji */
172
+ padding: 40px 20px;
173
+ text-align: left;
174
+ }
175
+ /* Style for main headers */
176
+ .header h1 {
177
+ color: white; /* White title */
178
+ font-family: 'Helvetica', sans-serif;
179
+ font-weight: bold;
180
+ font-size: 48px;
181
+ margin-bottom: 10px;
182
+ }
183
+
184
+ /* Style for footer */
185
+ .footer {
186
+ position: fixed;
187
+ left: 0;
188
+ bottom: 0;
189
+ width: 100%;
190
+ background-color: #1E90FF; /* Primary Blue */
191
+ color: white;
192
+ text-align: center;
193
+ padding: 10px 0;
194
+ font-family: 'Helvetica', sans-serif;
195
+ font-size: 14px;
196
+ }
197
+
198
+ /* Hide Streamlit's default hamburger menu and footer */
199
+ footer {visibility: hidden;}
200
+
201
+ /* New CSS class for UVP highlighting */
202
+ .uvp-highlight {
203
+ background-color: #f0f8ff; /* Light Blue Background */
204
+ color: #333333; /* Dark Text for Contrast */
205
+ padding: 20px; /* Inner Padding */
206
+ border-left: 5px solid #1E90FF; /* Blue Border on the Left */
207
+ border-radius: 5px; /* Rounded Corners */
208
+ margin-top: 20px; /* Top Margin */
209
+ margin-bottom: 20px; /* Bottom Margin */
210
+ font-size: 18px; /* Font Size */
211
+ line-height: 1.6; /* Line Height for Readability */
212
+ }
213
+
214
+ /* Optional: Adjust list styles within UVP */
215
+ .uvp-highlight ul {
216
+ list-style-type: disc;
217
+ margin-left: 20px;
218
+ }
219
+
220
+ /* Optional: Enhance the visibility of strong tags within UVP */
221
+ .uvp-highlight strong {
222
+ color: #1E90FF; /* Blue Color for Emphasis */
223
+ }
224
+ </style>
225
+ """
226
+ st.markdown(custom_css, unsafe_allow_html=True)
227
+
228
+
229
+ # -------------------- Exception Class -------------------- #
230
+ class JumpToMain(Exception):
231
+ """
232
+ Custom exception to jump back to the main execution flow.
233
+ """
234
+
235
+ pass
236
+
237
+
238
+ # -------------------- Initialize Page Configuration -------------------- #
239
+
240
+ # Load your logo from a file
241
+ agi_logo = Image.open(RESOURCE_PATH / "agi_logo.png")
242
+
243
+ # Ensure this is the very first Streamlit command after imports and function definitions
244
+ st.set_page_config(
245
+ menu_items=get_about_content(), # Adjust if necessary
246
+ layout="wide"
247
+ )
248
+
249
+ # -------------------- Inject Custom CSS -------------------- #
250
+ add_custom_css()
251
+
252
+
253
+ # -------------------- Render Logos -------------------- #
254
+ # Render the logo in the sidebar
255
+ # render_logo()
256
+
257
+
258
+ # -------------------- Streamlit Page Rendering -------------------- #
259
+ def page():
260
+ # Override the default .block-container styling
261
+ """
262
+ Display a landing page for AGILAB.
263
+ """
264
+ # Display landing page content from external Markdown file
265
+ display_landing_page()
266
+
267
+ cols = st.columns(2)
268
+ help_file = env.help_path / "index.html"
269
+ if cols[0].button("Read Documentation", type="tertiary", use_container_width=True):
270
+ open_docs(env, help_file, "project-editor")
271
+
272
+ # Add a button to proceed
273
+ if cols[1].button("Get Started", type="tertiary", use_container_width=True):
274
+ st.write("Redirecting to the main application...")
275
+ # Set the current page to '▶️ EDIT' and rerun the app
276
+ st.session_state.current_page = "▶️ EDIT"
277
+ st.query_params["current_page"] = "▶️ EDIT"
278
+ st.rerun()
279
+
280
+ # Footer with custom styling
281
+ current_year = datetime.now().year
282
+ st.markdown(
283
+ f"""
284
+ <div class='footer'>
285
+ &copy; 2020-{current_year} Thales SIX GTS. All rights reserved.
286
+ </div>
287
+ """,
288
+ unsafe_allow_html=True,
289
+ )
290
+
291
+
292
+ # -------------------- Main Application Entry -------------------- #
293
+ import argparse
294
+ import sys
295
+ import os
296
+ from pathlib import Path
297
+ from datetime import datetime
298
+ import streamlit as st
299
+ import importlib
300
+
301
+ # -------------------- Import Statements -------------------- #
302
+ from agi_gui.pagelib import (
303
+ env,
304
+ get_about_content,
305
+ render_logo,
306
+ open_docs,
307
+ RESOURCE_PATH,
308
+ get_base64_of_image,
309
+ )
310
+
311
+ # Additional imports
312
+ import ast
313
+ import re
314
+ import json
315
+ import glob
316
+ from pathlib import PurePosixPath, PureWindowsPath
317
+ from functools import lru_cache
318
+ import pandas as pd
319
+ import toml
320
+ import io
321
+ import subprocess
322
+ import random
323
+ import socket
324
+ from PIL import Image
325
+ import base64
326
+ import runpy
327
+ from typing import List, Union, Optional, Dict
328
+
329
+ # -------------------- Helper Functions -------------------- #
330
+
331
+ def add_custom_css():
332
+ """
333
+ Loads and injects external CSS into the Streamlit app.
334
+ """
335
+ css_path = RESOURCE_PATH / "first_page.css"
336
+ css_content = load_file_content(css_path)
337
+ if css_content:
338
+ st.markdown(f"<style>{css_content}</style>", unsafe_allow_html=True)
339
+
340
+ def load_file_content(file_path: Path) -> str:
341
+ """
342
+ Reads the content of a file.
343
+ """
344
+ try:
345
+ with open(file_path, "r", encoding="utf-8") as f:
346
+ return f.read()
347
+ except Exception as e:
348
+ st.error(f"Error loading {file_path}: {e}")
349
+ return ""
350
+
351
+ def display_landing_page():
352
+ """
353
+ Loads and displays the landing page Markdown content.
354
+ """
355
+ img_data = get_base64_of_image(RESOURCE_PATH / "agi_logo.png")
356
+ img_src = f"data:image/png;base64,{img_data}"
357
+ md_content = f"""
358
+ <div style="background-color: #333333; padding: 20px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); max-width: 800px; margin: 20px auto;">
359
+ <div style="display: flex; align-items: center; justify-content: center;">
360
+ <h1 style="margin: 0; padding: 0 10px 0 0;">Welcome to AGILAB</h1>
361
+ <img src="{img_src}" alt="AGI Logo" style="width:100px;">
362
+ </div>
363
+ <div style="text-align: center;">
364
+ <strong style="color: black;">a step further toward AGI</strong>
365
+ </div>
366
+ </div>
367
+ <div class="uvp-highlight">
368
+ <strong>Founding Concept:</strong> AGILAB outlines a method for scaling into a project’s execution environment without the need for virtualization or containerization (such as Docker). The approach involves encapsulating an app's logic into two components: a worker (which is scalable and free from dependency constraints) and a manager (which is easily integrable due to minimal dependency requirements). This design enables seamless integration within a single app, contributing to the move toward Artificial General Intelligence (AGI).
369
+ </div>
370
+ <div class="uvp-highlight">
371
+ <strong>AGILAB</strong>: Revolutionizing Data Science Experimentation with Zero Integration Hassles. As a comprehensive framework built on 50KLOC of pure Python and powered by Gen AI and ML, AGILAB scales effortlessly—from embedded systems to the cloud—empowering seamless collaboration on data insights and predictive modeling.
372
+ </div>
373
+ <p><strong>Key Features:</strong></p>
374
+ <ul>
375
+ <li><strong>Strong AI Enabler</strong>: Algos Integrations.</li>
376
+ <li><strong>Engineering AI Enabler</strong>: Feature Engineering.</li>
377
+ <li><strong>Availability</strong>: Works online and in standalone mode.</li>
378
+ <li><strong>Enhanced Deployment Productivity</strong>: Automates virtual environment deployment.</li>
379
+ <li><strong>Enhanced Coding Productivity</strong>: Seamless integration with openai-api.</li>
380
+ <li><strong>Enhanced Scalability</strong>: Distributes both data and algorithms on a cluster.</li>
381
+ <li><strong>User-Friendly Interface for Data Science</strong>: Integration of Jupyter-ai and ML Flow.</li>
382
+ <li><strong>Advanced Execution Tools</strong>: Enables Map Reduce and Direct Acyclic Graph Orchestration.</li>
383
+ </ul>
384
+ <p>
385
+ With AGILAB, there’s no need for additional integration—our all-in-one framework is ready to deploy, enabling you to focus on innovation rather than setup.
386
+ </p>
387
+ <div class="uvp-highlight">
388
+ <strong>Tips:</strong> To benefit from AGI cluster automation functionality, all you need is <strong>agi-core</strong> and <strong>agi-env</strong>. This means you can remove the lab and view directories. Historically, AGILAB was developed as a playground for agi-core.
389
+ </div>
390
+ """
391
+ st.markdown(md_content, unsafe_allow_html=True)
392
+
393
+ def page():
394
+ """
395
+ Display the landing page for AGILAB.
396
+ """
397
+ display_landing_page()
398
+ cols = st.columns(2)
399
+ help_file = st.session_state["env"].help_path / "index.html"
400
+ if cols[0].button("Read Documentation", type="tertiary", use_container_width=True):
401
+ open_docs(st.session_state["env"], help_file, "project-editor")
402
+ if cols[1].button("Get Started", type="tertiary", use_container_width=True):
403
+ st.write("Redirecting to the main application...")
404
+ st.session_state.current_page = "▶️ EDIT"
405
+ st.rerun()
406
+ current_year = datetime.now().year
407
+ st.markdown(
408
+ f"""
409
+ <div class='footer'>
410
+ &copy; 2020-{current_year} Thales SIX GTS. All rights reserved.
411
+ </div>
412
+ """,
413
+ unsafe_allow_html=True,
414
+ )
415
+
416
+ def read_env_key(key: str) -> str:
417
+ """
418
+ Look for the given key in os.environ, then in ~/.agilab/.env.
419
+ Return the value if found (and non-empty), otherwise return an empty string.
420
+ """
421
+ # 1. Check os.environ
422
+ value = os.environ.get(key, "").strip()
423
+ if value:
424
+ return value
425
+
426
+ # 2. Check ~/.agilab/.env file if it exists
427
+ env_file = Path.home() / ".agilab" / ".env"
428
+ if env_file.exists():
429
+ with env_file.open("r") as f:
430
+ for line in f:
431
+ if '=' in line:
432
+ k, v = line.strip().split('=', 1)
433
+ if k == key and v.strip():
434
+ return v.strip()
435
+ return ""
436
+
437
+ # -------------------- Main Application Entry -------------------- #
438
+ def main():
439
+ """
440
+ Main function to run the application.
441
+ """
442
+ # --- Command-Line Argument Parsing ---
443
+ parser = argparse.ArgumentParser(
444
+ description="Run the AGI Streamlit App with optional parameters."
445
+ )
446
+ parser.add_argument(
447
+ "--cluster-credentials",
448
+ type=str,
449
+ help="Cluster credentials (username:password)",
450
+ default=None
451
+ )
452
+ parser.add_argument(
453
+ "--openai-api-key",
454
+ type=str,
455
+ help="OpenAI API key (mandatory)",
456
+ default=None
457
+ )
458
+ args, unknown = parser.parse_known_args()
459
+
460
+ # Try to get the values from os.environ or the .env file first.
461
+ openai_api_key = read_env_key("OPENAI_API_KEY")
462
+ if not openai_api_key:
463
+ # If not found in environment or .env, override with CLI argument if provided.
464
+ openai_api_key = args.openai_api_key
465
+ if not openai_api_key:
466
+ openai_api_key = input("Enter OpenAI API key: ").strip()
467
+ if not openai_api_key:
468
+ print("Error: Missing mandatory parameter: --openai-api-key")
469
+ sys.exit(1)
470
+
471
+ cluster_credentials = read_env_key("CLUSTER_CREDENTIALS")
472
+ if not cluster_credentials:
473
+ cluster_credentials = args.cluster_credentials
474
+ if not cluster_credentials:
475
+ # Prompt for cluster info only if not found
476
+ cluster_enabled = input("Is cluster available? [N/y]: ").strip().lower() or "n"
477
+ if cluster_enabled == "y":
478
+ ssh_key_set = input("Is SSH key set? [N/y]: ").strip().lower() or "n"
479
+ if ssh_key_set == "y":
480
+ cluster_credentials = input("Enter user (SSH key is set): ").strip()
481
+ else:
482
+ cluster_credentials = input("Enter cluster credentials (user:password): ").strip()
483
+ else:
484
+ cluster_credentials = ""
485
+
486
+ # Store the final values in the environment
487
+ os.environ["OPENAI_API_KEY"] = openai_api_key
488
+ os.environ["CLUSTER_CREDENTIALS"] = cluster_credentials
489
+
490
+ # Update or create the .agilab/.env file if the keys are not already present
491
+ env_file = Path.home() / ".agilab" / ".env"
492
+ env_file.parent.mkdir(parents=True, exist_ok=True)
493
+ current = {}
494
+ if env_file.exists():
495
+ with env_file.open("r") as f:
496
+ for line in f:
497
+ if '=' in line:
498
+ k, v = line.strip().split('=', 1)
499
+ current[k] = v
500
+ with env_file.open("a") as f:
501
+ if "OPENAI_API_KEY" not in current or not current["OPENAI_API_KEY"]:
502
+ f.write(f"OPENAI_API_KEY={openai_api_key}\n")
503
+ if "CLUSTER_CREDENTIALS" not in current or not current["CLUSTER_CREDENTIALS"]:
504
+ f.write(f"CLUSTER_CREDENTIALS={cluster_credentials}\n")
505
+
506
+ # Adjust sys.path to include agi_env if needed.
507
+ path_agi_env = Path("fwk/env/src").resolve()
508
+ path_agi = str(path_agi_env)
509
+ if path_agi not in sys.path:
510
+ sys.path.insert(0, path_agi)
511
+ from agi_env.agi_env import AgiEnv
512
+
513
+ # -------------------- Global Configurations -------------------- #
514
+ treshold = 1
515
+ snippet_run_error = "fail to run your python snippet"
516
+ env_obj = AgiEnv("flight", with_lab=True, verbose=True)
517
+ st.session_state["env"] = env_obj
518
+ default_steps_file = "steps.toml"
519
+ default_df = "export.csv"
520
+ st.session_state["rapids_default"] = True
521
+
522
+
523
+ # -------------------- Navigation and Page Rendering -------------------- #
524
+ try:
525
+ if "current_page" not in st.session_state:
526
+ st.session_state.current_page = "AGILAB"
527
+
528
+ if st.session_state.current_page == "AGILAB":
529
+ st.session_state.current_page = None
530
+ page()
531
+ elif st.session_state.current_page == "▶️ EDIT":
532
+ st.session_state.current_page = None
533
+ page_module = importlib.import_module("pages.▶️ EDIT")
534
+ page_module.main()
535
+ else:
536
+ page()
537
+ except Exception as e:
538
+ st.error(f"An error occurred: {e}")
539
+ import traceback
540
+ st.error(traceback.format_exc())
541
+
542
+ # -------------------- Run the App -------------------- #
543
+ if __name__ == "__main__":
544
+ main()
agi_gui/__init__.py ADDED
File without changes
agi_gui/agi_copilot.py ADDED
@@ -0,0 +1,33 @@
1
+ # BSD 3-Clause License
2
+ #
3
+ # Copyright (c) 2025, Jean-Pierre Morard, THALES SIX GTS France SAS
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+ # 3. Neither the name of Jean-Pierre Morard nor the names of its contributors, or THALES SIX GTS France SAS, may be used to endorse or promote products derived from this software without specific prior written permission.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13
+
14
+ import traceback
15
+
16
+ import streamlit as st
17
+
18
+ df = st.session_state.loaded_df
19
+ snippet_file = st.session_state.snippet_file
20
+
21
+ with open(snippet_file, "r") as snippet:
22
+ try:
23
+ exec(snippet.read())
24
+
25
+ except KeyError as err:
26
+ raise KeyError(
27
+ f"{snippet_file}: columns name {err.args[0]} is not present in the dateframe, "
28
+ f"please rename it with a name of a column already in the dataset"
29
+ ) from err
30
+
31
+ except Exception as err:
32
+ st.error(f"```{snippet_file}: {err}\n{traceback.format_exc()}```")
33
+ st.session_state.data = df
agi_gui/lab_run.py ADDED
@@ -0,0 +1,63 @@
1
+ import argparse
2
+ import sys
3
+ from pathlib import Path
4
+ import streamlit.web.cli as stcli
5
+
6
+ def check_environment():
7
+
8
+ # Check if current directory is acceptable:
9
+ cwd = Path.cwd()
10
+ # For example, accept if the cwd contains 'pyproject.toml'
11
+ if not (cwd / "pyproject.toml").exists() and "agilab/src/fwk/gui" not in str(cwd):
12
+ print("Error: Please run this command from a directory that contains your agilab project (e.g. the project root or agilab/src/fwk/gui).")
13
+ sys.exit(1)
14
+
15
+ # Check if the package is installed (optional):
16
+ try:
17
+ import agi_gui # or any module from your package
18
+ except ImportError:
19
+ print("Error: The agilab package is not installed in this environment.")
20
+ sys.exit(1)
21
+
22
+ def main():
23
+
24
+ check_environment()
25
+
26
+ parser = argparse.ArgumentParser(
27
+ description="Run AGILAB application with custom options."
28
+ )
29
+ parser.add_argument(
30
+ "--cluster-credentials", type=str, help="Cluster account user:password", default=None
31
+ )
32
+ parser.add_argument(
33
+ "--openai-api-key", type=str, help="OpenAI API key", default=None
34
+ )
35
+ # Parse known arguments; extra arguments are captured in `unknown`
36
+ args, unknown = parser.parse_known_args()
37
+
38
+ # Determine the target script (adjust path if necessary)
39
+ target_script = str(Path(__file__).parent / "AGILAB.py")
40
+
41
+ # Build the base argument list for Streamlit.
42
+ new_argv = ["streamlit", "run", target_script]
43
+
44
+ # Collect custom arguments.
45
+ custom_args = []
46
+ if args.cluster_credentials is not None:
47
+ custom_args.extend(["--cluster-credentials", args.cluster_credentials])
48
+ if args.openai_api_key is not None:
49
+ custom_args.extend(["--openai-api-key", args.openai_api_key])
50
+ if unknown:
51
+ custom_args.extend(unknown)
52
+
53
+ # Only add the double dash and custom arguments if there are any.
54
+ if custom_args:
55
+ new_argv.append("--")
56
+ new_argv.extend(custom_args)
57
+
58
+ sys.argv = new_argv
59
+ sys.exit(stcli.main())
60
+
61
+
62
+ if __name__ == "__main__":
63
+ main()