From 2684cfc57255ce651095de6174a708ef44fd21f8 Mon Sep 17 00:00:00 2001 From: Solaris-star <820622658@qq.com> Date: Tue, 21 Jul 2026 15:38:29 +0800 Subject: [PATCH] fix: accept embeddings= alias and warn on unknown Llama kwargs The constructor historically used embedding=True. Callers that pass embeddings=True (plural) were silently swallowed by **kwargs, so embed() later raised a confusing RuntimeError. Accept embeddings as an alias, reject conflicting values, and warn on unexpected kwargs. Fixes #2210 Signed-off-by: Solaris-star <820622658@qq.com> --- llama_cpp/llama.py | 35 +++++++++++++++++++++++++++++++++-- tests/test_llama.py | 25 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/llama_cpp/llama.py b/llama_cpp/llama.py index b5bffd46b..b2704a630 100644 --- a/llama_cpp/llama.py +++ b/llama_cpp/llama.py @@ -91,6 +91,7 @@ def __init__( yarn_orig_ctx: int = 0, logits_all: bool = False, embedding: bool = False, + embeddings: Optional[bool] = None, offload_kqv: bool = True, flash_attn: bool = False, op_offload: Optional[bool] = None, @@ -173,7 +174,9 @@ def __init__( yarn_beta_slow: YaRN high correction dim yarn_orig_ctx: YaRN original context size logits_all: Return logits for all tokens, not just the last token. Must be True for completion to return logprobs. - embedding: Embedding mode only. + embedding: Embedding mode only (historical name). + embeddings: Alias of ``embedding``. Prefer this spelling; if both are + provided they must agree. offload_kqv: Offload K, Q, V to GPU. flash_attn: Use flash attention. op_offload: offload host tensor operations to device @@ -203,6 +206,34 @@ def __init__( set_verbose(verbose) + # Resolve embedding / embeddings. Historical name is ``embedding``; + # ``embeddings`` is accepted as an alias. The bare ``**kwargs`` sink + # previously swallowed the plural form so failures only appeared later + # inside embed() (issue #2210). + if embeddings is not None: + if not isinstance(embeddings, bool): + raise TypeError( + f"embeddings must be a bool, got {type(embeddings).__name__}" + ) + if embedding is True and embeddings is False: + raise ValueError( + "Conflicting values for embedding=True and embeddings=False" + ) + # When embeddings is provided, it is authoritative for the plural alias. + # If embedding was left at the default False, adopt embeddings. + # If embedding is True, require embeddings to also be True (checked above). + embedding = embeddings + + if kwargs: + unknown = ", ".join(sorted(str(k) for k in kwargs)) + warnings.warn( + f"Llama() got unexpected keyword argument(s): {unknown}. " + "These were ignored. If you meant embedding mode, pass " + "embedding=True (or embeddings=True).", + UserWarning, + stacklevel=2, + ) + if not Llama.__backend_initialized: with suppress_stdout_stderr(disable=verbose): llama_cpp.llama_backend_init() @@ -1088,7 +1119,7 @@ def embed( if self.context_params.embeddings is False: raise RuntimeError( - "Llama model must be created with embedding=True to call this method" + "Llama model must be created with embedding=True (or embeddings=True) to call this method" ) if self.verbose: diff --git a/tests/test_llama.py b/tests/test_llama.py index 70fce12d8..87ce28d68 100644 --- a/tests/test_llama.py +++ b/tests/test_llama.py @@ -653,3 +653,28 @@ def test_real_llama_embeddings(llama_cpp_embedding_model_path): repeated_embeddings = model.embed(list(reversed(prompts))) assert len(repeated_embeddings) == len(prompts) assert all(len(repeated) == len(embedding) for repeated in repeated_embeddings) + + +def test_embeddings_kwarg_alias_and_unknown_kwargs(): + """embeddings= is accepted; unknown kwargs warn; conflicts raise (issue #2210).""" + import warnings + + missing = "/nonexistent/path/to/model.gguf" + + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + try: + llama_cpp.Llama(model_path=missing, embeddings=True, not_a_real_flag=1) + except ValueError as exc: + assert "does not exist" in str(exc) + else: + raise AssertionError("expected ValueError for missing model path") + assert any(issubclass(w.category, UserWarning) for w in caught) + assert any("not_a_real_flag" in str(w.message) for w in caught) + + try: + llama_cpp.Llama(model_path=missing, embedding=True, embeddings=False) + raise AssertionError("expected conflicting embedding kwargs ValueError") + except ValueError as exc: + assert "Conflicting" in str(exc) +