|
1 | | -# EMSeek: Autonomous Agents for Electron Microscopy & Materials Analysis |
2 | | - |
3 | | -**EMSeek** is a modular, provenance-tracked multi-agent platform that connects raw electron microscopy (EM) images to materials structures and property insights. It automates end-to-end workflows—segmentation, crystallographic reconstruction, property prediction, literature grounding, and audit reporting—powered by LLM/MLLM orchestration. |
4 | | - |
5 | | ---- |
6 | | - |
7 | | -## ✨ Key Features |
8 | | - |
9 | | -- **SegMentor** – Reference-guided, all-in-one segmentation |
10 | | -- **CrystalForge** – Mask-aware EM → CIF reconstruction |
11 | | -- **MatProphet** – Gated Mixture-of-Experts property predictor with uncertainty calibration |
12 | | -- **ScholarSeeker** – Literature retrieval with citation anchoring |
13 | | -- **Guardian + Scribe** – Physical consistency checks and audit-ready reporting |
14 | | - |
15 | | ---- |
16 | | - |
17 | | - |
18 | | -## ⚙️ Installation |
19 | | - |
20 | | -**Requirements:** Python 3.10+, Linux/macOS preferred. GPU optional (PyTorch auto-detects CUDA). |
21 | | - |
22 | | -1. Create environment: |
| 1 | +<p align="center"> |
| 2 | + <img src="./samples/Logo.jpg" alt="EMSeek logo" width="420px" /> |
| 3 | +</p> |
| 4 | + |
| 5 | +<p align="center"> |
| 6 | +<a href="docs/architecture.md"> |
| 7 | +<img src="https://img.shields.io/badge/Read-Architecture-1e3a8a?style=for-the-badge" alt="Architecture Doc" /> |
| 8 | +</a> |
| 9 | +<a href="docs/agent-controllers.md"> |
| 10 | +<img src="https://img.shields.io/badge/Study-Agent%20Manual-2563eb?style=for-the-badge" alt="Agent Manual" /> |
| 11 | +</a> |
| 12 | +<a href="LICENSE"> |
| 13 | +<img src="https://img.shields.io/badge/License-Apache%202.0-22c55e?style=for-the-badge" alt="License" /> |
| 14 | +</a> |
| 15 | +<a href="https://github.com/PEESE/EMSeek/issues"> |
| 16 | +<img src="https://img.shields.io/badge/Open-Issues-f97316?style=for-the-badge&logo=github" alt="Open Issues" /> |
| 17 | +</a> |
| 18 | +</p> |
| 19 | + |
| 20 | +# Bridging Electron Microscopy and Materials Analysis with an Autonomous Agentic Platform |
| 21 | + |
| 22 | +## Overview |
| 23 | +EMSeek bridges raw electron microscopy (EM) data to actionable materials insights by pairing advanced reasoning with specialised actions. Rather than a monolithic model, EMSeek runs a provenance-tracked multi-agent system where a Maestro planner delegates work to targeted controllers, maintains shared memory, and streams NDJSON progress so every decision is auditable. |
| 24 | + |
| 25 | +### Why EMSeek Matters |
| 26 | +- Unifies perception, structure modelling, property inference, and literature reasoning into a reproducible, provenance-tracked workflow for EM. |
| 27 | +- Automates complex multi-stage analyses across diverse materials modalities with minimal human intervention. |
| 28 | +- Provides audit-ready artefacts, uncertainty calibration, and physical sanity checks to keep researchers in control. |
| 29 | +- Scales from exploratory analysis to production by exposing both browser and programmable interfaces, backed by configurable models and data stores. |
| 30 | + |
| 31 | +## Demo |
| 32 | +<p align="center"> |
| 33 | + <a href="https://youtu.be/GWGP8g39lV8" target="_blank" rel="noopener noreferrer"> |
| 34 | + <img src="https://img.youtube.com/vi/GWGP8g39lV8/hqdefault.jpg" alt="EMSeek demo video" width="720" /> |
| 35 | + </a> |
| 36 | +</p> |
| 37 | + |
| 38 | +## Quick Start |
| 39 | + |
| 40 | +### 1. Clone & Create an Environment |
23 | 41 | ```bash |
24 | | -conda create -n emseek python=3.10 -y && conda activate emseek |
25 | | -# or |
26 | | -python -m venv .venv && source .venv/bin/activate |
| 42 | +git clone https://github.com/PEESE/EMSeek.git |
| 43 | +cd EMSeek |
| 44 | +conda create -n emseek python=3.10 -y |
| 45 | +conda activate emseek |
| 46 | +# or: python -m venv .venv && source .venv/bin/activate |
27 | 47 | ``` |
28 | 48 |
|
29 | | -2. Install PyTorch (CPU/CUDA): [official guide](https://pytorch.org/get-started/locally/) |
30 | | - |
31 | | -3. Install dependencies: |
| 49 | +### 2. Install Core Dependencies |
| 50 | +Follow PyTorch's [official instructions](https://pytorch.org/get-started/locally/) for your platform (CPU-only is fine). Then install the EMSeek stack: |
32 | 51 | ```bash |
33 | 52 | pip install flask gunicorn litellm requests numpy pillow opencv-python scikit-image scipy matplotlib tqdm joblib ase pymatgen torchvision |
34 | 53 | ``` |
35 | 54 |
|
36 | | -**Optional packages:** |
37 | | -- Literature Q&A: `pip install paper-qa` |
38 | | -- Segmentation models: `pip install segmentation-models-pytorch` |
39 | | -- Property backends (UMA/MACE/MatterSim): `pip install fairchem mace-torch mattersim` |
| 55 | +**Optional extras** |
| 56 | +- Literature Q&A: `pip install paper-qa` |
| 57 | +- Segmentation family: `pip install segmentation-models-pytorch` |
| 58 | +- Property backends (UMA, MACE, MatterSim): `pip install fairchem mace-torch mattersim` |
40 | 59 |
|
41 | | -4. Set API keys: |
| 60 | +### 3. Provide API Keys |
| 61 | +EMSeek speaks to LLM/MLLM providers via LiteLLM. Export the keys you need (OpenAI-compatible shown below) before launching: |
42 | 62 | ```bash |
43 | | -export OPENAI_API_KEY=your_key_here |
44 | | -# optional |
45 | | -export CORE_API_KEY=your_key_here |
| 63 | +export OPENAI_API_KEY="your_openai_key" |
| 64 | +# Optional providers |
| 65 | +export CORE_API_KEY="your_core_key" |
| 66 | +export LLM_MODEL="gpt-5-nano" # overrides cfg.py defaults |
| 67 | +export MLLM_MODEL="gpt-4o-mini" # vision-capable model for captions |
46 | 68 | ``` |
47 | 69 |
|
48 | | ---- |
| 70 | +### 4. Fetch Models & Reference Data |
| 71 | +- Place segmentation and property checkpoints under `pretrained/` according to `cfg.py:TASK2MODEL`. |
| 72 | +- Add crystal structure libraries to `database/cif_lib/` (CIF files). |
| 73 | +- Drop supporting PDFs into `database/papers_lib/` for offline literature review. |
| 74 | +- Runtime logs and artefacts land in `history/<user>/<session>/` automatically. |
49 | 75 |
|
50 | | -## 📦 Data & Models |
51 | | - |
52 | | -- Download pretrained weights from [Google Drive](https://drive.google.com/drive/folders/1ltlPT8bclLc9QXfSOEWyKm64ZdtSPxQM?usp=sharing) and place them in `pretrained/` (see `cfg.py:TASK2MODEL`). |
53 | | -- Place `.cif` files in `database/cif_lib/`. |
54 | | -- Place PDFs in `database/papers_lib/`. |
55 | | - |
56 | | -Artifacts & logs are written to: |
57 | | -``` |
58 | | -history/<user_id>/ |
59 | | - ├── logs/ # JSONL traces |
60 | | - └── artifacts/ # masks, overlays, CIFs, patches, etc. |
61 | | -``` |
62 | | - |
63 | | ---- |
64 | | - |
65 | | -## 🚀 Usage |
66 | | - |
67 | | -### Web UI (dev mode) |
| 76 | +### 5. Launch & Smoke-Test |
| 77 | +**Browser UI (development):** |
68 | 78 | ```bash |
69 | 79 | python app.py |
70 | 80 | # visit http://localhost:8000 |
71 | 81 | ``` |
72 | 82 |
|
73 | | -### Production (gunicorn) |
| 83 | +**Production-ready gunicorn:** |
74 | 84 | ```bash |
75 | | -sh run.sh |
76 | | -# binds to 0.0.0.0:8000 |
| 85 | +gunicorn -w 2 -k gevent -b 0.0.0.0:8000 "app:app" |
77 | 86 | ``` |
78 | 87 |
|
79 | | -### Avoiding 413 (Upload Too Large) |
80 | | -If you see “Upload too large (413)” when sending image-only requests, your reverse proxy is likely rejecting the request body. Increase the proxy limit and (optionally) Flask’s content length: |
81 | | - |
82 | | -- Nginx: set a larger limit in http/server/location blocks and reload Nginx: |
83 | | - - `client_max_body_size 50M;` |
84 | | - - `proxy_read_timeout 600s;` |
85 | | - - See `deploy/nginx.conf.example` for a complete example. |
86 | | -- Flask: the app honors `MAX_UPLOAD_MB` (default 100). Example: `export MAX_UPLOAD_MB=200` before starting. |
87 | | - |
88 | | -Alternatively, downscale or compress images before uploading to reduce payload size. |
89 | | - |
90 | | -### REST API (NDJSON streaming) |
| 88 | +**REST NDJSON request:** |
91 | 89 | ```bash |
92 | | -curl -N -H 'Content-Type: application/json' -d '{ |
93 | | - "text": "Segment image and explain", |
94 | | - "files": ["/abs/path/to/em.png"], |
95 | | - "model": "general_model" |
96 | | - }' http://localhost:8000/api |
| 90 | +curl -N -H 'Content-Type: application/json' \ |
| 91 | + -d '{"text": "Segment and describe the uploaded EM image.", "files": ["/abs/path/to/image.png"], "model": "general_model"}' \ |
| 92 | + http://localhost:8000/api |
97 | 93 | ``` |
98 | 94 |
|
99 | | -### Python API |
| 95 | +**Python API:** |
100 | 96 | ```python |
101 | 97 | from emseek.platform import Platform |
102 | 98 | import cfg |
103 | 99 |
|
104 | | -plat = Platform(cfg) |
105 | | -plat.init_agent() |
| 100 | +platform = Platform(cfg) |
| 101 | +platform.init_agent() |
106 | 102 |
|
107 | | -payload = {"text": "Segment EM image", "files": ["em.png"]} |
108 | | -for line in plat.query_unified(payload): |
109 | | - print(line.strip()) # JSON objects (step/final) |
| 103 | +payload = {"text": "Segment EM image", "files": ["samples/oblique_AgBiSb2S6-1cbf0237027e_supercell_24x20x1_dose30000_sampling0.1_iDPC_V3.png"]} |
| 104 | +for frame in platform.query_unified(payload): |
| 105 | + print(frame.strip()) # JSON objects per step/final |
110 | 106 | ``` |
111 | 107 |
|
112 | | ---- |
113 | | - |
114 | | -## 🔧 LLM/MLLM Generation Settings |
115 | | - |
116 | | -Configure token and temperature limits centrally in `cfg.py` (overridable via environment variables): |
117 | | - |
118 | | -- LLM_MAX_TOKENS (env: `LLM_MAX_TOKENS`, default: 10240) |
119 | | -- LLM_TEMPERATURE (env: `LLM_TEMPERATURE`, default: 1.0) |
120 | | -- MLLM_MAX_TOKENS (env: `MLLM_MAX_TOKENS`, default: 10240) |
121 | | -- MLLM_TEMPERATURE (env: `MLLM_TEMPERATURE`, default: 1.0) |
122 | | - |
123 | | -All internal `llm`/`mllm` calls respect these settings unless explicitly overridden at the call site. |
124 | | - |
125 | | ---- |
| 108 | +If uploads are rejected with HTTP 413, raise the proxy limit (`client_max_body_size` in Nginx) and optionally export `MAX_UPLOAD_MB` before starting Flask. |
126 | 109 |
|
127 | | -## 🧩 Core Agents |
128 | 110 |
|
129 | | -- **MaestroAgent** – Orchestration & planning |
130 | | -- **SegMentorAgent** – Segmentation + visual LLM explanation |
131 | | -- **CrystalForgeAgent** – EM→CIF retrieval with similarity scoring |
132 | | -- **MatProphetAgent** – MoE property prediction with uncertainty signals |
133 | | -- **ScholarSeekerAgent** – PaperQA with CORE/local fallback |
134 | | -- **AnalyzerHubAgent** – Unified tool routing (HyperSpy, py4DSTEM, pymatgen, etc.) |
135 | | -- **GuardianAgent** – Physical consistency & audit checks |
136 | | -- **ScribeAgent** – Structured final report |
| 111 | +## Configuration Surface |
| 112 | +All runtime knobs live in `cfg.py`: |
| 113 | +- Model identifiers (`LLM_MODEL`, `MLLM_MODEL`, `EMBEDDING_MODEL`). |
| 114 | +- Generation limits (`LLM_MAX_TOKENS`, `MLLM_TEMPERATURE`, etc.). |
| 115 | +- Data roots (`HISTORY_ROOT`, `CIF_LIB_DIR`, `PDF_FOLDER`). |
| 116 | +- Concurrency and streaming heartbeats. |
137 | 117 |
|
138 | | ---- |
| 118 | +Environment variables override module defaults, so ops teams can configure deployments without editing code. |
139 | 119 |
|
140 | | -## 📜 License |
141 | 120 |
|
142 | | -This project is licensed under the terms in the [LICENSE](./LICENSE) file. |
| 121 | +## Observability & Provenance |
| 122 | +- Every agent step logs JSONL traces and writes artefacts under `history/<user>/<session>/` for audit trails. |
| 123 | +- Guardian and Scribe attach provenance metadata, curated context, and uncertainty summaries to outputs. |
| 124 | +- Session JSON records persist the latest conversations per user, powering history recall in the web UI. |
143 | 125 |
|
144 | | ---- |
145 | 126 |
|
146 | | -## 📖 Citation |
| 127 | +## Contributing |
| 128 | +We welcome pull requests for new agents, analysis tools, retrieval pipelines, and documentation. Open an issue to discuss ideas or share reproducible bug reports. Please ensure new features include tests or runnable notebooks when applicable and respect existing logging and provenance patterns. |
147 | 129 |
|
148 | | -If EMSeek is useful for your work, please cite: |
| 130 | +## License & Citation |
| 131 | +This project is released under the [Apache License 2.0](LICENSE). |
149 | 132 |
|
150 | 133 | ```bibtex |
151 | 134 | @misc{chen2025emseek, |
|
0 commit comments