DJHumanRPT commited on
Commit
517e8e2
·
verified ·
1 Parent(s): 60845b9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +546 -499
app.py CHANGED
@@ -1290,250 +1290,459 @@ with tab2:
1290
  if "show_suggested_vars" not in st.session_state:
1291
  st.session_state.show_suggested_vars = False
1292
 
1293
- # Basic template information
1294
- with st.expander("Template Information", expanded=True):
1295
- col1, col2 = st.columns(2)
1296
- with col1:
1297
- st.session_state.template_spec["name"] = st.text_input(
1298
- "Template Name", value=st.session_state.template_spec["name"]
1299
- )
1300
- with col2:
1301
- st.session_state.template_spec["version"] = st.text_input(
1302
- "Version", value=st.session_state.template_spec["version"]
 
 
 
 
 
 
 
 
 
 
 
1303
  )
1304
 
1305
- st.session_state.template_spec["description"] = st.text_area(
1306
- "Description",
1307
- value=st.session_state.template_spec["description"],
1308
- height=100,
1309
- )
1310
 
1311
- # Prompt Template Section
1312
- with st.expander("Prompt Template", expanded=True):
1313
- st.info("Use {variable_name} to refer to input variables in your template")
 
 
 
1314
 
1315
- # Add buttons for prompt management
1316
- col1, col2 = st.columns([1, 1])
1317
- with col1:
1318
- rewrite_prompt = st.button("AI Rewrite Prompt")
1319
- with col2:
1320
- reroll_prompt = st.button("Reroll Prompt Variation")
 
 
 
 
 
 
 
 
 
 
 
 
 
1321
 
1322
- # Handle prompt rewriting
1323
- if rewrite_prompt or reroll_prompt:
1324
- with st.spinner("Generating improved prompt template..."):
1325
- improved_template = generate_improved_prompt_template(
1326
- st.session_state.template_spec, st.session_state.knowledge_base
1327
  )
1328
- # Only update if we got a valid result back
1329
- if improved_template and len(improved_template) > 10:
1330
- st.session_state.template_spec["prompt"] = improved_template
1331
- st.success("Prompt template updated!")
1332
-
1333
- # Display the prompt template
1334
- prompt_template = st.text_area(
1335
- "Edit the prompt template",
1336
- value=st.session_state.template_spec["prompt"],
1337
- height=200,
1338
- )
1339
- st.session_state.template_spec["prompt"] = prompt_template
1340
 
1341
- # Knowledge Base Analysis Section - Moved outside of Input Variables expander
1342
- if st.session_state.knowledge_base:
1343
- with st.expander("Knowledge Base Analysis", expanded=False):
1344
- st.info("Analyze the knowledge base to suggest variables and values")
1345
-
1346
- if st.button(
1347
- "Analyze Knowledge Base for Variables",
1348
- key="analyze_kb_button_input",
1349
- ):
1350
- client = get_openai_client()
1351
- if not client:
1352
- st.error(
1353
- "Please provide an OpenAI API key to analyze the knowledge base."
1354
- )
1355
- else:
1356
- with st.spinner("Analyzing knowledge base..."):
1357
- suggested_vars = analyze_knowledge_base(
1358
- st.session_state.knowledge_base, client
1359
  )
1360
- if suggested_vars:
1361
- st.session_state.suggested_variables = suggested_vars
1362
- st.session_state.show_suggested_vars = True
1363
- st.success(
1364
- f"Found {len(suggested_vars)} potential variables in the knowledge base"
1365
  )
