Spaces:
Runtime error
Runtime error
Vaishnav14220
commited on
Commit
Β·
7ac4139
1
Parent(s):
d474c53
Enhance Reaction SVG tab: AI processing happens FIRST before rendering - DeepSeek analyzes and completes reactions before RDKit SVG generation, ensuring all reactions are properly enhanced/validated/completed
Browse files
app.py
CHANGED
|
@@ -222,8 +222,8 @@ def fetch_specific_db(db_name, formula):
|
|
| 222 |
|
| 223 |
# Generic table extraction
|
| 224 |
tables = soup.find_all('table')
|
| 225 |
-
|
| 226 |
-
|
| 227 |
df = pd.read_html(StringIO(str(tables[0])))[0]
|
| 228 |
|
| 229 |
# Fallback: Links for spectra/structures
|
|
@@ -900,7 +900,7 @@ def render_reaction_svg(reaction_text: str, api_key: str = "", auto_complete: bo
|
|
| 900 |
|
| 901 |
# Check if it's already SMILES format (contains >>)
|
| 902 |
if ">>" in reaction_text:
|
| 903 |
-
|
| 904 |
if svg:
|
| 905 |
status = "β
Reaction rendered successfully from SMILES."
|
| 906 |
return svg, status
|
|
@@ -917,7 +917,7 @@ def render_reaction_svg(reaction_text: str, api_key: str = "", auto_complete: bo
|
|
| 917 |
svg = _render_reaction_from_nist(completed_reaction)
|
| 918 |
if svg:
|
| 919 |
status = f"β
Reaction completed and rendered using DeepSeek AI.\nOriginal: {reaction_text}\nCompleted: {completed_reaction}"
|
| 920 |
-
|
| 921 |
else:
|
| 922 |
return "", f"π¨ DeepSeek completed reaction but rendering failed: {completed_reaction}"
|
| 923 |
else:
|
|
@@ -1065,13 +1065,13 @@ def fetch_detail(selected_url: str, manual_url: str, auto_fetch_thermo: bool = T
|
|
| 1065 |
return markdown, table, None, "", {}, ""
|
| 1066 |
|
| 1067 |
plot_fig = _build_dataset_plot(detail)
|
| 1068 |
-
|
| 1069 |
# Try to render the reaction title as SVG
|
| 1070 |
reaction_svg = ""
|
| 1071 |
if detail.title:
|
| 1072 |
title = detail.title.strip()
|
| 1073 |
smiles_attempt = None
|
| 1074 |
-
|
| 1075 |
# Try different reaction format conversions
|
| 1076 |
if " β " in title:
|
| 1077 |
# Format: "A + B β C"
|
|
@@ -1090,12 +1090,12 @@ def fetch_detail(selected_url: str, manual_url: str, auto_fetch_thermo: bool = T
|
|
| 1090 |
reactants = parts[0].replace(" + ", ".").strip()
|
| 1091 |
products = parts[1].replace(" + ", ".").strip()
|
| 1092 |
smiles_attempt = f"{reactants}>>{products}"
|
| 1093 |
-
|
| 1094 |
if smiles_attempt:
|
| 1095 |
svg = _render_smiles_to_svg(smiles_attempt)
|
| 1096 |
if svg:
|
| 1097 |
reaction_svg = svg
|
| 1098 |
-
|
| 1099 |
# Auto-fetch thermodynamic data for compounds in the reaction
|
| 1100 |
thermo_data = {}
|
| 1101 |
thermo_summary = ""
|
|
@@ -1265,24 +1265,24 @@ def build_interface() -> gr.Blocks:
|
|
| 1265 |
value=True,
|
| 1266 |
info="Automatically fetch thermodynamic data for searched compounds"
|
| 1267 |
)
|
| 1268 |
-
|
| 1269 |
-
|
| 1270 |
-
|
| 1271 |
-
|
| 1272 |
-
|
| 1273 |
-
|
| 1274 |
-
|
| 1275 |
-
|
| 1276 |
|
| 1277 |
search_button = gr.Button("π Search NIST", variant="primary")
|
| 1278 |
-
|
| 1279 |
|
| 1280 |
-
|
| 1281 |
-
|
| 1282 |
-
|
| 1283 |
-
|
| 1284 |
-
|
| 1285 |
-
|
| 1286 |
|
| 1287 |
# Search results thermodynamic data
|
| 1288 |
search_thermo_accordion = gr.Accordion(label="π¬ Search Query Thermodynamic Data", open=False)
|
|
@@ -1293,15 +1293,15 @@ def build_interface() -> gr.Blocks:
|
|
| 1293 |
with gr.TabItem("Reaction Detail"):
|
| 1294 |
with gr.Row():
|
| 1295 |
with gr.Column(scale=2):
|
| 1296 |
-
|
| 1297 |
-
|
| 1298 |
-
|
| 1299 |
-
|
| 1300 |
-
|
| 1301 |
-
|
| 1302 |
-
|
| 1303 |
-
|
| 1304 |
-
|
| 1305 |
with gr.Column(scale=1):
|
| 1306 |
auto_fetch_thermo = gr.Checkbox(
|
| 1307 |
label="π¬ Auto-fetch thermodynamics",
|
|
@@ -1315,31 +1315,31 @@ def build_interface() -> gr.Blocks:
|
|
| 1315 |
)
|
| 1316 |
|
| 1317 |
detail_button = gr.Button("Fetch Reaction Detail", variant="primary")
|
| 1318 |
-
|
| 1319 |
-
|
| 1320 |
-
|
| 1321 |
-
|
| 1322 |
with gr.Row():
|
| 1323 |
-
|
| 1324 |
with gr.Column():
|
| 1325 |
gr.Markdown("### Kinetics Data")
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
-
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
|
| 1332 |
-
|
| 1333 |
# Arrhenius plot
|
| 1334 |
with gr.Column():
|
| 1335 |
gr.Markdown("### Arrhenius Plot")
|
| 1336 |
reaction_plot = gr.Plot()
|
| 1337 |
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
# Auto-fetched thermodynamic data
|
| 1344 |
thermo_summary = gr.Markdown()
|
| 1345 |
thermo_accordion = gr.Accordion(label="π¬ Thermodynamic Data", open=False)
|
|
@@ -1350,13 +1350,18 @@ def build_interface() -> gr.Blocks:
|
|
| 1350 |
# Tab 3: Reaction SVG (Enhanced with NIST reactions and AI completion)
|
| 1351 |
with gr.TabItem("Reaction SVG"):
|
| 1352 |
gr.Markdown(
|
| 1353 |
-
"π¨ **Render chemical reactions as SVG using RDKit + AI
|
| 1354 |
-
"Choose from NIST database reactions, enter custom reactions, or let AI complete
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1355 |
"**Features:**\n"
|
| 1356 |
"- π§ͺ 200+ NIST database reactions\n"
|
| 1357 |
-
"- π€ AI-powered reaction
|
| 1358 |
-
"- π¬ Multiple input formats (NIST, SMILES, SMARTS)\n"
|
| 1359 |
-
"- β‘ Automatic format detection and conversion"
|
|
|
|
| 1360 |
)
|
| 1361 |
|
| 1362 |
# API Key Configuration
|
|
@@ -1367,7 +1372,7 @@ def build_interface() -> gr.Blocks:
|
|
| 1367 |
type="password",
|
| 1368 |
info="Get your API key from https://platform.deepseek.com/"
|
| 1369 |
)
|
| 1370 |
-
|
| 1371 |
"**How to get API key:**\n"
|
| 1372 |
"1. Visit https://platform.deepseek.com/\n"
|
| 1373 |
"2. Sign up/Login to your account\n"
|
|
@@ -1379,8 +1384,8 @@ def build_interface() -> gr.Blocks:
|
|
| 1379 |
# NIST reactions dropdown
|
| 1380 |
nist_reactions = _fetch_all_nist_reactions(limit=200)
|
| 1381 |
nist_reaction_options = [("", "")] + nist_reactions if nist_reactions else []
|
| 1382 |
-
|
| 1383 |
-
|
| 1384 |
with gr.Column():
|
| 1385 |
nist_reaction_dropdown = gr.Dropdown(
|
| 1386 |
label="π§ͺ NIST Database Reactions",
|
|
@@ -1389,8 +1394,8 @@ def build_interface() -> gr.Blocks:
|
|
| 1389 |
interactive=True,
|
| 1390 |
info=f"Select from {len(nist_reactions)} reactions in NIST kinetics database"
|
| 1391 |
)
|
| 1392 |
-
|
| 1393 |
-
|
| 1394 |
label="Custom Reaction Input",
|
| 1395 |
placeholder="Enter reaction in any format:\nNIST: CH4 + O2 β CO2 + H2O\nSMILES: CH4.O2>>CO2.H2O\nPartial: CH4 + O2 β (AI will complete)",
|
| 1396 |
lines=4,
|
|
@@ -1406,17 +1411,20 @@ def build_interface() -> gr.Blocks:
|
|
| 1406 |
)
|
| 1407 |
|
| 1408 |
ai_options = gr.CheckboxGroup(
|
| 1409 |
-
label="π€ AI Enhancement",
|
| 1410 |
-
choices=["Enable AI
|
| 1411 |
-
value=["Enable AI
|
| 1412 |
-
info="
|
| 1413 |
)
|
| 1414 |
|
| 1415 |
# Buttons
|
| 1416 |
with gr.Row():
|
| 1417 |
-
render_auto_btn = gr.Button("π
|
| 1418 |
-
|
| 1419 |
-
|
|
|
|
|
|
|
|
|
|
| 1420 |
clear_btn = gr.Button("ποΈ Clear", variant="stop")
|
| 1421 |
|
| 1422 |
# Output
|
|
@@ -1428,14 +1436,14 @@ def build_interface() -> gr.Blocks:
|
|
| 1428 |
def populate_from_nist_dropdown(selected_label):
|
| 1429 |
if selected_label and selected_label in nist_dict:
|
| 1430 |
return nist_dict[selected_label]
|
| 1431 |
-
|
| 1432 |
-
|
| 1433 |
nist_reaction_dropdown.change(
|
| 1434 |
fn=populate_from_nist_dropdown,
|
| 1435 |
inputs=nist_reaction_dropdown,
|
| 1436 |
-
|
| 1437 |
-
|
| 1438 |
-
|
| 1439 |
# Smart auto-render function
|
| 1440 |
def render_auto_reaction(reaction_text, api_key, ai_options, render_mode):
|
| 1441 |
if not reaction_text:
|
|
@@ -1444,35 +1452,52 @@ def build_interface() -> gr.Blocks:
|
|
| 1444 |
status_prefix = ""
|
| 1445 |
final_reaction = reaction_text
|
| 1446 |
|
| 1447 |
-
#
|
| 1448 |
-
if "Enable AI
|
| 1449 |
-
|
| 1450 |
-
|
| 1451 |
-
|
| 1452 |
-
|
| 1453 |
-
|
| 1454 |
-
|
| 1455 |
-
|
| 1456 |
-
|
| 1457 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1458 |
svg = _render_smiles_to_svg(final_reaction)
|
| 1459 |
render_type = "SMILES/SMARTS"
|
| 1460 |
-
elif render_mode == "Force NIST format"
|
| 1461 |
svg = _render_reaction_from_nist(final_reaction)
|
| 1462 |
render_type = "NIST format"
|
| 1463 |
-
else:
|
| 1464 |
-
#
|
| 1465 |
-
|
| 1466 |
-
if not svg:
|
| 1467 |
svg = _render_smiles_to_svg(final_reaction)
|
| 1468 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1469 |
|
| 1470 |
if svg:
|
| 1471 |
quality_note = " (High quality)" if "High quality rendering" in (ai_options or []) else ""
|
| 1472 |
-
|
|
|
|
| 1473 |
return svg, status
|
| 1474 |
else:
|
| 1475 |
-
return "", f"{status_prefix}β Could not render reaction.
|
| 1476 |
|
| 1477 |
# Legacy render functions (kept for compatibility)
|
| 1478 |
def render_nist_reaction(reaction_text, options):
|
|
@@ -1482,7 +1507,7 @@ def build_interface() -> gr.Blocks:
|
|
| 1482 |
svg = _render_reaction_from_nist(reaction_text)
|
| 1483 |
if svg:
|
| 1484 |
status = f"β
Successfully rendered NIST reaction: {reaction_text[:100]}..."
|
| 1485 |
-
if "High quality" in (options or []):
|
| 1486 |
status += " (High quality mode)"
|
| 1487 |
return svg, status
|
| 1488 |
else:
|
|
@@ -1495,7 +1520,7 @@ def build_interface() -> gr.Blocks:
|
|
| 1495 |
svg = _render_smiles_to_svg(reaction_text)
|
| 1496 |
if svg:
|
| 1497 |
status = f"β
Successfully rendered SMILES reaction: {reaction_text[:100]}..."
|
| 1498 |
-
if "High quality" in (options or []):
|
| 1499 |
status += " (High quality mode)"
|
| 1500 |
return svg, status
|
| 1501 |
else:
|
|
@@ -1509,8 +1534,8 @@ def build_interface() -> gr.Blocks:
|
|
| 1509 |
render_auto_btn.click(
|
| 1510 |
fn=render_auto_reaction,
|
| 1511 |
inputs=[reaction_input, deepseek_api_key, ai_options, render_mode],
|
| 1512 |
-
|
| 1513 |
-
|
| 1514 |
|
| 1515 |
render_nist_btn.click(
|
| 1516 |
fn=render_nist_reaction,
|
|
@@ -1532,8 +1557,8 @@ def build_interface() -> gr.Blocks:
|
|
| 1532 |
|
| 1533 |
# Tab 4: Kinetics Plotter
|
| 1534 |
with gr.TabItem("Kinetics Plotter"):
|
| 1535 |
-
|
| 1536 |
-
|
| 1537 |
A_input = gr.Number(value=1.3e-9, label="A (cmΒ³/moleculeΒ·s)")
|
| 1538 |
n_input = gr.Number(value=-0.495, label="n (power)")
|
| 1539 |
Ea_input = gr.Number(value=1150, label="Ea (J/mol)")
|
|
@@ -1571,8 +1596,8 @@ def build_interface() -> gr.Blocks:
|
|
| 1571 |
|
| 1572 |
fetch_btn = gr.Button("Fetch Data")
|
| 1573 |
|
| 1574 |
-
|
| 1575 |
-
|
| 1576 |
output_df = gr.Dataframe(label="Tabular Data")
|
| 1577 |
output_plot = gr.Plot(visible=False, label="Spectrum Preview") # For IR/UV/THz later
|
| 1578 |
|
|
@@ -1613,7 +1638,7 @@ def build_interface() -> gr.Blocks:
|
|
| 1613 |
["CH3"], ["benzene"], ["C6H5OH"]
|
| 1614 |
],
|
| 1615 |
inputs=[formula_input] # Note: This is placeholder; make per-tab if needed
|
| 1616 |
-
|
| 1617 |
|
| 1618 |
return demo
|
| 1619 |
|
|
|
|
| 222 |
|
| 223 |
# Generic table extraction
|
| 224 |
tables = soup.find_all('table')
|
| 225 |
+
df = None
|
| 226 |
+
if tables:
|
| 227 |
df = pd.read_html(StringIO(str(tables[0])))[0]
|
| 228 |
|
| 229 |
# Fallback: Links for spectra/structures
|
|
|
|
| 900 |
|
| 901 |
# Check if it's already SMILES format (contains >>)
|
| 902 |
if ">>" in reaction_text:
|
| 903 |
+
svg = _render_smiles_to_svg(reaction_text)
|
| 904 |
if svg:
|
| 905 |
status = "β
Reaction rendered successfully from SMILES."
|
| 906 |
return svg, status
|
|
|
|
| 917 |
svg = _render_reaction_from_nist(completed_reaction)
|
| 918 |
if svg:
|
| 919 |
status = f"β
Reaction completed and rendered using DeepSeek AI.\nOriginal: {reaction_text}\nCompleted: {completed_reaction}"
|
| 920 |
+
return svg, status
|
| 921 |
else:
|
| 922 |
return "", f"π¨ DeepSeek completed reaction but rendering failed: {completed_reaction}"
|
| 923 |
else:
|
|
|
|
| 1065 |
return markdown, table, None, "", {}, ""
|
| 1066 |
|
| 1067 |
plot_fig = _build_dataset_plot(detail)
|
| 1068 |
+
|
| 1069 |
# Try to render the reaction title as SVG
|
| 1070 |
reaction_svg = ""
|
| 1071 |
if detail.title:
|
| 1072 |
title = detail.title.strip()
|
| 1073 |
smiles_attempt = None
|
| 1074 |
+
|
| 1075 |
# Try different reaction format conversions
|
| 1076 |
if " β " in title:
|
| 1077 |
# Format: "A + B β C"
|
|
|
|
| 1090 |
reactants = parts[0].replace(" + ", ".").strip()
|
| 1091 |
products = parts[1].replace(" + ", ".").strip()
|
| 1092 |
smiles_attempt = f"{reactants}>>{products}"
|
| 1093 |
+
|
| 1094 |
if smiles_attempt:
|
| 1095 |
svg = _render_smiles_to_svg(smiles_attempt)
|
| 1096 |
if svg:
|
| 1097 |
reaction_svg = svg
|
| 1098 |
+
|
| 1099 |
# Auto-fetch thermodynamic data for compounds in the reaction
|
| 1100 |
thermo_data = {}
|
| 1101 |
thermo_summary = ""
|
|
|
|
| 1265 |
value=True,
|
| 1266 |
info="Automatically fetch thermodynamic data for searched compounds"
|
| 1267 |
)
|
| 1268 |
+
|
| 1269 |
+
with gr.Row():
|
| 1270 |
+
decomp = gr.Checkbox(label="Only decomposition reactions", value=False)
|
| 1271 |
+
category = gr.Dropdown(label="Result type filter", choices=CATEGORY_CHOICES, value=str(Category.any.value))
|
| 1272 |
+
units = gr.Textbox(
|
| 1273 |
+
label="Optional Units token",
|
| 1274 |
+
placeholder="Leave blank to use NIST account defaults",
|
| 1275 |
+
)
|
| 1276 |
|
| 1277 |
search_button = gr.Button("π Search NIST", variant="primary")
|
| 1278 |
+
search_status = gr.Markdown()
|
| 1279 |
|
| 1280 |
+
result_table = gr.Dataframe(
|
| 1281 |
+
headers=["#", "Records", "Reaction", "Detail URL"],
|
| 1282 |
+
datatype=["number", "number", "str", "str"],
|
| 1283 |
+
interactive=False,
|
| 1284 |
+
wrap=True,
|
| 1285 |
+
)
|
| 1286 |
|
| 1287 |
# Search results thermodynamic data
|
| 1288 |
search_thermo_accordion = gr.Accordion(label="π¬ Search Query Thermodynamic Data", open=False)
|
|
|
|
| 1293 |
with gr.TabItem("Reaction Detail"):
|
| 1294 |
with gr.Row():
|
| 1295 |
with gr.Column(scale=2):
|
| 1296 |
+
selection = gr.Dropdown(
|
| 1297 |
+
label="Select a reaction from the latest search",
|
| 1298 |
+
choices=[],
|
| 1299 |
+
interactive=False,
|
| 1300 |
+
)
|
| 1301 |
+
manual_url = gr.Textbox(
|
| 1302 |
+
label="Or paste a NIST detail URL",
|
| 1303 |
+
placeholder="https://kinetics.nist.gov/kinetics/ReactionSearch?....",
|
| 1304 |
+
)
|
| 1305 |
with gr.Column(scale=1):
|
| 1306 |
auto_fetch_thermo = gr.Checkbox(
|
| 1307 |
label="π¬ Auto-fetch thermodynamics",
|
|
|
|
| 1315 |
)
|
| 1316 |
|
| 1317 |
detail_button = gr.Button("Fetch Reaction Detail", variant="primary")
|
| 1318 |
+
|
| 1319 |
+
# Reaction metadata and details
|
| 1320 |
+
detail_markdown = gr.Markdown()
|
| 1321 |
+
|
| 1322 |
with gr.Row():
|
| 1323 |
+
# Kinetics data table
|
| 1324 |
with gr.Column():
|
| 1325 |
gr.Markdown("### Kinetics Data")
|
| 1326 |
+
dataset_table = gr.Dataframe(
|
| 1327 |
+
headers=["Section", "Squib", "Temp [K]", "A", "n", "Ea [J/mole]", "k(298 K)", "Order", "Squib URL"],
|
| 1328 |
+
datatype=["str"] * 9,
|
| 1329 |
+
interactive=False,
|
| 1330 |
+
wrap=True,
|
| 1331 |
+
)
|
| 1332 |
+
|
| 1333 |
# Arrhenius plot
|
| 1334 |
with gr.Column():
|
| 1335 |
gr.Markdown("### Arrhenius Plot")
|
| 1336 |
reaction_plot = gr.Plot()
|
| 1337 |
|
| 1338 |
+
# Reaction SVG visualization
|
| 1339 |
+
with gr.Row():
|
| 1340 |
+
gr.Markdown("### Reaction Structure")
|
| 1341 |
+
reaction_svg = gr.HTML()
|
| 1342 |
+
|
| 1343 |
# Auto-fetched thermodynamic data
|
| 1344 |
thermo_summary = gr.Markdown()
|
| 1345 |
thermo_accordion = gr.Accordion(label="π¬ Thermodynamic Data", open=False)
|
|
|
|
| 1350 |
# Tab 3: Reaction SVG (Enhanced with NIST reactions and AI completion)
|
| 1351 |
with gr.TabItem("Reaction SVG"):
|
| 1352 |
gr.Markdown(
|
| 1353 |
+
"π¨ **Render chemical reactions as SVG using RDKit + AI Enhancement**\n\n"
|
| 1354 |
+
"Choose from NIST database reactions, enter custom reactions, or let AI enhance/validate/complete your reactions!\n\n"
|
| 1355 |
+
"**Workflow:**\n"
|
| 1356 |
+
"1. π€ **AI Enhancement First**: DeepSeek AI analyzes and enhances your reaction\n"
|
| 1357 |
+
"2. π¨ **RDKit Rendering**: Complete reaction rendered as beautiful SVG\n"
|
| 1358 |
+
"3. β
**Validation**: AI confirms reaction balance and plausibility\n\n"
|
| 1359 |
"**Features:**\n"
|
| 1360 |
"- π§ͺ 200+ NIST database reactions\n"
|
| 1361 |
+
"- π€ AI-powered reaction enhancement (DeepSeek-V3.2-Exp)\n"
|
| 1362 |
+
"- π¬ Multiple input formats (NIST, SMILES, SMARTS, partial)\n"
|
| 1363 |
+
"- β‘ Automatic format detection and intelligent conversion\n"
|
| 1364 |
+
"- β
Reaction validation and balancing"
|
| 1365 |
)
|
| 1366 |
|
| 1367 |
# API Key Configuration
|
|
|
|
| 1372 |
type="password",
|
| 1373 |
info="Get your API key from https://platform.deepseek.com/"
|
| 1374 |
)
|
| 1375 |
+
gr.Markdown(
|
| 1376 |
"**How to get API key:**\n"
|
| 1377 |
"1. Visit https://platform.deepseek.com/\n"
|
| 1378 |
"2. Sign up/Login to your account\n"
|
|
|
|
| 1384 |
# NIST reactions dropdown
|
| 1385 |
nist_reactions = _fetch_all_nist_reactions(limit=200)
|
| 1386 |
nist_reaction_options = [("", "")] + nist_reactions if nist_reactions else []
|
| 1387 |
+
|
| 1388 |
+
with gr.Row():
|
| 1389 |
with gr.Column():
|
| 1390 |
nist_reaction_dropdown = gr.Dropdown(
|
| 1391 |
label="π§ͺ NIST Database Reactions",
|
|
|
|
| 1394 |
interactive=True,
|
| 1395 |
info=f"Select from {len(nist_reactions)} reactions in NIST kinetics database"
|
| 1396 |
)
|
| 1397 |
+
|
| 1398 |
+
reaction_input = gr.Textbox(
|
| 1399 |
label="Custom Reaction Input",
|
| 1400 |
placeholder="Enter reaction in any format:\nNIST: CH4 + O2 β CO2 + H2O\nSMILES: CH4.O2>>CO2.H2O\nPartial: CH4 + O2 β (AI will complete)",
|
| 1401 |
lines=4,
|
|
|
|
| 1411 |
)
|
| 1412 |
|
| 1413 |
ai_options = gr.CheckboxGroup(
|
| 1414 |
+
label="π€ AI Enhancement Options",
|
| 1415 |
+
choices=["Enable AI enhancement (recommended)", "High quality rendering", "Show AI reasoning"],
|
| 1416 |
+
value=["Enable AI enhancement (recommended)"],
|
| 1417 |
+
info="DeepSeek AI analyzes, validates, and enhances reactions before rendering"
|
| 1418 |
)
|
| 1419 |
|
| 1420 |
# Buttons
|
| 1421 |
with gr.Row():
|
| 1422 |
+
render_auto_btn = gr.Button("π AI First β Render (Recommended)", variant="primary",
|
| 1423 |
+
info="DeepSeek AI enhances/completes reaction first, then renders SVG")
|
| 1424 |
+
render_nist_btn = gr.Button("π§ͺ Direct NIST Render", variant="secondary",
|
| 1425 |
+
info="Render directly without AI enhancement")
|
| 1426 |
+
render_smiles_btn = gr.Button("π¬ Direct SMILES Render", variant="secondary",
|
| 1427 |
+
info="Render SMILES/SMARTS directly without AI enhancement")
|
| 1428 |
clear_btn = gr.Button("ποΈ Clear", variant="stop")
|
| 1429 |
|
| 1430 |
# Output
|
|
|
|
| 1436 |
def populate_from_nist_dropdown(selected_label):
|
| 1437 |
if selected_label and selected_label in nist_dict:
|
| 1438 |
return nist_dict[selected_label]
|
| 1439 |
+
return ""
|
| 1440 |
+
|
| 1441 |
nist_reaction_dropdown.change(
|
| 1442 |
fn=populate_from_nist_dropdown,
|
| 1443 |
inputs=nist_reaction_dropdown,
|
| 1444 |
+
outputs=reaction_input,
|
| 1445 |
+
)
|
| 1446 |
+
|
| 1447 |
# Smart auto-render function
|
| 1448 |
def render_auto_reaction(reaction_text, api_key, ai_options, render_mode):
|
| 1449 |
if not reaction_text:
|
|
|
|
| 1452 |
status_prefix = ""
|
| 1453 |
final_reaction = reaction_text
|
| 1454 |
|
| 1455 |
+
# Always try AI enhancement first if enabled and API key provided
|
| 1456 |
+
if "Enable AI enhancement (recommended)" in (ai_options or []) and api_key:
|
| 1457 |
+
# Try to complete/enhance the reaction using DeepSeek
|
| 1458 |
+
completed_reaction = _complete_reaction_with_deepseek(reaction_text, api_key)
|
| 1459 |
+
if completed_reaction and completed_reaction != reaction_text:
|
| 1460 |
+
final_reaction = completed_reaction
|
| 1461 |
+
status_prefix = f"π€ **AI Enhanced Reaction**\nOriginal: {reaction_text}\nAI Completed: {final_reaction}\n\n"
|
| 1462 |
+
elif completed_reaction == reaction_text:
|
| 1463 |
+
# AI validated the reaction as complete
|
| 1464 |
+
status_prefix = f"π€ **AI Validated Reaction**\nReaction confirmed as complete and balanced.\n\n"
|
| 1465 |
+
else:
|
| 1466 |
+
# AI failed, try direct rendering
|
| 1467 |
+
status_prefix = f"β οΈ **AI Enhancement Failed**\nProceeding with original reaction.\n\n"
|
| 1468 |
+
|
| 1469 |
+
# Render the final reaction (AI-enhanced or original)
|
| 1470 |
+
svg = None
|
| 1471 |
+
render_type = "unknown"
|
| 1472 |
+
|
| 1473 |
+
# Try different rendering approaches based on mode
|
| 1474 |
+
if render_mode == "Force SMILES/SMARTS":
|
| 1475 |
svg = _render_smiles_to_svg(final_reaction)
|
| 1476 |
render_type = "SMILES/SMARTS"
|
| 1477 |
+
elif render_mode == "Force NIST format":
|
| 1478 |
svg = _render_reaction_from_nist(final_reaction)
|
| 1479 |
render_type = "NIST format"
|
| 1480 |
+
else: # Auto (detect format)
|
| 1481 |
+
# First try SMILES if it contains >>
|
| 1482 |
+
if ">>" in final_reaction:
|
|
|
|
| 1483 |
svg = _render_smiles_to_svg(final_reaction)
|
| 1484 |
+
render_type = "SMILES/SMARTS (detected)"
|
| 1485 |
+
else:
|
| 1486 |
+
# Try NIST format first, then SMILES
|
| 1487 |
+
svg = _render_reaction_from_nist(final_reaction)
|
| 1488 |
+
if svg:
|
| 1489 |
+
render_type = "NIST format (detected)"
|
| 1490 |
+
else:
|
| 1491 |
+
svg = _render_smiles_to_svg(final_reaction)
|
| 1492 |
+
render_type = "SMILES/SMARTS (fallback)"
|
| 1493 |
|
| 1494 |
if svg:
|
| 1495 |
quality_note = " (High quality)" if "High quality rendering" in (ai_options or []) else ""
|
| 1496 |
+
reasoning_note = " (with AI reasoning)" if "Show AI reasoning" in (ai_options or []) else ""
|
| 1497 |
+
status = f"{status_prefix}β
Successfully rendered as {render_type}{quality_note}{reasoning_note}"
|
| 1498 |
return svg, status
|
| 1499 |
else:
|
| 1500 |
+
return "", f"{status_prefix}β Could not render reaction. The reaction format may not be supported: {final_reaction[:100]}...\n\nTry adjusting the render mode or checking your reaction syntax."
|
| 1501 |
|
| 1502 |
# Legacy render functions (kept for compatibility)
|
| 1503 |
def render_nist_reaction(reaction_text, options):
|
|
|
|
| 1507 |
svg = _render_reaction_from_nist(reaction_text)
|
| 1508 |
if svg:
|
| 1509 |
status = f"β
Successfully rendered NIST reaction: {reaction_text[:100]}..."
|
| 1510 |
+
if "High quality rendering" in (options or []):
|
| 1511 |
status += " (High quality mode)"
|
| 1512 |
return svg, status
|
| 1513 |
else:
|
|
|
|
| 1520 |
svg = _render_smiles_to_svg(reaction_text)
|
| 1521 |
if svg:
|
| 1522 |
status = f"β
Successfully rendered SMILES reaction: {reaction_text[:100]}..."
|
| 1523 |
+
if "High quality rendering" in (options or []):
|
| 1524 |
status += " (High quality mode)"
|
| 1525 |
return svg, status
|
| 1526 |
else:
|
|
|
|
| 1534 |
render_auto_btn.click(
|
| 1535 |
fn=render_auto_reaction,
|
| 1536 |
inputs=[reaction_input, deepseek_api_key, ai_options, render_mode],
|
| 1537 |
+
outputs=[reaction_svg_output, render_status],
|
| 1538 |
+
)
|
| 1539 |
|
| 1540 |
render_nist_btn.click(
|
| 1541 |
fn=render_nist_reaction,
|
|
|
|
| 1557 |
|
| 1558 |
# Tab 4: Kinetics Plotter
|
| 1559 |
with gr.TabItem("Kinetics Plotter"):
|
| 1560 |
+
with gr.Row():
|
| 1561 |
+
with gr.Column():
|
| 1562 |
A_input = gr.Number(value=1.3e-9, label="A (cmΒ³/moleculeΒ·s)")
|
| 1563 |
n_input = gr.Number(value=-0.495, label="n (power)")
|
| 1564 |
Ea_input = gr.Number(value=1150, label="Ea (J/mol)")
|
|
|
|
| 1596 |
|
| 1597 |
fetch_btn = gr.Button("Fetch Data")
|
| 1598 |
|
| 1599 |
+
with gr.Column():
|
| 1600 |
+
output_md = gr.Markdown()
|
| 1601 |
output_df = gr.Dataframe(label="Tabular Data")
|
| 1602 |
output_plot = gr.Plot(visible=False, label="Spectrum Preview") # For IR/UV/THz later
|
| 1603 |
|
|
|
|
| 1638 |
["CH3"], ["benzene"], ["C6H5OH"]
|
| 1639 |
],
|
| 1640 |
inputs=[formula_input] # Note: This is placeholder; make per-tab if needed
|
| 1641 |
+
)
|
| 1642 |
|
| 1643 |
return demo
|
| 1644 |
|