Skip to content

deprecate: completely replace fastembed bm25 with qdrant core bm25 in hosted qdrant#1166

Merged
joein merged 6 commits into
devfrom
deprecate-bm25
Mar 12, 2026
Merged

deprecate: completely replace fastembed bm25 with qdrant core bm25 in hosted qdrant#1166
joein merged 6 commits into
devfrom
deprecate-bm25

Conversation

@joein

@joein joein commented Mar 10, 2026

Copy link
Copy Markdown
Member

No description provided.

@netlify

netlify Bot commented Mar 10, 2026

Copy link
Copy Markdown

Deploy Preview for poetic-froyo-8baba7 failed.

Name Link
🔨 Latest commit f76caac
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/69b30ca9d0f1a2000872ee10

@coderabbitai

coderabbitai Bot commented Mar 10, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The BuiltinEmbedder class and its module were removed. Embedder gained a new constructor flag use_core_bm25 (default true), converted is_supported_sparse_model to an instance method, and added a BM25 code path that can return models.Document for sparse text. ModelEmbedder was updated to stop relying on BuiltinEmbedder, broaden return types to include models.Document, and unify model availability checks and error messaging. Tests were adjusted (some skips changed and a new BM25-focused test added). A FastEmbed import error message was slightly reworded and CI/workflow/test scripts were updated to run additional fastembed-related tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • tbung
  • coszio
  • hh-space-invader
  • generall
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess relevance to the changeset. Add a description explaining the motivation for replacing fastembed BM25 with core BM25, any breaking changes, and migration guidance for users.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: replacing fastembed BM25 with Qdrant core BM25 in hosted Qdrant, which aligns with the removal of BuiltinEmbedder and integration of core BM25 support in the Embedder class.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch deprecate-bm25
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@qdrant_client/embed/model_embedder.py`:
- Around line 438-441: The error message raised in the ValueError uses two
adjacent f-strings which concatenate without a space producing "supported
models.Check"; update the raise so the message is a single properly spaced
string—either merge into one f-string or add a leading/trailing space between
the two f-strings—at the ValueError that references model in model_embedder.py
(the raise ValueError(...) that mentions `{model}` and
`cloud_inference`/`fastembed`).
- Around line 55-59: The constructor is passing the wrong keyword to Embedder,
so change the call that creates self.embedder to pass
use_core_bm25=self._is_builtin_embedder_available (instead of use_bm25_core) so
Embedder.__init__ receives the correct flag; locate the Embedder(...)
instantiation in model_embedder.py where self._is_builtin_embedder_available is
used and replace the incorrect keyword so the Embedder class (in
qdrant_client/embed/embedder.py) correctly toggles _use_core_bm25 and allows
falling back to FastEmbedMisc when appropriate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 583e043d-213f-477d-9096-7bf4608569f8

📥 Commits

Reviewing files that changed from the base of the PR and between ee813f7 and c5d4c94.

📒 Files selected for processing (3)
  • qdrant_client/embed/builtin_embedder.py
  • qdrant_client/embed/embedder.py
  • qdrant_client/embed/model_embedder.py
💤 Files with no reviewable changes (1)
  • qdrant_client/embed/builtin_embedder.py

Comment thread qdrant_client/embed/model_embedder.py Outdated
Comment on lines +438 to +441
raise ValueError(
f"{model} is not found among supported models."
f"Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the concatenated exception text.

Lines 438-441 currently render supported models.Check because the two f-strings are joined without a space.

✏️ Proposed fix
                 raise ValueError(
-                    f"{model} is not found among supported models."
+                    f"{model} is not found among supported models. "
                     f"Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?"
                 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
raise ValueError(
f"{model} is not found among supported models."
f"Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?"
)
raise ValueError(
f"{model} is not found among supported models. "
f"Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?"
)
🧰 Tools
🪛 Ruff (0.15.5)

[warning] 438-441: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/model_embedder.py` around lines 438 - 441, The error
message raised in the ValueError uses two adjacent f-strings which concatenate
without a space producing "supported models.Check"; update the raise so the
message is a single properly spaced string—either merge into one f-string or add
a leading/trailing space between the two f-strings—at the ValueError that
references model in model_embedder.py (the raise ValueError(...) that mentions
`{model}` and `cloud_inference`/`fastembed`).

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
qdrant_client/embed/embedder.py (1)

243-246: ⚠️ Potential issue | 🔴 Critical

Critical: embed() bypasses the BM25 pathway because it uses FastEmbedMisc class method directly instead of the instance method.

The embed() method checks FastEmbedMisc.is_supported_sparse_model(model_name) at line 243, but when _use_core_bm25 is enabled and the model is "Qdrant/bm25", this model is not in FastEmbed's sparse model list. The code falls through to the else branch (line 256) and raises "Unsupported embedding model" without calling _embed_sparse_text().

