Skip to content

Commit 3464eb9

Browse files
Merge branch 'dev'
2 parents 0ee286d + 3e5834a commit 3464eb9

22 files changed

Lines changed: 925 additions & 373 deletions

README.md

Lines changed: 30 additions & 26 deletions
Large diffs are not rendered by default.

bumpver.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
[bumpver]
3-
current_version = "5.0.1"
3+
current_version = "5.1.0"
44
version_pattern = "MAJOR.MINOR.PATCH"
55
commit_message = "bump version {old_version} -> {new_version}"
66
tag_message = "{new_version}"

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-e .
2+
setuptools
23
sphinx
34
pydata-sphinx-theme
45
myst-parser

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def setup(app):
3838
project = "wdoc"
3939
copyright = "2025, thiswillbeyourgithub"
4040
author = "thiswillbeyourgithub"
41-
release = "5.0.1"
41+
release = "5.1.0"
4242

4343
# -- General configuration ---------------------------------------------------
4444
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

setup.py

Lines changed: 88 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -18,47 +18,17 @@ def run(self):
1818
except Exception as err:
1919
print(f"Error when installing playwright: '{err}'")
2020

21-
# do pip install --user -U --pre yt-dlp
21+
# Only refresh yt-dlp to its pre-release if the user actually installed
22+
# it (i.e. picked the [youtube] extra). This keeps yt-dlp optional while
23+
# still letting users track YouTube extractor fixes that land in
24+
# pre-releases before the stable pin catches up.
2225
try:
23-
subprocess.check_call(
24-
[
25-
sys.executable,
26-
"-m",
27-
]
28-
+ pip
29-
+ [
30-
"install",
31-
"--user",
32-
"-U",
33-
"--pre",
34-
"yt-dlp",
35-
]
36-
)
37-
except Exception as err:
38-
print(f"Error when installing yt-dlp pre-release: '{err}'")
39-
40-
# do "python -m pip install -U git+https://github.com/ahupp/python-magic/
41-
# see https://github.com/ahupp/python-magic/issues/261
42-
try:
43-
subprocess.check_call(
44-
[
45-
sys.executable,
46-
"-m",
47-
]
48-
+ pip
49-
+ [
50-
"install",
51-
"-U",
52-
"git+https://github.com/ahupp/python-magic/",
53-
],
54-
)
55-
except Exception as err:
56-
print(f"Error when pip updating python-magic from git: '{err}'")
26+
import yt_dlp # noqa: F401
5727

