kaxil commented on code in PR #72002:
URL: https://github.com/apache/airflow/pull/72002#discussion_r3997974027


##########
providers/common/ai/tests/unit/common/ai/hooks/test_llamaindex.py:
##########
@@ -128,6 +129,43 @@ def test_dispatches_with_api_base(self, mock_get_conn, 
mock_cls):
             api_base="http://localhost:11434/v1";,
         )
 
+    @patch("llama_index.embeddings.openai.OpenAIEmbedding")
+    @patch.object(LlamaIndexHook, "get_connection")
+    def test_dispatches_with_embedding_kwargs(self, mock_get_conn, mock_cls, 
caplog):
+        mock_get_conn.return_value = _conn(password="sk-test")
+        mock_cls.model_fields = {"api_key": None, "dimensions": None, 
"timeout": None}
+        hook = LlamaIndexHook(
+            embed_model="text-embedding-3-small",
+            embedding_kwargs={"api_key": "from-kwargs", "dimensions": 128, 
"timeout": 30},
+        )
+
+        hook.get_embedding_model()
+
+        mock_cls.assert_called_once_with(
+            model="text-embedding-3-small",
+            api_key="sk-test",
+            dimensions=128,
+            timeout=30,
+        )
+        assert "Connection parameters override embedding_kwargs values: 
['api_key']" in caplog.messages
+
+    @patch("llama_index.embeddings.openai.OpenAIEmbedding")
+    @patch.object(LlamaIndexHook, "get_connection")
+    def test_warns_about_unsupported_embedding_kwargs(self, mock_get_conn, 
mock_cls, caplog):

Review Comment:
   Both of these patch `OpenAIEmbedding` itself, so `supported_kwargs` is 
computed from the mock rather than the class: 
`inspect.signature(MagicMock().__init__).parameters` is `{'args', 'kw'}` and 
`model_fields` is whatever the test assigned two lines up, so the assertion 
checks the warning against its own stub. Deleting the `inspect.signature(...)` 
half of the union leaves all six tests in this file green, and so does 
replacing the whole union with `set()`, which would make the hook warn on every 
correct call.
   
   Keep the signature half, though: `mode`, `http_client` and 
`async_http_client` are `__init__`-only and absent from `model_fields`, so 
without it a user passing `http_client=` gets warned about a key that works. 
One test against the real class, parametrized over a signature-only key, a 
field-only key and a genuinely unsupported one, would pin it, and adding 
`assert "ignores unsupported" not in caplog.text` to 
`test_dispatches_with_embedding_kwargs` would catch the false-positive 
direction.



##########
providers/common/ai/src/airflow/providers/common/ai/hooks/llamaindex.py:
##########
@@ -179,7 +186,18 @@ def get_embedding_model(self) -> BaseEmbedding:
             extra_key="embed_model",
             kind="embedding",
         )
-        return OpenAIEmbedding(model=model_id, **self._connection_kwargs(conn))
+        connection_kwargs = self._connection_kwargs(conn)
+        overridden_keys = sorted(self.embedding_kwargs.keys() & 
connection_kwargs.keys())
+        if overridden_keys:
+            self.log.warning("Connection parameters override embedding_kwargs 
values: %s", overridden_keys)
+        kwargs = {**self.embedding_kwargs, **connection_kwargs}
+        supported_kwargs = 
set(inspect.signature(OpenAIEmbedding.__init__).parameters) | set(
+            OpenAIEmbedding.model_fields
+        )
+        unsupported_keys = sorted(self.embedding_kwargs.keys() - 
supported_kwargs)

Review Comment:
   `model_name` passes this guard (it is in `model_fields`) and is not a 
connection key, so neither new warning fires, but `OpenAIEmbedding.__init__` 
pops it and uses it to set both `_query_engine` and `_text_engine` 
(`llama_index/embeddings/openai/base.py:310-314` and `:332-333`), and those are 
what go on the wire as `engine=` (`:398` plus five sibling call sites). 
Captured the request at the declared 0.6.0 floor behind a mock transport: 
`embed_model="text-embedding-3-small"` with `embedding_kwargs={"model_name": 
"Qwen/Qwen3-Embedding-0.6B"}` sends `{"model": "Qwen/Qwen3-Embedding-0.6B", 
"dimensions": 128, ...}` with an empty warning list, while `embed_model` still 
reads `text-embedding-3-small` in the rendered template fields and in the UI.
   
   That matters because `llamaindex_retrieval.rst` tells users `embed_model` is 
the value that has to match between the embedding and retrieval tasks, and it 
would now be naming a model that did not produce the vectors. It is also not 
pathological input: your own test notes say to serve the vLLM model as 
`text-embedding-3-small` "because `LlamaIndexHook` validates the model name", 
so `model_name` is the next key a self-hosting user reaches for. Reserving 
`{"model", "model_name"}` and raising would close it, or make it the documented 
escape hatch.
   
   Same expression, smaller point: the supported set also picks up `self` and 
`kwargs` from the signature, so `embedding_kwargs={"kwargs": {...}}` (the 
mis-nesting a parameter named `embedding_kwargs` invites) passes the guard 
silently and is then dropped by pydantic's `extra="ignore"`, which is the exact 
case the guard exists to announce. Filtering `VAR_KEYWORD`/`VAR_POSITIONAL` and 
`self` out covers it.



##########
providers/common/ai/docs/operators/llamaindex_embedding.rst:
##########
@@ -86,22 +86,28 @@ Parameters
        binding ``loader.output`` resolves to the native list before
        execute.
    * - ``embed_model``
-     - String model name OR pre-built ``BaseEmbedding`` instance.
+     - String model name OR pre-built ``BaseEmbedding`` instance. Templated.
    * - ``llm_conn_id``
      - Airflow connection ID used when ``embed_model`` is a string. Falls
        back to ``LlamaIndexHook.default_conn_name`` (``llamaindex_default``)
-       when ``None``.
+       when ``None``. Templated.
    * - ``embed_conn_id``
      - Optional separate connection ID for the embedding provider. Falls
-       back to ``llm_conn_id`` when ``None``.
+       back to ``llm_conn_id`` when ``None``. Templated.
+   * - ``embedding_kwargs``
+     - Additional keyword arguments passed to the embedding model constructor
+       when ``embed_model`` is a string or omitted, for example
+       ``{"dimensions": 128}``. Supports templating; set the Dag's
+       ``render_template_as_native_obj=True`` when templating typed values such
+       as ``dimensions`` so they remain integers instead of strings.

Review Comment:
   `{"dimensions": 128}` here creates an obligation that only the retrieval 
page states ("must match those used to build the index"), which is the one page 
where the reader can no longer act on it. Nothing records the value at persist 
time, so a mismatch surfaces later as a shape error naming neither `dimensions` 
nor `embedding_kwargs`. One clause on this side would carry it.
   
   While you are here: none of the four new rows says where the valid keys come 
from. `providers/openai` links the API reference for its own `embedding_kwargs` 
(`operators/openai.py:44-47`), and a `.. seealso::` pointing at 
`llama_index.embeddings.openai.OpenAIEmbedding` and 
`langchain.embeddings.init_embeddings` would do the same job here. Worth the 
line because the two parameters share a name but not a value space: theirs is a 
per-request bag forwarded to `embeddings.create`, this one is a constructor bag.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to