fix: minor embed compat fixes

This commit is contained in:
Alex committed 2026-08-27 13:45:34 +01:00
1 parent dd3876fdcb
commit 869d87452b
6 files changed
+121 -2

No files matched your search

+5 -2
View File
@@ -202,7 +202,7 @@ def reembed_faiss(source_id: str, batch_size: int, dry_run: bool) -> Tuple[int,
``(chunks_seen, chunks_written)``.
"""
store = VectorCreator.create_vectorstore(
"faiss", source_id=source_id, embeddings_key="embeddings"
"faiss", source_id=source_id, embeddings_key=settings.EMBEDDINGS_KEY
)
chunks: List[Dict[str, Any]] = store.get_chunks() or []
if dry_run or not chunks:
@@ -217,7 +217,10 @@ def reembed_faiss(source_id: str, batch_size: int, dry_run: bool) -> Tuple[int,
# index and touches nothing on disk. The existing index is only replaced by
# ``save_local`` below, so a failure while embedding leaves it intact.
rebuilt = VectorCreator.create_vectorstore(
"faiss", source_id=source_id, embeddings_key="embeddings", docs_init=docs
"faiss",
source_id=source_id,
embeddings_key=settings.EMBEDDINGS_KEY,
docs_init=docs,
)
rebuilt.save_local()
return len(chunks), len(docs)
+13
View File
@@ -13,6 +13,11 @@ from application.vectorstore.model_registry import (
)
def _embeddings_name_is_explicit() -> bool:
"""True when ``EMBEDDINGS_NAME`` was configured rather than defaulted."""
return "EMBEDDINGS_NAME" in getattr(settings, "model_fields_set", set())
class RemoteEmbeddings:
"""
Wrapper for remote embeddings API (OpenAI-compatible).
@@ -47,10 +52,18 @@ class RemoteEmbeddings:
model contributes its own context window, so a request that the server
would reject -- or silently truncate -- is clipped here instead of
being sent and paid for.
That fallback needs the name to mean something. For a remote server it
is only a label forwarded as the ``model`` field, so the settings
default must not lend the server mpnet's 384-token window: a name
nobody chose describes nothing, and clipping on it would silently
discard most of every chunk.
"""
configured = settings.EMBEDDINGS_MAX_INPUT_TOKENS
if configured and configured > 0:
return configured
if not _embeddings_name_is_explicit():
return None
model_limit = max_input_tokens_for(self.model_name)
return model_limit if model_limit and model_limit > 0 else None
@@ -94,6 +94,27 @@ def _spec_for(model_name: str) -> EmbeddingModel:
)
def _pad_to_longest_in_batch(model: Any) -> None:
"""Undo a fixed padding width baked into a model's ``tokenizer.json``."""
# FastEmbed enables padding only when the tokenizer declares none, so a
# fixed ``length`` survives loading. Shorter inputs are then padded to that
# width while longer ones keep their own, the batch is ragged, and the ONNX
# tensor build fails. mpnet ships ``length: 128``; granite does not.
# Mean pooling masks pad tokens, so the vectors are unaffected.
tokenizer = getattr(getattr(model, "model", None), "tokenizer", None)
padding = getattr(tokenizer, "padding", None)
if not isinstance(padding, dict) or padding.get("length") is None:
return
tokenizer.enable_padding(
direction=padding.get("direction", "right"),
pad_id=padding.get("pad_id", 0),
pad_type_id=padding.get("pad_type_id", 0),
pad_token=padding.get("pad_token", "<pad>"),
length=None,
pad_to_multiple_of=padding.get("pad_to_multiple_of"),
)
class EmbeddingsWrapper:
"""Runs an embedding model locally through FastEmbed.
@@ -131,6 +152,7 @@ class EmbeddingsWrapper:
f"{exc}. Known models: {', '.join(known_names())}."
) from exc
_pad_to_longest_in_batch(self.model)
self.dimension = self.spec.dimension or self._probe_dimension()
logger.info("Embeddings model ready (dimension=%d)", self.dimension)