gsas2-query 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. gsas2_query-0.3.0/.env.example +45 -0
  2. gsas2_query-0.3.0/.github/workflows/ingest.yml +95 -0
  3. gsas2_query-0.3.0/.github/workflows/publish.yml +29 -0
  4. gsas2_query-0.3.0/.gitignore +27 -0
  5. gsas2_query-0.3.0/PKG-INFO +333 -0
  6. gsas2_query-0.3.0/README.md +298 -0
  7. gsas2_query-0.3.0/app.py +4 -0
  8. gsas2_query-0.3.0/cli.py +6 -0
  9. gsas2_query-0.3.0/conda-recipe/meta.yaml +53 -0
  10. gsas2_query-0.3.0/evaluation/EVALUATION_CASE_STUDY.md +234 -0
  11. gsas2_query-0.3.0/evaluation/eval_results_bge.json +884 -0
  12. gsas2_query-0.3.0/evaluation/questions.json +356 -0
  13. gsas2_query-0.3.0/evaluation/run_eval.py +157 -0
  14. gsas2_query-0.3.0/gsas_query/__init__.py +20 -0
  15. gsas2_query-0.3.0/gsas_query/_embed.py +43 -0
  16. gsas2_query-0.3.0/gsas_query/_paths.py +25 -0
  17. gsas2_query-0.3.0/gsas_query/_web.py +16 -0
  18. gsas2_query-0.3.0/gsas_query/app.py +154 -0
  19. gsas2_query-0.3.0/gsas_query/cli.py +215 -0
  20. gsas2_query-0.3.0/gsas_query/gui.py +690 -0
  21. gsas2_query-0.3.0/gsas_query/ingest.py +290 -0
  22. gsas2_query-0.3.0/gsas_query/rag.py +390 -0
  23. gsas2_query-0.3.0/gsas_query/sources.py +482 -0
  24. gsas2_query-0.3.0/gsas_query/static/index.html +533 -0
  25. gsas2_query-0.3.0/gsas_query/wordcount.py +78 -0
  26. gsas2_query-0.3.0/gui.py +5 -0
  27. gsas2_query-0.3.0/ingest.py +13 -0
  28. gsas2_query-0.3.0/main.py +4 -0
  29. gsas2_query-0.3.0/pyproject.toml +52 -0
  30. gsas2_query-0.3.0/rag.py +2 -0
  31. gsas2_query-0.3.0/requirements.txt +23 -0
  32. gsas2_query-0.3.0/sources.py +2 -0
  33. gsas2_query-0.3.0/static/index.html +506 -0
  34. gsas2_query-0.3.0/wordcount.py +5 -0
