ApiLogicServer 14.3.25__py3-none-any.whl → 14.5.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.
- api_logic_server_cli/add_cust/add_cust.py +283 -0
- api_logic_server_cli/api_logic_server.py +18 -250
- api_logic_server_cli/api_logic_server_info.yaml +3 -3
- api_logic_server_cli/cli.py +54 -35
- 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__/create_db_from_model.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/dbml.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 +47 -0
- api_logic_server_cli/create_from_model/create_db_from_model.py +2 -0
- api_logic_server_cli/create_from_model/dbml.py +113 -58
- api_logic_server_cli/create_from_model/ont_build.py +102 -74
- api_logic_server_cli/create_from_model/ont_create.py +7 -6
- api_logic_server_cli/create_from_model/safrs-react-admin-npm-build/static/.DS_Store +0 -0
- api_logic_server_cli/database/basic_demo.sqlite +0 -0
- api_logic_server_cli/database/basic_demo.txt +1 -0
- api_logic_server_cli/database/basic_demo_wg.sqlite +0 -0
- api_logic_server_cli/database/nw-gold-fix.sql +62 -0
- api_logic_server_cli/database/nw-gold.sqlite +0 -0
- api_logic_server_cli/{prototypes/manager/webgenai → fragments}/docker-compose.yml +1 -1
- api_logic_server_cli/genai/genai.py +42 -11
- api_logic_server_cli/genai/genai_graphics.py +252 -38
- api_logic_server_cli/genai/genai_svcs.py +20 -12
- api_logic_server_cli/manager.py +22 -12
- api_logic_server_cli/prototypes/.DS_Store +0 -0
- api_logic_server_cli/prototypes/base/.DS_Store +0 -0
- api_logic_server_cli/prototypes/base/.vscode/launch.json +22 -2
- api_logic_server_cli/prototypes/base/api/expose_api_models.py +3 -1
- api_logic_server_cli/prototypes/base/api_logic_server_run.py +5 -2
- api_logic_server_cli/prototypes/base/config/activate_logicbank.py +1 -0
- api_logic_server_cli/prototypes/base/config/config.py +123 -25
- api_logic_server_cli/prototypes/base/config/default.env +7 -1
- api_logic_server_cli/prototypes/base/config/logging.yml +1 -0
- api_logic_server_cli/prototypes/base/config/server_setup.py +33 -1
- api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -2
- api_logic_server_cli/prototypes/base/devops/docker-standard-image/docker-compose-standard-image.yml +7 -2
- api_logic_server_cli/prototypes/base/docs/training/logic_bank_api.prompt +314 -0
- api_logic_server_cli/prototypes/base/docs/training/logic_example.py +41 -0
- api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +12 -5
- api_logic_server_cli/prototypes/base/integration/n8n/n8n_producer.py +68 -21
- api_logic_server_cli/prototypes/base/integration/n8n/n8n_readme.md +19 -0
- api_logic_server_cli/prototypes/base/integration/system/FlaskKafka.py +5 -1
- api_logic_server_cli/prototypes/base/test/basic/server_test.py +1 -1
- api_logic_server_cli/prototypes/base/ui/templates/bar_chart.jinja +64 -0
- api_logic_server_cli/prototypes/basic_demo/README.md +29 -52
- api_logic_server_cli/prototypes/basic_demo/customizations/api/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/mcp_server_executor.py +138 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py +92 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/proper_update_def.json +71 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env +13 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +131 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/1_langchain_loader.py +71 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/2_gpt_mcp_prompt.txt +19 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +13 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +295 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_schema.txt +47 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_server_discovery.json +9 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_flow.png +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_orchestration.yaml +49 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/wny mcp flows.png +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/natlang_to_api.py +73 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/curl.txt +5 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP Overview.png +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Arch.png +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Overview_Executor.png +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/1 - prompt_messages_array.json +10 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/2 - completion_tool_context.json +12 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/llm_schema.txt +38 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_2.yaml +17393 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3.yaml +16660 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3_relaxed.yaml +109 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_server.py +51 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_serverZ.py +72 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/validate_jsonapi.py +64 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/run_executor.py +23 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/swagger_converter.py +65 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/z_old/3_executor_test_agent.py +52 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/3_executor_test_agent.py +52 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/README_functon.md +201 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/ai_plugin.json +17 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/nw-swagger_3.json +1731 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/snippets.txt +5 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3 genai_demo_with_get.json +1731 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3.json +1782 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo.json +264 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo_with_update.json +1782 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +62 -44
- api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py +11 -12
- api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +166 -0
- api_logic_server_cli/prototypes/basic_demo/iteration/api/{customize_api.py → api_discovery/order_b2b.py} +17 -23
- api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderB2B.py +6 -5
- api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderShipping.py +4 -4
- api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +69 -43
- api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +125 -50
- api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +1 -1
- api_logic_server_cli/prototypes/manager/README.md +30 -4
- api_logic_server_cli/prototypes/manager/README_X.md +663 -0
- api_logic_server_cli/prototypes/manager/system/genai/.DS_Store +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/.DS_Store +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/.DS_Store +0 -0
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +0 -10
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +32 -10
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/002_create_db_models.prompt +4 -4
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/003_create_db_models.response +77 -47
- api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +1 -1
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/dashboard_services.jinja +83 -0
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_dashboard_WIP.py +34 -0
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/{graphics_services.py → graphics_services_api_xxx.py} +0 -9
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db.jinja +46 -0
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db_each_method.jinja +36 -0
- api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/graphics.prompt +7 -3
- api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/response_format.prompt +8 -1
- api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +100 -0
- api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.sh +116 -0
- api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/readme.md +7 -0
- api_logic_server_cli/prototypes/manager/system/style-guide.yaml +2 -2
- api_logic_server_cli/prototypes/manager/webgenai/README.md +6 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/count_orders_by_category.prompt +1 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/order_count_by_month.prompt +1 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/request copy.json +892 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/request.json +6 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/response.json +17 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/response.yaml +59 -0
- api_logic_server_cli/prototypes/nw/docs/graphics/sales_by_category.prompt +1 -0
- api_logic_server_cli/prototypes/nw/ui/admin/home.js +5 -4
- api_logic_server_cli/prototypes/nw/ui/app_model_custom.yaml +851 -1082
- api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +45 -26
- api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/openapi.py +130 -0
- api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/proper_update_def.json +71 -0
- api_logic_server_cli/prototypes/nw_no_cust/config/default.env +13 -0
- api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/count_orders_by_category.prompt +1 -0
- api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/sales_by_employee.prompt +1 -0
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/nginx/nginx.conf +2 -2
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/package-lock.json +9725 -1180
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +6 -9
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/app.config.ts +2 -1
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/shared/app.services.config.ts +1 -1
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/css/app.scss +4 -0
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/en.json +1 -1
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/es.json +14 -12
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.prod.ts +5 -5
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.ts +5 -5
- api_logic_server_cli/prototypes/ont_app/templates/app_config.jinja +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/date_template.html +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/detail_template.html +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/new_template.html +16 -16
- api_logic_server_cli/prototypes/ont_app/templates/textarea_template.html +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/timestamp_template.html +1 -1
- api_logic_server_cli/prototypes/sample_ai/logic/declare_logic.py +30 -13
- apilogicserver-14.5.0.dist-info/METADATA +76 -0
- {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/RECORD +160 -88
- {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/WHEEL +1 -1
- api_logic_server_cli/prototypes/basic_demo/apply_customizations.ps1 +0 -17
- api_logic_server_cli/prototypes/basic_demo/apply_customizations.sh +0 -14
- api_logic_server_cli/prototypes/basic_demo/apply_iteration.ps1 +0 -20
- api_logic_server_cli/prototypes/basic_demo/apply_iteration.sh +0 -15
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_jsonapi_rpc.jinja +0 -37
- api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_unused.jinja +0 -38
- apilogicserver-14.3.25.dist-info/METADATA +0 -167
- {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/entry_points.txt +0 -0
- {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/licenses/LICENSE +0 -0
- {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/top_level.txt +0 -0
|
@@ -43,11 +43,11 @@ def import_module_from_path(module_name, file_path):
|
|
|
43
43
|
class GenAI(object):
|
|
44
44
|
""" Create project from genai prompt(s).
|
|
45
45
|
|
|
46
|
-
Called by api_logic_server, to run ChatGPT (or
|
|
46
|
+
Called by api_logic_server, to run ChatGPT (or response file) to create SQLAlchemy model
|
|
47
47
|
|
|
48
48
|
api_logic_server then uses model to create db, proceeds with normal project creation.
|
|
49
49
|
|
|
50
|
-
* there is also a callback to genai to
|
|
50
|
+
* NB: there is also a callback to genai to genai#insert_logic.. (& graphics) into created project
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
53
|
def __init__(self, project: Project):
|
|
@@ -71,7 +71,8 @@ class GenAI(object):
|
|
|
71
71
|
"""
|
|
72
72
|
Main Driver for GenAI - called by api_logic_server, to
|
|
73
73
|
* run ChatGPT (or respone file) to create_db_models.py - models & test data
|
|
74
|
-
* which then used
|
|
74
|
+
* which then used by apiLogic_server#api_logic_server_cli/create_from_model/create_db_from_model.py, for normal project creation.
|
|
75
|
+
* warning - test data failure here is not reported
|
|
75
76
|
|
|
76
77
|
The key argument is `--using`
|
|
77
78
|
* It can be a file, dir (conversation) or text argument.
|
|
@@ -152,9 +153,11 @@ class GenAI(object):
|
|
|
152
153
|
# main driver starts here
|
|
153
154
|
#######################################################
|
|
154
155
|
|
|
155
|
-
log.info(f'\nGenAI [{self.project.project_name}] creating microservice...')
|
|
156
|
+
log.info(f'\n\nGenAI [{self.project.project_name}] creating microservice...')
|
|
156
157
|
log.info(f'.. .. --using prompt: {self.project.genai_using}')
|
|
157
|
-
log.info(f'.. ..
|
|
158
|
+
log.info(f'.. .. --project-name[self.project.project_name]: {self.project.project_name}')
|
|
159
|
+
log.info(f'.. .. project.project_directory_actual: {self.project.project_directory_actual}')
|
|
160
|
+
log.info(f'.. .. in pwd: {os.getcwd()}\n')
|
|
158
161
|
|
|
159
162
|
if self.project.genai_repaired_response != '':
|
|
160
163
|
log.info(f'.. retry from [repaired] response file: {self.project.genai_repaired_response}')
|
|
@@ -183,12 +186,22 @@ class GenAI(object):
|
|
|
183
186
|
if not genai_demo_response_path.is_file():
|
|
184
187
|
log.debug(f'.. standard genai_demo response not found: {genai_demo_response_path}')
|
|
185
188
|
else:
|
|
186
|
-
with open(genai_demo_response_path, 'r') as response_file:
|
|
187
|
-
response_dict = json.load(response_file)
|
|
189
|
+
with open(genai_demo_response_path, 'r') as response_file: # fail-safe demo
|
|
190
|
+
response_dict = json.load(response_file) # BUT, the prompt is in wg? which needs graphics
|
|
188
191
|
log.debug(f'.. used standard genai_demo response: {genai_demo_response_path}')
|
|
189
192
|
genai_demo_response_path = Path('system/genai/temp/response.json')
|
|
190
193
|
with open(genai_demo_response_path, 'w') as response_file:
|
|
191
194
|
json.dump(response_dict, response_file, indent=4)
|
|
195
|
+
# the request is a cli arg; for wg: sra/src/components/apifab/WebGenAICreate.tsx
|
|
196
|
+
if limit_tables := False: # failed experiment to limit table iterations for genai_demo
|
|
197
|
+
# eg, fails to: Add Sales Rep table, as a parent of Order.
|
|
198
|
+
genai_demo_request_path = Path('system/genai/temp/request.json')
|
|
199
|
+
utils.replace_string_in_file(in_file=genai_demo_request_path,
|
|
200
|
+
search_for='at least 12 tables',
|
|
201
|
+
replace_with='only the requested and added tables')
|
|
202
|
+
self.messages[0]['content'] = self.messages[0]['content'].replace(
|
|
203
|
+
'at least 12 tables', 'only the requested and added tables')
|
|
204
|
+
pass
|
|
192
205
|
|
|
193
206
|
else: # for retry from corrected response... eg system/genai/temp/chatgpt_retry.response
|
|
194
207
|
self.resolved_model = "(n/a: model not used for repaired response)"
|
|
@@ -316,7 +329,7 @@ class GenAI(object):
|
|
|
316
329
|
log.debug(f'.. from file: {self.project.genai_using}')
|
|
317
330
|
raw_prompt = file.read()
|
|
318
331
|
prompt = self.get_prompt__with_inserts(raw_prompt=raw_prompt, for_iteration=False) # insert db-specific logic
|
|
319
|
-
self.logic_enabled = True
|
|
332
|
+
self.logic_enabled = True
|
|
320
333
|
if os.environ.get("APILOGICPROJECT_LOGIC_ENABLED") is not None and \
|
|
321
334
|
os.environ.get("APILOGICPROJECT_LOGIC_ENABLED") == 'False':
|
|
322
335
|
self.logic_enabled = False
|
|
@@ -398,13 +411,20 @@ class GenAI(object):
|
|
|
398
411
|
return learning_requests # TODO - what if no learning requests?
|
|
399
412
|
|
|
400
413
|
def get_prompt__with_inserts(self, raw_prompt: str, for_iteration: bool = False) -> str:
|
|
401
|
-
""" prompt-engineering:
|
|
414
|
+
""" prompt-engineering for both initial & iteration:
|
|
402
415
|
|
|
403
416
|
1. insert db-specific logic into prompt
|
|
404
|
-
2. insert iteration prompt (
|
|
417
|
+
2. insert iteration prompt (iff for_iteration)
|
|
405
418
|
3. insert logic_inserts.prompt ('1 line: Use LogicBank to create declare_logic()...')
|
|
406
419
|
4. designates prompt-format (response_format.prompt)
|
|
407
420
|
|
|
421
|
+
Eg, initial creation: expands system/genai/prompt_inserts/sqlite_inserts.prompt
|
|
422
|
+
1. use sqlalchemy to create...
|
|
423
|
+
2. <requirements>prompt</requirements>
|
|
424
|
+
3. Use autonum.. (sql hints)
|
|
425
|
+
4. Graphics training...
|
|
426
|
+
5. Response format
|
|
427
|
+
|
|
408
428
|
Args:
|
|
409
429
|
raw_prompt (str): the prompt from file or text argument
|
|
410
430
|
for_iteration (bool, optional): Inserts 'Update the prior response...' Defaults to False.
|
|
@@ -473,6 +493,8 @@ class GenAI(object):
|
|
|
473
493
|
|
|
474
494
|
Also creates the doc directory for record of prompt, response.
|
|
475
495
|
|
|
496
|
+
And, invokes genai_graphics
|
|
497
|
+
|
|
476
498
|
TODO - use genai_rules_from_response
|
|
477
499
|
|
|
478
500
|
"""
|
|
@@ -513,6 +535,12 @@ class GenAI(object):
|
|
|
513
535
|
log.debug(f'.. removed hallucination: {each_line}')
|
|
514
536
|
return return_line
|
|
515
537
|
|
|
538
|
+
log.info(f'\n\nGenAI [{self.project.project_name}] creating microservice...')
|
|
539
|
+
log.info(f'.. .. --using prompt: {self.project.genai_using}')
|
|
540
|
+
log.info(f'.. .. --project-name[self.project.project_name]: {self.project.project_name}')
|
|
541
|
+
log.info(f'.. .. project.project_directory_actual: {self.project.project_directory_actual}')
|
|
542
|
+
log.info(f'.. .. in pwd: {os.getcwd()}\n')
|
|
543
|
+
|
|
516
544
|
logic_file = self.project.project_directory_path.joinpath('logic/declare_logic.py')
|
|
517
545
|
if self.logic_enabled:
|
|
518
546
|
translated_logic = genai_svcs.get_code_update_logic_file(rule_list = self.response_dict.rules,
|
|
@@ -576,7 +604,10 @@ class GenAI(object):
|
|
|
576
604
|
except: # intentional try/catch/bury - it's just docs, so don't fail
|
|
577
605
|
import traceback
|
|
578
606
|
log.error(f"\n\nERROR creating genai project docs: {docs_dir}\n\n{traceback.format_exc()}")
|
|
579
|
-
genai_graphics = GenAIGraphics(project=self.project,
|
|
607
|
+
genai_graphics = GenAIGraphics(project=self.project,
|
|
608
|
+
replace_with='!new-wg',
|
|
609
|
+
using=None,
|
|
610
|
+
genai_version=self.project.genai_version)
|
|
580
611
|
|
|
581
612
|
def save_prompt_messages_to_system_genai_temp_project(self):
|
|
582
613
|
"""
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
import importlib
|
|
7
7
|
from api_logic_server_cli.genai.genai_utils import call_chatgpt
|
|
8
8
|
import requests
|
|
9
|
-
import os
|
|
9
|
+
import os, time
|
|
10
10
|
import datetime
|
|
11
11
|
import create_from_model.api_logic_server_utils as utils
|
|
12
12
|
import time
|
|
@@ -29,49 +29,101 @@ K_data_model_prompt = "Use SQLAlchemy to create"
|
|
|
29
29
|
log = logging.getLogger(__name__)
|
|
30
30
|
|
|
31
31
|
class GenAIGraphics(object):
|
|
32
|
-
"""
|
|
33
|
-
Adds Graphics to
|
|
34
|
-
* adds `
|
|
35
|
-
* adds
|
|
32
|
+
""" 4/3/2025
|
|
33
|
+
Adds Graphics to projects (genai project or als project):
|
|
34
|
+
* adds `database/database_discovery` file to project (methods on database.models classes)
|
|
35
|
+
* adds `api/api_discovery` file to project (dashboard services - calls db methods, above)
|
|
36
|
+
* adds `docs/graphics` prompt files to **wg** project (graphics prompt files)
|
|
36
37
|
|
|
37
38
|
Invoked from:
|
|
38
39
|
1. **New GenAI Project:** for newly created project (e,g, mgr system/genai/examples/genai_demo/genai_demo.prompt)
|
|
39
|
-
* `--using` is None ==> Docs folder already has WGResponse.graphics[]
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
* `--using` is None ==> Docs folder already has WGResponse.graphics[]
|
|
41
|
+
* see api_logic_server_cli/genai/genai_svcs.py#insert_logic_into_created_project
|
|
42
|
+
2. **Existing Project:** `als genai-graphics [--using]` # existing project
|
|
43
|
+
* `--using` ==> Call ChatGPT for WGResponse.graphics, default = `<project>/docs/graphics/*.prompt`
|
|
42
44
|
* note: dbml not rebuilt after rebuild-from-db
|
|
43
45
|
3. **Existing WG Project:** in-place (do not create new project with new test data)
|
|
44
46
|
* Same as #1, but requires WG UI change ('in place', 'graphics' button, ...) to use genai_graphics cmd
|
|
45
47
|
|
|
48
|
+
Testing:
|
|
49
|
+
* BLT to create manager
|
|
50
|
+
* Test from source: launch.json (in group 3) has `Add Graphics to blt/samples/nw...`
|
|
51
|
+
* Note: uses `<mgr>/system/genai/graphics_templates`
|
|
52
|
+
* Don't forget to copy these back to `api_logic_server_cli/prototypes/manager/system/genai/graphics_templates`
|
|
53
|
+
* Optionally: update `bypass_for_debug` to True to skip ChatGPT call
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
|
|
55
|
+
Persistence model for graphics: docs/response.json (also in docs/graphics/response.json, for als customization)
|
|
56
|
+
* Requirements:
|
|
57
|
+
1. Fail-safe: do not let WG projects fail due to graphics - but alert user, just once
|
|
58
|
+
2. Iterable: do not lose graphics on WG iteration
|
|
59
|
+
* Running design: 4/12
|
|
60
|
+
* Fail-safe: implemented in dashboard_service.py -- for each <graphic.name> query:
|
|
61
|
+
1. if exists(docs/graphics/<graphics.name>.err), bypass the query
|
|
62
|
+
2. wrap each dashboard_service query in a try/except block
|
|
63
|
+
3. if exception,
|
|
64
|
+
* return "graphics failed" to iFrame so user can see it
|
|
65
|
+
* create docs/graphics/<graphics>.err to inhibit future calls
|
|
66
|
+
* For wg (--using == None):
|
|
67
|
+
* iterations build on docs/response.json, so graphics are preserved
|
|
68
|
+
* todo: verify add-rules
|
|
69
|
+
* this code creates docs/graphics/<graphics.name>.prompt
|
|
70
|
+
* preserves graphics when opening project in als mode
|
|
71
|
+
* ALS developers manage their own docs/graphics
|
|
72
|
+
|
|
50
73
|
Open Issues
|
|
51
|
-
* How to
|
|
52
|
-
* How
|
|
53
|
-
*
|
|
74
|
+
* How to enforce licensing? eg, create stubbed api/api_discovery/dashboard_services.py
|
|
75
|
+
* How can user delete or alter the graphics? Activate the Project Summary Graphics button [replace]
|
|
76
|
+
* Graphics for wg projects (not showing)
|
|
77
|
+
* No Graphics (just shows {} )
|
|
54
78
|
|
|
55
79
|
"""
|
|
56
80
|
|
|
57
|
-
def __init__(self, project: Project, using: str, genai_version: str):
|
|
81
|
+
def __init__(self, project: Project, using: str, genai_version: str, replace_with: str):
|
|
58
82
|
"""
|
|
59
83
|
Add graphics to existing projects - [see docs](https://apilogicserver.github.io/Docs/WebGenAI-CLI/#add-graphics-to-existing-projects)
|
|
60
84
|
|
|
61
|
-
|
|
85
|
+
Called to inject graphics into existing project, by:
|
|
86
|
+
1. genai#insert_logic for NEW WG projects (--replace_with = '!new-wg', using already-built docs dir)
|
|
87
|
+
2. cli for EXISTING projects (add from docs/graphics, or update per replace_with)
|
|
62
88
|
|
|
89
|
+
Args:
|
|
90
|
+
project (Project): Project object
|
|
91
|
+
using (str): path to graphics prompt files (set by genai#insert_logic, or None, for existing project)
|
|
92
|
+
replace_with (str): (request type): '!using' (default), '!new-wg', '!delete', '!retry`, or '!request'
|
|
93
|
+
genai_version (str): GenAI version to use
|
|
63
94
|
"""
|
|
64
95
|
|
|
65
96
|
self.project = project
|
|
66
|
-
self.
|
|
97
|
+
self.using = using
|
|
67
98
|
self.manager_path = genai_svcs.get_manager_path()
|
|
68
|
-
|
|
69
|
-
|
|
99
|
+
self.start_time = time.time()
|
|
100
|
+
self.replace_with = replace_with
|
|
101
|
+
''' '!using', '!new-wg', '!delete', '!retry`, or '!request Graph Sales... '''
|
|
102
|
+
graphics_response_path = self.project.project_directory_path.joinpath('docs/graphics/response.json') # assume existing project
|
|
103
|
+
if replace_with == '!new-wg': # if new webgenai, response already prepared here
|
|
70
104
|
graphics_response_path = self.project.project_directory_path.joinpath('docs/response.json')
|
|
71
|
-
|
|
72
|
-
|
|
105
|
+
|
|
106
|
+
log.info(f"\nGenAIGraphics start...")
|
|
107
|
+
log.info(f"... args:")
|
|
108
|
+
log.info(f"..... self.replace_with: {self.replace_with}")
|
|
109
|
+
log.info(f"..... self.using: {self.using}")
|
|
110
|
+
log.info(f"..... graphics_response_path: {graphics_response_path}")
|
|
111
|
+
log.info(f"..... self.project.project_directory_actual: {self.project.project_directory_actual}")
|
|
112
|
+
log.info(f"..... self.project.project_directory_path: {str(self.project.project_directory_path)}")
|
|
113
|
+
|
|
114
|
+
if self.replace_with != '!new-wg' and self.replace_with != '!using' : # update existing genai project
|
|
115
|
+
replaced_graphics = self.graphics_replace_with_in_existing_project()
|
|
116
|
+
if self.replace_with == '!delete': # we are done (else create docs/graphics prompts for processing below)
|
|
117
|
+
log.info(f"... update existing genai project - delete graphics")
|
|
118
|
+
return
|
|
119
|
+
log.info(f"... update genai existing project - from docs/graphics prompts with {replaced_graphics}")
|
|
120
|
+
|
|
121
|
+
if replace_with == '!new-wg':
|
|
122
|
+
log.info(f"... NEW WG project - already built: docs/002_create_db_models.prompt")
|
|
123
|
+
else:
|
|
124
|
+
log.info(f"... EXISTING project - process prompts in docs/graphics")
|
|
73
125
|
if bypass_for_debug := False:
|
|
74
|
-
pass
|
|
126
|
+
pass # uses already-built docs/graphics/response.json
|
|
75
127
|
else:
|
|
76
128
|
prompt = genai_svcs.read_and_expand_prompt(self.manager_path.joinpath('system/genai/prompt_inserts/graphics_request.prompt'))
|
|
77
129
|
prompt_lines = prompt.split('\n') # ChatGPT instructions
|
|
@@ -87,74 +139,236 @@ class GenAIGraphics(object):
|
|
|
87
139
|
using = self.project.project_directory_path.joinpath('docs/graphics'),
|
|
88
140
|
api_version=genai_version)
|
|
89
141
|
|
|
90
|
-
self.
|
|
142
|
+
self.create_data_class_methods(graphics_response_path)
|
|
143
|
+
self.create_graphics_dashboard_service(graphics_response_path)
|
|
144
|
+
self.create_genai_graphics_prompts(graphics_response_path)
|
|
145
|
+
log.info(f"\ngenai-graphics completed in [{str(int(time.time() - self.start_time))} secs] \n")
|
|
91
146
|
pass
|
|
92
147
|
|
|
93
|
-
def
|
|
94
|
-
""" Process graphics response from ChatGPT
|
|
148
|
+
def create_data_class_methods(self, graphics_response_path: Path):
|
|
149
|
+
""" Process graphics response from ChatGPT docs/graphics/response.json
|
|
150
|
+
* 'graphics' attributes map directly (by name) to <mgr>/system/genai/graphics_templates
|
|
151
|
+
"""
|
|
95
152
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
shutil.copy(graphic_services_header_path, graphics_services_path)
|
|
153
|
+
shutil.copy(self.manager_path.joinpath('system/genai/graphics_templates/graphics_services_db.jinja'),
|
|
154
|
+
self.project.project_directory_path.joinpath('database/database_discovery/graphics_services.py')) # all the db-class methods are created in this file
|
|
99
155
|
|
|
100
156
|
# open and read the graphics_response_path json file
|
|
101
157
|
assert graphics_response_path.exists(), f'Graphics response file not found: {graphics_response_path}'
|
|
102
158
|
with open(graphics_response_path, 'r') as file:
|
|
103
159
|
graphics_response = json.load(file)
|
|
104
|
-
log.info(f'
|
|
160
|
+
log.info(f'... create_data_class_methods - from {graphics_response_path}')
|
|
105
161
|
graphics = graphics_response['graphics']
|
|
106
162
|
for each_graphic in graphics: # add each service to api/api_discovery
|
|
107
163
|
self.fix_sqlalchemy_query(each_graphic)
|
|
108
164
|
env = Environment(loader=FileSystemLoader(self.manager_path.joinpath('system/genai/graphics_templates')))
|
|
109
165
|
|
|
110
|
-
template = env.get_template('
|
|
166
|
+
template = env.get_template('graphics_services_db_each_method.jinja')
|
|
111
167
|
rendered_result = template.render( **each_graphic )
|
|
112
|
-
with open(self.project.project_directory_path.joinpath(f'
|
|
168
|
+
with open(self.project.project_directory_path.joinpath(f'database/database_discovery/graphics_services.py'), 'a') as out_file:
|
|
113
169
|
out_file.write(rendered_result)
|
|
114
170
|
|
|
171
|
+
log.info(f'..... added db class method: {each_graphic['name']} to database_discovery')
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
""" note it needs the /1 - what is that about?
|
|
176
|
+
curl -X 'GET' \
|
|
177
|
+
'http://localhost:5656/api/Category/sales_by_category' \
|
|
178
|
+
-H 'accept: application/vnd.api+json' \
|
|
179
|
+
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTc0MzY5MTc3OCwianRpIjoiNDBlYzZkNGMtMzk4My00OGEwLTgxMjQtYzQwY2RmYWFiZWRhIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6InUxIiwibmJmIjoxNzQzNjkxNzc4LCJleHAiOjE3NDM3MDUwOTh9.WLDxdkp3PIsgUqR0t9-ymQDR0eOAECdQsgS_3YTqAQ0'
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
def create_graphics_dashboard_service(self, graphics_response_path: Path):
|
|
183
|
+
""" Process graphics response from ChatGPT graphics_response_path """
|
|
184
|
+
|
|
185
|
+
# open and read the graphics_response_path json file
|
|
186
|
+
assert graphics_response_path.exists(), f'Graphics response file not found: {graphics_response_path}'
|
|
187
|
+
with open(graphics_response_path, 'r') as file:
|
|
188
|
+
graphics_response = json.load(file)
|
|
189
|
+
if 'graphics' not in graphics_response:
|
|
190
|
+
log.error(f'No graphics found in {graphics_response_path}')
|
|
191
|
+
return
|
|
192
|
+
graphics = graphics_response['graphics']
|
|
193
|
+
|
|
194
|
+
env = Environment(loader=FileSystemLoader(self.manager_path.joinpath('system/genai/graphics_templates')))
|
|
195
|
+
iframe_templates= []
|
|
196
|
+
has_iframe = False
|
|
197
|
+
iframe_links = []
|
|
198
|
+
dashboards = []
|
|
199
|
+
cnt = 0
|
|
200
|
+
template = env.get_template('dashboard_services.jinja')
|
|
201
|
+
for each_graphic in graphics: # add each service to api/api_discovery
|
|
202
|
+
cnt += 1
|
|
203
|
+
server = '{server}'
|
|
204
|
+
iframe = f'iframe_{cnt} = iframe_template.format(url=f"{server}chart_graphics/{each_graphic['name']}")\n'
|
|
205
|
+
iframe_templates.append(iframe)
|
|
206
|
+
link = "{"+ f'iframe_{cnt}' + "}"
|
|
207
|
+
iframe_links.append(f'{link}')
|
|
208
|
+
sqlalchemy_query = each_graphic['class_x_axis']
|
|
209
|
+
|
|
210
|
+
# create the dashboard service query (skip if .err file exists, create .err file if query fails)
|
|
211
|
+
# typical failure: xxx
|
|
212
|
+
db = f"""
|
|
213
|
+
previously_failed = Path('docs/graphics/{each_graphic['name']}.err').exists()
|
|
214
|
+
if previously_failed:
|
|
215
|
+
pass # query has previously failed, so skip it
|
|
216
|
+
else:
|
|
217
|
+
try:
|
|
218
|
+
results = models.{sqlalchemy_query}.{each_graphic['name']}(None)
|
|
219
|
+
color = 'rgba(75, 192, 192, 0.2)'
|
|
220
|
+
dashboard{cnt} = template.render(result=results, color=color)
|
|
221
|
+
dashboard_result['{each_graphic['name']}']= dashboard{cnt}
|
|
222
|
+
except Exception as e:
|
|
223
|
+
msg = f"GenAI query creation error on models.{sqlalchemy_query}.{each_graphic['name']}: " + str(e)
|
|
224
|
+
dashboard_result['{each_graphic['name']}'] = msg
|
|
225
|
+
app_logger.error(msg)
|
|
226
|
+
with open('docs/graphics//{each_graphic['name']}.err', 'w') as err_file:
|
|
227
|
+
err_file.write(msg) # this logs the error to prevent future calls
|
|
228
|
+
|
|
229
|
+
"""
|
|
230
|
+
dashboards.append(db)
|
|
231
|
+
|
|
232
|
+
rendered_result = template.render(iframe_templates=iframe_templates, iframe_links=" ".join(iframe_links), has_iframe=cnt > 0 , dashboards= dashboards)
|
|
233
|
+
with open(self.project.project_directory_path.joinpath(f'api/api_discovery/dashboard_services.py'), 'w') as out_file:
|
|
234
|
+
out_file.write(rendered_result)
|
|
235
|
+
log.info(f'... create_graphics_dashboard_service - created api/api_discovery/dashboard_services.py')
|
|
236
|
+
|
|
237
|
+
for each_graphic in graphics:
|
|
238
|
+
self.fix_sqlalchemy_query(each_graphic)
|
|
115
239
|
template = env.get_template('html_template.jinja')
|
|
116
240
|
rendered_result = template.render( **each_graphic )
|
|
117
241
|
with open(self.project.project_directory_path.joinpath(f'api/api_discovery/{each_graphic['name']}.html'), 'w') as out_file:
|
|
118
242
|
out_file.write(rendered_result)
|
|
119
243
|
|
|
120
244
|
with open(self.project.project_directory_path.joinpath(f'api/api_discovery/{each_graphic['name']}.sql'), 'w') as out_file:
|
|
121
|
-
|
|
245
|
+
sql_query = "System Error: missing sql_query - check WGResult format"
|
|
246
|
+
if 'sql_query' in each_graphic:
|
|
247
|
+
sql_query = each_graphic['sql_query']
|
|
248
|
+
out_file.write(sql_query)
|
|
122
249
|
|
|
123
|
-
log.info(f'
|
|
250
|
+
log.info(f'..... added dashboard query: {each_graphic['name']} to api_discovery')
|
|
251
|
+
|
|
124
252
|
pass
|
|
125
253
|
|
|
254
|
+
def create_genai_graphics_prompts(self, graphics_response_path: Path):
|
|
255
|
+
""" if genai project, create graphics prompt file: docs/graphics/wg_graphics.prompt
|
|
256
|
+
"""
|
|
257
|
+
if self.using is not None:
|
|
258
|
+
return # it's an als request, not a genai project (todo: confirm this works on iterations)
|
|
259
|
+
|
|
260
|
+
# open and read the graphics_response_path json file
|
|
261
|
+
assert graphics_response_path.exists(), f'Graphics response file not found: {graphics_response_path}'
|
|
262
|
+
with open(graphics_response_path, 'r') as file:
|
|
263
|
+
graphics_response = json.load(file)
|
|
264
|
+
log.info(f'... create_genai_graphics_prompts - from {graphics_response_path}')
|
|
265
|
+
graphics = graphics_response['graphics']
|
|
266
|
+
graphics_prompt = ''
|
|
267
|
+
graphics_prompt_count = 0
|
|
268
|
+
for each_graphic in graphics: # add each prompt to docs/graphics
|
|
269
|
+
graphics_prompt_count += 1
|
|
270
|
+
graphics_prompt += each_graphic['prompt'] + '\n'
|
|
271
|
+
with open(self.project.project_directory_path.joinpath(f'docs/graphics/wg_graphics.prompt'), 'w') as out_file:
|
|
272
|
+
out_file.write(graphics_prompt)
|
|
273
|
+
log.info(f'..... added docs/graphics/wg_graphics.prompt')
|
|
274
|
+
pass
|
|
275
|
+
|
|
276
|
+
def graphics_replace_with_in_existing_project(self) -> str:
|
|
277
|
+
"""
|
|
278
|
+
Delete graphics for wg project (als projects - just delete the docs/graphics files)
|
|
279
|
+
1. Update docs/*.prompt to remove lines starting with Graphics
|
|
280
|
+
* Prevents reappearance on iteration
|
|
281
|
+
2. Presume (!) not necessary to delete the graphics[] in docs/*.response files
|
|
282
|
+
3. If delete, rename the api/api_discovery/dashboard_services.py file so it won't be called
|
|
283
|
+
|
|
284
|
+
This does not rebuild / create a new project - operates on current project.
|
|
285
|
+
|
|
286
|
+
If self.replace_with is retry or request, build docs/graphics/wg_graphics.prompt
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
# for all docs/*.prompt files, alter lines where the first characters are 'Graph' (case insensitive)
|
|
290
|
+
docs_dir = self.project.project_directory_path.joinpath('docs')
|
|
291
|
+
replaced_count = 0
|
|
292
|
+
replaced_prompts = ''
|
|
293
|
+
log.info(f"... graphics_replace_with_in_existing_project - self.replace_with: {self.replace_with}")
|
|
294
|
+
|
|
295
|
+
for prompt_file in docs_dir.glob('*.prompt'):
|
|
296
|
+
with open(prompt_file, 'r') as file:
|
|
297
|
+
lines = file.readlines()
|
|
298
|
+
line_number = 0
|
|
299
|
+
with open(prompt_file, 'w') as file:
|
|
300
|
+
for line in lines:
|
|
301
|
+
line_number += 1
|
|
302
|
+
if not line.strip().lower().startswith('graph '):
|
|
303
|
+
file.write(line)
|
|
304
|
+
else:
|
|
305
|
+
replaced_prompts += line
|
|
306
|
+
replaced_count += 1
|
|
307
|
+
if self.replace_with == '!retry': # we are just doing retry - don't replace, use existing wg_graphics
|
|
308
|
+
file.write(line)
|
|
309
|
+
continue
|
|
310
|
+
elif self.replace_with.startswith('!request'): # replacing - replace ==> docs and doc/graphics
|
|
311
|
+
if replaced_count == 1:
|
|
312
|
+
file.write(self.replace_with + '\n')
|
|
313
|
+
graphics_prompt = self.replace_with[8:]
|
|
314
|
+
with open(self.project.project_directory_path.joinpath(f'docs/graphics/wg_graphics.prompt'), 'w') as out_file:
|
|
315
|
+
out_file.write(self.replace_with)
|
|
316
|
+
else:
|
|
317
|
+
assert self.replace_with == '!delete', f"genai_graphics - expected !delete, got: {self.replace_with}"
|
|
318
|
+
pass # removing line
|
|
319
|
+
|
|
320
|
+
log.info(f"..... completed - processed {replaced_count} graph line(s).")
|
|
321
|
+
|
|
322
|
+
# Stop graphics: rename the old dashboard_services.py file to dashboard_services.pyZ
|
|
323
|
+
dashboard_service_path = self.project.project_directory_path.joinpath('api/api_discovery/dashboard_services.py')
|
|
324
|
+
if dashboard_service_path.exists():
|
|
325
|
+
renamed_path = dashboard_service_path.with_suffix('.pyZ')
|
|
326
|
+
dashboard_service_path.rename(renamed_path)
|
|
327
|
+
log.info(f"..... Renamed existing dashboard_services.py to {renamed_path}")
|
|
328
|
+
else:
|
|
329
|
+
log.info(f'.. Note: {dashboard_service_path} not found')
|
|
330
|
+
return replaced_prompts
|
|
331
|
+
|
|
126
332
|
def fix_sqlalchemy_query(self, graphic: Dict):
|
|
127
333
|
""" Fix the SQLAlchemy query for the graphic """
|
|
128
334
|
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'].replace('\\n', '\n')
|
|
129
335
|
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'].replace('\"', '"')
|
|
130
|
-
|
|
336
|
+
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'].replace('.isnot', '.is_not')
|
|
131
337
|
|
|
338
|
+
# this part is for readability, not 'fixing'
|
|
339
|
+
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'].replace('session.query', '(session.query')
|
|
340
|
+
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'] + ')'
|
|
341
|
+
graphic['sqlalchemy_query'] = graphic['sqlalchemy_query'].replace(').', ')\n .')
|
|
342
|
+
pass
|
|
132
343
|
|
|
133
344
|
def append_data_model(self) -> List[str]:
|
|
134
345
|
""" Get the data model
|
|
135
346
|
|
|
136
347
|
Returns:
|
|
137
|
-
list:
|
|
348
|
+
list[str]: the data model lines
|
|
138
349
|
"""
|
|
139
350
|
|
|
140
351
|
data_model_lines = []
|
|
352
|
+
data_model_lines.extend(['Here is the data model - please use it to create the graphics:'])
|
|
141
353
|
data_model_path = self.project.project_directory_path.joinpath('database/models.py')
|
|
142
354
|
assert data_model_path.exists(), f"Data model file not found: {data_model_path}"
|
|
143
355
|
with open(data_model_path, 'r') as file:
|
|
144
356
|
prompt_lines = file.readlines()
|
|
145
357
|
data_model_lines.extend(prompt_lines)
|
|
358
|
+
data_model_lines.extend(['End of data model'])
|
|
146
359
|
return data_model_lines
|
|
147
360
|
|
|
148
361
|
def append_graphics_files(self) -> List[str]:
|
|
149
|
-
""" Get graphics files (typically from project)
|
|
362
|
+
""" Get graphics files (typically from project/docs/graphics)
|
|
363
|
+
* 1 file per graphic
|
|
150
364
|
|
|
151
365
|
Returns:
|
|
152
366
|
list: logic_files
|
|
153
367
|
"""
|
|
154
368
|
|
|
155
369
|
graphics_lines = []
|
|
156
|
-
if Path(self.
|
|
157
|
-
for each_file in sorted(Path(self.
|
|
370
|
+
if Path(self.using).is_dir(): # conversation from directory
|
|
371
|
+
for each_file in sorted(Path(self.using).iterdir()):
|
|
158
372
|
if each_file.is_file() and each_file.suffix == '.prompt':
|
|
159
373
|
# read lines from each_file, and append to prompt
|
|
160
374
|
with open(each_file, 'r') as file:
|
|
@@ -42,11 +42,18 @@ class Model(BaseModel):
|
|
|
42
42
|
description: str
|
|
43
43
|
name: str
|
|
44
44
|
|
|
45
|
-
class
|
|
46
|
-
sqlalchemy_query: str # sqlalchemy group by result = { "result": [ ("name", "value) ] }
|
|
45
|
+
class Graphic(BaseModel):
|
|
46
|
+
sqlalchemy_query: str # sqlalchemy query using group by, returns result = { "result": [ ("name", "value") ] }
|
|
47
47
|
sql_query: str # sql query using group by, returns result = { "result": [ ("name", "value") ] }
|
|
48
48
|
classes_used: str # comma-delimited list of classes used in sqlalchemy_query
|
|
49
|
-
|
|
49
|
+
class_x_axis: str # name of class for x axis
|
|
50
|
+
name: str # suggested Python name for sqlalchemy_query - unique
|
|
51
|
+
prompt: str # prompt used to create the graphic
|
|
52
|
+
title: str # expanded name
|
|
53
|
+
xAxis: str # caption for x axis
|
|
54
|
+
yAxis: str # caption for y axis
|
|
55
|
+
dashboard: bool # whether appears on home page
|
|
56
|
+
graph_type: str # Bar, Line, Pie
|
|
50
57
|
html_code: str # create a java script app to show a bar chart from sqlalchemy_query result
|
|
51
58
|
|
|
52
59
|
class TestDataRow(BaseModel):
|
|
@@ -57,7 +64,7 @@ class WGResult(BaseModel): # must match system/genai/prompt_inserts/response_fo
|
|
|
57
64
|
# response: str # result
|
|
58
65
|
models : List[Model] # list of sqlalchemy classes in the response
|
|
59
66
|
rules : List[Rule] # list rule declarations
|
|
60
|
-
graphics: List[
|
|
67
|
+
graphics: List[Graphic] # list of graphs
|
|
61
68
|
test_data: str
|
|
62
69
|
test_data_rows: List[TestDataRow] # list of test data rows
|
|
63
70
|
test_data_sqlite: str # test data as sqlite INSERT statements
|
|
@@ -737,10 +744,10 @@ def get_create_prompt__with_inserts(arg_prompt_inserts: str='', raw_prompt: str=
|
|
|
737
744
|
pre_post = file.read() # eg, Use SQLAlchemy to create a sqlite database named system/genai/temp/create_db_models.sqlite, with
|
|
738
745
|
prompt_result = pre_post.replace('{{prompt}}', raw_prompt)
|
|
739
746
|
if for_iteration:
|
|
740
|
-
# Update the prior response - be sure not to lose classes and test data already created.
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
log.debug(f'.. iteration inserted: Update the prior response')
|
|
747
|
+
# Update the prior response - be sure not to lose classes, attributes, rules and test data already created.
|
|
748
|
+
iteration_prompt = read_and_expand_prompt(get_manager_path().joinpath(f'system/genai/prompt_inserts/iteration.prompt'))
|
|
749
|
+
prompt_result = iteration_prompt + '\n\n' + prompt_result
|
|
750
|
+
log.debug(f'.. iteration inserted: Update the prior response, using prompt_inserts/iteration.prompt')
|
|
744
751
|
#log.debug(f'.... iteration prompt result: {prompt_result}')
|
|
745
752
|
|
|
746
753
|
prompt_lines = prompt_result.split('\n')
|
|
@@ -766,10 +773,11 @@ def get_create_prompt__with_inserts(arg_prompt_inserts: str='', raw_prompt: str=
|
|
|
766
773
|
do_logic = False
|
|
767
774
|
prompt_line_number += 1
|
|
768
775
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
776
|
+
if format_not_requested := False: # FIXME - double format definition on create; others??
|
|
777
|
+
response_format_file_name = get_manager_path().joinpath(f'system/genai/prompt_inserts/response_format.prompt')
|
|
778
|
+
with open(response_format_file_name, 'r') as file:
|
|
779
|
+
response_format = file.readlines()
|
|
780
|
+
prompt_lines.extend(response_format)
|
|
773
781
|
|
|
774
782
|
prompt_result = "\n".join(prompt_lines) # back to a string
|
|
775
783
|
pass
|