From c709b407b46ae535772979754fc9ed45f0ec159d Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Fri, 23 Jan 2026 13:19:08 +0000 Subject: [PATCH 1/3] fix: friendly error messages for optional backend dependencies - Wraps optional backend imports (hf, watsonx, litellm) in try/except blocks - Updates AGENTS.md with new coding standard - Adds reproduction script and PR description artifact --- AGENTS.md | 2 ++ mellea/stdlib/session.py | 36 +++++++++++++++------ pr_description.md | 67 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 pr_description.md diff --git a/AGENTS.md b/AGENTS.md index b7b2950d..6cb66905 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,7 +39,9 @@ uv run ruff format . && uv run ruff check . # Lint & format - **Google-style docstrings** - **Ruff** for linting/formatting - Use `...` in `@generative` function bodies +- Use `...` in `@generative` function bodies - Prefer primitives over classes +- **Friendly Dependency Errors**: Wraps optional backend imports in `try/except ImportError` with a helpful message (e.g., "Please pip install mellea[hf]"). See `mellea/stdlib/session.py` for examples. ## 5. Commits & Hooks [Angular format](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit): `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `release:` diff --git a/mellea/stdlib/session.py b/mellea/stdlib/session.py index 0c1df16f..1d706cf5 100644 --- a/mellea/stdlib/session.py +++ b/mellea/stdlib/session.py @@ -58,21 +58,39 @@ def backend_name_to_class(name: str) -> Any: return OllamaModelBackend elif name == "hf" or name == "huggingface": - from mellea.backends.huggingface import LocalHFBackend - - return LocalHFBackend + try: + from mellea.backends.huggingface import LocalHFBackend + + return LocalHFBackend + except ImportError as e: + raise ImportError( + "The 'hf' backend requires extra dependencies. " + "Please install them with: pip install 'mellea[hf]'" + ) from e elif name == "openai": from ..backends.openai import OpenAIBackend return OpenAIBackend elif name == "watsonx": - from ..backends.watsonx import WatsonxAIBackend - - return WatsonxAIBackend + try: + from ..backends.watsonx import WatsonxAIBackend + + return WatsonxAIBackend + except ImportError as e: + raise ImportError( + "The 'watsonx' backend requires extra dependencies. " + "Please install them with: pip install 'mellea[watsonx]'" + ) from e elif name == "litellm": - from ..backends.litellm import LiteLLMBackend - - return LiteLLMBackend + try: + from ..backends.litellm import LiteLLMBackend + + return LiteLLMBackend + except ImportError as e: + raise ImportError( + "The 'litellm' backend requires extra dependencies. " + "Please install them with: pip install 'mellea[litellm]'" + ) from e else: return None diff --git a/pr_description.md b/pr_description.md new file mode 100644 index 00000000..ec24481b --- /dev/null +++ b/pr_description.md @@ -0,0 +1,67 @@ +# Friendly Error Messages for Optional Dependencies + +## Summary +Improves the user experience for optional backends (`hf`, `watsonx`, `litellm`) by wrapping their imports in `try/except ImportError` blocks. + +## Problem +Previously, if a user ran `start_session(backend="hf")` without installing `mellea[hf]`, they received a raw `ModuleNotFoundError: No module named 'outlines'`. This was confusing for new users who didn't know `outlines` is an internal dependency of the HuggingFace backend. + +## Solution +This PR catches the `ImportError` during the backend resolution phase and raises a cleaner `ImportError` that explicitly tells the user which extra to install. + +**New Error Message:** +> The 'hf' backend requires extra dependencies. Please install them with: pip install 'mellea[hf]' + +## Verification +Verified in a clean virtual environment (Python 3.12) with **no** extra dependencies installed. + +**Test Script Output:** +
+Click to see reproduction script (verify_fixes.py) + +```python +import mellea +import sys + +def test_backend_import(backend_name): + print(f"\n--- Testing backend: {backend_name} ---") + try: + # start_session internally calls backend_name_to_class which triggers the import + mellea.start_session(backend_name=backend_name) + except ImportError as e: + msg = str(e) + print(f"Caught Expected ImportError: {msg}") + if "requires extra dependencies" in msg and f"mellea[{backend_name}]" in msg: + print("SUCCESS: Friendly error message detected.") + else: + print("FAILURE: ImportError caught but message format is wrong!") + except Exception as e: + print(f"FAILURE: Caught unexpected exception type: {type(e).__name__}: {e}") + else: + print("FAILURE: No exception raised! (Did you install the extras by mistake?)") + +if __name__ == "__main__": + test_backend_import("hf") + test_backend_import("watsonx") + test_backend_import("litellm") +``` +
+ +```text +--- Testing backend: hf --- +Caught Expected ImportError: The 'hf' backend requires extra dependencies. Please install them with: pip install 'mellea[hf]' +SUCCESS: Friendly error message detected. + +--- Testing backend: watsonx --- +Caught Expected ImportError: The 'watsonx' backend requires extra dependencies. Please install them with: pip install 'mellea[watsonx]' +SUCCESS: Friendly error message detected. + +--- Testing backend: litellm --- +Caught Expected ImportError: The 'litellm' backend requires extra dependencies. Please install them with: pip install 'mellea[litellm]' +SUCCESS: Friendly error message detected. +``` + +## Note on Other Dependencies +* **vLLM**: Not used in `start_session()`, so users cannot trigger this crash. To fix this, we would first need to add "vllm" support to `backend_name_to_class`, and then wrap that new import in the same `try/except` block. That feels like a new feature so do it when adding? +* **Docling**: Usage is isolated to `RichDocument`, but requires refactoring top-level imports (lazy loading) to fix properly. Out of scope for this quick fix. Can add here for completeness but would mean a bigger change? +* **Dev dependencies**: Missing dev tools (e.g. `pytest`) will still raise standard errors. From c96b60e5955250033e73b220d1e10de8c67d5326 Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Fri, 23 Jan 2026 13:24:05 +0000 Subject: [PATCH 2/3] docs: reformat pr description with template and issue link --- pr_description.md | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pr_description.md b/pr_description.md index ec24481b..e56f6cb1 100644 --- a/pr_description.md +++ b/pr_description.md @@ -1,18 +1,38 @@ -# Friendly Error Messages for Optional Dependencies + + # Misc PR -## Summary +## Type of PR + +- [x] Bug Fix +- [ ] New Feature +- [ ] Documentation +- [ ] Other + +## Description +- [x] Link to Issue: Fixes #342 + +### Summary Improves the user experience for optional backends (`hf`, `watsonx`, `litellm`) by wrapping their imports in `try/except ImportError` blocks. -## Problem +### Problem Previously, if a user ran `start_session(backend="hf")` without installing `mellea[hf]`, they received a raw `ModuleNotFoundError: No module named 'outlines'`. This was confusing for new users who didn't know `outlines` is an internal dependency of the HuggingFace backend. -## Solution +### Solution This PR catches the `ImportError` during the backend resolution phase and raises a cleaner `ImportError` that explicitly tells the user which extra to install. **New Error Message:** > The 'hf' backend requires extra dependencies. Please install them with: pip install 'mellea[hf]' -## Verification +### Note on Other Dependencies +* **vLLM**: Not used in `start_session()`, so users cannot trigger this crash. To fix this, we would first need to add "vllm" support to `backend_name_to_class`, and then wrap that new import in the same `try/except` block. That feels like a new feature so do it when adding? +* **Docling**: Usage is isolated to `RichDocument`, but requires refactoring top-level imports (lazy loading) to fix properly. Out of scope for this quick fix. Can add here for completeness but would mean a bigger change? +* **Dev dependencies**: Missing dev tools (e.g. `pytest`) will still raise standard errors. + +### Testing +- [ ] Tests added to the respective file if code was changed +- [ ] New code has 100% coverage if code as added +- [ ] Ensure existing tests and github automation passes (a maintainer will kick off the github automation when the rest of the PR is populated) + Verified in a clean virtual environment (Python 3.12) with **no** extra dependencies installed. **Test Script Output:** @@ -60,8 +80,3 @@ SUCCESS: Friendly error message detected. Caught Expected ImportError: The 'litellm' backend requires extra dependencies. Please install them with: pip install 'mellea[litellm]' SUCCESS: Friendly error message detected. ``` - -## Note on Other Dependencies -* **vLLM**: Not used in `start_session()`, so users cannot trigger this crash. To fix this, we would first need to add "vllm" support to `backend_name_to_class`, and then wrap that new import in the same `try/except` block. That feels like a new feature so do it when adding? -* **Docling**: Usage is isolated to `RichDocument`, but requires refactoring top-level imports (lazy loading) to fix properly. Out of scope for this quick fix. Can add here for completeness but would mean a bigger change? -* **Dev dependencies**: Missing dev tools (e.g. `pytest`) will still raise standard errors. From e8b6b82723174aca75f217252ef7a3af21587b4a Mon Sep 17 00:00:00 2001 From: Nigel Jones Date: Mon, 26 Jan 2026 08:34:51 +0000 Subject: [PATCH 3/3] fix: remove pr description - checked in erroneously Signed-off-by: Nigel Jones --- pr_description.md | 82 ----------------------------------------------- 1 file changed, 82 deletions(-) delete mode 100644 pr_description.md diff --git a/pr_description.md b/pr_description.md deleted file mode 100644 index e56f6cb1..00000000 --- a/pr_description.md +++ /dev/null @@ -1,82 +0,0 @@ - - # Misc PR - -## Type of PR - -- [x] Bug Fix -- [ ] New Feature -- [ ] Documentation -- [ ] Other - -## Description -- [x] Link to Issue: Fixes #342 - -### Summary -Improves the user experience for optional backends (`hf`, `watsonx`, `litellm`) by wrapping their imports in `try/except ImportError` blocks. - -### Problem -Previously, if a user ran `start_session(backend="hf")` without installing `mellea[hf]`, they received a raw `ModuleNotFoundError: No module named 'outlines'`. This was confusing for new users who didn't know `outlines` is an internal dependency of the HuggingFace backend. - -### Solution -This PR catches the `ImportError` during the backend resolution phase and raises a cleaner `ImportError` that explicitly tells the user which extra to install. - -**New Error Message:** -> The 'hf' backend requires extra dependencies. Please install them with: pip install 'mellea[hf]' - -### Note on Other Dependencies -* **vLLM**: Not used in `start_session()`, so users cannot trigger this crash. To fix this, we would first need to add "vllm" support to `backend_name_to_class`, and then wrap that new import in the same `try/except` block. That feels like a new feature so do it when adding? -* **Docling**: Usage is isolated to `RichDocument`, but requires refactoring top-level imports (lazy loading) to fix properly. Out of scope for this quick fix. Can add here for completeness but would mean a bigger change? -* **Dev dependencies**: Missing dev tools (e.g. `pytest`) will still raise standard errors. - -### Testing -- [ ] Tests added to the respective file if code was changed -- [ ] New code has 100% coverage if code as added -- [ ] Ensure existing tests and github automation passes (a maintainer will kick off the github automation when the rest of the PR is populated) - -Verified in a clean virtual environment (Python 3.12) with **no** extra dependencies installed. - -**Test Script Output:** -
-Click to see reproduction script (verify_fixes.py) - -```python -import mellea -import sys - -def test_backend_import(backend_name): - print(f"\n--- Testing backend: {backend_name} ---") - try: - # start_session internally calls backend_name_to_class which triggers the import - mellea.start_session(backend_name=backend_name) - except ImportError as e: - msg = str(e) - print(f"Caught Expected ImportError: {msg}") - if "requires extra dependencies" in msg and f"mellea[{backend_name}]" in msg: - print("SUCCESS: Friendly error message detected.") - else: - print("FAILURE: ImportError caught but message format is wrong!") - except Exception as e: - print(f"FAILURE: Caught unexpected exception type: {type(e).__name__}: {e}") - else: - print("FAILURE: No exception raised! (Did you install the extras by mistake?)") - -if __name__ == "__main__": - test_backend_import("hf") - test_backend_import("watsonx") - test_backend_import("litellm") -``` -
- -```text ---- Testing backend: hf --- -Caught Expected ImportError: The 'hf' backend requires extra dependencies. Please install them with: pip install 'mellea[hf]' -SUCCESS: Friendly error message detected. - ---- Testing backend: watsonx --- -Caught Expected ImportError: The 'watsonx' backend requires extra dependencies. Please install them with: pip install 'mellea[watsonx]' -SUCCESS: Friendly error message detected. - ---- Testing backend: litellm --- -Caught Expected ImportError: The 'litellm' backend requires extra dependencies. Please install them with: pip install 'mellea[litellm]' -SUCCESS: Friendly error message detected. -```