1 Commits

Author SHA1 Message Date
Tarik Moussa
4efaa55ed8 spike(embed): F-04 BGE-M3 dense+sparse — NO-GO
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 <noreply@anthropic.com>
2026-06-04 23:37:47 +02:00

68
spike.py Normal file
View File

@@ -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())