The instance method is_supported_sparse_model() (lines 445-454) correctly handles the BM25 shortcut, but embed() bypasses it by calling the class method directly.

Proposed fix - use the instance method for sparse model check
-            elif FastEmbedMisc.is_supported_sparse_model(model_name):
+            elif self.is_supported_sparse_model(model_name):
                 embeddings = self._embed_sparse_text(
                     texts, model_name, options, is_query, batch_size
                 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/embedder.py` around lines 243 - 246, The embed() method
incorrectly calls the class method
FastEmbedMisc.is_supported_sparse_model(model_name) which bypasses the
instance-level BM25 shortcut; change the check to call the instance method
(self.is_supported_sparse_model or the instance method defined at lines 445-454)
so that when self._use_core_bm25 is enabled and model_name == "Qdrant/bm25" the
code routes into self._embed_sparse_text(texts, model_name, options, is_query,
batch_size) instead of falling through to the unsupported-model branch.
♻️ Duplicate comments (1)
qdrant_client/embed/model_embedder.py (1)

440-443: ⚠️ Potential issue | 🟡 Minor

Missing space in concatenated error message.

The two f-strings are joined without a space, producing "supported models.Check". This was flagged in a prior review.

✏️ Proposed fix
             raise ValueError(
-                f"{model} is not found among supported models."
+                f"{model} is not found among supported models. "
                 f"Check if `cloud_inference` is set to True or `fastembed` is installed (for local inference)?"
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/model_embedder.py` around lines 440 - 443, The ValueError
message raised in model_embedder.py concatenates two f-strings without a
separating space, causing "...supported models.Check..."; update the raise
ValueError in the block that references model to produce a single properly
spaced message (either merge into one f-string or add a leading/trailing space
between the two parts) so the final error reads "...supported models. Check if
`cloud_inference`..." and still includes the {model} interpolation and the
guidance about cloud_inference/fastembed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@qdrant_client/embed/embedder.py`:
- Around line 243-246: The embed() method incorrectly calls the class method
FastEmbedMisc.is_supported_sparse_model(model_name) which bypasses the
instance-level BM25 shortcut; change the check to call the instance method
(self.is_supported_sparse_model or the instance method defined at lines 445-454)
so that when self._use_core_bm25 is enabled and model_name == "Qdrant/bm25" the
code routes into self._embed_sparse_text(texts, model_name, options, is_query,
batch_size) instead of falling through to the unsupported-model branch.

---

Duplicate comments:
In `@qdrant_client/embed/model_embedder.py`:
- Around line 440-443: The ValueError message raised in model_embedder.py
concatenates two f-strings without a separating space, causing "...supported
models.Check..."; update the raise ValueError in the block that references model
to produce a single properly spaced message (either merge into one f-string or
add a leading/trailing space between the two parts) so the final error reads
"...supported models. Check if `cloud_inference`..." and still includes the
{model} interpolation and the guidance about cloud_inference/fastembed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 867fd866-cd1d-4061-a5d1-81a5e196e749

📥 Commits

Reviewing files that changed from the base of the PR and between c5d4c94 and 07d8881.

📒 Files selected for processing (2)
  • qdrant_client/embed/embedder.py
  • qdrant_client/embed/model_embedder.py

@joein joein requested a review from tbung March 11, 2026 11:22
@joein joein changed the title deprecate: completely replace fastembed bm25 with qdrant core bm25 deprecate: completely replace fastembed bm25 with qdrant core bm25 in hosted qdrant Mar 12, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
qdrant_client/embed/embedder.py (1)

445-456: ⚠️ Potential issue | 🟡 Minor

Fix redundant .lower() comparison.

The .lower() call on the string literal is unnecessary. Change line 454:

-        if self._use_core_bm25 and model_name.lower() == "Qdrant/bm25".lower():
+        if self._use_core_bm25 and model_name.lower() == "qdrant/bm25":

Regarding the conversion from @classmethod to instance method: while this is technically a breaking change for external callers, no usages of Embedder.is_supported_sparse_model as a class method were found in the codebase. All current internal calls already use instance method syntax (self.is_supported_sparse_model or embedder_instance.is_supported_sparse_model), so this change aligns with the actual usage patterns.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/embedder.py` around lines 445 - 456, The equality check
in is_supported_sparse_model unnecessarily calls .lower() on the string literal;
update the comparison in Embedder.is_supported_sparse_model to compare
model_name.lower() to the lowercase literal "qdrant/bm25" (keep the existing
_use_core_bm25 guard and the fallback to
FastEmbedMisc.is_supported_sparse_model(model_name)), so the method reads: if
self._use_core_bm25 and model_name.lower() == "qdrant/bm25": return True.
🧹 Nitpick comments (3)
tests/embed_tests/test_local_inference.py (2)

1736-1778: Missing collection cleanup for remote client.

The test creates a collection on the remote client but doesn't delete it at the end. Other tests in this file consistently clean up collections. Consider adding cleanup to avoid leaving test state.

♻️ Proposed fix to add cleanup
     if not local_client._FASTEMBED_INSTALLED:
         with pytest.raises(ImportError):
             local_client.upsert(COLLECTION_NAME, points)
     else:
         local_client.upsert(COLLECTION_NAME, points)
+
+    remote_client.delete_collection(COLLECTION_NAME)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/embed_tests/test_local_inference.py` around lines 1736 - 1778, The
test_bm25_core leaves the remote_client collection (COLLECTION_NAME) behind;
wrap the remote_client collection creation/upsert in a try/finally (or add
explicit cleanup at the end of the test) and call
remote_client.delete_collection(COLLECTION_NAME) in the finally/cleanup block to
ensure the remote collection is removed even if assertions fail; reference the
existing remote_client and COLLECTION_NAME identifiers when adding the cleanup.

1775-1777: Fragile ImportError assertion lacks specificity.

Using pytest.raises(ImportError) without a match parameter will pass for any ImportError, not just the expected fastembed import error. Based on the error message in fastembed_common.py, consider adding a match pattern.

♻️ Proposed fix to add match pattern
     if not local_client._FASTEMBED_INSTALLED:
-        with pytest.raises(ImportError):
+        with pytest.raises(ImportError, match="fastembed is not installed"):
             local_client.upsert(COLLECTION_NAME, points)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/embed_tests/test_local_inference.py` around lines 1775 - 1777, The test
currently asserts a generic ImportError when fastembed isn't installed; update
the pytest.raises in tests/embed_tests/test_local_inference.py to assert the
specific fastembed import error by adding a match pattern that matches the
message raised in fastembed_common.py (referencing
local_client._FASTEMBED_INSTALLED and the local_client.upsert call); change the
pytest.raises(ImportError) to pytest.raises(ImportError, match="...") using the
exact substring from fastembed_common.py so only the intended import failure
passes.
qdrant_client/embed/embedder.py (1)

300-305: Redundant .lower() call on string literal.

The expression "Qdrant/bm25".lower() evaluates to "qdrant/bm25" at runtime. Using the lowercase literal directly improves clarity and avoids unnecessary computation.

♻️ Proposed fix
-        if self._use_core_bm25 and model_name.lower() == "Qdrant/bm25".lower():
+        if self._use_core_bm25 and model_name.lower() == "qdrant/bm25":
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/embedder.py` around lines 300 - 305, The comparison in
the embedder method redundantly calls .lower() on the string literal; change the
condition to compare model_name.lower() == "qdrant/bm25" (lowercase literal) so
it reads if self._use_core_bm25 and model_name.lower() == "qdrant/bm25": and
keep the existing return constructing models.Document for each text (referencing
_use_core_bm25, model_name, and models.Document).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@qdrant_client/embed/embedder.py`:
- Around line 30-32: Embedder.__init__ currently accepts an unused **kwargs
which should be removed; update the constructor signature in class Embedder to
drop **kwargs (leaving threads: int | None = None, use_core_bm25: bool = True)
and remove any references to that parameter in the body, and update any call
sites that were passing extra keyword args to instead pass model options
directly to get_or_init_model (or forward them explicitly where appropriate) so
no model options are silently discarded.

---

Outside diff comments:
In `@qdrant_client/embed/embedder.py`:
- Around line 445-456: The equality check in is_supported_sparse_model
unnecessarily calls .lower() on the string literal; update the comparison in
Embedder.is_supported_sparse_model to compare model_name.lower() to the
lowercase literal "qdrant/bm25" (keep the existing _use_core_bm25 guard and the
fallback to FastEmbedMisc.is_supported_sparse_model(model_name)), so the method
reads: if self._use_core_bm25 and model_name.lower() == "qdrant/bm25": return
True.

---

Nitpick comments:
In `@qdrant_client/embed/embedder.py`:
- Around line 300-305: The comparison in the embedder method redundantly calls
.lower() on the string literal; change the condition to compare
model_name.lower() == "qdrant/bm25" (lowercase literal) so it reads if
self._use_core_bm25 and model_name.lower() == "qdrant/bm25": and keep the
existing return constructing models.Document for each text (referencing
_use_core_bm25, model_name, and models.Document).

In `@tests/embed_tests/test_local_inference.py`:
- Around line 1736-1778: The test_bm25_core leaves the remote_client collection
(COLLECTION_NAME) behind; wrap the remote_client collection creation/upsert in a
try/finally (or add explicit cleanup at the end of the test) and call
remote_client.delete_collection(COLLECTION_NAME) in the finally/cleanup block to
ensure the remote collection is removed even if assertions fail; reference the
existing remote_client and COLLECTION_NAME identifiers when adding the cleanup.
- Around line 1775-1777: The test currently asserts a generic ImportError when
fastembed isn't installed; update the pytest.raises in
tests/embed_tests/test_local_inference.py to assert the specific fastembed
import error by adding a match pattern that matches the message raised in
fastembed_common.py (referencing local_client._FASTEMBED_INSTALLED and the
local_client.upsert call); change the pytest.raises(ImportError) to
pytest.raises(ImportError, match="...") using the exact substring from
fastembed_common.py so only the intended import failure passes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e5201d6-990f-40d2-aff1-ba1376a6f0a4

📥 Commits

Reviewing files that changed from the base of the PR and between 07d8881 and 85cbb97.

📒 Files selected for processing (3)
  • qdrant_client/embed/embedder.py
  • qdrant_client/fastembed_common.py
  • tests/embed_tests/test_local_inference.py
✅ Files skipped from review due to trivial changes (1)
  • qdrant_client/fastembed_common.py

Comment on lines +30 to +32
def __init__(
self, threads: int | None = None, use_core_bm25: bool = True, **kwargs: Any
) -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for Embedder instantiation to see if kwargs are being passed
rg -n "Embedder\(" --type py -A 3 | head -50

Repository: qdrant/qdrant-client

Length of output: 1326


🏁 Script executed:

cat -n qdrant_client/embed/embedder.py | sed -n '1,70p'

Repository: qdrant/qdrant-client

Length of output: 2886


🏁 Script executed:

cat -n qdrant_client/embed/model_embedder.py | sed -n '45,75p'

Repository: qdrant/qdrant-client

Length of output: 1605


🏁 Script executed:

#!/bin/bash
# Check for Embedder subclasses
rg -n "class.*\(.*Embedder.*\)" --type py

# Check all Embedder instantiations to see what kwargs might be passed
echo "=== Embedder instantiations ==="
rg -n "Embedder\(" --type py -B 2 -A 2

Repository: qdrant/qdrant-client

Length of output: 1791


Remove unused **kwargs parameter from Embedder.__init__.

The **kwargs parameter is accepted but never used in the constructor body. While get_or_init_model() accepts its own **kwargs for model options, the ones passed to __init__ are silently discarded, creating unnecessary confusion for maintainers and callers.

♻️ Proposed fix
     def __init__(
-        self, threads: int | None = None, use_core_bm25: bool = True, **kwargs: Any
+        self, threads: int | None = None, use_core_bm25: bool = True
     ) -> None:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def __init__(
self, threads: int | None = None, use_core_bm25: bool = True, **kwargs: Any
) -> None:
def __init__(
self, threads: int | None = None, use_core_bm25: bool = True
) -> None:
🧰 Tools
🪛 Ruff (0.15.5)

[warning] 31-31: Unused method argument: kwargs

(ARG002)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@qdrant_client/embed/embedder.py` around lines 30 - 32, Embedder.__init__
currently accepts an unused **kwargs which should be removed; update the
constructor signature in class Embedder to drop **kwargs (leaving threads: int |
None = None, use_core_bm25: bool = True) and remove any references to that
parameter in the body, and update any call sites that were passing extra keyword
args to instead pass model options directly to get_or_init_model (or forward
them explicitly where appropriate) so no model options are silently discarded.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration-tests.sh`:
- Line 71: The pip uninstall command "pip3 uninstall fastembed" is interactive
and will hang CI; make it non-interactive by adding the confirmation flag (e.g.,
change to "pip3 uninstall -y fastembed" or "pip3 uninstall --yes fastembed") so
the uninstall proceeds without prompting; update the command in
tests/integration-tests.sh where "pip3 uninstall fastembed" appears.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d865c8b3-909b-481d-80e9-acab9e708cfb

📥 Commits

Reviewing files that changed from the base of the PR and between 85cbb97 and d39e144.

📒 Files selected for processing (2)
  • .github/workflows/integration-tests.yml
  • tests/integration-tests.sh
💤 Files with no reviewable changes (1)
  • .github/workflows/integration-tests.yml

Comment thread tests/integration-tests.sh Outdated
@joein joein merged commit 0a69a4c into dev Mar 12, 2026
8 checks passed
joein added a commit that referenced this pull request Mar 13, 2026
… hosted qdrant (#1166)

* deprecate: completely replace fastembed bm25 with qdrant core bm25

* fix: fix param name in embedder, accept lower case bm25 model name

* tests: enable skipped tests, add bm25 core usage tests

* fix: fix ci, run fastembed tests in integration tests

* fix: fix pip uninstall prompt

* tests: log message when running tests wo fastembed
@Anush008 Anush008 deleted the deprecate-bm25 branch March 14, 2026 04:13
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.

2 participants