1366
- else:
1367
- st.warning(
1368
- "Could not extract variables from the knowledge base"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1369
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1370
 
1371
- # Display suggested variables if they exist
1372
- if (
1373
- st.session_state.suggested_variables
1374
- and st.session_state.show_suggested_vars
1375
- ):
1376
- st.subheader("Suggested Variables")
 
1377
 
1378
- for i, var in enumerate(st.session_state.suggested_variables):
1379
- # Generate a unique ID for this variable
1380
- var_id = f"{var['name']}_{i}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1381
 
1382
- # Check if this variable has already been added
1383
- if var_id in st.session_state.added_suggestions:
1384
- continue
1385
 
1386
- col1, col2 = st.columns([4, 1])
1387
  with col1:
1388
- st.markdown(
1389
- f"**{var['name']}** ({var['type']}): {var['description']}"
1390
- )
1391
- if var.get("options"):
1392
- st.markdown(f"Options: {', '.join(var['options'])}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
  with col2:
1394
- if st.button("Add", key=f"add_suggested_{var_id}"):
1395
- # Add this variable to the template
1396
- new_var = {
1397
- "name": var["name"],
1398
- "description": var["description"],
1399
- "type": var["type"],
1400
- }
1401
- if var.get("options"):
1402
- new_var["options"] = var["options"]
1403
- if var["type"] in ["string", "int", "float"]:
1404
- new_var["min"] = 1
1405
- new_var["max"] = 100
1406
 
1407
- # Add to input variables
1408
- st.session_state.template_spec["input"].append(new_var)
 
 
 
 
 
1409
 
1410
- # Mark this variable as added
1411
- st.session_state.added_suggestions.add(var_id)
 
 
 
 
 
 
 
 
 
1412
 
1413
- # Show success message
1414
- st.success(f"Added {var['name']} to input variables!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1415
 
1416
- # Input Variables Section
1417
- with st.expander("Input Variables", expanded=True):
1418
- # Add input variable button
1419
- col1, col2 = st.columns([3, 1])
1420
- with col1:
1421
- new_input_name = st.text_input(
1422
- "New input variable name", key="new_input_name"
1423
- )
1424
- with col2:
1425
- if st.button("Add Input Variable"):
1426
- new_var = {
1427
- "name": (
1428
- new_input_name
1429
- if new_input_name
1430
- else f"new_input_{len(st.session_state.template_spec['input']) + 1}"
1431
- ),
1432
- "description": "New input variable",
1433
- "type": "string",
1434
- "min": 1,
1435
- "max": 100,
1436
- }
1437
- st.session_state.template_spec["input"].append(new_var)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1438
 
1439
- # Display input variables with integrated input fields
1440
- st.subheader("Input Variables")
 
 
1441
 
1442
- # Create a container for the variables
1443
- for i, input_var in enumerate(st.session_state.template_spec["input"]):
1444
- var_name = input_var["name"]
1445
- var_type = input_var["type"]
1446
- var_desc = input_var["description"]
1447
 
1448
- with st.container():
1449
- # Variable header with description
1450
- st.markdown(f"##### {var_desc}")
1451
 
1452
- # Create columns for the variable controls
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1453
  col1, col2, col3 = st.columns([3, 1, 1])
1454
 
1455
  with col1:
1456
- # Create the appropriate input field based on variable type
1457
- if var_type == "string":
1458
- st.session_state.user_inputs[var_name] = st.text_input(
1459
- f"Enter value for {var_name}", key=f"use_{var_name}"
1460
- )
1461
- elif var_type == "int":
1462
- st.session_state.user_inputs[var_name] = st.number_input(
1463
- f"Enter value for {var_name}",
1464
- min_value=input_var.get("min", None),
1465
- max_value=input_var.get("max", None),
1466
- step=1,
1467
- key=f"use_{var_name}",
1468
- )
1469
- elif var_type == "float":
1470
- st.session_state.user_inputs[var_name] = st.number_input(
1471
- f"Enter value for {var_name}",
1472
- min_value=float(input_var.get("min", 0)),
1473
- max_value=float(input_var.get("max", 100)),
1474
- key=f"use_{var_name}",
1475
- )
1476
- elif var_type == "bool":
1477
- st.session_state.user_inputs[var_name] = st.checkbox(
1478
- f"Select value for {var_name}", key=f"use_{var_name}"
1479
- )
1480
- elif var_type == "categorical":
1481
- options = input_var.get("options", [])
1482
- min_selections = input_var.get("min", 1)
1483
- max_selections = input_var.get("max", 1)
1484
-
1485
- if options:
1486
- if min_selections == 1 and max_selections == 1:
1487
- # Single selection
1488
- st.session_state.user_inputs[var_name] = (
1489
- st.selectbox(
1490
- f"Select value for {var_name}",
1491
- options=options,
1492
- key=f"use_{var_name}",
1493
- )
1494
- )
1495
- else:
1496
- # Multi-selection
1497
- st.session_state.user_inputs[var_name] = (
1498
- st.multiselect(
1499
- f"Select {min_selections}-{max_selections} values for {var_name}",
1500
- options=options,
1501
- default=(
1502
- options[:min_selections]
1503
- if len(options) >= min_selections
1504
- else options
1505
- ),
1506
- key=f"use_{var_name}",
1507
- )
1508
- )
1509
- else:
1510
- st.warning(f"No options defined for {var_name}")
1511
 
1512
  with col2:
1513
  # Button to edit this variable
1514
- if st.button("Edit Settings", key=f"edit_input_{i}"):
1515
- st.session_state.show_variable_editor = i
1516
 
1517
  with col3:
1518
  # Button to remove this variable
1519
- if st.button("Remove", key=f"remove_input_{i}"):
1520
- st.session_state.template_spec["input"].pop(i)
1521
  st.rerun()
1522
 
1523
  # Show editor if this variable is selected
1524
- if st.session_state.show_variable_editor == i:
1525
  with st.container():
1526
  st.markdown("---")
1527
- st.markdown(f"##### Variable Settings: {input_var['name']}")
 
 
1528
 
1529
  # Name and description
1530
- input_var["name"] = st.text_input(
1531
- "Name", value=input_var["name"], key=f"input_name_{i}"
1532
  )
1533
- input_var["description"] = st.text_input(
1534
  "Description",
1535
- value=input_var["description"],
1536
- key=f"input_desc_{i}",
1537
  )
1538
 
1539
  # Type selection
@@ -1552,31 +1761,31 @@ with tab2:
1552
  "float",
1553
  "bool",
1554
  "categorical",
1555
- ].index(input_var["type"]),
1556
- key=f"input_type_{i}",
1557
  )
1558
- input_var["type"] = var_type
1559
 
1560
  # Type-specific settings
1561
  if var_type in ["string", "int", "float"]:
1562
  col1, col2 = st.columns(2)
1563
  with col1:
1564
- input_var["min"] = st.number_input(
1565
  "Min",
1566
- value=int(input_var.get("min", 0)),
1567
- key=f"input_min_{i}",
1568
  )
1569
  with col2:
1570
- input_var["max"] = st.number_input(
1571
  "Max",
1572
- value=int(input_var.get("max", 100)),
1573
- key=f"input_max_{i}",
1574
  )
1575
 
1576
  if var_type == "categorical":
1577
  # Suggest options from KB button
1578
  if st.button(
1579
- "Suggest Options from KB", key=f"suggest_input_{i}"
1580
  ):
1581
  client = get_openai_client()
1582
  if not client:
@@ -1589,18 +1798,18 @@ with tab2:
1589
  )
1590
  else:
1591
  with st.spinner(
1592
- f"Suggesting options for {input_var['name']}..."
1593
  ):
1594
  suggestions = (
1595
  suggest_variable_values_from_kb(
1596
- input_var["name"],
1597
  "categorical",
1598
  st.session_state.knowledge_base,
1599
  client,
1600
  )
1601
  )
1602
  if suggestions and "options" in suggestions:
1603
- input_var["options"] = suggestions[
1604
  "options"
1605
  ]
1606
  st.success(
@@ -1612,13 +1821,13 @@ with tab2:
1612
  )
1613
 
1614
  # Options editor
1615
- options = input_var.get("options", [])
1616
  options_str = st.text_area(
1617
  "Options (one per line)",
1618
  value="\n".join(options),
1619
- key=f"input_options_{i}",
1620
  )
