|
import os |
|
import gradio as gr |
|
import json |
|
from rxnim import RXNIM |
|
from getReaction import generate_combined_image |
|
import torch |
|
from rxn.reaction import Reaction |
|
|
|
PROMPT_DIR = "prompts/" |
|
ckpt_path = "./rxn/model/model.ckpt" |
|
model = Reaction(ckpt_path, device=torch.device('cpu')) |
|
|
|
|
|
PROMPT_NAMES = { |
|
"2_RxnOCR.txt": "Reaction Image Parsing Workflow", |
|
} |
|
example_diagram = "examples/exp.png" |
|
|
|
def list_prompt_files_with_names(): |
|
""" |
|
列出 prompts 目录下的所有 .txt 文件,为没有名字的生成默认名字。 |
|
返回 {friendly_name: filename} 映射。 |
|
""" |
|
prompt_files = {} |
|
for f in os.listdir(PROMPT_DIR): |
|
if f.endswith(".txt"): |
|
|
|
friendly_name = PROMPT_NAMES.get(f, f"Task: {os.path.splitext(f)[0]}") |
|
prompt_files[friendly_name] = f |
|
return prompt_files |
|
|
|
def parse_reactions(output_json): |
|
""" |
|
解析 JSON 格式的反应数据并格式化输出,包含颜色定制。 |
|
""" |
|
reactions_data = json.loads(output_json) |
|
reactions_list = reactions_data.get("reactions", []) |
|
detailed_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", [])] |
|
conditions = [ |
|
f"<span style='color:red'>{c.get('smiles', c.get('text', 'Unknown'))}[{c.get('role', 'Unknown')}]</span>" |
|
for c in reaction.get("conditions", []) |
|
] |
|
conditions_1 = [ |
|
f"<span style='color:black'>{c.get('smiles', c.get('text', 'Unknown'))}[{c.get('role', 'Unknown')}]</span>" |
|
for c in reaction.get("conditions", []) |
|
] |
|
products = [f"<span style='color:orange'>{p.get('smiles', 'Unknown')}</span>" for p in reaction.get("products", [])] |
|
products_1 = [f"<span style='color:black'>{p.get('smiles', 'Unknown')}</span>" for p in reaction.get("products", [])] |
|
|
|
|
|
full_reaction = f"{'.'.join(reactants)}>>{'.'.join(products_1)} | {', '.join(conditions_1)}" |
|
full_reaction = f"<span style='color:black'>{full_reaction}</span>" |
|
|
|
|
|
reaction_output = f"<b>Reaction: </b> {reaction_id}<br>" |
|
reaction_output += f" Reactants: <span style='color:blue'>{', '.join(reactants)}</span><br>" |
|
reaction_output += f" Conditions: {', '.join(conditions)}<br>" |
|
reaction_output += f" Products: {', '.join(products)}<br>" |
|
reaction_output += f" <b>Full Reaction:</b> {full_reaction}<br>" |
|
reaction_output += "<br>" |
|
detailed_output.append(reaction_output) |
|
|
|
return detailed_output |
|
|
|
def process_chem_image(image, selected_task): |
|
chem_mllm = RXNIM() |
|
|
|
|
|
prompt_path = os.path.join(PROMPT_DIR, prompts_with_names[selected_task]) |
|
image_path = "temp_image.png" |
|
image.save(image_path) |
|
|
|
|
|
rxnim_result = chem_mllm.process(image_path, prompt_path) |
|
|
|
|
|
detailed_reactions = parse_reactions(rxnim_result) |
|
|
|
|
|
predictions = model.predict_image_file(image_path, molscribe=True, ocr=True) |
|
combined_image_path = generate_combined_image(predictions, image_path) |
|
|
|
json_file_path = "output.json" |
|
with open(json_file_path, "w") as json_file: |
|
json.dump(json.loads(rxnim_result), json_file, indent=4) |
|
|
|
|
|
|
|
return "\n\n".join(detailed_reactions), combined_image_path, example_diagram, json_file_path |
|
|
|
|
|
|
|
prompts_with_names = list_prompt_files_with_names() |
|
|
|
|
|
examples = [ |
|
|
|
["examples/reaction1.png", "Reaction Image Parsing Workflow"], |
|
["examples/reaction2.png", "Reaction Image Parsing Workflow"], |
|
["examples/reaction3.png", "Reaction Image Parsing Workflow"], |
|
["examples/reaction4.png", "Reaction Image Parsing Workflow"], |
|
] |
|
|
|
|
|
demo = gr.Interface( |
|
fn=process_chem_image, |
|
inputs=[ |
|
gr.Image(type="pil", label="Upload Reaction Image"), |
|
gr.Radio( |
|
choices=list(prompts_with_names.keys()), |
|
label="Select a predefined task", |
|
), |
|
], |
|
outputs=[ |
|
gr.HTML(label="Reaction outputs"), |
|
gr.Image(label="Visualization"), |
|
gr.Image(value=example_diagram, label="Schematic Diagram"), |
|
gr.File(label="Download JSON File"), |
|
|
|
], |
|
title="Towards Large-scale Chemical Reaction Image Parsing via a Multimodal Large Language Model", |
|
description="Upload a reaction image and select a predefined task prompt.", |
|
examples=examples, |
|
examples_per_page=20, |
|
) |
|
|
|
demo.launch() |
|
|