chemgraph-loop / README.md
rockyaaos's picture
README: full dev/ops doc
ae98bf4 verified
|
Raw
History Blame Contribute Delete
5.22 kB
---
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)
1. **LLM intent router** (`llm_parse_query`, PRIMARY) β€” one `gpt-4o-mini` JSON
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
emits `nearest`/`note` for 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.
2. **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** in `precomputed/`
(`cached:true`, shown as "precomputed real run").
3. **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-specific `result`
(energy / dipole vector+magnitude / ir.modes / thermo H,S,G), `verified`.
4. **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 `Infrared`
intensity 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**.
```python
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`.