Implement core/embedder.py with the Embedder class that wraps a sentence-transformers model and exposes batch embedding with model metadata properties needed for lineage records.
Requirements
- Implement
Embedder class in core/embedder.py
- Constructor:
__init__(self, model_name: str = "all-MiniLM-L6-v2")
- Load model on construction:
self._model = SentenceTransformer(model_name)
- Implement
model_id property returning the model name string
- Implement
dimension property returning the model's output dimension as int (query from loaded model: self._model.get_sentence_embedding_dimension())
- Implement
embed(texts: list[str]) -> list[list[float]] — calls model.encode(texts, convert_to_numpy=True), returns as list of Python float lists
- Implement
embed_query(query: str) -> list[float] — convenience wrapper for single string, returns a single embedding vector
- Support batch processing:
embed() accepts a list and passes it directly to model.encode() for efficient batching
- Create tests in
tests/core/test_embedder.py covering: model_id property, dimension property, embed() output shape, embed_query() output length matches dimension
Design Guidance
core/embedder.py already exists as a stub — implement Embedder there
- Import:
from sentence_transformers import SentenceTransformer
- The
dimension property is used downstream to: (1) populate embedding_model_id in LineageRecord, (2) validate vector dimensions via validate_embedding_dimension(), (3) inform LanceDB table creation
- Model download note:
all-MiniLM-L6-v2 is ~80MB and downloads on first use. Tests that instantiate the real embedder will be slow on first run. For unit tests in this file, use the real model but accept the download cost. Integration tests may mock the embedder.
embed() return type: convert numpy arrays to Python lists using .tolist() on the numpy array: return self._model.encode(texts, convert_to_numpy=True).tolist()
- The
model_id property is recorded as embedding_model_id in LineageRecord — it must be stable and deterministic for the same model
- Do not expose the underlying
SentenceTransformer object directly; keep it as a private _model attribute
Acceptance Criteria
Parent Issue
Part of #40
Discussion
This work is detailed in discussion 41
Implement
core/embedder.pywith theEmbedderclass that wraps a sentence-transformers model and exposes batch embedding with model metadata properties needed for lineage records.Requirements
Embedderclass incore/embedder.py__init__(self, model_name: str = "all-MiniLM-L6-v2")self._model = SentenceTransformer(model_name)model_idproperty returning the model name stringdimensionproperty returning the model's output dimension as int (query from loaded model:self._model.get_sentence_embedding_dimension())embed(texts: list[str]) -> list[list[float]]— callsmodel.encode(texts, convert_to_numpy=True), returns as list of Python float listsembed_query(query: str) -> list[float]— convenience wrapper for single string, returns a single embedding vectorembed()accepts a list and passes it directly tomodel.encode()for efficient batchingtests/core/test_embedder.pycovering: model_id property, dimension property, embed() output shape, embed_query() output length matches dimensionDesign Guidance
core/embedder.pyalready exists as a stub — implementEmbeddertherefrom sentence_transformers import SentenceTransformerdimensionproperty is used downstream to: (1) populateembedding_model_idinLineageRecord, (2) validate vector dimensions viavalidate_embedding_dimension(), (3) inform LanceDB table creationall-MiniLM-L6-v2is ~80MB and downloads on first use. Tests that instantiate the real embedder will be slow on first run. For unit tests in this file, use the real model but accept the download cost. Integration tests may mock the embedder.embed()return type: convert numpy arrays to Python lists using.tolist()on the numpy array:return self._model.encode(texts, convert_to_numpy=True).tolist()model_idproperty is recorded asembedding_model_idinLineageRecord— it must be stable and deterministic for the same modelSentenceTransformerobject directly; keep it as a private_modelattributeAcceptance Criteria
Embedder()constructs without error (model loads)embedder.model_idreturns the model name string passed to constructorembedder.dimensionreturns the correct output dimension for the model (384 forall-MiniLM-L6-v2)embedder.embed(["text1", "text2"])returns a list of 2 vectors, each of lengthembedder.dimensionembedder.embed_query("query")returns a single vector of lengthembedder.dimensiontests/core/test_embedder.pypassesParent Issue
Part of #40
Discussion
This work is detailed in discussion 41