Skip to content

symfonic.memory.embeddings.factory

factory

String-identifier factory for :class:EmbeddingProvider implementations.

v7.3 Roadmap Item 13.1 (PR-C). Scaffold projects set EMBEDDING_PROVIDER in .env and surface the string at the Settings -> FrameworkConfig.embedding_provider boundary; this factory turns the string into a concrete provider instance.

None of the providers ship in core -- each entry below is an optional extra:

  • sentence-transformers -- installs the sentence-transformers extra; uses the same internal class shape as the scaffold's legacy _build_embedder(). Honours the EMBEDDING_MODEL env var.
  • openai -- requires the openai extra; talks to the OpenAI embeddings API. Honours OPENAI_API_KEY and EMBEDDING_MODEL (defaults to text-embedding-3-small).

Unknown identifiers raise ValueError so a typo surfaces immediately at agent construction time rather than as a silent embedding=None. None / empty string returns None -- the default off path.

SUPPORTED_PROVIDER_IDENTIFIERS module-attribute

SUPPORTED_PROVIDER_IDENTIFIERS = (
    "sentence-transformers",
    "openai",
)

String identifiers accepted by :func:make_embedding_provider.

The literal "none" and the empty string are also accepted and map to None (no auto-embed; caller still populates manually).

make_embedding_provider

make_embedding_provider(
    identifier: str | None,
) -> EmbeddingProvider | None

Build an :class:EmbeddingProvider from a string identifier.

Returns None for the default-off path (identifier in {None, "", "none"}). Raises ValueError on an unknown string so a typo in .env does not silently degrade to keyword-only retrieval.

The actual provider instance is constructed lazily -- importing this module does NOT pull in sentence_transformers or the OpenAI SDK. Each branch handles its own ImportError and re-raises as ValueError with the required pip-install hint.

Source code in src/symfonic/memory/embeddings/factory.py
def make_embedding_provider(
    identifier: str | None,
) -> EmbeddingProvider | None:
    """Build an :class:`EmbeddingProvider` from a string *identifier*.

    Returns ``None`` for the default-off path (``identifier in
    {None, "", "none"}``). Raises ``ValueError`` on an unknown string so
    a typo in ``.env`` does not silently degrade to keyword-only
    retrieval.

    The actual provider instance is constructed lazily -- importing this
    module does NOT pull in ``sentence_transformers`` or the OpenAI SDK.
    Each branch handles its own ImportError and re-raises as
    ``ValueError`` with the required pip-install hint.
    """
    if identifier is None:
        return None
    name = identifier.strip().lower()
    if name in {"", "none"}:
        return None

    if name == "sentence-transformers":
        return _build_sentence_transformers_provider()
    if name == "openai":
        return _build_openai_provider()

    raise ValueError(
        f"Unknown EMBEDDING_PROVIDER identifier: {identifier!r}. "
        f"Supported: {', '.join(SUPPORTED_PROVIDER_IDENTIFIERS)} "
        f"or 'none' / empty for off.",
    )