From 4efaa55ed8087d78f4c62482a10573b0117cbf97 Mon Sep 17 00:00:00 2001 From: Tarik Moussa Date: Thu, 4 Jun 2026 23:37:47 +0200 Subject: [PATCH] =?UTF-8?q?spike(embed):=20F-04=20BGE-M3=20dense+sparse=20?= =?UTF-8?q?=E2=80=94=20NO-GO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reason: SentenceTransformer.encode() in sentence-transformers 5.5.1 does not accept return_dense / return_sparse kwargs. Those belong to the FlagEmbedding.BGEM3FlagModel API, which is not in our dependency set. Dense encoding works fine via the vanilla encode() call (shape (N, 1024), float32). Sparse / lexical_weights requires either: (a) adding FlagEmbedding as a dependency, or (b) using sentence_transformers.SparseEncoder with a SPLADE checkpoint, or (c) driving the underlying transformers model and sparse head manually. Branch retained as documentation per docs/loops/spike-gate.md. Co-Authored-By: Claude Opus 4.7 --- spike.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 spike.py diff --git a/spike.py b/spike.py new file mode 100644 index 0000000..48c9138 --- /dev/null +++ b/spike.py @@ -0,0 +1,68 @@ +"""Spike: verify BGE-M3 dense+sparse encoding via sentence-transformers. + +RESULT: NO-GO. + +The session prompt for F-04 specified an `encode()` call signature of +``encode([...], return_dense=True, return_sparse=True, batch_size=2)``. +This signature originates from the ``FlagEmbedding.BGEM3FlagModel`` API, +not ``sentence_transformers.SentenceTransformer``. + +With ``sentence-transformers==5.5.1`` and ``BAAI/bge-m3``: + + >>> model.encode(['hello', 'world'], return_dense=True, return_sparse=True) + ValueError: SentenceTransformer.encode() has been called with additional + keyword arguments that this model does not use: + ['return_sparse', 'return_dense']. + +The vanilla call ``model.encode([...])`` returns dense vectors of shape +``(2, 1024)`` and dtype ``float32`` as expected — dense embeddings work. +Sparse / lexical-weights output is NOT exposed via the standard +``SentenceTransformer`` wrapper. To get the BGE-M3 sparse head we must: + + (a) Install ``FlagEmbedding`` and load via ``BGEM3FlagModel``, or + (b) Drive the underlying ``transformers`` model directly and apply the + sparse projection head ourselves, or + (c) Use ``sentence_transformers.SparseEncoder`` with a different + (SPLADE-style) checkpoint. + +Decision required from Theorist/Leader: which path? +""" + +from __future__ import annotations + +import sys + + +def main() -> int: + try: + from sentence_transformers import SentenceTransformer + + model = SentenceTransformer("BAAI/bge-m3") + out = model.encode( + ["hello", "world"], + return_dense=True, + return_sparse=True, + batch_size=2, + ) + + if isinstance(out, dict): + dense = out.get("dense_vecs") + sparse = out.get("lexical_weights") + else: + dense = out + sparse = None + + assert dense is not None, "no dense output" + assert dense.shape == (2, 1024), f"dense shape {dense.shape} != (2, 1024)" + assert isinstance(sparse, list) and len(sparse) == 2, "sparse not list of 2" + assert all(isinstance(d, dict) for d in sparse), "sparse elements not dicts" + except Exception as exc: # noqa: BLE001 — spike must catch everything + print(f"Spike: NO-GO — {type(exc).__name__}: {exc}") + return 1 + + print("Spike: GO") + return 0 + + +if __name__ == "__main__": + sys.exit(main())