58-
# Install audioop-lts only for Python 3.13+
59-
# audioop was removed in Python 3.13, and pydub needs it
60-
# See https://github.com/jiaaro/pydub/issues/815
61-
if sys.version_info >= (3, 13):
28+
has_yt_dlp = True
29+
except ImportError:
30+
has_yt_dlp = False
31+
if has_yt_dlp:
6232
try:
6333
subprocess.check_call(
6434
[
@@ -69,27 +39,41 @@ def run(self):
6939
+ [
7040
"install",
7141
"-U",
72-
"audioop-lts>=0.2.2",
42+
"--pre",
43+
"yt-dlp",
7344
]
7445
)
7546
except Exception as err:
76-
print(f"Error when installing audioop-lts for Python 3.13+: '{err}'")
47+
print(f"Error when installing yt-dlp pre-release: '{err}'")
7748

78-
# do "openparse-download"
49+
# Only run "openparse-download" if openparse is actually installed.
50+
# openparse[ml] is in install_requires today, but guard anyway so this
51+
# post-install does not crash on a stripped-down install.
7952
try:
80-
subprocess.check_call(
81-
["openparse-download"],
82-
)
83-
except Exception as err:
84-
print(
85-
"Error when trying to run 'openparse-download' to download"
86-
f" weights for deep learning based table detection : '{err}'"
87-
"\nBy default wdoc still uses pymupdf via openparse so it "
88-
"shouldn't matter too much.\n"
89-
"For more: see https://github.com/Filimoa/open-parse/"
90-
)
53+
import openparse # noqa: F401
54+
55+
has_openparse = True
56+
except ImportError:
57+
has_openparse = False
58+
if has_openparse:
59+
try:
60+
subprocess.check_call(
61+
["openparse-download"],
62+
)
63+
except Exception as err:
64+
print(
65+
"Error when trying to run 'openparse-download' to download"
66+
f" weights for deep learning based table detection : '{err}'"
67+
"\nBy default wdoc still uses pymupdf via openparse so it "
68+
"shouldn't matter too much.\n"
69+
"For more: see https://github.com/Filimoa/open-parse/"
70+
)
9171

9272
# do "import nltk ; nltk.download('punkt_tab')"
73+
# Likely redundant: `unstructured` (our only nltk consumer, via
74+
# unstructured.nlp.tokenize) already lazily runs nltk.download("punkt_tab")
75+
# on first use. Kept as a safety net so the download happens at install
76+
# time rather than on the first parse of an office document.
9377
try:
9478
import nltk
9579

@@ -145,7 +129,7 @@ def run(self):
145129

146130
setup(
147131
name="wdoc",
148-
version="5.0.1",
132+
version="5.1.0",
149133
description="A perfect AI powered RAG for document query and summary. Supports ~all LLM and ~all filetypes (url, pdf, epub, youtube (incl playlist), audio, anki, md, docx, pptx, or any combination!)",
150134
long_description=long_description,
151135
long_description_content_type="text/markdown",
@@ -184,18 +168,19 @@ def run(self):
184168
},
185169
python_requires=">=3.11",
186170
install_requires=[
171+
# Core RAG engine
187172
"sqlalchemy>=2.0.32",
188173
"beautifulsoup4>=4.12.3",
189174
"fire>=0.6.0",
190175
"ftfy>=6.2.0",
191176
"joblib>=1.4.2",
192-
"langchain>=1.2.0",
193-
"langchain-classic>=1.0.0",
194-
"langchain-community>=0.3.30",
195-
"langchain-openai>=0.3.34",
196-
"langchain-litellm>=0.3.5",
177+
"langchain>=1.3.0",
178+
"langchain-classic>=1.0.7",
179+
"langchain-community>=0.4.1",
180+
"langchain-openai>=1.2.1",
181+
"langchain-litellm>=0.6.5",
197182
"langfuse>=3.6.1", # for observability
198-
"litellm>=v1.78.2",
183+
"litellm>=v1.84.0",
199184
"nest_asyncio>=1.6.0", # needed to fix ollama 'event loop closed' error thanks to https://github.com/BerriAI/litellm/pull/7625/files
200185
"chonkie[all]>=1.4.0", # chonkie is for the semantic embeddings
201186
"chonkie[semantic]>=1.4.0",
@@ -211,7 +196,6 @@ def run(self):
211196
"loguru >= 0.7.2",
212197
"grandalf >= 0.8", # to print ascii graph
213198
"lazy-import >= 0.2.2",
214-
"py_ankiconnect >= 1.1.2", # DIY wrapper to tell anki to sync just in case
215199
"scikit-learn >= 1.5.1", # for semantic reordering
216200
"scipy >= 1.13.1", # for semantic reordering
217201
# 'python-magic >= 0.4.27', # for detecting file type # made optional as it can help infer the filetype, and 0.4.28 is necessary for the pipe feature.
@@ -220,47 +204,53 @@ def run(self):
220204
"nltk>=3.9.2", # needed for punkt_tab download in post-install
221205
"blake3>=1.0.8", # faster than sha256
222206
"pandas >= 2.3.3",
223-
# some loaders are included by default:
224-
"playwright >= 1.45.0", # for online_media and urls
207+
"trio >= 0.31.0", # for some reason older versions of trio, when present are used and cause issues on python 3.11: https://github.com/python-trio/trio/issues/2317
208+
"unstructured >= 0.18.15", # base package only, used by pdf loader for clean_extra_whitespace. The heavy [all-docs] extra is in [office].
209+
# PDF loading (default, since pdf is the most common filetype)
225210
"openparse[ml] >= 0.5.7", # pdf with table support
226-
# youtube
227-
"yt-dlp >= 2025.09.26", # we actually need to install yt-dlp here otherwise readthedocs crashes. Note that in the postinstall script above it will be reinstalled using the master branch
228-
"youtube-transcript-api >= 0.6.2",
229-
# "pytube >= 15.0.0",
230-
# url
231-
"tldextract>=5.1.2",
211+
"pdfminer.six >= 20231228",
212+
"pillow_heif >= 0.16.0",
213+
"pypdfium2 >= 4.30.0",
214+
"pymupdf >= 1.24.5",
215+
"pdfplumber >= 0.11.1",
216+
"pdf2image >= 1.17.0",
217+
# URL / web loading (default, since urls are the most common filetype)
218+
"playwright >= 1.45.0", # for online_media and urls
232219
"goose3 >= 3.1.20",
220+
"tldextract>=5.1.2",
233221
# online search via 'filetype=web'
234222
"ddgs >= 9.6.0",
235223
"duckduckgo-search >= 8.1.1",
236-
# audio/video transcription
237-
"deepgram-sdk >= 3.2.7",
238-
"httpx >= 0.27.0", # to increase deepgram timeout
239-
"pydub >= 0.25.1", # extracting audio from local video
240-
"ffmpeg-python >= 0.2.0", # extracting audio from local video
241-
"torchaudio >= 2.8.0", # silence removal from audio
242-
"trio >= 0.31.0", # for some reason older versions of trio, when present are used and cause issues on python 3.11: https://github.com/python-trio/trio/issues/2317
243-
# many file formats
244-
"unstructured[all-docs]>=0.18.15",
245224
],
246225
extras_require={
247-
"full": [
248-
# Loaders:
249-
# pdf
250-
"pdfminer.six >= 20231228",
251-
"pillow_heif >= 0.16.0",
252-
"pypdfium2 >= 4.30.0",
253-
"pymupdf >= 1.24.5",
254-
"pdfplumber >= 0.11.1",
255-
"pdf2image >= 1.17.0",
256-
# word documents
257-
"docx2txt >= 0.8",
258-
# epub
259-
"pandoc >= 2.4",
260-
# anki
226+
"youtube": [
227+
"yt-dlp >= 2026.3.17", # NOTE: the postinstall script reinstalls yt-dlp from the master branch
228+
"youtube-transcript-api >= 1.2.4",
229+
# "pytube >= 15.0.0",
230+
],
231+
"audio": [
232+
# audio/video transcription
233+
"deepgram-sdk >= 3.2.7",
234+
"httpx >= 0.27.0", # to increase deepgram timeout
235+
"pydub >= 0.25.1", # extracting audio from local video
236+
# audioop was removed in stdlib in Python 3.13 and pydub needs it
237+
# See https://github.com/jiaaro/pydub/issues/815
238+
"audioop-lts>=0.2.2; python_version>='3.13'",
239+
"ffmpeg-python >= 0.2.0", # extracting audio from local video
240+
"torchaudio >= 2.8.0", # silence removal from audio
241+
],
242+
"anki": [
261243
"ankipandas>=0.3.15",
262-
# logseq files (I'm the dev behind it)
263-
"LogseqMarkdownParser >= 3.3",
244+
"py_ankiconnect >= 1.1.2", # DIY wrapper to tell anki to sync just in case
245+
],
246+
"office": [
247+
# word, powerpoint, epub and other office formats
248+
"unstructured[all-docs]>=0.18.15",
249+
"docx2txt >= 0.8",
250+
"pandoc >= 2.4", # for epub
251+
],
252+
"logseq": [
253+
"LogseqMarkdownParser >= 3.3", # I'm the dev behind it
264254
],
265255
"fasttext": [
266256
# buggy in windows so optional: https://github.com/zafercavdar/fasttext-langdetect/issues/14
@@ -271,6 +261,10 @@ def run(self):
271261
# sudo apt install build-essential libpoppler-cpp-dev pkg-config python3-dev
272262
"pdftotext >= 2.2.2",
273263
],
264+
"full": [
265+
# aggregates all loader extras (self-reference requires pip >= 21.2)
266+
"wdoc[youtube,audio,anki,office,logseq]",
267+
],
274268
"dev": [
275269
"ruff >= 0.14.1",
276270
# "isort >= 6.0.0",

tests/run_all_tests.sh

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,38 @@ set -e
44
set -o pipefail
55
set -u
66

7+
# Crash early if a model that will be used requires an API key we don't have.
8+
# Defaults mirror those in test_wdoc.py and wdoc/utils/env.py.
9+
_ALL_TEST_MODELS=(
10+
"${WDOC_TEST_OPENAI_MODEL:-gpt-4o}"
11+
"${WDOC_TEST_OPENAI_EVAL_MODEL:-gpt-4o-mini}"
12+
"${WDOC_TEST_OPENAI_EMBED_MODEL:-text-embedding-3-small}"
13+
"${WDOC_TEST_OPENROUTER_MODEL:-openrouter/mistralai/mistral-small-3.2-24b-instruct}"
14+
"${WDOC_TEST_OPENROUTER_EVAL_MODEL:-openrouter/mistralai/mistral-small-3.2-24b-instruct}"
15+
"${WDOC_TEST_DEFAULT_MODEL:-openrouter/deepseek/deepseek-v4-pro}"
16+
"${WDOC_TEST_DEFAULT_EVAL_MODEL:-openrouter/deepseek/deepseek-v4-flash}"
17+
"${WDOC_TEST_DEFAULT_EMBED_MODEL:-openai/text-embedding-3-small}"
18+
)
19+
_check_provider_key() {
20+
local prefix="$1" keyvar="$2" m
21+
for m in "${_ALL_TEST_MODELS[@]}"; do
22+
if [[ "$m" == ${prefix}* ]]; then
23+
if [[ -z "${(P)keyvar:-}" ]]; then
24+
echo "ERROR: $keyvar env var is not set but a test model starts with '$prefix'. Set $keyvar or override the relevant WDOC_TEST_* model env vars." >&2
25+
exit 1
26+
fi
27+
return 0
28+
fi
29+
done
30+
}
31+
_check_provider_key "openrouter/" OPENROUTER_API_KEY
32+
_check_provider_key "openai/" OPENAI_API_KEY
33+
_check_provider_key "mistral/" MISTRAL_API_KEY
34+
if [[ -z "${WDOC_WHISPER_API_KEY:-}" ]]; then
35+
echo "ERROR: WDOC_WHISPER_API_KEY env var is not set but is required to test whisper transcription. Set WDOC_WHISPER_API_KEY before running tests." >&2
36+
exit 1
37+
fi
38+
739
# cleanup previous
840
[[ "$(type deactivate)" == "deactivate is a shell function"* ]] && deactivate
941
[ -e "temp" ] && rm -r temp
@@ -17,11 +49,7 @@ source test_venv/bin/activate
1749
sleep 1
1850

1951
# install wdoc
20-
uv pip install -e ".."
21-
22-
# install test suite
23-
uv pip install pytest pytest-xdist
24-
sleep 1
52+
uv pip install -e "..[full,dev,fasttext,pdftotext]"
2553

2654
# Store the venv python path to ensure we use it consistently
2755
PYTHON_EXEC=$(which python)
@@ -54,22 +82,6 @@ echo "\nDone with first round of pytest!"
5482

5583
cd ..
5684

57-
# also check if we can install those then redo some of the tests
58-
uv pip install -e "..[fasttext]"
59-
uv pip install -e "..[pdftotext]"
60-
cd temp
61-
62-
echo "\nTesting wdoc (basic)"
63-
$PYTHON_EXEC -m pytest --disable-warnings --show-capture=no --code-highlight=yes --tb=short -m basic ../test_wdoc.py
64-
echo "Done with wdoc (basic)"
65-
66-
# check if we can install the dev test
67-
cd ..
68-
uv pip install -e "..[dev]"
69-
70-
# check if we can install the full wdoc
71-
uv pip install -e "..[full]"
72-
7385
# cleanup
7486
deactivate
7587
# trash test_venv temp if present

0 commit comments

Comments
 (0)