@@ -0,0 +1,45 @@
1
+ # ── LLM Backend ──────────────────────────────────────────────────────────────
2
+ # Backend selection precedence:
3
+ # 1. LLM_BACKEND env var (if set) always takes effect.
4
+ # 2. If LLM_BACKEND is NOT set and llama-cpp-python is installed, llama_cpp
5
+ # is selected automatically.
6
+ # 3. If neither of the above applies, "ollama" is the default.
7
+ #
8
+ # "ollama" — fully local, free, no data leaves the network
9
+ # "llama_cpp" — in-process llama-cpp-python (auto-selected if installed)
10
+ # "anthropic" — Anthropic Claude API (requires ANTHROPIC_API_KEY below)
11
+ # "retrieval" — no LLM; returns raw matched chunks (offline / testing)
12
+ LLM_BACKEND=ollama
13
+
14
+ # ── llama-cpp-python settings (used when llama_cpp backend is active) ─────────
15
+ # Install: conda install -c conda-forge llama-cpp-python
16
+ # or: pip install "gsas-query[llama_cpp]"
17
+ # Download a GGUF model from Hugging Face, then set the path below.
18
+ # LLAMA_CPP_MODEL=/path/to/model.gguf
19
+ # LLAMA_CPP_N_CTX=4096 # context window size (tokens)
20
+ # LLAMA_CPP_MAX_TOKENS=1500 # maximum tokens to generate
21
+
22
+ # ── Ollama settings (used when LLM_BACKEND=ollama) ───────────────────────────
23
+ # Install Ollama: https://ollama.com
24
+ # Pull a model: ollama pull llama3
25
+ # Recommended models (balance of quality and speed):
26
+ # llama3 — 8B params, good quality, ~8 GB RAM
27
+ # llama3:70b — 70B params, excellent quality, ~48 GB RAM / GPU
28
+ # mistral — fast, ~5 GB RAM
29
+ # phi3 — lightweight, ~4 GB RAM
30
+ OLLAMA_URL=http://localhost:11434
31
+ OLLAMA_MODEL=llama3
32
+
33
+ # ── Anthropic API (only needed if LLM_BACKEND=anthropic) ─────────────────────
34
+ # ANTHROPIC_API_KEY=sk-ant-...
35
+ # ANTHROPIC_MODEL=claude-sonnet-4-6
36
+
37
+ # ── Server settings ───────────────────────────────────────────────────────────
38
+ # Comma-separated origins allowed for CORS. Use "*" to allow all.
39
+ ALLOWED_ORIGINS=*
40
+
41
+ # Requests per minute per IP (0 to disable)
42
+ RATE_LIMIT_RPM=30
43
+
44
+ # Secret key required for POST /ingest (leave blank to disable auth on that route)
45
+ ADMIN_KEY=
@@ -0,0 +1,95 @@
1
+ name: Build ChromaDB index
2
+ # This creates a index to the GSAS-II documents and places it as
3
+ # downloadable release file under the name
4
+ # https://github.com/<owner>/<repo>/releases/download/latest-chroma-db/chroma_db_latest.zip
5
+ # (as well as a artifact)
6
+
7
+ on:
8
+ workflow_dispatch:
9
+ inputs:
10
+ include_book:
11
+ description: "Include Book HTML contents"
12
+ type: boolean
13
+ default: true
14
+ include_manual:
15
+ description: "Include Programmers' Manual"
16
+ type: boolean
17
+ default: true
18
+
19
+ jobs:
20
+ ingest:
21
+ runs-on: ubuntu-latest
22
+ timeout-minutes: 45
23
+ permissions:
24
+ #contents: read
25
+ contents: write # changed: needed to create/update release/tag
26
+
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.12"
33
+
34
+ - name: Cache pip
35
+ uses: actions/cache@v4
36
+ with:
37
+ path: ~/.cache/pip
38
+ key: pip-ingest-${{ hashFiles('pyproject.toml') }}
39
+
40
+ # Embeddings use chromadb's built-in ONNX runtime (all-MiniLM-L6-v2)
41
+ # so PyTorch and sentence-transformers are not required.
42
+ - name: Install gsas_query package
43
+ run: pip install -e ".[dev]"
44
+
45
+ - name: Build ChromaDB index (HTML only, contents by options)
46
+ env:
47
+ TOKENIZERS_PARALLELISM: "false"
48
+ OMP_NUM_THREADS: "1"
49
+ GSAS_QUERY_DATA_DIR: ${{ github.workspace }}/ci_data
50
+ run: |
51
+ cmd="python ingest.py --html-only"
52
+ if [ "${{ inputs.include_book }}" = "true" ]; then
53
+ cmd="$cmd --book"
54
+ fi
55
+ if [ "${{ inputs.include_manual }}" = "true" ]; then
56
+ cmd="$cmd --manual"
57
+ fi
58
+ echo "Running: $cmd"
59
+ eval "$cmd"
60
+
61
+ - name: Show index stats
62
+ env:
63
+ GSAS_QUERY_DATA_DIR: ${{ github.workspace }}/ci_data
64
+ run: |
65
+ python -c "
66
+ import chromadb, os
67
+ path = os.path.join(os.environ['GSAS_QUERY_DATA_DIR'], 'chroma_db')
68
+ c = chromadb.PersistentClient(path=path)
69
+ col = c.get_collection('gsasii_docs')
70
+ print(f'Chunks in index: {col.count()}')
71
+ "
72
+
73
+ - name: Upload chroma_db artifact
74
+ uses: actions/upload-artifact@v4
75
+ with:
76
+ name: chroma_db
77
+ path: ci_data/chroma_db/
78
+ retention-days: 90
79
+
80
+ - name: Package chroma_db as zip
81
+ run: |
82
+ cd ci_data
83
+ zip -r ../chroma_db_latest.zip chroma_db
84
+
85
+ - name: Create/Update stable release and upload asset
86
+ uses: softprops/action-gh-release@v2
87
+ with:
88
+ tag_name: latest-chroma-db
89
+ name: Latest ChromaDB Index
90
+ body: Auto-updated ChromaDB index artifact from ingest workflow.
91
+ files: chroma_db_latest.zip
92
+ overwrite_files: true
93
+ make_latest: true
94
+ env:
95
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read # required for actions/checkout
13
+ id-token: write # required for OIDC trusted publishing
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+
22
+ - name: Install build
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,27 @@
1
+ # Environment
2
+ .env
3
+ *.env.local
4
+
5
+ # Vector store (rebuild with ingest.py — do not commit)
6
+ chroma_db/
7
+
8
+ # Python
9
+ __pycache__/
10
+ *.py[cod]
11
+ *.pyo
12
+ .venv/
13
+ venv/
14
+ env/
15
+ *.egg-info/
16
+ dist/
17
+ build/
18
+
19
+ # macOS
20
+ .DS_Store
21
+
22
+ # Downloaded PDFs (re-fetched during ingestion)
23
+ *.pdf
24
+ manuscript/
25
+
26
+ # Internal admin paperwork (disclosure drafts etc.)
27
+ release/
@@ -0,0 +1,333 @@
1
+ Metadata-Version: 2.5
2
+ Name: gsas2-query
3
+ Version: 0.3.0
4
+ Summary: Query-GSAS-II Documentation Assistant — semantic search and AI answers over GSAS-II tutorials and help pages
5
+ Project-URL: Repository, https://github.com/AdvancedPhotonSource/Query-GSAS-II
6
+ Author-email: Pawan Tripathi <ptripathi@anl.gov>, Brian Toby <toby@anl.gov>
7
+ License: MIT
8
+ Keywords: crystallography,documentation,gsas,rag,xrd
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: beautifulsoup4>=4.12.0
16
+ Requires-Dist: chromadb>=0.5.0
17
+ Requires-Dist: fastapi>=0.110.0
18
+ Requires-Dist: fastembed>=0.3.0
19
+ Requires-Dist: httpx>=0.27.0
20
+ Requires-Dist: lxml>=5.0.0
21
+ Requires-Dist: pydantic>=2.0.0
22
+ Requires-Dist: pypdf>=4.0.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+ Requires-Dist: requests>=2.31.0
25
+ Requires-Dist: uvicorn[standard]>=0.29.0
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.25.0; extra == 'anthropic'
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == 'dev'
30
+ Provides-Extra: gui
31
+ Requires-Dist: wxpython>=4.2.0; extra == 'gui'
32
+ Provides-Extra: llama-cpp
33
+ Requires-Dist: llama-cpp-python>=0.2.0; extra == 'llama-cpp'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # gsas2-query — GSAS-II Documentation Assistant
37
+
38
+ Semantic search + AI answers over the full GSAS-II documentation set:
39
+ **129 HTML pages** (home, help, and all 62 tutorials) plus the
40
+ **Programmer's Guide** and **Powder Crystallography** book PDFs.
41
+
42
+ Answers include **inline citations** — every `[N]` in the response is a
43
+ clickable link to the exact documentation section that supported that sentence.
44
+
45
+ All embedding and retrieval runs on your machine — no data is sent externally
46
+ unless you explicitly choose the Anthropic API backend.
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ ### pip
53
+
54
+ ```bash
55
+ pip install gsas2-query
56
+ ```
57
+
58
+ Or install directly from source:
59
+
60
+ ```bash
61
+ pip install git+https://github.com/AdvancedPhotonSource/Query-GSAS-II.git
62
+ ```
63
+
64
+ ### conda
65
+
66
+ ```bash
67
+ conda install -c conda-forge gsas2-query
68
+ ```
69
+
70
+ ### Into an existing GSAS-II environment
71
+
72
+ ```bash
73
+ # Activate the GSAS-II conda environment first, then:
74
+ pip install gsas2-query
75
+ ```
76
+
77
+ ### Development / editable install
78
+
79
+ ```bash
80
+ git clone https://github.com/AdvancedPhotonSource/Query-GSAS-II.git
81
+ cd Query-GSAS-II
82
+ pip install -e ".[dev]"
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Ollama — free local LLM (recommended when llama.cpp is not installed)
88
+
89
+ ```bash
90
+ brew install ollama # macOS; see https://ollama.com for other platforms
91
+ ollama serve & # start the local server
92
+ ollama pull llama3 # ~5 GB one-time download
93
+ ```
94
+
95
+ Other model options: `llama3:70b` (better quality, ~40 GB), `mistral` (faster, ~4 GB).
96
+
97
+ ---
98
+
99
+ ## llama-cpp-python — in-process local LLM (auto-selected when installed)
100
+
101
+ `llama-cpp-python` runs a GGUF model directly inside the Python process — no
102
+ separate server required. It is cross-platform and available from conda-forge.
103
+
104
+ When `llama-cpp-python` is importable, gsas2-query selects it **automatically**
105
+ without any `LLM_BACKEND` setting.
106
+
107
+ ### Install
108
+
109
+ ```bash
110
+ conda install -c conda-forge llama-cpp-python # recommended
111
+ # or:
112
+ pip install "gsas2-query[llama_cpp]"
113
+ ```
114
+
115
+ ### Download a GGUF model
116
+
117
+ Download any GGUF-format model from Hugging Face, for example:
118
+
119
+ ```bash
120
+ # Llama 3.1 8B (Q4_K_M quantisation, ~5 GB):
121
+ wget https://huggingface.co/bartowski/Meta-Llama-3.1-8B-Instruct-GGUF/resolve/main/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf
122
+ ```
123
+
124
+ ### Configure
125
+
126
+ Set the model path in your `.env` or environment:
127
+
128
+ ```env
129
+ LLAMA_CPP_MODEL=/path/to/Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf
130
+ # Optional tuning:
131
+ # LLAMA_CPP_N_CTX=4096 # context window (default: 4096)
132
+ # LLAMA_CPP_MAX_TOKENS=1500 # max tokens to generate (default: 1500)
133
+ ```
134
+
135
+ ---
136
+
137
+ ## First-time setup — index the documentation
138
+
139
+ Run once, or again when the docs are updated. Fetches ~130 web pages and 2 PDFs,
140
+ embeds everything locally. Takes ~10–20 minutes.
141
+
142
+ By default the index is stored in `~/.GSASII/gsas_query/chroma_db`
143
+ (see [User data directory](#userdatadirectory) for details).
144
+
145
+ ```bash
146
+ gsas2-query --setup # all sources (HTML + PDFs)
147
+ gsas2-query --setup --html-only # skip PDFs, faster (~5 min)
148
+ gsas2-query --setup --reset # drop index and rebuild from scratch
149
+ ```
150
+
151
+ HTML-only index is 21 Mb. With GSAS-II Programmer's Guide, 41 Mb; with
152
+ textbook as well, 53 Mb.
153
+
154
+ ---
155
+
156
+ ## Usage
157
+
158
+ ### Command-line — single question
159
+
160
+ ```bash
161
+ gsas2-query "How do I set up a sequential refinement?"
162
+ gsas2-query "What parameters control the background in Rietveld?"
163
+ gsas2-query "How do I export a CIF for publication?"
164
+ ```
165
+
166
+ ### Command-line — interactive REPL
167
+
168
+ Multi-turn conversation that remembers previous questions in the session.
169
+
170
+ ```bash
171
+ gsas2-query
172
+ ```
173
+
174
+ ```
175
+ GSAS-II Documentation Assistant
176
+ ════════════════════════════════════════════════════════════════════════════════
177
+
178
+ Knowledge base: 3,847 indexed chunks.
179
+ LLM backend: ollama
180
+ Type your question and press Enter. 'clear' resets history, 'quit' exits.
181
+
182
+ ────────────────────────────────────────────────────────────────────────────────
183
+ You: How do I constrain lattice parameters?
184
+ Thinking…
185
+ Assistant: To constrain lattice parameters in GSAS-II, open the Constraints
186
+ tab in the Phase panel [1]…
187
+
188
+ Sources:
189
+ [94%] Help: Phase General › Constraints
190
+ https://advancedphotonsource.github.io/GSAS-II-tutorials/help/phasegeneral.html
191
+ ```
192
+
193
+ Commands inside the REPL: `clear` (reset history), `quit` / `exit` (exit).
194
+
195
+ ### Desktop GUI
196
+
197
+ Opens a standalone floating dialog — stays open while you work in GSAS-II.
198
+
199
+ ```bash
200
+ gsas2-query --gui
201
+ ```
202
+
203
+ ### Embed in GSAS-II Help menu
204
+
205
+ Add one call to the GSAS-II menu handler (e.g. in `GSASIIctrl.py`):
206
+
207
+ ```python
208
+ def OnDocAssistant(self, event):
209
+ try:
210
+ from gsas_query.gui import show_assistant
211
+ show_assistant(self) # self = GSAS-II main frame
212
+ except ImportError:
213
+ wx.MessageBox(
214
+ "GSAS-II Assistant not installed.\n"
215
+ "Run: pip install gsas2-query",
216
+ "Not available"
217
+ )
218
+ ```
219
+
220
+ `show_assistant()` is idempotent — calling it a second time raises the existing
221
+ window rather than opening a duplicate.
222
+
223
+ ### Web UI
224
+
225
+ ```bash
226
+ gsas2-query-web # serves on 0.0.0.0:8000
227
+ HOST=127.0.0.1 PORT=8765 gsas2-query-web
228
+ ```
229
+
230
+ Then open `http://localhost:8000` in a browser. The web UI shows inline citations
231
+ as clickable superscript links and source chips below each answer.
232
+
233
+ ---
234
+
235
+ ## CLI flags reference
236
+
237
+ | Flag | Description |
238
+ |---|---|
239
+ | `--setup` | Index all documentation sources |
240
+ | `--setup --reset` | Drop the existing index and rebuild |
241
+ | `--setup --html-only` | Index HTML only, skip PDFs |
242
+ | `--gui` | Open the wxPython desktop assistant |
243
+ | `--backend ollama\|anthropic\|retrieval\|llama_cpp` | Override `LLM_BACKEND` env var |
244
+ | `--model <name>` | Override OLLAMA_MODEL, ANTHROPIC_MODEL, or LLAMA_CPP_MODEL |
245
+ | `--stats` | Show chunk count, backend, and DB path |
246
+
247
+ ---
248
+
249
+ ## LLM backend configuration
250
+
251
+ Backend selection precedence:
252
+
253
+ 1. `LLM_BACKEND` env var (or `--backend` CLI flag) **always takes effect when set**.
254
+ 2. If `LLM_BACKEND` is **not set** and `llama-cpp-python` is importable, `llama_cpp` is selected automatically.
255
+ 3. Otherwise the default is `ollama`.
256
+
257
+ | Backend | Config | Notes |
258
+ |---|---|---|
259
+ | `llama_cpp` (auto) | `LLAMA_CPP_MODEL=/path/to/model.gguf` | In-process, no daemon needed; auto-selected when llama-cpp-python is installed |
260
+ | `ollama` (default) | `OLLAMA_MODEL=llama3` | Free, fully local — no data leaves the network |
261
+ | `anthropic` | `ANTHROPIC_API_KEY=sk-ant-…` | Better answers; queries sent to Anthropic |
262
+ | `retrieval` | — | No LLM — returns raw matched chunks; useful offline or for testing |
263
+
264
+ ```bash
265
+ gsas2-query --backend retrieval "What is Le Bail extraction?"
266
+ gsas2-query --backend ollama --model mistral "How do I index peaks?"
267
+ gsas2-query --backend llama_cpp --model /path/to/model.gguf "How do I refine a structure?"
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Inline citations
273
+
274
+ When using Ollama, llama_cpp, or Anthropic backends, answers contain `[N]` markers inline.
275
+ In the **web UI** these render as clickable superscript links opening the exact
276
+ source section. In the **CLI**, source URLs are listed below the answer with
277
+ relevance scores.
278
+
279
+ ---
280
+
281
+ ## Doc sources
282
+
283
+ | Category | Count |
284
+ |---|---|
285
+ | Home / installation pages | 22 |
286
+ | Help pages (all sections) | 42 |
287
+ | Tutorials | 62 |
288
+ | Programmer's Guide (PDF, readthedocs) | 1 |
289
+ | Powder Crystallography book (PDF, auto-fetches latest release) | 1 |
290
+ | **Total** | **128 sources** |
291
+
292
+ All HTML sources are fetched from
293
+ `https://advancedphotonsource.github.io/GSAS-II-tutorials/`.
294
+ The book PDF is fetched from the latest GitHub release of
295
+ [briantoby/PowderCrystallography](https://github.com/briantoby/PowderCrystallography/releases).
296
+
297
+ ---
298
+
299
+ ## Re-indexing when docs update
300
+
301
+ ```bash
302
+ gsas2-query --setup --reset
303
+ ```
304
+
305
+ Or trigger via the web API (requires `ADMIN_KEY` set in `.env`):
306
+
307
+ ```bash
308
+ curl -X POST http://localhost:8000/ingest -H "X-Admin-Key: your-key"
309
+ ```
310
+
311
+ ---
312
+
313
+ ## Security and deployment notes
314
+
315
+ - All embeddings and vector search run locally (sentence-transformers, ChromaDB).
316
+ - Ollama runs entirely on-premises — no queries leave the network.
317
+ - The `anthropic` backend sends question text and retrieved doc chunks to Anthropic.
318
+ Do not use it in air-gapped or data-sensitive environments.
319
+ - The web server applies per-IP rate limiting (default 30 req/min, configurable
320
+ via `RATE_LIMIT_RPM` in `.env`).
321
+ - The `/ingest` endpoint is protected by `X-Admin-Key`; leave `ADMIN_KEY` blank
322
+ to disable remote re-indexing.
323
+
324
+ ---
325
+
326
+ ## User data directory
327
+
328
+ The ChromaDB index is stored at `~/.GSASII/gsas_query/chroma_db` by default.
329
+ Override with the `GSAS_QUERY_DATA_DIR` environment variable:
330
+
331
+ ```bash
332
+ GSAS_QUERY_DATA_DIR=/data/gsas_query gsas2-query --setup
333
+ ```