Spaces:
Running
title: ChemGraph Loop
emoji: π§ͺ
colorFrom: green
colorTo: yellow
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: Real agentic chemistry workflow β resolve, simulate, verify
ChemGraph Loop
A guarded, natural-language API around the real ChemGraph agent β Argonne Leadership Computing Facility's agentic computational-chemistry framework (LangGraph + ASE), running the workflow-correctness hardening by Lu Zhang.
Backs the live demo at sciencesloop.com/agent (frontend =
lu-zhang-site/src/components/ChemGraphDemo.astro).
- GitHub (source):
github.com/rockyzl/chemgraph-loop(private) - Deploy target: HF Space
rockyaaos/chemgraph-loop(Docker, free CPU-basic) - Upstream ChemGraph: https://github.com/argonne-lcf/ChemGraph (Apache-2.0)
How it works (request lifecycle)
- LLM intent router (
llm_parse_query, PRIMARY) β onegpt-4o-miniJSON call reads the plain-language question and returns{molecule, task, calculator}, resolving the molecule by ANY name/synonym/formula ("dihydrogen monoxide"/"H2O"/"NH3"/"CO2"/"EtOH"/"benzol" β canonical). It refuses to match derivatives to a parent (dimethoxybenzene β benzene) and emitsnearest/notefor out-of-scope molecules.keyword_fallback(token match, no regex) runs ONLY if the model call fails. This is intentionally agentic, not a rule engine. - Route by physics cost:
energy/dipole= single-point (~12β25 s) β run the real ChemGraph agent LIVE on a canonical, guard-matched query built from the intent.ir/thermo= finite-difference Hessian (too slow for free CPU) β served from precomputed real agent runs inprecomputed/(cached:true, shown as "precomputed real run").
- Extract (
cg_extract.extract) β unified rich payload: molecule/formula/ smiles,structure.atoms(parsed from molecule.xyz, drives the 3D viewer),steps[](tool calls + folded detail), task-specificresult(energy / dipole vector+magnitude / ir.modes / thermo H,S,G),verified. - Clarification node β out-of-scope molecule or an unavailable heavy task
returns
{clarify:true, message, suggestions:[{label,query}]}(HTTP 200), NOT an error. The frontend renders it as a conversational bubble + chips.
Endpoints
GET / β health: molecules, tasks, live_tasks, ir_molecules, thermo_molecules
POST /run { "query": "IR spectrum of water" } # natural-language (primary)
POST /run { "molecule": "water", "calculator": "emt" } # legacy, energy only
/run returns one of: a rich result payload Β· a clarify payload Β· an error
(429 rate limit Β· 504 timeout Β· 500 agent error).
Coverage & reliability (IMPORTANT)
- energy / dipole: LIVE for all 10 allow-listed molecules (water, methane, ammonia, methanol, ethanol, carbon dioxide, benzene, acetic acid, formaldehyde, hydrogen peroxide).
- thermochemistry: precomputed for all 10 (thermo uses plain
Vibrations; works for large molecules). - IR / vibrations: precomputed for β€4-atom molecules only β water,
ammonia, carbon dioxide, formaldehyde, hydrogen peroxide. The ASE
Infraredintensity step returns empty modes for β₯5-atom molecules (methane, methanol, ethanol, acetic acid, benzene all fail β confirmed). Do NOT add β₯5-atom IR; the clarification node covers them. - Guard-matched queries only (single-point / dipole / ir / thermo). "geometry optimization" phrasing makes the agent loop β never expose it.
- Display-layer IR filter: keep modes with
cm1 β₯ 100&intensity > 1e-3(drops spurious near-zero / translation-rotation modes).
Files
| File | Role |
|---|---|
app.py |
FastAPI: intent router, routing, clarification node, guards (CORS, rate limit, timeout) |
cg_extract.py |
shared payload extractor (structure/steps/results) β used by app + precompute |
precompute.py |
offline heavy-task generator: python precompute.py <molecule...> |
precomputed/<slug>__<task>.json |
bundled real agent runs for ir/thermo |
Dockerfile |
CPU torch β pip install .[calculators] β copies wrappers LAST (fast layer-cached rebuilds) |
src/ |
vendored copy of Lu's hardened ChemGraph fork |
Deploy / operate
The HF Space builds from its own git; push files with huggingface_hub
(~/.local env at /tmp/hfenv/bin/python on Lu's box) β upload_file /
upload_folder / delete_file each trigger a rebuild (~2β4 min, layer-cached
since wrappers copy late). OPENAI_API_KEY is a Space secret.
from huggingface_hub import HfApi
HfApi().upload_file(path_or_fileobj="app.py", path_in_repo="app.py",
repo_id="rockyaaos/chemgraph-loop", repo_type="space",
commit_message="...")
Add a spectrum/thermo molecule: run precompute.py <name>, validate the IR
modes are non-empty & physical (cm1β₯100), upload_file the JSON, let the Space
rebuild (its _avail(task) picks it up automatically). Only β€4-atom molecules
get valid IR.
CORS allows sciencesloop.com, *.vercel.app, and localhost:4321.