import gradio as gr
import json
from main import ChemEagle
from rdkit import Chem
from rdkit.Chem import rdChemReactions, Draw, AllChem
from rdkit.Chem.Draw import rdMolDraw2D
import cairosvg
import re
import os
example_diagram = "examples/exp.png"
rdkit_image = "examples/rdkit.png"
def parse_reactions(output_json):
if isinstance(output_json, str):
reactions_data = json.loads(output_json)
else:
reactions_data = output_json
reactions_list = reactions_data.get("reactions", [])
detailed_output = []
smiles_output = []
for reaction in reactions_list:
reaction_id = reaction.get("reaction_id", "Unknown ID")
reactants = [r.get("smiles", "Unknown") for r in reaction.get("reactants", [])]
conds = reaction.get("conditions")
if conds is None:
conds = reaction.get("condition", [])
conditions = [
f"{c.get('smiles', c.get('text', 'Unknown'))}[{c.get('role', 'Unknown')}]"
for c in conds
]
conditions_1 = [
f"{c.get('smiles', c.get('text', 'Unknown'))}[{c.get('role', 'Unknown')}]"
for c in conds
]
products = [f"{p.get('smiles', 'Unknown')}" for p in reaction.get("products", [])]
products_1 = [f"{p.get('smiles', 'Unknown')}" for p in reaction.get("products", [])]
products_2 = [r.get("smiles", "Unknown") for r in reaction.get("products", [])]
additional = reaction.get("additional_info", [])
additional_str = [str(x) for x in additional if x]
tail = conditions_1 + additional_str
tail_str = ", ".join(tail)
full_reaction = f"{'.'.join(reactants)}>>{'.'.join(products_1)} | {tail_str}"
full_reaction = f"{full_reaction}"
reaction_output = f"Reaction: {reaction_id}
"
reaction_output += f" Reactants: {', '.join(reactants)}
"
reaction_output += f" Conditions: {', '.join(conditions)}
"
reaction_output += f" Products: {', '.join(products)}
"
reaction_output += f" additional_info: {', '.join(additional_str)}
"
reaction_output += f" Full Reaction: {full_reaction}
"
detailed_output.append(reaction_output)
reaction_smiles = f"{'.'.join(reactants)}>>{'.'.join(products_2)}"
smiles_output.append(reaction_smiles)
return detailed_output, smiles_output
def parse_mol(output_json):
"""
解析单分子/多分子的 ChemEagle 输出,返回与 parse_reactions 相同的 detailed_output, smiles_output。
"""
if isinstance(output_json, str):
mols_data = json.loads(output_json)
else:
mols_data = output_json
molecules_list = mols_data.get("molecules", [])
detailed_output = []
smiles_output = []
for i, mol in enumerate(molecules_list):
smiles = mol.get("smiles", "Unknown")
label = mol.get("label", f"Mol {i+1}")
bbox = mol.get("bbox", [])
# 可自定义格式
mol_output = f"Molecule: {label}
" \
f" SMILES: {smiles}
" \
f" bbox: {bbox}
"
detailed_output.append(mol_output)
smiles_output.append(smiles)
return detailed_output, smiles_output
def process_chem_image(image):
image_path = "temp_image.png"
image.save(image_path)
chemeagle_result = ChemEagle(image_path)
if "molecules" in chemeagle_result:
detailed, smiles = parse_mol(chemeagle_result)
else:
detailed, smiles = parse_reactions(chemeagle_result)
json_path = "output.json"
with open(json_path, 'w') as jf:
json.dump(chemeagle_result, jf, indent=2)
return "\n\n".join(detailed), smiles, example_diagram, json_path
def process_chem_image_api(image, api_key, endpoint):
# 动态设置环境变量
os.environ["API_KEY"] = api_key
os.environ["AZURE_ENDPOINT"] = endpoint or "" # endpoint 允许为空
image_path = "temp_image.png"
image.save(image_path)
# 假设 ChemEagle 内部会用 os.getenv("API_KEY") 或 os.environ["API_KEY"]
chemeagle_result = ChemEagle(image_path)
if "molecules" in chemeagle_result:
detailed, smiles = parse_mol(chemeagle_result)
else:
detailed, smiles = parse_reactions(chemeagle_result)
json_path = "output.json"
with open(json_path, 'w') as jf:
json.dump(chemeagle_result, jf, indent=2)
return "\n\n".join(detailed), smiles, example_diagram, json_path
with gr.Blocks() as demo:
gr.Markdown(
"""