Commit 2d836d6
Drop nltk (#645)
# Drop NLTK dependency; serve stopwords statically
## Why
RedisVL only used NLTK for one thing: default stopword lists in
full-text
query building. Pulling in the whole `nltk` package for that has cost us
repeatedly — packaging/support friction and a recurring source of test
flakiness (parallel pytest-xdist workers racing on `nltk.download()`,
most
recently patched in #644).
The stopword lists are small, static, and change rarely. This PR bundles
them
directly and removes `nltk` entirely.
## What changed
- **New static data** — `redisvl/utils/stopwords.json` (33 languages,
~11k
words, ~120KB), extracted once from NLTK's `stopwords` corpus so the
lists
are byte-identical to what NLTK returned. **No behavior change** for any
supported language.
- **New loader** — `redisvl/utils/stopwords.py` exposes
`get_stopwords(language)`,
which lazily reads and caches the JSON via `importlib.resources`.
- **Rewired consumers** — `full_text_query_helper.py` and `query.py` now
call
`get_stopwords()` instead of lazily importing NLTK and downloading the
corpus.
The download/race/retry blocks are gone.
- **Removed vestigial imports** — `aggregate.py` had unused `nltk`
lazy-imports
(it already routes through the helper); deleted.
- **Dropped the dependency** — removed the `nltk` extra and its entry in
the
`all` extra from `pyproject.toml`.
- **Simplified tests** — deleted the `ensure_nltk_stopwords` session
fixture
from `tests/conftest.py`. The xdist download race it guarded against no
longer exists: there is no download.
- **Spellcheck** — added `stopwords.json` to codespell's `--skip` list
(it's a
multi-language word-list data file, not prose).
## Backward compatibility
The public API is unchanged. All existing usages still work:
- `stopwords="english"` (default), `"german"`, `"french"`, etc. — any of
the
33 bundled languages
- `stopwords={"custom", "set"}` / list / tuple
- `stopwords=None` (no filtering)
Error behavior is preserved: an unknown language string raises
`ValueError`
(now with the list of available languages), and a
non-string/non-collection
raises `TypeError`.
The only user-visible change: `pip install redisvl[nltk]` no longer
resolves
(the extra was removed). Worth a changelog note.
## Verification
- All stopword / query / aggregation / hybrid unit tests pass (945
passed);
`german` still yields `der`/`die`/`und`, invalid language →
`ValueError`,
invalid type → `TypeError`.
- Confirmed `stopwords.json` ships in the built wheel
(`redisvl/utils/stopwords.json` present in `redisvl-*.whl`).
- pre-commit (format, isort, mypy, codespell) passes.
## Downstream follow-up (separate, not in this PR)
`redis-ai-resources` has two notebooks
(`python-recipes/vector-search/01_redisvl.ipynb`,
`02_hybrid_search.ipynb`) that carry `nltk` in their `%pip install`
lines and
one stale markdown reference. Nothing breaks (they never `import nltk`),
but
the `nltk` install is now dead weight. That cleanup should land
**after** this
release and bump the notebooks' `redisvl` floor to the version that
bundles
stopwords.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches default full-text tokenization for all string `stopwords`
language codes; lists are meant to match NLTK but any drift or packaging
omission of `stopwords.json` would change search behavior. Removing the
`nltk` extra is a breaking install change for users who relied on it.
>
> **Overview**
> **Removes the `nltk` optional dependency** and ships default full-text
stopword lists as bundled `redisvl/utils/stopwords.json` (~33
languages), loaded via new `get_stopwords()` in
`redisvl/utils/stopwords.py`.
>
> **Full-text query paths** (`query.py`, `full_text_query_helper.py`)
now call `get_stopwords()` instead of lazy NLTK imports and runtime
`nltk.download()`; unused NLTK imports in `aggregate.py` are removed.
>
> **Packaging and CI:** `nltk` is dropped from `pyproject.toml`
extras/`all` and `uv.lock`; codespell skips `stopwords.json`. The pytest
session fixture that pre-downloaded NLTK stopwords for xdist is deleted
from `tests/conftest.py`.
>
> Public stopword API behavior for supported languages and custom sets
is intended to stay the same; `pip install redisvl[nltk]` no longer
applies.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
23a8c335ea20a879319cdccababa91b0cabe5be6. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>1 parent 36f7612 commit 2d836d6
9 files changed
Lines changed: 11205 additions & 105 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
44 | 43 | | |
45 | 44 | | |
46 | 45 | | |
| |||
62 | 61 | | |
63 | 62 | | |
64 | 63 | | |
65 | | - | |
66 | 64 | | |
67 | 65 | | |
68 | 66 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | 11 | | |
16 | 12 | | |
17 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | | - | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
| |||
1406 | 1404 | | |
1407 | 1405 | | |
1408 | 1406 | | |
1409 | | - | |
1410 | | - | |
1411 | | - | |
1412 | | - | |
1413 | | - | |
1414 | | - | |
1415 | | - | |
1416 | | - | |
1417 | | - | |
1418 | | - | |
1419 | | - | |
1420 | | - | |
1421 | | - | |
1422 | | - | |
1423 | | - | |
| 1407 | + | |
1424 | 1408 | | |
1425 | 1409 | | |
1426 | 1410 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | 4 | | |
8 | 5 | | |
9 | 6 | | |
| |||
88 | 85 | | |
89 | 86 | | |
90 | 87 | | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
| 88 | + | |
106 | 89 | | |
107 | 90 | | |
108 | 91 | | |
| |||
0 commit comments