Skip to content

perf: lazy-import litellm, faiss, torch to speed up import lotus - #268

Open
01luyicheng wants to merge 1 commit into
lotus-data:mainfrom
01luyicheng:perf/lazy-import
Open

perf: lazy-import litellm, faiss, torch to speed up import lotus#268
01luyicheng wants to merge 1 commit into
lotus-data:mainfrom
01luyicheng:perf/lazy-import

Conversation

@01luyicheng

Copy link
Copy Markdown

Purpose

Closes #143.

import lotus currently takes ~4s (per issue #143), and up to ~10s in environments where all optional backends (torch, sentence_transformers, faiss) are installed. The root cause is that lotus/models/lm.py, lotus/pricing.py, lotus/types.py, lotus/models/__init__.py, and lotus/vector_store/__init__.py all eagerly import heavy dependencies (litellm ~4s, torch, sentence_transformers, faiss) at import lotus time, even when the user never instantiates an LM or a vector store.

This PR defers all of those imports until they are actually needed.

Test Plan

# 1. Verify heavy deps are no longer loaded at import time
python -c "
import lotus, sys
assert 'litellm' not in sys.modules
assert 'torch' not in sys.modules
assert 'sentence_transformers' not in sys.modules
assert 'faiss' not in sys.modules
print('lazy ok')
"

# 2. Verify import time dropped
python -c "import time; t0=time.perf_counter(); import lotus; print(f'{time.perf_counter()-t0:.3f}s')"

# 3. Verify LM still works (litellm loads lazily on first use)
python -c "
from lotus.models import LM
lm = LM(model='gpt-4o-mini')
print(lm.count_tokens('hello world'))
"

# 4. Run the new + existing tests
pytest tests/test_import_lazy.py -v
pytest tests/test_lm.py::TestLM::test_lm_rate_limiting_with_mock -v

Test Results

Import time (same environment, all backends installed):

Before (main) After (this PR)
import lotus 10.55s 1.10s (9.6x faster)
litellm loaded yes no (deferred)
torch loaded yes no (deferred)
sentence_transformers loaded yes no (deferred)
faiss loaded yes no (deferred)

In an environment with only litellm installed (no torch/st/faiss, matching the issue reporter's setup), import lotus drops from ~4s to ~1s.

pytest:

  • tests/test_import_lazy.py: 8 passed (asserts litellm/torch/st/faiss absent from sys.modules after import lotus; verifies public API still resolves; covers __getattr__ cache + AttributeError contract)
  • tests/test_lm.py::TestLM::test_lm_rate_limiting_with_mock: passed (mock path updated from lotus.models.lm.batch_completion to litellm.batch_completion)
  • tests/test_lm.py: 4 remaining failures are pre-existing and unrelated to this PR — they require OPENAI_API_KEY credentials (Missing credentials error) and fail on main as well.
  • ruff check / ruff format --check: clean on all changed files.

(Optional) Documentation Update

No public API changes. from lotus.models import LM, from lotus.models import SentenceTransformersRM, from lotus.vector_store import FaissVS, etc. all continue to work unchanged (now resolved lazily via PEP 562 __getattr__).

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Refactoring (no functional changes)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, updating docstrings
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

BEFORE SUBMITTING, PLEASE READ https://github.com/lotus-data/lotus/blob/main/CONTRIBUTING.md

Closes lotus-data#143.

`import lotus` currently takes ~4s (issue lotus-data#143) because litellm (~4s),
torch, sentence_transformers, and faiss are all loaded eagerly at import
time. In environments with all optional backends installed, the combined
import time can reach ~10s. This PR defers all of them until they are
actually needed.

Changes:
- lotus/models/__init__.py: keep LM / RM / Reranker (base) eager so existing
  type annotations keep working; load SentenceTransformersRM /
  CrossEncoderReranker / LiteLLMRM / ColBERTv2RM lazily via PEP 562
  __getattr__.
- lotus/vector_store/__init__.py: keep VS (base) eager; load FaissVS /
  WeaviateVS / QdrantVS lazily.
- lotus/models/lm.py: add `from __future__ import annotations` and defer
  all litellm imports (batch_completion, AuthenticationError, ModelResponse,
  Choices, ChoiceLogprobs, decode/encode/token_counter, supports_reasoning)
  to the methods that use them. litellm is ~4s and only needed when an LM is
  actually called, not at `import lotus` time.
- lotus/pricing.py: defer litellm / completion_cost to inside
  calculate_cost_from_response.
- lotus/types.py: add `from __future__ import annotations` and move
  ChatCompletionTokenLogprob to TYPE_CHECKING (only used in dataclass
  annotations).
- tests/test_import_lazy.py: assert litellm, torch, sentence_transformers,
  faiss are absent from sys.modules after `import lotus`, and that all
  public names still resolve.
- tests/test_lm.py: update mock path from `lotus.models.lm.batch_completion`
  to `litellm.batch_completion` (the symbol is no longer a module-level
  attribute of lotus.models.lm after lazy-importing).

Result: `import lotus` drops from ~10.5s to ~1.1s (9.6x) in an environment
with all backends installed, and from ~4s to ~1s with only litellm installed.
The remaining ~1s is dominated by openai (~0.6s) and pandas (~0.2s), which
are out of scope for this PR.

LM stays eager because it is referenced as a type annotation
(lotus.models.LM) in lotus/settings.py and lotus/sem_ops/*.py; making it
lazy would require from __future__ import annotations across many files,
out of scope for this PR.
Copilot AI review requested due to automatic review settings July 4, 2026 04:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Import lotus seems unusually slow

2 participants