ApiLogicServer 12.1.0__py3-none-any.whl → 12.1.26__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.
Files changed (51) hide show
  1. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/METADATA +1 -1
  2. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/RECORD +47 -39
  3. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/WHEEL +1 -1
  4. api_logic_server_cli/api_logic_server.py +16 -4
  5. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  6. api_logic_server_cli/cli.py +20 -9
  7. api_logic_server_cli/cli_args_base.py +2 -0
  8. api_logic_server_cli/cli_args_project.py +9 -3
  9. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  10. api_logic_server_cli/create_from_model/__pycache__/ui_admin_creator.cpython-312.pyc +0 -0
  11. api_logic_server_cli/create_from_model/ont_create.py +3 -1
  12. api_logic_server_cli/create_from_model/ui_admin_creator.py +6 -4
  13. api_logic_server_cli/genai.py +386 -286
  14. api_logic_server_cli/logging.yml +5 -0
  15. api_logic_server_cli/prototypes/.DS_Store +0 -0
  16. api_logic_server_cli/prototypes/base/api_logic_server_run.py +0 -2
  17. api_logic_server_cli/prototypes/base/config/server_setup.py +15 -1
  18. api_logic_server_cli/prototypes/base/integration/kafka/kafka_consumer.py +1 -1
  19. api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +1 -1
  20. api_logic_server_cli/prototypes/base/readme.md +21 -8
  21. api_logic_server_cli/prototypes/manager/.DS_Store +0 -0
  22. api_logic_server_cli/prototypes/manager/.vscode/.DS_Store +0 -0
  23. api_logic_server_cli/prototypes/manager/.vscode/launch.json +20 -0
  24. api_logic_server_cli/prototypes/manager/README.md +25 -1
  25. api_logic_server_cli/prototypes/manager/system/.DS_Store +0 -0
  26. api_logic_server_cli/prototypes/manager/system/genai/.DS_Store +0 -0
  27. api_logic_server_cli/prototypes/manager/system/genai/create_db_models_inserts/create_db_models_create_db.py +1 -0
  28. api_logic_server_cli/prototypes/manager/system/genai/create_db_models_inserts/create_db_models_imports.py +10 -7
  29. api_logic_server_cli/prototypes/manager/system/genai/create_db_models_inserts/create_db_models_test_data.py +1 -1
  30. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +99 -22
  31. api_logic_server_cli/prototypes/manager/system/genai/learning_requests/logic_bank_api.prompt +120 -7
  32. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/.DS_Store +0 -0
  33. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/response_format.prompt +26 -2
  34. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/sqlite_inserts.prompt +10 -4
  35. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/{sqlite_inserts_iterations.prompt → zsqlite_inserts_iterations.prompt} +5 -2
  36. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/create_db_models.py +96 -0
  37. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_000.response +1 -0
  38. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_001.prompt +208 -0
  39. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_002.prompt +89 -0
  40. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_003.prompt +40 -0
  41. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_004.response +57 -0
  42. api_logic_server_cli/prototypes/manager/system/genai/retry/conv/inf-1_iter_1_1_005.response +57 -0
  43. api_logic_server_cli/prototypes/manager/system/genai/retry/readme.md +1 -0
  44. api_logic_server_cli/prototypes/manager/system/genai/retry/retry.response +57 -0
  45. api_logic_server_cli/genaiZ.py +0 -752
  46. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example_z +0 -130
  47. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/web_genai copy.prompt +0 -15
  48. api_logic_server_cli/prototypes/manager/system/secrets.txt +0 -6
  49. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/LICENSE +0 -0
  50. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/entry_points.txt +0 -0
  51. {ApiLogicServer-12.1.0.dist-info → ApiLogicServer-12.1.26.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,14 @@
1
1
  import json
2
+ import sys
2
3
  import time
4
+ import traceback
3
5
  from typing import Dict, List
4
6
  from api_logic_server_cli.cli_args_project import Project
5
7
  import logging
6
8
  from pathlib import Path
7
9
  import importlib
8
10
  import requests
9
- import os
11
+ import os,re
10
12
  import create_from_model.api_logic_server_utils as utils
11
13
  import shutil
12
14
  import openai
@@ -14,25 +16,46 @@ from openai import OpenAI
14
16
  from typing import List, Dict
15
17
  from pydantic import BaseModel
16
18
  from dotmap import DotMap
19
+ import importlib.util
17
20
 
18
21
  log = logging.getLogger(__name__)
19
22
 
23
+ K_LogicBankOff = "LBX"
24
+ ''' Disable Logic (for demos) '''
25
+
20
26
  class Rule(BaseModel):
21
27
  name: str
22
28
  description: str
29
+ use_case: str
23
30
  code: str # logicbank rule code
24
31
 
25
32
  class Model(BaseModel):
26
33
  classname: str
27
34
  code: str # sqlalchemy model code
35
+ sqlite_create: str # sqlite create table statement
28
36
  description: str
29
37
  name: str
30
38
 
39
+ class TestDataRow(BaseModel):
40
+ test_data_row_variable: str # the Python test data row variable
41
+ code: str # Python code to create a test data row instance
42
+
31
43
  class WGResult(BaseModel): # must match system/genai/prompt_inserts/response_format.prompt
32
44
  # response: str # result
33
45
  models : List[Model] # list of sqlalchemy classes in the response
34
46
  rules : List[Rule] # list rule declarations
35
47
  test_data: str
48
+ test_data_rows: List[TestDataRow] # list of test data rows
49
+ test_data_sqlite: str # test data as sqlite INSERT statements
50
+ name: str # suggest a short name for the project
51
+
52
+
53
+ def import_module_from_path(module_name, file_path):
54
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
55
+ module = importlib.util.module_from_spec(spec)
56
+ sys.modules[module_name] = module
57
+ spec.loader.exec_module(module)
58
+ return module
36
59
 
37
60
 
38
61
  class GenAI(object):
@@ -51,12 +74,11 @@ class GenAI(object):
51
74
  The key argument is `--using`
52
75
  * It can be a file, dir (conversation) or text argument.
53
76
  * It's "stem" denotes the project name to be created at cwd
54
- * `self.project.genai_using`
77
+ * `self.project.genai_using` (not used by WebGenAI)
55
78
 
56
- The (rarely used) `--repaired_response`
79
+ The (rarely used) `--repaired_response` --> `self.project.genai_repaired_response`
57
80
  * is for retry from corrected response
58
81
  * `--using` is required to get the project name, to be created at cwd
59
- * `self.project.genai_repaired_response`
60
82
 
61
83
  __init__() is the main driver (work directory is <manager>/system/genai/temp/)
62
84
 
@@ -76,28 +98,10 @@ class GenAI(object):
76
98
 
77
99
  see key_module_map() for key methods
78
100
 
79
-
80
- ##### Explore interim copilot access:
81
-
82
- VSCode/Copilot-chat can turn prompts into logic, so can we automate with API?
83
-
84
- https://stackoverflow.com/questions/76741410/how-to-invoke-github-copilot-programmatically
85
- https://docs.google.com/document/d/1o0TeNQtuT6moWU1bOq2K20IbSw4YhV1x_aFnKwo_XeU/edit#heading=h.3xmoi7pevsnp
86
- https://code.visualstudio.com/api/extension-guides/chat
87
- https://code.visualstudio.com/api/extension-guides/language-model
88
- https://github.com/B00TK1D/copilot-api
89
-
90
- ### Or use ChatGPT:
91
-
92
- Not sure vscode/copilot is best approach, since we'd like to activate this during project creation
93
- (eg on web/GenAI - not using vscode).
94
-
95
- * Thomas suggests there are ways to "teach" ChatGPT about Logic Bank. This is a *great* idea.
96
-
97
- https://platform.openai.com/docs/guides/fine-tuning/create-a-fine-tuned-model
101
+ https://platform.openai.com/finetune/ftjob-2i1wkh4t4l855NKCovJeHExs?filter=all
98
102
  """
99
103
 
100
- self.project = project
104
+ self.project = project # als project info (cli args etc)
101
105
  log.info(f'\nGenAI [{self.project.project_name}] creating microservice from: {self.project.genai_using}')
102
106
  if self.project.genai_repaired_response != '':
103
107
  log.info(f'.. retry from [repaired] response file: {self.project.genai_repaired_response}')
@@ -109,28 +113,39 @@ class GenAI(object):
109
113
  """ eg, if response contains table defs, save_prompt_messages_to_system_genai_temp_project raises an exception to trigger retry """
110
114
  self.prompt = ""
111
115
  """ `--using` - can come from file or text argument """
112
-
116
+ self.logic_enabled = True
117
+ """ K_LogicBankOff is used for demos, where we don't want to create logic """
113
118
  self.messages = self.get_prompt_messages() # compute self.messages, from file, dir or text argument
114
119
 
115
120
  if self.project.genai_repaired_response == '': # normal path - get response from ChatGPT
116
- api_version = f'{self.project.genai_version}' # eg, "gpt-4o"
117
- api_version = "gpt-4o-2024-08-06"
118
- start_time = time.time()
119
- client = OpenAI(api_key=os.getenv("APILOGICSERVER_CHATGPT_APIKEY"))
120
- completion = client.beta.chat.completions.parse(
121
- messages=self.messages, response_format=WGResult,
122
- # temperature=0.0,
123
- model=api_version
124
- )
125
- log.debug(f'ChatGPT ({str(int(time.time() - start_time))} secs) - response at: system/genai/temp/chatgpt_original.response')
126
-
127
- data = completion.choices[0].message.content
128
- response_dict = json.loads(data)
129
- self.get_and_save_raw_response_data(completion=completion, response_dict=response_dict)
130
- # print(json.dumps(json.loads(data), indent=4))
131
- pass
132
-
121
+ try:
122
+ api_version = f'{self.project.genai_version}' # eg, "gpt-4o"
123
+ start_time = time.time()
124
+ db_key = os.getenv("APILOGICSERVER_CHATGPT_APIKEY")
125
+ client = OpenAI(api_key=os.getenv("APILOGICSERVER_CHATGPT_APIKEY"))
126
+ model = api_version
127
+ if model == "": # default from CLI is '', meaning fall back to env variable or system default...
128
+ model = os.getenv("APILOGICSERVER_CHATGPT_MODEL")
129
+ if model is None or model == "*": # system default chatgpt model
130
+ model = "gpt-4o-2024-08-06"
131
+ self.resolved_model = model
132
+ completion = client.beta.chat.completions.parse(
133
+ messages=self.messages, response_format=WGResult,
134
+ # temperature=self.project.genai_temperature, values .1 and .7 made students / charges fail
135
+ model=model # for own model, use "ft:gpt-4o-2024-08-06:personal:logicbank:ARY904vS"
136
+ )
137
+ log.debug(f'ChatGPT ({str(int(time.time() - start_time))} secs) - response at: system/genai/temp/chatgpt_original.response')
138
+
139
+ data = completion.choices[0].message.content
140
+ response_dict = json.loads(data)
141
+ self.get_and_save_raw_response_data(completion=completion, response_dict=response_dict)
142
+ # print(json.dumps(json.loads(data), indent=4))
143
+ pass
144
+ except Exception as inst:
145
+ log.error(f"\n\nError: ChatGPT call failed\n{inst}\n\n")
146
+ sys.exit('ChatGPT call failed - please see https://apilogicserver.github.io/Docs/WebGenAI-CLI/#configuration')
133
147
  else: # for retry from corrected response... eg system/genai/temp/chatgpt_retry.response
148
+ self.resolved_model = "(n/a: model not used for repaired response)"
134
149
  log.debug(f'\nUsing [corrected] response from: {self.project.genai_repaired_response}')
135
150
  with open(self.project.genai_repaired_response, 'r') as response_file:
136
151
  response_dict = json.load(response_file)
@@ -138,7 +153,7 @@ class GenAI(object):
138
153
  self.response_dict = DotMap(response_dict)
139
154
  """ the raw response data from ChatGPT which will be fixed & saved create_db_models.py """
140
155
 
141
- # self.project.genai_logic = self.get_logic_from_prompt()
156
+ self.get_valid_project_name()
142
157
 
143
158
  self.fix_and_write_model_file() # write create_db_models.py for db creation, & logic
144
159
  self.save_prompt_messages_to_system_genai_temp_project() # save prompts, response and models.py
@@ -154,13 +169,15 @@ class GenAI(object):
154
169
  if self.project.genai_repaired_response == '': # clean up unless retrying from chatgpt_original.response
155
170
  Path('system/genai/temp/chatgpt_original.response').unlink(missing_ok=True)
156
171
  Path('system/genai/temp/chatgpt_retry.response').unlink(missing_ok=True)
157
- Path('system/genai/temp/create_db_models.sqlite').unlink(missing_ok=True)
158
172
 
159
173
  def create_presets(self, prompt_messages: List[Dict[str, str]]):
160
174
  """ Create presets - you are a data modelling expert, and logicbank api etc """
161
175
  pass
162
176
 
163
- starting_message = {"role": "system", "content": "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"}
177
+ you_are = "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"
178
+ if self.project.genai_tables > 0:
179
+ you_are = you_are.replace('4', str(self.project.genai_tables))
180
+ starting_message = {"role": "system", "content": you_are}
164
181
  prompt_messages.append( starting_message)
165
182
 
166
183
  learning_requests = self.get_learning_requests()
@@ -169,6 +186,28 @@ class GenAI(object):
169
186
  log.debug(f'.. conv[000] presets: {starting_message}')
170
187
  log.debug(f'.. conv[001] presets: {learning_requests[0]["content"][:30]}...')
171
188
  return len(learning_requests)
189
+
190
+ def chatgpt_excp(self):
191
+ # https://apilogicserver.github.io/Docs/WebGenAI-CLI/
192
+ pass
193
+
194
+ def get_valid_project_name(self):
195
+ """ Get a valid project name from the project name
196
+ Takes a string and returns a valid filename constructed from the string.
197
+ """
198
+
199
+ # Replace invalid characters with underscores
200
+ valid_name = re.sub(r'[ \\/*?:"<>|\t\n\r\x0b\x0c]', '_', self.response_dict.name)
201
+ valid_name = valid_name.strip() # Remove leading and trailing spaces
202
+ valid_name = valid_name[:255] # Limit the filename length
203
+ if self.project.project_name == '_genai_default':
204
+ log.debug(f'.. project name: {valid_name} (from response: {self.response_dict.name})')
205
+ self.response_dict.name = valid_name
206
+ self.project.project_name = self.response_dict.name
207
+ self.project.project_name_last_node = self.response_dict.name
208
+ else:
209
+ self.project.directory_setup() # avoid names like "system/genai/temp/TBD"
210
+ return
172
211
 
173
212
  def get_prompt_messages(self) -> List[Dict[str, str]]:
174
213
  """ Get prompt from file, dir (conversation) or text argument
@@ -212,7 +251,7 @@ class GenAI(object):
212
251
  response_count += 1
213
252
  else:
214
253
  request_count += 1 # rebuild response with *all* tables
215
- if request_count > 1: # Run Config: genai AUTO DEALERSHIP CONVERSATION
254
+ if request_count > 2: # Run Config: genai AUTO DEALERSHIP CONVERSATION
216
255
  if 'updating the prior response' not in prompt:
217
256
  prompt = self.get_prompt__with_inserts(raw_prompt=prompt, for_iteration=True)
218
257
  prompt_messages.append( {"role": role, "content": prompt})
@@ -271,27 +310,43 @@ class GenAI(object):
271
310
  elif 'mysql' in self.project.db_url:
272
311
  prompt_inserts = f'mysql_inserts.prompt'
273
312
 
274
- if prompt_inserts != "*":
313
+ if prompt_inserts == "*":
314
+ pass # '*' means caller has computed their own prompt -- no inserts
315
+ else: # do prompt engineering (inserts)
275
316
  prompt_eng_file_name = f'system/genai/prompt_inserts/{prompt_inserts}'
276
- if for_iteration:
277
- prompt_eng_file_name = prompt_eng_file_name.replace('.', '_iterations.')
278
317
  assert Path(prompt_eng_file_name).exists(), \
279
318
  f"Missing prompt_inserts file: {prompt_eng_file_name}" # eg api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/sqlite_inserts.prompt
280
- log.debug(f'get_prompt__with_inserts: {str(os.getcwd())} / {prompt_eng_file_name}')
319
+ log.debug(f'get_prompt__with_inserts: {str(os.getcwd())} \n .. merged with: {prompt_eng_file_name}')
281
320
  with open(prompt_eng_file_name, 'r') as file:
282
321
  pre_post = file.read() # eg, Use SQLAlchemy to create a sqlite database named system/genai/temp/create_db_models.sqlite, with
283
322
  prompt_result = pre_post.replace('{{prompt}}', raw_prompt)
323
+ if for_iteration:
324
+ # Update the prior response - be sure not to lose classes and test data already created.
325
+ prompt_result = 'Update the prior response - be sure not to lose classes and test data already created.' \
326
+ + '\n\n' + prompt_result
327
+ log.debug(f'.. iteration inserted: Update the prior response')
328
+ log.debug(f'.... iteration prompt result: {prompt_result}')
284
329
 
285
330
  prompt_lines = prompt_result.split('\n')
286
331
  prompt_line_number = 0
332
+ do_logic = True
287
333
  for each_line in prompt_lines:
288
- if "LogicBank" in each_line:
334
+ if 'Create multiple rows of test data' in each_line:
335
+ if self.project.genai_test_data_rows > 0:
336
+ each_line = each_line.replace(
337
+ f'Create multiple rows',
338
+ f'Create {self.project.genai_test_data_rows} rows')
339
+ prompt_lines[prompt_line_number] = each_line
340
+ log.debug(f'.. inserted explicit test data: {each_line}')
341
+ if K_LogicBankOff in each_line:
342
+ self.logic_enabled = False # for demos
343
+ if "LogicBank" in each_line and do_logic == True:
289
344
  log.debug(f'.. inserted: {each_line}')
290
345
  prompt_eng_logic_file_name = f'system/genai/prompt_inserts/logic_inserts.prompt'
291
346
  with open(prompt_eng_logic_file_name, 'r') as file:
292
347
  prompt_logic = file.read() # eg, Use SQLAlchemy to...
293
348
  prompt_lines[prompt_line_number] = prompt_logic
294
- break
349
+ do_logic = False
295
350
  prompt_line_number += 1
296
351
 
297
352
  response_format_file_name = f'system/genai/prompt_inserts/response_format.prompt'
@@ -347,39 +402,6 @@ class GenAI(object):
347
402
  logic_text += ' ' + each_line + '\n'
348
403
  return logic_text
349
404
 
350
- @staticmethod
351
- def remove_logic_halluncinations(each_line: str) -> str:
352
- """remove hallucinations from logic
353
-
354
- eg: Rule.setup()
355
-
356
- Args:
357
- each_line (str): _description_
358
-
359
- Returns:
360
- str: _description_
361
- """ """ """
362
- return_line = each_line
363
- if each_line.startswith(' Rule.') or each_line.startswith(' DeclareRule.'):
364
- if 'Rule.sum' in each_line:
365
- pass
366
- elif 'Rule.count' in each_line:
367
- pass
368
- elif 'Rule.formula' in each_line:
369
- pass
370
- elif 'Rule.copy' in each_line:
371
- pass
372
- elif 'Rule.constraint' in each_line:
373
- pass
374
- elif 'Rule.allocate' in each_line:
375
- pass
376
- elif 'Rule.calculate' in each_line:
377
- return_line = each_line.replace('Rule.calculate', 'Rule.copy')
378
- else:
379
- return_line = each_line.replace(' ', ' # ')
380
- log.debug(f'.. removed hallucination: {each_line}')
381
- return return_line
382
-
383
405
  def insert_logic_into_created_project(self): # TODO - redesign if conversation
384
406
  """Called *after project created* to insert prompt logic into
385
407
  1. declare_logic.py (as comment)
@@ -388,19 +410,62 @@ class GenAI(object):
388
410
  Also creates the doc directory for record of prompt, response.
389
411
  """
390
412
 
413
+ def remove_logic_halluncinations(each_line: str) -> str:
414
+ """remove hallucinations from logic
415
+
416
+ eg: Rule.setup()
417
+
418
+ Args:
419
+ each_line (str): _description_
420
+
421
+ Returns:
422
+ str: _description_
423
+ """ """ """
424
+ return_line = each_line
425
+ if each_line.startswith('Rule.'):
426
+ # Sometimes indents left out (EmpDepts) - "code": "Rule.sum(derive=Department.salary_total, as_sum_of=Employee.salary)\nRule.constraint(validate=Department,\n as_condition=lambda row: row.salary_total <= row.budget,\n error_msg=\"Department salary total ({row.salary_total}) exceeds budget ({row.budget})\")"
427
+ each_line = " " + each_line # add missing indent
428
+ log.debug(f'.. fixed hallucination/indent: {each_line}')
429
+ if each_line.startswith(' Rule.') or each_line.startswith(' DeclareRule.'):
430
+ if 'Rule.sum' in each_line:
431
+ pass
432
+ elif 'Rule.count' in each_line:
433
+ pass
434
+ elif 'Rule.formula' in each_line:
435
+ pass
436
+ elif 'Rule.copy' in each_line:
437
+ pass
438
+ elif 'Rule.constraint' in each_line:
439
+ pass
440
+ elif 'Rule.allocate' in each_line:
441
+ pass
442
+ elif 'Rule.calculate' in each_line:
443
+ return_line = each_line.replace('Rule.calculate', 'Rule.copy')
444
+ else:
445
+ return_line = each_line.replace(' ', ' # ')
446
+ log.debug(f'.. removed hallucination: {each_line}')
447
+ return return_line
448
+
449
+ logic_enabled = True
391
450
  logic_file = self.project.project_directory_path.joinpath('logic/declare_logic.py')
392
451
  in_logic = False
393
452
  translated_logic = "\n # Logic from GenAI: (or, use your IDE w/ code completion)\n"
394
453
  for each_rule in self.response_dict.rules:
395
454
  comment_line = each_rule.description
396
455
  translated_logic += f'\n # {comment_line}\n'
397
- each_line = each_rule.code
398
- if 'declare_logic.py' not in each_line:
399
- each_repaired_line = self.remove_logic_halluncinations(each_line=each_line)
400
- if not each_repaired_line.startswith(' '): # sometimes in indents, sometimes not
401
- each_repaired_line = ' ' + each_repaired_line
402
- if 'def declare_logic' not in each_repaired_line:
403
- translated_logic += each_repaired_line + '\n'
456
+ code_lines = each_rule.code.split('\n')
457
+ if '\n' in each_rule.code:
458
+ debug_string = "good breakpoint - multi-line rule"
459
+ for each_line in code_lines:
460
+ if 'declare_logic.py' not in each_line:
461
+ each_repaired_line = remove_logic_halluncinations(each_line=each_line)
462
+ if not each_repaired_line.startswith(' '): # sometimes in indents, sometimes not
463
+ each_repaired_line = ' ' + each_repaired_line
464
+ if 'def declare_logic' not in each_repaired_line:
465
+ translated_logic += each_repaired_line + '\n'
466
+ if self.logic_enabled == False:
467
+ translated_logic = "\n # Logic from GenAI: (or, use your IDE w/ code completion)\n"
468
+ translated_logic += "\n # LogicBank Disabled \n"
404
469
  translated_logic += "\n # End Logic from GenAI\n\n"
405
470
  utils.insert_lines_at(lines=translated_logic,
406
471
  file_name=logic_file,
@@ -450,51 +515,209 @@ class GenAI(object):
450
515
  response_data (str): the chatgpt response
451
516
 
452
517
  """
453
- create_db_model_lines = list()
454
- create_db_model_lines.extend(self.get_lines_from_file(f'system/genai/create_db_models_inserts/create_db_models_imports.py'))
455
518
 
519
+ def get_model_class_lines(model: DotMap) -> list[str]:
520
+ """Get the model class from the model
521
+
522
+ Args:
523
+ model (Model): the model
524
+
525
+ Returns:
526
+ stlist[str]: the model class lines, fixed up
527
+ """
528
+
529
+ create_db_model_lines = list()
530
+ create_db_model_lines.append('\n\n')
531
+ class_lines = model.code.split('\n')
532
+ line_num = 0
533
+ indents_to_remove = 0
534
+ for each_line in class_lines:
535
+ line_num += 1
536
+ ''' decimal issues
537
+
538
+ 1. bad import: see Run: tests/test_databases/ai-created/genai_demo/genai_demo_decimal
539
+ from decimal import Decimal # Decimal fix: needs to be from decimal import DECIMAL
540
+
541
+ 2. Missing missing import: from SQLAlchemy import .... DECIMAL
542
+
543
+ 3. Column(Decimal) -> Column(DECIMAL)
544
+ see in: tests/test_databases/ai-created/budget_allocation/budget_allocations/budget_allocations_3_decimal
545
+
546
+ 4. Bad syntax on test data: see Run: blt/time_cards_decimal from RESPONSE
547
+ got: balance=DECIMAL('100.50')
548
+ needed: balance=1000.0
549
+ fixed with import in create_db_models_prefix.py
550
+
551
+ 5. Bad syntax on test data cals: see api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_conversation_bad_decimal/genai_demo_03.response
552
+ got: or Decimal('0.00')
553
+ needed: or decimal.Decimal('0.00')
554
+
555
+ 6. Bad syntax on test data cals: see api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_conversation_bad_decimal_2/genai_demo_conversation_002.response
556
+ got: or DECIMAL('
557
+ needed: or decimal.Decimal('0.00')
558
+ '''
559
+ if "= Table(" in each_line: # tests/test_databases/ai-created/time_cards/time_card_kw_arg/genai.response
560
+ log.debug(f'.. fix_and_write_model_file detects table - raise excp to trigger retry')
561
+ self.post_error = "ChatGPT Response contains table (not class) definitions: " + each_line
562
+ if 'sqlite:///' in each_line: # must be sqlite:///system/genai/temp/create_db_models.sqlite
563
+ current_url_rest = each_line.split('sqlite:///')[1]
564
+ quote_type = "'"
565
+ if '"' in current_url_rest:
566
+ quote_type = '"' # eg, tests/test_databases/ai-created/time_cards/time_card_decimal/genai.response
567
+ current_url = current_url_rest.split(quote_type)[0]
568
+ proper_url = 'system/genai/temp/create_db_models.sqlite'
569
+ each_line = each_line.replace(current_url, proper_url)
570
+ if current_url != proper_url:
571
+ log.debug(f'.. fixed sqlite url: {current_url} -> system/genai/temp/create_db_models.sqlite')
572
+ if 'Decimal,' in each_line: # SQLAlchemy import
573
+ each_line = each_line.replace('Decimal,', 'DECIMAL,')
574
+ # other Decimal bugs: see api_logic_server_cli/prototypes/manager/system/genai/reference/errors/chatgpt_decimal.txt
575
+ if ', Decimal' in each_line: # Cap'n K, at your service
576
+ each_line = each_line.replace(', Decimal', ', DECIMAL')
577
+ if 'rom decimal import Decimal' in each_line:
578
+ each_line = each_line.replace('from decimal import Decimal', 'import decimal')
579
+ if '=Decimal(' in each_line:
580
+ each_line = each_line.replace('=Decimal(', '=decimal.Decimal(')
581
+ if ' Decimal(' in each_line:
582
+ each_line = each_line.replace(' Decimal(', ' decimal.Decimal(')
583
+ if 'Column(Decimal)' in each_line:
584
+ each_line = each_line.replace('Column(Decimal)', 'Column(DECIMAL)')
585
+ if "DECIMAL('" in each_line:
586
+ each_line = each_line.replace("DECIMAL('", "decimal.Decimal('")
587
+ if 'end_time(datetime' in each_line: # tests/test_databases/ai-created/time_cards/time_card_kw_arg/genai.response
588
+ each_line = each_line.replace('end_time(datetime', 'end_time=datetime')
589
+ if indents_to_remove > 0:
590
+ each_line = each_line[indents_to_remove:]
591
+ if 'relationship(' in each_line and self.project.genai_use_relns == False:
592
+ # airport4 fails with could not determine join condition between parent/child tables on relationship Airport.flights
593
+ if each_line.startswith(' '):
594
+ each_line = each_line.replace(' ', ' # ')
595
+ else: # sometimes it puts relns outside the class (so, outdented)
596
+ each_line = '# ' + each_line
597
+ if 'sqlite:///system/genai/temp/model.sqlite': # fix prior version
598
+ each_line = each_line.replace('sqlite:///system/genai/temp/model.sqlite',
599
+ 'sqlite:///system/genai/temp/create_db_models.sqlite')
600
+
601
+ # logicbank fixes
602
+ if 'from logic_bank' in each_line: # we do our own imports
603
+ each_line = each_line.replace('from', '# from')
604
+ if 'LogicBank.activate' in each_line:
605
+ each_line = each_line.replace('LogicBank.activate', '# LogicBank.activate')
606
+
607
+ create_db_model_lines.append(each_line + '\n')
608
+ return create_db_model_lines
609
+
610
+ def fix_model_lines(models, create_db_model_lines):
611
+ did_base = False
612
+ for each_model in models:
613
+ model_lines = get_model_class_lines(model=each_model)
614
+ for each_line in model_lines:
615
+ each_fixed_line = each_line.replace('sa.', '') # sometimes it puts sa. in front of Column
616
+ if 'Base = declarative_base()' in each_fixed_line: # sometimes created for each class
617
+ if did_base:
618
+ each_fixed_line = '# ' + each_fixed_line
619
+ did_base = True
620
+ if 'datetime.datetime.utcnow' in each_fixed_line:
621
+ each_fixed_line = each_fixed_line.replace('datetime.datetime.utcnow', 'datetime.now()')
622
+ if 'Column(date' in each_fixed_line:
623
+ each_fixed_line = each_fixed_line.replace('Column(dat', 'column(Date')
624
+ create_db_model_lines.append(each_fixed_line)
625
+ return create_db_model_lines
626
+
627
+ def insert_test_data_lines(test_data_lines : list[str]) -> list[str]:
628
+ """Insert test data lines into the model file
629
+
630
+ Args:
631
+ test_data_lines (list(str)):
632
+ * initially header (engine =, sesssion =)
633
+ * this function appends CPT test data
634
+
635
+ Returns:
636
+ list[str]: variable names for the test data rows (for create_all)
637
+ """
638
+
639
+ def fix_test_data_line(each_fixed_line: str) -> str:
640
+ """Fix the test data line
641
+
642
+ Args:
643
+ each_fixed_line (str): the test data line
644
+
645
+ Returns:
646
+ str: the fixed test data line
647
+ """
648
+
649
+ if '=datetime' in each_fixed_line:
650
+ each_fixed_line = each_fixed_line.replace('=datetime.date', '=date')
651
+ if 'datetime.datetime.utcnow' in each_fixed_line:
652
+ each_fixed_line = each_fixed_line.replace('datetime.datetime.utcnow', 'datetime.now()')
653
+ if 'engine = create_engine' in each_fixed_line: # CBT sometimes has engine = create_engine, so do we!
654
+ each_fixed_line = each_fixed_line.replace('engine = create_engine', '# engine = create_engine')
655
+ check_for_row_name = False
656
+ if each_fixed_line.startswith('Base') or each_fixed_line.startswith('engine'):
657
+ check_for_row_name = False
658
+ if 'Base.metadata.create_all(engine)' in each_fixed_line:
659
+ each_fixed_line = each_fixed_line.replace('Base.metadata.create_all(engine)', '# Base.metadata.create_all(engine)')
660
+ return each_fixed_line
661
+
662
+ row_names = list()
663
+ use_test_data_rows = True # CPT test data, new format - test_data_rows (*way* less variable)
664
+ if use_test_data_rows & hasattr(self.response_dict, 'test_data_rows'):
665
+ test_data_rows = self.response_dict.test_data_rows
666
+ log.debug(f'.... test_data_rows: {len(test_data_rows)}')
667
+ for each_row in test_data_rows:
668
+ each_fixed_line = fix_test_data_line(each_row.code)
669
+ test_data_lines.append(each_fixed_line)
670
+ row_names.append(each_row.test_data_row_variable)
671
+ pass
672
+ else: # CPT test data, old format - rows, plus session, engine etc (quite variable)
673
+ test_data_lines_ori = self.response_dict.test_data.split('\n') # gpt response
674
+ log.debug(f'.... test_data_lines...')
675
+ for each_line in test_data_lines_ori:
676
+ each_fixed_line = fix_test_data_line(each_line)
677
+ check_for_row_name = True
678
+ test_data_lines.append(each_fixed_line) # append the fixed test data line
679
+ if check_for_row_name and ' = ' in each_line and '(' in each_line: # CPT test data might have: tests = []
680
+ assign = each_line.split(' = ')[0]
681
+ # no tokens for: Session = sessionmaker(bind=engine) or session = Session()
682
+ if '.' not in assign and 'Session' not in each_line and 'session.' not in each_line:
683
+ row_names.append(assign)
684
+ return row_names
685
+
686
+ create_db_model_lines = list()
687
+ create_db_model_lines.append(f'# using resolved_model {self.resolved_model}')
688
+ create_db_model_lines.extend( # imports for classes (comes from api_logic_server_cli/prototypes/manager/system/genai/create_db_models_inserts/create_db_models_imports.py)
689
+ self.get_lines_from_file(f'system/genai/create_db_models_inserts/create_db_models_imports.py'))
690
+ create_db_model_lines.append("\nfrom sqlalchemy.dialects.sqlite import *\n") # specific for genai
691
+
456
692
  models = self.response_dict.models
457
- did_base = False
458
- for each_model in models:
459
- model_lines = self.get_model_class_lines(model=each_model)
460
- for each_line in model_lines:
461
- each_fixed_line = each_line.replace('sa.', '') # sometimes it puts sa. in front of Column
462
- if 'Base = declarative_base()' in each_fixed_line: # sometimes created for each class
463
- if did_base:
464
- each_fixed_line = '# ' + each_fixed_line
465
- did_base = True
466
- create_db_model_lines.append(each_fixed_line)
467
-
468
- create_db_model_lines.extend(self.get_lines_from_file(f'system/genai/create_db_models_inserts/create_db_models_create_db.py'))
469
-
470
- test_data_lines = self.response_dict.test_data.split('\n')
471
- row_names = list()
472
- for each_line in test_data_lines:
473
- each_fixed_line = each_line
474
- if '=datetime' in each_fixed_line:
475
- each_fixed_line = each_fixed_line.replace('=datetime.date', '=date')
476
- if 'engine = create_engine' in each_fixed_line: # CBT sometimes has engine = create_engine, so do we!
477
- each_fixed_line = each_fixed_line.replace('engine = create_engine', '# engine = create_engine')
478
- if 'Base.metadata.create_all(engine)e' in each_fixed_line:
479
- each_fixed_line = each_fixed_line.replace('Base.metadata.create_all(engine)', '# Base.metadata.create_all(engine)')
480
- create_db_model_lines.append(each_fixed_line + '\n')
481
- if ' = ' in each_line and '(' in each_line: # CPT test data might have: tests = []
482
- assign = each_line.split(' = ')[0]
483
- # no tokens for: Session = sessionmaker(bind=engine) or session = Session()
484
- if '.' not in assign and 'Session' not in each_line and 'session.' not in each_line:
485
- row_names.append(assign)
486
-
487
- create_db_model_lines.append('\n\n')
488
- row_name_list = ', '.join(row_names)
489
- add_rows = f'session.add_all([{row_name_list}])'
490
- create_db_model_lines.append(add_rows + '\n')
491
- create_db_model_lines.append('session.commit()\n')
693
+
694
+ # Usage inside the class
695
+ create_db_model_lines = fix_model_lines(models, create_db_model_lines)
492
696
 
493
697
  with open(f'{self.project.from_model}', "w") as create_db_model_file:
494
- for line in create_db_model_lines:
495
- create_db_model_file.write(f"{line}")
698
+ create_db_model_file.write("".join(create_db_model_lines))
699
+ create_db_model_file.write("\n\n# end of model classes\n\n")
700
+
701
+ # classes done, create db and add test_data code
702
+ test_data_lines = self.get_lines_from_file(f'system/genai/create_db_models_inserts/create_db_models_create_db.py')
703
+ test_data_lines.append('session.commit()')
496
704
 
497
- log.debug(f'.. model file created: {self.project.from_model}')
705
+ row_names = insert_test_data_lines(test_data_lines)
706
+
707
+ test_data_lines.append('\n\n')
708
+ row_name_list = ', '.join(row_names)
709
+ add_rows = f'session.add_all([{row_name_list}])'
710
+ test_data_lines.append(add_rows )
711
+ test_data_lines.append('session.commit()')
712
+ test_data_lines.append('# end of test data\n\n')
713
+
714
+ with open(f'{self.project.from_model}', "a") as create_db_model_file:
715
+ create_db_model_file.write("try:\n ")
716
+ create_db_model_file.write("\n ".join(test_data_lines))
717
+ create_db_model_file.write("except Exception as exc:\n")
718
+ create_db_model_file.write(" print(f'Test Data Error: {exc}')\n")
719
+
720
+ log.debug(f'.. code for db creation and test data: {self.project.from_model}')
498
721
 
499
722
  def get_lines_from_file(self, file_name: str) -> list[str]:
500
723
  """Get lines from a file
@@ -510,105 +733,6 @@ class GenAI(object):
510
733
  lines = file.readlines()
511
734
  return lines
512
735
 
513
- def get_model_test_data_lines_ZZ(self, model: DotMap) -> list[str]:
514
- create_db_model_lines = list()
515
- create_db_model_lines.append('\n\n')
516
- sample_data = model.sample_data
517
- for each_line in sample_data:
518
- create_db_model_lines.append(each_line + '\n')
519
- return create_db_model_lines
520
-
521
- def get_model_class_lines(self, model: DotMap) -> list[str]:
522
- """Get the model class from the model
523
-
524
- Args:
525
- model (Model): the model
526
-
527
- Returns:
528
- stlist[str]: the model class lines, fixed up
529
- """
530
-
531
- create_db_model_lines = list()
532
- create_db_model_lines.append('\n\n')
533
- class_lines = model.code.split('\n')
534
- line_num = 0
535
- indents_to_remove = 0
536
- for each_line in class_lines:
537
- line_num += 1
538
- ''' decimal issues
539
-
540
- 1. bad import: see Run: tests/test_databases/ai-created/genai_demo/genai_demo_decimal
541
- from decimal import Decimal # Decimal fix: needs to be from decimal import DECIMAL
542
-
543
- 2. Missing missing import: from SQLAlchemy import .... DECIMAL
544
-
545
- 3. Column(Decimal) -> Column(DECIMAL)
546
- see in: tests/test_databases/ai-created/budget_allocation/budget_allocations/budget_allocations_3_decimal
547
-
548
- 4. Bad syntax on test data: see Run: blt/time_cards_decimal from RESPONSE
549
- got: balance=DECIMAL('100.50')
550
- needed: balance=1000.0
551
- fixed with import in create_db_models_prefix.py
552
-
553
- 5. Bad syntax on test data cals: see api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_conversation_bad_decimal/genai_demo_03.response
554
- got: or Decimal('0.00')
555
- needed: or decimal.Decimal('0.00')
556
-
557
- 6. Bad syntax on test data cals: see api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_conversation_bad_decimal_2/genai_demo_conversation_002.response
558
- got: or DECIMAL('
559
- needed: or decimal.Decimal('0.00')
560
- '''
561
- if "= Table(" in each_line: # tests/test_databases/ai-created/time_cards/time_card_kw_arg/genai.response
562
- log.debug(f'.. fix_and_write_model_file detects table - raise excp to trigger retry')
563
- self.post_error = "ChatGPT Response contains table (not class) definitions: " + each_line
564
- if 'sqlite:///' in each_line: # must be sqlite:///system/genai/temp/create_db_models.sqlite
565
- current_url_rest = each_line.split('sqlite:///')[1]
566
- quote_type = "'"
567
- if '"' in current_url_rest:
568
- quote_type = '"' # eg, tests/test_databases/ai-created/time_cards/time_card_decimal/genai.response
569
- current_url = current_url_rest.split(quote_type)[0]
570
- proper_url = 'system/genai/temp/create_db_models.sqlite'
571
- each_line = each_line.replace(current_url, proper_url)
572
- if current_url != proper_url:
573
- log.debug(f'.. fixed sqlite url: {current_url} -> system/genai/temp/create_db_models.sqlite')
574
- if 'Decimal,' in each_line: # SQLAlchemy import
575
- each_line = each_line.replace('Decimal,', 'DECIMAL,')
576
- # other Decimal bugs: see api_logic_server_cli/prototypes/manager/system/genai/reference/errors/chatgpt_decimal.txt
577
- if ', Decimal' in each_line: # Cap'n K, at your service
578
- each_line = each_line.replace(', Decimal', ', DECIMAL')
579
- if 'rom decimal import Decimal' in each_line:
580
- each_line = each_line.replace('from decimal import Decimal', 'import decimal')
581
- if '=Decimal(' in each_line:
582
- each_line = each_line.replace('=Decimal(', '=decimal.Decimal(')
583
- if ' Decimal(' in each_line:
584
- each_line = each_line.replace(' Decimal(', ' decimal.Decimal(')
585
- if 'Column(Decimal)' in each_line:
586
- each_line = each_line.replace('Column(Decimal)', 'Column(DECIMAL)')
587
- if "DECIMAL('" in each_line:
588
- each_line = each_line.replace("DECIMAL('", "decimal.Decimal('")
589
- if 'end_time(datetime' in each_line: # tests/test_databases/ai-created/time_cards/time_card_kw_arg/genai.response
590
- each_line = each_line.replace('end_time(datetime', 'end_time=datetime')
591
- if indents_to_remove > 0:
592
- each_line = each_line[indents_to_remove:]
593
- if 'relationship(' in each_line and self.project.genai_use_relns == False:
594
- # airport4 fails with could not determine join condition between parent/child tables on relationship Airport.flights
595
- if each_line.startswith(' '):
596
- each_line = each_line.replace(' ', ' # ')
597
- else: # sometimes it puts relns outside the class (so, outdented)
598
- each_line = '# ' + each_line
599
- if 'sqlite:///system/genai/temp/model.sqlite': # fix prior version
600
- each_line = each_line.replace('sqlite:///system/genai/temp/model.sqlite',
601
- 'sqlite:///system/genai/temp/create_db_models.sqlite')
602
-
603
- # logicbank fixes
604
- if 'from logic_bank' in each_line: # we do our own imports
605
- each_line = each_line.replace('from', '# from')
606
- if 'LogicBank.activate' in each_line:
607
- each_line = each_line.replace('LogicBank.activate', '# LogicBank.activate')
608
-
609
- create_db_model_lines.append(each_line + '\n')
610
- return create_db_model_lines
611
-
612
736
  def save_prompt_messages_to_system_genai_temp_project(self):
613
737
  """
614
738
  Save prompts / responses to system/genai/temp/{project}/genai.response
@@ -657,37 +781,10 @@ class GenAI(object):
657
781
  log.error(f"\n\nError: {inst} \n..creating diagnostic files into dir: {str(gen_temp_dir)}\n\n")
658
782
  pass # intentional try/catch/bury - it's just diagnostics, so don't fail
659
783
  debug_string = "good breakpoint - return to main driver, and execute create_db_models.py"
660
-
661
- def get_headers_with_openai_api_key_ZZ(self) -> dict:
662
- """
663
- Returns:
664
- dict: api header with OpenAI key (exits if not provided)
665
- """
666
-
667
- pass # https://community.openai.com/t/how-do-i-call-chatgpt-api-with-python-code/554554
668
- if os.getenv('APILOGICSERVER_CHATGPT_APIKEY'):
669
- openai_api_key = os.getenv('APILOGICSERVER_CHATGPT_APIKEY')
670
- else:
671
- from dotenv import dotenv_values
672
- secrets = dotenv_values("system/secrets.txt")
673
- openai_api_key = secrets['APILOGICSERVER_CHATGPT_APIKEY']
674
- if openai_api_key == 'your-api-key-here':
675
- if os.getenv('APILOGICSERVER_CHATGPT_APIKEY'):
676
- openai_api_key = os.getenv('APILOGICSERVER_CHATGPT_APIKEY')
677
- else:
678
- log.error("\n\nMissing env value: APILOGICSERVER_CHATGPT_APIKEY")
679
- log.error("... Check your system/secrets file...\n")
680
- exit(1)
681
- headers = {
682
- "Content-Type": "application/json",
683
- "Authorization": f"Bearer {openai_api_key}"
684
- }
685
- return headers
686
784
 
687
785
  def get_and_save_raw_response_data(self, completion: object, response_dict: dict):
688
786
  """
689
- Returns:
690
- str: response_data
787
+ Write prompt --> system/genai/temp/chatgpt_original/retry.response
691
788
  """
692
789
 
693
790
  ''' TODO - is exception used instead of return_code...
@@ -698,7 +795,6 @@ class GenAI(object):
698
795
  if completion.status_code != 200:
699
796
  print("Error:", completion.status_code, completion.text) # eg, You exceeded your current quota
700
797
  '''
701
-
702
798
  with open(f'system/genai/temp/chatgpt_original.response', "w") as response_file: # save for debug
703
799
  json.dump(response_dict, response_file, indent=4)
704
800
  with open(f'system/genai/temp/chatgpt_retry.response', "w") as response_file: # repair this & retry
@@ -706,10 +802,11 @@ class GenAI(object):
706
802
  return
707
803
 
708
804
 
709
- def genai(using, db_url, repaired_response: bool, genai_version: str,
805
+ def genai_cli_retry(using: str, db_url: str, repaired_response: str, genai_version: str,
710
806
  retries: int, opt_locking: str, prompt_inserts: str, quote: bool,
711
- use_relns: bool, project_name: str):
712
- """ CLI caller provides using, or repaired_response & using
807
+ use_relns: bool, project_name: str, tables: int, test_data_rows: int,
808
+ temperature: float) -> None:
809
+ """ CLI Caller: provides using, or repaired_response & using
713
810
 
714
811
  Called from cli commands: genai, genai-create, genai-iterate
715
812
 
@@ -720,46 +817,48 @@ def genai(using, db_url, repaired_response: bool, genai_version: str,
720
817
  import api_logic_server_cli.api_logic_server as PR
721
818
 
722
819
  resolved_project_name = project_name
723
- if resolved_project_name == '' or resolved_project_name is None:
724
- resolved_project_name = Path(using).stem # default project name is the <cwd>/last node of using
820
+ if repaired_response != "":
821
+ if resolved_project_name == '' or resolved_project_name is None:
822
+ resolved_project_name = Path(using).stem # project dir is the <cwd>/last node of using
725
823
  resolved_project_name = resolved_project_name.replace(' ', '_')
824
+ start_time = time.time()
726
825
 
727
826
  try_number = 1
728
827
  genai_use_relns = use_relns
729
828
  """ if 'unable to determine join condition', we retry this with False """
730
829
  if repaired_response != "":
731
830
  try_number = retries # if not calling GenAI, no need to retry:
732
- # TODO or 0, right?
831
+ failed = False
832
+ pr = PR.ProjectRun(command="create",
833
+ genai_version=genai_version,
834
+ genai_temperature = temperature,
835
+ genai_using=using, # the prompt file, or dir of prompt/response
836
+ repaired_response=repaired_response, # retry from [repaired] response file
837
+ opt_locking=opt_locking,
838
+ genai_prompt_inserts=prompt_inserts,
839
+ genai_use_relns=genai_use_relns,
840
+ quote=quote,
841
+ genai_tables=tables,
842
+ genai_test_data_rows=test_data_rows,
843
+ project_name=resolved_project_name, db_url=db_url,
844
+ execute=False)
733
845
  if retries < 0: # for debug: catch exceptions at point of failure
734
- PR.ProjectRun(command="create", genai_version=genai_version,
735
- genai_using=using, # the prompt file, or conversation dir
736
- repaired_response=repaired_response, # retry from [repaired] response file
737
- opt_locking=opt_locking,
738
- genai_prompt_inserts=prompt_inserts,
739
- genai_use_relns=genai_use_relns,
740
- quote=quote,
741
- project_name=resolved_project_name, db_url=db_url)
846
+ pr.create_project() # calls GenAI() - the main driver
742
847
  log.info(f"GENAI successful")
743
848
  else:
744
- failed = False
745
849
  while try_number <= retries:
746
850
  try:
747
851
  failed = False
748
- PR.ProjectRun(command="create", genai_version=genai_version,
749
- genai_using=using, # the prompt file, or dir of prompt/response
750
- repaired_response=repaired_response, # retry from [repaired] response file
751
- opt_locking=opt_locking,
752
- genai_prompt_inserts=prompt_inserts,
753
- genai_use_relns=genai_use_relns,
754
- quote=quote,
755
- project_name=resolved_project_name, db_url=db_url)
852
+ pr.create_project() # calls GenAI() - the main driver
756
853
  if do_force_failure := False:
757
854
  if try_number < 3:
758
855
  raise Exception("Forced Failure for Internal Testing")
759
856
  break # success - exit the loop
760
857
  except Exception as e: # almost certaily in api_logic_server_cli/create_from_model/create_db_from_model.py
858
+ log.error(traceback.format_exc())
761
859
  log.error(f"\n\nGenai failed With Error: {e}")
762
-
860
+ if resolved_project_name == '_genai_default':
861
+ resolved_project_name = pr.project_name # defaulted in genai from response
763
862
  if Path(using).is_dir():
764
863
  log.debug('conversation dir, check in-place iteration')
765
864
  '''
@@ -819,10 +918,11 @@ def genai(using, db_url, repaired_response: bool, genai_version: str,
819
918
  try_number += 1
820
919
  log.debug(f"\n\nRetry Genai #{try_number}\n")
821
920
  pass # retry (retries times)
822
- if failed == True: # retries exhausted (if failed: threw "an integer is required" ??
921
+ if failed == True: # retries exhausted (if failed: threw "an integer is required" ??
922
+ pass # https://github.com/microsoft/debugpy/issues/1708
823
923
  log.error(f"\n\nGenai Failed (Retries: {retries})")
824
924
  exit(1)
825
- log.info(f"GENAI successful on try {try_number}")
925
+ log.info(f"\nGENAI ({str(int(time.time() - start_time))} secs) successful on try {try_number}\n")
826
926
 
827
927
 
828
928
  def key_module_map():