1621
- input_var["options"] = [
1622
  opt.strip()
1623
  for opt in options_str.split("\n")
1624
  if opt.strip()
@@ -1627,324 +1836,162 @@ with tab2:
1627
  # Min/max selections
1628
  col1, col2 = st.columns(2)
1629
  with col1:
1630
- input_var["min"] = st.number_input(
1631
  "Min selections",
1632
- value=int(input_var.get("min", 1)),
1633
  min_value=0,
1634
- key=f"input_cat_min_{i}",
1635
  )
1636
  with col2:
1637
- input_var["max"] = st.number_input(
1638
  "Max selections",
1639
- value=int(input_var.get("max", 1)),
1640
  min_value=1,
1641
- key=f"input_cat_max_{i}",
1642
  )
1643
 
1644
  # Close editor button
1645
- if st.button("Done Editing", key=f"done_input_{i}"):
1646
- st.session_state.show_variable_editor = None
1647
  st.rerun()
1648
 
1649
  st.markdown("---")
1650
 
1651
- st.divider()
 
 
1652
 
1653
- # Output Variables Section
1654
- with st.expander("Output Variables", expanded=True):
1655
- # Add output variable button
1656
- col1, col2 = st.columns([3, 1])
1657
- with col1:
1658
- new_output_name = st.text_input(
1659
- "New output variable name", key="new_output_name"
1660
  )
1661
- with col2:
1662
- if st.button("Add Output Variable"):
1663
- new_var = {
1664
- "name": (
1665
- new_output_name
1666
- if new_output_name
1667
- else f"new_output_{len(st.session_state.template_spec['output']) + 1}"
1668
- ),
1669
- "description": "New output variable",
1670
- "type": "string",
1671
- "min": 1,
1672
- "max": 100,
1673
- }
1674
- st.session_state.template_spec["output"].append(new_var)
1675
 
1676
- # Display output variables in a table-like format
1677
- st.subheader("Output Variables")
 
1678
 
1679
- # Create a container for the variables
1680
- for i, output_var in enumerate(st.session_state.template_spec["output"]):
1681
- col1, col2, col3 = st.columns([3, 1, 1])
 
 
1682
 
1683
- with col1:
1684
- st.markdown(
1685
- f"**{output_var['name']}** - {output_var['description']}"
1686
- )
1687
-
1688
- with col2:
1689
- # Button to edit this variable
1690
- if st.button("Edit", key=f"edit_output_{i}"):
1691
- st.session_state.show_output_editor = i
1692
-
1693
- with col3:
1694
- # Button to remove this variable
1695
- if st.button("Remove", key=f"remove_output_{i}"):
1696
- st.session_state.template_spec["output"].pop(i)
1697
- st.rerun()
1698
-
1699
- # Show editor if this variable is selected
1700
- if st.session_state.show_output_editor == i:
1701
- with st.container():
1702
- st.markdown("---")
1703
- st.markdown(f"##### Edit Output Variable: {output_var['name']}")
1704
-
1705
- # Name and description
1706
- output_var["name"] = st.text_input(
1707
- "Name", value=output_var["name"], key=f"output_name_{i}"
1708
- )
1709
- output_var["description"] = st.text_input(
1710
- "Description",
1711
- value=output_var["description"],
1712
- key=f"output_desc_{i}",
1713
- )
1714
-
1715
- # Type selection
1716
- var_type = st.selectbox(
1717
- "Type",
1718
- options=["string", "int", "float", "bool", "categorical"],
1719
- index=[
1720
- "string",
1721
- "int",
1722
- "float",
1723
- "bool",
1724
- "categorical",
1725
- ].index(output_var["type"]),
1726
- key=f"output_type_{i}",
1727
  )
1728
- output_var["type"] = var_type
1729
 
1730
- # Type-specific settings
1731
- if var_type in ["string", "int", "float"]:
1732
- col1, col2 = st.columns(2)
1733
- with col1:
1734
- output_var["min"] = st.number_input(
1735
- "Min",
1736
- value=int(output_var.get("min", 0)),
1737
- key=f"output_min_{i}",
1738
- )
1739
- with col2:
1740
- output_var["max"] = st.number_input(
1741
- "Max",
1742
- value=int(output_var.get("max", 100)),
1743
- key=f"output_max_{i}",
1744
- )
1745
-
1746
- if var_type == "categorical":
1747
- # Suggest options from KB button
1748
- if st.button(
1749
- "Suggest Options from KB", key=f"suggest_output_{i}"
1750
- ):
1751
- client = get_openai_client()
1752
- if not client:
1753
- st.error(
1754
- "Please provide an OpenAI API key to suggest options."
1755
- )
1756
- elif not st.session_state.knowledge_base:
1757
- st.warning(
1758
- "No knowledge base available. Please upload documents first."
1759
- )
1760
- else:
1761
- with st.spinner(
1762
- f"Suggesting options for {output_var['name']}..."
1763
- ):
1764
- suggestions = suggest_variable_values_from_kb(
1765
- output_var["name"],
1766
- "categorical",
1767
- st.session_state.knowledge_base,
1768
- client,
1769
- )
1770
- if suggestions and "options" in suggestions:
1771
- output_var["options"] = suggestions[
1772
- "options"
1773
- ]
1774
- st.success(
1775
- f"Found {len(suggestions['options'])} options"
1776
- )
1777
- else:
1778
- st.warning(
1779
- "Could not find suitable options in the knowledge base"
1780
- )
1781
-
1782
- # Options editor
1783
- options = output_var.get("options", [])
1784
- options_str = st.text_area(
1785
- "Options (one per line)",
1786
- value="\n".join(options),
1787
- key=f"output_options_{i}",
1788
  )
1789
- output_var["options"] = [
1790
- opt.strip()
1791
- for opt in options_str.split("\n")
1792
- if opt.strip()
1793
- ]
1794
-
1795
- # Min/max selections
1796
- col1, col2 = st.columns(2)
1797
- with col1:
1798
- output_var["min"] = st.number_input(
1799
- "Min selections",
1800
- value=int(output_var.get("min", 1)),
1801
- min_value=0,
1802
- key=f"output_cat_min_{i}",
1803
- )
1804
- with col2:
1805
- output_var["max"] = st.number_input(
1806
- "Max selections",
1807
- value=int(output_var.get("max", 1)),
1808
- min_value=1,
1809
- key=f"output_cat_max_{i}",
1810
- )
1811
-
1812
- # Close editor button
1813
- if st.button("Done Editing", key=f"done_output_{i}"):
1814
- st.session_state.show_output_editor = None
1815
- st.rerun()
1816
 
1817
- st.markdown("---")
 
 
 
 
 
 
 
 
 
 
 
1818
 
1819
- # Handle the lore/knowledge base as a special variable
1820
- prompt_template = st.session_state.template_spec["prompt"]
1821
- if "{lore}" in prompt_template:
1822
- with st.expander("Document Knowledge Base", expanded=True):
1823
- st.markdown("##### Document Knowledge Base")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1824
 
1825
- # Display info about the knowledge base
1826
- if st.session_state.knowledge_base:
1827
- st.success(
1828
- f"Using content from {len(st.session_state.uploaded_filenames) if 'uploaded_filenames' in st.session_state else 'uploaded'} documents as knowledge base"
 
 
1829
  )
1830
-
1831
- # Use a button to toggle knowledge base content view instead of an expander
1832
- if st.button(
1833
- "View/Hide Knowledge Base Content", key="toggle_kb_view"
1834
- ):
1835
- st.session_state.show_kb_content = not st.session_state.get(
1836
- "show_kb_content", False
1837
  )
1838
 
1839
- if st.session_state.get("show_kb_content", False):
 
1840
  st.text_area(
1841
- "Knowledge base content",
1842
- value=st.session_state.knowledge_base[:2000]
1843
- + (
1844
- "..."
1845
- if len(st.session_state.knowledge_base) > 2000
1846
- else ""
1847
- ),
1848
  height=200,
1849
  disabled=True,
1850
  )
1851
 
1852
- # Add option to edit if needed
1853
- use_edited_lore = st.checkbox("Edit knowledge base content")
1854
- if use_edited_lore:
1855
- st.session_state.user_inputs["lore"] = st.text_area(
1856
- "Edit knowledge base for this generation",
1857
- value=st.session_state.knowledge_base,
1858
- height=300,
1859
- )
1860
- else:
1861
- st.session_state.user_inputs["lore"] = (
1862
- st.session_state.knowledge_base
1863
- )
1864
- else:
1865
- st.warning(
1866
- "No documents uploaded. You can provide custom lore below."
1867
- )
1868
- st.session_state.user_inputs["lore"] = st.text_area(
1869
- "Enter background information or context",
1870
- placeholder="Enter custom lore or background information here...",
1871
- height=150,
1872
- )
1873
 
1874
- # Template JSON
1875
- with st.expander("Template JSON", expanded=False):
1876
- st.json(st.session_state.template_spec)
1877
-
1878
- # Download button
1879
- template_json = json.dumps(st.session_state.template_spec, indent=2)
1880
- st.download_button(
1881
- label="Download Template JSON",
1882
- data=template_json,
1883
- file_name="template_spec.json",
1884
- mime="application/json",
1885
- )
1886
 
1887
- # Generate Output Section
1888
- st.header("Generate Output")
 
 
1889
 
1890
- # Generate Output button
1891
- if st.button("Generate Output", key="generate_button"):
1892
- # Check if API key is provided
1893
- if not st.session_state.get("api_key"):
1894
- st.error(
1895
- "Please provide an OpenAI API key in the sidebar before generating output."
1896
- )
1897
- else:
1898
- # Fill the prompt template with user-provided values
1899
- filled_prompt = prompt_template
1900
- for var_name, var_value in st.session_state.user_inputs.items():
1901
- filled_prompt = filled_prompt.replace(
1902
- f"{{{var_name}}}", str(var_value)
1903
  )
1904
-
1905
- # Show the filled prompt
1906
- with st.expander("View populated prompt"):
1907
- st.text_area(
1908
- "Prompt sent to LLM",
1909
- value=filled_prompt,
1910
- height=200,
1911
- disabled=True,
1912
  )
 
 
 
1913
 
1914
- # Call LLM with the filled prompt
1915
- with st.spinner("Generating output..."):
1916
- model_selected = st.session_state.model
1917
- generated_output = call_llm(filled_prompt, model=model_selected)
1918
- st.session_state.generated_output = generated_output
1919
-
1920
- # Display generated output
1921
- if "generated_output" in st.session_state and st.session_state.generated_output:
1922
- st.header("Generated Output")
1923
-
1924
- # Check if the output is a dictionary (JSON)
1925
- if isinstance(st.session_state.generated_output, dict):
1926
- # Display as JSON
1927
- st.json(st.session_state.generated_output)
1928
-
1929
- # Option to save the output as JSON
1930
- output_json = json.dumps(st.session_state.generated_output, indent=2)
1931
- st.download_button(
1932
- label="Download Output (JSON)",
1933
- data=output_json,
1934
- file_name="generated_output.json",
1935
- mime="application/json",
1936
- )
1937
- else:
1938
- # Display as text
1939
- st.write(st.session_state.generated_output)
1940
-
1941
- # Option to save the output as text
1942
- st.download_button(
1943
- label="Download Output",
1944
- data=str(st.session_state.generated_output),
1945
- file_name="generated_output.txt",
1946
- mime="text/plain",
1947
- )
1948
  else:
1949
  st.info(
1950
  "No template has been generated yet. Go to the 'Setup' tab to create one."
@@ -2362,4 +2409,4 @@ with tab3:
2362
  else:
2363
  st.info(
2364
  "No template has been generated yet. Go to the 'Setup' tab to create one."
2365
- )
 
1290
  if "show_suggested_vars" not in st.session_state:
1291
  st.session_state.show_suggested_vars = False
1292
 
1293
+ # Create main layout with left (settings) and right (generation) columns
1294
+ left_col, right_col = st.columns([3, 2])
1295
+
1296
+ # LEFT COLUMN - Settings
1297
+ with left_col:
1298
+ # Basic template information
1299
+ with st.expander("Template Information", expanded=True):
1300
+ col1, col2 = st.columns(2)
1301
+ with col1:
1302
+ st.session_state.template_spec["name"] = st.text_input(
1303
+ "Template Name", value=st.session_state.template_spec["name"]
1304
+ )
1305
+ with col2:
1306
+ st.session_state.template_spec["version"] = st.text_input(
1307
+ "Version", value=st.session_state.template_spec["version"]
1308
+ )
1309
+
1310
+ st.session_state.template_spec["description"] = st.text_area(
1311
+ "Description",
1312
+ value=st.session_state.template_spec["description"],
1313
+ height=100,
1314
  )
1315
 
1316
+ # Prompt Template Section
1317
+ with st.expander("Prompt Template", expanded=False):
1318
+ st.info(
1319
+ "Use {variable_name} to refer to input variables in your template"
1320
+ )
1321
 
1322
+ # Add buttons for prompt management
1323
+ col1, col2 = st.columns([1, 1])
1324
+ with col1:
1325
+ rewrite_prompt = st.button("AI Rewrite Prompt")
1326
+ with col2:
1327
+ reroll_prompt = st.button("Reroll Prompt Variation")
1328
 
1329
+ # Handle prompt rewriting
1330
+ if rewrite_prompt or reroll_prompt:
1331
+ with st.spinner("Generating improved prompt template..."):
1332
+ improved_template = generate_improved_prompt_template(
1333
+ st.session_state.template_spec,
1334
+ st.session_state.knowledge_base,
1335
+ )
1336
+ # Only update if we got a valid result back
1337
+ if improved_template and len(improved_template) > 10:
1338
+ st.session_state.template_spec["prompt"] = improved_template
1339
+ st.success("Prompt template updated!")
1340
+
1341
+ # Display the prompt template
1342
+ prompt_template = st.text_area(
1343
+ "Edit the prompt template",
1344
+ value=st.session_state.template_spec["prompt"],
1345
+ height=200,
1346
+ )
1347
+ st.session_state.template_spec["prompt"] = prompt_template
1348
 
1349
+ # Knowledge Base Analysis Section
1350
+ if st.session_state.knowledge_base:
1351
+ with st.expander("Knowledge Base Analysis", expanded=False):
1352
+ st.info(
1353
+ "Analyze the knowledge base to suggest variables and values"
1354
  )
 
 
 
 
 
 
 
 
 
 
 
 
1355
 
1356
+ if st.button(
1357
+ "Analyze Knowledge Base for Variables",
1358
+ key="analyze_kb_button_input",
1359
+ ):
1360
+ client = get_openai_client()
1361
+ if not client:
1362
+ st.error(
1363
+ "Please provide an OpenAI API key to analyze the knowledge base."
 
 
 
 
 
 
 
 
 
 
1364
  )
1365
+ else:
1366
+ with st.spinner("Analyzing knowledge base..."):
1367
+ suggested_vars = analyze_knowledge_base(
1368
+ st.session_state.knowledge_base, client
 
1369
  )
1370
+ if suggested_vars:
1371
+ st.session_state.suggested_variables = (
1372
+ suggested_vars
1373
+ )
1374
+ st.session_state.show_suggested_vars = True
1375
+ st.success(
1376
+ f"Found {len(suggested_vars)} potential variables in the knowledge base"
1377
+ )
1378
+ else:
1379
+ st.warning(
1380
+ "Could not extract variables from the knowledge base"
1381
+ )
1382
+
1383
+ # Display suggested variables if they exist
1384
+ if (
1385
+ st.session_state.suggested_variables
1386
+ and st.session_state.show_suggested_vars
1387
+ ):
1388
+ st.subheader("Suggested Variables")
1389
+
1390
+ for i, var in enumerate(st.session_state.suggested_variables):
1391
+ # Generate a unique ID for this variable
1392
+ var_id = f"{var['name']}_{i}"
1393
+
1394
+ # Check if this variable has already been added
1395
+ if var_id in st.session_state.added_suggestions:
1396
+ continue
1397
+
1398
+ col1, col2 = st.columns([4, 1])
1399
+ with col1:
1400
+ st.markdown(
1401
+ f"**{var['name']}** ({var['type']}): {var['description']}"
1402
  )
1403
+ if var.get("options"):
1404
+ st.markdown(f"Options: {', '.join(var['options'])}")
1405
+ with col2:
1406
+ if st.button("Add", key=f"add_suggested_{var_id}"):
1407
+ # Add this variable to the template
1408
+ new_var = {
1409
+ "name": var["name"],
1410
+ "description": var["description"],
1411
+ "type": var["type"],
1412
+ }
1413
+ if var.get("options"):
1414
+ new_var["options"] = var["options"]
1415
+ if var["type"] in ["string", "int", "float"]:
1416
+ new_var["min"] = 1
1417
+ new_var["max"] = 100
1418
+
1419
+ # Add to input variables
1420
+ st.session_state.template_spec["input"].append(
1421
+ new_var
1422
+ )
1423
 
1424
+ # Mark this variable as added
1425
+ st.session_state.added_suggestions.add(var_id)
1426
+
1427
+ # Show success message
1428
+ st.success(
1429
+ f"Added {var['name']} to input variables!"
1430
+ )
1431
 
1432
+ # Input Variables Section
1433
+ with st.expander("Input Variables", expanded=True):
1434
+ # Add input variable button
1435
+ col1, col2 = st.columns([3, 1])
1436
+ with col1:
1437
+ new_input_name = st.text_input(
1438
+ "New input variable name", key="new_input_name"
1439
+ )
1440
+ with col2:
1441
+ if st.button("Add Input Variable"):
1442
+ new_var = {
1443
+ "name": (
1444
+ new_input_name
1445
+ if new_input_name
1446
+ else f"new_input_{len(st.session_state.template_spec['input']) + 1}"
1447
+ ),
1448
+ "description": "New input variable",
1449
+ "type": "string",
1450
+ "min": 1,
1451
+ "max": 100,
1452
+ }
1453
+ st.session_state.template_spec["input"].append(new_var)
1454
+
1455
+ # Display input variables with integrated input fields
1456
+ st.subheader("Input Variables")
1457
+
1458
+ # Create a container for the variables
1459
+ for i, input_var in enumerate(st.session_state.template_spec["input"]):
1460
+ var_name = input_var["name"]
1461
+ var_type = input_var["type"]
1462
+ var_desc = input_var["description"]
1463
+
1464
+ with st.container():
1465
+ # Variable header with description
1466
+ st.markdown(f"##### {var_name}\n###### {var_desc}")
1467
 
1468
+ # Create columns for the variable controls
1469
+ col1, col2, col3 = st.columns([3, 1, 1])
 
1470
 
 
1471
  with col1:
1472
+ # Create the appropriate input field based on variable type
1473
+ if var_type == "string":
1474
+ st.session_state.user_inputs[var_name] = st.text_input(
1475
+ f"Enter value for {var_name}", key=f"use_{var_name}"
1476
+ )
1477
+ elif var_type == "int":
1478
+ st.session_state.user_inputs[var_name] = (
1479
+ st.number_input(
1480
+ f"Enter value for {var_name}",
1481
+ min_value=input_var.get("min", None),
1482
+ max_value=input_var.get("max", None),
1483
+ step=1,
1484
+ key=f"use_{var_name}",
1485
+ )
1486
+ )
1487
+ elif var_type == "float":
1488
+ st.session_state.user_inputs[var_name] = (
1489
+ st.number_input(
1490
+ f"Enter value for {var_name}",
1491
+ min_value=float(input_var.get("min", 0)),
1492
+ max_value=float(input_var.get("max", 100)),
1493
+ key=f"use_{var_name}",
1494
+ )
1495
+ )
1496
+ elif var_type == "bool":
1497
+ st.session_state.user_inputs[var_name] = st.checkbox(
1498
+ f"Select value for {var_name}",
1499
+ key=f"use_{var_name}",
1500
+ )
1501
+ elif var_type == "categorical":
1502
+ options = input_var.get("options", [])
1503
+ min_selections = input_var.get("min", 1)
1504
+ max_selections = input_var.get("max", 1)
1505
+
1506
+ if options:
1507
+ if min_selections == 1 and max_selections == 1:
1508
+ # Single selection
1509
+ st.session_state.user_inputs[var_name] = (
1510
+ st.selectbox(
1511
+ f"Select value for {var_name}",
1512
+ options=options,
1513
+ key=f"use_{var_name}",
1514
+ )
1515
+ )
1516
+ else:
1517
+ # Multi-selection
1518
+ st.session_state.user_inputs[var_name] = (
1519
+ st.multiselect(
1520
+ f"Select {min_selections}-{max_selections} values for {var_name}",
1521
+ options=options,
1522
+ default=(
1523
+ options[:min_selections]
1524
+ if len(options) >= min_selections
1525
+ else options
1526
+ ),
1527
+ key=f"use_{var_name}",
1528
+ )
1529
+ )
1530
+ else:
1531
+ st.warning(f"No options defined for {var_name}")
1532
+
1533
  with col2:
1534
+ # Button to edit this variable
1535
+ if st.button("Edit Settings", key=f"edit_input_{i}"):
1536
+ st.session_state.show_variable_editor = i
1537
+
1538
+ with col3:
1539
+ # Button to remove this variable
1540
+ if st.button("Remove", key=f"remove_input_{i}"):
1541
+ st.session_state.template_spec["input"].pop(i)
1542
+ st.rerun()
 
 
 
1543
 
1544
+ # Show editor if this variable is selected
1545
+ if st.session_state.show_variable_editor == i:
1546
+ with st.container():
1547
+ st.markdown("---")
1548
+ st.markdown(
1549
+ f"##### Variable Settings: {input_var['name']}"
1550
+ )
1551
 
1552
+ # Name and description
1553
+ input_var["name"] = st.text_input(
1554
+ "Name",
1555
+ value=input_var["name"],
1556
+ key=f"input_name_{i}",
1557
+ )
1558
+ input_var["description"] = st.text_input(
1559
+ "Description",
1560
+ value=input_var["description"],
1561
+ key=f"input_desc_{i}",
1562
+ )
1563
 
1564
+ # Type selection
1565
+ var_type = st.selectbox(
1566
+ "Type",
1567
+ options=[
1568
+ "string",
1569
+ "int",
1570
+ "float",
1571
+ "bool",
1572
+ "categorical",
1573
+ ],
1574
+ index=[
1575
+ "string",
1576
+ "int",
1577
+ "float",
1578
+ "bool",
1579
+ "categorical",
1580
+ ].index(input_var["type"]),
1581
+ key=f"input_type_{i}",
1582
+ )
1583
+ input_var["type"] = var_type
1584
+
1585
+ # Type-specific settings
1586
+ if var_type in ["string", "int", "float"]:
1587
+ col1, col2 = st.columns(2)
1588
+ with col1:
1589
+ input_var["min"] = st.number_input(
1590
+ "Min",
1591
+ value=int(input_var.get("min", 0)),
1592
+ key=f"input_min_{i}",
1593
+ )
1594
+ with col2:
1595
+ input_var["max"] = st.number_input(
1596
+ "Max",
1597
+ value=int(input_var.get("max", 100)),
1598
+ key=f"input_max_{i}",
1599
+ )
1600
 
1601
+ if var_type == "categorical":
1602
+ # Suggest options from KB button
1603
+ if st.button(
1604
+ "Suggest Options from KB",
1605
+ key=f"suggest_input_{i}",
1606
+ ):
1607
+ client = get_openai_client()
1608
+ if not client:
1609
+ st.error(
1610
+ "Please provide an OpenAI API key to suggest options."
1611
+ )
1612
+ elif not st.session_state.knowledge_base:
1613
+ st.warning(
1614
+ "No knowledge base available. Please upload documents first."
1615
+ )
1616
+ else:
1617
+ with st.spinner(
1618
+ f"Suggesting options for {input_var['name']}..."
1619
+ ):
1620
+ suggestions = (
1621
+ suggest_variable_values_from_kb(
1622
+ input_var["name"],
1623
+ "categorical",
1624
+ st.session_state.knowledge_base,
1625
+ client,
1626
+ )
1627
+ )
1628
+ if (
1629
+ suggestions
1630
+ and "options" in suggestions
1631
+ ):
1632
+ input_var["options"] = suggestions[
1633
+ "options"
1634
+ ]
1635
+ st.success(
1636
+ f"Found {len(suggestions['options'])} options"
1637
+ )
1638
+ else:
1639
+ st.warning(
1640
+ "Could not find suitable options in the knowledge base"
1641
+ )
1642
+
1643
+ # Options editor
1644
+ options = input_var.get("options", [])
1645
+ options_str = st.text_area(
1646
+ "Options (one per line)",
1647
+ value="\n".join(options),
1648
+ key=f"input_options_{i}",
1649
+ )
1650
+ input_var["options"] = [
1651
+ opt.strip()
1652
+ for opt in options_str.split("\n")
1653
+ if opt.strip()
1654
+ ]
1655
+
1656
+ # Min/max selections
1657
+ col1, col2 = st.columns(2)
1658
+ with col1:
1659
+ input_var["min"] = st.number_input(
1660
+ "Min selections",
1661
+ value=int(input_var.get("min", 1)),
1662
+ min_value=0,
1663
+ key=f"input_cat_min_{i}",
1664
+ )
1665
+ with col2:
1666
+ input_var["max"] = st.number_input(
1667
+ "Max selections",
1668
+ value=int(input_var.get("max", 1)),
1669
+ min_value=1,
1670
+ key=f"input_cat_max_{i}",
1671
+ )
1672
 
1673
+ # Close editor button
1674
+ if st.button("Done Editing", key=f"done_input_{i}"):
1675
+ st.session_state.show_variable_editor = None
1676
+ st.rerun()
1677
 
1678
+ st.markdown("---")
 
 
 
 
1679
 
1680
+ st.divider()
 
 
1681
 
1682
+ # Output Variables Section
1683
+ with st.expander("Output Variables", expanded=True):
1684
+ # Add output variable button
1685
+ col1, col2 = st.columns([3, 1])
1686
+ with col1:
1687
+ new_output_name = st.text_input(
1688
+ "New output variable name", key="new_output_name"
1689
+ )
1690
+ with col2:
1691
+ if st.button("Add Output Variable"):
1692
+ new_var = {
1693
+ "name": (
1694
+ new_output_name
1695
+ if new_output_name
1696
+ else f"new_output_{len(st.session_state.template_spec['output']) + 1}"
1697
+ ),
1698
+ "description": "New output variable",
1699
+ "type": "string",
1700
+ "min": 1,
1701
+ "max": 100,
1702
+ }
1703
+ st.session_state.template_spec["output"].append(new_var)
1704
+
1705
+ # Display output variables in a table-like format
1706
+ st.subheader("Output Variables")
1707
+
1708
+ # Create a container for the variables
1709
+ for i, output_var in enumerate(
1710
+ st.session_state.template_spec["output"]
1711
+ ):
1712
  col1, col2, col3 = st.columns([3, 1, 1])
1713
 
1714
  with col1:
1715
+ st.markdown(
1716
+ f"**{output_var['name']}** - {output_var['description']}"
1717
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1718
 
1719
  with col2:
1720
  # Button to edit this variable
1721
+ if st.button("Edit", key=f"edit_output_{i}"):
1722
+ st.session_state.show_output_editor = i
1723
 
1724
  with col3:
1725
  # Button to remove this variable
1726
+ if st.button("Remove", key=f"remove_output_{i}"):
1727
+ st.session_state.template_spec["output"].pop(i)
1728
  st.rerun()
1729
 
1730
  # Show editor if this variable is selected
1731
+ if st.session_state.show_output_editor == i:
1732
  with st.container():
1733
  st.markdown("---")
1734
+ st.markdown(
1735
+ f"##### Edit Output Variable: {output_var['name']}"
1736
+ )
1737
 
1738
  # Name and description
1739
+ output_var["name"] = st.text_input(
1740
+ "Name", value=output_var["name"], key=f"output_name_{i}"
1741
  )
1742
+ output_var["description"] = st.text_input(
1743
  "Description",
1744
+ value=output_var["description"],
1745
+ key=f"output_desc_{i}",
1746
  )
1747
 
1748
  # Type selection
 
1761
  "float",
1762
  "bool",
1763
  "categorical",
1764
+ ].index(output_var["type"]),
1765
+ key=f"output_type_{i}",
1766
  )
1767
+ output_var["type"] = var_type
1768
 
1769
  # Type-specific settings
1770
  if var_type in ["string", "int", "float"]:
1771
  col1, col2 = st.columns(2)
1772
  with col1:
1773
+ output_var["min"] = st.number_input(
1774
  "Min",
1775
+ value=int(output_var.get("min", 0)),
1776
+ key=f"output_min_{i}",
1777
  )
1778
  with col2:
1779
+ output_var["max"] = st.number_input(
1780
  "Max",
1781
+ value=int(output_var.get("max", 100)),
1782
+ key=f"output_max_{i}",
1783
  )
1784
 
1785
  if var_type == "categorical":
1786
  # Suggest options from KB button
1787
  if st.button(
1788
+ "Suggest Options from KB", key=f"suggest_output_{i}"
1789
  ):
1790
  client = get_openai_client()
1791
  if not client:
 
1798
  )
