Spaces:
Paused
Paused
Download app.py from andreamena/CrysText: direct link, hf CLI and curl.
- Browser
- Download file 4.9 kB
-
https://huggingface.co/spaces/andreamena/CrysText/resolve/main/app.py
- Command line
-
hf download hf://spaces/andreamena/CrysText/app.py
-
curl -L -o app.py https://huggingface.co/spaces/andreamena/CrysText/resolve/main/app.py
4.9 kB
| import gradio as gr | |
| import os | |
| import shutil | |
| import subprocess | |
| from llama_cpp import Llama | |
| from pymatgen.core import Structure | |
| from huggingface_hub import hf_hub_download | |
| # -------------------- | |
| # Paths & Config | |
| # -------------------- | |
| GEN_DIR = "generation_cifs" | |
| REPO_ID = "andreamena/crystext-gguf" | |
| FILENAME = "crystext-rl.gguf" | |
| # Fixed evaluation compositions (from your dataset) | |
| KNOWN_MATERIALS = [ | |
| "NaTiVS4", | |
| "ScAlRh2", | |
| "Fe3Te2Se", | |
| "Eu2CrSbO6", | |
| "Fe(HO)2", | |
| "Sm(CoB)2", | |
| "GaTe", | |
| "Zr2VRe3", | |
| "LiMnO2", | |
| "AlAu4", | |
| ] | |
| # -------------------- | |
| # Load GGUF model | |
| # -------------------- | |
| print("⏳ Downloading Model from Hub... this may take a minute...") | |
| try: | |
| model_path = hf_hub_download(repo_id=REPO_ID, filename=FILENAME) | |
| print(f"✅ Model downloaded to: {model_path}") | |
| print("⏳ Initializing CPU Engine...") | |
| llm = Llama( | |
| model_path=model_path, | |
| n_ctx=2048, | |
| n_threads=2, # HF free tier = 2 vCPUs | |
| verbose=True | |
| ) | |
| print("✅ Engine Ready!") | |
| except Exception as e: | |
| print(f"❌ Error setting up model: {e}") | |
| llm = None | |
| # -------------------- | |
| # Generation helpers | |
| # -------------------- | |
| def generate_single_cif(composition, space_group, temperature): | |
| prompt = f"""Below is an instruction that describes a task, paired with an input that provides further context. | |
| ### Instruction: | |
| Generate CIF for the given material description | |
| ### Input: | |
| Material composition is {composition}. It has a space group number {space_group}. | |
| ### Response: | |
| """ | |
| output = llm( | |
| prompt, | |
| max_tokens=2048, | |
| temperature=temperature, | |
| stop=["</s>"], | |
| echo=False | |
| ) | |
| return output["choices"][0]["text"] | |
| # -------------------- | |
| # Main pipeline | |
| # -------------------- | |
| def run_demo(composition, space_group, num_samples, temperature, progress=gr.Progress()): | |
| shutil.rmtree(GEN_DIR, ignore_errors=True) | |
| os.makedirs(GEN_DIR, exist_ok=True) | |
| if llm is None: | |
| return None, "Model failed to load.", "N/A" | |
| status_msg = f"Generating {num_samples} candidates (CPU: ~6 min/sample)\n" | |
| generated_files = [] | |
| for i in progress.tqdm(range(int(num_samples)), desc="Generating structures"): | |
| try: | |
| cif_text = generate_single_cif(composition, space_group, temperature) | |
| cif_text = cif_text.replace("```cif", "").replace("```", "").strip() | |
| path = os.path.join(GEN_DIR, f"sample_{i}.cif") | |
| with open(path, "w") as f: | |
| f.write(cif_text) | |
| generated_files.append(path) | |
| except Exception as e: | |
| print(f"Sample {i} failed: {e}") | |
| if not generated_files: | |
| return None, "No valid CIFs generated.", "N/A" | |
| # Evaluation | |
| progress(0.9, desc="Evaluating structures...") | |
| try: | |
| subprocess.run(["python", "select_best_cif.py"], check=True) | |
| eval_text = subprocess.check_output(["python", "evaluation.py"], text=True) | |
| final_path = "final.cif" | |
| if os.path.exists(final_path): | |
| struct = Structure.from_file(final_path) | |
| sg_info = struct.get_space_group_info(symprec=0.1) | |
| return final_path, f"{status_msg}\n{eval_text}", f"{sg_info}" | |
| else: | |
| return None, f"{status_msg}\nEvaluation finished but no final.cif found.", "N/A" | |
| except Exception as e: | |
| return None, f"Evaluation error: {e}", "N/A" | |
| # -------------------- | |
| # Gradio UI | |
| # -------------------- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# CrysText-RL: Crystal Generation") | |
| gr.Markdown(f"Running GGUF model sourced from: `{REPO_ID}`") | |
| with gr.Row(): | |
| with gr.Column(): | |
| composition = gr.Dropdown( | |
| choices=KNOWN_MATERIALS, | |
| value="NaTiVS4", | |
| label="Composition (evaluation set)" | |
| ) | |
| space_group = gr.Slider( | |
| minimum=1, | |
| maximum=230, | |
| step=1, | |
| value=8, | |
| label="Target Space Group" | |
| ) | |
| num_samples = gr.Slider( | |
| 1, 6, value=1, step=1, | |
| label="Samples (CPU-limited)" | |
| ) | |
| temperature = gr.Slider( | |
| 0.6, 1.0, value=0.8, step=0.05, | |
| label="Temperature" | |
| ) | |
| run_btn = gr.Button("Generate Crystal Structure", variant="primary") | |
| with gr.Column(): | |
| sg_output = gr.Textbox(label="Predicted Space Group") | |
| eval_output = gr.Textbox(label="Evaluation Metrics", lines=10) | |
| best_cif = gr.File(label="Download Best CIF") | |
| run_btn.click( | |
| run_demo, | |
| inputs=[composition, space_group, num_samples, temperature], | |
| outputs=[best_cif, eval_output, sg_output], | |
| ) | |
| demo.launch( | |
| auth=(os.environ.get("app_user"), os.environ.get("app_pass")), | |
| ssr_mode=False | |
| ) | |