This repo is now a synthesis-planning project aligned with the proposal in MCTS_Materials_Synthesis_Project_Proposal.docx. The old crystal-search package and its study directories have been removed so the repository now reflects the new synthesis-first scope directly.
The current codebase focuses on the proposal's first practical milestone:
- public dataset download and normalization
- a canonical route schema for mined synthesis recipes
- modality-aware synthesis grammars for solid-state, hydrothermal, and precipitation planning
- retrieval of analogous literature routes
- route scoring with explicit stoichiometric balancing, redox-aware hard checks, thermodynamic proxy features, and a pluggable retrieval-grounded judge interface
- Monte Carlo Tree Search over partial synthesis routes
- retrospective split generation, baselines, and ablation-style benchmark evaluation
The initial planner is intentionally a strong solid-state baseline, not a claim that the full proposal is finished. The solution-based dataset is downloaded and normalized for future hydrothermal and precipitation support, but the executable planner currently targets solid_state routes.
The planner now supports executable solid_state, hydrothermal, and precipitation search, with a deterministic judge by default and benchmark support for nearest-neighbor and frequency-prior baselines.
The repo now uses the public datasets referenced in the proposal:
- Solid-state dataset:
CederGroupHub/text-mined-synthesis_public- file:
solid-state_dataset_20200713.json.xz
- file:
- Solution dataset:
CederGroupHub/text-mined-solution-synthesis_public- file:
solution-synthesis_dataset_2021-8-5.json.zip
- file:
They are downloaded into data/raw/ and normalized into JSONL route records in data/processed/.
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip setuptools wheel pytest numpy pandas
.venv/bin/python -m pip install .For development:
.venv/bin/python -m pip install '.[dev]'The CLI now looks for local configuration in config.py first, then config.json.
config.pyis gitignored and safe for local secrets such as API keys.config.example.pyis the tracked template showing the expected shape.config.example.jsonremains available if you prefer JSON for non-secret defaults.
If you use the model-backed judge, keep the real key only in local config.py or an environment variable such as OPENAI_API_KEY.
Download the public datasets:
python run_mcts.py download-dataNormalize them into route records:
python run_mcts.py prepare-dataPlan routes for a target:
python run_mcts.py plan --target BaTiO3 --iterations 250 --top-k 5Plan a hydrothermal route:
python run_mcts.py plan --target CoFe2O4 --modality hydrothermalPlan a precipitation route:
python run_mcts.py plan --target TiO2 --modality precipitationRun with ablation-style switches:
python run_mcts.py plan --target BaTiO3 --disable-retrieval
python run_mcts.py plan --target BaTiO3 --judge none --disable-judge
python run_mcts.py plan --target BaTiO3 --disable-hard-checksUse a retrieval-grounded structured judge with an OpenAI-compatible endpoint:
python run_mcts.py plan \
--target BaTiO3 \
--judge openai_structured \
--judge-model gpt-4o-miniYou can also override credentials or endpoint per run:
python run_mcts.py plan \
--target BaTiO3 \
--judge openai_structured \
--judge-model gpt-4o-mini \
--judge-api-key "$OPENAI_API_KEY" \
--judge-base-url "https://api.openai.com/v1"For LiteLLM-style or other OpenAI-compatible proxy endpoints that prefer chat completions, set:
python run_mcts.py plan \
--target BaTiO3 \
--judge openai_structured \
--judge-model gpt-oss-120b \
--judge-base-url "https://aiportal-api.aws.lanl.gov" \
--judge-api-style chat_completionsGenerate benchmark splits:
python run_mcts.py make-splits --split-type target_formulaRun a small retrospective benchmark:
python run_mcts.py benchmark --split-type chemical_system --iterations 50 --rollout-count 3Run baseline and ablation comparisons:
python run_mcts.py benchmark --method nearest_neighbor
python run_mcts.py benchmark --method frequency_prior
python run_mcts.py benchmark --method suiteThe planner writes ranked routes to planning_results/ and prints a short summary to the terminal.
- docs/ARCHITECTURE.md: package layout, planning pipeline, and current design boundaries
- docs/DATASETS.md: public dataset sources, local file layout, and normalization outputs
Given a target such as BaTiO3, the current planner:
- Loads normalized solid-state routes from the mined literature corpus.
- Retrieves analogous targets by element overlap, target family, and rough composition similarity.
- Builds precursor candidates from exact analog routes plus element-level precursor usage priors.
- Expands a staged solid-state grammar:
- precursor set
- preparation steps
- heating schedule
- finalization
- Uses modality-aware grammars for hydrothermal and precipitation when requested:
- solvent setup
- reaction/hold/precipitation step
- washing, drying, and optional post-anneal
- Applies hard validity checks for element coverage, modality consistency, lab constraints, temperature bounds, atmosphere compatibility, solvent requirements, exact precursor-to-target balancing with common volatile species, and redox/environment consistency.
- Scores completed routes using:
- element coverage and balanced reaction feasibility
- hard validity
- precursor plausibility
- thermodynamic proxy features such as gas release, decomposition alignment, and redox support
- retrieval support
- condition plausibility
- hazard and complexity penalties
- retrieval-grounded judge notes, flags, rubric scores, and uncertainty
- Uses MCTS to prioritize promising partial routes and returns a small diverse portfolio.
docs/- architecture and dataset notes for the rewritten planner
data/raw/: downloaded public corporaprocessed/: normalized JSONL route records generated locally
synthesis_planner/datasets.py: dataset download, loading, normalizationformula.py: formula parsing and target-family heuristicschemistry.py: stoichiometric balancing, oxidation/redox checks, and thermodynamic proxy featuresretrieval.py: analog retrieval and precursor prior generationgrammar.py: staged solid-state grammarconstraints.py: modality-aware hard validity checksjudge.py: deterministic and model-backed structured retrieval-grounded judgesscoring.py: chemistry-aware route scoring plus judge integrationmcts.py: compact PUCT-style tree searchplanner.py: high-level planning interfacebenchmark.py: split generation, baselines, and evaluationscli.py:download-data,prepare-data,plan,make-splits,benchmark
tests/- focused on formula parsing, normalization, retrieval, scoring, planner behavior, and CLI parsing
- Thermodynamic scoring now uses offline chemistry proxies derived from balanced reactions and redox checks, but it still does not use tabulated formation energies or phase-diagram data.
- The judge interface is pluggable, and now supports a structured OpenAI-compatible judge, but the default remains deterministic so the repo still works offline and remains testable.
- Route scoring is still a baseline heuristic layer rather than a calibrated literature-plus-physics model.
- The benchmark harness now includes baselines and simple ablations, but it still does not cover the full expert/prospective evaluation loop from the proposal.
Unit tests:
.venv/bin/python -m pytestCLI smoke-tested commands:
.venv/bin/python run_mcts.py make-splits --split-type target_formula
.venv/bin/python run_mcts.py benchmark --split-type random --test-fraction 0.0002 --iterations 8 --rollout-count 2
.venv/bin/python run_mcts.py benchmark --method suite --split-type random --test-fraction 0.0002 --iterations 6 --rollout-count 2
.venv/bin/python run_mcts.py plan --target CoFe2O4 --modality hydrothermal
.venv/bin/python run_mcts.py plan --target TiO2 --modality precipitationThe rewritten test suite covers the new synthesis-planning path rather than the legacy crystal-search code.