1799
  else:
1800
  with st.spinner(
1801
+ f"Suggesting options for {output_var['name']}..."
1802
  ):
1803
  suggestions = (
1804
  suggest_variable_values_from_kb(
1805
+ output_var["name"],
1806
  "categorical",
1807
  st.session_state.knowledge_base,
1808
  client,
1809
  )
1810
  )
1811
  if suggestions and "options" in suggestions:
1812
+ output_var["options"] = suggestions[
1813
  "options"
1814
  ]
1815
  st.success(
 
1821
  )
1822
 
1823
  # Options editor
1824
+ options = output_var.get("options", [])
1825
  options_str = st.text_area(
1826
  "Options (one per line)",
1827
  value="\n".join(options),
1828
+ key=f"output_options_{i}",
1829
  )
1830
+ output_var["options"] = [
1831
  opt.strip()
1832
  for opt in options_str.split("\n")
1833
  if opt.strip()
 
1836
  # Min/max selections
1837
  col1, col2 = st.columns(2)
1838
  with col1:
1839
+ output_var["min"] = st.number_input(
1840
  "Min selections",
1841
+ value=int(output_var.get("min", 1)),
1842
  min_value=0,
1843
+ key=f"output_cat_min_{i}",
1844
  )
1845
  with col2:
1846
+ output_var["max"] = st.number_input(
1847
  "Max selections",
1848
+ value=int(output_var.get("max", 1)),
1849
  min_value=1,
1850
+ key=f"output_cat_max_{i}",
1851
  )
1852
 
1853
  # Close editor button
1854
+ if st.button("Done Editing", key=f"done_output_{i}"):
1855
+ st.session_state.show_output_editor = None
1856
  st.rerun()
1857
 
1858
  st.markdown("---")
1859
 
1860
+ # Template JSON
1861
+ with st.expander("Template JSON", expanded=False):
1862
+ st.json(st.session_state.template_spec)
1863
 
1864
+ # Download button
1865
+ template_json = json.dumps(st.session_state.template_spec, indent=2)
1866
+ st.download_button(
1867
+ label="Download Template JSON",
1868
+ data=template_json,
1869
+ file_name="template_spec.json",
1870
+ mime="application/json",
1871
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1872
 
1873
+ # RIGHT COLUMN - Generation
1874
+ with right_col:
1875
+ st.header("Generation")
1876
 
1877
+ # Handle the lore/knowledge base as a special variable
1878
+ prompt_template = st.session_state.template_spec["prompt"]
1879
+ if "{lore}" in prompt_template:
1880
+ with st.expander("Document Knowledge Base", expanded=False):
1881
+ st.markdown("##### Document Knowledge Base")
1882
 
1883
+ # Display info about the knowledge base
1884
+ if st.session_state.knowledge_base:
1885
+ st.success(
1886
+ f"Using content from {len(st.session_state.uploaded_filenames) if 'uploaded_filenames' in st.session_state else 'uploaded'} documents as knowledge base"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1887
  )
 
1888
 
1889
+ # Use a button to toggle knowledge base content view instead of an expander
1890
+ if st.button(
1891
+ "View/Hide Knowledge Base Content", key="toggle_kb_view"
1892
+ ):
1893
+ st.session_state.show_kb_content = not st.session_state.get(
1894
+ "show_kb_content", False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1895
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1896
 
1897
+ if st.session_state.get("show_kb_content", False):
1898
+ st.text_area(
1899
+ "Knowledge base content",
1900
+ value=st.session_state.knowledge_base[:2000]
1901
+ + (
1902
+ "..."
1903
+ if len(st.session_state.knowledge_base) > 2000
1904
+ else ""
1905
+ ),
1906
+ height=200,
1907
+ disabled=True,
1908
+ )
1909
 
1910
+ # Add option to edit if needed
1911
+ use_edited_lore = st.checkbox("Edit knowledge base content")
1912
+ if use_edited_lore:
1913
+ st.session_state.user_inputs["lore"] = st.text_area(
1914
+ "Edit knowledge base for this generation",
1915
+ value=st.session_state.knowledge_base,
1916
+ height=300,
1917
+ )
1918
+ else:
1919
+ st.session_state.user_inputs["lore"] = (
1920
+ st.session_state.knowledge_base
1921
+ )
1922
+ else:
1923
+ st.warning(
1924
+ "No documents uploaded. You can provide custom lore below."
1925
+ )
1926
+ st.session_state.user_inputs["lore"] = st.text_area(
1927
+ "Enter background information or context",
1928
+ placeholder="Enter custom lore or background information here...",
1929
+ height=150,
1930
+ )
1931
 
1932
+ # Generate Output button
1933
+ if st.button("Generate Output", key="generate_button"):
1934
+ # Check if API key is provided
1935
+ if not st.session_state.get("api_key"):
1936
+ st.error(
1937
+ "Please provide an OpenAI API key in the sidebar before generating output."
1938
  )
1939
+ else:
1940
+ # Fill the prompt template with user-provided values
1941
+ filled_prompt = prompt_template
1942
+ for var_name, var_value in st.session_state.user_inputs.items():
1943
+ filled_prompt = filled_prompt.replace(
1944
+ f"{{{var_name}}}", str(var_value)
 
1945
  )
1946
 
1947
+ # Show the filled prompt
1948
+ with st.expander("View populated prompt"):
1949
  st.text_area(
1950
+ "Prompt sent to LLM",
1951
+ value=filled_prompt,
 
 
 
 
 
1952
  height=200,
1953
  disabled=True,
1954
  )
1955
 
1956
+ # Call LLM with the filled prompt
1957
+ with st.spinner("Generating output..."):
1958
+ model_selected = st.session_state.model
1959
+ generated_output = call_llm(filled_prompt, model=model_selected)
1960
+ st.session_state.generated_output = generated_output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1961
 
1962
+ # Display generated output
1963
+ if (
1964
+ "generated_output" in st.session_state
1965
+ and st.session_state.generated_output
1966
+ ):
1967
+ st.header("Generated Output")
 
 
 
 
 
 
1968
 
1969
+ # Check if the output is a dictionary (JSON)
1970
+ if isinstance(st.session_state.generated_output, dict):
1971
+ # Display as JSON
1972
+ st.json(st.session_state.generated_output)
1973
 
1974
+ # Option to save the output as JSON
1975
+ output_json = json.dumps(
1976
+ st.session_state.generated_output, indent=2
 
 
 
 
 
 
 
 
 
 
1977
  )
1978
+ st.download_button(
1979
+ label="Download Output (JSON)",
1980
+ data=output_json,
1981
+ file_name="generated_output.json",
1982
+ mime="application/json",
 
 
 
1983
  )
1984
+ else:
1985
+ # Display as text
1986
+ st.write(st.session_state.generated_output)
1987
 
1988
+ # Option to save the output as text
1989
+ st.download_button(
1990
+ label="Download Output",
1991
+ data=str(st.session_state.generated_output),
1992
+ file_name="generated_output.txt",
1993
+ mime="text/plain",
1994
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1995
  else:
1996
  st.info(
1997
  "No template has been generated yet. Go to the 'Setup' tab to create one."
 
2409
  else:
2410
  st.info(
2411
  "No template has been generated yet. Go to the 'Setup' tab to create one."
2412
+ )