ApiLogicServer 14.2.20__py3-none-any.whl → 14.3.7__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.
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/METADATA +2 -2
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/RECORD +90 -69
- api_logic_server_cli/api_logic_server.py +5 -1
- api_logic_server_cli/api_logic_server_info.yaml +3 -3
- api_logic_server_cli/cli.py +5 -2
- api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/api_logic_server_utils.py +4 -0
- api_logic_server_cli/create_from_model/ont_build.py +53 -19
- api_logic_server_cli/create_from_model/ont_create.py +14 -5
- api_logic_server_cli/fragments/declare_logic.py +72 -0
- api_logic_server_cli/{prototypes/manager/system/genai/create_db_models_inserts/logic_discovery_prefix.py → fragments/declare_logic_begin.py} +2 -1
- api_logic_server_cli/fragments/declare_logic_end.py +52 -0
- api_logic_server_cli/genai/genai.py +25 -8
- api_logic_server_cli/genai/genai_logic_builder.py +14 -11
- api_logic_server_cli/genai/genai_svcs.py +104 -7
- api_logic_server_cli/manager.py +20 -16
- api_logic_server_cli/model_migrator/model_migrator_start.py +1 -1
- api_logic_server_cli/model_migrator/reposreader.py +9 -1
- api_logic_server_cli/model_migrator/rule_obj.py +24 -6
- api_logic_server_cli/prototypes/base/api/api_discovery/ontimize_api.py +4 -1
- api_logic_server_cli/prototypes/base/api/system/expression_parser.py +10 -4
- api_logic_server_cli/prototypes/base/config/activate_logicbank.py +8 -4
- api_logic_server_cli/prototypes/base/database/bind_dbs.py +1 -1
- api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -5
- api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +32 -8
- api_logic_server_cli/prototypes/base/integration/system/RowDictMapper.py +33 -16
- api_logic_server_cli/prototypes/base/logic/declare_logic.py +9 -3
- api_logic_server_cli/prototypes/base/logic/load_verify_rules.py +217 -0
- api_logic_server_cli/prototypes/base/logic/logic_discovery/auto_discovery.py +22 -13
- api_logic_server_cli/prototypes/genai_demo/api/customize_api.py +9 -11
- api_logic_server_cli/prototypes/genai_demo/database/.DS_Store +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/models.py +52 -42
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/OrderB2B.py +4 -6
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/__pycache__/OrderB2B.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/integration/row_dict_maps/row_dict_maps_readme.md +3 -0
- api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/declare_logic.py +58 -62
- api_logic_server_cli/prototypes/genai_demo/logic/load_verify_rules.py +216 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/__init__.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/__pycache__/error_testing.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/logic_discovery/auto_discovery.py +52 -0
- api_logic_server_cli/prototypes/genai_demo/logic/readme_declare_logic.md +172 -0
- api_logic_server_cli/prototypes/genai_demo/security/__pycache__/declare_security.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +86 -53
- api_logic_server_cli/prototypes/manager/.vscode/launch.json +1 -1
- api_logic_server_cli/prototypes/manager/README.md +19 -4
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +4 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +34 -26
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +3 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/.DS_Store +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/000_you_are.prompt +1 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/001_logic_training.prompt +314 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/002_create_db_models.prompt +150 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/003_create_db_models.response +134 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/004_iteratio_logic.prompt +131 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/005_create_db_models.response-example +141 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/create_db_models.py +105 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/db.dbml +70 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/readme.md +6 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_iteration_discount/response.json +178 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/genai/examples/genai_demo/wg_dev_merge/wg_genai_demo_no_logic_fixed_from_CLI/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/base_genai_demo_no_logic/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/dev_demo_no_logic_fixed/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/wg_dev_merge/wg_demo_no_logic_fixed/system/genai/examples/genai_demo/wg_dev_merge/wg_genai_demo_no_logic_fixed_from_CLI/logic/declare_logic.py +0 -1
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/002_create_db_models.prompt +194 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/003_create_db_models.response +298 -0
- api_logic_server_cli/prototypes/{genai_demo/database/chatgpt/sample_ai.sqlite → manager/system/genai/examples/time_tracking_billing/db.sqlite} +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/time_tracking_billing/readme.md +61 -0
- api_logic_server_cli/prototypes/manager/system/genai/learning_requests/logic_bank_api.prompt +29 -11
- api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/iteration.prompt +2 -1
- api_logic_server_cli/prototypes/nw_no_cust/venv_setup/system_note.txt +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/home_tree_template.html +9 -0
- api_logic_server_cli/prototypes/ont_app/templates/tree_routing.jinja +32 -0
- api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
- api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
- api_logic_server_cli/tools/mini_skel/logic/load_verify_rules.py +1 -1
- api_logic_server_cli/model_migrator/system/custom_endpoint.py +0 -545
- api_logic_server_cli/prototypes/base/database/test_data/z_test_data_rows.py +0 -98
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/copilot_models.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/__pycache__/sample_ai_models.cpython-312.pyc +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.chatgpt +0 -16
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai.sql +0 -66
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_items.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.py +0 -156
- api_logic_server_cli/prototypes/genai_demo/database/chatgpt/sample_ai_models.sqlite +0 -0
- api_logic_server_cli/prototypes/genai_demo/logic/cocktail-napkin.jpg +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/LICENSE +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/WHEEL +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/entry_points.txt +0 -0
- {ApiLogicServer-14.2.20.dist-info → ApiLogicServer-14.3.7.dist-info}/top_level.txt +0 -0
|
@@ -159,8 +159,11 @@ class OntBuilder(object):
|
|
|
159
159
|
if use_local:
|
|
160
160
|
with contextlib.suppress(Exception):
|
|
161
161
|
return self.local_env.get_template(template_name)
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
try:
|
|
163
|
+
return self.env.get_template(template_name)
|
|
164
|
+
except Exception as e:
|
|
165
|
+
log.error(f"Error loading template {template_name} - {e}")
|
|
166
|
+
return None
|
|
164
167
|
|
|
165
168
|
|
|
166
169
|
def build_application(self, show_messages: bool = True):
|
|
@@ -229,11 +232,7 @@ class OntBuilder(object):
|
|
|
229
232
|
self.generate_home_template(app_path, entity_favorites, each_entity_name, each_entity, entity_name)
|
|
230
233
|
self.generate_new_template(app_path, entity_favorites, each_entity_name, each_entity, entity_name)
|
|
231
234
|
self.generate_detail_template(app_path, entity_favorites, each_entity_name, each_entity, entity_name)
|
|
232
|
-
if self.api_endpoint:
|
|
233
|
-
print(f"Ontimize Build for --api-endpoint={self.api_endpoint} - entity: {each_entity_name}")
|
|
234
|
-
return
|
|
235
235
|
self.generate_routing(app_path, each_entity_name, each_entity, entity_name)
|
|
236
|
-
|
|
237
236
|
self.generate_card_home_template(app_path, entity_favorites, each_entity_name, each_entity, entity_name)
|
|
238
237
|
|
|
239
238
|
# menu groups/routing and service config
|
|
@@ -269,7 +268,11 @@ class OntBuilder(object):
|
|
|
269
268
|
source=app_config,
|
|
270
269
|
)
|
|
271
270
|
def generate_routing(self, app_path, each_entity_name, each_entity, entity_name):
|
|
272
|
-
|
|
271
|
+
home_template_name = self.find_template(each_entity, "home_template","home_template.html")
|
|
272
|
+
if home_template_name == "home_tree_template.html":
|
|
273
|
+
routing = self.load_routing("tree_routing.jinja", entity_name, each_entity)
|
|
274
|
+
else:
|
|
275
|
+
routing = self.load_routing("routing.jinja", entity_name, each_entity)
|
|
273
276
|
write_file(app_path, entity_name, "", "-routing.module.ts", routing)
|
|
274
277
|
module = self.load_module("module.jinja", entity_name=each_entity_name, entity=each_entity)
|
|
275
278
|
write_file(app_path, entity_name, "", ".module.ts", module)
|
|
@@ -324,6 +327,11 @@ class OntBuilder(object):
|
|
|
324
327
|
if home_template_name == "grid_template.html":
|
|
325
328
|
home_scss = self.get_template("grid_home.scss").render(entity=each_entity_name)
|
|
326
329
|
ts = self.load_ts("grid_home_template.jinja", each_entity_name, each_entity, entity_favorites)
|
|
330
|
+
elif home_template_name != "home_template.html":
|
|
331
|
+
home_scss = self.get_template("home.scss").render(entity=each_entity_name)
|
|
332
|
+
home_template_nm = home_template_name.split(".")
|
|
333
|
+
ts_template = self.find_template(each_entity, f"{home_template_nm[0]}.jinja","home_template.jinja")
|
|
334
|
+
ts = self.load_ts(ts_template, each_entity_name, each_entity, entity_favorites)
|
|
327
335
|
else:
|
|
328
336
|
home_scss = self.get_template("home.scss").render(entity=each_entity_name)
|
|
329
337
|
ts = self.load_ts("home_template.jinja", each_entity_name, each_entity, entity_favorites)
|
|
@@ -455,7 +463,7 @@ class OntBuilder(object):
|
|
|
455
463
|
# loader=PackageLoader(package_name="APILOGICPROJECT",package_path="/ApiLogicServer/ApiLogicServer-dev/build_and_test/nw/ui/templates"),
|
|
456
464
|
loader=FileSystemLoader(searchpath=f"{templates_path}")
|
|
457
465
|
)
|
|
458
|
-
local_templates_path = self.app_path.joinpath(
|
|
466
|
+
local_templates_path = self.app_path.joinpath('templates')
|
|
459
467
|
local_env = Environment (
|
|
460
468
|
loader=FileSystemLoader(searchpath=f"{local_templates_path}")
|
|
461
469
|
)
|
|
@@ -464,7 +472,7 @@ class OntBuilder(object):
|
|
|
464
472
|
template_env = Environment(
|
|
465
473
|
loader=FileSystemLoader(searchpath=f"{self.template_dir}")
|
|
466
474
|
)
|
|
467
|
-
return (env,local_env, template_env)
|
|
475
|
+
return (env, local_env, template_env)
|
|
468
476
|
|
|
469
477
|
def load_ts(self, template_name: str, entity_name: str, entity: any, favorites: any) -> str:
|
|
470
478
|
# The above code is a Python function that takes a template name as input, retrieves the template
|
|
@@ -586,9 +594,15 @@ class OntBuilder(object):
|
|
|
586
594
|
if getattr(entity,"tab_groups",None) != None:
|
|
587
595
|
for tg in entity["tab_groups"]:
|
|
588
596
|
exclude = tg.get("exclude", False) or self.global_values["exclude_listpicker"] == True
|
|
589
|
-
if tg["direction"] == "toone"
|
|
590
|
-
|
|
591
|
-
|
|
597
|
+
if tg["direction"] == "toone" \
|
|
598
|
+
and column.name in tg["fks"] \
|
|
599
|
+
and column.name not in ["Id","id"] \
|
|
600
|
+
and len(tg["fks"]) == 1 \
|
|
601
|
+
and not exclude:
|
|
602
|
+
col_type = next((col.type for col in entity.columns if col.name == col_var["name"]), None)
|
|
603
|
+
if col_type and col_var["type"].lower().split("(")[0] in ["bigint", "int","integer", "numeric","decimal"]:
|
|
604
|
+
tab_name, tab_var = self.get_tab_attrs(entity=entity, parent_entity=parent_entity, fk_tab=tg)
|
|
605
|
+
return self.table_cell_render.render(tab_var)
|
|
592
606
|
|
|
593
607
|
name = column.label if hasattr(column, "label") and column.label != DotMap() else column.name
|
|
594
608
|
self.add_title(column["name"], name)
|
|
@@ -606,6 +620,8 @@ class OntBuilder(object):
|
|
|
606
620
|
return self.table_real_template.render(col_var)
|
|
607
621
|
elif template_type == "table_column":
|
|
608
622
|
return self.table_column.render(col_var)
|
|
623
|
+
elif template_type.upper() == "CHECKBOX":
|
|
624
|
+
return self.check_circle_template.render(col_var)
|
|
609
625
|
else:
|
|
610
626
|
if template_type == "TEXTAREA":
|
|
611
627
|
return self.table_textarea_template.render(col_var)
|
|
@@ -629,6 +645,8 @@ class OntBuilder(object):
|
|
|
629
645
|
return "CURRENCY"
|
|
630
646
|
elif column.type in ["BLOB","CLOB", "VARBINARY"]:
|
|
631
647
|
return "IMAGE"
|
|
648
|
+
elif column.type == "BOOLEAN":
|
|
649
|
+
return "BOOLEAN"
|
|
632
650
|
return "TEXT"
|
|
633
651
|
def load_new_template(self, template_name: str,entity_name: str, entity: any, favorites: any) -> str:
|
|
634
652
|
"""
|
|
@@ -662,8 +680,14 @@ class OntBuilder(object):
|
|
|
662
680
|
self.add_title(column["name"], name)
|
|
663
681
|
for fk in fks:
|
|
664
682
|
exclude = fk.get("exclude", "false") == "true"
|
|
665
|
-
if column.name in fk["attrs"]
|
|
683
|
+
if column.name in fk["attrs"] \
|
|
684
|
+
and fk["direction"] == "toone" \
|
|
685
|
+
and len(fk["attrs"]) == 1 \
|
|
686
|
+
and not exclude:
|
|
687
|
+
#and column.template != 'text':
|
|
666
688
|
fk_entity = self.get_entity(fk["resource"])
|
|
689
|
+
#col_type = next((col.type for col in entity.columns if col.name == col_var["name"]), None)
|
|
690
|
+
#if col_type and col_var["type"] != col_type:
|
|
667
691
|
return self.gen_pick_list_col(col_var, fk, entity)
|
|
668
692
|
return self.gen_field_template(column, col_var)
|
|
669
693
|
|
|
@@ -723,8 +747,14 @@ class OntBuilder(object):
|
|
|
723
747
|
for fk in fks:
|
|
724
748
|
# TODO - not sure how to handle multiple fks attrs - so only support 1 for now
|
|
725
749
|
exclude = fk.get("exclude", "false") == "true"
|
|
726
|
-
if column.name in fk["attrs"]
|
|
727
|
-
|
|
750
|
+
if column.name in fk["attrs"] \
|
|
751
|
+
and fk["direction"] == "toone" \
|
|
752
|
+
and len(fk["attrs"]) == 1 \
|
|
753
|
+
and not exclude:
|
|
754
|
+
#and column.template != 'text':
|
|
755
|
+
#col_type = next((col.type for col in entity.columns if col.name == col_var["name"]), None)
|
|
756
|
+
#if col_type and col_var["type"] != col_type:
|
|
757
|
+
return self.gen_pick_list_col(col_var, fk, entity)
|
|
728
758
|
self.add_title(column["name"], name)
|
|
729
759
|
return self.gen_field_template(column, col_var)
|
|
730
760
|
|
|
@@ -912,7 +942,7 @@ class OntBuilder(object):
|
|
|
912
942
|
rv = self.nif_template.render(col_var)
|
|
913
943
|
elif col_type in ["DECIMAL","NUMERIC", "DOUBLE","REAL"]:
|
|
914
944
|
rv = self.real_template.render(col_var)
|
|
915
|
-
elif template_type == "CHECK_CIRCLE"
|
|
945
|
+
elif template_type == "CHECK_CIRCLE" or col_type in ["BIT","BOOLEAN"]:
|
|
916
946
|
rv == self.check_circle_template.render(col_var)
|
|
917
947
|
else:
|
|
918
948
|
rv = self.text_template.render(col_var)
|
|
@@ -1069,11 +1099,15 @@ def get_first_tab_group_entity(entity: any):
|
|
|
1069
1099
|
def calculate_template(column):
|
|
1070
1100
|
col_type = column.type.upper().split("(")[0]
|
|
1071
1101
|
name = column.name.upper()
|
|
1072
|
-
if
|
|
1102
|
+
if col_type in ["INTEGER","INT", "TINYINT", "SMALLINT"]:
|
|
1103
|
+
return "INTEGER"
|
|
1104
|
+
if col_type in ["BIT","BOOLEAN"]:
|
|
1105
|
+
return "CHECKBOX"
|
|
1106
|
+
elif name.endswith("AMT") or name.endswith("AMOUNT") or name.endswith("TOTAL") or name in ["BALANCE","CREDITLIMIT","FREIGHT"]:
|
|
1073
1107
|
return "CURRENCY"
|
|
1074
|
-
|
|
1108
|
+
elif name.endswith("DT") or name.endswith("DATE"):
|
|
1075
1109
|
return "DATE" if col_type == "DATE" else "TIMESTAMP"
|
|
1076
|
-
|
|
1110
|
+
elif name == "DISCOUNT":
|
|
1077
1111
|
return "PERCENT"
|
|
1078
1112
|
template = column.template.upper() if hasattr(column,"template") and column.template != DotMap() else col_type
|
|
1079
1113
|
if template == "TEXT" and col_type in ["DECIMAL","INTEGER","NUMERIC","REAL","FLOAT"]:
|
|
@@ -63,6 +63,10 @@ class OntCreator(object):
|
|
|
63
63
|
self.admin_app = admin_app
|
|
64
64
|
self.app = app
|
|
65
65
|
|
|
66
|
+
def attribute_exists(self, attribute: DotMap, attributes: List[DotMap]) -> bool:
|
|
67
|
+
return any(
|
|
68
|
+
each_attribute.name == attribute.name for each_attribute in attributes
|
|
69
|
+
)
|
|
66
70
|
def create_application(self, show_messages: bool = True):
|
|
67
71
|
""" Iterate over ui/admin/admin.yml, and create app...
|
|
68
72
|
|
|
@@ -124,7 +128,8 @@ class OntCreator(object):
|
|
|
124
128
|
each_attribute=each_attribute,
|
|
125
129
|
each_resource_name=each_resource_name,
|
|
126
130
|
resources=resources)
|
|
127
|
-
app_model_out.entities[each_resource_name].columns
|
|
131
|
+
if not self.attribute_exists(app_model_attribute, app_model_out.entities[each_resource_name].columns):
|
|
132
|
+
app_model_out.entities[each_resource_name].columns.append(app_model_attribute)
|
|
128
133
|
app_model_out.entities[each_resource_name].pop('attributes')
|
|
129
134
|
|
|
130
135
|
app_model_out.entities[each_resource_name].primary_key = []
|
|
@@ -151,8 +156,7 @@ class OntCreator(object):
|
|
|
151
156
|
pass
|
|
152
157
|
if show_messages:
|
|
153
158
|
log.info("\nEdit the add_model.yaml as desired, and ApiLogicServer app-build\n")
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
|
|
156
160
|
def create_model_entity(self, each_resource, resources: list) -> DotMap:
|
|
157
161
|
each_resource.favorite = each_resource.user_key
|
|
158
162
|
each_resource.exclude = "false"
|
|
@@ -227,7 +231,7 @@ class OntCreator(object):
|
|
|
227
231
|
if col_type in ["SERIAL","SERIAL4"]:
|
|
228
232
|
rv = "nif"
|
|
229
233
|
if col_type in ["DECIMAL","NUMERIC"]:
|
|
230
|
-
rv = "
|
|
234
|
+
rv = "real"
|
|
231
235
|
elif col_type in ["DOUBLE", "FLOAT", "REAL"]:
|
|
232
236
|
rv = "real"
|
|
233
237
|
elif col_type in ["DATE","DATETIME","TIME","TIMESTAMP"]:
|
|
@@ -240,8 +244,13 @@ class OntCreator(object):
|
|
|
240
244
|
rv = "image"
|
|
241
245
|
elif col_type in ["BLOB","CLOB","VARBINARY","BINARY","BYTEA","LONGBLOB","MEDIUMBLOB","TINYBLOB"]:
|
|
242
246
|
rv = "textarea"
|
|
247
|
+
elif col_type in ["BOOLEAN","BOOL"]:
|
|
248
|
+
rv = "checkbox"
|
|
243
249
|
else:
|
|
244
|
-
|
|
250
|
+
if "amount" in column.name or "price" in column.name or "rate" in column.name:
|
|
251
|
+
rv = "currency"
|
|
252
|
+
else:
|
|
253
|
+
rv = "text" #char varchar string etc
|
|
245
254
|
else:
|
|
246
255
|
rv = "text"
|
|
247
256
|
return rv
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
from logic_bank.exec_row_logic.logic_row import LogicRow
|
|
4
|
+
from logic_bank.extensions.rule_extensions import RuleExtension
|
|
5
|
+
from logic_bank.logic_bank import Rule
|
|
6
|
+
import database.models as models
|
|
7
|
+
import api.system.opt_locking.opt_locking as opt_locking
|
|
8
|
+
from security.system.authorization import Grant, Security
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
def declare_logic():
|
|
14
|
+
''' Declarative multi-table derivations and constraints, extensible with Python.
|
|
15
|
+
|
|
16
|
+
Brief background: see readme_declare_logic.md
|
|
17
|
+
|
|
18
|
+
Your Code Goes Here - Use code completion (Rule.) to declare rules
|
|
19
|
+
'''
|
|
20
|
+
|
|
21
|
+
from logic.logic_discovery.auto_discovery import discover_logic
|
|
22
|
+
discover_logic()
|
|
23
|
+
|
|
24
|
+
def handle_all(logic_row: LogicRow): # #als: TIME / DATE STAMPING, OPTIMISTIC LOCKING
|
|
25
|
+
"""
|
|
26
|
+
This is generic - executed for all classes.
|
|
27
|
+
|
|
28
|
+
Invokes optimistic locking, and checks Grant permissions.
|
|
29
|
+
|
|
30
|
+
Also provides user/date stamping.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
logic_row (LogicRow): from LogicBank - old/new row, state
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
if os.getenv("APILOGICPROJECT_NO_FLASK") is not None:
|
|
37
|
+
print("\ndeclare_logic.py Using TestBase\n")
|
|
38
|
+
return # enables rules to be used outside of Flask, e.g., test data loading
|
|
39
|
+
|
|
40
|
+
if logic_row.is_updated() and logic_row.old_row is not None and logic_row.nest_level == 0:
|
|
41
|
+
opt_locking.opt_lock_patch(logic_row=logic_row)
|
|
42
|
+
|
|
43
|
+
Grant.process_updates(logic_row=logic_row)
|
|
44
|
+
|
|
45
|
+
did_stamping = False
|
|
46
|
+
if enable_stamping := False: # #als: DATE / USER STAMPING
|
|
47
|
+
row = logic_row.row
|
|
48
|
+
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
|
|
49
|
+
row.CreatedOn = datetime.datetime.now()
|
|
50
|
+
did_stamping = True
|
|
51
|
+
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedBy"):
|
|
52
|
+
row.CreatedBy = Security.current_user().id
|
|
53
|
+
# if Config.SECURITY_ENABLED == True else 'public'
|
|
54
|
+
did_stamping = True
|
|
55
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedOn"):
|
|
56
|
+
row.UpdatedOn = datetime.datetime.now()
|
|
57
|
+
did_stamping = True
|
|
58
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedBy"):
|
|
59
|
+
row.UpdatedBy = Security.current_user().id \
|
|
60
|
+
if Config.SECURITY_ENABLED == True else 'public'
|
|
61
|
+
did_stamping = True
|
|
62
|
+
if did_stamping:
|
|
63
|
+
logic_row.log("early_row_event_all_classes - handle_all did stamping")
|
|
64
|
+
Rule.early_row_event_all_classes(early_row_event_all_classes=handle_all)
|
|
65
|
+
|
|
66
|
+
#als rules report
|
|
67
|
+
from api.system import api_utils
|
|
68
|
+
# api_utils.rules_report()
|
|
69
|
+
|
|
70
|
+
app_logger.debug("..logic/declare_logic.py (logic == rules + code)")
|
|
71
|
+
|
|
72
|
+
|
|
@@ -4,7 +4,6 @@ from logic_bank.exec_row_logic.logic_row import LogicRow
|
|
|
4
4
|
from logic_bank.extensions.rule_extensions import RuleExtension
|
|
5
5
|
from logic_bank.logic_bank import Rule
|
|
6
6
|
import database.models as models
|
|
7
|
-
from database.models import *
|
|
8
7
|
import api.system.opt_locking.opt_locking as opt_locking
|
|
9
8
|
from security.system.authorization import Grant, Security
|
|
10
9
|
import logging
|
|
@@ -18,4 +17,6 @@ def declare_logic():
|
|
|
18
17
|
|
|
19
18
|
Your Code Goes Here - Use code completion (Rule.) to declare rules
|
|
20
19
|
'''
|
|
20
|
+
|
|
21
|
+
# this logic is automatically discovered by declare_logic.py#discover_logic()
|
|
21
22
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
from logic.logic_discovery.auto_discovery import discover_logic
|
|
3
|
+
discover_logic()
|
|
4
|
+
|
|
5
|
+
def handle_all(logic_row: LogicRow): # #als: TIME / DATE STAMPING, OPTIMISTIC LOCKING
|
|
6
|
+
"""
|
|
7
|
+
This is generic - executed for all classes.
|
|
8
|
+
|
|
9
|
+
Invokes optimistic locking, and checks Grant permissions.
|
|
10
|
+
|
|
11
|
+
Also provides user/date stamping.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
logic_row (LogicRow): from LogicBank - old/new row, state
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
if os.getenv("APILOGICPROJECT_NO_FLASK") is not None:
|
|
18
|
+
print("\ndeclare_logic.py Using TestBase\n")
|
|
19
|
+
return # enables rules to be used outside of Flask, e.g., test data loading
|
|
20
|
+
|
|
21
|
+
if logic_row.is_updated() and logic_row.old_row is not None and logic_row.nest_level == 0:
|
|
22
|
+
opt_locking.opt_lock_patch(logic_row=logic_row)
|
|
23
|
+
|
|
24
|
+
Grant.process_updates(logic_row=logic_row)
|
|
25
|
+
|
|
26
|
+
did_stamping = False
|
|
27
|
+
if enable_stamping := False: # #als: DATE / USER STAMPING
|
|
28
|
+
row = logic_row.row
|
|
29
|
+
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
|
|
30
|
+
row.CreatedOn = datetime.datetime.now()
|
|
31
|
+
did_stamping = True
|
|
32
|
+
if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedBy"):
|
|
33
|
+
row.CreatedBy = Security.current_user().id
|
|
34
|
+
# if Config.SECURITY_ENABLED == True else 'public'
|
|
35
|
+
did_stamping = True
|
|
36
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedOn"):
|
|
37
|
+
row.UpdatedOn = datetime.datetime.now()
|
|
38
|
+
did_stamping = True
|
|
39
|
+
if logic_row.ins_upd_dlt == "upd" and hasattr(row, "UpdatedBy"):
|
|
40
|
+
row.UpdatedBy = Security.current_user().id \
|
|
41
|
+
if Config.SECURITY_ENABLED == True else 'public'
|
|
42
|
+
did_stamping = True
|
|
43
|
+
if did_stamping:
|
|
44
|
+
logic_row.log("early_row_event_all_classes - handle_all did stamping")
|
|
45
|
+
Rule.early_row_event_all_classes(early_row_event_all_classes=handle_all)
|
|
46
|
+
|
|
47
|
+
#als rules report
|
|
48
|
+
from api.system import api_utils
|
|
49
|
+
# api_utils.rules_report()
|
|
50
|
+
|
|
51
|
+
app_logger.debug("..logic/declare_logic.py (logic == rules + code)")
|
|
52
|
+
|
|
@@ -176,6 +176,19 @@ class GenAI(object):
|
|
|
176
176
|
using = 'system/genai/temp',
|
|
177
177
|
api_version=self.project.genai_version)
|
|
178
178
|
response_dict = json.loads(data)
|
|
179
|
+
if os.environ.get("APILOGICPROJECT_IS_GENAI_DEMO") is not None and \
|
|
180
|
+
os.environ.get("APILOGICPROJECT_IS_GENAI_DEMO") == 'True':
|
|
181
|
+
genai_demo_response_path = Path('system/genai/examples/genai_demo/genai_demo.response_example')
|
|
182
|
+
if not genai_demo_response_path.is_file():
|
|
183
|
+
log.debug(f'.. standard genai_demo response not found: {genai_demo_response_path}')
|
|
184
|
+
else:
|
|
185
|
+
with open(genai_demo_response_path, 'r') as response_file:
|
|
186
|
+
response_dict = json.load(response_file)
|
|
187
|
+
log.debug(f'.. used standard genai_demo response: {genai_demo_response_path}')
|
|
188
|
+
genai_demo_response_path = Path('system/genai/temp/response.json')
|
|
189
|
+
with open(genai_demo_response_path, 'w') as response_file:
|
|
190
|
+
json.dump(response_dict, response_file, indent=4)
|
|
191
|
+
|
|
179
192
|
else: # for retry from corrected response... eg system/genai/temp/chatgpt_retry.response
|
|
180
193
|
self.resolved_model = "(n/a: model not used for repaired response)"
|
|
181
194
|
log.debug(f'\nUsing [corrected] response from: {self.project.genai_repaired_response}')
|
|
@@ -303,7 +316,7 @@ class GenAI(object):
|
|
|
303
316
|
raw_prompt = file.read()
|
|
304
317
|
prompt = self.get_prompt__with_inserts(raw_prompt=raw_prompt, for_iteration=False) # insert db-specific logic
|
|
305
318
|
self.logic_enabled = False
|
|
306
|
-
if 'LogicBank' in prompt: # if prompt has logic, we need to insert the training
|
|
319
|
+
if 'LogicBank' in prompt and K_LogicBankOff not in prompt: # if prompt has logic, we need to insert the training
|
|
307
320
|
prompt_messages.extend( self.get_prompt_learning_requests())
|
|
308
321
|
self.logic_enabled = True
|
|
309
322
|
if prompt.startswith('You are a '): # if it's a preset, we need to insert the prompt
|
|
@@ -494,13 +507,12 @@ class GenAI(object):
|
|
|
494
507
|
return return_line
|
|
495
508
|
|
|
496
509
|
logic_file = self.project.project_directory_path.joinpath('logic/declare_logic.py')
|
|
497
|
-
if
|
|
510
|
+
if self.logic_enabled:
|
|
511
|
+
translated_logic = genai_svcs.get_code_update_logic_file(rule_list = self.response_dict.rules,
|
|
512
|
+
logic_file_path = logic_file)
|
|
513
|
+
else: # prompt contains LogicBankOff (eg, LBX - some demo thing)
|
|
498
514
|
translated_logic = "\n # Logic from GenAI: (or, use your IDE w/ code completion)\n"
|
|
499
|
-
translated_logic +=
|
|
500
|
-
if self.logic_enabled == False:
|
|
501
|
-
translated_logic = "\n # Logic from GenAI: (or, use your IDE w/ code completion)\n"
|
|
502
|
-
translated_logic += "\n # LogicBank Disabled \n"
|
|
503
|
-
translated_logic += "\n # End Logic from GenAI\n\n"
|
|
515
|
+
translated_logic += "\n # LogicBank Disabled \n"
|
|
504
516
|
utils.insert_lines_at(lines=translated_logic,
|
|
505
517
|
file_name=logic_file,
|
|
506
518
|
at='discover_logic()',
|
|
@@ -541,7 +553,12 @@ class GenAI(object):
|
|
|
541
553
|
is_genai_demo = False
|
|
542
554
|
if os.getenv('APILOGICPROJECT_IS_GENAI_DEMO') is not None or self.project.project_name == 'genai_demo':
|
|
543
555
|
self.project.project_directory_path.joinpath('docs/project_is_genai_demo.txt').touch()
|
|
544
|
-
# and DON'T create test data (db.sqlite already set up in
|
|
556
|
+
# and DON'T create test data (db.sqlite already set up in recursive copy)
|
|
557
|
+
project_docs_response = self.project.project_directory_path.joinpath('docs/response.json')
|
|
558
|
+
with open(project_docs_response, "w") as response_file: # WebG uses this for wg_rules
|
|
559
|
+
json.dump(self.response_dict, response_file, indent=4)
|
|
560
|
+
pass # not possible on create_db_models, since project paths not yet set by api_logic_server
|
|
561
|
+
|
|
545
562
|
else: # normal path
|
|
546
563
|
genai_svcs.rebuild_test_data_for_project(
|
|
547
564
|
use_project_path = self.project.project_directory_path,
|
|
@@ -84,7 +84,9 @@ class GenAILogic(object):
|
|
|
84
84
|
log.debug(f'.. ChatGPT - saving raw response to: system/genai/temp/chatgpt_original.response')
|
|
85
85
|
response_str = genai_svcs.call_chatgpt(messages=self.messages, api_version=self.project.genai_version, using=self.project.genai_using)
|
|
86
86
|
response = json.loads(response_str)
|
|
87
|
-
|
|
87
|
+
# FIXME - perhaps required for fixup (it is failing)
|
|
88
|
+
# the rules & data models are expected to be in docs... not there
|
|
89
|
+
# self.get_and_save_response_data(response=response, file=each_file) # save raw response to docs/logic
|
|
88
90
|
self.response_dict = DotMap(response)
|
|
89
91
|
rule_list = self.response_dict.rules
|
|
90
92
|
each_code_file = self.project.project_directory_path.joinpath(f'logic/logic_discovery/{each_file.stem}.py')
|
|
@@ -354,21 +356,22 @@ class GenAILogic(object):
|
|
|
354
356
|
"""
|
|
355
357
|
translated_logic = ""
|
|
356
358
|
if file.suffix == '.py': # for logic files (not suggestions - they are .txt)
|
|
357
|
-
manager_root = Path(os.getcwd()).parent
|
|
358
|
-
|
|
359
|
+
manager_root = Path(os.getcwd()).parent # FIXME this moved
|
|
360
|
+
logic_prefix_path = self.project.api_logic_server_dir_path.joinpath('fragments/declare_logic_begin.py')
|
|
361
|
+
with open(logic_prefix_path, "r") as logic_prefix_file:
|
|
359
362
|
logic_prefix = logic_prefix_file.read()
|
|
360
|
-
translated_logic = logic_prefix # imports, your code goes here
|
|
363
|
+
translated_logic = logic_prefix # imports (such as `from logic_bank.logic_bank import Rule``), your code goes here
|
|
361
364
|
translated_logic += f'\n # Logic from GenAI {str(datetime.datetime.now().strftime("%B %d, %Y %H:%M:%S"))}:\n\n'
|
|
362
365
|
|
|
363
|
-
|
|
366
|
+
with open(file, "w") as logic_file: # write the prefix, so get_code can fix the imports
|
|
367
|
+
logic_file.write(translated_logic)
|
|
368
|
+
log.debug(f'.. created logic code: {file}')
|
|
369
|
+
|
|
370
|
+
# update logic file with translated rules (and fix import if there is a Rule table)
|
|
371
|
+
rule_code = genai_svcs.get_code_update_logic_file(rule_list = rule_list,
|
|
372
|
+
logic_file_path = file)
|
|
364
373
|
translated_logic += rule_code
|
|
365
374
|
translated_logic += "\n # End Logic from GenAI\n\n"
|
|
366
|
-
|
|
367
|
-
# logic_file_name = file.stem + '.py'
|
|
368
|
-
# logic_file_path = self.project.project_directory_path.joinpath(f'logic/logic_discovery/{logic_file_name}')
|
|
369
|
-
with open(file, "w") as logic_file:
|
|
370
|
-
logic_file.write(translated_logic)
|
|
371
|
-
log.debug(f'.. stored logic code: {file}')
|
|
372
375
|
pass
|
|
373
376
|
|
|
374
377
|
def get_headers_with_openai_api_key(self) -> dict:
|
|
@@ -71,16 +71,99 @@ try: # this is just for WebGenAI
|
|
|
71
71
|
except Exception as exc:
|
|
72
72
|
pass # this is just for WebGenAI, ok to ignore error
|
|
73
73
|
|
|
74
|
-
def
|
|
75
|
-
"""returns code snippet for rules from rule
|
|
74
|
+
def get_code_update_logic_file(rule_list: List[DotMap], logic_file_path: Path = None) -> str:
|
|
75
|
+
"""returns code snippet for rules from rule, updates rules if logic_file_path provided
|
|
76
|
+
|
|
77
|
+
* see avoid_collisions_on_rule
|
|
76
78
|
|
|
77
79
|
Args:
|
|
78
80
|
rule_list (List[DotMap]): list of rules from ChatGPT in DotMap format
|
|
81
|
+
logic_file_path (Path): if provided, update default rule file, with provisions for model named `Rule`
|
|
79
82
|
|
|
80
83
|
Returns:
|
|
81
84
|
str: the rule code
|
|
82
85
|
"""
|
|
83
86
|
|
|
87
|
+
import re
|
|
88
|
+
|
|
89
|
+
patterns = [ re.compile(r"derive=(\w+).*$"),
|
|
90
|
+
re.compile(r"from_parent=(\w+).*$"),
|
|
91
|
+
re.compile(r"Rule\.constraint\(validate=(\w+).*$"),
|
|
92
|
+
re.compile(r"as_sum_of=(\w+).*$"),
|
|
93
|
+
re.compile(r"as_count_of=(\w+).*$")
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
def get_imports(each_line: str, imports: set):
|
|
97
|
+
"""updates imports by extracting the class names to import
|
|
98
|
+
|
|
99
|
+
eg, Rule.constraint(validate=Customer) -> Customer
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
each_line (str): the ChatGPT code
|
|
103
|
+
imports (set): the set of imported classes (updated in place)
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
for each_pattern in patterns:
|
|
107
|
+
match = each_pattern.search(each_line)
|
|
108
|
+
if match:
|
|
109
|
+
the_class_name = match.group(1)
|
|
110
|
+
log.debug(f'.. found class: {the_class_name} in: {each_line}')
|
|
111
|
+
imports.add(the_class_name)
|
|
112
|
+
else:
|
|
113
|
+
pass
|
|
114
|
+
# log.debug(f'.. no classes found in: {each_line}')
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
def insert_logic_into_file_and_avoid_collisions_on_rule(translated_logic: str, imports: set, logic_file_path: Path = None) -> None:
|
|
118
|
+
""" Update logic file with rule code (if provided), with collision avoidance on models named Rule
|
|
119
|
+
|
|
120
|
+
If there's a model named `Rule`, that collides with LogicBank.Rule. So, change LogicBank.Rule refs:
|
|
121
|
+
|
|
122
|
+
1. `from logic_bank.logic_bank import Rule`
|
|
123
|
+
* to: from logic_bank.logic_bank import Rule as LogicBankRule
|
|
124
|
+
2. `Rule.early_row_event_all_classes(early_row_event_all_classes=handle_all)`
|
|
125
|
+
* to: LogicBankRule.early_row_event_all_classes
|
|
126
|
+
* not used in logic_files, so project is None
|
|
127
|
+
3. Users' logic (e.g, Rule.constraint) --> LogicBank.Rule.constraint
|
|
128
|
+
|
|
129
|
+
Beware of these cases:
|
|
130
|
+
1. als create - this is not used (but logic/declare_logic.py must exist)
|
|
131
|
+
2. als genai - uses this, with discovery stuff & Rule.early_event at the end
|
|
132
|
+
3. als genai-logic - logic/logic_discovery files, no discovery stuff at end
|
|
133
|
+
4. webG logic - operates differently, to create logic/wg_rules files (for diagnostics)
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
rule_list (List[DotMap]): list of rules from ChatGPT in DotMap format
|
|
137
|
+
project (Project): a Project object (unless creating a logic file)
|
|
138
|
+
imports (set): the set of imported classes
|
|
139
|
+
"""
|
|
140
|
+
insert_logic = "\n # Logic from GenAI: (or, use your IDE w/ code completion)\n"
|
|
141
|
+
insert_logic += translated_logic
|
|
142
|
+
insert_logic += "\n # End Logic from GenAI\n\n"
|
|
143
|
+
|
|
144
|
+
utils.insert_lines_at(lines=insert_logic,
|
|
145
|
+
file_name=logic_file_path,
|
|
146
|
+
at='discover_logic()',
|
|
147
|
+
after=True)
|
|
148
|
+
|
|
149
|
+
if 'Rule' not in imports:
|
|
150
|
+
return
|
|
151
|
+
if logic_file_path is None: # this needs review for WebGenAI
|
|
152
|
+
log.debug(f'.. .. WebGenAI - avoid_collisions_on_rule: {logic_file_path}')
|
|
153
|
+
return
|
|
154
|
+
# find and replace `Rule` in declare_logic.py:
|
|
155
|
+
utils.replace_string_in_file(search_for='from logic_bank.logic_bank import Rule',
|
|
156
|
+
replace_with='from logic_bank.logic_bank import Rule as LogicBankRule',
|
|
157
|
+
in_file=logic_file_path)
|
|
158
|
+
utils.replace_string_in_file(search_for='Rule.early_row_event_all_classes',
|
|
159
|
+
replace_with='LogicBankRule.early_row_event_all_classes',
|
|
160
|
+
in_file=logic_file_path)
|
|
161
|
+
utils.replace_string_in_file(search_for=' Rule.',
|
|
162
|
+
replace_with=' LogicBankRule.',
|
|
163
|
+
in_file=logic_file_path)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
84
167
|
def remove_logic_halluncinations(each_line: str) -> str:
|
|
85
168
|
"""remove hallucinations from logic
|
|
86
169
|
|
|
@@ -110,6 +193,8 @@ def get_code(rule_list: List[DotMap]) -> str:
|
|
|
110
193
|
pass
|
|
111
194
|
elif 'Rule.constraint' in each_line:
|
|
112
195
|
pass
|
|
196
|
+
elif 'Rule.after_flush_row_event' in each_line:
|
|
197
|
+
pass
|
|
113
198
|
elif 'Rule.allocate' in each_line:
|
|
114
199
|
pass
|
|
115
200
|
elif 'Rule.calculate' in each_line:
|
|
@@ -119,7 +204,9 @@ def get_code(rule_list: List[DotMap]) -> str:
|
|
|
119
204
|
log.debug(f'.. removed hallucination: {each_line}')
|
|
120
205
|
return return_line
|
|
121
206
|
|
|
207
|
+
|
|
122
208
|
translated_logic = ""
|
|
209
|
+
imports = set()
|
|
123
210
|
for each_rule in rule_list:
|
|
124
211
|
comment_line = each_rule.description
|
|
125
212
|
translated_logic += f'\n # {comment_line}\n'
|
|
@@ -129,11 +216,19 @@ def get_code(rule_list: List[DotMap]) -> str:
|
|
|
129
216
|
for each_line in code_lines:
|
|
130
217
|
if 'declare_logic.py' not in each_line:
|
|
131
218
|
each_repaired_line = remove_logic_halluncinations(each_line=each_line)
|
|
219
|
+
get_imports(each_line = each_repaired_line, imports=imports)
|
|
132
220
|
if not each_repaired_line.startswith(' '): # sometimes in indents, sometimes not
|
|
133
221
|
each_repaired_line = ' ' + each_repaired_line
|
|
134
222
|
if 'def declare_logic' not in each_repaired_line:
|
|
135
|
-
translated_logic += each_repaired_line + '\n'
|
|
136
|
-
|
|
223
|
+
translated_logic += each_repaired_line + '\n'
|
|
224
|
+
|
|
225
|
+
# from database.models import Customer, Order, Item, Product
|
|
226
|
+
return_translated_logic = ' from database.models import ' + ', '.join(imports) + '\n' + translated_logic
|
|
227
|
+
insert_logic_into_file_and_avoid_collisions_on_rule(
|
|
228
|
+
imports=imports,
|
|
229
|
+
translated_logic=return_translated_logic,
|
|
230
|
+
logic_file_path=logic_file_path)
|
|
231
|
+
return return_translated_logic
|
|
137
232
|
|
|
138
233
|
def rebuild_test_data_for_project(response: str = 'docs/response.json',
|
|
139
234
|
project: Project = None,
|
|
@@ -168,7 +263,6 @@ def rebuild_test_data_for_project(response: str = 'docs/response.json',
|
|
|
168
263
|
existing_models = rebuild_project
|
|
169
264
|
del existing_models['rules']
|
|
170
265
|
del existing_models['test_data']
|
|
171
|
-
del existing_models['test_data_rows']
|
|
172
266
|
del existing_models['test_data_sqlite']
|
|
173
267
|
rebuild_request.append({"role": "user", "content": json.dumps(existing_models)})
|
|
174
268
|
with open(get_manager_path().joinpath('system/genai/prompt_inserts/rebuild_test_data.prompt'), 'r') as file:
|
|
@@ -436,6 +530,8 @@ def fix_and_write_model_file(response_dict: DotMap, save_dir: str, post_error:
|
|
|
436
530
|
check_for_row_name = False
|
|
437
531
|
if 'Base.metadata.create_all(engine)' in each_fixed_line:
|
|
438
532
|
each_fixed_line = each_fixed_line.replace('Base.metadata.create_all(engine)', '# Base.metadata.create_all(engine)')
|
|
533
|
+
if ',00' in each_fixed_line:
|
|
534
|
+
each_fixed_line = each_fixed_line.replace(',00', ',0')
|
|
439
535
|
return each_fixed_line
|
|
440
536
|
|
|
441
537
|
row_names = list()
|
|
@@ -767,8 +863,9 @@ def call_chatgpt(messages: List[Dict[str, str]], api_version: str, using: str) -
|
|
|
767
863
|
model = api_version
|
|
768
864
|
if model == "": # default from CLI is '', meaning fall back to env variable or system default...
|
|
769
865
|
model = os.getenv("APILOGICSERVER_CHATGPT_MODEL")
|
|
770
|
-
if model is None or model == "*":
|
|
771
|
-
model = "gpt-4o-2024-08-06"
|
|
866
|
+
if model is None or model == "*": # system default chatgpt model
|
|
867
|
+
model = "gpt-4o-2024-08-06" # 33 sec
|
|
868
|
+
# model = "o3-mini" # 130 sec
|
|
772
869
|
with open(Path(using).joinpath('request.json'), "w") as request_file: # save for debug
|
|
773
870
|
json.dump(messages, request_file, indent=4)
|
|
774
871
|
log.info(f'.. saved request: {using}/request.json')
|