syntaxmatrix 2.5.5.5__py3-none-any.whl → 2.6.2__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.
- syntaxmatrix/__init__.py +3 -2
- syntaxmatrix/agentic/agents.py +1220 -169
- syntaxmatrix/agentic/agents_orchestrer.py +326 -0
- syntaxmatrix/agentic/code_tools_registry.py +27 -32
- syntaxmatrix/auth.py +142 -5
- syntaxmatrix/commentary.py +16 -16
- syntaxmatrix/core.py +192 -84
- syntaxmatrix/db.py +460 -4
- syntaxmatrix/{display.py → display_html.py} +2 -6
- syntaxmatrix/gpt_models_latest.py +1 -1
- syntaxmatrix/media/__init__.py +0 -0
- syntaxmatrix/media/media_pixabay.py +277 -0
- syntaxmatrix/models.py +1 -1
- syntaxmatrix/page_builder_defaults.py +183 -0
- syntaxmatrix/page_builder_generation.py +1122 -0
- syntaxmatrix/page_layout_contract.py +644 -0
- syntaxmatrix/page_patch_publish.py +1471 -0
- syntaxmatrix/preface.py +670 -0
- syntaxmatrix/profiles.py +28 -10
- syntaxmatrix/routes.py +1941 -593
- syntaxmatrix/selftest_page_templates.py +360 -0
- syntaxmatrix/settings/client_items.py +28 -0
- syntaxmatrix/settings/model_map.py +1022 -207
- syntaxmatrix/settings/prompts.py +328 -130
- syntaxmatrix/static/assets/hero-default.svg +22 -0
- syntaxmatrix/static/icons/bot-icon.png +0 -0
- syntaxmatrix/static/icons/favicon.png +0 -0
- syntaxmatrix/static/icons/logo.png +0 -0
- syntaxmatrix/static/icons/logo3.png +0 -0
- syntaxmatrix/templates/admin_branding.html +104 -0
- syntaxmatrix/templates/admin_features.html +63 -0
- syntaxmatrix/templates/admin_secretes.html +108 -0
- syntaxmatrix/templates/change_password.html +124 -0
- syntaxmatrix/templates/dashboard.html +296 -131
- syntaxmatrix/templates/dataset_resize.html +535 -0
- syntaxmatrix/templates/edit_page.html +2535 -0
- syntaxmatrix/utils.py +2728 -2835
- {syntaxmatrix-2.5.5.5.dist-info → syntaxmatrix-2.6.2.dist-info}/METADATA +6 -2
- {syntaxmatrix-2.5.5.5.dist-info → syntaxmatrix-2.6.2.dist-info}/RECORD +42 -25
- syntaxmatrix/generate_page.py +0 -634
- syntaxmatrix/static/icons/hero_bg.jpg +0 -0
- {syntaxmatrix-2.5.5.5.dist-info → syntaxmatrix-2.6.2.dist-info}/WHEEL +0 -0
- {syntaxmatrix-2.5.5.5.dist-info → syntaxmatrix-2.6.2.dist-info}/licenses/LICENSE.txt +0 -0
- {syntaxmatrix-2.5.5.5.dist-info → syntaxmatrix-2.6.2.dist-info}/top_level.txt +0 -0
syntaxmatrix/core.py
CHANGED
|
@@ -16,7 +16,6 @@ from .file_processor import process_admin_pdf_files
|
|
|
16
16
|
from google.genai import types
|
|
17
17
|
from .vector_db import query_embeddings
|
|
18
18
|
from .vectorizer import embed_text
|
|
19
|
-
from syntaxmatrix.settings.prompts import SMXAI_CHAT_ID, SMXAI_CHAT_INSTRUCTIONS, SMXAI_WEBSITE_DESCRIPTION
|
|
20
19
|
from typing import List, Generator
|
|
21
20
|
from .auth import init_auth_db
|
|
22
21
|
from . import profiles as _prof
|
|
@@ -28,20 +27,26 @@ from html import unescape
|
|
|
28
27
|
from .plottings import render_plotly, pyplot, describe_plotly, describe_matplotlib
|
|
29
28
|
from threading import RLock
|
|
30
29
|
from syntaxmatrix.settings.model_map import GPT_MODELS_LATEST
|
|
31
|
-
|
|
30
|
+
from syntaxmatrix.settings.prompts import(
|
|
31
|
+
SMXAI_CHAT_IDENTITY,
|
|
32
|
+
SMXAI_CHAT_INSTRUCTIONS,
|
|
33
|
+
SMXAI_WEBSITE_DESCRIPTION,
|
|
34
|
+
)
|
|
35
|
+
from syntaxmatrix.settings.client_items import read_client_file, getenv_api_key
|
|
32
36
|
|
|
33
37
|
# ──────── framework‐local storage paths ────────
|
|
34
38
|
# this ensures the key & data always live under the package dir,
|
|
35
|
-
# regardless of where the developer `cd` into before launching.
|
|
36
39
|
_CLIENT_DIR = detect_project_root()
|
|
37
40
|
_HISTORY_DIR = os.path.join(_CLIENT_DIR, "smx_history")
|
|
38
41
|
os.makedirs(_HISTORY_DIR, exist_ok=True)
|
|
39
42
|
|
|
43
|
+
_BRANDING_DIR = os.path.join(_CLIENT_DIR, "branding")
|
|
44
|
+
os.makedirs(_BRANDING_DIR, exist_ok=True)
|
|
45
|
+
|
|
40
46
|
_SECRET_PATH = os.path.join(_CLIENT_DIR, ".smx_secret_key")
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
load_dotenv(_CLIENT_DOTENV_PATH, override=True)
|
|
48
|
+
# OPENAI_API_KEY = getenv_api_key(_CLIENT_DIR, "OPENAI_API_KEY"))
|
|
49
|
+
# dotenv_content = read_client_file(_CLIENT_DIR, ".env")
|
|
45
50
|
|
|
46
51
|
_ICONS_PATH = os.path.join(_CLIENT_DIR, "static", "icons")
|
|
47
52
|
os.makedirs(_ICONS_PATH, exist_ok=True)
|
|
@@ -53,9 +58,9 @@ class SyntaxMUI:
|
|
|
53
58
|
host="127.0.0.1",
|
|
54
59
|
port="5080",
|
|
55
60
|
user_icon="👩🏿🦲",
|
|
56
|
-
bot_icon="<img src='/static/icons/
|
|
61
|
+
bot_icon="<img src='/static/icons/bot-icon.png' width=20' alt='bot'/>",
|
|
57
62
|
favicon="/static/icons/favicon.png",
|
|
58
|
-
site_logo="<img src='/static/icons/logo.png' width='
|
|
63
|
+
site_logo="<img src='/static/icons/logo.png' width='45' alt='logo'/>",
|
|
59
64
|
site_title="SyntaxMatrix",
|
|
60
65
|
project_name="smxAI",
|
|
61
66
|
theme_name="light",
|
|
@@ -70,12 +75,15 @@ class SyntaxMUI:
|
|
|
70
75
|
self.bot_icon = bot_icon
|
|
71
76
|
self.site_logo = site_logo
|
|
72
77
|
self.favicon = favicon
|
|
78
|
+
self._default_site_logo = site_logo
|
|
79
|
+
self._default_favicon = favicon
|
|
73
80
|
self.site_title = site_title
|
|
74
81
|
self.project_name = project_name
|
|
75
82
|
self.ui_mode = ui_mode
|
|
76
83
|
self.theme_toggle_enabled = False
|
|
77
84
|
self.user_files_enabled = False
|
|
78
|
-
self.
|
|
85
|
+
self.registration_enabled = False
|
|
86
|
+
self.smxai_identity = SMXAI_CHAT_IDENTITY
|
|
79
87
|
self.smxai_instructions = SMXAI_CHAT_INSTRUCTIONS
|
|
80
88
|
self.website_description = SMXAI_WEBSITE_DESCRIPTION
|
|
81
89
|
self._eda_output = {} # {chat_id: html}
|
|
@@ -96,15 +104,23 @@ class SyntaxMUI:
|
|
|
96
104
|
self._last_llm_usage = None
|
|
97
105
|
routes.setup_routes(self)
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
self.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
self.
|
|
107
|
+
# Apply client branding overrides if present on disk
|
|
108
|
+
self._apply_branding_from_disk()
|
|
109
|
+
|
|
110
|
+
# LLM Profiles
|
|
111
|
+
self.admin_profile = {}
|
|
112
|
+
self.chat_profile = {}
|
|
113
|
+
self.classifier_profile = {}
|
|
114
|
+
self.summarizer_profile = {}
|
|
115
|
+
self.coder_profile = {}
|
|
116
|
+
self.imagetexter_profile = {}
|
|
117
|
+
self.textimager_profile = {}
|
|
118
|
+
self.imageeditor_profile = {}
|
|
104
119
|
|
|
105
120
|
self._gpt_models_latest_prev_resp_ids = {}
|
|
106
121
|
self.is_streaming = False
|
|
107
122
|
self.stream_args = {}
|
|
123
|
+
self._apply_feature_flags_from_db()
|
|
108
124
|
|
|
109
125
|
self._recent_visual_summaries = []
|
|
110
126
|
|
|
@@ -311,6 +327,27 @@ class SyntaxMUI:
|
|
|
311
327
|
|
|
312
328
|
def enable_user_files(self):
|
|
313
329
|
self.user_files_enabled = True
|
|
330
|
+
|
|
331
|
+
def enable_registration(self):
|
|
332
|
+
self.registration_enabled = True
|
|
333
|
+
|
|
334
|
+
def _apply_feature_flags_from_db(self):
|
|
335
|
+
"""
|
|
336
|
+
Pull persisted toggles from app_settings.
|
|
337
|
+
"""
|
|
338
|
+
def _truthy(v):
|
|
339
|
+
return str(v or "").strip().lower() in ("1", "true", "yes", "on")
|
|
340
|
+
|
|
341
|
+
try:
|
|
342
|
+
stream_v = db.get_setting("feature.stream_mode", "0")
|
|
343
|
+
user_files_v = db.get_setting("feature.user_files", "0")
|
|
344
|
+
|
|
345
|
+
self.is_streaming = _truthy(stream_v)
|
|
346
|
+
self.user_files_enabled = _truthy(user_files_v)
|
|
347
|
+
except Exception:
|
|
348
|
+
# Keep defaults if DB isn't ready for any reason
|
|
349
|
+
pass
|
|
350
|
+
|
|
314
351
|
|
|
315
352
|
@staticmethod
|
|
316
353
|
def columns(components):
|
|
@@ -320,23 +357,49 @@ class SyntaxMUI:
|
|
|
320
357
|
col_html += "</div>"
|
|
321
358
|
return col_html
|
|
322
359
|
|
|
360
|
+
# Site Branding
|
|
323
361
|
def set_site_title(self, title):
|
|
324
362
|
self.site_title = title
|
|
325
|
-
|
|
326
363
|
def set_project_name(self, project_name):
|
|
327
364
|
self.project_name = project_name
|
|
328
|
-
|
|
329
365
|
def set_favicon(self, icon):
|
|
330
366
|
self.favicon = icon
|
|
331
|
-
|
|
332
367
|
def set_site_logo(self, logo):
|
|
333
368
|
self.site_logo = logo
|
|
334
|
-
|
|
335
369
|
def set_user_icon(self, icon):
|
|
336
370
|
self.user_icon = icon
|
|
337
|
-
|
|
338
371
|
def set_bot_icon(self, icon):
|
|
339
372
|
self.bot_icon = icon
|
|
373
|
+
|
|
374
|
+
def _apply_branding_from_disk(self):
|
|
375
|
+
"""
|
|
376
|
+
If a client logo/favicon exists in syntaxmatrixdir/branding/,
|
|
377
|
+
use it; otherwise keep the framework defaults.
|
|
378
|
+
"""
|
|
379
|
+
branding_dir = os.path.join(_CLIENT_DIR, "branding")
|
|
380
|
+
|
|
381
|
+
def _pick(basename: str):
|
|
382
|
+
for ext in (".png", ".jpg", ".jpeg"):
|
|
383
|
+
fn = f"{basename}{ext}"
|
|
384
|
+
p = os.path.join(branding_dir, fn)
|
|
385
|
+
if os.path.exists(p):
|
|
386
|
+
return fn
|
|
387
|
+
return None
|
|
388
|
+
|
|
389
|
+
logo_fn = _pick("logo")
|
|
390
|
+
fav_fn = _pick("favicon")
|
|
391
|
+
|
|
392
|
+
if logo_fn:
|
|
393
|
+
# Use client-served endpoint (added in routes.py below)
|
|
394
|
+
self.site_logo = f"<img src='/branding/{logo_fn}' width='45' alt='logo'/>"
|
|
395
|
+
else:
|
|
396
|
+
self.site_logo = getattr(self, "_default_site_logo", self.site_logo)
|
|
397
|
+
|
|
398
|
+
if fav_fn:
|
|
399
|
+
self.favicon = f"/branding/{fav_fn}"
|
|
400
|
+
else:
|
|
401
|
+
self.favicon = getattr(self, "_default_favicon", self.favicon)
|
|
402
|
+
|
|
340
403
|
|
|
341
404
|
def text_input(self, key, id, label, placeholder=""):
|
|
342
405
|
if not placeholder:
|
|
@@ -514,12 +577,12 @@ class SyntaxMUI:
|
|
|
514
577
|
# ──────────────────────────────────────────────────────────────
|
|
515
578
|
# *********** LLM CLIENT HELPERS **********************
|
|
516
579
|
# ──────────────────────────────────────────────────────────────
|
|
517
|
-
def
|
|
518
|
-
self.
|
|
580
|
+
def set_smxai_identity(self, profile):
|
|
581
|
+
self.set_smxai_identity = profile
|
|
519
582
|
|
|
520
583
|
|
|
521
|
-
def
|
|
522
|
-
self.
|
|
584
|
+
def set_smxai_instructions(self, instructions):
|
|
585
|
+
self.set_smxai_instructions = instructions
|
|
523
586
|
|
|
524
587
|
|
|
525
588
|
def set_website_description(self, desc):
|
|
@@ -592,18 +655,17 @@ class SyntaxMUI:
|
|
|
592
655
|
|
|
593
656
|
|
|
594
657
|
def classify_query_intent(self, query: str) -> str:
|
|
595
|
-
from syntaxmatrix.gpt_models_latest import extract_output_text as _out, set_args
|
|
596
658
|
|
|
597
|
-
if not self.
|
|
598
|
-
|
|
599
|
-
if not
|
|
600
|
-
return
|
|
601
|
-
self.
|
|
602
|
-
self.
|
|
659
|
+
if not self.classifier_profile:
|
|
660
|
+
classifier_profile = _prof.get_profile('classifier') or _prof.get_profile('chat') or _prof.get_profile('summarizer') or _prof.get_profile('admin')
|
|
661
|
+
if not classifier_profile:
|
|
662
|
+
return "Error: Set a profile for Classification"
|
|
663
|
+
self.classifier_profile = classifier_profile
|
|
664
|
+
self.classifier_profile['client'] = _prof.get_client(classifier_profile)
|
|
603
665
|
|
|
604
|
-
_client = self.
|
|
605
|
-
_provider = self.
|
|
606
|
-
_model = self.
|
|
666
|
+
_client = self.classifier_profile['client']
|
|
667
|
+
_provider = self.classifier_profile['provider']
|
|
668
|
+
_model = self.classifier_profile['model']
|
|
607
669
|
|
|
608
670
|
# New instruction format with hybrid option
|
|
609
671
|
_intent_profile = "You are an intent classifier. Respond ONLY with the intent name."
|
|
@@ -697,35 +759,36 @@ class SyntaxMUI:
|
|
|
697
759
|
|
|
698
760
|
def generate_contextual_title(self, chat_history):
|
|
699
761
|
|
|
700
|
-
if not self.
|
|
701
|
-
|
|
702
|
-
if not
|
|
703
|
-
return
|
|
762
|
+
if not self.summarizer_profile:
|
|
763
|
+
summarizer_profile = _prof.get_profile('summarizer') or _prof.get_profile('classifier') or _prof.get_profile('chat') or _prof.get_profile('admin')
|
|
764
|
+
if not summarizer_profile:
|
|
765
|
+
return "<code style='color:red;'>Error: No Agent setup yet.</code>"
|
|
704
766
|
|
|
705
|
-
self.
|
|
706
|
-
self.
|
|
767
|
+
self.summarizer_profile = summarizer_profile
|
|
768
|
+
self.summarizer_profile['client'] = _prof.get_client(summarizer_profile)
|
|
707
769
|
|
|
708
770
|
conversation = "\n".join([f"{role}: {msg}" for role, msg in chat_history])
|
|
709
771
|
_title_profile = "You are a title generator that creates concise and relevant titles for the given conversations."
|
|
772
|
+
|
|
710
773
|
_instructions = f"""
|
|
711
774
|
Generate a contextual title (5 short words max) from the given Conversation History
|
|
712
775
|
The title should be concise - with no preamble, relevant, and capture the essence of this Conversation: \n{conversation}.\n\n
|
|
713
776
|
return only the title.
|
|
714
777
|
"""
|
|
715
778
|
|
|
716
|
-
_client = self.
|
|
717
|
-
_provider = self.
|
|
718
|
-
_model = self.
|
|
779
|
+
_client = self.summarizer_profile['client']
|
|
780
|
+
_provider = self.summarizer_profile['provider']
|
|
781
|
+
_model = self.summarizer_profile['model']
|
|
719
782
|
|
|
720
783
|
def google_generated_title():
|
|
721
784
|
try:
|
|
722
785
|
response = _client.models.generate_content(
|
|
723
786
|
model=_model,
|
|
724
|
-
contents=f"{_title_profile}\n{_instructions}"
|
|
787
|
+
contents=f"{_title_profile}\n\n{_instructions}"
|
|
725
788
|
)
|
|
726
789
|
return response.text.strip()
|
|
727
790
|
except Exception as e:
|
|
728
|
-
return f"Summary agent error!"
|
|
791
|
+
return f"Google Summary agent error!"
|
|
729
792
|
|
|
730
793
|
def gpt_models_latest_generated_title():
|
|
731
794
|
try:
|
|
@@ -740,7 +803,7 @@ class SyntaxMUI:
|
|
|
740
803
|
resp = _client.responses.create(**args)
|
|
741
804
|
return _out(resp).strip()
|
|
742
805
|
except Exception as e:
|
|
743
|
-
return f"Summary agent error!"
|
|
806
|
+
return f"OpenAI 5s Summary agent error!"
|
|
744
807
|
|
|
745
808
|
def anthropic_generated_title():
|
|
746
809
|
try:
|
|
@@ -753,7 +816,7 @@ class SyntaxMUI:
|
|
|
753
816
|
)
|
|
754
817
|
return response.content[0].text.strip()
|
|
755
818
|
except Exception as e:
|
|
756
|
-
return f"Summary agent error!"
|
|
819
|
+
return f"Anthropic Summary agent error!"
|
|
757
820
|
|
|
758
821
|
def openai_sdk_generated_title():
|
|
759
822
|
prompt = [
|
|
@@ -767,10 +830,14 @@ class SyntaxMUI:
|
|
|
767
830
|
temperature=0.3,
|
|
768
831
|
max_tokens=50
|
|
769
832
|
)
|
|
770
|
-
|
|
771
|
-
|
|
833
|
+
print("\nRESPONSE:\n", response)
|
|
834
|
+
|
|
835
|
+
title = response.choices[0].message.content
|
|
836
|
+
|
|
837
|
+
print("\nTITLE:\n", title)
|
|
838
|
+
return title
|
|
772
839
|
except Exception as e:
|
|
773
|
-
return f"Summary agent error!"
|
|
840
|
+
return f"SDK Summary agent error!"
|
|
774
841
|
|
|
775
842
|
if _provider == "google":
|
|
776
843
|
title = google_generated_title()
|
|
@@ -792,18 +859,18 @@ class SyntaxMUI:
|
|
|
792
859
|
|
|
793
860
|
def process_query_stream(self, query: str, context: str, history: list, stream=True) -> Generator[str, None, None]:
|
|
794
861
|
|
|
795
|
-
if not self.
|
|
862
|
+
if not self.chat_profile:
|
|
796
863
|
chat_profile = _prof.get_profile("chat") or _prof.get_profile("admin")
|
|
797
864
|
if not chat_profile:
|
|
798
865
|
yield """<p style='color:red;'>Error: Chat profile is not configured. Add a chat profile inside the admin panel or contact your administrator.</p>
|
|
799
866
|
"""
|
|
800
867
|
return None
|
|
801
|
-
self.
|
|
802
|
-
self.
|
|
868
|
+
self.chat_profile = chat_profile
|
|
869
|
+
self.chat_profile['client'] = _prof.get_client(chat_profile)
|
|
803
870
|
|
|
804
|
-
_provider = self.
|
|
805
|
-
_client = self.
|
|
806
|
-
_model = self.
|
|
871
|
+
_provider = self.chat_profile['provider']
|
|
872
|
+
_client = self.chat_profile['client']
|
|
873
|
+
_model = self.chat_profile['model']
|
|
807
874
|
|
|
808
875
|
_contents = f"""
|
|
809
876
|
{self.smxai_instructions}\n\n
|
|
@@ -877,18 +944,18 @@ class SyntaxMUI:
|
|
|
877
944
|
|
|
878
945
|
def process_query(self, query, context, history, stream=False):
|
|
879
946
|
|
|
880
|
-
if not self.
|
|
947
|
+
if not self.chat_profile:
|
|
881
948
|
chat_profile = _prof.get_profile("chat") or _prof.get_profile("admin")
|
|
882
949
|
if not chat_profile:
|
|
883
950
|
return """<p style='color:red;'>Error: Chat profile is not configured. Add a chat profile inside the admin panel or contact your administrator.</p>
|
|
884
951
|
"""
|
|
885
952
|
return
|
|
886
953
|
|
|
887
|
-
self.
|
|
888
|
-
self.
|
|
889
|
-
_provider = self.
|
|
890
|
-
_client = self.
|
|
891
|
-
_model = self.
|
|
954
|
+
self.chat_profile = chat_profile
|
|
955
|
+
self.chat_profile['client'] = _prof.get_client(chat_profile)
|
|
956
|
+
_provider = self.chat_profile['provider']
|
|
957
|
+
_client = self.chat_profile['client']
|
|
958
|
+
_model = self.chat_profile['model']
|
|
892
959
|
_contents = f"""
|
|
893
960
|
{self.smxai_instructions}\n\n
|
|
894
961
|
Question: {query}\n
|
|
@@ -1027,7 +1094,7 @@ class SyntaxMUI:
|
|
|
1027
1094
|
return code
|
|
1028
1095
|
_prompt = f"```python\n{code}\n```"
|
|
1029
1096
|
|
|
1030
|
-
repair_profile =
|
|
1097
|
+
repair_profile = self.coder_profile
|
|
1031
1098
|
if not repair_profile:
|
|
1032
1099
|
return (
|
|
1033
1100
|
'<div class="smx-alert smx-alert-warn">'
|
|
@@ -1137,21 +1204,28 @@ class SyntaxMUI:
|
|
|
1137
1204
|
tasks = [str(t).strip().lower() for t in tasks if str(t).strip()]
|
|
1138
1205
|
|
|
1139
1206
|
ai_profile = """
|
|
1140
|
-
- You are a Python expert
|
|
1141
|
-
- Your task is to generate a single, complete, production-
|
|
1207
|
+
- You are a Python expert specialising in Data Science (DS) and Machine Learning (ML).
|
|
1208
|
+
- Your task is to generate a single, complete, production-ready Python script that can be executed in a Jupyter-like Python kernel, based on the given instructions.
|
|
1142
1209
|
- The dataset is already loaded as a pandas DataFrame named `df` (no file I/O or file uploads).
|
|
1143
|
-
- Make a copy of `df` and name it `df_copy`.
|
|
1144
|
-
-
|
|
1145
|
-
-
|
|
1146
|
-
|
|
1147
|
-
-
|
|
1210
|
+
- Make a copy of `df` and name it `df_copy`.
|
|
1211
|
+
- Make sure `df_copy` is preprocessed and cleaned, and name it `df_cleaned`, if not already done so.
|
|
1212
|
+
- Work only with `df_cleaned` to perform the ML tasks described in the given context.
|
|
1213
|
+
|
|
1214
|
+
- Always treat modelling as features `X` and target `y`:
|
|
1215
|
+
* Choose ONE target column in `df_cleaned` (the value to be predicted) and refer to it as `target_col` or `y`.
|
|
1216
|
+
* Build the feature matrix `X` from `df_cleaned` WITHOUT including the target column or any direct transformation of it.
|
|
1217
|
+
* Examples of forbidden feature leakage: if predicting `sellingprice`, do NOT include `sellingprice`, `log_sellingprice`, `margin = sellingprice - mmr`, or any other direct function of `sellingprice` in `X`.
|
|
1218
|
+
* You may create target-derived columns (margins, flags, percentage differences) for descriptive tables or plots, but NEVER use them as model inputs.
|
|
1219
|
+
|
|
1220
|
+
- When you need a modelling frame, define `required_cols = [target_col] + feature_cols` where `feature_cols` excludes the target and its transforms, and then create `df_filtered = df_cleaned[required_cols]`.
|
|
1221
|
+
|
|
1222
|
+
- Use the {TEMPLATE_CATALOGUE} below to educate yourself about available helper functions and reference code, and ensure the implementations are in the code you generate.
|
|
1223
|
+
- The final output MUST BE the complete, executable Python code for the requested analysis, wrapped in a single fenced Python code block (```python ... ```), and MUST BE able to fulfil the user's request: {tasks}.
|
|
1148
1224
|
- Do not include any explanatory text or markdown outside the code block.
|
|
1149
1225
|
"""
|
|
1150
1226
|
|
|
1151
1227
|
TEMPLATE_CATALOGUE = """
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
Visualisation templates (dataset-agnostic):
|
|
1228
|
+
Visualisation templates:
|
|
1155
1229
|
- viz_pie(df, category_col=None, top_k=8): pie/donut shares within a category.
|
|
1156
1230
|
- viz_stacked_bar(df, x=None, hue=None, normalise=True): composition across groups.
|
|
1157
1231
|
- viz_count_bar(df, category_col=None, top_k=12): counts/denominators by category.
|
|
@@ -1191,9 +1265,9 @@ class SyntaxMUI:
|
|
|
1191
1265
|
|
|
1192
1266
|
"""
|
|
1193
1267
|
### Template rules
|
|
1194
|
-
- You MAY call
|
|
1268
|
+
- You MAY call 1 or more templates if they matche the task.
|
|
1195
1269
|
- Do NOT invent template names.
|
|
1196
|
-
- If no template fits, write minimal direct pandas/sklearn/seaborn code instead.
|
|
1270
|
+
- If no template fits, write minimal direct pandas/sklearn/seaborn code instead, for visualization.
|
|
1197
1271
|
- Keep the solution short: avoid writing wrappers/utilities already handled by SyntaxMatrix hardener.
|
|
1198
1272
|
|
|
1199
1273
|
#### Template selection hint examples:
|
|
@@ -1216,8 +1290,7 @@ class SyntaxMUI:
|
|
|
1216
1290
|
set `random_state=42` where relevant.
|
|
1217
1291
|
4) Be defensive, but avoid hard-failing on optional fields:
|
|
1218
1292
|
- If the primary column, needed to answer the question, is missing, review your copy of the `df` again.
|
|
1219
|
-
Make sure that you selected the proper column.
|
|
1220
|
-
Never use a column/variable which isn't available or defined.
|
|
1293
|
+
- Make sure that you selected the proper column. Never use a column/variable which isn't available or defined.
|
|
1221
1294
|
- If a secondary/extra column is missing, show a warning with `show(...)` and continue using available fields.
|
|
1222
1295
|
- Handle missing values sensibly (drop rows for simple EDA; use `ColumnTransformer` + `SimpleImputer` for modelling).
|
|
1223
1296
|
- For categorical features in ML, use `OneHotEncoder(handle_unknown="ignore")`
|
|
@@ -1249,6 +1322,20 @@ class SyntaxMUI:
|
|
|
1249
1322
|
11) You MUST NOT reference any column outside Available columns: {AVAILABLE_COLUMNS}.
|
|
1250
1323
|
12) If asked to predict/classify, choose the target by matching the task text to Allowed columns
|
|
1251
1324
|
and never invent a new name.
|
|
1325
|
+
13) Treat df as the primary dataset you must work with.
|
|
1326
|
+
14) The dataset is already loaded as df (no file I/O or file uploads).
|
|
1327
|
+
15) All outputs must be visible to the user via the provided show(...) helper.
|
|
1328
|
+
16) Never use print(...); use show(...) instead.
|
|
1329
|
+
17) You MUST NOT read from or write to local files, folders, or external storage.
|
|
1330
|
+
- Do not call open(...), Path(...).write_text/write_bytes, or similar file APIs.
|
|
1331
|
+
- Do not use df.to_csv(...), df.to_excel(...), df.to_parquet(...),
|
|
1332
|
+
df.to_pickle(...), df.to_json(...), df.to_hdf(...), or any other
|
|
1333
|
+
method that writes to disk.
|
|
1334
|
+
- Do not call joblib.dump(...), pickle.dump(...), torch.save(...),
|
|
1335
|
+
numpy.save(...), numpy.savetxt(...), or similar saving functions.
|
|
1336
|
+
- Do not call plt.savefig(..., 'somefile.png') or any variant that
|
|
1337
|
+
writes an image to a filename. Plots must be rendered in-memory only.
|
|
1338
|
+
18) Keep everything in memory and surface results via show(...) or plots.
|
|
1252
1339
|
|
|
1253
1340
|
#### Cohort rules
|
|
1254
1341
|
When you generate plots for cohorts or categories, you MUST obey these rules:
|
|
@@ -1297,21 +1384,21 @@ class SyntaxMUI:
|
|
|
1297
1384
|
- And ends with at least 3 visible output (`show(...)` and/or `plt.show()`).
|
|
1298
1385
|
""")
|
|
1299
1386
|
|
|
1300
|
-
if not self.
|
|
1301
|
-
|
|
1302
|
-
if not
|
|
1387
|
+
if not self.coder_profile:
|
|
1388
|
+
_coder_profile = _prof.get_profile("coder")
|
|
1389
|
+
if not _coder_profile:
|
|
1303
1390
|
return (
|
|
1304
1391
|
'<div class="smx-alert smx-alert-warn">'
|
|
1305
|
-
'No LLM profile configured for <code>coding</code>
|
|
1392
|
+
'No LLM profile configured for <code>coding</code> <br>'
|
|
1306
1393
|
'Please, add the LLM profile inside the admin panel or contact your Administrator.'
|
|
1307
1394
|
'</div>'
|
|
1308
1395
|
)
|
|
1309
1396
|
|
|
1310
|
-
self.
|
|
1311
|
-
self.
|
|
1397
|
+
self.coder_profile = _coder_profile
|
|
1398
|
+
self.coder_profile['client'] = _prof.get_client(_coder_profile)
|
|
1312
1399
|
|
|
1313
1400
|
# code = mlearning_agent(instructions, ai_profile, self._coding_profile)
|
|
1314
|
-
code, usage = mlearning_agent(instructions, ai_profile, self.
|
|
1401
|
+
code, usage = mlearning_agent(instructions, ai_profile, self.coder_profile)
|
|
1315
1402
|
self._last_llm_usage = usage
|
|
1316
1403
|
|
|
1317
1404
|
if code:
|
|
@@ -1359,7 +1446,22 @@ class SyntaxMUI:
|
|
|
1359
1446
|
return code.strip()
|
|
1360
1447
|
|
|
1361
1448
|
return "Error: AI code generation failed."
|
|
1449
|
+
|
|
1362
1450
|
|
|
1451
|
+
def get_image_generator_profile(self):
|
|
1452
|
+
if not self._fullvision_profile:
|
|
1453
|
+
fullvision_profile = _prof.get_profile("fullvision")
|
|
1454
|
+
if not fullvision_profile:
|
|
1455
|
+
return (
|
|
1456
|
+
'<div class="smx-alert smx-alert-warn">'
|
|
1457
|
+
'No Full Vision profile configured for <code>coding</code> <br>'
|
|
1458
|
+
'Please, add it inside the admin panel or contact your Administrator.'
|
|
1459
|
+
'</div>'
|
|
1460
|
+
)
|
|
1461
|
+
self._fullvision_profile = fullvision_profile
|
|
1462
|
+
self._fullvision_profile['client'] = _prof.get_client(fullvision_profile)
|
|
1463
|
+
|
|
1464
|
+
return self._fullvision_profile
|
|
1363
1465
|
|
|
1364
1466
|
def sanitize_rough_to_markdown_task(self, rough: str) -> str:
|
|
1365
1467
|
"""
|
|
@@ -1395,7 +1497,13 @@ class SyntaxMUI:
|
|
|
1395
1497
|
|
|
1396
1498
|
# Drop optional <rough> wrapper
|
|
1397
1499
|
return out.replace("<rough>", "").replace("</rough>", "").strip()
|
|
1398
|
-
|
|
1500
|
+
|
|
1501
|
+
def current_profile(self, agency):
|
|
1502
|
+
current_profile = _prof.get_profile(agency) or _prof.get_profile('admin')
|
|
1503
|
+
if not current_profile:
|
|
1504
|
+
return "Error: Configure the valid LLM profile."
|
|
1505
|
+
current_profile['client'] = _prof.get_client(current_profile)
|
|
1506
|
+
return current_profile
|
|
1399
1507
|
|
|
1400
1508
|
def run(self):
|
|
1401
1509
|
url = f"http://{self.host}:{self.port}/"
|