ApiLogicServer 14.2.2__py3-none-any.whl → 14.3.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.
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/METADATA +2 -2
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/RECORD +73 -54
- api_logic_server_cli/api_logic_server.py +47 -10
- api_logic_server_cli/api_logic_server_info.yaml +3 -3
- api_logic_server_cli/cli.py +9 -3
- 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/client.py +24 -0
- api_logic_server_cli/genai/genai.py +37 -17
- api_logic_server_cli/genai/genai_logic_builder.py +21 -35
- api_logic_server_cli/genai/genai_svcs.py +109 -13
- api_logic_server_cli/genai/genai_utils.py +0 -1
- 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/config/activate_logicbank.py +8 -4
- api_logic_server_cli/prototypes/base/config/config.py +10 -6
- api_logic_server_cli/prototypes/base/database/bind_dbs.py +2 -1
- api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -5
- api_logic_server_cli/prototypes/base/logic/declare_logic.py +8 -3
- api_logic_server_cli/prototypes/base/logic/load_verify_rules.py +216 -0
- api_logic_server_cli/prototypes/base/logic/logic_discovery/auto_discovery.py +23 -11
- api_logic_server_cli/prototypes/genai_demo/database/models.py +11 -55
- api_logic_server_cli/prototypes/genai_demo/logic/declare_logic.py +29 -21
- api_logic_server_cli/prototypes/manager/.vscode/launch.json +3 -3
- api_logic_server_cli/prototypes/manager/README.md +25 -10
- api_logic_server_cli/prototypes/manager/system/genai/create_db_models_inserts/create_db_models_imports.py +1 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +19 -18
- 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/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 +8 -0
- api_logic_server_cli/prototypes/manager/system/genai/learning_requests/logic_bank_api.prompt +14 -10
- 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 +2 -1
- api_logic_server_cli/tools/mini_skel/logic/load_verify_rules.py +1 -1
- api_logic_server_cli/tools/mini_skel/run.py +1 -0
- 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
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/LICENSE +0 -0
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/WHEEL +0 -0
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/entry_points.txt +0 -0
- {ApiLogicServer-14.2.2.dist-info → ApiLogicServer-14.3.0.dist-info}/top_level.txt +0 -0
|
@@ -23,18 +23,30 @@ def discover_logic():
|
|
|
23
23
|
spec.loader.exec_module(each_logic_file) # runs "bare" module code (e.g., initialization)
|
|
24
24
|
each_logic_file.declare_logic() # invoke create function
|
|
25
25
|
|
|
26
|
+
# if False and Path(__file__).parent.parent.parent.joinpath("docs/project_is_genai_demo.txt").exists():
|
|
27
|
+
# return # for genai_demo, logic is in logic/declare_logic.py (so ignore logic_discovery)
|
|
28
|
+
|
|
26
29
|
wg_logic_path = Path(__file__).parent.parent.joinpath("wg_rules")
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
logic.append(
|
|
35
|
-
|
|
36
|
-
spec.loader.exec_module(
|
|
37
|
-
|
|
30
|
+
if wg_logic_path.exists():
|
|
31
|
+
run_local = os.environ.get("WG_PROJECT") is None # eg, running export locally
|
|
32
|
+
# run_local = False # for debug
|
|
33
|
+
if run_local:
|
|
34
|
+
wg_export_logic_path = Path(__file__).parent.parent.parent.joinpath("logic/wg_rules/active_rules_export.py")
|
|
35
|
+
if wg_export_logic_path.is_file():
|
|
36
|
+
spec = importlib.util.spec_from_file_location("module.name", wg_export_logic_path)
|
|
37
|
+
logic.append(str(wg_export_logic_path))
|
|
38
|
+
wg_export_logic_file = importlib.util.module_from_spec(spec)
|
|
39
|
+
spec.loader.exec_module(wg_export_logic_file) # runs "bare" module code (e.g., initialization)
|
|
40
|
+
wg_export_logic_file.declare_logic() # invoke create function
|
|
41
|
+
else:
|
|
42
|
+
for root, dirs, files in os.walk(wg_logic_path):
|
|
43
|
+
for file in files:
|
|
44
|
+
if file.endswith(".py") and 'active_rules_export.py' != file:
|
|
45
|
+
spec = importlib.util.spec_from_file_location("module.name", wg_logic_path.joinpath(file))
|
|
46
|
+
logic.append(file)
|
|
47
|
+
each_logic_file = importlib.util.module_from_spec(spec)
|
|
48
|
+
spec.loader.exec_module(each_logic_file) # runs "bare" module code (e.g., initialization)
|
|
49
|
+
each_logic_file.init_rule() # invoke create function
|
|
38
50
|
|
|
39
51
|
app_logger.info(f"..discovered logic: {logic}")
|
|
40
52
|
return
|
|
@@ -16,9 +16,9 @@ from sqlalchemy.ext.declarative import declarative_base
|
|
|
16
16
|
# mypy: ignore-errors
|
|
17
17
|
########################################################################################################################
|
|
18
18
|
|
|
19
|
-
from
|
|
19
|
+
from database.system.SAFRSBaseX import SAFRSBaseX, TestBase
|
|
20
20
|
from flask_login import UserMixin
|
|
21
|
-
import safrs, flask_sqlalchemy
|
|
21
|
+
import safrs, flask_sqlalchemy, os
|
|
22
22
|
from safrs import jsonapi_attr
|
|
23
23
|
from flask_sqlalchemy import SQLAlchemy
|
|
24
24
|
from sqlalchemy.orm import relationship
|
|
@@ -35,12 +35,16 @@ metadata = Base.metadata
|
|
|
35
35
|
|
|
36
36
|
from sqlalchemy.dialects.sqlite import *
|
|
37
37
|
|
|
38
|
+
if os.getenv('APILOGICPROJECT_NO_FLASK') is None or os.getenv('APILOGICPROJECT_NO_FLASK') == 'None':
|
|
39
|
+
Base = SAFRSBaseX # enables rules to be used outside of Flask, e.g., test data loading
|
|
40
|
+
else:
|
|
41
|
+
Base = TestBase # ensure proper types, so rules work for data loading
|
|
42
|
+
print('*** Models.py Using TestBase ***')
|
|
38
43
|
|
|
39
44
|
|
|
40
|
-
class Customer(
|
|
45
|
+
class Customer(Base):
|
|
41
46
|
__tablename__ = 'Customers'
|
|
42
47
|
_s_collection_name = 'Customer' # type: ignore
|
|
43
|
-
__bind_key__ = 'None'
|
|
44
48
|
|
|
45
49
|
CustomerID = Column(Integer, primary_key=True)
|
|
46
50
|
CustomerName = Column(Text, nullable=False)
|
|
@@ -54,23 +58,10 @@ class Customer(SAFRSBase, Base):
|
|
|
54
58
|
# child relationships (access children)
|
|
55
59
|
OrderList : Mapped[List["Order"]] = relationship(back_populates="Customer")
|
|
56
60
|
|
|
57
|
-
@jsonapi_attr
|
|
58
|
-
def _check_sum_(self): # type: ignore [no-redef]
|
|
59
|
-
return None if isinstance(self, flask_sqlalchemy.model.DefaultMeta) \
|
|
60
|
-
else self._check_sum_property if hasattr(self,"_check_sum_property") \
|
|
61
|
-
else None # property does not exist during initialization
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
def _check_sum_(self, value): # type: ignore [no-redef]
|
|
65
|
-
self._check_sum_property = value
|
|
66
|
-
|
|
67
|
-
S_CheckSum = _check_sum_
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class Product(SAFRSBase, Base):
|
|
62
|
+
class Product(Base):
|
|
71
63
|
__tablename__ = 'Products'
|
|
72
64
|
_s_collection_name = 'Product' # type: ignore
|
|
73
|
-
__bind_key__ = 'None'
|
|
74
65
|
|
|
75
66
|
ProductID = Column(Integer, primary_key=True)
|
|
76
67
|
ProductName = Column(Text, nullable=False)
|
|
@@ -82,23 +73,11 @@ class Product(SAFRSBase, Base):
|
|
|
82
73
|
# child relationships (access children)
|
|
83
74
|
ItemList : Mapped[List["Item"]] = relationship(back_populates="Product")
|
|
84
75
|
|
|
85
|
-
@jsonapi_attr
|
|
86
|
-
def _check_sum_(self): # type: ignore [no-redef]
|
|
87
|
-
return None if isinstance(self, flask_sqlalchemy.model.DefaultMeta) \
|
|
88
|
-
else self._check_sum_property if hasattr(self,"_check_sum_property") \
|
|
89
|
-
else None # property does not exist during initialization
|
|
90
|
-
|
|
91
|
-
@_check_sum_.setter
|
|
92
|
-
def _check_sum_(self, value): # type: ignore [no-redef]
|
|
93
|
-
self._check_sum_property = value
|
|
94
|
-
|
|
95
|
-
S_CheckSum = _check_sum_
|
|
96
76
|
|
|
97
77
|
|
|
98
|
-
class Order(
|
|
78
|
+
class Order(Base):
|
|
99
79
|
__tablename__ = 'Orders'
|
|
100
80
|
_s_collection_name = 'Order' # type: ignore
|
|
101
|
-
__bind_key__ = 'None'
|
|
102
81
|
|
|
103
82
|
OrderID = Column(Integer, primary_key=True)
|
|
104
83
|
CustomerID = Column(ForeignKey('Customers.CustomerID'))
|
|
@@ -113,23 +92,11 @@ class Order(SAFRSBase, Base):
|
|
|
113
92
|
# child relationships (access children)
|
|
114
93
|
ItemList : Mapped[List["Item"]] = relationship(back_populates="Order")
|
|
115
94
|
|
|
116
|
-
@jsonapi_attr
|
|
117
|
-
def _check_sum_(self): # type: ignore [no-redef]
|
|
118
|
-
return None if isinstance(self, flask_sqlalchemy.model.DefaultMeta) \
|
|
119
|
-
else self._check_sum_property if hasattr(self,"_check_sum_property") \
|
|
120
|
-
else None # property does not exist during initialization
|
|
121
95
|
|
|
122
|
-
@_check_sum_.setter
|
|
123
|
-
def _check_sum_(self, value): # type: ignore [no-redef]
|
|
124
|
-
self._check_sum_property = value
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class Item(SAFRSBase, Base):
|
|
97
|
+
class Item(Base):
|
|
130
98
|
__tablename__ = 'Items'
|
|
131
99
|
_s_collection_name = 'Item' # type: ignore
|
|
132
|
-
__bind_key__ = 'None'
|
|
133
100
|
|
|
134
101
|
ItemID = Column(Integer, primary_key=True)
|
|
135
102
|
OrderID = Column(ForeignKey('Orders.OrderID'))
|
|
@@ -144,14 +111,3 @@ class Item(SAFRSBase, Base):
|
|
|
144
111
|
|
|
145
112
|
# child relationships (access children)
|
|
146
113
|
|
|
147
|
-
@jsonapi_attr
|
|
148
|
-
def _check_sum_(self): # type: ignore [no-redef]
|
|
149
|
-
return None if isinstance(self, flask_sqlalchemy.model.DefaultMeta) \
|
|
150
|
-
else self._check_sum_property if hasattr(self,"_check_sum_property") \
|
|
151
|
-
else None # property does not exist during initialization
|
|
152
|
-
|
|
153
|
-
@_check_sum_.setter
|
|
154
|
-
def _check_sum_(self, value): # type: ignore [no-redef]
|
|
155
|
-
self._check_sum_property = value
|
|
156
|
-
|
|
157
|
-
S_CheckSum = _check_sum_
|
|
@@ -20,19 +20,16 @@ def declare_logic():
|
|
|
20
20
|
''' Declarative multi-table derivations and constraints, extensible with Python.
|
|
21
21
|
|
|
22
22
|
Brief background: see readme_declare_logic.md
|
|
23
|
-
|
|
24
|
-
Your Code Goes Here - Use code completion (Rule.) to declare rules
|
|
25
23
|
|
|
26
|
-
GenAI:
|
|
24
|
+
GenAI: the following prompt was sent to GenAI-Logic, which translated it into the code below:
|
|
27
25
|
|
|
28
|
-
Use
|
|
26
|
+
Use case: Check Credit
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
5. Store the Items.UnitPrice as a copy from Product.UnitPrice
|
|
28
|
+
1. The Customer's balance is less than the credit limit
|
|
29
|
+
2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
|
|
30
|
+
3. The Order's amount_total is the sum of the Item amount
|
|
31
|
+
4. The Item amount is the quantity * unit_price
|
|
32
|
+
5. The Item unit_price is copied from the Product unit_price
|
|
36
33
|
'''
|
|
37
34
|
|
|
38
35
|
from logic_bank.logic_bank import Rule
|
|
@@ -40,39 +37,50 @@ def declare_logic():
|
|
|
40
37
|
from logic.logic_discovery.auto_discovery import discover_logic
|
|
41
38
|
discover_logic()
|
|
42
39
|
|
|
43
|
-
# Logic from GenAI: (or, use your IDE w/ code completion)
|
|
40
|
+
# Logic from GenAI: (or, use your IDE w/ code completion)
|
|
41
|
+
|
|
42
|
+
# Ensures the customer's balance is less than the credit limit.
|
|
43
|
+
Rule.constraint(validate=Customer,
|
|
44
|
+
as_condition=lambda row: row.Balance <= row.CreditLimit,
|
|
45
|
+
error_msg="Customer balance ({row.Balance}) exceeds credit limit ({row.CreditLimit})")
|
|
46
|
+
|
|
47
|
+
# Computes the customer's balance as the sum of unshipped orders.
|
|
44
48
|
Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal, where=lambda row: row.ShipDate is None)
|
|
49
|
+
|
|
50
|
+
# Computes the total amount of an order as the sum of item amounts.
|
|
45
51
|
Rule.sum(derive=Order.AmountTotal, as_sum_of=Item.Amount)
|
|
52
|
+
|
|
53
|
+
# Calculates the item amount as the quantity times unit price. (original rule, prior to iteration)
|
|
46
54
|
# Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)
|
|
55
|
+
|
|
56
|
+
# Copies the unit price from the parent product to the item.
|
|
47
57
|
Rule.copy(derive=Item.UnitPrice, from_parent=Product.UnitPrice)
|
|
48
|
-
Rule.constraint(validate=Customer,
|
|
49
|
-
as_condition=lambda row: row.Balance <= row.CreditLimit,
|
|
50
|
-
error_msg="Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})")
|
|
51
58
|
|
|
52
59
|
# End Logic from GenAI
|
|
53
60
|
|
|
61
|
+
|
|
62
|
+
#als: Demonstrate that logic == Rules + Python (for extensibility)
|
|
63
|
+
|
|
64
|
+
# 4. Items.Amount = Quantity * UnitPrice, altered with IDE for CarbonNeutral discount
|
|
54
65
|
def derive_amount(row: Item, old_row: Item, logic_row: LogicRow):
|
|
55
66
|
amount = row.Quantity * row.UnitPrice
|
|
56
67
|
if row.Product.CarbonNeutral == True and row.Quantity >= 10:
|
|
57
68
|
amount = amount * Decimal(0.9) # breakpoint here
|
|
58
69
|
return amount
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Rule.formula(derive=Item.Amount, calling=derive_amount)
|
|
62
|
-
|
|
63
|
-
#als: Demonstrate that logic == Rules + Python (for extensibility)
|
|
70
|
+
# now register function; note logic ordering is automatic
|
|
71
|
+
Rule.formula(derive=Item.Amount, calling=derive_amount)
|
|
64
72
|
|
|
65
73
|
def send_order_to_shipping(row: Order, old_row: Order, logic_row: LogicRow):
|
|
66
74
|
""" #als: Send Kafka message formatted by OrderShipping RowDictMapper
|
|
67
75
|
|
|
68
76
|
Format row per shipping requirements, and send (e.g., a message)
|
|
69
77
|
|
|
70
|
-
NB: the after_flush event makes Order.Id avaible.
|
|
78
|
+
NB: the after_flush event makes Order.Id avaible.
|
|
71
79
|
|
|
72
80
|
Args:
|
|
73
81
|
row (Order): inserted Order
|
|
74
82
|
old_row (Order): n/a
|
|
75
|
-
logic_row (LogicRow): bundles curr/old row, with ins/upd/dlt
|
|
83
|
+
logic_row (LogicRow): bundles curr/old row, with ins/upd/dlt (etc) state
|
|
76
84
|
"""
|
|
77
85
|
if logic_row.is_inserted():
|
|
78
86
|
kafka_producer.send_kafka_message(logic_row=logic_row,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "0.2.0",
|
|
6
6
|
"configurations": [
|
|
7
7
|
{
|
|
8
|
-
"name": "1. GENAI - Create
|
|
8
|
+
"name": "1. GENAI - Create genai_logic demo project",
|
|
9
9
|
"type": "debugpy",
|
|
10
10
|
"request": "launch",
|
|
11
11
|
"program": "${workspaceFolder}/venv/lib/python3.12/site-packages/api_logic_server_cli/cli.py",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"APILOGICSERVER_DEBUG": "False",
|
|
19
19
|
"OPT_LOCKING": "optional"},
|
|
20
20
|
"justMyCode": false,
|
|
21
|
-
"args": [ "genai", "--retries=-1",
|
|
22
|
-
"--using=${workspaceFolder}/system/genai/examples
|
|
21
|
+
"args": [ "genai", "--retries=-1", "--project-name=genai_demo",
|
|
22
|
+
"--using=${workspaceFolder}/system/genai/examples/genai_demo/genai_demo_informal.prompt"],
|
|
23
23
|
"console": "internalConsole",
|
|
24
24
|
"internalConsoleOptions": "openOnSessionStart"
|
|
25
25
|
},
|
|
@@ -101,7 +101,7 @@ Then, try your own databases [(db-url examples here)](https://apilogicserver.git
|
|
|
101
101
|
1. If you have signed up, this will create and open a project called `genai_demo` from `genai_demo.prompt` (available in left Explorer pane):
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
|
-
als genai --using=system/genai/examples/genai_demo/genai_demo.prompt
|
|
104
|
+
als genai --using=system/genai/examples/genai_demo/genai_demo.prompt --project-name=genai_demo
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
|
|
@@ -109,7 +109,7 @@ als genai --using=system/genai/examples/genai_demo/genai_demo.prompt
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
```bash
|
|
112
|
-
als genai --
|
|
112
|
+
als genai --repaired-response=system/genai/examples/genai_demo/genai_demo_iteration/005_create_db_models.response-example --project-name=genai_demo
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
Verify it's operating properly:
|
|
@@ -140,7 +140,7 @@ Verify it's operating properly:
|
|
|
140
140
|
|
|
141
141
|
2. Your created project is opened in your IDE, ready to execute and customize.
|
|
142
142
|
|
|
143
|
-
a. Review `
|
|
143
|
+
a. Review `Tutorial.md`, Explore Customizations.
|
|
144
144
|
|
|
145
145
|

|
|
146
146
|
|
|
@@ -149,9 +149,22 @@ Verify it's operating properly:
|
|
|
149
149
|
|
|
150
150
|
<details markdown>
|
|
151
151
|
|
|
152
|
-
<summary> You can iterate the data model
|
|
152
|
+
<summary> You can iterate the logic and data model</summary>
|
|
153
153
|
|
|
154
|
-
<br>
|
|
154
|
+
<br>Logic iterations are particuarly useful. For example, here we take the basic check-credit logic, and add:
|
|
155
|
+
|
|
156
|
+
> Provide a 10% discount when buying more than 10 carbon neutral products.<br><br>The Item carbon neutral is copied from the Product carbon neutral
|
|
157
|
+
|
|
158
|
+
Explore [genai_demo_iteration_discount](system/genai/examples/genai_demo/genai_demo_iteration_discount). This will add carbon_neutral to the data model, and update the logic to provide the discount:
|
|
159
|
+
|
|
160
|
+
```bash title='Iterate Business Logic'
|
|
161
|
+
# Iterate with data model and logic
|
|
162
|
+
als genai --project-name='genai_demo_with_logic' --using=system/genai/examples/genai_demo/genai_demo_iteration
|
|
163
|
+
# open Docs/db.dbml
|
|
164
|
+
```
|
|
165
|
+
<br>
|
|
166
|
+
|
|
167
|
+
You can add new columns/tables, while keeping the prior model intact:
|
|
155
168
|
|
|
156
169
|
```bash title='Iterate Without Logic'
|
|
157
170
|
# Step 1 - create without logic
|
|
@@ -164,7 +177,9 @@ als genai --project-name='genai_demo_no_logic' --using=system/genai/examples/gen
|
|
|
164
177
|
als genai --project-name='genai_demo_with_logic' --using=system/genai/examples/genai_demo/genai_demo_iteration
|
|
165
178
|
# open Docs/db.dbml
|
|
166
179
|
```
|
|
167
|
-
|
|
180
|
+
|
|
181
|
+
Explore [genai_demo_iteration](system/genai/examples/genai_demo/genai_demo_iteration) - observe the `--using` is a *directory* of prompts. These include the prompts from the first example, plus an *iteration prompt* (`004_iteration_renames_logic.prompt`) to rename tables and add logic.
|
|
182
|
+
|
|
168
183
|
|
|
169
184
|
</details>
|
|
170
185
|
</br>
|
|
@@ -274,7 +289,7 @@ After starting the [Manager](https://apilogicserver.github.io/Docs/Manager):
|
|
|
274
289
|
|
|
275
290
|
```bash title="0. Create Project Requiring Fixup"
|
|
276
291
|
# 0. Create a project requiring fixup
|
|
277
|
-
als genai --
|
|
292
|
+
als genai --repaired-response=system/genai/examples/genai_demo/genai_demo_fixup_required.json --project-name=genai_demo_fixup_required
|
|
278
293
|
```
|
|
279
294
|
|
|
280
295
|
If you run this project, you will observe that it fails with:
|
|
@@ -298,7 +313,7 @@ Finally, use the created [fixup files](genai_demo_fixup_required/docs/fixup/) to
|
|
|
298
313
|
```bash title="2. Rebuild the project from the fixup response data model"
|
|
299
314
|
# 2. Rebuild the project from the fixup response data model
|
|
300
315
|
cd ../
|
|
301
|
-
als genai --
|
|
316
|
+
als genai --repaired-response=genai_demo_fixup_required/docs/fixup/response_fixup.json --project-name=fixed_project
|
|
302
317
|
```
|
|
303
318
|
|
|
304
319
|
|
|
@@ -390,7 +405,7 @@ als create --project-name=genai_demo --from-model=system/genai/temp/create_db_mo
|
|
|
390
405
|
Or, correct the chatgpt response, and
|
|
391
406
|
|
|
392
407
|
```bash
|
|
393
|
-
als genai --
|
|
408
|
+
als genai --repaired-response=system/genai/examples/genai_demo/genai_demo.response_example --project-name=genai_demo
|
|
394
409
|
```
|
|
395
410
|
|
|
396
411
|
We have seen failures such as:
|
|
@@ -583,7 +598,7 @@ als genai --using=system/genai/examples/genai_demo/genai_demo.prompt
|
|
|
583
598
|
|
|
584
599
|
# Or, Microservice Automation from Saved Response
|
|
585
600
|
# Admin App, API, Project
|
|
586
|
-
als genai --
|
|
601
|
+
als genai --repaired-response=system/genai/temp/chatgpt_retry.response
|
|
587
602
|
|
|
588
603
|
# Logic and Security
|
|
589
604
|
# - see logic (logic/declare_logic.py, logic/cocktail-napkin.jpg); add an Order and Item
|
|
@@ -7,6 +7,7 @@ import decimal
|
|
|
7
7
|
import logging
|
|
8
8
|
import sqlalchemy
|
|
9
9
|
from sqlalchemy.sql import func
|
|
10
|
+
from decimal import Decimal
|
|
10
11
|
from logic_bank.logic_bank import Rule
|
|
11
12
|
from sqlalchemy import create_engine, Column, Integer, String, Float, ForeignKey, Date, DateTime, Numeric, Boolean, Text, DECIMAL
|
|
12
13
|
from sqlalchemy.types import *
|
api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example
CHANGED
|
@@ -2,62 +2,63 @@
|
|
|
2
2
|
"models": [
|
|
3
3
|
{
|
|
4
4
|
"classname": "Customer",
|
|
5
|
-
"code": "class Customer(Base):\n __tablename__ = '
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"name": "customers"
|
|
5
|
+
"code": "class Customer(Base):\n __tablename__ = 'customer'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String, unique=True)\n balance = Column(DECIMAL)\n credit_limit = Column(DECIMAL)",
|
|
6
|
+
"description": "Represents a customer in the system with unique name, balance, and credit limit attributes.",
|
|
7
|
+
"name": "Customer"
|
|
9
8
|
},
|
|
10
9
|
{
|
|
11
10
|
"classname": "Order",
|
|
12
|
-
"code": "class Order(Base):\n __tablename__ = '
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"name": "orders"
|
|
11
|
+
"code": "class Order(Base):\n __tablename__ = 'order'\n id = Column(Integer, primary_key=True, autoincrement=True)\n customer_id = Column(Integer, ForeignKey('customer.id'))\n date_shipped = Column(Date)\n amount_total = Column(DECIMAL)\n notes = Column(String)",
|
|
12
|
+
"description": "Represents an order made by a customer, including a notes field.",
|
|
13
|
+
"name": "Order"
|
|
16
14
|
},
|
|
17
15
|
{
|
|
18
16
|
"classname": "Item",
|
|
19
|
-
"code": "class Item(Base):\n __tablename__ = '
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"name": "items"
|
|
17
|
+
"code": "class Item(Base):\n __tablename__ = 'item'\n id = Column(Integer, primary_key=True, autoincrement=True)\n order_id = Column(Integer, ForeignKey('order.id'))\n product_id = Column(Integer, ForeignKey('product.id'))\n quantity = Column(Integer, nullable=False)\n unit_price = Column(DECIMAL)\n amount = Column(DECIMAL)",
|
|
18
|
+
"description": "Represents an item in an order, including quantity and pricing details.",
|
|
19
|
+
"name": "Item"
|
|
23
20
|
},
|
|
24
21
|
{
|
|
25
22
|
"classname": "Product",
|
|
26
|
-
"code": "class Product(Base):\n __tablename__ = '
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"name": "products"
|
|
23
|
+
"code": "class Product(Base):\n __tablename__ = 'product'\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(String)\n unit_price = Column(DECIMAL)",
|
|
24
|
+
"description": "Represents a product available in the system with a unit price.",
|
|
25
|
+
"name": "Product"
|
|
30
26
|
}
|
|
31
27
|
],
|
|
32
28
|
"rules": [
|
|
33
29
|
{
|
|
34
30
|
"name": "Customer Balance Constraint",
|
|
35
|
-
"description": "Ensures the customer's balance
|
|
31
|
+
"description": "Ensures the customer's balance is aligned with the credit limit.",
|
|
36
32
|
"use_case": "Customer.balance <= credit_limit",
|
|
37
|
-
"
|
|
33
|
+
"entity": "Customer",
|
|
34
|
+
"code": "Rule.constraint(validate=Customer,\n as_condition=lambda row: row.balance <= row.credit_limit,\n error_msg='Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})')"
|
|
38
35
|
},
|
|
39
36
|
{
|
|
40
37
|
"name": "Customer Balance Derivation",
|
|
41
38
|
"description": "Calculates the customer's balance as the sum of orders' amount_total where date_shipped is null.",
|
|
42
39
|
"use_case": "Customer.balance = Sum(Order.amount_total where date_shipped is null)",
|
|
40
|
+
"entity": "Customer",
|
|
43
41
|
"code": "Rule.sum(derive=Customer.balance, as_sum_of=Order.amount_total, where=lambda row: row.date_shipped is None)"
|
|
44
42
|
},
|
|
45
43
|
{
|
|
46
44
|
"name": "Order Amount Total Derivation",
|
|
47
45
|
"description": "Calculates order's amount_total as the sum of item amounts.",
|
|
48
46
|
"use_case": "Order.amount_total = Sum(Item.amount)",
|
|
47
|
+
"entity": "Order",
|
|
49
48
|
"code": "Rule.sum(derive=Order.amount_total, as_sum_of=Item.amount)"
|
|
50
49
|
},
|
|
51
50
|
{
|
|
52
51
|
"name": "Item Amount Derivation",
|
|
53
52
|
"description": "Calculates item amount as quantity multiplied by unit price.",
|
|
54
53
|
"use_case": "Item.amount = quantity * unit_price",
|
|
54
|
+
"entity": "Item",
|
|
55
55
|
"code": "Rule.formula(derive=Item.amount, as_expression=lambda row: row.quantity * row.unit_price)"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"name": "Copy Item Unit Price",
|
|
59
59
|
"description": "Copies the product's unit price to the item.",
|
|
60
60
|
"use_case": "Store the Item.unit_price as a copy from Product.unit_price",
|
|
61
|
+
"entity": "Item",
|
|
61
62
|
"code": "Rule.copy(derive=Item.unit_price, from_parent=Product.unit_price)"
|
|
62
63
|
}
|
|
63
64
|
],
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
You are a data modelling expert and python software architect who expands on user input ideas. You create data models with at least 4 tables
|